Commit in lcsim/sandbox/Partridge on MAIN
DefaultStrategy.java+47added 1.1
HelicalTrackFitter.java+180added 1.1
HitManager.java+124added 1.1
SeedCandidate.java+97added 1.1
SeedLayer.java+89added 1.1
SeedStrategy.java+136added 1.1
SeedTracker.java+309added 1.1
SeedTrackerDriver.java+34added 1.1
SmearMCHits.java+82added 1.1
+1098
9 added files


lcsim/sandbox/Partridge
DefaultStrategy.java added at 1.1
diff -N DefaultStrategy.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ DefaultStrategy.java	6 Aug 2007 23:59:57 -0000	1.1
@@ -0,0 +1,47 @@
+/*
+ * DefaultStrategy.java
+ *
+ * Created on March 29, 2006, 3:45 PM
+ *
+ */
+
+package org.lcsim.contrib.seedtracker;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ *
+ * @author Richard Partridge
+ * @version 1.0
+ */
+public class DefaultStrategy
+{
+    private List<SeedStrategy> StrategyList;
+    
+    /** Creates a new instance of DefaultStrategy */
+    public DefaultStrategy()
+    {
+        StrategyList = new ArrayList();
+        
+        List<SeedLayer> TD012Layers = new ArrayList();
+        TD012Layers.add(new SeedLayer("TrackerEndcap", 0, SeedLayer.SeedType.SeedInner));
+        TD012Layers.add(new SeedLayer("TrackerEndcap", 1, SeedLayer.SeedType.SeedMiddle));
+        TD012Layers.add(new SeedLayer("TrackerEndcap", 2, SeedLayer.SeedType.SeedOuter));
+//        StrategyList.add(new SeedStrategy("TD012",TD012Layers));
+        
+        List<SeedLayer> VB012Layers = new ArrayList();
+        VB012Layers.add(new SeedLayer("VertexBarrel", 2, SeedLayer.SeedType.SeedInner));
+        VB012Layers.add(new SeedLayer("VertexBarrel", 3, SeedLayer.SeedType.SeedMiddle));
+        VB012Layers.add(new SeedLayer("VertexBarrel", 4, SeedLayer.SeedType.SeedOuter));
+        VB012Layers.add(new SeedLayer("TrackerBarrel", 0, SeedLayer.SeedType.Confirm3D));
+//        VB012Layers.add(new SeedLayer("VertexBarrel", 0, SeedLayer.SeedType.Confirm3D));
+//        VB012Layers.add(new SeedLayer("VertexBarrel", 1, SeedLayer.SeedType.Confirm3D));
+        StrategyList.add(new SeedStrategy("VB012",VB012Layers));
+        
+    }
+    public List<SeedStrategy> getStrategyList()
+    {
+        return StrategyList;
+    }
+}

lcsim/sandbox/Partridge
HelicalTrackFitter.java added at 1.1
diff -N HelicalTrackFitter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ HelicalTrackFitter.java	6 Aug 2007 23:59:57 -0000	1.1
@@ -0,0 +1,180 @@
+/*
+ * HelicalTrackFitter.java
+ *
+ * Created on March 25, 2006, 6:11 PM
+ *
+ * $Id: HelicalTrackFitter.java,v 1.1 2007/08/06 23:59:57 partridge Exp $
+ */
+
+package org.lcsim.contrib.seedtracker;
+import hep.physics.matrix.SymmetricMatrix;
+import static java.lang.Math.atan2;
+import static java.lang.Math.abs;
+import static java.lang.Math.PI;
+import static java.lang.Math.cos;
+import static java.lang.Math.sin;
+import org.lcsim.fit.circle.CircleFit;
+import org.lcsim.fit.circle.CircleFitter;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.line.SlopeInterceptLineFit;
+import org.lcsim.fit.line.SlopeInterceptLineFitter;
+/**
+ * Fit a helix to a set of space points.  First, a circle is fit to the x-y coordinates.
+ * A straight-line fit is then performed on the s-z coordinates.
+ * 
+ * The r-phi and z coordinate measurements are assumed to be uncorrelated.  A block
+ * diagonal covariance matrix is formed from the results of the circle and s-z fits,
+ * ignoring any correlations between these fits.
+ * 
+ * The resulting track parameters follow the "L3 Convention" adopted by org.lcsim.
+ * 
+ * Modified August 2006 by Richard Partridge
+ * @author Norman Graf
+ */
+public class HelicalTrackFitter
+{
+    private CircleFitter _cfitter = new CircleFitter();
+    private SlopeInterceptLineFitter _lfitter = new SlopeInterceptLineFitter();
+    
+    private HelicalTrackFit _fit;
+    
+    private double[] _circleParameters = new double[3];
+    
+    /**
+     * Creates a new instance of HelicalTrackFitter.
+     */
+    public HelicalTrackFitter()
+    {
+    }
+    
+    /**
+     * Fit a helix to a set of space points.  The space points should be ordered in
+     * increasing track length.  The code will properly handle loopers provided
+     * that the change in direction between successive points is less than pi.
+     * @param x Array of x coordinates
+     * @param y Array of y coordinates
+     * @param z Array of z coordinates
+     * @param drphi Error in r-phi hit position
+     * @param dz Error in z coordinate.  A negative value indicates that this point is to
+     * be excluded in the s-z fit.
+     * @param np Number of points
+     * @return True for successful fit
+     */
+    public boolean fit(double[] x, double[] y, double[] z, double[] drphi, double[] dz, int np)
+    {
+        // fit a circle in the x-y plane
+        double[] wrphi = new double[np];
+        for(int i=0; i<np; ++i)
+        {
+            wrphi[i] = 1/(drphi[i]*drphi[i]);
+        }
+        boolean success = _cfitter.fit(x, y, wrphi, np);
+        if(!success) return false;
+        
+        CircleFit cfit = _cfitter.getfit();
+        double radius = 1./cfit.curvature();
+        double phi0 = cfit.phi();
+        double dca = -cfit.dca();
+        double xc = (radius-dca)*sin(phi0);
+        double yc = -(radius-dca)*cos(phi0);
+        _circleParameters[0] = xc;
+        _circleParameters[1] = yc;
+        _circleParameters[2] = radius;
+        // fit a line in the s-z plane
+        // assumes points are in increasing order
+        double[] s = new double[np];
+        double[] sfit = new double[np];
+        double[] zfit = new double[np];
+        double[] wz = new double[np];
+        int nz = 0;
+        for(int i=0; i<np; i++)
+        {
+            if (i==0) {
+                s[0] = s(radius, xc, yc, x[0], y[0], 0., 0.);
+            }
+            else {
+                s[i] = s(radius, xc, yc, x[i], y[i], x[i-1], y[i-1]) + s[i-1];
+            }
+            if (dz[i]>0) {
+                sfit[nz] = s[i];
+                zfit[nz] = z[i];
+                wz[nz] = 1/(dz[i]*dz[i]);
+                nz++;
+            }
+        }
+        
+        success = _lfitter.fit(sfit, zfit, wz, nz);
+        if(!success) return false;
+        SlopeInterceptLineFit lfit = _lfitter.getFit();
+        
+        double[] pars = new double[5];
+        SymmetricMatrix cov = new SymmetricMatrix(5);
+        double[] chisq = new double[2];
+        int[] ndf = new int[2];
+        
+        chisq[0] = cfit.chisq();
+        chisq[1] = lfit.chisquared();
+        
+        ndf[1] = lfit.ndf();
+        ndf[0] = np - 3;
+        
+        // d0, xy impact parameter.  Note: - sign due to opposite sign convention in CircleFitter
+        pars[0] = -cfit.dca();
+        // phi0
+        pars[1] =  cfit.phi();
+        // omega signed curvature
+        pars[2] = cfit.curvature();
+        // z0
+        pars[3] = lfit.intercept();
+        // tan lambda
+        pars[4] = lfit.slope();
+        
+        // fill in covariance matrix
+        cov.setElement(0,0, cfit.cov()[0]);
+        cov.setElement(0,1,-cfit.cov()[1]);  // Need - sign due to sign convention in CircleFitter
+        cov.setElement(1,1, cfit.cov()[2]);
+        cov.setElement(0,2,-cfit.cov()[3]);  // Need - sign due to sign convention in CircleFitter
+        cov.setElement(1,2, cfit.cov()[4]);
+        cov.setElement(2,2, cfit.cov()[5]);
+        //cov[0][3] = 0.;
+        //cov[1][3] = 0.;
+        //cov[2][3] = 0.;
+        cov.setElement(3,3, lfit.interceptUncertainty());
+        //cov[0][4] = 0.;
+        //cov[1][4] = 0.;
+        //cov[2][4] = 0.;
+        cov.setElement(3,4, lfit.covariance());
+        cov.setElement(4,4, lfit.slopeUncertainty());
+        _fit = new HelicalTrackFit(pars, cov, chisq, ndf);
+        _fit.setCircleParameters(_circleParameters);
+        return true;
+    }
+    
+    /**
+     * Get the results of the most recent fit.
+     * @return HelicalTrackFit corresponding to most recent fit
+     */
+    public HelicalTrackFit getFit()
+    {
+        return _fit;
+    }
+    
+    /**
+     * Get the circle paramaters (xc, yc, R) from the most recent fit.
+     * @return Circle parameters (xc, yc, R)
+     */
+    public double[] getCircleParameters()
+    {
+        return _circleParameters;
+    }
+    
+    double s(double radius, double xcenter, double ycenter, double x1, double y1, double x2, double y2)
+    {
+        double phi1 = atan2( (y1-ycenter), (x1-xcenter) );
+        double phi2 = atan2( (y2-ycenter), (x2-xcenter) );
+        double dphi = abs(phi1-phi2);
+        if(dphi>PI) dphi = 2.*PI-dphi;
+        return abs(radius)*dphi;
+    }
+    
+}
\ No newline at end of file

lcsim/sandbox/Partridge
HitManager.java added at 1.1
diff -N HitManager.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ HitManager.java	6 Aug 2007 23:59:57 -0000	1.1
@@ -0,0 +1,124 @@
+/*
+ * HitManager.java
+ *
+ * Created on August 4, 2007, 4:03 PM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.contrib.seedtracker;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.lcsim.event.base.BaseTrackerHitMC;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
+
+/**
+ * Organize tracker hits into lists of hits sorted by detector name, layer number, and barrel-endcap flag
+ * @author Richard Partridge
+ * @version 1.0
+ */
+public class HitManager {
+    HashMap<String, List<TrackerHit>> map;
+    HashMap<String, double> _rmin;
+    HashMap<String, double> rmax;
+    HashMap<String, double> zmin;
+    HashMap<String, double> zmax;
+    private double _RMin = 99999;
+    private double _RMax = 0;
+    private double _ZMin = 99999;
+    private double _ZMax = -99999;
+    
+    /** Creates a new instance of HitManager */
+    public HitManager() {
+        
+    }
+    
+    /**
+     * Sort the hits into distinct lists where each list has a unique detector name, layer number, and barrel endcap flag
+     * @param event EventHeader for the event to be organized
+     */
+    public void OrganizeHits(EventHeader event) {
+        map = new HashMap<String, List<TrackerHit>>();
+        List<List<TrackerHit>> hitcollections = event.get(TrackerHit.class);
+        for (List<TrackerHit> hitlist : hitcollections) {
+            for (TrackerHit hit : hitlist) {
+                String identifier = LyrIdentifier(hit);
+                if (!map.containsKey(identifier)) {
+                    map.put(identifier, new ArrayList<TrackerHit>());
+                }
+                List<TrackerHit> lyrhits = map.get(identifier);
+                lyrhits.add(hit);
+            }
+        }
+    }
+    
+    /**
+     * Return a list of TrackerHits for a particular detector name, layer number, and barrel-endcap flag
+     * @param detname Name of the detector as referenced by the getName method of the subDetector class
+     * @param layer Layer number
+     * @param beflag Barrel-endcap flag
+     * @return List of matching TrackerHits
+     */
+    public List<TrackerHit> getTrackerHits(String detname, int layer, BarrelEndcapFlag beflag) {
+        return map.get(Identifier(detname, layer, beflag));
+    }
+    
+    public List<TrackerHit> getTrackerHits(SeedLayer seedlayer) {
+        return map.get(Identifier(seedlayer.getDetName(), seedlayer.getLayer(), seedlayer.getBEFlag()));
+    }
+    
+    private String LyrIdentifier(TrackerHit hit) {
+        if (hit instanceof BaseTrackerHitMC) {
+            BaseTrackerHitMC newhit = (BaseTrackerHitMC) hit;
+            SimTrackerHit simhit = newhit.getSimHits().get(0);
+            String detname = simhit.getSubdetector().getName();
+            int layer = simhit.getLayer();
+            BarrelEndcapFlag beflag = simhit.getIDDecoder().getBarrelEndcapFlag();
+            return Identifier(detname, layer, beflag);
+        } else return new String("Unknown");
+    }
+    
+    private String Identifier(String detname, int layer, BarrelEndcapFlag beflag) {
+        return new String(detname+layer+beflag.toString());
+    }
+    
+    /**
+     * Return the smallest radius for a hit in this layer
+     * @return Smallest radius for a hit in this layer
+     */
+    public double getRMin() {
+        return _RMin;
+    }
+    
+    /**
+     * Return largest radius for a hit in this layer
+     * @return Largest radius for a hit in this layer
+     */
+    public double getRMax() {
+        return _RMax;
+    }
+    
+    /**
+     * Return minimum z for a hit in this layer
+     * @return Minimum z for a hit in this layer
+     */
+    public double getZMin() {
+        return _ZMin;
+    }
+    
+    /**
+     * Return the maximum z coordinate for a hit in this layer
+     * @return Maximum z coordinate for a hit in this layer
+     */
+    public double getZMax() {
+        return _ZMax;
+    }
+    
+}

lcsim/sandbox/Partridge
SeedCandidate.java added at 1.1
diff -N SeedCandidate.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SeedCandidate.java	6 Aug 2007 23:59:57 -0000	1.1
@@ -0,0 +1,97 @@
+/*
+ * SeedCandidate.java
+ *
+ * Created on August 3, 2007, 11:05 AM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.contrib.seedtracker;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+
+/**
+ * Candidate seed containing a list of hits that make up the SeedCandidate and the associated helix parameters
+ * @author Richard Partridge
+ * @version 1.0
+ */
+public class SeedCandidate {
+    
+    private List<TrackerHit> _trackerhits = new ArrayList<TrackerHit>();
+    private HelicalTrackFit _helix;
+    
+    /**
+     * Create a new SeedCandidate from a list of hits
+     * @param trackerhits List of tracker hits for the SeedCandidate
+     */
+    public SeedCandidate(List<TrackerHit> trackerhits) {
+        _trackerhits.addAll(trackerhits);
+    }
+    
+    /**
+     * Create a new SeedCandidate from a list of hits and a helix
+     * @param trackerhits List of TrackerHits for the SeedCandidate
+     * @param helix HelicalTrackFit associated with the SeedCandidate
+     */
+    public SeedCandidate(List<TrackerHit> trackerhits, HelicalTrackFit helix) {
+        this(trackerhits);
+        _helix = helix;
+    }
+    
+    /**
+     * Creates a clone of an existing instance of SeedCandidate
+     * @param seed Existing SeedCandidate to be cloned
+     */
+    public SeedCandidate(SeedCandidate seed) {
+        this(seed.getTrackerHits(), seed.getHelix());
+    }
+    
+    /**
+     * Assign a list of TrackerHits to the SeedCandidate
+     * @param trackerhits List of TrackerHits for the SeedCandidate
+     */
+    public void setTrackerHits(List<TrackerHit> trackerhits) {
+        _trackerhits.clear();
+        _trackerhits.addAll(trackerhits);
+        return;
+    }
+    
+    /**
+     * Assign helix parameters to the SeedCandidate
+     * @param helix HelicalTrackFit associated with the SeedCandidate
+     */
+    public void setHelix(HelicalTrackFit helix) {
+        _helix = helix;
+        return;
+    }
+    
+    /**
+     * Add a hit to the SeedCandidate
+     * @param hit TrackerHit to be added to the SeedCandidate
+     */
+    public void addHit(TrackerHit hit) {
+        _trackerhits.add(hit);
+        return;
+    }
+    
+    /**
+     * Return the list of TrackerHits for the SeedCandidate
+     * @return List of TrackerHits for the SeedCandidate
+     */
+    public List<TrackerHit> getTrackerHits() {
+        return _trackerhits;
+    }
+    
+    /**
+     * Return the HelicalTrackFit associated with the SeedCandidate
+     * @return HelicalTrackFit associated with the SeedCandidate
+     */
+    public HelicalTrackFit getHelix() {
+        return _helix;
+    }
+}

lcsim/sandbox/Partridge
SeedLayer.java added at 1.1
diff -N SeedLayer.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SeedLayer.java	6 Aug 2007 23:59:57 -0000	1.1
@@ -0,0 +1,89 @@
+/*
+ * SeedLayer.java
+ *
+ * Created on March 29, 2006, 1:59 PM
+ *
+ */
+
+package org.lcsim.contrib.seedtracker;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lcsim.event.TrackerHit;
+import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
+
+/**
+ * Encapsulates information about a tracker layer needed for the SeedTracker algorithm
+ * @author Richard Partridge
+ * @version 1.0
+ */
+public class SeedLayer {
+    /**
+     * Enumeration of possible layer types
+     */
+    public enum SeedType {
+        /**
+         * Seed layer
+         */
+        Seed, 
+        /**
+         * Confirmation layer
+         */
+        Confirm, 
+        /**
+         * Track extension layer
+         */
+        Extend}
+
+    private String _DetName;
+    private int _Layer;
+    private SeedType _Type;
+    private BarrelEndcapFlag _BEFlag;
+    
+    /**
+     * Creates a new instance of SeedLayer
+     * @param DetName Decector name
+     * @param Layer Layer number
+     * @param BEFlag Barrel-Endcap flag
+     * @param Type Layer type
+     */
+    public SeedLayer(String DetName, int Layer, BarrelEndcapFlag BEFlag, SeedType Type) {
+        _DetName = DetName;
+        _Layer = Layer;
+        _BEFlag = BEFlag;
+        _Type = Type;
+    }
+    
+    /**
+     * Return the detector name
+     * @return Detector name
+     */
+    public String getDetName() {
+        return _DetName;
+    }
+    
+    /**
+     * Return the layer number
+     * @return Layer number
+     */
+    public int getLayer() {
+        return _Layer;
+    }
+    
+    /**
+     * Return the barrel-endcap flag
+     * @return Barrel-endcap flag
+     */
+    public BarrelEndcapFlag getBEFlag() {
+        return _BEFlag;
+    }
+    
+    /**
+     * Retrun the layer type
+     * @return Layer type
+     */
+    public SeedType getType() {
+        return _Type;
+    }
+}

lcsim/sandbox/Partridge
SeedStrategy.java added at 1.1
diff -N SeedStrategy.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SeedStrategy.java	6 Aug 2007 23:59:57 -0000	1.1
@@ -0,0 +1,136 @@
+/*
+ * SeedStrategy.java
+ *
+ * Created on March 29, 2006, 3:04 PM
+ *
+ */
+
+package org.lcsim.contrib.seedtracker;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import org.lcsim.contrib.seedtracker.SeedLayer;
+
+/**
+ * Encapsulate the parameters and layers u
+ * @author Richard Partridge
+ * @version 1.0
+ */
+public class SeedStrategy {
+    private String _Name;
+    private List<SeedLayer> _LayerList = new ArrayList<SeedLayer>();
+    private double _MinPT = 0.5;
+    private double _MaxDCA = 10.0;
+    private double _MaxZ0 = 10.0;
+    private double _MaxChisq = 100.;
+    private int _MinConfirm = 1;
+    private int _MinHits = 4;
+    
+    /** Creates a new instance of SeedStrategy */
+    public SeedStrategy(String Name, List<SeedLayer> LayerList, double MinPT,
+            double MaxDCA, double MaxZ0, double MaxChisq, int MinConfirm, int MinHits) {
+        this(Name, MinPT, MaxDCA, MaxZ0, MaxChisq, MinConfirm, MinHits);
+        _LayerList.addAll(LayerList);
+    }
+    
+    public SeedStrategy(String Name, double MinPT, double MaxDCA,double MaxZ0,
+            double MaxChisq, int MinConfirm, int MinHits) {
+        _Name = Name;
+        _MinPT = MinPT;
+        _MaxDCA = MaxDCA;
+        _MaxZ0 = MaxZ0;
+        _MaxChisq = MaxChisq;
+        _MinConfirm = MinConfirm;
+        _MinHits = MinHits;
+    }
+    
+    public SeedStrategy(String Name) {
+        _Name = Name;
+    }
+    
+    public SeedStrategy(String Name, List<SeedLayer> LayerList) {
+        _Name = Name;
+        _LayerList.addAll(LayerList);
+    }
+    
+    public String getName() {
+        return _Name;
+    }
+    
+    public List<SeedLayer> getLayerList() {
+        return _LayerList;
+    }
+    
+    public double getMinPT() {
+        return _MinPT;
+    }
+    
+    public double getMaxDCA() {
+        return _MaxDCA;
+    }
+    
+    public double getMaxZ0() {
+        return _MaxZ0;
+    }
+    
+    public double getMaxChisq() {
+        return _MaxChisq;
+    }
+    
+    public int getMinConfirm() {
+        return _MinConfirm;
+    }
+    
+    public int getMinHits() {
+        return _MinHits;
+    }
+    
+    public void putLayerList(List<SeedLayer> LayerList) {
+        _LayerList.addAll(LayerList);
+        return;
+    }
+    
+    public void putMinPT(double MinPT) {
+        _MinPT = MinPT;
+        return;
+    }
+    
+    public void putMaxDCA(double MaxDCA) {
+        _MaxDCA = MaxDCA;
+        return;
+    }
+    
+    public void putMaxZ0(double MaxZ0) {
+        _MaxZ0 = MaxZ0;
+        return;
+    }
+    
+    public void putMaxChisq(double MaxChisq) {
+        _MaxChisq = MaxChisq;
+        return;
+    }
+    
+    public void putMinConfirm(int MinConfirm) {
+        _MinConfirm = MinConfirm;
+        return;
+    }
+    
+    public void putMinHits(int MinHits) {
+        _MinHits = MinHits;
+        return;
+    }
+    
+    public void addLayer(SeedLayer Layer) {
+        _LayerList.add(Layer);
+        return;
+    }
+    
+     public List<SeedLayer> getLayers(SeedLayer.SeedType type) {
+        List<SeedLayer> layers = new ArrayList();
+        for (SeedLayer layer : _LayerList) {
+            if (layer.getType() == type) layers.add(layer);
+        }
+        return layers;
+    }
+}
\ No newline at end of file

lcsim/sandbox/Partridge
SeedTracker.java added at 1.1
diff -N SeedTracker.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SeedTracker.java	6 Aug 2007 23:59:57 -0000	1.1
@@ -0,0 +1,309 @@
+/*
+ * SeedTracker.java
+ *
+ * Created on August 16, 2005, 8:54 AM
+ *
+ */
+
+package org.lcsim.contrib.seedtracker;
+
+import java.util.ArrayList;
+import java.util.ListIterator;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.event.base.BaseTrack;
+import org.lcsim.event.base.BaseTrackerHitMC;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.subdetector.MultiLayerTracker;
+import org.lcsim.util.Driver;
+import org.lcsim.event.EventHeader;
+import org.lcsim.fit.helicaltrack.HelicalTrackFitter;
+import java.util.List;
+
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.BasicHep3Vector;
+
+/**
+ * Tracking algorithm based on forming track seeds from all 3-hit combinations
+ * and adding tracks to the helix defined by the three hits.
+ *
+ * @author Richard Partridge
+ * @version 1.0
+ */
+public class SeedTracker extends Driver {
+    private DefaultStrategy DS = new DefaultStrategy();
+    private List<SeedStrategy> StrategyList = DS.getStrategyList();
+    private HelicalTrackFitter hf = new HelicalTrackFitter();
+    private HelicalTrackFit helix;
+    private Hep3Vector IP = new BasicHep3Vector(0.,0.,0.);
+    private double BField;
+    
+    /** Creates a new instance of SeedTracker */
+    public SeedTracker() {
+    }
+    
+    protected void process(EventHeader event) {
+        
+        // Find the magnetic field
+        Detector detector = event.getDetector();
+        BField = detector.getFieldMap().getField(IP).z();
+        
+        // Associate hits with layers (ignore layers that aren't included in a strategy
+        AssociateHits(event);
+        
+        // Create a list of tracks
+        List<BaseTrack> tracklist = new ArrayList();
+        
+        // Loop over all strategies
+        for (SeedStrategy strategy : StrategyList) {
+            // Find the 3 hits seeds for this strategy
+            List<SeedCandidate> seedlist = FindSeeds(strategy);
+            // Loop over the seeds
+            for (SeedCandidate seed : seedlist) {
+                // See if we can create a helix that satisfies the cuts for this strategy
+                boolean status = hf.fit(seed.getTrackerHits());
+                if (!status) continue;
+                List<List<TrackerHit>> confirmlist = FindConfirms(strategy, seed);
+                int maxhits = 3 + strategy.getConfirmLayers().size();
+                int minhits = 3 + strategy.getMinConfirm();
+                // First try to find one or more tracks using all the confirm hits
+                // If this fails, work our way down to the minimum number
+                for (int nhit = maxhits; nhit >= minhits; nhit--) {
+                    boolean foundtrack = false;
+                    for (List<TrackerHit> candidate : confirmlist) {
+                        if (candidate.size() == nhit) {
+                            if (!isDuplicate(candidate, tracklist)) {
+                                boolean status2 = FindHelix(strategy, candidate);
+                                if (status2) {
+                                    // Create a new track
+                                    BaseTrack track = new BaseTrack();
+                                    track.setReferencePoint(IP.v());
+                                    track.setRefPointIsDCA(false);
+                                    track.setTrackParameters(helix.parameters(), BField);
+                                    track.setChisq(helix.chisq()[0]+helix.chisq()[1]);
+                                    track.setNDF(helix.ndf()[0]+helix.ndf()[1]);
+                                    track.setCovarianceMatrix(helix.covariance());
+                                    track.setTrackType(0);
+                                    List<TrackerHit> castcand = new ArrayList();
+                                    for (BaseTrackerHitMC hit : candidate) {
+                                        castcand.add((TrackerHit) hit);
+                                    }
+                                    track.addHits(castcand);
+                                    tracklist.add(track);
+                                    foundtrack = true;
+                                }
+                            }
+                        }
+                    }
+                    if (foundtrack) break;
+                }
+            }
+        }
+        event.put("Tracks", tracklist, Track.class, 0);
+    }
+    
+    private void AssociateHits(EventHeader event) {
+        List<BaseTrackerHitMC>  hitcol = event.get(BaseTrackerHitMC.class,"BaseTrackerHitMC");
+        
+        for (SeedStrategy strategy : StrategyList) {
+            for (SeedLayer slyr : strategy.getLayerList()) {
+                slyr.clearHitList();
+                for (BaseTrackerHitMC hit : hitcol) {
+                    for (SimTrackerHit simhit : hit.getSimHits()) {
+                        if (simhit.getLayer() == slyr.Layer) {
+                            if (simhit.getSubdetector().getName().equals(slyr.getDetName())) {
+                                slyr.addHit(hit);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return;
+    }
+    public List<SeedStrategy> getStrategyList() {
+        return StrategyList;
+    }
+    
+    public void putStrategyList(List<SeedStrategy> StrategyList) {
+        this.StrategyList = StrategyList;
+        return;
+    }
+    
+    private List<SeedCandidate> FindSeeds(SeedStrategy strategy) {
+        
+        SeedLayer inner = strategy.getSeedInner();
+        SeedLayer middle = strategy.getSeedMiddle();
+        SeedLayer outer = strategy.getSeedOuter();
+        
+        double RMin = strategy.getMinPT() / (0.0003 * BField);
+        double dMax = strategy.getMaxDCA();
+        
+        // Todo: add code to limit seeds to those that satisfy cuts
+        List<SeedCandidate> seedlist = new ArrayList();
+        
+        for (TrackerHit si : inner.getHitList()) {
+            double[] pos1 = si.getPosition();
+            double r1 = Math.sqrt(pos1[0]*pos1[0] + pos1[1]*pos1[1]);
+            double phi1 = Math.atan2(pos1[1],pos1[0]);
+            double dphi1 = Math.asin((2*RMin*dMax - dMax*dMax-r1*r1)/(2*r1*(RMin-dMax)));
+            for (TrackerHit sm : middle.getHitList()) {
+                double[] pos2 = sm.getPosition();
+                double r2 = Math.sqrt(pos2[0]*pos2[0] + pos2[1]*pos2[1]);
+                double phi2 = Math.atan2(pos2[1],pos2[0]);
+                double dphi2 = Math.asin((2*RMin*dMax - dMax*dMax-r2*r2)/(2*r2*(RMin-dMax)));
+                if (Math.abs(phi2-phi1) > Math.abs(dphi2-dphi1)) continue;
+                
+                for (TrackerHit so : outer.getHitList()) {
+                    double[] pos3 = so.getPosition();
+                    double r3 = Math.sqrt(pos3[0]*pos3[0] + pos3[1]*pos3[1]);
+                    double phi3 = Math.atan2(pos3[1],pos3[0]);
+                    double dphi3 = Math.asin((2*RMin*dMax - dMax*dMax-r3*r3)/(2*r3*(RMin-dMax)));
+                    if (Math.abs(phi3-phi2) > Math.abs(dphi3-dphi2)) continue;
+                    
+                    List<TrackerHit> hitlist = new ArrayList();
+                    hitlist.add(si);
+                    hitlist.add(sm);
+                    hitlist.add(so);
+                    seedlist.add(new SeedCandidate(hitlist));
+                }
+            }
+        }
+        System.out.println(" Number of seeds: "+seedlist.size());
+        
+        return seedlist;
+    }
+    
+    private boolean FindHelix(SeedStrategy strategy, List<BaseTrackerHitMC> hitlist) {
+        boolean status = false;
+        int np = hitlist.size();
+        double[] xx = new double[np];
+        double[] yy = new double[np];
+        double[] zz = new double[np];
+        double[] drphi = new double[np];
+        double[] dz = new double[np];
+        
+        for (int i=0; i<np; i++) {
+            BaseTrackerHitMC hit = hitlist.get(i);
+            double[] position = hit.getPosition();
+            xx[i] = position[0];
+            yy[i] = position[1];
+            zz[i] = position[2];
+            double[] covmat = hit.getCovMatrix();
+            drphi[i] = rphi_error(position, covmat);
+            dz[i] = Math.sqrt(covmat[5]);
+        }
+        boolean goodfit = hf.fit(xx, yy, zz, drphi, dz, np);
+        if (goodfit) {
+            helix = hf.getFit();
+            double[] params = helix.parameters();
+            double pT = 0.0003 * BField / Math.abs(params[2]);
+            if (helix.chisq()[0]+helix.chisq()[1] < strategy.getMaxChisq()) {
+                if (pT > strategy.getMinPT()) {
+                    double d0 = params[0];
+                    if (d0 < strategy.getMaxDCA()) {
+                        double z0 = params[3];
+                        if (z0 < strategy.getMaxZ0()) {
+                            System.out.println(" d0 "+params[0]);
+                            System.out.println(" phi0 "+params[1]);
+                            System.out.println(" curvatures "+params[2]);
+                            System.out.println(" z0 "+params[3]);
+                            System.out.println(" slope "+params[4]);
+                            System.out.println(" pT "+pT);
+                            status = true;
+                        }
+                    }
+                }
+            }
+        }
+        return status;
+    }
+    
+    private List<List<TrackerHit>> FindConfirms(SeedStrategy strategy, SeedCandidate seed) {
+        // Create a list of possible confirmation hits for each confirmation layer
+        List<List<TrackerHit>> confirmbylayer = new ArrayList();
+        // Loop over the various layers
+        for (SeedLayer layer : strategy.getConfirmLayers()) {
+            // Get the list of potential confirmation hits for this layer
+            // Todo - select only hits near tracks
+            List<TrackerHit> confirmhits = layer.getHitList();
+            // If we have some confirmation hits in this layer, add the list of hits for this layer
+            if (confirmhits.size()>0) confirmbylayer.add(confirmhits);
+        }
+        // Initialize a list of track candidates that include confirmation hits
+        List<List<TrackerHit>> candlist = new ArrayList();
+        // check that there are sufficient layers with confirmation hits
+        if (confirmbylayer.size() >= strategy.getMinConfirm()) {
+            // Start with our seed hits as a candidate
+            candlist.add(seed.getTrackerHits());
+            // Loop over all the confirming layers
+            for (List<TrackerHit> confirmhits : confirmbylayer) {
+                // Create a list of new candidates that have hits added from this layer
+                List<List<TrackerHit>> newcandlist = new ArrayList();
+                // Loop over all existing candidates
+                for (List<TrackerHit> oldcand : candlist) {
+                    // Loop over all the hits in this confirming layer
+                    for (TrackerHit hit : confirmhits) {
+                        // Create a new track candidate that adds this hit
+                        List<TrackerHit> newcand = new ArrayList();
+                        boolean status = newcand.addAll(oldcand);
+                        newcand.add(hit);
+                        newcandlist.add(newcand);
+                    }
+                }
+                boolean status = candlist.addAll(newcandlist);
+            }
+        }
+        // Remove candidates that have too few confirmation hits
+//        ListIterator<List<BaseTrackerHitMC>> itr = candlist.listIterator();
+//        while (itr.hasNext()) {
+//            List<BaseTrackerHitMC> hitlist = itr.next();
+//            if (hitlist.size() < strategy.getMinConfirm()+3) candlist.remove(hitlist);
+//        }
+        
+        return candlist;
+    }
+    
+    private boolean isDuplicate(List<TrackerHit> hitlist, List<BaseTrack> tracklist) {
+        boolean isDuplicate = false;
+        for (BaseTrack track : tracklist) {
+            List<TrackerHit> hitlist2 = track.getTrackerHits();
+            boolean matchall = true;
+            if (hitlist.size() <= hitlist2.size()) {
+                for ( BaseTrackerHitMC hit1 : hitlist) {
+                    boolean match = false;
+                    for (TrackerHit hit2 : hitlist2) {
+                        if (hit1 == (BaseTrackerHitMC) hit2) {
+                            match = true;
+                            break;
+                        }
+                    }
+                    if (!match) {
+                        matchall = false;
+                        break;
+                    }
+                }
+                if (matchall) {
+                    isDuplicate = true;
+                    break;
+                }
+            }
+        }
+        return isDuplicate;
+    }
+    
+    private double rphi_error(double[] position, double[] covmat) {
+        // Todo: include MS errors in weight
+        double x = position[0];
+        double y = position[1];
+        double r2 = x * x + y * y;
+        double varxx = covmat[0];
+        double varxy = covmat[1];
+        double varyy = covmat[2];
+        return Math.sqrt((y * y * varxx + x * x * varyy - 2 * x * y * varxy) / r2);
+    }
+    
+}
\ No newline at end of file

lcsim/sandbox/Partridge
SeedTrackerDriver.java added at 1.1
diff -N SeedTrackerDriver.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SeedTrackerDriver.java	6 Aug 2007 23:59:57 -0000	1.1
@@ -0,0 +1,34 @@
+/*
+ * SeedTrackerDriver.java
+ *
+ * Created on March 29, 2006, 4:58 PM
+ *
+ */
+
+package org.lcsim.contrib.seedtracker;
+
+import org.lcsim.contrib.seedtracker.SeedTracker;
+import org.lcsim.contrib.seedtracker.SmearMCHits;
+import org.lcsim.event.EventHeader;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author Richard Partridge
+ * @version 1.0
+ */
+public class SeedTrackerDriver extends Driver
+{  
+    /** Creates a new instance of SeedTrackerDriver */
+    public SeedTrackerDriver()
+    {
+        add(new SmearMCHits());
+        add(new SeedTracker());
+    }
+
+    public void process(EventHeader event)
+    {
+        super.process(event);
+        return;     
+    }    
+}

lcsim/sandbox/Partridge
SmearMCHits.java added at 1.1
diff -N SmearMCHits.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SmearMCHits.java	6 Aug 2007 23:59:57 -0000	1.1
@@ -0,0 +1,82 @@
+/*
+ * SmearMCHits.java
+ *
+ * Created on July 12, 2006, 10:25 AM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.contrib.seedtracker;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import org.lcsim.util.Driver;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseTrackerHitMC;
+
+/**
+ *
+ * @author partridge
+ */
+public class SmearMCHits extends Driver{
+    
+    Random rn = new Random();
+    double drphi = 0.005;
+    double dz = 0.005;
+    
+    /** Creates a new instance of SmearMCHits */
+    public SmearMCHits() {
+    }
+    
+    public void process(EventHeader event) {
+        
+        //  Initialize the TrackerHit list
+        List<BaseTrackerHitMC> trkhits = new ArrayList<BaseTrackerHitMC>();
+        //  Get the SimTrackerHit collections
+        List<List<SimTrackerHit>> allgenhits = event.get(SimTrackerHit.class);
+        //  Loop over the various hit collections
+        for (List<SimTrackerHit> genhitcol : allgenhits) {
+            //  Now loop over the hits in a particular collection
+            for (SimTrackerHit genhit : genhitcol) {
+                //  Generate a new BaseTrackerHitMC for each SimTrackerHit
+                //  Note: treat all layers the same for now, hard code the resolution
+                double x = genhit.getPoint()[0];
+                double y = genhit.getPoint()[1];
+                double z = genhit.getPoint()[2];
+                double r = Math.sqrt(x*x + y*y);
+                double phi = Math.atan2(y,x);
+                phi = phi + (drphi / r) * rn.nextGaussian();
+                z = z + dz * rn.nextGaussian();
+                // Fill in smeared position
+                double[] pos = new double[3];
+                pos[0] = r * Math.cos(phi);
+                pos[1] = r * Math.sin(phi);
+                pos[2] = z;
+                // covariance matrix in lower triangular form
+                double[] cov = new double[6];
+                cov[0] = Math.pow(Math.sin(phi)*drphi,2);
+                cov[1] = -Math.sin(phi)*Math.cos(phi)*drphi*drphi;
+                cov[2] = Math.pow(Math.cos(phi)*drphi,2);
+                cov[3] = 0.;
+                cov[4] = 0.;
+                cov[5] = dz*dz;
+                
+                double time = genhit.getTime();
+                
+                double dedx = genhit.getdEdx();
+                
+                int type = 0;
+                //  Create the list of SimTrackerHits for this TrackerHit and add our hit to the list
+                List<SimTrackerHit> hits = new ArrayList<SimTrackerHit>();
+                hits.add(genhit);
+                //  Create a new TrackerHit and add it to our list of tracker hits
+                trkhits.add(new BaseTrackerHitMC(pos, cov,  time, dedx, type, hits));
+            }
+        }
+        //  Put the list of TrackerHits into the event
+        event.put("BaseTrackerHitMC",trkhits,BaseTrackerHitMC.class,0);
+    }  
+}
CVSspam 0.2.8