Print

Print


Author: [log in to unmask]
Date: Wed Jun 15 18:24:50 2016
New Revision: 4404

Log:
Added user directory. Added Hit Efficiency Driver.

Added:
    java/trunk/users/src/main/java/org/hps/users/mrsolt/
    java/trunk/users/src/main/java/org/hps/users/mrsolt/TrackHitEfficiency.java

Added: java/trunk/users/src/main/java/org/hps/users/mrsolt/TrackHitEfficiency.java
 =============================================================================
--- java/trunk/users/src/main/java/org/hps/users/mrsolt/TrackHitEfficiency.java	(added)
+++ java/trunk/users/src/main/java/org/hps/users/mrsolt/TrackHitEfficiency.java	Wed Jun 15 18:24:50 2016
@@ -0,0 +1,1132 @@
+/**
+ * Analysis driver to calculate hit efficiencies in the SVT
+ */
+/**
+ * @author mrsolt
+ *
+ */
+package org.hps.users.mrsolt;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogramFactory;
+import hep.aida.IPlotterFactory;
+import hep.aida.IPlotter;
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.ITree;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.converter.compact.subdetector.SvtStereoLayer;
+import org.lcsim.detector.converter.compact.subdetector.HpsTracker2;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.solids.Point3D;
+import org.lcsim.detector.solids.Polygon3D;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.HpsSiSensor;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiStrips;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+import org.hps.conditions.beam.BeamEnergy.BeamEnergyCollection;
+import org.hps.recon.tracking.TrackUtils;
+import org.hps.recon.tracking.TrackerHitUtils;
+
+public class TrackHitEfficiency extends Driver {
+
+
+    // Use JFreeChart as the default plotting backend
+    static { 
+        hep.aida.jfree.AnalysisFactory.register();
+    }
+
+    // Plotting
+    protected AIDA aida = AIDA.defaultInstance();
+    ITree tree; 
+    IHistogramFactory histogramFactory; 
+    IPlotterFactory plotterFactory = IAnalysisFactory.create().createPlotterFactory();
+    protected Map<String, IPlotter> plotters = new HashMap<String, IPlotter>(); 
+    private Map<String, IHistogram1D> trackMomentumPlots = new HashMap<String, IHistogram1D>(); 
+    private Map<String, IHistogram1D> trackPlots = new HashMap<String, IHistogram1D>();
+
+    //private Map<SiSensor, Map<Integer, Hep3Vector>> stripPositions = new HashMap<SiSensor, Map<Integer, Hep3Vector>>(); 
+    private List<HpsSiSensor> sensors = null;
+    private Map<Track, ReconstructedParticle> reconParticleMap = new HashMap<Track, ReconstructedParticle>();
+    private Map<Integer, List<SvtStereoLayer>> topStereoLayers = new HashMap<Integer, List<SvtStereoLayer>>();
+    private Map<Integer, List<SvtStereoLayer>> bottomStereoLayers = new HashMap<Integer, List<SvtStereoLayer>>();
+    
+    IHistogram1D trackMomentumPlots_top;
+    IHistogram1D trackMomentumPlots_bot;
+    IHistogram1D HitEfficiency_top;
+    IHistogram1D HitEfficiency_bot;
+    IHistogram1D HitEfficiencyError_top;
+    IHistogram1D HitEfficiencyError_bot;
+    IHistogram1D HitEfficiency_Momentum_top;
+    IHistogram1D HitEfficiency_Momentum_bot;
+    IHistogram1D HitEfficiencyError_Momentum_top;
+    IHistogram1D HitEfficiencyError_Momentum_bot;
+    IHistogram1D TrackXTop;
+    IHistogram1D TrackYTop;
+    IHistogram1D TrackXBot;
+    IHistogram1D TrackYBot;
+    Map<Integer, IHistogram1D> trackMomentum = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> trackMomentum_top = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> trackMomentum_bot = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> trackMomentum_accepted = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> trackMomentum_accepted_top = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> trackMomentum_accepted_bot = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> trackMomentum_final = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> trackMomentum_final_top = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> trackMomentum_final_bot = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram2D> HitEfficiencyPos_top = new HashMap<Integer,IHistogram2D>();
+    Map<Integer, IHistogram2D> HitEfficiencyPos_bot = new HashMap<Integer,IHistogram2D>();
+    Map<Integer, IHistogram2D> HitEfficiencyErrorPos_top = new HashMap<Integer,IHistogram2D>();
+    Map<Integer, IHistogram2D> HitEfficiencyErrorPos_bot = new HashMap<Integer,IHistogram2D>();
+    Map<Integer, IHistogram1D> HitPosition_top = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> HitPosition_bot = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> UnbiasedResidualX_top = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> UnbiasedResidualX_bot = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> UnbiasedResidualY_top = new HashMap<Integer,IHistogram1D>();
+    Map<Integer, IHistogram1D> UnbiasedResidualY_bot = new HashMap<Integer,IHistogram1D>();
+    
+    int num_lay = 6;
+    
+    /*double topXResidualOffset1 = -0.0259575; 
+    double topYResidualOffset1 = 0.00255140; 
+    double botXResidualOffset1 = -.00154694; 
+    double botYResidualOffset1 = -0.0103718; 
+    
+    double topXResidualCut1 = 0.438542;
+    double topYResidualCut1 = 0.167872;
+    double botXResidualCut1 = 0.434835;
+    double botYResidualCut1 = 0.169351;*/
+    
+    double[] topXResidualOffset = new double[num_lay];
+    double[] topYResidualOffset = new double[num_lay]; 
+    double[] botXResidualOffset = new double[num_lay]; 
+    double[] botYResidualOffset = new double[num_lay]; 
+    
+    double[] topXResidualCut = new double[num_lay];
+    double[] topYResidualCut = new double[num_lay];
+    double[] botXResidualCut = new double[num_lay];
+    double[] botYResidualCut = new double[num_lay];
+    
+    double topXResidualOffset1 = 0; 
+    double topYResidualOffset1 = 0; 
+    double botXResidualOffset1 = 0; 
+    double botYResidualOffset1 = 0; 
+    
+    double topXResidualCut1 = 3;
+    double topYResidualCut1 = 2;
+    double botXResidualCut1 = 3;
+    double botYResidualCut1 = 2;
+    
+    double topXResidualOffset2 = 0; 
+    double topYResidualOffset2 = 0; 
+    double botXResidualOffset2 = 0; 
+    double botYResidualOffset2 = 0; 
+    
+    double topXResidualCut2 = 2;
+    double topYResidualCut2 = 1;
+    double botXResidualCut2 = 2;
+    double botYResidualCut2 = 1;
+    
+    double topXResidualOffset3 = 0; 
+    double topYResidualOffset3 = 0; 
+    double botXResidualOffset3 = 0; 
+    double botYResidualOffset3 = 0; 
+    
+    double topXResidualCut3 = 2;
+    double topYResidualCut3 = 1;
+    double botXResidualCut3 = 2;
+    double botYResidualCut3 = 1;
+    
+    double topXResidualOffset4 = 0; 
+    double topYResidualOffset4 = 0; 
+    double botXResidualOffset4 = 0; 
+    double botYResidualOffset4 = 0; 
+    
+    double topXResidualCut4 = 2;
+    double topYResidualCut4 = 1;
+    double botXResidualCut4 = 2;
+    double botYResidualCut4 = 1;
+    
+    double topXResidualOffset5 = 0; 
+    double topYResidualOffset5 = 0; 
+    double botXResidualOffset5 = 0; 
+    double botYResidualOffset5 = 0; 
+    
+    double topXResidualCut5 = 2;
+    double topYResidualCut5 = 2;
+    double botXResidualCut5 = 2;
+    double botYResidualCut5 = 2;
+    
+    double topXResidualOffset6 = 0; 
+    double topYResidualOffset6 = 0; 
+    double botXResidualOffset6 = 0; 
+    double botYResidualOffset6 = 0; 
+    
+    double topXResidualCut6 = 6;
+    double topYResidualCut6 = 3;
+    double botXResidualCut6 = 6;
+    double botYResidualCut6 = 3;
+    
+    int nSigCut = 1;
+
+    TrackerHitUtils trackerHitUtils = new TrackerHitUtils();
+    
+    boolean debug = false;
+    boolean ecalClusterTrackMatch = false;
+    
+    // Plot flags
+    boolean enableMomentumPlots = true;
+    boolean enableChiSquaredPlots = true;
+    boolean enableTrackPositionPlots = true;
+    boolean maskBadChannels = false;
+    
+    double numberOfTopTracksTot = 0;
+    double numberOfBotTracksTot = 0;
+    double numberOfTopTracksWithHitOnMissingLayerTot = 0; 
+    double numberOfBotTracksWithHitOnMissingLayerTot = 0;
+    double[] topTracksPerMissingLayer = new double[5];
+    double[] topTracksWithHitOnMissingLayer = new double[5];
+    double[] bottomTracksPerMissingLayer = new double[5];
+    double[] bottomTracksWithHitOnMissingLayer = new double[5];
+
+    int nBinx = 110;
+    int nBiny = 120;
+    int nP = 20;
+    int[] numberOfTopTracks = new int[num_lay];
+    int[] numberOfBotTracks = new int[num_lay];
+    int[] numberOfTopTracksWithHitOnMissingLayer = new int[num_lay];
+    int[] numberOfBotTracksWithHitOnMissingLayer = new int[num_lay];
+    double[] hitEfficiencyTop = new double[num_lay];
+    double[] hitEfficiencyBot = new double[num_lay];
+    double[] errorTop = new double[num_lay];
+    double[] errorBot = new double[num_lay];
+    int[][][] numberOfTopTracksPos = new int[num_lay][nBinx][nBiny];
+    int[][][] numberOfBotTracksPos = new int[num_lay][nBinx][nBiny];
+    int[][][] numberOfTopTracksWithHitOnMissingLayerPos = new int[num_lay][nBinx][nBiny];
+    int[][][] numberOfBotTracksWithHitOnMissingLayerPos = new int[num_lay][nBinx][nBiny];
+    double[][][] hitEfficiencyTopPos = new double[num_lay][nBinx][nBiny];
+    double[][][] hitEfficiencyBotPos = new double[num_lay][nBinx][nBiny];
+    double[][][] hitEfficiencyErrorTopPos = new double[num_lay][nBinx][nBiny];
+    double[][][] hitEfficiencyErrorBotPos = new double[num_lay][nBinx][nBiny];
+    int[] numberOfTopTracksMomentum = new int[nP];
+    int[] numberOfBotTracksMomentum = new int[nP];
+    int[] numberOfTopTracksWithHitOnMissingLayerMomentum = new int[nP];
+    int[] numberOfBotTracksWithHitOnMissingLayerMomentum = new int[nP];
+    double[] hitEfficiencyMomentumTop = new double[nP];
+    double[] hitEfficiencyMomentumBot = new double[nP];
+    double[] hitEfficiencyErrorMomentumTop = new double[nP];
+    double[] hitEfficiencyErrorMomentumBot = new double[nP];
+    
+    double lowerLimX = -100;
+    double upperLimX = 120;
+    double lowerLimY = -50;
+    double upperLimY = 70;
+    double lowerLimP;
+    double upperLimP;
+   
+    double angle = -0.035;
+    double xComp = Math.sin(angle);
+    double yComp = Math.cos(angle);
+    double zComp = 0.0;
+    Hep3Vector unitNormal = new BasicHep3Vector(xComp,yComp,zComp);
+    
+    Hep3Vector zPointonPlaneLay1Top = new BasicHep3Vector(0,92.09,0);
+    Hep3Vector zPointonPlaneLay2Top = new BasicHep3Vector(0,192.1,0);
+    Hep3Vector zPointonPlaneLay3Top = new BasicHep3Vector(0,292.2,0);
+    Hep3Vector zPointonPlaneLay4Top = new BasicHep3Vector(0,492.4,0);
+    Hep3Vector zPointonPlaneLay5Top = new BasicHep3Vector(0,692.7,0);
+    Hep3Vector zPointonPlaneLay6Top = new BasicHep3Vector(0,893.2,0);
+    Hep3Vector[] zPointonPlaneTop = new Hep3Vector[num_lay];
+    
+    Hep3Vector zPointonPlaneLay1Bot = new BasicHep3Vector(0,107.7,0);
+    Hep3Vector zPointonPlaneLay2Bot = new BasicHep3Vector(0,207.9,0);
+    Hep3Vector zPointonPlaneLay3Bot = new BasicHep3Vector(0,308.8,0);
+    Hep3Vector zPointonPlaneLay4Bot = new BasicHep3Vector(0,508.4,0);
+    Hep3Vector zPointonPlaneLay5Bot = new BasicHep3Vector(0,708.7,0);
+    Hep3Vector zPointonPlaneLay6Bot = new BasicHep3Vector(0,909.0,0);
+    Hep3Vector[] zPointonPlaneBot = new Hep3Vector[num_lay];
+    
+    Hep3Vector trackPos = null;
+    Hep3Vector frontTrackPos = null;
+    Hep3Vector rearTrackPos = null;
+    
+    // Collections
+    private String fsParticlesCollectionName = "FinalStateParticles";
+    private String stereoHitCollectionName = "HelicalTrackHits";
+    private String trackCollectionName = "MatchedTracks";
+   
+    // Constants
+    public static final double SENSOR_LENGTH = 98.33; // mm
+    public static final double SENSOR_WIDTH = 38.3399; // mm
+    private static final String SUBDETECTOR_NAME = "Tracker";
+
+    // By default, require that all tracks have 5 hits
+    int hitsOnTrack = 5;
+
+    /**
+     * Default Constructor
+     */
+    public TrackHitEfficiency(){
+    }
+
+    /**
+     *  Set the number of stereo hits associated with a track fit.
+     *
+     *  @param hitsOnTrack : Number of stereo hits associated with a track fit.
+     */
+    public void setHitsOnTrack(int hitsOnTrack) { 
+        this.hitsOnTrack = hitsOnTrack;
+    }
+    
+    /**
+     *  Enable/Disable debug 
+     */
+    public void  setDebug(boolean debug){
+        this.debug = debug;
+    }
+    
+    public void setTrackCollectionName(String trackCollectionName) {
+    	this.trackCollectionName = trackCollectionName; 
+    }
+    
+    /**
+     * Enable/Disable masking of bad channels
+     */
+    public void setMaskBadChannels(boolean maskBadChannels){
+        this.maskBadChannels = maskBadChannels; 
+    }
+    
+    double ebeam;
+    
+    public void detectorChanged(Detector detector){
+    	
+    	aida.tree().cd("/");
+    	tree = aida.tree();
+        //tree = IAnalysisFactory.create().createTreeFactory().create();
+        histogramFactory = IAnalysisFactory.create().createHistogramFactory(tree);
+    
+        
+        BeamEnergyCollection beamEnergyCollection = 
+                this.getConditionsManager().getCachedConditions(BeamEnergyCollection.class, "beam_energies").getCachedData();        
+        ebeam = beamEnergyCollection.get(0).getBeamEnergy();
+        lowerLimP = 0.2 * ebeam;
+        upperLimP = 1.3 * ebeam;
+        
+        zPointonPlaneTop[0] = zPointonPlaneLay1Top;
+        zPointonPlaneTop[1] = zPointonPlaneLay2Top;
+        zPointonPlaneTop[2] = zPointonPlaneLay3Top;
+        zPointonPlaneTop[3] = zPointonPlaneLay4Top;
+        zPointonPlaneTop[4] = zPointonPlaneLay5Top;
+        zPointonPlaneTop[5] = zPointonPlaneLay6Top;
+        
+        zPointonPlaneBot[0] = zPointonPlaneLay1Top;
+        zPointonPlaneBot[1] = zPointonPlaneLay2Top;
+        zPointonPlaneBot[2] = zPointonPlaneLay3Top;
+        zPointonPlaneBot[3] = zPointonPlaneLay4Top;
+        zPointonPlaneBot[4] = zPointonPlaneLay5Top;
+        zPointonPlaneBot[5] = zPointonPlaneLay6Top;
+        
+        topXResidualOffset[0] = topXResidualOffset1;
+        topYResidualOffset[0] = topYResidualOffset1; 
+        botXResidualOffset[0] = botXResidualOffset1; 
+        botYResidualOffset[0] = botYResidualOffset1; 
+        
+        topXResidualCut[0] = topXResidualCut1;
+        topYResidualCut[0] = topYResidualCut1;
+        botXResidualCut[0] = botXResidualCut1;
+        botYResidualCut[0] = botYResidualCut1;
+        
+        topXResidualOffset[1] = topXResidualOffset2;
+        topYResidualOffset[1] = topYResidualOffset2; 
+        botXResidualOffset[1] = botXResidualOffset2; 
+        botYResidualOffset[1] = botYResidualOffset2; 
+        
+        topXResidualCut[1] = topXResidualCut2;
+        topYResidualCut[1] = topYResidualCut2;
+        botXResidualCut[1] = botXResidualCut2;
+        botYResidualCut[1] = botYResidualCut2;
+        
+        topXResidualOffset[2] = topXResidualOffset3;
+        topYResidualOffset[2] = topYResidualOffset3; 
+        botXResidualOffset[2] = botXResidualOffset3; 
+        botYResidualOffset[2] = botYResidualOffset3; 
+        
+        topXResidualCut[2] = topXResidualCut3;
+        topYResidualCut[2] = topYResidualCut3;
+        botXResidualCut[2] = botXResidualCut3;
+        botYResidualCut[2] = botYResidualCut3;
+        
+        topXResidualOffset[3] = topXResidualOffset4;
+        topYResidualOffset[3] = topYResidualOffset4; 
+        botXResidualOffset[3] = botXResidualOffset4; 
+        botYResidualOffset[3] = botYResidualOffset4; 
+        
+        topXResidualCut[3] = topXResidualCut4;
+        topYResidualCut[3] = topYResidualCut4;
+        botXResidualCut[3] = botXResidualCut4;
+        botYResidualCut[3] = botYResidualCut4;
+        
+        topXResidualOffset[4] = topXResidualOffset5;
+        topYResidualOffset[4] = topYResidualOffset5; 
+        botXResidualOffset[4] = botXResidualOffset5; 
+        botYResidualOffset[4] = botYResidualOffset5; 
+        
+        topXResidualCut[4] = topXResidualCut5;
+        topYResidualCut[4] = topYResidualCut5;
+        botXResidualCut[4] = botXResidualCut5;
+        botYResidualCut[4] = botYResidualCut5;
+        
+        topXResidualOffset[5] = topXResidualOffset6;
+        topYResidualOffset[5] = topYResidualOffset6; 
+        botXResidualOffset[5] = botXResidualOffset6; 
+        botYResidualOffset[5] = botYResidualOffset6; 
+        
+        topXResidualCut[5] = topXResidualCut6;
+        topYResidualCut[5] = topYResidualCut6;
+        botXResidualCut[5] = botXResidualCut6;
+        botYResidualCut[5] = botYResidualCut6;
+        
+        
+        // Get the HpsSiSensor objects from the tracker detector element
+        sensors = detector.getSubdetector(SUBDETECTOR_NAME)
+                          .getDetectorElement().findDescendants(HpsSiSensor.class);
+   
+        // If the detector element had no sensors associated with it, throw
+        // an exception
+        if (sensors.size() == 0) {
+            throw new RuntimeException("No sensors were found in this detector.");
+        }
+
+        // Get the stereo layers from the geometry and build the stereo
+        // layer maps
+        List<SvtStereoLayer> stereoLayers 
+            = ((HpsTracker2) detector.getSubdetector(SUBDETECTOR_NAME).getDetectorElement()).getStereoPairs();
+        for (SvtStereoLayer stereoLayer : stereoLayers) { 
+            if (stereoLayer.getAxialSensor().isTopLayer()) {
+                //System.out.println("Adding stereo layer " + stereoLayer.getLayerNumber());
+                if (!topStereoLayers.containsKey(stereoLayer.getLayerNumber())) { 
+                    topStereoLayers.put(stereoLayer.getLayerNumber(), new ArrayList<SvtStereoLayer>());
+                } 
+                topStereoLayers.get(stereoLayer.getLayerNumber()).add(stereoLayer);
+            } else { 
+                if (!bottomStereoLayers.containsKey(stereoLayer.getLayerNumber())) { 
+                    bottomStereoLayers.put(stereoLayer.getLayerNumber(), new ArrayList<SvtStereoLayer>());
+                } 
+                bottomStereoLayers.get(stereoLayer.getLayerNumber()).add(stereoLayer);
+            }
+        }
+    
+        plotters.put("Event Information", plotterFactory.create("Event information"));
+        plotters.get("Event Information").createRegions(2, 3);
+
+        trackPlots.put("Number of tracks", histogramFactory.createHistogram1D("Number of tracks", 10, 0, 10));
+        plotters.get("Event Information").region(0).plot(trackPlots.get("Number of tracks"));
+
+        trackPlots.put("Unused Layer", histogramFactory.createHistogram1D("Unused Layer", 6, 1, 7));
+        plotters.get("Event Information").region(1).plot(trackPlots.get("Unused Layer"));
+        
+        trackPlots.put("Unbiased Residual x - Top", histogramFactory.createHistogram1D("Unbiased Residual x - Top", 100, -10, 10));
+        plotters.get("Event Information").region(2).plot(trackPlots.get("Unbiased Residual x - Top"));
+
+        trackPlots.put("Unbiased Residual x - Bottom", histogramFactory.createHistogram1D("Unbiased Residual x - Bottom", 100, -10, 10));
+        plotters.get("Event Information").region(3).plot(trackPlots.get("Unbiased Residual x - Bottom"));
+
+        trackPlots.put("Unbiased Residual y - Top", histogramFactory.createHistogram1D("Unbiased Residual y - Top", 100, -10, 10));
+        plotters.get("Event Information").region(4).plot(trackPlots.get("Unbiased Residual y - Top"));
+
+        trackPlots.put("Unbiased Residual y - Bottom", histogramFactory.createHistogram1D("Unbiased Residual y - Bottom", 100, -10, 10));
+        plotters.get("Event Information").region(5).plot(trackPlots.get("Unbiased Residual y - Bottom"));
+
+        plotters.put("Track Momentum", plotterFactory.create("Track Momentum"));
+        plotters.get("Track Momentum").createRegions(2, 2);
+
+        trackMomentumPlots.put("Track Momentum", histogramFactory.createHistogram1D("Track Momentum", 50, 0, ebeam*1.3));
+        plotters.get("Track Momentum").region(0).plot(trackMomentumPlots.get("Track Momentum"));
+           
+        trackMomentumPlots.put("Track Momentum - Tracks Within Acceptance",
+                histogramFactory.createHistogram1D("Track Momentum - Tracks Within Acceptance", 50, 0, ebeam*1.3));
+        plotters.get("Track Momentum").region(1)
+                                      .plot(trackMomentumPlots.get("Track Momentum - Tracks Within Acceptance"));
+
+        trackMomentumPlots.put("Track Momentum - All Layers Hit", 
+                histogramFactory.createHistogram1D("Track Momentum - All Layers Hit", 50, 0, ebeam*1.3));
+        plotters.get("Track Momentum").region(2)
+                                      .plot(trackMomentumPlots.get("Track Momentum - All Layers Hit"));
+        
+        trackMomentumPlots_top = aida.histogram1D("Track Momentum Top", 50, 0, ebeam*1.3);
+        trackMomentumPlots_bot = aida.histogram1D("Track Momentum Bot", 50, 0, ebeam*1.3);
+        
+        HitEfficiency_top = aida.histogram1D("Hit Efficiency Top", num_lay, 0, num_lay);
+        HitEfficiency_bot = aida.histogram1D("Hit Efficiency Bot", num_lay, 0, num_lay);
+        HitEfficiencyError_top = aida.histogram1D("Hit Efficiency Error Top", num_lay, 0, num_lay);
+        HitEfficiencyError_bot = aida.histogram1D("Hit Efficiency Error Bot", num_lay, 0, num_lay);
+        HitEfficiency_Momentum_top = aida.histogram1D("Hit Efficiency Momentum Top", nP, lowerLimP, upperLimP);
+        HitEfficiency_Momentum_bot = aida.histogram1D("Hit Efficiency Momentum Bot", nP, lowerLimP, upperLimP);
+        HitEfficiencyError_Momentum_top = aida.histogram1D("Hit Efficiency Error Momentum Top", nP, lowerLimP, upperLimP);
+        HitEfficiencyError_Momentum_bot = aida.histogram1D("Hit Efficiency Error Momentum Bot", nP, lowerLimP, upperLimP);
+        TrackXTop = aida.histogram1D("Extrapolated Track X Top", 50, lowerLimX, upperLimX);
+        TrackYTop = aida.histogram1D("Extrapolated Track Y Top", 50, lowerLimY, upperLimY);
+        TrackXBot = aida.histogram1D("Extrapolated Track X Bot", 50, lowerLimX, upperLimX);
+        TrackYBot = aida.histogram1D("Extrapolated Track Y Bot", 50, lowerLimY, upperLimY);
+        
+        for(int i = 0; i < num_lay; i++){
+        	trackMomentum.put((i+1),histogramFactory.createHistogram1D("Track Momentum Layer #" + (i+1), 50, 0, ebeam*1.3));
+        	trackMomentum_top.put((i+1),histogramFactory.createHistogram1D("Track Momentum Top Layer #" + (i+1), 50, 0, ebeam*1.3));
+        	trackMomentum_bot.put((i+1),histogramFactory.createHistogram1D("Track Momentum Bot Layer #" + (i+1), 50, 0, ebeam*1.3));
+        	trackMomentum_accepted.put((i+1),histogramFactory.createHistogram1D("Track Momentum Accepted Layer #" + (i+1), 50, 0, ebeam*1.3));
+        	trackMomentum_accepted_top.put((i+1),histogramFactory.createHistogram1D("Track Momentum Accepted Top Layer #" + (i+1), 50, 0, ebeam*1.3));
+        	trackMomentum_accepted_bot.put((i+1),histogramFactory.createHistogram1D("Track Momentum Accepted Bot Layer #" + (i+1), 50, 0, ebeam*1.3));
+        	trackMomentum_final.put((i+1),histogramFactory.createHistogram1D("Track Momentum Final Layer #" + (i+1), 50, 0, ebeam*1.3));
+        	trackMomentum_final_top.put((i+1),histogramFactory.createHistogram1D("Track Momentum Final Top Layer #" + (i+1), 50, 0, ebeam*1.3));
+        	trackMomentum_final_bot.put((i+1),histogramFactory.createHistogram1D("Track Momentum Final Bot Layer #" + (i+1), 50, 0, ebeam*1.3));
+        	HitEfficiencyPos_top.put((i+1),histogramFactory.createHistogram2D("Hit Efficiency for Hit Positions Top Layer #" + (i+1), nBinx, lowerLimX, upperLimX, nBiny, lowerLimY, upperLimY));
+        	HitEfficiencyPos_bot.put((i+1),histogramFactory.createHistogram2D("Hit Efficiency for Hit Positions Bot Layer #" + (i+1), nBinx, lowerLimX, upperLimX, nBiny, lowerLimY, upperLimY));
+        	HitEfficiencyErrorPos_top.put((i+1),histogramFactory.createHistogram2D("Hit Efficiency Error for Hit Positions Top Layer #" + (i+1), nBinx, lowerLimX, upperLimX, nBiny, lowerLimY, upperLimY));
+        	HitEfficiencyErrorPos_bot.put((i+1),histogramFactory.createHistogram2D("Hit Efficiency Error for Hit Positions Bot Layer #" + (i+1), nBinx, lowerLimX, upperLimX, nBiny, lowerLimY, upperLimY));
+        	HitPosition_top.put((i+1),histogramFactory.createHistogram1D("Hit Position Top Layer #" + (i+1), 1100, 0, 1100));
+        	HitPosition_bot.put((i+1),histogramFactory.createHistogram1D("Hit Position Bot Layer #" + (i+1), 1100, 0, 1100));
+        	UnbiasedResidualX_top.put((i+1),histogramFactory.createHistogram1D("Unbiased Residual X Top Layer #" + (i+1),100,-10,10));
+        	UnbiasedResidualX_bot.put((i+1),histogramFactory.createHistogram1D("Unbiased Residual X Bot Layer #" + (i+1),100,-10,10));
+        	UnbiasedResidualY_top.put((i+1),histogramFactory.createHistogram1D("Unbiased Residual Y Top Layer #" + (i+1),100,-10,10));
+        	UnbiasedResidualY_bot.put((i+1),histogramFactory.createHistogram1D("Unbiased Residual Y Bot Layer #" + (i+1),100,-10,10));
+        }
+        
+        for (IPlotter plotter : plotters.values()) { 
+            plotter.show();
+        }
+    }
+    @Override
+public void process(EventHeader event){
+		aida.tree().cd("/");
+        
+		System.out.println("Hello");
+		
+        // If the event does not have tracks, skip it
+        //if(!event.hasCollection(Track.class, trackCollectionName)) return;
+
+        // Get the list of tracks from the event
+        List<List<Track>> trackCollections = event.get(Track.class);
+        
+        // For now, only look at events with a single track
+        //if(tracks.size() != 1 ) return;
+       
+        // Get the list of final state particles from the event.  These will
+        // be used to obtain the track momentum.
+        List<ReconstructedParticle> fsParticles = event.get(ReconstructedParticle.class, fsParticlesCollectionName);
+      
+        //this.mapReconstructedParticlesToTracks(tracks, fsParticles);
+        
+        //trackPlots.get("Number of tracks").fill(tracks.size());
+        
+        //  Get all of the stereo hits in the event
+        List<TrackerHit> stereoHits = event.get(TrackerHit.class, stereoHitCollectionName);
+        
+        // Get the list of Ecal clusters from the event
+        //List<Cluster> ecalClusters = event.get(Cluster.class, ecalClustersCollectionName);
+
+        for (List<Track> tracks : trackCollections) {
+        	for(Track track : tracks){
+        		// Check that the track has the required number of hits.  The number of hits
+        		// required to make a track is set in the tracking strategy.
+        		if(track.getTrackerHits().size() != this.hitsOnTrack){
+        			System.out.println("This track doesn't have the required number of hits.");
+        			continue;
+        		}          
+        		HpsSiSensor trackSensor = (HpsSiSensor) ((RawTrackerHit)track.getTrackerHits().get(0).getRawHits().get(0)).getDetectorElement();
+        		// Calculate the momentum of the track
+        		HelicalTrackFit hlc_trk_fit = TrackUtils.getHTF(track.getTrackStates().get(0));
+        		
+        		//double p = this.getReconstructedParticle(track).getMomentum().magnitude();
+        		double B_field = Math.abs(TrackUtils.getBField(event.getDetector()).y());
+
+                double p = hlc_trk_fit.p(B_field);
+                
+        		trackMomentumPlots.get("Track Momentum").fill(p);
+        		if (trackSensor.isTopLayer()) {
+        			trackMomentumPlots_top.fill(p);
+        		} else { 
+        			trackMomentumPlots_bot.fill(p);
+        		}
+        		// Find which of the layers isn't being used in the track fit
+        		int unusedLayer = this.getUnusedSvtLayer(track.getTrackerHits());
+            
+        		trackPlots.get("Unused Layer").fill(unusedLayer);
+        		trackMomentum.get(unusedLayer).fill(p);
+        		if (trackSensor.isTopLayer()) {   			
+        			trackMomentum_top.get(unusedLayer).fill(p);
+        		} else{
+        			trackMomentum_bot.get(unusedLayer).fill(p);
+        		}
+        		if(!isWithinAcceptance(track, unusedLayer)) continue;
+        		
+        		//int nTop = 0;
+        		//int nBot = 0;
+        		//for (TrackerHit stereoHit : stereoHits) {
+        			//HpsSiSensor hitSensor = (HpsSiSensor) ((RawTrackerHit) stereoHit.getRawHits().get(0)).getDetectorElement();
+      	          
+        			//if ((trackSensor.isTopLayer() && hitSensor.isBottomLayer()) 
+        					//|| (trackSensor.isBottomLayer() && hitSensor.isTopLayer())) continue;
+        			
+        			//int layer = (hitSensor.getLayerNumber() + 1)/2;
+               	 	
+               	 	//if (unusedLayer != layer) continue; 
+        			
+        			//Hep3Vector stereoHitPosition = new BasicHep3Vector(stereoHit.getPosition());
+           	 		//Hep3Vector trackPosition = TrackUtils.extrapolateTrack(track, stereoHitPosition.z());
+           	 	//Hep3Vector trackPositionExtrap = TrackUtils.getHelixPlaneIntercept(hlc_trk_fit,unitNormal,zPointonPlane[unusedLayer-1],B_field);
+           	 	//TrackX.fill(trackPositionExtrap.x());
+           	 	//TrackY.fill(trackPositionExtrap.y());
+           	 	trackMomentum_accepted.get(unusedLayer).fill(p);
+           	 	if (trackSensor.isTopLayer()) {
+           	 			//if (nTop > 0){;
+           	 				//continue;
+           	 			//}
+           	 		//Hep3Vector trackPositionExtrap = TrackUtils.getHelixPlaneIntercept(hlc_trk_fit,unitNormal,zPointonPlaneTop[unusedLayer-1],B_field);
+           	 		//TrackXTop.fill(trackPositionExtrap.x());
+           	 		//TrackYTop.fill(trackPositionExtrap.y());
+           	 		trackMomentum_accepted_top.get(unusedLayer).fill(p);
+           	 		numberOfTopTracks[unusedLayer-1]++;
+           	 		for(int i = 0; i<nP;i++){
+           	 			double mP = (upperLimP - lowerLimP)/((double) nP);
+           	 			double lowerP = mP * i + lowerLimP;
+           	 			double upperP = lowerP + mP;
+           	 			if(lowerP < p && p < upperP){
+           	 				numberOfTopTracksMomentum[i]++;
+           	 			}
+           	 		}
+           	 		for(int i = 0; i<nBinx; i++){
+           	 			double mX = (upperLimX - lowerLimX)/((double) nBinx);
+           	 			double lowerX = mX * i + lowerLimX;
+           	 			double upperX = lowerX + mX;
+           	 			/*if(lowerX < trackPositionExtrap.x() && trackPositionExtrap.x() < upperX){
+           	 				for(int j = 0; j<nBiny; j++){
+           	 					double mY = (upperLimY - lowerLimY)/((double) nBiny);
+           	 					double lowerY = mY * j + lowerLimY;
+           	 					double upperY = lowerY + mY;
+           	 					if(lowerY < trackPositionExtrap.y() && trackPositionExtrap.y() < upperY){
+           	 						numberOfTopTracksPos[unusedLayer-1][i][j]++;
+           	 					}     
+           	 				}
+           	 			}*/          	 			
+           	 		}
+           	 		//nTop++;
+           	 	} else{
+           	 			//if (nBot > 0){;
+           	 			//continue;
+           	 			//}
+           	 		//Hep3Vector trackPositionExtrap = TrackUtils.getHelixPlaneIntercept(hlc_trk_fit,unitNormal,zPointonPlaneBot[unusedLayer-1],B_field);
+           	 		//TrackXBot.fill(trackPositionExtrap.x());
+           	 		//TrackYBot.fill(trackPositionExtrap.y());
+           	 		trackMomentum_accepted_bot.get(unusedLayer).fill(p);
+           	 		numberOfBotTracks[unusedLayer-1]++;
+           	 		for(int i = 0; i<nP;i++){
+           	 			double mP = (upperLimP - lowerLimP)/((double) nP);
+           	 			double lowerP = mP * i + lowerLimP;
+           	 			double upperP = lowerP + mP;
+           	 			if(lowerP < p && p < upperP){
+           	 				numberOfBotTracksMomentum[i]++;
+           	 			}
+           	 		}
+           	 		for(int i = 0; i<nBinx; i++){
+           	 			double mX = (upperLimX - lowerLimX)/((double) nBinx);
+           	 			double lowerX = mX * i + lowerLimX;
+           	 			double upperX = lowerX + mX;
+           	 			/*if(lowerX < trackPositionExtrap.x() && trackPositionExtrap.x() < upperX){
+           	 				for(int j = 0; j<nBiny; j++){
+           	 					double mY = (upperLimY - lowerLimY)/((double) nBiny);
+           	 					double lowerY = mY * j + lowerLimY;
+           	 					double upperY = lowerY + mY;
+           	 					if(lowerY < trackPositionExtrap.y() && trackPositionExtrap.y() < upperY){
+           	 						numberOfBotTracksPos[unusedLayer-1][i][j]++;
+           	 						//}     
+           	 				}          	 			
+           	 			}
+           	 		}*/
+           	 			//nBot++;
+           	 	}
+        	}
+        		int countTop = 0;
+        		int countBot = 0;
+        		for (TrackerHit stereoHit : stereoHits) {
+        			HpsSiSensor hitSensor = (HpsSiSensor) ((RawTrackerHit) stereoHit.getRawHits().get(0)).getDetectorElement();
+            	          
+        			if ((trackSensor.isTopLayer() && hitSensor.isBottomLayer()) 
+        					|| (trackSensor.isBottomLayer() && hitSensor.isTopLayer())) continue;
+        			
+        			// Retrieve the layer number by using the sensor
+               	 	int layer = (hitSensor.getLayerNumber() + 1)/2;
+               	 	
+               	 	if (unusedLayer != layer) continue;              	 	
+               	 	
+               	 	//System.out.println(count);
+               	 	
+               	 	//System.out.println("Track " + track + "   Collection " + trackCollections);
+                        
+               	 	Hep3Vector stereoHitPosition = new BasicHep3Vector(stereoHit.getPosition());
+               	 	Hep3Vector trackPosition = TrackUtils.extrapolateTrack(track, stereoHitPosition.z());
+               	 	double xResidual = trackPosition.x() - stereoHitPosition.x();
+               	 	double yResidual = trackPosition.y() - stereoHitPosition.y();
+             
+               	 	trackMomentum_final.get(unusedLayer).fill(p);                        
+               	 	if (hitSensor.isTopLayer()) {
+               	 		UnbiasedResidualX_top.get(unusedLayer).fill(xResidual);
+               	 		UnbiasedResidualY_top.get(unusedLayer).fill(yResidual);
+               	 		HitPosition_top.get(unusedLayer).fill(stereoHitPosition.z());
+               	 		trackPlots.get("Unbiased Residual x - Top").fill(xResidual);
+               	 		trackPlots.get("Unbiased Residual y - Top").fill(yResidual);
+               	 		//if (Math.abs(xResidual+this.topXResidualOffset) > nSigCut*this.topXResidualCut 
+               	 				//&& Math.abs(yResidual + this.topYResidualOffset) > nSigCut*this.topYResidualCut) continue;
+               	 		if (Math.abs(xResidual+topXResidualOffset[unusedLayer-1]) > nSigCut*topXResidualCut[unusedLayer-1] 
+       	 					|| Math.abs(yResidual + topYResidualOffset[unusedLayer-1]) > nSigCut*topYResidualCut[unusedLayer-1]) continue;
+               	 		if (countTop > 0){
+               	 			System.out.println("Top " + unusedLayer);
+               	 			continue;
+               	 		}
+               	 		trackMomentumPlots.get("Track Momentum - All Layers Hit").fill(p);
+               	 		trackMomentum_final_top.get(unusedLayer).fill(p);
+               	 		numberOfTopTracksWithHitOnMissingLayer[unusedLayer-1]++;
+               	 		for(int i = 0; i<nP;i++){
+               	 			double mP = (upperLimP - lowerLimP)/((double) nP);
+               	 			double lowerP = mP * i + lowerLimP;
+               	 			double upperP = lowerP + mP;
+               	 			if(lowerP < p && p < upperP){
+               	 				numberOfTopTracksWithHitOnMissingLayerMomentum[i]++;
+               	 			}
+               	 		}
+               	 		for(int i = 0; i<nBinx; i++){
+               	 			double mX = (upperLimX - lowerLimX)/((double) nBinx);
+               	 			double lowerX = mX * i + lowerLimX;
+               	 			double upperX = lowerX + mX;
+               	 			if(lowerX < trackPosition.x() && trackPosition.x() < upperX){
+               	 				for(int j = 0; j<nBiny; j++){
+               	 					double mY = (upperLimY - lowerLimY)/((double) nBiny);
+               	 					double lowerY = mY * j + lowerLimY;
+               	 					double upperY = lowerY + mY;
+               	 					if(lowerY < trackPosition.y() && trackPosition.y() < upperY){
+               	 						numberOfTopTracksWithHitOnMissingLayerPos[unusedLayer-1][i][j]++;
+               	 					}     
+               	 				}
+               	 			}             	 			
+               	 		}
+               	 		countTop++;               	                	 		
+               	 	} else {
+               	 		UnbiasedResidualX_bot.get(unusedLayer).fill(xResidual);
+               	 		UnbiasedResidualY_bot.get(unusedLayer).fill(yResidual);
+               	 		HitPosition_bot.get(unusedLayer).fill(stereoHitPosition.z());
+               	 		trackPlots.get("Unbiased Residual x - Bottom").fill(xResidual);
+               	 		trackPlots.get("Unbiased Residual y - Bottom").fill(yResidual);
+               	 		//if (Math.abs(xResidual+this.botXResidualOffset) > nSigCut*this.botXResidualCut 
+               	 				//&& Math.abs(yResidual + this.botYResidualOffset) > nSigCut*this.botYResidualCut) continue;
+               	 		if (Math.abs(xResidual+botXResidualOffset[unusedLayer-1]) > nSigCut*botXResidualCut[unusedLayer-1] 
+       	 					|| Math.abs(yResidual + botYResidualOffset[unusedLayer-1]) > nSigCut*botYResidualCut[unusedLayer-1]) continue;
+               	 		if (countBot > 0){
+           	 				System.out.println("Bot " + unusedLayer);
+           	 				continue;
+           	 			}
+               	 		trackMomentumPlots.get("Track Momentum - All Layers Hit").fill(p);
+               	 		trackMomentum_final_bot.get(unusedLayer).fill(p);
+               	 		numberOfBotTracksWithHitOnMissingLayer[unusedLayer-1]++;
+               	 		for(int i = 0; i<nP;i++){
+               	 			double mP = (upperLimP - lowerLimP)/((double) nP);
+               	 			double lowerP = mP * i + lowerLimP;
+               	 			double upperP = lowerP + mP;
+               	 			if(lowerP < p && p < upperP){
+               	 				numberOfBotTracksWithHitOnMissingLayerMomentum[i]++;
+               	 			}
+               	 		}
+               	 		for(int i = 0; i<nBinx; i++){
+               	 			double mX = (upperLimX - lowerLimX)/((double) nBinx);
+               	 			double lowerX = mX * i + lowerLimX;
+               	 			double upperX = lowerX + mX;
+               	 			if(lowerX < trackPosition.x() && trackPosition.x() < upperX){
+               	 				for(int j = 0; j<nBiny; j++){
+               	 					double mY = (upperLimY - lowerLimY)/((double) nBiny);
+               	 					double lowerY = mY * j + lowerLimY;
+               	 					double upperY = lowerY + mY;
+               	 					if(lowerY < trackPosition.y() && trackPosition.y() < upperY){
+               	 						numberOfBotTracksWithHitOnMissingLayerPos[unusedLayer-1][i][j]++;
+               	 					}     
+               	 				}
+               	 			}             	 			
+               	 		}
+               	 		countBot++;            	 	
+        			}
+        		}          
+        	}
+        }
+    }
+
+
+
+/**
+ *  Find which of the layers is not being used in the track fit
+ *
+ *  @param hits : List of stereo hits associated with a track
+ *  @return Layer not used in the track fit
+ */
+private int getUnusedSvtLayer(List<TrackerHit> stereoHits) {
+    
+    int[] svtLayer = new int[6];
+    
+    // Loop over all of the stereo hits associated with the track
+    for (TrackerHit stereoHit : stereoHits) {
+        
+        // Retrieve the sensor associated with one of the hits.  This will
+        // be used to retrieve the layer number
+        HpsSiSensor sensor = (HpsSiSensor) ((RawTrackerHit) stereoHit.getRawHits().get(0)).getDetectorElement();
+        
+        // Retrieve the layer number by using the sensor
+        int layer = (sensor.getLayerNumber() + 1)/2;
+       
+        // If a hit is associated with that layer, increment its 
+        // corresponding counter
+        svtLayer[layer - 1]++;
+    }
+    
+    // Loop through the layer counters and find which layer has not been
+    // incremented i.e. is unused by the track
+    for(int layer = 0; layer < svtLayer.length; layer++){
+        if(svtLayer[layer] == 0) { 
+            System.out.println("Layer number " + (layer+1) + " is not used");
+            return (layer + 1);
+        }
+    }
+  
+    // If all of the layers are being used, this track can't be used to 
+    // in the single hit efficiency calculation.  This means that something
+    // is wrong with the file
+    // TODO: This should probably throw an exception
+    return -1;
+}
+
+/**
+ * Extrapolate a track to a layer and check that it lies within its 
+ * acceptance.
+ *  
+ * @param track The track that will be extrapolated to the layer of interest
+ * @param layer The layer number to extrapolate to
+ * @return true if the track lies within the sensor acceptance, false otherwise
+ */
+private boolean isWithinAcceptance(Track track, int layer) {
+   
+    // TODO: Move this to a utility class 
+   
+    //System.out.println("Retrieving sensors for layer: " + layer);
+    
+    // Since TrackUtils.isTop/BottomTrack does not work when running off 
+    // a recon file, get the detector volume that a track is associated 
+    // with by using the sensor.  This assumes that a track is always
+    // composed by stereo hits that lie within a single detector volume
+    HpsSiSensor sensor = (HpsSiSensor) ((RawTrackerHit)track.getTrackerHits().get(0).getRawHits().get(0)).getDetectorElement();
+    
+    // Get the sensors associated with the layer that the track
+    // will be extrapolated to
+    List<SvtStereoLayer> stereoLayers = null;
+    
+    // if (TrackUtils.isTopTrack(track, track.getTrackerHits().size())) {
+    if (sensor.isTopLayer()) {
+        //System.out.println("Top track found.");
+        stereoLayers = this.topStereoLayers.get(layer);
+    //} else if (TrackUtils.isBottomTrack(track, track.getTrackerHits().size())) {
+    } else {
+        //System.out.println("Bottom track found.");
+        stereoLayers = this.bottomStereoLayers.get(layer);
+    }
+    
+    for (SvtStereoLayer stereoLayer : stereoLayers) { 
+        Hep3Vector axialSensorPosition = stereoLayer.getAxialSensor().getGeometry().getPosition();
+        Hep3Vector stereoSensorPosition = stereoLayer.getStereoSensor().getGeometry().getPosition();
+   
+        //System.out.println("Axial sensor position: " + axialSensorPosition.toString());
+        //System.out.println("Stereo sensor position: " + stereoSensorPosition.toString());
+        
+        Hep3Vector axialTrackPos = TrackUtils.extrapolateTrack(track,  axialSensorPosition.z());
+        Hep3Vector stereoTrackPos = TrackUtils.extrapolateTrack(track, stereoSensorPosition.z());
+  
+        //System.out.println("Track position at axial sensor: " + axialTrackPos.toString());
+        //System.out.println("Track position at stereo sensor: " + stereoTrackPos.toString());
+        
+        if(this.sensorContainsTrack(axialTrackPos, stereoLayer.getAxialSensor()) 
+                && this.sensorContainsTrack(stereoTrackPos, stereoLayer.getStereoSensor())){
+            //System.out.println("Track lies within layer acceptance.");
+            return true;
+        }
+    }
+    
+    return false;
+    
+    /*int layerNumber = (layer - 1)/2 + 1;
+    String title = "Track Position - Layer " + layerNumber + " - Tracks Within Acceptance";
+    //aida.histogram2D(title).fill(trackPos.y(), trackPos.z());
+    //aida.cloud2D(title).fill(frontTrackPos.y(), frontTrackPos.z()); */
+    
+}
+
+/**
+ * 
+ */
+public int findIntersectingChannel(Hep3Vector trackPosition, SiSensor sensor){
+    
+    //--- Check that the track doesn't pass through a region of bad channels ---//
+    //--------------------------------------------------------------------------//
+
+    //Rotate the track position to the JLab coordinate system
+    //this.printDebug("Track position in tracking frame: " + trackPosition.toString());
+    Hep3Vector trackPositionDet = VecOp.mult(VecOp.inverse(this.trackerHitUtils.detToTrackRotationMatrix()), trackPosition);
+    //this.printDebug("Track position in JLab frame " + trackPositionDet.toString());
+    // Rotate the track to the sensor coordinates
+    ITransform3D globalToLocal = sensor.getReadoutElectrodes(ChargeCarrier.HOLE).getGlobalToLocal();
+    globalToLocal.transform(trackPositionDet);
+    //this.printDebug("Track position in sensor electrodes frame " + trackPositionDet.toString());
+
+    // Find the closest channel to the track position
+    double deltaY = Double.MAX_VALUE;
+    int intersectingChannel = 0;
+    for(int physicalChannel= 0; physicalChannel < 639; physicalChannel++){ 
+        /*this.printDebug(SvtUtils.getInstance().getDescription(sensor) + " : Channel " + physicalChannel 
+                + " : Strip Position " + stripPositions.get(sensor).get(physicalChannel));
+        this.printDebug(SvtUtils.getInstance().getDescription(sensor) + ": Channel " + physicalChannel
+                + " : Delta Y: " + Math.abs(trackPositionDet.x() - stripPositions.get(sensor).get(physicalChannel).x()));*/
+        /*if(Math.abs(trackPositionDet.x() - stripPositions.get(sensor).get(physicalChannel).x()) < deltaY ){
+            deltaY = Math.abs(trackPositionDet.x() - stripPositions.get(sensor).get(physicalChannel).x()); 
+            intersectingChannel = physicalChannel;
+        }*/
+    }
+
+    
+    return intersectingChannel;
+}
+
+/**
+ *
+ */
+public boolean sensorContainsTrack(Hep3Vector trackPosition, HpsSiSensor sensor){
+
+    
+    if(maskBadChannels){
+        int intersectingChannel = this.findIntersectingChannel(trackPosition, sensor);
+        if(intersectingChannel == 0 || intersectingChannel == 638) return false;
+        
+        if(sensor.isBadChannel(intersectingChannel) 
+                || sensor.isBadChannel(intersectingChannel+1) 
+                || sensor.isBadChannel(intersectingChannel-1)){
+            //this.printDebug("Track intersects a bad channel!");
+            return false;
+        }
+    }
+    
+    ITransform3D localToGlobal = sensor.getGeometry().getLocalToGlobal();
+    
+    Hep3Vector sensorPos = sensor.getGeometry().getPosition();   
+    Box sensorSolid = (Box) sensor.getGeometry().getLogicalVolume().getSolid();
+    Polygon3D sensorFace = sensorSolid.getFacesNormalTo(new BasicHep3Vector(0, 0, 1)).get(0);
+    
+    List<Point3D> vertices = new ArrayList<Point3D>();
+    for(int index = 0; index < 4; index++){
+        vertices.add(new Point3D());
+    }
+    for(Point3D vertex : sensorFace.getVertices()){
+        if(vertex.y() < 0 && vertex.x() > 0){
+            localToGlobal.transform(vertex);
+            //vertices.set(0, new Point3D(vertex.y() + sensorPos.x(), vertex.x() + sensorPos.y(), vertex.z() + sensorPos.z()));
+            vertices.set(0, new Point3D(vertex.x(), vertex.y(), vertex.z()));
+           //System.out.println(this.getClass().getSimpleName() + ": Vertex 1 Position: " + vertices.get(0).toString());
+           //System.out.println(this.getClass().getSimpleName() + ": Transformed Vertex 1 Position: " + localToGlobal.transformed(vertex).toString());
+        } 
+        else if(vertex.y() > 0 && vertex.x() > 0){
+            localToGlobal.transform(vertex);
+            //vertices.set(1, new Point3D(vertex.y() + sensorPos.x(), vertex.x() + sensorPos.y(), vertex.z() + sensorPos.z()));
+            vertices.set(1, new Point3D(vertex.x(), vertex.y(), vertex.z()));
+            //System.out.println(this.getClass().getSimpleName() + ": Vertex 2 Position: " + vertices.get(1).toString());
+            //System.out.println(this.getClass().getSimpleName() + ": Transformed Vertex 2 Position: " + localToGlobal.transformed(vertex).toString());
+        } 
+        else if(vertex.y() > 0 && vertex.x() < 0){
+            localToGlobal.transform(vertex);
+            //vertices.set(2, new Point3D(vertex.y() + sensorPos.x(), vertex.x() + sensorPos.y(), vertex.z() + sensorPos.z()));
+            vertices.set(2, new Point3D(vertex.x(), vertex.y(), vertex.z()));
+            //System.out.println(this.getClass().getSimpleName() + ": Vertex 3 Position: " + vertices.get(2).toString());
+            //System.out.println(this.getClass().getSimpleName() + ": Transformed Vertex 3 Position: " + localToGlobal.transformed(vertex).toString());
+        }             
+        else if(vertex.y() < 0 && vertex.x() < 0){
+            localToGlobal.transform(vertex);
+            //vertices.set(3, new Point3D(vertex.y() + sensorPos.x(), vertex.x() + sensorPos.y(), vertex.z() + sensorPos.z()));
+            vertices.set(3, new Point3D(vertex.x(), vertex.y(), vertex.z()));
+            //System.out.println(this.getClass().getSimpleName() + ": Vertex 4 Position: " + vertices.get(3).toString());
+            //System.out.println(this.getClass().getSimpleName() + ": Transformed Vertex 4 Position: " + localToGlobal.transformed(vertex).toString());
+        } 
+    }
+
+    /*
+    double area1 = this.findTriangleArea(vertices.get(0).x(), vertices.get(0).y(), vertices.get(1).x(), vertices.get(1).y(), trackPosition.y(), trackPosition.z()); 
+    double area2 = this.findTriangleArea(vertices.get(1).x(), vertices.get(1).y(), vertices.get(2).x(), vertices.get(2).y(), trackPosition.y(), trackPosition.z()); 
+    double area3 = this.findTriangleArea(vertices.get(2).x(), vertices.get(2).y(), vertices.get(3).x(), vertices.get(3).y(), trackPosition.y(), trackPosition.z()); 
+    double area4 = this.findTriangleArea(vertices.get(3).x(), vertices.get(3).y(), vertices.get(0).x(), vertices.get(0).y(), trackPosition.y(), trackPosition.z()); 
+    */
+    
+    double area1 = this.findTriangleArea(vertices.get(0).x(), vertices.get(0).y(), vertices.get(1).x(), vertices.get(1).y(), trackPosition.x(), trackPosition.y()); 
+    double area2 = this.findTriangleArea(vertices.get(1).x(), vertices.get(1).y(), vertices.get(2).x(), vertices.get(2).y(), trackPosition.x(), trackPosition.y()); 
+    double area3 = this.findTriangleArea(vertices.get(2).x(), vertices.get(2).y(), vertices.get(3).x(), vertices.get(3).y(), trackPosition.x(), trackPosition.y()); 
+    double area4 = this.findTriangleArea(vertices.get(3).x(), vertices.get(3).y(), vertices.get(0).x(), vertices.get(0).y(), trackPosition.x(), trackPosition.y()); 
+
+    if((area1 > 0 && area2 > 0 && area3 > 0 && area4 > 0) || (area1 < 0 && area2 < 0 && area3 < 0 && area4 < 0)) return true;
+    return false;
+} 
+
+/**
+*
+*/
+public double findTriangleArea(double x0, double y0, double x1, double y1, double x2, double y2){
+  return .5*(x1*y2 - y1*x2 -x0*y2 + y0*x2 + x0*y1 - y0*x1); 
+}
+
+@Override
+public void endOfData(){
+    
+    /*for(int i = 0; i<num_lay; i++){
+    	hitEfficiencyTop[i] = numberOfTopTracksWithHitOnMissingLayer[i]/ (double) numberOfTopTracks[i];
+    	System.out.println(hitEfficiencyTop[i]);
+    	hitEfficiencyBot[i] = numberOfBotTracksWithHitOnMissingLayer[i]/(double) numberOfBotTracks[i];
+    	numberOfTopTracksTot = numberOfTopTracksTot + numberOfTopTracks[i];
+    	numberOfBotTracksTot = numberOfBotTracksTot + numberOfBotTracks[i];
+    	numberOfTopTracksWithHitOnMissingLayerTot = numberOfTopTracksWithHitOnMissingLayerTot + numberOfTopTracksWithHitOnMissingLayer[i];
+    	numberOfBotTracksWithHitOnMissingLayerTot = numberOfBotTracksWithHitOnMissingLayerTot + numberOfBotTracksWithHitOnMissingLayer[i];
+    	errorTop[i] = Math.sqrt(1/(double) numberOfTopTracks[i] + 1/(double) numberOfTopTracksWithHitOnMissingLayer[i]);
+    	errorBot[i] = Math.sqrt(1/(double) numberOfBotTracks[i] + 1/(double) numberOfBotTracksWithHitOnMissingLayer[i]);
+    	
+    	
+    	
+    	HitEfficiency_top.fill(i,hitEfficiencyTop[i]);
+    	HitEfficiency_bot.fill(i,hitEfficiencyBot[i]);
+    	HitEfficiencyError_top.fill(i,errorTop[i]);
+    	HitEfficiencyError_bot.fill(i,errorBot[i]);
+    	double mX = (upperLimX - lowerLimX)/((double) nBinx);
+    	double mY = (upperLimY - lowerLimY)/((double) nBiny);
+    	for(int j = 0; j<nBinx; j++){
+    		double x = mX * (j+0.5) + lowerLimX;
+    		for(int k = 0; k<nBiny; k++){
+    			double y = mY * (k+0.5) + lowerLimY;
+    			if(numberOfTopTracksWithHitOnMissingLayerPos[i][j][k] != 0){
+    				hitEfficiencyTopPos[i][j][k] = numberOfTopTracksWithHitOnMissingLayerPos[i][j][k]/(double) numberOfTopTracksPos[i][j][k];
+    				hitEfficiencyErrorTopPos[i][j][k] = Math.sqrt(1/(double) numberOfTopTracksPos[i][j][k]+1/(double) numberOfTopTracksWithHitOnMissingLayerPos[i][j][k]);
+    			}
+    			else{
+    				hitEfficiencyTopPos[i][j][k] = 0;
+    				hitEfficiencyErrorTopPos[i][j][k] = 0;
+    			}
+    			if(numberOfBotTracksWithHitOnMissingLayerPos[i][j][k] != 0){
+    				hitEfficiencyBotPos[i][j][k] = numberOfBotTracksWithHitOnMissingLayerPos[i][j][k]/(double) numberOfBotTracksPos[i][j][k];
+    				hitEfficiencyErrorBotPos[i][j][k] = Math.sqrt(1/(double) numberOfBotTracksPos[i][j][k]+1/(double) numberOfBotTracksWithHitOnMissingLayerPos[i][j][k]);
+    			}
+    			else{
+    				hitEfficiencyBotPos[i][j][k] = 0;
+    				hitEfficiencyErrorBotPos[i][j][k] = 0;
+    			}
+    			if(hitEfficiencyTopPos[i][j][k]>1){
+    				hitEfficiencyTopPos[i][j][k] = 1.0;
+    			}
+    			if(hitEfficiencyBotPos[i][j][k]>1){
+    				hitEfficiencyBotPos[i][j][k] = 1.0;
+    			}
+    			//System.out.println(i + "  " + x + "  " + y + "  " + numberOfTopTracksWithHitOnMissingLayerPos[i][j][k] + "  " + numberOfTopTracksPos[i][j][k] + "  " + hitEfficiencyTopPos[i][j][k]);
+    			HitEfficiencyPos_top.get(i+1).fill(x,y,hitEfficiencyTopPos[i][j][k]);
+    			HitEfficiencyPos_bot.get(i+1).fill(x,y,hitEfficiencyBotPos[i][j][k]);
+    			HitEfficiencyErrorPos_top.get(i+1).fill(x,y,hitEfficiencyErrorTopPos[i][j][k]);
+    			HitEfficiencyErrorPos_bot.get(i+1).fill(x,y,hitEfficiencyErrorBotPos[i][j][k]);
+    		}
+    	}
+    }
+    double mP = (upperLimP - lowerLimP)/((double) nP);
+    for(int i = 0; i<nP; i++){
+    	hitEfficiencyMomentumTop[i] = numberOfTopTracksWithHitOnMissingLayerMomentum[i]/(double) numberOfTopTracksMomentum[i];
+    	hitEfficiencyMomentumBot[i] = numberOfBotTracksWithHitOnMissingLayerMomentum[i]/(double) numberOfBotTracksMomentum[i];
+    	hitEfficiencyErrorMomentumTop[i] = Math.sqrt(1/(double) numberOfTopTracksMomentum[i] + 1/(double) numberOfTopTracksWithHitOnMissingLayerMomentum[i]);
+    	hitEfficiencyErrorMomentumBot[i] = Math.sqrt(1/(double) numberOfBotTracksMomentum[i] + 1/(double) numberOfBotTracksWithHitOnMissingLayerMomentum[i]);
+		double p = mP * (i+0.5) + lowerLimP;
+    	HitEfficiency_Momentum_top.fill(p,hitEfficiencyMomentumTop[i]);
+    	HitEfficiency_Momentum_bot.fill(p,hitEfficiencyMomentumBot[i]);
+    	HitEfficiencyError_Momentum_top.fill(p,hitEfficiencyErrorMomentumTop[i]);
+    	HitEfficiencyError_Momentum_bot.fill(p,hitEfficiencyErrorMomentumBot[i]);
+    }
+   System.out.println("%===================================================================%");
+   System.out.println("%======================  Hit Efficiencies ==========================%");
+   System.out.println("%===================================================================% \n%");
+   if(numberOfTopTracksTot > 0){
+	   for(int i = 0; i<num_lay; i++){
+		   System.out.println("Top Layer #"+(i+1)+ "   "+numberOfTopTracksWithHitOnMissingLayer[i] +" / "+ numberOfTopTracks[i]+ " = " +hitEfficiencyTop[i]);
+	   }
+       double topEfficiency = numberOfTopTracksWithHitOnMissingLayerTot/numberOfTopTracksTot;
+       System.out.println("% Top Hit Efficiency: " + numberOfTopTracksWithHitOnMissingLayerTot + "/" + 
+                           numberOfTopTracksTot + " = " + topEfficiency*100 + "%");
+       System.out.println("% Top Hit Efficiency Error: sigma poisson = " 
+                           + topEfficiency*Math.sqrt((1/numberOfTopTracksWithHitOnMissingLayerTot) + (1/numberOfTopTracksTot))*100 + "%");
+       System.out.println("% Top Hit Efficiency Error: sigma binomial = " 
+                           + (1/numberOfTopTracksTot)*Math.sqrt(numberOfTopTracksWithHitOnMissingLayerTot*(1-topEfficiency))*100 + "%");
+   }
+   if(numberOfBotTracksTot > 0){
+	   for(int i = 0; i<num_lay; i++){
+		   System.out.println("Bot Layer #"+(i+1)+ "   "+numberOfBotTracksWithHitOnMissingLayer[i] +" / "+ numberOfBotTracks[i]+ " = " +hitEfficiencyBot[i]); 
+	   }
+       double bottomEfficiency = numberOfBotTracksWithHitOnMissingLayerTot/numberOfBotTracksTot;
+       System.out.println("% Bottom Hit Efficiency: " + numberOfBotTracksWithHitOnMissingLayerTot + "/" 
+                           + numberOfBotTracksTot + " = " + bottomEfficiency*100 + "%");
+       System.out.println("% Bottom Hit Efficiency Error: sigma poisson= " 
+                           + bottomEfficiency*Math.sqrt((1/numberOfBotTracksWithHitOnMissingLayerTot) + (1/numberOfBotTracksTot))*100 + "%");
+       System.out.println("% Bottom Hit Efficiency Error: sigma binomial = " 
+                           + (1/numberOfBotTracksTot)*Math.sqrt(numberOfBotTracksWithHitOnMissingLayerTot*(1-bottomEfficiency))*100 + "%");
+   }
+/*        for(int index = 0; index < topTracksWithHitOnMissingLayer.length; index++){
+       if(topTracksPerMissingLayer[index] > 0)
+           System.out.println("% Top Layer " + (index+1) + ": " + (topTracksWithHitOnMissingLayer[index]/topTracksPerMissingLayer[index])*100 + "%");
+   }
+   for(int index = 0; index < bottomTracksWithHitOnMissingLayer.length; index++){
+       if(bottomTracksPerMissingLayer[index] > 0)
+           System.out.println("% Bottom Layer " + (index+1) + ": " + (bottomTracksWithHitOnMissingLayer[index]/bottomTracksPerMissingLayer[index])*100 + "%");
+   }*/
+   System.out.println("% \n%===================================================================%");
+}
+
+/**
+* 
+* @param tracks
+* @param particles
+*/
+private void mapReconstructedParticlesToTracks(List<Track> tracks, List<ReconstructedParticle> particles) {
+   
+  reconParticleMap.clear();
+  for (ReconstructedParticle particle : particles) {
+      for (Track track : tracks) {
+          if (!particle.getTracks().isEmpty() && particle.getTracks().get(0) == track) {
+              reconParticleMap.put(track, particle);
+          }
+      }
+  }
+}
+
+/**
+* 
+* @param track
+* @return
+*/
+private ReconstructedParticle getReconstructedParticle(Track track) {
+   return reconParticleMap.get(track);
+}
+
+}