Print

Print


Author: [log in to unmask]
Date: Wed Dec  2 21:01:47 2015
New Revision: 4006

Log:
Merge trunk changes into branch.

Added:
    java/branches/jeremy-dev/users/src/main/java/org/hps/users/meeg/TrackCleanupDriver.java
      - copied unchanged from r4005, java/trunk/users/src/main/java/org/hps/users/meeg/TrackCleanupDriver.java
Modified:
    java/branches/jeremy-dev/   (props changed)
    java/branches/jeremy-dev/analysis/src/main/java/org/hps/analysis/dataquality/TrackingMonitoring.java
    java/branches/jeremy-dev/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterEnergyCorrection.java
    java/branches/jeremy-dev/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java
    java/branches/jeremy-dev/recon/src/main/java/org/hps/recon/filtering/V0CandidateFilter.java
    java/branches/jeremy-dev/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java
    java/branches/jeremy-dev/run-database/src/main/java/org/hps/run/database/RunDatabaseBuilder.java
    java/branches/jeremy-dev/steering-files/src/main/resources/org/hps/steering/production/V0CandidateFilter.lcsim
    java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java
    java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/TrackData.java
    java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java

Modified: java/branches/jeremy-dev/analysis/src/main/java/org/hps/analysis/dataquality/TrackingMonitoring.java
 =============================================================================
--- java/branches/jeremy-dev/analysis/src/main/java/org/hps/analysis/dataquality/TrackingMonitoring.java	(original)
+++ java/branches/jeremy-dev/analysis/src/main/java/org/hps/analysis/dataquality/TrackingMonitoring.java	Wed Dec  2 21:01:47 2015
@@ -571,7 +571,7 @@
             IHistogram1D hitTimeResidual = getSensorPlot(plotDir + trackCollectionName + "/" + triggerType + "/" + timeresidDir + "hitTimeResidual_", getNiceSensorName(sensor));
             IFitResult result = fitGaussian(hitTimeResidual, fitter, "range=\"(-20.0,20.0)\"");
             if (result != null) {
-                LOGGER.info(String.format("%s\t%f\t%f\t%d\t%d", getNiceSensorName(sensor), result.fittedParameters()[1], result.fittedParameters()[2], sensor.getFebID(), sensor.getFebHybridID()));
+                System.out.format("%s\t%f\t%f\t%d\t%d\t%f\n", getNiceSensorName(sensor), result.fittedParameters()[1], result.fittedParameters()[2], sensor.getFebID(), sensor.getFebHybridID(), sensor.getT0Shift());
             }
         }
 

Modified: java/branches/jeremy-dev/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterEnergyCorrection.java
 =============================================================================
--- java/branches/jeremy-dev/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterEnergyCorrection.java	(original)
+++ java/branches/jeremy-dev/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterEnergyCorrection.java	Wed Dec  2 21:01:47 2015
@@ -1,7 +1,14 @@
 package org.hps.recon.ecal.cluster;
 
+import hep.physics.vec.Hep3Vector;
+
+import org.hps.detector.ecal.EcalCrystal;
+import org.hps.detector.ecal.HPSEcalDetectorElement;
+import org.jdom.DataConversionException;
+//import org.hps.recon.tracking.TrackUtils;
 import org.lcsim.event.Cluster;
 import org.lcsim.event.base.BaseCluster;
+import org.lcsim.geometry.subdetector.HPSEcal3;
 
 /**
  * This is the cluster energy correction requiring the particle id 
@@ -13,61 +20,129 @@
  * @author Jeremy McCormick <[log in to unmask]>
  */
 public final class ClusterEnergyCorrection {
-        
-    // Variables for electron energy corrections.
-    //Updated with recent monte carlo --7AUG15 HS. 
-    //Old values from 2014-2015 commented out to right.
-    static final double ELECTRON_ENERGY_A = 0.01004;//-0.0027;
-    static final double ELECTRON_ENERGY_B = -0.122;//-0.06;
-    static final double ELECTRON_ENERGY_C = 0.9646;//0.95;
-    
+	
+	// Variables for electron energy corrections.
+	static final double par0_em = 0.009051;
+    static final double par1_em[] = {35,-0.1322,-0.0005613,16.42,0.3431,-2.021,74.85,-0.3626};
+    static final double par2_em[] = {35, 0.9652, 0.003234, 18.06, 0.2592, 8.586, 75.08, -0.3771};
+
     // Variables for positron energy corrections.
-    static final double POSITRON_ENERGY_A = 0.00711;//-0.0096;
-    static final double POSITRON_ENERGY_B = -0.1154;//-0.042;
-    static final double POSITRON_ENERGY_C = 0.9614;//0.94;
+    static final double par0_ep = 0.01307;
+    static final double par1_ep[] = {35,-0.1415,-0.0008183,17.88,0.2886,-1.192,73.12,-0.3747};
+    static final double par2_ep[] = {35, 0.9733, 0.003713, 18.19, 0.2557, 8.342, 72.44, -0.3834};
     
     // Variables for photon energy corrections.
-    static final double PHOTON_ENERGY_A = 0.007595;//0.0015;
-    static final double PHOTON_ENERGY_B = -0.09766;//-0.047;
-    static final double PHOTON_ENERGY_C = 0.9512;//0.94;
+    static final double par0_p = 0.01604;
+    static final double par1_p[] = {35,-0.1268,-0.0008572,16.76,0.2784,-0.07232,72.88,-0.1685};
+    static final double par2_p[] = {35, 0.965, 0.004, 18.05, 0.24, 3.027, 74.93, -0.3221};
           
     /**
      * Calculate the corrected energy for the cluster.
      * @param cluster The input cluster.
      * @return The corrected energy.
      */
-    public static double calculateCorrectedEnergy(Cluster cluster) {
+    public static double calculateCorrectedEnergy(HPSEcal3 ecal, Cluster cluster) {
         double rawE = cluster.getEnergy();
-        return computeCorrectedEnergy(cluster.getParticleId(), rawE);
+        return computeCorrectedEnergy(ecal, cluster.getParticleId(), rawE, cluster.getPosition()[0], cluster.getPosition()[1]);
+    }
+    
+    /**
+     * Calculate the corrected energy for the cluster using track position at ecal.
+     * @param cluster The input cluster.
+     * @return The corrected energy.
+     */
+    public static double calculateCorrectedEnergy(HPSEcal3 ecal, Cluster cluster, double ypos) {
+        double rawE = cluster.getEnergy();
+        return computeCorrectedEnergy(ecal, cluster.getParticleId(), rawE, cluster.getPosition()[0], ypos);
     }
     
     /**
      * Calculate the corrected energy and set on the cluster.
      * @param cluster The input cluster.
      */
-    public static void setCorrectedEnergy(BaseCluster cluster) {
-        double correctedEnergy = calculateCorrectedEnergy(cluster);
+    public static void setCorrectedEnergy(HPSEcal3 ecal, BaseCluster cluster) {
+        double correctedEnergy = calculateCorrectedEnergy(ecal, cluster);
         cluster.setEnergy(correctedEnergy);
     }
-                            
+    
+    /**
+     * Calculate the corrected energy and set on the cluster.
+     * @param cluster The input cluster.
+     */
+    
+    public static void setCorrectedEnergy(HPSEcal3 ecal, BaseCluster cluster, double ypos) {
+        double correctedEnergy = calculateCorrectedEnergy(ecal, cluster, ypos);
+        cluster.setEnergy(correctedEnergy);
+    }
+                           
     /**
      * Calculates energy correction based on cluster raw energy and particle type as per 
      * <a href="https://misportal.jlab.org/mis/physics/hps_notes/index.cfm?note_year=2014">HPS Note 2014-001</a>
      * @param pdg Particle id as per PDG
      * @param rawEnergy Raw Energy of the cluster (sum of hits with shared hit distribution)
      * @return Corrected Energy
-     */    
-    private static double computeCorrectedEnergy(int pdg, double rawEnergy) {
-        switch(pdg) {
+     */  
+    
+    private static double computeCorrectedEnergy(HPSEcal3 ecal, int pdg, double rawEnergy, double xpos, double ypos) {
+        //distance to beam gap edge
+    	double r;
+    	//Get these values from the Ecal geometry:
+    	HPSEcalDetectorElement detElement = (HPSEcalDetectorElement) ecal.getDetectorElement();
+//        double BEAMGAPTOP = 22.3;//ecal.getNode().getChild("layout").getAttribute("beamgapTop").getDoubleValue();//mm
+        double BEAMGAPTOP=20.0;
+		try {
+			BEAMGAPTOP = ecal.getNode().getChild("layout").getAttribute("beamgapTop").getDoubleValue();
+		} catch (DataConversionException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}//mm
+        double BEAMGAPBOT=-20.0;
+		try {
+			BEAMGAPBOT = -ecal.getNode().getChild("layout").getAttribute("beamgapBottom").getDoubleValue();
+		} catch (DataConversionException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}//mm
+        double BEAMGAPTOPC = BEAMGAPTOP + 13.0;//mm
+        double BEAMGAPBOTC = BEAMGAPBOT - 13.0;//mm
+    	// x-coordinates of crystals on either side of row 1 cut out
+        EcalCrystal crystalM = detElement.getCrystal(-11, 1);
+        Hep3Vector posM = crystalM.getPositionFront();
+        EcalCrystal crystalP = detElement.getCrystal(-1, 1);
+        Hep3Vector posP = crystalP.getPositionFront();
+               
+    	if ((xpos<posM.x())||(xpos>posP.x())){
+        	if (ypos>0){
+        		r = Math.abs(ypos-BEAMGAPTOP);}    		
+        	else{
+        		r = Math.abs(ypos-BEAMGAPBOT);}
+        }
+    	// crystals above row 1 cut out
+        else {
+        	if (ypos>0){
+        		if (ypos>(par1_em[0]+BEAMGAPTOP)){
+            		r = Math.abs(ypos-BEAMGAPTOP);}
+        		else{
+            		r = Math.abs(ypos-BEAMGAPTOPC);}
+        	}
+        	else {
+        		if (ypos>(-par1_em[0]+BEAMGAPBOT)){
+        			r = Math.abs(ypos-BEAMGAPBOTC);}
+        		else {
+        			r = Math.abs(ypos-BEAMGAPBOT);}
+        	}
+        }
+    	   	
+    	switch(pdg) {
             case 11: 
                 // electron             
-                return computeCorrectedEnergy(rawEnergy, ELECTRON_ENERGY_A, ELECTRON_ENERGY_B, ELECTRON_ENERGY_C);
+                return computeCorrectedEnergy(r, rawEnergy, par0_em, par1_em, par2_em);
             case -11: 
                 // positron
-                return computeCorrectedEnergy(rawEnergy, POSITRON_ENERGY_A, POSITRON_ENERGY_B, POSITRON_ENERGY_C);
+                return computeCorrectedEnergy(r, rawEnergy, par0_ep, par1_ep, par2_ep);
             case 22: 
                 // photon
-                return computeCorrectedEnergy(rawEnergy, PHOTON_ENERGY_A, PHOTON_ENERGY_B, PHOTON_ENERGY_C);
+                return computeCorrectedEnergy(r, rawEnergy, par0_p, par1_p, par2_p);
             default: 
                 // unknown 
                 return rawEnergy;
@@ -82,8 +157,10 @@
      * @param A,B,C from fitting in note
      * @return Corrected Energy
      */   
-    private static double computeCorrectedEnergy(double rawEnergy, double varA, double varB, double varC){
-        double corrEnergy = rawEnergy / (varA / rawEnergy + varB / (Math.sqrt(rawEnergy)) + varC);
+    private static double computeCorrectedEnergy(double y, double rawEnergy, double varA, double varB[], double varC[]){
+        int ii = y<varB[0] ? 2 : 5;
+    	double corrEnergy = rawEnergy / (varA / rawEnergy + (varB[1]-varB[ii]*Math.exp(-(y-varB[ii+1])*varB[ii+2])) / (Math.sqrt(rawEnergy)) + 
+    			(varC[1]-varC[ii]*Math.exp(-(y-varC[ii+1])*varC[ii+2])));
         return corrEnergy;
     }                   
 }

Modified: java/branches/jeremy-dev/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java
 =============================================================================
--- java/branches/jeremy-dev/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java	(original)
+++ java/branches/jeremy-dev/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java	Wed Dec  2 21:01:47 2015
@@ -334,7 +334,7 @@
      * Apply HPS-specific energy and position corrections to a list of clusters in place.
      * @param clusters The list of clusters.
      */
-    public static void applyCorrections(List<Cluster> clusters) {
+    public static void applyCorrections(HPSEcal3 ecal, List<Cluster> clusters) {
                 
         // Loop over the clusters.
         for (Cluster cluster : clusters) {
@@ -347,16 +347,16 @@
                 ClusterPositionCorrection.setCorrectedPosition(baseCluster);
             
                 // Apply PID based energy correction.
-                ClusterEnergyCorrection.setCorrectedEnergy(baseCluster);
-            }
-        }
-    }
-    
-    /**
-     * Apply HPS-specific energy and position corrections to a cluster.
-     * @param cluster The input cluster.
-     */
-    public static void applyCorrections(Cluster cluster) {
+                ClusterEnergyCorrection.setCorrectedEnergy(ecal, baseCluster);
+            }
+        }
+    }
+      
+    /**
+     * Apply HPS-specific energy and position corrections to a cluster without track information.
+     * @param cluster The input cluster.
+     */
+    public static void applyCorrections(HPSEcal3 ecal, Cluster cluster) {
                             
         if (cluster instanceof BaseCluster) {
             
@@ -366,7 +366,25 @@
             ClusterPositionCorrection.setCorrectedPosition(baseCluster);
             
             // Apply PID based energy correction.
-            ClusterEnergyCorrection.setCorrectedEnergy(baseCluster);
+            ClusterEnergyCorrection.setCorrectedEnergy(ecal, baseCluster);
+        }        
+    }   
+    
+    /**
+     * Apply HPS-specific energy and position corrections to a cluster with track information.
+     * @param cluster The input cluster.
+     */
+    public static void applyCorrections(HPSEcal3 ecal, Cluster cluster, double ypos) {
+        
+        if (cluster instanceof BaseCluster) {
+            
+            BaseCluster baseCluster = (BaseCluster)cluster;            
+                        
+            // Apply PID based position correction, which should happen before final energy correction.
+            ClusterPositionCorrection.setCorrectedPosition(baseCluster);
+            
+            // Apply PID based energy correction.
+            ClusterEnergyCorrection.setCorrectedEnergy(ecal, baseCluster, ypos);
         }        
     }    
         

Modified: java/branches/jeremy-dev/recon/src/main/java/org/hps/recon/filtering/V0CandidateFilter.java
 =============================================================================
--- java/branches/jeremy-dev/recon/src/main/java/org/hps/recon/filtering/V0CandidateFilter.java	(original)
+++ java/branches/jeremy-dev/recon/src/main/java/org/hps/recon/filtering/V0CandidateFilter.java	Wed Dec  2 21:01:47 2015
@@ -4,15 +4,22 @@
 import java.util.List;
 import org.hps.recon.ecal.cluster.ClusterUtilities;
 import org.hps.recon.particle.ReconParticleDriver;
+import org.hps.recon.tracking.TrackData;
+import org.hps.recon.tracking.TrackType;
 import org.hps.record.epics.EpicsData;
+import org.hps.record.scalers.ScalerData;
 import org.lcsim.event.EventHeader;
 import org.lcsim.event.ReconstructedParticle;
 
 /**
  * Class to strip off trident candidates. Currently defined as: e+ e- events
- * with tracks. If the tight constraint is enabled, tracks must be matched to
- * clusters and the Ecal cluster times must be within _timingCut [2.5ns] of each
- * other.
+ * with tracks; track and vertex chi2 must be better than values defined by
+ * cuts, and track times must be within trackDtCut of each other. If the tight
+ * constraint is enabled, tracks must be matched to clusters, the Ecal cluster
+ * times must be within _timingCut [2.5ns] of each other, and there must be
+ * exactly one V0 passing all cuts.
+ *
+ * Only GBL vertices are considered.
  *
  * @author Norman A Graf
  *
@@ -20,8 +27,13 @@
  */
 public class V0CandidateFilter extends EventReconFilter {
 
-    private String _V0CandidateCollectionName = "TargetConstrainedV0Candidates";
+    private String _V0CandidateCollectionName = "UnconstrainedV0Candidates";
     private double _clusterTimingCut = 2.5;
+    private double v0Chi2Cut = 10.0;
+    private double trackChi2Cut = 20.0;
+    private double trackDtCut = 5.0;
+    private double trackPMax = 0.9;
+    private double v0PMax = 1.4;
 
     private boolean _tight = false;
     private boolean _keepEpicsDataEvents = false;
@@ -30,9 +42,15 @@
     protected void process(EventHeader event) {
         incrementEventProcessed();
         if (_keepEpicsDataEvents) {
-            // don't drop any events with EPICS data:
-            final EpicsData data = EpicsData.read(event);
-            if (data != null) {
+            // don't drop any events with EPICS or scaler data:
+            final EpicsData epicsData = EpicsData.read(event);
+            if (epicsData != null) {
+                incrementEventPassed();
+                return;
+            }
+
+            final ScalerData scalerData = ScalerData.read(event);
+            if (scalerData != null) {
                 incrementEventPassed();
                 return;
             }
@@ -41,45 +59,96 @@
             skipEvent();
         }
         List<ReconstructedParticle> V0Candidates = event.get(ReconstructedParticle.class, _V0CandidateCollectionName);
-        if (V0Candidates.isEmpty()) {
-            skipEvent();
-        }
+        int nV0 = 0; //number of good V0
+        for (ReconstructedParticle v0 : V0Candidates) {
+            ReconstructedParticle electron = v0.getParticles().get(ReconParticleDriver.ELECTRON);
+            ReconstructedParticle positron = v0.getParticles().get(ReconParticleDriver.POSITRON);
 
-        // tight requires ONLY ONE real vertex fit 
-        if (_tight) {
-            if (V0Candidates.size() != 2) {
-                skipEvent();
+            if (!TrackType.isGBL(v0.getType())) { //we only care about GBL vertices
+                continue;
             }
-            for (ReconstructedParticle rp : V0Candidates) {
-
-                ReconstructedParticle electron;
-                ReconstructedParticle positron;
-
-                List<ReconstructedParticle> fsParticles = rp.getParticles();
-                if (fsParticles.size() != 2) {
-                    skipEvent();
+            if (v0.getStartVertex().getChi2() > v0Chi2Cut) {
+                continue;
+            }
+            if (electron.getTracks().get(0).getChi2() > trackChi2Cut || positron.getTracks().get(0).getChi2() > trackChi2Cut) {
+                continue;
+            }
+            if (electron.getMomentum().magnitude() > trackPMax || positron.getMomentum().magnitude() > trackPMax) {
+                continue;
+            }
+            if (v0.getMomentum().magnitude() > v0PMax) {
+                continue;
+            }
+            double eleTime = TrackData.getTrackTime(TrackData.getTrackData(event, electron.getTracks().get(0)));
+            double posTime = TrackData.getTrackTime(TrackData.getTrackData(event, positron.getTracks().get(0)));
+            if (Math.abs(eleTime - posTime) > trackDtCut) {
+                continue;
+            }
+            if (_tight) { // tight requires cluster matches and cluster time cut
+                if (electron.getClusters().isEmpty() || positron.getClusters().isEmpty()) {
+                    continue;
                 }
-                // require both electrons to be associated with an ECal cluster
-                electron = fsParticles.get(ReconParticleDriver.ELECTRON);
-                if (electron.getClusters().isEmpty()) {
-                    skipEvent();
-                }
-                positron = fsParticles.get(ReconParticleDriver.POSITRON);
-                if (positron.getClusters().isEmpty()) {
-                    skipEvent();
-                }
-
                 // calorimeter cluster timing cut
                 // first CalorimeterHit in the list is the seed crystal
                 double t1 = ClusterUtilities.getSeedHitTime(electron.getClusters().get(0));
                 double t2 = ClusterUtilities.getSeedHitTime(positron.getClusters().get(0));
 
                 if (abs(t1 - t2) > _clusterTimingCut) {
-                    skipEvent();
+                    continue;
                 }
             }
+            nV0++;
+        }
+        if (nV0 == 0) {
+            skipEvent();
+        }
+        // tight requires ONLY ONE candidate vertex
+        if (_tight && nV0 != 1) {
+            skipEvent();
         }
         incrementEventPassed();
+    }
+
+    /**
+     * Maximum vertex chi2 for a V0 to be counted.
+     *
+     * @param v0Chi2Cut default of 10.0.
+     */
+    public void setV0Chi2Cut(double v0Chi2Cut) {
+        this.v0Chi2Cut = v0Chi2Cut;
+    }
+
+    /**
+     * Maximum track chi2 for a V0 to be counted. A V0 is rejected if either of
+     * the final state tracks has a chi2 exceeding the cut.
+     *
+     * @param trackChi2Cut default of 20.0.
+     */
+    public void setTrackChi2Cut(double trackChi2Cut) {
+        this.trackChi2Cut = trackChi2Cut;
+    }
+
+    /**
+     * Maximum track time different for a V0 to be counted.
+     *
+     * @param trackDtCut units of ns, default of 5.0
+     */
+    public void setTrackDtCut(double trackDtCut) {
+        this.trackDtCut = trackDtCut;
+    }
+
+    /**
+     * Maximum track momentum for a V0 to be counted. A V0 is rejected if either
+     * of the final state tracks has momentum exceeding this cut.
+     *
+     * @param trackPMax units of GeV, default of 0.9
+     */
+    public void setTrackPMax(double trackPMax) {
+        this.trackPMax = trackPMax;
+    }
+
+    public void setV0PMax(double v0PMax) {
+        this.v0PMax = v0PMax;
     }
 
     /**

Modified: java/branches/jeremy-dev/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java
 =============================================================================
--- java/branches/jeremy-dev/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java	(original)
+++ java/branches/jeremy-dev/recon/src/main/java/org/hps/recon/particle/ReconParticleDriver.java	Wed Dec  2 21:01:47 2015
@@ -7,13 +7,16 @@
 import hep.physics.vec.VecOp;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 import org.hps.recon.ecal.cluster.ClusterUtilities;
 import org.hps.recon.tracking.CoordinateTransformations;
+import org.hps.recon.tracking.TrackUtils;
 import org.hps.recon.utils.TrackClusterMatcher;
+import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
 import org.lcsim.event.EventHeader;
 import org.lcsim.event.ReconstructedParticle;
@@ -23,6 +26,8 @@
 import org.lcsim.event.base.BaseReconstructedParticle;
 import org.lcsim.geometry.Detector;
 import org.lcsim.util.Driver;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+
 
 /**
  * Driver framework for generating reconstructed particles and matching clusters
@@ -44,6 +49,8 @@
     public static final int POSITRON = 1;
     public static final int MOLLER_TOP = 0;
     public static final int MOLLER_BOT = 1;
+    
+    HPSEcal3 ecal;
 
     /**
      * Sets the name of the LCIO collection for beam spot constrained V0
@@ -173,6 +180,8 @@
         this.trackCollectionNames = trackCollectionNames;
     }
 
+        
+    
     /**
      * Updates the magnetic field parameters to match the appropriate values for
      * the current detector settings.
@@ -188,6 +197,7 @@
             flipSign = -1;
         }
 
+        ecal = (HPSEcal3) detector.getSubdetector("Ecal");
         matcher.setBFieldMap(detector.getFieldMap());
 
     }
@@ -222,6 +232,9 @@
         // Create a list of unmatched clusters. A cluster should be
         // removed from the list if a matching track is found.
         Set<Cluster> unmatchedClusters = new HashSet<Cluster>(clusters);
+        
+        // Create a mapping of matched clusters to corresponding tracks.
+        HashMap<Cluster, Track> clusterToTrack = new HashMap<Cluster,Track>();
 
         // Loop through all of the track collections and try to match every
         // track to a cluster.  Allow a cluster to be matched to multiple 
@@ -263,6 +276,9 @@
                     // Check if the cluster and track are a valid match.
                     if (matcher.isMatch(cluster, track)) {
 
+                    	// Store the matched cluster to matched track.
+                    	clusterToTrack.put(cluster, track);
+                    	
                         // Store the matched cluster.
                         matchedCluster = cluster;
 
@@ -315,10 +331,17 @@
             }
         }
 
-        // Apply the corrections to the Ecal clusters
+        // Apply the corrections to the Ecal clusters using track information, if available
         for (Cluster cluster : clusters) {
             if (cluster.getParticleId() != 0) {
-                ClusterUtilities.applyCorrections(cluster);
+            	if (clusterToTrack.containsKey(cluster)){
+            		Track matchedT = clusterToTrack.get(cluster);
+            		double ypos = TrackUtils.getTrackStateAtECal(matchedT).getReferencePoint()[2];
+            		ClusterUtilities.applyCorrections(ecal, cluster, ypos);
+            	}
+            	else {
+            		ClusterUtilities.applyCorrections(ecal, cluster);          		
+            	}
             }
         }
 

Modified: java/branches/jeremy-dev/run-database/src/main/java/org/hps/run/database/RunDatabaseBuilder.java
 =============================================================================
--- java/branches/jeremy-dev/run-database/src/main/java/org/hps/run/database/RunDatabaseBuilder.java	(original)
+++ java/branches/jeremy-dev/run-database/src/main/java/org/hps/run/database/RunDatabaseBuilder.java	Wed Dec  2 21:01:47 2015
@@ -49,7 +49,7 @@
 /**
  * Builds a complete {@link RunSummary} object from various data sources, including the data catalog and the run
  * spreadsheet, so that it is ready to be inserted into the run database using the DAO interfaces.  This class also 
- * extracts EPICS data, scaler data, trigger config and SVT config information.
+ * extracts EPICS data, scaler data, trigger config and SVT config information from all of the EVIO files in a run.
  * <p>
  * The setters and some other methods follow the builder pattern and so can be chained by the caller.
  * 

Modified: java/branches/jeremy-dev/steering-files/src/main/resources/org/hps/steering/production/V0CandidateFilter.lcsim
 =============================================================================
--- java/branches/jeremy-dev/steering-files/src/main/resources/org/hps/steering/production/V0CandidateFilter.lcsim	(original)
+++ java/branches/jeremy-dev/steering-files/src/main/resources/org/hps/steering/production/V0CandidateFilter.lcsim	Wed Dec  2 21:01:47 2015
@@ -22,12 +22,6 @@
         <!-- Driver to strip events -->
         <driver name="StripEvent"
                 type="org.hps.recon.filtering.V0CandidateFilter">
-              <!-- Name of the V0 Candidate Collection of ReconstructedParticles -->
-              <v0CandidateCollectionName>TargetConstrainedV0Candidates</v0CandidateCollectionName>
-              <!-- Maximum difference in the ECal cluster times [ns]-->
-              <clusterTimingCut>2.5</clusterTimingCut>
-              <!-- A tight selection requires one and only one real V0 vertex --> 
-              <tightConstraint>false</tightConstraint>
               <!-- Setting this true keeps ALL events containing EPICS data -->
               <keepEpicsDataEvents>true</keepEpicsDataEvents>
         </driver>

Modified: java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java
 =============================================================================
--- java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java	(original)
+++ java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java	Wed Dec  2 21:01:47 2015
@@ -427,7 +427,7 @@
                     Collection<TrackerHit> htsList = hittostrip.allFrom(cross);
                     for (TrackerHit strip : htsList) {
                         Set<HelicalTrackHit> sharedCrosses = hittostrip.allTo(strip);
-                        System.out.println(sharedCrosses.size());
+//                        System.out.println(sharedCrosses.size());
                         if (sharedCrosses.size() > 1) {
 //                    this.getLogger().warning(String.format("removing possible ghost hit"));
                             iter.remove();

Modified: java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/TrackData.java
 =============================================================================
--- java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/TrackData.java	(original)
+++ java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/TrackData.java	Wed Dec  2 21:01:47 2015
@@ -1,6 +1,13 @@
 package org.hps.recon.tracking;
 
+import java.util.List;
+import org.apache.commons.math3.util.Pair;
+import org.lcsim.event.EventHeader;
 import org.lcsim.event.GenericObject;
+import org.lcsim.event.LCRelation;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.Track;
+import org.lcsim.event.base.BaseRelationalTable;
 
 /**
  * Generic object used to persist track data not available through a Track
@@ -155,4 +162,24 @@
     public boolean isFixedSize() {
         return true;
     }
+
+    private static Pair<EventHeader, RelationalTable> trackDataToTrackCache = null;
+
+    public static RelationalTable getTrackDataToTrackTable(EventHeader event) {
+        if (trackDataToTrackCache == null || trackDataToTrackCache.getFirst() != event) {
+            RelationalTable trackDataToTrack = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+            List<LCRelation> hitrelations = event.get(LCRelation.class, TRACK_DATA_RELATION_COLLECTION);
+            for (LCRelation relation : hitrelations) {
+                if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+                    trackDataToTrack.add(relation.getFrom(), relation.getTo());
+                }
+            }
+            trackDataToTrackCache = new Pair<EventHeader, RelationalTable>(event, trackDataToTrack);
+        }
+        return trackDataToTrackCache.getSecond();
+    }
+
+    public static GenericObject getTrackData(EventHeader event, Track track) {
+        return (GenericObject) getTrackDataToTrackTable(event).from(track);
+    }
 }

Modified: java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java
 =============================================================================
--- java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java	(original)
+++ java/branches/jeremy-dev/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java	Wed Dec  2 21:01:47 2015
@@ -1,19 +1,21 @@
 package org.hps.recon.tracking;
 
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Matrix;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.SpacePoint;
+import hep.physics.vec.VecOp;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
-import hep.physics.matrix.SymmetricMatrix;
-import hep.physics.vec.BasicHep3Vector;
-import hep.physics.vec.Hep3Matrix;
-import hep.physics.vec.Hep3Vector;
-import hep.physics.vec.SpacePoint;
-import hep.physics.vec.VecOp;
-
+import org.apache.commons.math3.util.Pair;
+import org.hps.recon.tracking.EventQuality.Quality;
+import org.hps.recon.tracking.gbl.HelicalTrackStripGbl;
+import static org.lcsim.constants.Constants.fieldConversion;
 import org.lcsim.detector.ITransform3D;
 import org.lcsim.detector.solids.Box;
 import org.lcsim.detector.solids.Point3D;
@@ -48,10 +50,6 @@
 import org.lcsim.util.swim.Helix;
 import org.lcsim.util.swim.Line;
 import org.lcsim.util.swim.Trajectory;
-import org.hps.recon.tracking.EventQuality.Quality;
-import org.hps.recon.tracking.gbl.HelicalTrackStripGbl;
-
-import static org.lcsim.constants.Constants.fieldConversion;
 
 /**
  * Assorted helper functions for the track and helix objects in lcsim. Re-use as
@@ -984,24 +982,36 @@
         return new HelicalTrackHit(pos, hitcov, dedx, time, type, rhits, detname, layer, beflag);
     }
 
+    private static Pair<EventHeader, RelationalTable> hitToStripsCache = null;
+
     public static RelationalTable getHitToStripsTable(EventHeader event) {
-        RelationalTable hitToStrips = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
-        List<LCRelation> hitrelations = event.get(LCRelation.class, "HelicalTrackHitRelations");
-        for (LCRelation relation : hitrelations)
-            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
-                hitToStrips.add(relation.getFrom(), relation.getTo());
-
-        return hitToStrips;
-    }
+        if (hitToStripsCache == null || hitToStripsCache.getFirst() != event) {
+            RelationalTable hitToStrips = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+            List<LCRelation> hitrelations = event.get(LCRelation.class, "HelicalTrackHitRelations");
+            for (LCRelation relation : hitrelations) {
+                if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+                    hitToStrips.add(relation.getFrom(), relation.getTo());
+                }
+            }
+            hitToStripsCache = new Pair<EventHeader, RelationalTable>(event, hitToStrips);
+        }
+        return hitToStripsCache.getSecond();
+    }
+
+    private static Pair<EventHeader, RelationalTable> hitToRotatedCache = null;
 
     public static RelationalTable getHitToRotatedTable(EventHeader event) {
-
-        RelationalTable hitToRotated = new BaseRelationalTable(RelationalTable.Mode.ONE_TO_ONE, RelationalTable.Weighting.UNWEIGHTED);
-        List<LCRelation> rotaterelations = event.get(LCRelation.class, "RotatedHelicalTrackHitRelations");
-        for (LCRelation relation : rotaterelations)
-            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
-                hitToRotated.add(relation.getFrom(), relation.getTo());
-        return hitToRotated;
+        if (hitToRotatedCache == null || hitToRotatedCache.getFirst() != event) {
+            RelationalTable hitToRotated = new BaseRelationalTable(RelationalTable.Mode.ONE_TO_ONE, RelationalTable.Weighting.UNWEIGHTED);
+            List<LCRelation> rotaterelations = event.get(LCRelation.class, "RotatedHelicalTrackHitRelations");
+            for (LCRelation relation : rotaterelations) {
+                if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+                    hitToRotated.add(relation.getFrom(), relation.getTo());
+                }
+            }
+            hitToRotatedCache = new Pair<EventHeader, RelationalTable>(event, hitToRotated);
+        }
+        return hitToRotatedCache.getSecond();
     }
 
     public static double getTrackTime(Track track, RelationalTable hitToStrips, RelationalTable hitToRotated) {