Print

Print


Commit in lcsim/src/org/lcsim/recon/pfa/identifier on MAIN
FlexibleHelixExtrapolator.java+81added 1.1
HelixExtrapolationResult.java+65added 1.1
HelixExtrapolator.java+313added 1.1
TrackHelixExtrapolator.java+172added 1.1
TrackHelixPlusHitExtrapolator.java+113added 1.1
LocalHelixExtrapolationTrackClusterMatcher.java+12-91.2 -> 1.3
LocalHelixExtrapolationTrackMIPClusterMatcher.java+7-51.2 -> 1.3
LocalHelixExtrapolator.java+51-2631.15 -> 1.16
+814-277
5 added + 3 modified, total 8 files
MJC: Overhaul interface used for track extrapolation inside PFA

lcsim/src/org/lcsim/recon/pfa/identifier
FlexibleHelixExtrapolator.java added at 1.1
diff -N FlexibleHelixExtrapolator.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ FlexibleHelixExtrapolator.java	6 Sep 2008 23:47:00 -0000	1.1
@@ -0,0 +1,81 @@
+package org.lcsim.recon.pfa.identifier;
+
+import hep.physics.vec.*;
+import java.util.*;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.event.base.BaseTrackMC;
+
+public class FlexibleHelixExtrapolator extends HelixExtrapolator
+{
+    private LocalHelixExtrapolator m_LocalHelixExtrapolator = null;
+    private TrackHelixExtrapolator m_TrackHelixExtrapolator = null;
+    private HelixExtrapolator m_currentLiveExtrapolator = null;
+
+    public FlexibleHelixExtrapolator() {
+	super();
+	m_LocalHelixExtrapolator = new LocalHelixExtrapolator();
+	m_TrackHelixExtrapolator = new TrackHelixExtrapolator();
+    }
+
+    // Main interface
+
+    // This is where the track is specified -- decide at this point which
+    // kind of extrapolator to use.
+    public HelixExtrapolationResult performExtrapolation(Track tr) {
+	if (tr == null) {
+	    // Null track -- blank everything and return failure
+	    m_currentLiveExtrapolator = null;
+	    return null;
+	} else if (tr instanceof BaseTrackMC || tr instanceof org.lcsim.mc.fast.tracking.ReconTrack) {
+	    m_currentLiveExtrapolator = m_LocalHelixExtrapolator;
+	} else {
+	    m_currentLiveExtrapolator = m_TrackHelixExtrapolator;
+	}
+	return m_currentLiveExtrapolator.performExtrapolation(tr);
+    }
+
+    // Main interface routines
+    protected Hep3Vector getInterceptPoint() {
+	return m_currentLiveExtrapolator.getInterceptPoint();
+    }
+    protected Hep3Vector getTangent() {
+	return m_currentLiveExtrapolator.getTangent();
+    }
+    protected Hep3Vector getTangent(Hep3Vector v) {
+	return m_currentLiveExtrapolator.getTangent(v);
+    }
+    protected Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax ) {
+	return m_currentLiveExtrapolator.extendToEndcapLayer(layer, endcap_layering_z,endcap_rmin, endcap_rmax);
+    }
+    protected Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax ) {
+	return m_currentLiveExtrapolator.extendToBarrelLayer(layer, barrel_layering_r, barrel_zmin, barrel_zmax);
+    }
+
+    // Other things that need to be propagated to the extrapolator:
+    public void useFCAL(boolean use) {
+	super.useFCAL(use);
+	m_LocalHelixExtrapolator.useFCAL(use);
+	m_TrackHelixExtrapolator.useFCAL(use);
+    }
+
+    public void process(EventHeader event) {
+	super.process(event);
+	m_LocalHelixExtrapolator.process(event);
+	m_TrackHelixExtrapolator.process(event);
+    }
+
+    public void initGeometry(EventHeader event) {
+	super.initGeometry(event);
+	m_LocalHelixExtrapolator.initGeometry(event);
+	m_TrackHelixExtrapolator.initGeometry(event);
+    }
+
+    public void setCutSeparation(double cutSeparation) {
+	super.setCutSeparation(cutSeparation);
+	m_LocalHelixExtrapolator.setCutSeparation(cutSeparation);
+	m_TrackHelixExtrapolator.setCutSeparation(cutSeparation);
+    }
+
+}

lcsim/src/org/lcsim/recon/pfa/identifier
HelixExtrapolationResult.java added at 1.1
diff -N HelixExtrapolationResult.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ HelixExtrapolationResult.java	6 Sep 2008 23:47:00 -0000	1.1
@@ -0,0 +1,65 @@
+package org.lcsim.recon.pfa.identifier;
+
+import hep.physics.vec.*;
+import java.util.*;
+
+public class HelixExtrapolationResult
+{
+    HelixExtrapolator m_internalExtrapolator;
+    protected HelixExtrapolationResult(HelixExtrapolator extrap) {
+	m_internalExtrapolator = extrap;
+    }
+
+    // Interface
+    public Hep3Vector getInterceptPoint() {
+	return m_internalExtrapolator.getInterceptPoint();
+    }
+    public Hep3Vector getTangent() {
+	return m_internalExtrapolator.getTangent();
+    }
+    public Hep3Vector getTangent(Hep3Vector v) {
+	return m_internalExtrapolator.getTangent(v);
+    }
+    public Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax ) {
+	return m_internalExtrapolator.extendToEndcapLayer(layer, endcap_layering_z, endcap_rmin, endcap_rmax);
+    }
+    public Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax ) {
+	return m_internalExtrapolator.extendToBarrelLayer(layer, barrel_layering_r, barrel_zmin, barrel_zmax );
+    }
+    public Long extendToECALLayerAndFindCell(int layer) {
+	return m_internalExtrapolator.extendToECALLayerAndFindCell(layer);
+    }
+    public Long extendToHCALLayerAndFindCell(int layer) {
+	return m_internalExtrapolator.extendToHCALLayerAndFindCell(layer);
+    }
+    public Long extendToMCALLayerAndFindCell(int layer) {
+	return m_internalExtrapolator.extendToMCALLayerAndFindCell(layer);
+    }
+    public Hep3Vector extendToECALLayer(int layer) {
+	return m_internalExtrapolator.extendToECALLayer(layer);
+    }
+    public Hep3Vector extendToHCALLayer(int layer) {
+	return m_internalExtrapolator.extendToHCALLayer(layer);
+    }
+    public Hep3Vector extendToMCALLayer(int layer) {
+	return m_internalExtrapolator.extendToMCALLayer(layer);
+    }
+    public Hep3Vector extendToECALBarrelLayer(int layer) {
+	return m_internalExtrapolator.extendToECALBarrelLayer(layer);
+    }
+    public Hep3Vector extendToECALEndcapLayer(int layer) {
+	return m_internalExtrapolator.extendToECALEndcapLayer(layer);
+    }
+    public Hep3Vector extendToHCALBarrelLayer(int layer) {
+	return m_internalExtrapolator.extendToHCALBarrelLayer(layer);
+    }
+    public Hep3Vector extendToHCALEndcapLayer(int layer) {
+	return m_internalExtrapolator.extendToHCALEndcapLayer(layer);
+    }
+    public Hep3Vector extendToMCALBarrelLayer(int layer) {
+	return m_internalExtrapolator.extendToMCALBarrelLayer(layer);
+    }
+    public Hep3Vector extendToMCALEndcapLayer(int layer) {
+	return m_internalExtrapolator.extendToMCALEndcapLayer(layer);
+    }
+}

lcsim/src/org/lcsim/recon/pfa/identifier
HelixExtrapolator.java added at 1.1
diff -N HelixExtrapolator.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ HelixExtrapolator.java	6 Sep 2008 23:47:00 -0000	1.1
@@ -0,0 +1,313 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import hep.physics.vec.*;
+import org.lcsim.util.decision.*;
+
+import hep.physics.particle.Particle;
+import org.lcsim.util.swim.HelixSwimmer;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.geometry.subdetector.CylindricalCalorimeter;
+import org.lcsim.geometry.Detector;
+import org.lcsim.recon.cluster.util.BasicCluster;
+import org.lcsim.recon.cluster.util.TensorClusterPropertyCalculator;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.util.Driver;
+import org.lcsim.event.MCParticle;
+import org.lcsim.mc.fast.tracking.ReconTrack;
+import org.lcsim.event.SimCalorimeterHit;
+import org.lcsim.recon.pfa.identifier.TrackClusterMatcher;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.mc.fast.tracking.ReconTrack;
+import org.lcsim.event.base.*;
+import org.lcsim.geometry.IDDecoder;
+
+abstract public class HelixExtrapolator extends Driver
+{
+
+    protected boolean m_init = false;
+    protected double m_ECAL_barrel_zmin;
+    protected double m_HCAL_barrel_zmin;
+    protected double m_MCAL_barrel_zmin;
+    protected double m_ECAL_barrel_zmax;
+    protected double m_HCAL_barrel_zmax;
+    protected double m_MCAL_barrel_zmax;
+    protected double m_ECAL_barrel_r;
+    protected double m_HCAL_barrel_r;
+    protected double m_MCAL_barrel_r;
+    protected double m_ECAL_endcap_z;
+    protected double m_FCAL_endcap_z;
+    protected double m_HCAL_endcap_z;
+    protected double m_MCAL_endcap_z;
+    protected Vector<Double> m_ECAL_barrel_layering_r;
+    protected Vector<Double> m_HCAL_barrel_layering_r;
+    protected Vector<Double> m_MCAL_barrel_layering_r;
+    protected Vector<Double> m_ECAL_endcap_layering_z;
+    protected Vector<Double> m_FCAL_endcap_layering_z;
+    protected Vector<Double> m_HCAL_endcap_layering_z;
+    protected Vector<Double> m_MCAL_endcap_layering_z;
+    protected double m_ECAL_endcap_rmin;
+    protected double m_FCAL_endcap_rmin;
+    protected double m_HCAL_endcap_rmin;
+    protected double m_MCAL_endcap_rmin;
+    protected double m_ECAL_endcap_rmax;
+    protected double m_FCAL_endcap_rmax;
+    protected double m_HCAL_endcap_rmax;
+    protected double m_MCAL_endcap_rmax;
+    protected double[] m_fieldStrength;
+
+    protected double m_cutSeparation = 30.0; // 3cm
+    public void setCutSeparation(double cutSeparation) { m_cutSeparation = cutSeparation; }
+
+    boolean m_barrelValid = false;
+    boolean m_endcapValid = false;
+
+    EventHeader m_event = null;
+    Track m_track = null;
+
+    boolean m_useFCAL = false;
+    boolean m_interceptsFCAL = false;
+    boolean m_debug = false;
+
+    public HelixExtrapolator() {
+	super();
+    }
+
+    protected HelixExtrapolator(HelixExtrapolator old) {
+	super();
+	m_init = false;
+	if (old.m_init && old.m_event != null) {
+	    initGeometry(old.m_event);
+	}
+	
+	setCutSeparation(old.m_cutSeparation);
+	m_barrelValid = old.m_barrelValid;
+	m_endcapValid = old.m_endcapValid;
+	m_event = old.m_event;
+	m_track = old.m_track;
+	useFCAL(old.m_useFCAL);
+	m_interceptsFCAL = old.m_interceptsFCAL;
+	m_debug = old.m_debug;
+    }
+
+    /** Allow use of FCAL. */
+    public void useFCAL(boolean use) {
+	m_useFCAL = use;
+    }
+
+    /** Process this event, storing geometry info if needed. */
+    public void process(EventHeader event) {
+	m_event = event;
+	initGeometry(event);
+    }
+
+    /** Initialize geometry. This is done automatically if the class is run as a driver. */
+    public void initGeometry(EventHeader event) {
+	Detector det = event.getDetector();
+	CylindricalCalorimeter emb = ((CylindricalCalorimeter) det.getSubdetectors().get("EMBarrel"));
+	CylindricalCalorimeter eme = ((CylindricalCalorimeter) det.getSubdetectors().get("EMEndcap"));
+	CylindricalCalorimeter hdb = ((CylindricalCalorimeter) det.getSubdetectors().get("HADBarrel"));
+	CylindricalCalorimeter hde = ((CylindricalCalorimeter) det.getSubdetectors().get("HADEndcap"));
+	CylindricalCalorimeter fwe = ((CylindricalCalorimeter) det.getSubdetectors().get("ForwardEMEndcap"));
+	CylindricalCalorimeter mub = ((CylindricalCalorimeter) det.getSubdetectors().get("MuonBarrel"));
+	CylindricalCalorimeter mue = ((CylindricalCalorimeter) det.getSubdetectors().get("MuonEndcap"));
+	m_ECAL_barrel_zmin = emb.getZMin();
+	m_HCAL_barrel_zmin = hdb.getZMin();
+	m_MCAL_barrel_zmin = mub.getZMin();
+	m_ECAL_barrel_zmax = emb.getZMax();
+	m_HCAL_barrel_zmax = hdb.getZMax();
+	m_MCAL_barrel_zmax = mub.getZMax();
+	m_ECAL_barrel_r = emb.getLayering().getDistanceToLayerSensorMid(0);
+	m_HCAL_barrel_r = hdb.getLayering().getDistanceToLayerSensorMid(0);
+	m_MCAL_barrel_r = mub.getLayering().getDistanceToLayerSensorMid(0);
+	m_ECAL_endcap_z = eme.getLayering().getDistanceToLayerSensorMid(0);
+	m_FCAL_endcap_z = fwe.getLayering().getDistanceToLayerSensorMid(0);
+	m_HCAL_endcap_z = hde.getLayering().getDistanceToLayerSensorMid(0);
+	m_MCAL_endcap_z = mue.getLayering().getDistanceToLayerSensorMid(0);
+	m_ECAL_endcap_rmin = eme.getInnerRadius();
+	m_FCAL_endcap_rmin = fwe.getInnerRadius();
+	m_HCAL_endcap_rmin = hde.getInnerRadius();
+	m_MCAL_endcap_rmin = mue.getInnerRadius();
+	m_ECAL_endcap_rmax = eme.getOuterRadius();
+	m_FCAL_endcap_rmax = fwe.getOuterRadius();
+	m_HCAL_endcap_rmax = hde.getOuterRadius();
+	m_MCAL_endcap_rmax = mue.getOuterRadius();
+	double[] zero = {0, 0, 0};
+	m_fieldStrength = det.getFieldMap().getField(zero);
+	m_ECAL_barrel_layering_r = new Vector<Double>();
+	for (int iLayer=0; iLayer<emb.getLayering().getLayerCount(); iLayer++) {
+	    double r = emb.getLayering().getDistanceToLayerSensorMid(iLayer);
+	    m_ECAL_barrel_layering_r.add(new Double(r));
+	}
+	m_ECAL_endcap_layering_z = new Vector<Double>();
+	for (int iLayer=0; iLayer<eme.getLayering().getLayerCount(); iLayer++) {
+	    double z = eme.getLayering().getDistanceToLayerSensorMid(iLayer);
+	    m_ECAL_endcap_layering_z.add(new Double(z));
+	}
+	m_FCAL_endcap_layering_z = new Vector<Double>();
+	for (int iLayer=0; iLayer<fwe.getLayering().getLayerCount(); iLayer++) {
+	    double z = fwe.getLayering().getDistanceToLayerSensorMid(iLayer);
+	    m_FCAL_endcap_layering_z.add(new Double(z));
+	}
+	m_HCAL_barrel_layering_r = new Vector<Double>();
+	for (int iLayer=0; iLayer<hdb.getLayering().getLayerCount(); iLayer++) {
+	    double r = hdb.getLayering().getDistanceToLayerSensorMid(iLayer);
+	    m_HCAL_barrel_layering_r.add(new Double(r));
+	}
+	m_HCAL_endcap_layering_z = new Vector<Double>();
+	for (int iLayer=0; iLayer<hde.getLayering().getLayerCount(); iLayer++) {
+	    double z = hde.getLayering().getDistanceToLayerSensorMid(iLayer);
+	    m_HCAL_endcap_layering_z.add(new Double(z));
+	}
+	m_MCAL_barrel_layering_r = new Vector<Double>();
+	for (int iLayer=0; iLayer<hdb.getLayering().getLayerCount(); iLayer++) {
+	    double r = hdb.getLayering().getDistanceToLayerSensorMid(iLayer);
+	    m_MCAL_barrel_layering_r.add(new Double(r));
+	}
+	m_MCAL_endcap_layering_z = new Vector<Double>();
+	for (int iLayer=0; iLayer<hde.getLayering().getLayerCount(); iLayer++) {
+	    double z = hde.getLayering().getDistanceToLayerSensorMid(iLayer);
+	    m_MCAL_endcap_layering_z.add(new Double(z));
+	}
+	m_init = true;
+    }
+ 
+    // Interface
+    abstract public    HelixExtrapolationResult performExtrapolation(Track tr);
+    abstract protected Hep3Vector getInterceptPoint();
+    abstract protected Hep3Vector getTangent();
+    abstract protected Hep3Vector getTangent(Hep3Vector v);
+    abstract protected Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax );
+    abstract protected Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax );
+
+    // Things that only use the interface
+    
+    protected Long extendToECALLayerAndFindCell(int layer) {
+	Hep3Vector point = extendToECALLayer(layer);
+	IDDecoder id = null;
+	if (m_barrelValid) {
+	    id = m_event.getDetector().getDecoder("EcalBarrHits");
+	    if (id == null) { throw new AssertionError("Failed to find barrel ID"); }
+	} else if (m_endcapValid) {
+	    id = m_event.getDetector().getDecoder("EcalEndcapHits");
+	    if (id == null) { throw new AssertionError("Failed to find endcap ID"); }
+	}
+	if (id != null && point != null) {
+	    long cell = id.findCellContainingXYZ(point);
+	    id.setID(cell);
+	    Hep3Vector cellCenter = id.getPositionVector();
+	    return new Long(cell);
+	} else {
+	    return null;
+	}
+    }
+
+    protected Long extendToHCALLayerAndFindCell(int layer) {
+	Hep3Vector point = extendToHCALLayer(layer);
+	IDDecoder id = null;
+	if (m_barrelValid) {
+	    id = m_event.getDetector().getDecoder("HcalBarrHits");
+	    if (id == null) { throw new AssertionError("Failed to find barrel ID"); }
+	} else if (m_endcapValid) {
+	    id = m_event.getDetector().getDecoder("HcalEndcapHits");
+	    if (id == null) { throw new AssertionError("Failed to find endcap ID"); }
+	}
+	if (id != null && point != null) {
+	    long cell = id.findCellContainingXYZ(point);
+	    id.setID(cell);
+	    Hep3Vector cellCenter = id.getPositionVector();
+	    return new Long(cell);
+	} else {
+	    return null;
+	}
+    }
+
+    protected Long extendToMCALLayerAndFindCell(int layer) {
+	Hep3Vector point = extendToMCALLayer(layer);
+	IDDecoder id = null;
+	if (m_barrelValid) {
+	    id = m_event.getDetector().getDecoder("MuonBarrHits");
+	    if (id == null) { throw new AssertionError("Failed to find barrel ID"); }
+	} else if (m_endcapValid) {
+	    id = m_event.getDetector().getDecoder("MuonEndcapHits");
+	    if (id == null) { throw new AssertionError("Failed to find endcap ID"); }
+	}
+	if (id != null && point != null) {
+	    long cell = id.findCellContainingXYZ(point);
+	    id.setID(cell);
+	    Hep3Vector cellCenter = id.getPositionVector();
+	    return new Long(cell);
+	} else {
+	    return null;
+	}
+    }
+
+    /** Assumes extrapolation has already been done. */
+    protected Hep3Vector extendToECALLayer(int layer) {
+	if (m_barrelValid) {
+	    return extendToECALBarrelLayer(layer);
+	} else if (m_endcapValid) {
+	    return extendToECALEndcapLayer(layer);
+	} else {
+	    // No solution
+	    return null;
+	}
+    }
+
+    /** Assumes extrapolation has already been done. */
+    protected Hep3Vector extendToHCALLayer(int layer) {
+	if (m_barrelValid) {
+	    return extendToHCALBarrelLayer(layer);
+	} else if (m_endcapValid) {
+	    return extendToHCALEndcapLayer(layer);
+	} else {
+	    // No solution
+	    return null;
+	}
+    }
+
+    /** Assumes extrapolation has already been done. */
+    protected Hep3Vector extendToMCALLayer(int layer) {
+	if (m_barrelValid) {
+	    return extendToMCALBarrelLayer(layer);
+	} else if (m_endcapValid) {
+	    return extendToMCALEndcapLayer(layer);
+	} else {
+	    // No solution
+	    return null;
+	}
+    }
+
+    /** Assumes extrapolation has already been done. */
+    protected Hep3Vector extendToECALBarrelLayer(int layer) {
+	return extendToBarrelLayer(layer, m_ECAL_barrel_layering_r, m_ECAL_barrel_zmin, m_ECAL_barrel_zmax);
+    }
+    /** Assumes extrapolation has already been done. */
+    protected Hep3Vector extendToECALEndcapLayer(int layer) {
+	if (m_useFCAL && m_interceptsFCAL) {
+	    Hep3Vector vec = extendToEndcapLayer(layer, m_FCAL_endcap_layering_z, m_FCAL_endcap_rmin, m_FCAL_endcap_rmax);
+	    if (vec != null) {
+		return vec;
+	    }
+	}
+	return extendToEndcapLayer(layer, m_ECAL_endcap_layering_z, m_ECAL_endcap_rmin, m_ECAL_endcap_rmax);
+    }
+    /** Assumes extrapolation has already been done. */
+    protected Hep3Vector extendToHCALBarrelLayer(int layer) {
+	return extendToBarrelLayer(layer, m_HCAL_barrel_layering_r, m_HCAL_barrel_zmin, m_HCAL_barrel_zmax);
+    }
+    /** Assumes extrapolation has already been done. */
+    protected Hep3Vector extendToHCALEndcapLayer(int layer) {
+	return extendToEndcapLayer(layer, m_HCAL_endcap_layering_z, m_HCAL_endcap_rmin, m_HCAL_endcap_rmax);
+    }
+    /** Assumes extrapolation has already been done. */
+    protected Hep3Vector extendToMCALBarrelLayer(int layer) {
+	return extendToBarrelLayer(layer, m_MCAL_barrel_layering_r, m_MCAL_barrel_zmin, m_MCAL_barrel_zmax);
+    }
+    /** Assumes extrapolation has already been done. */
+    protected Hep3Vector extendToMCALEndcapLayer(int layer) {
+	return extendToEndcapLayer(layer, m_MCAL_endcap_layering_z, m_MCAL_endcap_rmin, m_MCAL_endcap_rmax);
+    }
+}

lcsim/src/org/lcsim/recon/pfa/identifier
TrackHelixExtrapolator.java added at 1.1
diff -N TrackHelixExtrapolator.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TrackHelixExtrapolator.java	6 Sep 2008 23:47:00 -0000	1.1
@@ -0,0 +1,172 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import hep.physics.vec.*;
+import org.lcsim.util.decision.*;
+
+import hep.physics.particle.Particle;
+import org.lcsim.util.swim.HelixSwimmer;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.geometry.subdetector.CylindricalCalorimeter;
+import org.lcsim.geometry.Detector;
+import org.lcsim.recon.cluster.util.BasicCluster;
+import org.lcsim.recon.cluster.util.TensorClusterPropertyCalculator;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.util.Driver;
+import org.lcsim.event.MCParticle;
+import org.lcsim.mc.fast.tracking.ReconTrack;
+import org.lcsim.event.SimCalorimeterHit;
+import org.lcsim.recon.pfa.identifier.TrackClusterMatcher;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.mc.fast.tracking.ReconTrack;
+import org.lcsim.event.base.*;
+import org.lcsim.geometry.IDDecoder;
+
+public class TrackHelixExtrapolator extends HelixExtrapolator
+{
+    protected Hep3Vector m_intercept = null;
+    protected HelixSwimmer m_swimmer = null;
+    protected double m_alphaIntercept = Double.NaN;
+
+    public TrackHelixExtrapolator() {
+	super();
+    }
+
+    protected TrackHelixExtrapolator(TrackHelixExtrapolator old) {
+	super(old);
+	if (old.m_intercept != null) {
+	    m_intercept = new BasicHep3Vector(old.m_intercept.x(), old.m_intercept.y(), old.m_intercept.z());
+	} else {
+	    m_intercept = null;
+	}
+	m_swimmer = old.m_swimmer; // Safe, since any change to track will create a new HelixSwimmer.
+	m_alphaIntercept = old.m_alphaIntercept;
+    }
+
+    public void process(EventHeader event) {
+	super.process(event);
+    }
+
+    protected Hep3Vector getInterceptPoint() {
+	return new BasicHep3Vector(m_intercept.x(), m_intercept.y(), m_intercept.z());
+    }
+    public HelixExtrapolationResult performExtrapolation(Track tr) {
+	m_track = tr;
+	// Null track means we blank everything and return failure.
+	if (tr == null) {
+	    m_intercept = null;
+	    m_swimmer = null;
+	    m_alphaIntercept = Double.NaN;
+	    return null;
+	}
+
+	// Make a HelixSwimmer to propagate the track
+	m_swimmer = new HelixSwimmer(m_fieldStrength[2]);
+	m_swimmer.setTrack(tr);
+	
+        // Try swimming to the barrel:
+        double  alphaBarrel = swimToBarrel(m_swimmer);
+        boolean validBarrel = false;
+        // Try swimming to the endcap:
+        double  alphaEndcap = swimToEndcap(m_swimmer);
+        boolean validEndcap = false;
+
+	// Get helix fit output
+	m_alphaIntercept = Double.NaN; 
+        if (isValidBarrelIntercept(m_swimmer, alphaBarrel, m_cutSeparation)) {
+            m_alphaIntercept = alphaBarrel;
+            validBarrel = true;
+        } else if (isValidEndcapIntercept(m_swimmer, alphaEndcap, m_cutSeparation)) {
+            m_alphaIntercept = alphaEndcap;
+            validEndcap = true;
+        }
+
+	// Did we make a successful extrapolation?
+        if ( Double.isNaN(m_alphaIntercept)) {
+	    // No -- extrapolation failed
+	    return null;
+	} else if ( !(validEndcap || validBarrel) ) {
+	    // Invalid state
+	    return null;
+	} else {
+	    // One or both solutions valid.
+	    if ( validEndcap && validBarrel ) {
+		// Both apparently valid... check again
+		boolean tightValidEndcap = isValidEndcapIntercept(m_swimmer, alphaEndcap, 0.0);
+		boolean tightValidBarrel = isValidBarrelIntercept(m_swimmer, alphaBarrel, 0.0);
+		if (tightValidEndcap && tightValidBarrel) {
+		    throw new AssertionError("Invalid state");
+		} else if (!tightValidEndcap && !tightValidBarrel) {
+		    throw new AssertionError("Invalid state");
+		} else {
+		    // Only one valid solution -- OK
+		    validEndcap = tightValidEndcap;
+		    validBarrel = tightValidBarrel;
+		}
+	    }
+	    // Extrapolation succeeded.
+	    m_intercept = m_swimmer.getPointAtDistance(m_alphaIntercept);
+	    m_barrelValid = validBarrel;
+	    m_endcapValid = validEndcap;
+	    // Output
+	    HelixExtrapolationResult output = new HelixExtrapolationResult(new TrackHelixExtrapolator(this));
+	    return output;
+	}
+    }
+    protected Hep3Vector getTangent() {
+	return VecOp.unit(m_swimmer.getMomentumAtLength(m_alphaIntercept));
+    }
+    protected Hep3Vector getTangent(Hep3Vector v) {
+	double alphaPoint = m_swimmer.getDistanceToPoint(v);
+	return VecOp.unit(m_swimmer.getMomentumAtLength(alphaPoint));
+    }
+    protected Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax ) {
+	double layer_z = Math.abs(endcap_layering_z.get(layer));
+        double distanceToEndcap1 = m_swimmer.getDistanceToZ( layer_z);
+        double distanceToEndcap2 = m_swimmer.getDistanceToZ(-layer_z);
+	if (distanceToEndcap1>0) {
+	    return m_swimmer.getPointAtDistance(distanceToEndcap1);
+	} else {
+	    return m_swimmer.getPointAtDistance(distanceToEndcap2);
+	}
+    }
+    protected Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax ) {
+	double layer_r =  barrel_layering_r.get(layer);
+	double distance = m_swimmer.getDistanceToRadius(layer_r);
+	return m_swimmer.getPointAtDistance(distance);
+    }
+
+    // Internal stuff
+    protected double swimToBarrel(HelixSwimmer swimmer) {
+        // Look for a hit in the first layer of the ECAL barrel
+        return swimmer.getDistanceToRadius(m_ECAL_barrel_r);
+    }
+    protected double swimToEndcap(HelixSwimmer swimmer) {
+        // Look for a hit in the first layer of the ECAL endcap
+        double distanceToEndcap1 = swimmer.getDistanceToZ(m_ECAL_endcap_z);
+        double distanceToEndcap2 = swimmer.getDistanceToZ(-m_ECAL_endcap_z);
+        if (distanceToEndcap1>0) {
+            return distanceToEndcap1;
+        } else {
+            return distanceToEndcap2;
+        }
+    }
+    protected boolean isValidBarrelIntercept(HelixSwimmer swimmer, double alpha, double uncertainty) {
+        // Must have -m_ECAL_barrel_z <= z <= +m_ECAL_barrel_z (within errors)
+        //double uncertainty = m_cutSeparation;
+        Hep3Vector intercept = swimmer.getPointAtDistance(alpha);
+        double z = intercept.z();
+        boolean zInRange = (z >= m_ECAL_barrel_zmin-uncertainty && z <= m_ECAL_barrel_zmax+uncertainty);
+        return zInRange;
+    }
+    protected boolean isValidEndcapIntercept(HelixSwimmer swimmer, double alpha, double uncertainty) {
+        // Must have m_ECAL_endcap_rmin <= r <= m_ECAL_endcap_rmax (within errors)
+        //double uncertainty = m_cutSeparation;
+        Hep3Vector intercept = swimmer.getPointAtDistance(alpha);
+        double r = Math.sqrt(intercept.x()*intercept.x() + intercept.y()*intercept.y());
+        boolean rInRange = (r >= m_ECAL_endcap_rmin-uncertainty && r <= m_ECAL_endcap_rmax+uncertainty);
+        return rInRange;
+    }
+}

lcsim/src/org/lcsim/recon/pfa/identifier
TrackHelixPlusHitExtrapolator.java added at 1.1
diff -N TrackHelixPlusHitExtrapolator.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TrackHelixPlusHitExtrapolator.java	6 Sep 2008 23:47:00 -0000	1.1
@@ -0,0 +1,113 @@
+package org.lcsim.recon.pfa.identifier;
+
+import java.util.*;
+import hep.physics.vec.*;
+
+import org.lcsim.event.TrackerHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.util.swim.HelixSwimmer;
+import org.lcsim.event.Track;
+
+public class TrackHelixPlusHitExtrapolator extends TrackHelixExtrapolator 
+{
+    public TrackHelixPlusHitExtrapolator() {
+	super();
+    }
+
+    protected TrackHelixPlusHitExtrapolator(TrackHelixPlusHitExtrapolator old) {
+	super(old);
+    }
+
+    public void process(EventHeader event) {
+	super.process(event);
+    }
+
+    public HelixExtrapolationResult performExtrapolation(Track tr) {
+	// Null track means we blank everything and return failure.
+	m_track = tr;
+	if (tr == null) {
+	    m_intercept = null;
+	    m_swimmer = null;
+	    m_alphaIntercept = Double.NaN;
+	    return null;
+	}
+
+	// Start by swimming as per parent:
+	super.performExtrapolation(tr);
+	
+	// Now scan over tracker hits and find the one with the outermost Z:
+	List<TrackerHit> trackHits = tr.getTrackerHits();
+	if (trackHits.size() == 0) { throw new AssertionError("Track found with no track hits!"); }
+	TrackerHit trackHitWithLargestModZ = null;
+	Hep3Vector positionOfTrackHitWithLargestModZ = null;
+	for (TrackerHit trackHit : trackHits) {
+	    Hep3Vector pos = new BasicHep3Vector(trackHit.getPosition());
+	    if (trackHitWithLargestModZ==null) {
+		trackHitWithLargestModZ = trackHit;
+		positionOfTrackHitWithLargestModZ = pos;
+	    } else {
+		if (Math.abs(pos.z()) > Math.abs(positionOfTrackHitWithLargestModZ.z())) {
+		    trackHitWithLargestModZ = trackHit;
+		    positionOfTrackHitWithLargestModZ = pos;
+		}
+	    }
+	}
+
+	if (trackHitWithLargestModZ == null) {
+	    throw new AssertionError("Unable to determine outermost hit!");
+	} else {
+	    // Find the POCA to the hit with the old helix:
+	    double alpha = m_swimmer.getTrackLengthToPoint(positionOfTrackHitWithLargestModZ);
+	    Hep3Vector pointOfClosestApproachToTrackHit = m_swimmer.getPointAtLength(alpha);
+	    Hep3Vector momentumAtPOCA = m_swimmer.getMomentumAtLength(alpha);
+	    
+	    // Make a new helix swimmer:
+	    HelixSwimmer newHelix = new HelixSwimmer(m_fieldStrength[2]);
+	    newHelix.setTrack(momentumAtPOCA, pointOfClosestApproachToTrackHit, tr.getCharge());
+	    // Over-write old helix swimmer:
+	    m_swimmer = newHelix;
+
+	    // Try swimming to the barrel:
+	    double  alphaBarrel = swimToBarrel(m_swimmer);
+	    boolean validBarrel = false;
+	    // Try swimming to the endcap:
+	    double  alphaEndcap = swimToEndcap(m_swimmer);
+	    boolean validEndcap = false;
+
+	    // Get helix fit output
+	    m_alphaIntercept = Double.NaN; 
+	    if (isValidBarrelIntercept(m_swimmer, alphaBarrel, m_cutSeparation)) {
+		m_alphaIntercept = alphaBarrel;
+		validBarrel = true;
+	    } else if (isValidEndcapIntercept(m_swimmer, alphaEndcap, m_cutSeparation)) {
+		m_alphaIntercept = alphaEndcap;
+		validEndcap = true;
+	    }
+
+	    // Did we make a successful extrapolation?
+	    if ( Double.isNaN(m_alphaIntercept)) {
+		// No -- extrapolation failed
+		if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" failed to extrapolate: alpha is NaN"); }
+		return null;
+	    } else if ( !(validEndcap || validBarrel) ) {
+		// Invalid state
+		if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" failed to extrapolate: not a valid barrel or endcap point"); }
+		return null;
+	    } else if ( validEndcap && validBarrel ) {
+		// Invalid state
+		if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" failed to extrapolate: valid barrel AND endcap point"); }
+		throw new AssertionError("DEBUG: "+this.getClass().getName()+" failed to extrapolate: valid barrel AND endcap point");
+		//return null;
+	    } else {
+		// Extrapolation succeeded.
+		m_intercept = m_swimmer.getPointAtDistance(m_alphaIntercept);
+		m_barrelValid = validBarrel;
+		m_endcapValid = validEndcap;
+		if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" extrapolated OK."); }
+		// Output
+		HelixExtrapolationResult output = new HelixExtrapolationResult(new TrackHelixPlusHitExtrapolator(this));
+		return output;
+	    }
+	}
+    }
+}

lcsim/src/org/lcsim/recon/pfa/identifier
LocalHelixExtrapolationTrackClusterMatcher.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- LocalHelixExtrapolationTrackClusterMatcher.java	26 Mar 2008 20:11:08 -0000	1.2
+++ LocalHelixExtrapolationTrackClusterMatcher.java	6 Sep 2008 23:47:00 -0000	1.3
@@ -37,17 +37,16 @@
 public class LocalHelixExtrapolationTrackClusterMatcher extends Driver implements TrackClusterMatcher
 {
     /** Simple constructor. */
-    public LocalHelixExtrapolationTrackClusterMatcher() {
+    public LocalHelixExtrapolationTrackClusterMatcher(HelixExtrapolator extrap) {
 	super();
-	m_extrap= new LocalHelixExtrapolator();
+	m_extrap = extrap;
     }
 
     /** Constructor, specifying additional cut to apply. */
-    public LocalHelixExtrapolationTrackClusterMatcher(DecisionMakerPair<Track,Cluster> extraCut) { 
+    public LocalHelixExtrapolationTrackClusterMatcher(DecisionMakerPair<Track,Cluster> extraCut, HelixExtrapolator extrap) { 
 	super();
 	m_extraCut = extraCut;
-	m_extrap= new LocalHelixExtrapolator();
-	add(m_extrap);
+	m_extrap = extrap;
     }
 
     /** Another way to specify the additional cut. */
@@ -68,7 +67,11 @@
       */
     public Cluster matchTrackToCluster(Track tr, List<Cluster> clusters) {
 	if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" trying to match track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+" to a list of "+clusters.size()+" clusters."); }
-	Hep3Vector point = m_extrap.performExtrapolation(tr);
+	HelixExtrapolationResult result = m_extrap.performExtrapolation(tr);
+	Hep3Vector point = null;
+	if (result != null) {
+	    point = result.getInterceptPoint();
+	}
 	if (point != null) {
 	    // Extrapolated to ECAL OK.
 	    if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+": extrapolated track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+" to r="+(Math.sqrt(point.x()*point.x()+point.y()*point.y()))+", z="+point.z()); }
@@ -110,14 +113,14 @@
     public void setCutSeparation(double cutSeparation) { m_cutSeparation = cutSeparation; m_extrap.setCutSeparation(cutSeparation); }
     public void setCutFirstLayer(int cutFirstLayer) { m_cutFirstLayer = cutFirstLayer; }
 
-    public LocalHelixExtrapolator getExtrapolator() { return m_extrap; }
-    public void setExtrapolator(LocalHelixExtrapolator extrap) { m_extrap = extrap; }
+    public HelixExtrapolator getExtrapolator() { return m_extrap; }
+    public void setExtrapolator(HelixExtrapolator extrap) { m_extrap = extrap; }
 
     protected DecisionMakerPair<Track,Cluster> m_extraCut = null;
     protected double m_cutSeparation = 30.0; // 3cm
     protected int    m_cutFirstLayer = 5; // Cluster must have a hit in in layer 0,1,2,3, or 4.
     protected EventHeader m_event;
-    protected LocalHelixExtrapolator m_extrap = null;
+    protected HelixExtrapolator m_extrap = null;
 
     // Utility routines
     // ----------------

lcsim/src/org/lcsim/recon/pfa/identifier
LocalHelixExtrapolationTrackMIPClusterMatcher.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- LocalHelixExtrapolationTrackMIPClusterMatcher.java	26 Mar 2008 20:11:08 -0000	1.2
+++ LocalHelixExtrapolationTrackMIPClusterMatcher.java	6 Sep 2008 23:47:00 -0000	1.3
@@ -17,16 +17,18 @@
 
 public class LocalHelixExtrapolationTrackMIPClusterMatcher extends LocalHelixExtrapolationTrackClusterMatcher
 {
-    public LocalHelixExtrapolationTrackMIPClusterMatcher() {
-	super();
+    public LocalHelixExtrapolationTrackMIPClusterMatcher(HelixExtrapolator extrap) {
+	super(extrap);
     }
 
-    public LocalHelixExtrapolationTrackMIPClusterMatcher(DecisionMakerPair<Track,Cluster> extraCut) { 
-	super(extraCut);
+    public LocalHelixExtrapolationTrackMIPClusterMatcher(DecisionMakerPair<Track,Cluster> extraCut, HelixExtrapolator extrap) { 
+	super(extraCut, extrap);
     }
 
     public Cluster matchTrackToCluster(Track tr, List<Cluster> clusters) {
-	Hep3Vector point = m_extrap.performExtrapolation(tr);
+	HelixExtrapolationResult result = m_extrap.performExtrapolation(tr);
+	Hep3Vector point = null;
+	if (result != null) { point = result.getInterceptPoint(); }
 	if (point != null) {
 	    // Extrapolated to ECAL OK.
 	    // Now, what is the tangent at that point?

lcsim/src/org/lcsim/recon/pfa/identifier
LocalHelixExtrapolator.java 1.15 -> 1.16
diff -u -r1.15 -r1.16
--- LocalHelixExtrapolator.java	31 Aug 2008 18:48:13 -0000	1.15
+++ LocalHelixExtrapolator.java	6 Sep 2008 23:47:00 -0000	1.16
@@ -32,41 +32,8 @@
  *
  */
 
-public class LocalHelixExtrapolator extends Driver
+public class LocalHelixExtrapolator extends HelixExtrapolator
 {
-
-    protected boolean m_init = false;
-    protected double m_ECAL_barrel_zmin;
-    protected double m_HCAL_barrel_zmin;
-    protected double m_MCAL_barrel_zmin;
-    protected double m_ECAL_barrel_zmax;
-    protected double m_HCAL_barrel_zmax;
-    protected double m_MCAL_barrel_zmax;
-    protected double m_ECAL_barrel_r;
-    protected double m_HCAL_barrel_r;
-    protected double m_MCAL_barrel_r;
-    protected double m_ECAL_endcap_z;
-    protected double m_FCAL_endcap_z;
-    protected double m_HCAL_endcap_z;
-    protected double m_MCAL_endcap_z;
-    protected Vector<Double> m_ECAL_barrel_layering_r;
-    protected Vector<Double> m_HCAL_barrel_layering_r;
-    protected Vector<Double> m_MCAL_barrel_layering_r;
-    protected Vector<Double> m_ECAL_endcap_layering_z;
-    protected Vector<Double> m_FCAL_endcap_layering_z;
-    protected Vector<Double> m_HCAL_endcap_layering_z;
-    protected Vector<Double> m_MCAL_endcap_layering_z;
-    protected double m_ECAL_endcap_rmin;
-    protected double m_FCAL_endcap_rmin;
-    protected double m_HCAL_endcap_rmin;
-    protected double m_MCAL_endcap_rmin;
-    protected double m_ECAL_endcap_rmax;
-    protected double m_FCAL_endcap_rmax;
-    protected double m_HCAL_endcap_rmax;
-    protected double m_MCAL_endcap_rmax;
-    protected double[] m_fieldStrength;
-    boolean m_barrelValid = false;
-    boolean m_endcapValid = false;
     double m_trackParam_xc = 0.0;
     double m_trackParam_yc = 0.0;
     double m_trackParam_radius = 0.0;
@@ -77,107 +44,44 @@
     double m_track_phi0 = 0.0;
     double m_track_phi1 = 0.0;
     boolean m_track_dphi_negative = false;
-    EventHeader m_event = null;
-    int m_trackCharge = 0;
 
-    boolean _debug = false;
     boolean m_debugChargeFlip = false;
 
-    boolean m_useFCAL = false;
-    boolean m_interceptsFCAL = false;
+    // ONLY "performExtrapolation" is allowed to modify this!
+    private BasicHep3Vector m_lastInterceptPoint = null;
 
-    /** Allow use of FCAL. */
-    public void useFCAL(boolean use) {
-	m_useFCAL = use;
+    public LocalHelixExtrapolator() {
+	super();
     }
 
-    /** Process this event, storing geometry info if needed. */
-    public void process(EventHeader event) {
-	m_event = event;
-	initGeometry(event);
-    }
-
-    /** Initialize geometry. This is done automatically if the class is run as a driver. */
-    public void initGeometry(EventHeader event) {
-	Detector det = event.getDetector();
-	CylindricalCalorimeter emb = ((CylindricalCalorimeter) det.getSubdetectors().get("EMBarrel"));
-	CylindricalCalorimeter eme = ((CylindricalCalorimeter) det.getSubdetectors().get("EMEndcap"));
-	CylindricalCalorimeter hdb = ((CylindricalCalorimeter) det.getSubdetectors().get("HADBarrel"));
-	CylindricalCalorimeter hde = ((CylindricalCalorimeter) det.getSubdetectors().get("HADEndcap"));
-	CylindricalCalorimeter fwe = ((CylindricalCalorimeter) det.getSubdetectors().get("ForwardEMEndcap"));
-	CylindricalCalorimeter mub = ((CylindricalCalorimeter) det.getSubdetectors().get("MuonBarrel"));
-	CylindricalCalorimeter mue = ((CylindricalCalorimeter) det.getSubdetectors().get("MuonEndcap"));
-	m_ECAL_barrel_zmin = emb.getZMin();
-	m_HCAL_barrel_zmin = hdb.getZMin();
-	m_MCAL_barrel_zmin = mub.getZMin();
-	m_ECAL_barrel_zmax = emb.getZMax();
-	m_HCAL_barrel_zmax = hdb.getZMax();
-	m_MCAL_barrel_zmax = mub.getZMax();
-	m_ECAL_barrel_r = emb.getLayering().getDistanceToLayerSensorMid(0);
-	m_HCAL_barrel_r = hdb.getLayering().getDistanceToLayerSensorMid(0);
-	m_MCAL_barrel_r = mub.getLayering().getDistanceToLayerSensorMid(0);
-	m_ECAL_endcap_z = eme.getLayering().getDistanceToLayerSensorMid(0);
-	m_FCAL_endcap_z = fwe.getLayering().getDistanceToLayerSensorMid(0);
-	m_HCAL_endcap_z = hde.getLayering().getDistanceToLayerSensorMid(0);
-	m_MCAL_endcap_z = mue.getLayering().getDistanceToLayerSensorMid(0);
-	m_ECAL_endcap_rmin = eme.getInnerRadius();
-	m_FCAL_endcap_rmin = fwe.getInnerRadius();
-	m_HCAL_endcap_rmin = hde.getInnerRadius();
-	m_MCAL_endcap_rmin = mue.getInnerRadius();
-	m_ECAL_endcap_rmax = eme.getOuterRadius();
-	m_FCAL_endcap_rmax = fwe.getOuterRadius();
-	m_HCAL_endcap_rmax = hde.getOuterRadius();
-	m_MCAL_endcap_rmax = mue.getOuterRadius();
-	double[] zero = {0, 0, 0};
-	m_fieldStrength = det.getFieldMap().getField(zero);
-	m_ECAL_barrel_layering_r = new Vector<Double>();
-	for (int iLayer=0; iLayer<emb.getLayering().getLayerCount(); iLayer++) {
-	    double r = emb.getLayering().getDistanceToLayerSensorMid(iLayer);
-	    m_ECAL_barrel_layering_r.add(new Double(r));
-	}
-	m_ECAL_endcap_layering_z = new Vector<Double>();
-	for (int iLayer=0; iLayer<eme.getLayering().getLayerCount(); iLayer++) {
-	    double z = eme.getLayering().getDistanceToLayerSensorMid(iLayer);
-	    m_ECAL_endcap_layering_z.add(new Double(z));
-	}
-	m_FCAL_endcap_layering_z = new Vector<Double>();
-	for (int iLayer=0; iLayer<fwe.getLayering().getLayerCount(); iLayer++) {
-	    double z = fwe.getLayering().getDistanceToLayerSensorMid(iLayer);
-	    m_FCAL_endcap_layering_z.add(new Double(z));
-	}
-	m_HCAL_barrel_layering_r = new Vector<Double>();
-	for (int iLayer=0; iLayer<hdb.getLayering().getLayerCount(); iLayer++) {
-	    double r = hdb.getLayering().getDistanceToLayerSensorMid(iLayer);
-	    m_HCAL_barrel_layering_r.add(new Double(r));
-	}
-	m_HCAL_endcap_layering_z = new Vector<Double>();
-	for (int iLayer=0; iLayer<hde.getLayering().getLayerCount(); iLayer++) {
-	    double z = hde.getLayering().getDistanceToLayerSensorMid(iLayer);
-	    m_HCAL_endcap_layering_z.add(new Double(z));
-	}
-	m_MCAL_barrel_layering_r = new Vector<Double>();
-	for (int iLayer=0; iLayer<hdb.getLayering().getLayerCount(); iLayer++) {
-	    double r = hdb.getLayering().getDistanceToLayerSensorMid(iLayer);
-	    m_MCAL_barrel_layering_r.add(new Double(r));
-	}
-	m_MCAL_endcap_layering_z = new Vector<Double>();
-	for (int iLayer=0; iLayer<hde.getLayering().getLayerCount(); iLayer++) {
-	    double z = hde.getLayering().getDistanceToLayerSensorMid(iLayer);
-	    m_MCAL_endcap_layering_z.add(new Double(z));
+    protected LocalHelixExtrapolator(LocalHelixExtrapolator old) {
+	super(old);
+	m_trackParam_xc = old.m_trackParam_xc;
+	m_trackParam_yc = old.m_trackParam_yc;
+	m_trackParam_radius = old.m_trackParam_radius;
+	m_trackParam_dz_by_dphi = old.m_trackParam_dz_by_dphi;
+	m_trackPoint_z = old.m_trackPoint_z;
+	m_trackPoint_phi = old.m_trackPoint_phi;
+	m_track_z0 = old.m_track_z0;
+	m_track_phi0 = old.m_track_phi0;
+	m_track_phi1 = old.m_track_phi1;
+	m_track_dphi_negative = old.m_track_dphi_negative;
+	m_debugChargeFlip = old.m_debugChargeFlip;
+	if (old.m_lastInterceptPoint == null) {
+	    m_lastInterceptPoint = null;
+	} else {
+	    m_lastInterceptPoint = new BasicHep3Vector(old.m_lastInterceptPoint.x(), old.m_lastInterceptPoint.y(), old.m_lastInterceptPoint.z());
 	}
-	m_init = true;
     }
 
-    protected double m_cutSeparation = 30.0; // 3cm
-    public void setCutSeparation(double cutSeparation) { m_cutSeparation = cutSeparation; }
+    public void process(EventHeader event) {
+	super.process(event);
+    }
 
     // Utility routines
     // ----------------
 
-    // ONLY "performExtrapolation" is allowed to modify this!
-    private BasicHep3Vector m_lastInterceptPoint = null;
-
-    public BasicHep3Vector getLastInterceptPoint() {
+    protected Hep3Vector getInterceptPoint() {
 	if (m_lastInterceptPoint == null) {
 	    return null;
 	} else {
@@ -185,7 +89,13 @@
 	}
     }
 
-    public Hep3Vector performExtrapolation(Track tr) {
+    public HelixExtrapolationResult performExtrapolation(Track tr) {
+	m_track = tr;
+	if (tr == null) {
+	    // Null track -- blank everything and return failure
+	    m_trackParam_xc = m_trackParam_yc = m_trackParam_radius = m_trackParam_dz_by_dphi = m_trackPoint_z = m_trackPoint_phi = m_track_z0 = m_track_phi0 = m_track_phi1 = 0.0;
+	    return null;
+	}
 
 	// Sanity check -- check for a specific case where we try to
 	// extrapolate an unphysical track of class MultipleTrackTrack.
@@ -203,7 +113,7 @@
 	if (trackerHits.size() < 3) { 
 	    // Need at least 3 hits to make a helix.
 	    m_lastInterceptPoint = null;
-	    return m_lastInterceptPoint;
+	    return null;
 	}
 	// Hit 0 is the closest to the calorimeter (confusing!)
 	SimTrackerHit hit0 = null;
@@ -352,23 +262,26 @@
 	m_track_phi0 = phi0;
 	m_track_phi1 = phi1;
 	m_track_z0 = z0;
-	m_trackCharge = tr.getCharge();
 	if (m_endcapValid) {
 	    m_trackPoint_z = found_endcap_z;
 	    m_trackPoint_phi = found_endcap_phi;
 	    m_lastInterceptPoint = new BasicHep3Vector(found_endcap_x, found_endcap_y, found_endcap_z);
-	    return m_lastInterceptPoint;
+	    HelixExtrapolationResult output = new HelixExtrapolationResult(new LocalHelixExtrapolator(this));
+	    if (output.getInterceptPoint() == null) { throw new AssertionError("Successful extrapolation, but intercept point is null!"); }
+	    return output;
 	}
 	if (m_barrelValid) {
 	    m_trackPoint_z = found_barrel_z;
 	    m_trackPoint_phi = found_barrel_phi;
 	    m_lastInterceptPoint = new BasicHep3Vector(found_barrel_x, found_barrel_y, found_barrel_z);
-	    return m_lastInterceptPoint;
+	    HelixExtrapolationResult output = new HelixExtrapolationResult(new LocalHelixExtrapolator(this));
+	    if (output.getInterceptPoint() == null) { throw new AssertionError("Successful extrapolation, but intercept point is null!"); }
+	    return output;
 	}
 
 	// No solution
 	m_lastInterceptPoint = null;
-	return m_lastInterceptPoint;
+	return null;
     }
 
     private Collection<SimTrackerHit> findHits(Track tr) {
@@ -394,70 +307,10 @@
 	return hitsMatched;
     }
 
-    public Long extendToECALLayerAndFindCell(int layer) {
-	Hep3Vector point = extendToECALLayer(layer);
-	IDDecoder id = null;
-	if (m_barrelValid) {
-	    id = m_event.getDetector().getDecoder("EcalBarrHits");
-	    if (id == null) { throw new AssertionError("Failed to find barrel ID"); }
-	} else if (m_endcapValid) {
-	    id = m_event.getDetector().getDecoder("EcalEndcapHits");
-	    if (id == null) { throw new AssertionError("Failed to find endcap ID"); }
-	}
-	if (id != null && point != null) {
-	    long cell = id.findCellContainingXYZ(point);
-	    id.setID(cell);
-	    Hep3Vector cellCenter = id.getPositionVector();
-	    return new Long(cell);
-	} else {
-	    return null;
-	}
-    }
-
-    public Long extendToHCALLayerAndFindCell(int layer) {
-	Hep3Vector point = extendToHCALLayer(layer);
-	IDDecoder id = null;
-	if (m_barrelValid) {
-	    id = m_event.getDetector().getDecoder("HcalBarrHits");
-	    if (id == null) { throw new AssertionError("Failed to find barrel ID"); }
-	} else if (m_endcapValid) {
-	    id = m_event.getDetector().getDecoder("HcalEndcapHits");
-	    if (id == null) { throw new AssertionError("Failed to find endcap ID"); }
-	}
-	if (id != null && point != null) {
-	    long cell = id.findCellContainingXYZ(point);
-	    id.setID(cell);
-	    Hep3Vector cellCenter = id.getPositionVector();
-	    return new Long(cell);
-	} else {
-	    return null;
-	}
-    }
-
-    public Long extendToMCALLayerAndFindCell(int layer) {
-	Hep3Vector point = extendToMCALLayer(layer);
-	IDDecoder id = null;
-	if (m_barrelValid) {
-	    id = m_event.getDetector().getDecoder("MuonBarrHits");
-	    if (id == null) { throw new AssertionError("Failed to find barrel ID"); }
-	} else if (m_endcapValid) {
-	    id = m_event.getDetector().getDecoder("MuonEndcapHits");
-	    if (id == null) { throw new AssertionError("Failed to find endcap ID"); }
-	}
-	if (id != null && point != null) {
-	    long cell = id.findCellContainingXYZ(point);
-	    id.setID(cell);
-	    Hep3Vector cellCenter = id.getPositionVector();
-	    return new Long(cell);
-	} else {
-	    return null;
-	}
-    }
-
     /** Assumes extrapolation has already been done. */
-    public Hep3Vector getTangent() {
+    protected Hep3Vector getTangent() {
 	double dphi = 0.01;
-	if (m_trackCharge > 0) { dphi = -0.01; }
+	if (m_track.getCharge() > 0.0) { dphi = -0.01; }
 	double dx = m_trackParam_radius * ( Math.cos(m_trackPoint_phi+dphi) - Math.cos(m_trackPoint_phi) );
 	double dy = m_trackParam_radius * ( Math.sin(m_trackPoint_phi+dphi) - Math.sin(m_trackPoint_phi) );
 	double dz = m_trackParam_dz_by_dphi * dphi;
@@ -465,7 +318,7 @@
 	return tangent;
     }
 
-    public Hep3Vector getTangent(Hep3Vector v, Track tr){
+    protected Hep3Vector getTangent(Hep3Vector v){
                                                                                                                               
         double x0 = v.x();
         double y0 = v.y();
@@ -473,8 +326,8 @@
 
         double phi0 = Math.atan2(y0-m_trackParam_yc, x0-m_trackParam_xc); // in the range -pi through +pi
 
-        if(_debug){
-            Hep3Vector P = new BasicHep3Vector(tr.getMomentum());
+        if(m_debug){
+            Hep3Vector P = new BasicHep3Vector(m_track.getMomentum());
             System.out.println("Center of radius= " + m_trackParam_xc + " " + m_trackParam_yc);                             
             System.out.println("This position= " + x0 + " " + y0 + " " + z0);
             System.out.println("phi at this point= " + phi0);
@@ -485,15 +338,15 @@
             System.out.println("R from p/0.3B=  " + r + " magnetic field= " + zField);
         }
 
-        if(m_track_dphi_negative && m_trackCharge < 0) {
-	    if (m_debugChargeFlip || _debug) {
+        if(m_track_dphi_negative && m_track.getCharge() < 0.0) {
+	    if (m_debugChargeFlip || m_debug) {
 		System.out.println("Error: rotational direction is wrong");
 		System.out.println("Charge is negative but it is determined to turn clockwise");
 	    }
 	}
                                                                                                                               
         double dphi = 0.01;
-	if (m_trackCharge > 0) { dphi = -0.01; }
+	if (m_track.getCharge() > 0.0) { dphi = -0.01; }
         double dx = m_trackParam_radius * ( Math.cos(phi0+dphi) - Math.cos(phi0) );
         double dy = m_trackParam_radius * ( Math.sin(phi0+dphi) - Math.sin(phi0) );
         double dz = m_trackParam_dz_by_dphi * dphi;
@@ -502,7 +355,7 @@
         return tangent;
     }
 
-    private Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax )
+    protected Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax )
     {
 	if (!m_barrelValid && !m_endcapValid) { return null; }
 
@@ -575,7 +428,7 @@
 	    }
     }
 
-    private Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax ) 
+    protected Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax ) 
     {
 	if (!m_barrelValid && !m_endcapValid) { return null; }
 
@@ -605,70 +458,5 @@
 	}
     }
 
-    /** Assumes extrapolation has already been done. */
-    public Hep3Vector extendToECALLayer(int layer) {
-	if (m_barrelValid) {
-	    return extendToECALBarrelLayer(layer);
-	} else if (m_endcapValid) {
-	    return extendToECALEndcapLayer(layer);
-	} else {
-	    // No solution
-	    return null;
-	}
-    }
-
-    /** Assumes extrapolation has already been done. */
-    public Hep3Vector extendToHCALLayer(int layer) {
-	if (m_barrelValid) {
-	    return extendToHCALBarrelLayer(layer);
-	} else if (m_endcapValid) {
-	    return extendToHCALEndcapLayer(layer);
-	} else {
-	    // No solution
-	    return null;
-	}
-    }
 
-    /** Assumes extrapolation has already been done. */
-    public Hep3Vector extendToMCALLayer(int layer) {
-	if (m_barrelValid) {
-	    return extendToMCALBarrelLayer(layer);
-	} else if (m_endcapValid) {
-	    return extendToMCALEndcapLayer(layer);
-	} else {
-	    // No solution
-	    return null;
-	}
-    }
-
-    /** Assumes extrapolation has already been done. */
-    public Hep3Vector extendToECALBarrelLayer(int layer) {
-	return extendToBarrelLayer(layer, m_ECAL_barrel_layering_r, m_ECAL_barrel_zmin, m_ECAL_barrel_zmax);
-    }
-    /** Assumes extrapolation has already been done. */
-    public Hep3Vector extendToECALEndcapLayer(int layer) {
-	if (m_useFCAL && m_interceptsFCAL) {
-	    Hep3Vector vec = extendToEndcapLayer(layer, m_FCAL_endcap_layering_z, m_FCAL_endcap_rmin, m_FCAL_endcap_rmax);
-	    if (vec != null) {
-		return vec;
-	    }
-	}
-	return extendToEndcapLayer(layer, m_ECAL_endcap_layering_z, m_ECAL_endcap_rmin, m_ECAL_endcap_rmax);
-    }
-    /** Assumes extrapolation has already been done. */
-    public Hep3Vector extendToHCALBarrelLayer(int layer) {
-	return extendToBarrelLayer(layer, m_HCAL_barrel_layering_r, m_HCAL_barrel_zmin, m_HCAL_barrel_zmax);
-    }
-    /** Assumes extrapolation has already been done. */
-    public Hep3Vector extendToHCALEndcapLayer(int layer) {
-	return extendToEndcapLayer(layer, m_HCAL_endcap_layering_z, m_HCAL_endcap_rmin, m_HCAL_endcap_rmax);
-    }
-    /** Assumes extrapolation has already been done. */
-    public Hep3Vector extendToMCALBarrelLayer(int layer) {
-	return extendToBarrelLayer(layer, m_MCAL_barrel_layering_r, m_MCAL_barrel_zmin, m_MCAL_barrel_zmax);
-    }
-    /** Assumes extrapolation has already been done. */
-    public Hep3Vector extendToMCALEndcapLayer(int layer) {
-	return extendToEndcapLayer(layer, m_MCAL_endcap_layering_z, m_MCAL_endcap_rmin, m_MCAL_endcap_rmax);
-    }
 }
CVSspam 0.2.8