Print

Print


Author: [log in to unmask]
Date: Mon Jul  6 16:36:19 2015
New Revision: 3231

Log:
Merge in trunk changes.

Added:
    java/branches/HPSJAVA-488/detector-data/detectors/HPS-EngRun2015-Nominal-v2/
      - copied from r3230, java/trunk/detector-data/detectors/HPS-EngRun2015-Nominal-v2/
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/ReadSurveyOutput.java
      - copied unchanged from r3230, java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/ReadSurveyOutput.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyResult.java
      - copied unchanged from r3230, java/trunk/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyResult.java
    java/branches/HPSJAVA-488/detector-model/src/test/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2014v1SurveyLCDDTest.java
      - copied unchanged from r3230, java/trunk/detector-model/src/test/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2014v1SurveyLCDDTest.java
    java/branches/HPSJAVA-488/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTracker2014v1Survey.xml
      - copied unchanged from r3230, java/trunk/detector-model/src/test/resources/org/lcsim/geometry/subdetector/HPSTracker2014v1Survey.xml
    java/branches/HPSJAVA-488/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/HeadBankData.java
      - copied unchanged from r3230, java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/HeadBankData.java
    java/branches/HPSJAVA-488/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/svt/SampleZeroHVBiasChecker.java
      - copied unchanged from r3230, java/trunk/monitoring-drivers/src/main/java/org/hps/monitoring/drivers/svt/SampleZeroHVBiasChecker.java
    java/branches/HPSJAVA-488/recon/src/main/java/org/hps/recon/filtering/CollectionSizeFilter.java
      - copied unchanged from r3230, java/trunk/recon/src/main/java/org/hps/recon/filtering/CollectionSizeFilter.java
    java/branches/HPSJAVA-488/recon/src/main/java/org/hps/recon/filtering/EcalPairsFilter.java
      - copied unchanged from r3230, java/trunk/recon/src/main/java/org/hps/recon/filtering/EcalPairsFilter.java
    java/branches/HPSJAVA-488/recon/src/main/java/org/hps/recon/filtering/SVTSmallHitsFilter.java
      - copied unchanged from r3230, java/trunk/recon/src/main/java/org/hps/recon/filtering/SVTSmallHitsFilter.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/Crawler.java
      - copied unchanged from r3230, java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/Crawler.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/CrawlerConfig.java
      - copied unchanged from r3230, java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/CrawlerConfig.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/ScalerDataUpdater.java
      - copied unchanged from r3230, java/trunk/record-util/src/main/java/org/hps/record/evio/crawler/ScalerDataUpdater.java
    java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/production/SampleZeroMonitoring.lcsim
      - copied unchanged from r3230, java/trunk/steering-files/src/main/resources/org/hps/steering/production/SampleZeroMonitoring.lcsim
    java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/users/meeg/PairsSkimmer.lcsim
      - copied unchanged from r3230, java/trunk/steering-files/src/main/resources/org/hps/steering/users/meeg/PairsSkimmer.lcsim
    java/branches/HPSJAVA-488/tracking/src/main/resources/org/hps/recon/tracking/strategies/HPS_s345_c2_e16.xml
      - copied unchanged from r3230, java/trunk/tracking/src/main/resources/org/hps/recon/tracking/strategies/HPS_s345_c2_e16.xml
    java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/kmccarty/InvariantMassPairDriver.java
      - copied unchanged from r3230, java/trunk/users/src/main/java/org/hps/users/kmccarty/InvariantMassPairDriver.java
    java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/kmccarty/MTEAnalysis.java
      - copied unchanged from r3230, java/trunk/users/src/main/java/org/hps/users/kmccarty/MTEAnalysis.java
    java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/meeg/ReconParticleCleanupDriver.java
      - copied unchanged from r3230, java/trunk/users/src/main/java/org/hps/users/meeg/ReconParticleCleanupDriver.java
    java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/omoreno/SharedHitAnalysis.java
      - copied unchanged from r3230, java/trunk/users/src/main/java/org/hps/users/omoreno/SharedHitAnalysis.java
    java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/phansson/ReadSurveyRotations.java
      - copied unchanged from r3230, java/trunk/users/src/main/java/org/hps/users/phansson/ReadSurveyRotations.java
Removed:
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/EvioFileCrawler.java
Modified:
    java/branches/HPSJAVA-488/   (props changed)
    java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/EcalMonitoring.java
    java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/FinalStateMonitoring.java
    java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TrackingMonitoring.java
    java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TrackingResiduals.java
    java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TridentMonitoring.java
    java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/V0Monitoring.java
    java/branches/HPSJAVA-488/conditions/   (props changed)
    java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/svt/SvtBiasConditionsLoader.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/AlignmentCorrection.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTestRunTracker2014GeometryDefinition.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTracker2014GeometryDefinition.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerBuilder.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerGeometryDefinition.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerLCDDBuilder.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyCoordinateSystem.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyVolume.java
    java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2014Base.java
    java/branches/HPSJAVA-488/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java
    java/branches/HPSJAVA-488/evio/src/main/java/org/hps/evio/LCSimEngRunEventBuilder.java
    java/branches/HPSJAVA-488/integration-tests/   (props changed)
    java/branches/HPSJAVA-488/integration-tests/src/test/java/org/hps/test/it/EcalSimReconTest.java
    java/branches/HPSJAVA-488/parent/pom.xml
    java/branches/HPSJAVA-488/plugin/pom.xml
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/JCacheManager.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunLog.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunLogUpdater.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunProcessor.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunSummary.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryUpdater.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/package-info.java
    java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/scalers/ScalersEvioProcessor.java
    java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/readout/EngineeringRun2015TrigPairs1.lcsim
    java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/readout/EngineeringRun2015TrigSingles1.lcsim
    java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/recon/EngineeringRun2015FullReconGbl2.lcsim
    java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/recon/EngineeringRun2015FullReconMC.lcsim
    java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java
    java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java
    java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLFileIO.java
    java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutput.java
    java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutputDriver.java
    java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/luca/FeeCalibHistCreator.java
    java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/omoreno/SvtClusterAnalysis.java
    java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/omoreno/SvtHitEfficiency.java
    java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/phansson/TrackingReconstructionPlots.java

Modified: java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/EcalMonitoring.java
 =============================================================================
--- java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/EcalMonitoring.java	(original)
+++ java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/EcalMonitoring.java	Mon Jul  6 16:36:19 2015
@@ -2,17 +2,13 @@
 
 import hep.aida.IHistogram1D;
 import hep.aida.IHistogram2D;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import org.apache.commons.math.stat.StatUtils;
-import org.hps.recon.ecal.triggerbank.AbstractIntData;
-import org.hps.recon.ecal.triggerbank.TIData;
-import org.hps.recon.ecal.triggerbank.TestRunTriggerData;
+import org.hps.recon.ecal.cluster.ClusterUtilities;
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
 import org.lcsim.event.EventHeader;
-import org.lcsim.event.GenericObject;
 import org.lcsim.geometry.Detector;
 
 /**
@@ -41,6 +37,7 @@
     IHistogram1D clusterSizePlot;
     IHistogram1D clusterEnergyPlot;
     IHistogram1D clusterTimes;
+    IHistogram1D clusterTimeMean;
     IHistogram1D clusterTimeSigma;
     //mg...12/13/2014
     IHistogram1D twoclusterTotEnergy;
@@ -55,8 +52,11 @@
     IHistogram2D fiducialenergyVsX;
     IHistogram2D energyVsY;
     IHistogram2D energyVsX;
+    IHistogram2D energyVsT;
     IHistogram2D xVsY;
     IHistogram2D pairsE1vsE2;
+    IHistogram2D pairsT1vsT2;
+    IHistogram1D pairsDeltaT;
 
     int nEvents = 0;
     int nTotHits = 0;
@@ -66,7 +66,6 @@
     double sumClusterEnergy = 0;
     double sumClusterTime = 0;
     boolean fillHitPlots = true;
-    private Map<String, Double> monitoredQuantityMap = new HashMap<>();
     String[] ecalQuantNames = {"avg_N_hits", "avg_Hit_Energy",
         "avg_N_clusters", "avg_N_hitsPerCluster", "avg_Cluster_Energy", "avg_ClusterTime"};
     double maxE = 1.1;
@@ -90,6 +89,7 @@
         this.fillHitPlots = fill;
     }
 
+    @Override
     protected void detectorChanged(Detector detector) {
         System.out.println("EcalMonitoring::detectorChanged  Setting up the plotter");
         aida.tree().cd("/");
@@ -105,14 +105,18 @@
         clusterCountPlot = aida.histogram1D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Cluster Count per Event", 10, -0.5, 9.5);
         clusterSizePlot = aida.histogram1D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Cluster Size", 10, -0.5, 9.5);
         clusterEnergyPlot = aida.histogram1D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Cluster Energy", 100, -0.1, maxE);
-        clusterTimes = aida.histogram1D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Cluster Time Mean", 200, 0, 4.0 * 50);
+        clusterTimes = aida.histogram1D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Cluster Seed Times", 400, 0, 4.0 * 50);
+        clusterTimeMean = aida.histogram1D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Cluster Time Mean", 400, 0, 4.0 * 50);
         clusterTimeSigma = aida.histogram1D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Cluster Time Sigma", 100, 0, 10);
         twoclusterTotEnergy = aida.histogram1D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Two Cluster Energy Sum", 100, 0, maxE);
         twoclusterEnergyAsymmetry = aida.histogram1D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Two Cluster Energy Asymmetry", 100, 0, 1.0);
-        xVsY = aida.histogram2D(plotClustersDir +  triggerType + "/"+clusterCollectionName + "X vs Y (NHits >1)", 200, -200.0, 200.0, 85, -85.0, 85.0);
+        energyVsT = aida.histogram2D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Energy vs time", 400, 0.0, 200.0, 100, -0.1, maxE);
+        xVsY = aida.histogram2D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " X vs Y (NHits >1)", 200, -200.0, 200.0, 85, -85.0, 85.0);
         energyVsX = aida.histogram2D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Energy vs X", 50, 0, 1.6, 50, .0, 200.0);
         energyVsY = aida.histogram2D(plotClustersDir +  triggerType + "/"+clusterCollectionName + " Energy vs Y", 50, 0, 1.6, 50, 20.0, 85.0);
         pairsE1vsE2 = aida.histogram2D(plotClustersDir +  triggerType + "/"+clusterCollectionName + "Pair E1 vs E2", 50, 0, 2, 50, 0, 2);
+        pairsT1vsT2 = aida.histogram2D(plotClustersDir +  triggerType + "/"+clusterCollectionName + "Pair T1 vs T2", 200, 0, 100, 200, 0, 100);
+        pairsDeltaT = aida.histogram1D(plotClustersDir + triggerType + "/" + clusterCollectionName + " Pair Time Difference", 100, -20.0, 20.0);
 
         fiducialClusterCountPlot = aida.histogram1D(plotClustersDir +  triggerType + "/"+plotFidCutDir + clusterCollectionName + " Cluster Count with Fiducal Cut", 10, -0.5, 9.5);
         fiducialClusterSizePlot = aida.histogram1D(plotClustersDir+  triggerType + "/" +plotFidCutDir + clusterCollectionName + " Cluster Size with Fiducal Cut", 10, -0.5, 9.5);
@@ -159,10 +163,6 @@
         List<Cluster> clusters;
         if (event.hasCollection(Cluster.class, clusterCollectionName))
             clusters = event.get(Cluster.class, clusterCollectionName);
-        else if (event.hasCollection(Cluster.class, clusterCollectionName))
-            clusters = event.get(Cluster.class, clusterCollectionName);
-        else if (event.hasCollection(Cluster.class, clusterCollectionName))
-            clusters = event.get(Cluster.class, clusterCollectionName);
         else {
             clusterCountPlot.fill(0);
             return;
@@ -173,9 +173,11 @@
         int fidcnt = 0;
         for (Cluster cluster : clusters) {
             clusterEnergyPlot.fill(cluster.getEnergy());
+            clusterTimes.fill(ClusterUtilities.findSeedHit(cluster).getTime());
+            energyVsT.fill(ClusterUtilities.findSeedHit(cluster).getTime(), cluster.getEnergy());
             sumClusterEnergy += cluster.getEnergy();
             double[] times = new double[cluster.getCalorimeterHits().size()];
-            double[] energies = new double[cluster.getCalorimeterHits().size()];
+//            double[] energies = new double[cluster.getCalorimeterHits().size()];
             CalorimeterHit seed = cluster.getCalorimeterHits().get(0);
             int ix = seed.getIdentifierFieldValue("ix");
             int iy = seed.getIdentifierFieldValue("iy");
@@ -196,11 +198,11 @@
 
             int size = 0;
             for (CalorimeterHit hit : cluster.getCalorimeterHits()) {
-                energies[size] = hit.getCorrectedEnergy();
+//                energies[size] = hit.getCorrectedEnergy();
                 times[size] = hit.getTime();
                 size++;
             }
-            clusterTimes.fill(StatUtils.mean(times, 0, size));
+            clusterTimeMean.fill(StatUtils.mean(times, 0, size));
             clusterSizePlot.fill(size); //The number of "hits" in a "cluster"
             clusterTimeSigma.fill(Math.sqrt(StatUtils.variance(times, 0, size)));
             sumHitPerCluster += size;
@@ -212,16 +214,18 @@
         if (clusters.size() == 2) {
             Cluster cl1 = clusters.get(0);
             Cluster cl2 = clusters.get(1);
-            double[] p1 = cl1.getPosition();
-            double[] p2 = cl2.getPosition();
+//            double[] p1 = cl1.getPosition();
+//            double[] p2 = cl2.getPosition();
             double e1 = cl1.getEnergy();
             double e2 = cl2.getEnergy();
+            double t1 = ClusterUtilities.findSeedHit(cl1).getTime();
+            double t2 = ClusterUtilities.findSeedHit(cl2).getTime();
             twoclusterTotEnergy.fill(e1 + e2);
             twoclusterEnergyAsymmetry.fill(Math.abs(e1 - e2) / (e1 + e2));
             pairsE1vsE2.fill(e1, e2);
-
-        }
-
+            pairsT1vsT2.fill(t1, t2);
+            pairsDeltaT.fill(t1 - t2);
+        }
     }
 
     @Override

Modified: java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/FinalStateMonitoring.java
 =============================================================================
--- java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/FinalStateMonitoring.java	(original)
+++ java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/FinalStateMonitoring.java	Mon Jul  6 16:36:19 2015
@@ -15,13 +15,12 @@
 import java.util.Map.Entry;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import org.hps.recon.ecal.triggerbank.AbstractIntData;
-import org.hps.recon.ecal.triggerbank.TIData;
+import org.hps.recon.ecal.cluster.ClusterUtilities;
 import org.hps.recon.tracking.TrackUtils;
 import org.lcsim.event.Cluster;
 import org.lcsim.event.EventHeader;
-import org.lcsim.event.GenericObject;
 import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.RelationalTable;
 import org.lcsim.event.Track;
 import org.lcsim.geometry.Detector;
 
@@ -34,8 +33,8 @@
  * output is crap; no charge<0 tracks & the track momentum isn't filled; likely
  * a problem with ReconParticle
  *
- * May 20, 2014: this was fixed by a) Omar's changes to ReconParticle and
- * b) making sure I run ECal clustering before this
+ * May 20, 2014: this was fixed by a) Omar's changes to ReconParticle and b)
+ * making sure I run ECal clustering before this
  *
  *
  */
@@ -55,15 +54,48 @@
     double sumdelX = 0.0;
     double sumdelY = 0.0;
     double sumEoverP = 0.0;
-    private String plotDir = "FinalStateParticles/";
+    private final String plotDir = "FinalStateParticles/";
     double beamEnergy = 1.05; //GeV
     double maxFactor = 2.5;
     double feeMomentumCut = 0.8; //GeV
 
-   public void setFinalStateParticlesColName(String fsp){
-       this.finalStateParticlesColName=fsp;
-   }
-    
+    IHistogram1D elePx;
+    IHistogram1D elePy;
+    IHistogram1D elePz;
+    IHistogram1D elePzBeam;
+    IHistogram1D elePzBeamTop;
+    IHistogram1D elePzBeamBottom;
+    IHistogram1D elePTop;
+    IHistogram1D elePBottom;
+
+    IHistogram1D posPx;
+    IHistogram1D posPy;
+    IHistogram1D posPz;
+    IHistogram1D posPTop;
+    IHistogram1D posPBottom;
+
+    /*  photon quanties (...right now, just unassociated clusters) */
+    IHistogram1D nPhotonsHisto;
+    IHistogram1D enePhoton;
+    IHistogram1D xPhoton;
+    IHistogram1D yPhoton;
+
+    /*  tracks with associated clusters */
+    IHistogram1D eneOverp;
+    IHistogram1D deltaXAtCal;
+    IHistogram1D deltaYAtCal;
+//    IHistogram2D trackXvsECalX;
+//    IHistogram2D trackYvsECalY;
+    IHistogram2D trackPvsECalE;
+    IHistogram2D trackTvsECalT;
+    IHistogram1D timeMatchDeltaT;
+    /* number of unassocaited tracks/event */
+    IHistogram1D nUnAssTracksHisto;
+
+    public void setFinalStateParticlesColName(String fsp) {
+        this.finalStateParticlesColName = fsp;
+    }
+
     @Override
     protected void detectorChanged(Detector detector) {
         System.out.println("FinalStateMonitoring::detectorChanged  Setting up the plotter");
@@ -71,36 +103,38 @@
 
         /*  Final State Particle Quantities   */
         /*  plot electron & positron momentum separately  */
-        IHistogram1D elePx = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Electron Px (GeV)", 100, -0.1, 0.200);
-        IHistogram1D elePy = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Electron Py (GeV)", 100, -0.1, 0.1);
-        IHistogram1D elePz = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Electron Pz (GeV)", 100, 0, beamEnergy * maxFactor);
-        IHistogram1D elePzBeam = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Beam Electrons Total P (GeV)", 100, feeMomentumCut, beamEnergy * maxFactor);
-        IHistogram1D elePzBeamTop = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Beam Electrons Total P (GeV):  Top", 100, feeMomentumCut, beamEnergy * maxFactor);
-        IHistogram1D elePzBeamBottom = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Beam Electrons Total P (GeV):  Bottom", 100, feeMomentumCut, beamEnergy * maxFactor);
-        IHistogram1D elePTop = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Electron Total P (GeV):  Top", 100, 0, beamEnergy * maxFactor);
-        IHistogram1D elePBottom = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Electron Total P (GeV):  Bottom", 100, 0, beamEnergy * maxFactor);
-
-        IHistogram1D posPx = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Px (GeV)", 50, -0.1, 0.200);
-        IHistogram1D posPy = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Py (GeV)", 50, -0.1, 0.1);
-        IHistogram1D posPz = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Pz (GeV)", 50, 0, beamEnergy * maxFactor);
-       IHistogram1D posPTop = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Total P (GeV):  Top", 100, 0, beamEnergy * maxFactor);
-        IHistogram1D posPBottom = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Total P (GeV):  Bottom", 100, 0, beamEnergy * maxFactor);
+        elePx = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Electron Px (GeV)", 100, -0.1, 0.200);
+        elePy = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Electron Py (GeV)", 100, -0.1, 0.1);
+        elePz = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Electron Pz (GeV)", 100, 0, beamEnergy * maxFactor);
+        elePzBeam = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Beam Electrons Total P (GeV)", 100, feeMomentumCut, beamEnergy * maxFactor);
+        elePzBeamTop = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Beam Electrons Total P (GeV):  Top", 100, feeMomentumCut, beamEnergy * maxFactor);
+        elePzBeamBottom = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Beam Electrons Total P (GeV):  Bottom", 100, feeMomentumCut, beamEnergy * maxFactor);
+        elePTop = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Electron Total P (GeV):  Top", 100, 0, beamEnergy * maxFactor);
+        elePBottom = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Electron Total P (GeV):  Bottom", 100, 0, beamEnergy * maxFactor);
+
+        posPx = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Positron Px (GeV)", 50, -0.1, 0.200);
+        posPy = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Positron Py (GeV)", 50, -0.1, 0.1);
+        posPz = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Positron Pz (GeV)", 50, 0, beamEnergy * maxFactor);
+        posPTop = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Positron Total P (GeV):  Top", 100, 0, beamEnergy * maxFactor);
+        posPBottom = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Positron Total P (GeV):  Bottom", 100, 0, beamEnergy * maxFactor);
 
         /*  photon quanties (...right now, just unassociated clusters) */
-        IHistogram1D nPhotonsHisto = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Number of photons per event", 15, 0, 15);
-        IHistogram1D enePhoton = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Photon Energy (GeV)", 50, 0, 2.4);
-        IHistogram1D xPhoton = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Photon X position (mm)", 50, -200, 200);
-        IHistogram1D yPhoton = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Photon Y position (mm)", 50, -100, 100);
+        nPhotonsHisto = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Number of photons per event", 15, 0, 15);
+        enePhoton = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Photon Energy (GeV)", 50, 0, 2.4);
+        xPhoton = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Photon X position (mm)", 50, -200, 200);
+        yPhoton = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Photon Y position (mm)", 50, -100, 100);
 
         /*  tracks with associated clusters */
-        IHistogram1D eneOverp = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Cluster Energy Over TrackMomentum", 50, 0, 2.0);
-        IHistogram1D deltaXAtCal = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "delta X @ ECal (mm)", 50, -50, 50.0);
-        IHistogram1D deltaYAtCal = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "delta Y @ ECal (mm)", 50, -50, 50.0);
-        //IHistogram2D trackXvsECalX = aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "track X vs ECal X", 50, -300, 300.0, 50, -300, 300.0);
-        //IHistogram2D trackYvsECalY = aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "track Y vs ECal Y", 50, -100, 100.0, 50, -100, 100.0);
-        IHistogram2D trackPvsECalE = aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "track mom vs ECal E", 50, 0.1, beamEnergy * maxFactor, 50, 0.1, beamEnergy * maxFactor);
+        eneOverp = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Cluster Energy Over TrackMomentum", 50, 0, 2.0);
+        deltaXAtCal = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "delta X @ ECal (mm)", 50, -50, 50.0);
+        deltaYAtCal = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "delta Y @ ECal (mm)", 50, -50, 50.0);
+//        trackXvsECalX = aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "track X vs ECal X", 50, -300, 300.0, 50, -300, 300.0);
+//        trackYvsECalY = aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "track Y vs ECal Y", 50, -100, 100.0, 50, -100, 100.0);
+        trackPvsECalE = aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "track mom vs ECal E", 50, 0.1, beamEnergy * maxFactor, 50, 0.1, beamEnergy * maxFactor);
+        trackTvsECalT = aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "track T vs ECal T", 200, 0.0, 200.0, 100, -25.0, 25.0);
+        timeMatchDeltaT = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "ECal T minus track T", 200, -25, 175);
         /* number of unassocaited tracks/event */
-        IHistogram1D nUnAssTracksHisto = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Number of unassociated tracks per event", 5, 0, 5);
+        nUnAssTracksHisto = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType + "/" + "Number of unassociated tracks per event", 5, 0, 5);
     }
 
     @Override
@@ -108,24 +142,31 @@
         /*  make sure everything is there */
 
         if (!event.hasCollection(ReconstructedParticle.class, finalStateParticlesColName)) {
-            if (debug)
+            if (debug) {
                 System.out.println(finalStateParticlesColName + " collection not found???");
+            }
             return;
         }
 
+        RelationalTable hitToStrips = TrackUtils.getHitToStripsTable(event);
+        RelationalTable hitToRotated = TrackUtils.getHitToRotatedTable(event);
+
         //check to see if this event is from the correct trigger (or "all");
-        if (!matchTrigger(event))
+        if (!matchTrigger(event)) {
             return;
+        }
 
         nRecoEvents++;
         int nPhotons = 0;  //number of photons 
         int nUnAssTracks = 0; //number of tracks w/o clusters
         List<ReconstructedParticle> finalStateParticles = event.get(ReconstructedParticle.class, finalStateParticlesColName);
-        if (debug)
+        if (debug) {
             System.out.println("This events has " + finalStateParticles.size() + " final state particles");
+        }
         for (ReconstructedParticle fsPart : finalStateParticles) {
-            if (debug)
+            if (debug) {
                 System.out.println("PDGID = " + fsPart.getParticleIDUsed() + "; charge = " + fsPart.getCharge() + "; pz = " + fsPart.getMomentum().x());
+            }
 
             // Extrapolate the track to the Ecal cluster position
             boolean isPhoton = false;
@@ -134,14 +175,17 @@
             Cluster fsCluster = null;
             //TODO:  mg-May 14, 2014 use PID to do this instead...not sure if that's implemented yet
             if (fsPart.getTracks().size() == 1)//should always be 1 or zero for final state particles
+            {
                 fsTrack = fsPart.getTracks().get(0);
-            else
+            } else {
                 isPhoton = true;
+            }
             //get the cluster
-            if (fsPart.getClusters().size() == 1)
+            if (fsPart.getClusters().size() == 1) {
                 fsCluster = fsPart.getClusters().get(0);
-            else
+            } else {
                 hasCluster = false;
+            }
 
             //deal with electrons & positrons first
             if (!isPhoton) {
@@ -149,32 +193,35 @@
                 Hep3Vector mom = fsPart.getMomentum();
                 if (charge < 0) {
                     nTotEle++;
-                    aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Electron Px (GeV)").fill(mom.x());
-                    aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Electron Py (GeV)").fill(mom.y());
-                    aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Electron Pz (GeV)").fill(mom.z());
-                    aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Beam Electrons Total P (GeV)").fill(mom.magnitude());
-                    if (mom.y() > 0){
-                        aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Beam Electrons Total P (GeV):  Top").fill(mom.magnitude());
-                        aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Electron Total P (GeV):  Top").fill(mom.magnitude());
-                }            else{
-                        aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Beam Electrons Total P (GeV):  Bottom").fill(mom.magnitude());
-                        aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Electron Total P (GeV):  Bottom").fill(mom.magnitude());
-                }
+                    elePx.fill(mom.x());
+                    elePy.fill(mom.y());
+                    elePz.fill(mom.z());
+                    elePzBeam.fill(mom.magnitude());
+                    if (mom.y() > 0) {
+                        elePzBeamTop.fill(mom.magnitude());
+                        elePTop.fill(mom.magnitude());
+                    } else {
+                        elePzBeamBottom.fill(mom.magnitude());
+                        elePBottom.fill(mom.magnitude());
+                    }
                 } else {
                     nTotPos++;
-                    aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Px (GeV)").fill(mom.x());
-                    aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Py (GeV)").fill(mom.y());
-                    aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Pz (GeV)").fill(mom.z());
-                      if (mom.y() > 0){
-                        aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Total P (GeV):  Top").fill(mom.magnitude());
-                }            else{
-                        aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Positron Total P (GeV):  Bottom").fill(mom.magnitude());
-                }
+                    posPx.fill(mom.x());
+                    posPy.fill(mom.y());
+                    posPz.fill(mom.z());
+                    if (mom.y() > 0) {
+                        posPTop.fill(mom.magnitude());
+                    } else {
+                        posPBottom.fill(mom.magnitude());
+                    }
                 }
 
             }
             //now, the photons
             if (isPhoton) {
+                if (fsCluster == null) {
+                    throw new RuntimeException("isPhoton==true but no cluster found: should never happen");
+                }
                 double ene = fsPart.getEnergy();
                 //TODO:  mg-May 14, 2014....I would like to do this!!!!
                 //double xpos = fsCluster.getPositionAtShowerMax(false)[0];// false-->assume a photon instead of electron from calculating shower depth
@@ -185,12 +232,15 @@
                 double ypos = clusterPosition.y();
                 nPhotons++;
                 nTotPhotons++;
-                aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Photon Energy (GeV)").fill(ene);
-                aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Photon X position (mm)").fill(xpos);
-                aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Photon Y position (mm)").fill(ypos);
+                enePhoton.fill(ene);
+                xPhoton.fill(xpos);
+                yPhoton.fill(ypos);
             }
 
             if (hasCluster && !isPhoton) {
+                if (fsCluster == null) {
+                    throw new RuntimeException("hasCluster==true but no cluster found: should never happen");
+                }
                 nTotAss++;
                 Hep3Vector mom = fsPart.getMomentum();
                 double ene = fsPart.getEnergy();
@@ -204,13 +254,15 @@
                 sumdelY += dy;
                 sumEoverP += eOverP;
 
-                aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Cluster Energy Over TrackMomentum").fill(eOverP);
-                aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "delta X @ ECal (mm)").fill(dx);
-                aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "delta Y @ ECal (mm)").fill(dy);
+                eneOverp.fill(eOverP);
+                deltaXAtCal.fill(dx);
+                deltaYAtCal.fill(dy);
                 /* here are some plots for debugging track-cluster matching */
-                // aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "track X vs ECal X").fill(trackPosAtEcal.x(), clusterPosition.x());
-                // aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "track Y vs ECal Y").fill(trackPosAtEcal.y(), clusterPosition.y());
-                aida.histogram2D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "track mom vs ECal E").fill(fsPart.getMomentum().magnitude(), fsPart.getEnergy());
+//                trackXvsECalX.fill(trackPosAtEcal.x(), clusterPosition.x());
+//                trackYvsECalY.fill(trackPosAtEcal.y(), clusterPosition.y());
+                trackPvsECalE.fill(fsPart.getMomentum().magnitude(), fsPart.getEnergy());
+                trackTvsECalT.fill(ClusterUtilities.getSeedHitTime(fsCluster), TrackUtils.getTrackTime(fsTrack, hitToStrips, hitToRotated));
+                timeMatchDeltaT.fill(ClusterUtilities.getSeedHitTime(fsCluster) - TrackUtils.getTrackTime(fsTrack, hitToStrips, hitToRotated));
                 //          if(dy<-20)
                 //              System.out.println("Big deltaY...")
 
@@ -220,15 +272,16 @@
                 nTotUnAss++; //and keep a running total for averaging
             }
         }
-        aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Number of unassociated tracks per event").fill(nUnAssTracks);
-        aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Number of photons per event").fill(nPhotons);
+        nUnAssTracksHisto.fill(nUnAssTracks);
+        nPhotonsHisto.fill(nPhotons);
     }
 
     @Override
     public void printDQMData() {
         System.out.println("FinalStateMonitoring::printDQMData");
-        for (Entry<String, Double> entry : monitoredQuantityMap.entrySet())
+        for (Entry<String, Double> entry : monitoredQuantityMap.entrySet()) {
             System.out.println(entry.getKey() + " = " + entry.getValue());
+        }
         System.out.println("*******************************");
     }
 
@@ -240,12 +293,12 @@
         IAnalysisFactory analysisFactory = IAnalysisFactory.create();
         IFitFactory fitFactory = analysisFactory.createFitFactory();
         IFitter fitter = fitFactory.createFitter("chi2");
-        IHistogram1D beamE = aida.histogram1D(plotDir + finalStateParticlesColName + "/" + triggerType+ "/" + "Beam Electrons Total P (GeV)");
-        IFitResult result = fitBeamEnergyPeak(beamE, fitter, "range=\"(-10.0,10.0)\"");
+        IFitResult result = fitBeamEnergyPeak(elePzBeam, fitter, "range=\"(-10.0,10.0)\"");
         if (result != null) {
             double[] pars = result.fittedParameters();
-            for (int i = 0; i < 5; i++)
+            for (int i = 0; i < 5; i++) {
                 System.out.println("Beam Energy Peak:  " + result.fittedParameterNames()[i] + " = " + pars[i]);
+            }
             monitoredQuantityMap.put(finalStateParticlesColName + " " + triggerType + " " + fpQuantNames[7], (double) pars[1]);
             monitoredQuantityMap.put(finalStateParticlesColName + " " + triggerType + " " + fpQuantNames[8], (double) pars[2]);
         }
@@ -263,20 +316,23 @@
         pstyle.legendBoxStyle().setVisible(false);
         pstyle.dataStyle().fillStyle().setColor("green");
         pstyle.dataStyle().lineStyle().setColor("black");
-        plotter.region(0).plot(beamE);
+        plotter.region(0).plot(elePzBeam);
 //        plotter.region(0).plot(result.fittedFunction());
-        if (outputPlots)
+        if (outputPlots) {
             try {
                 plotter.writeToFile(outputPlotDir + "beamEnergyElectrons.png");
             } catch (IOException ex) {
                 Logger.getLogger(FinalStateMonitoring.class.getName()).log(Level.SEVERE, null, ex);
             }
+        }
     }
 
     @Override
     public void printDQMStrings() {
         for (int i = 0; i < 9; i++)//TODO:  do this in a smarter way...loop over the map
+        {
             System.out.println("ALTER TABLE dqm ADD " + fpQuantNames[i] + " double;");
+        }
     }
 
     IFitResult fitBeamEnergyPeak(IHistogram1D h1d, IFitter fitter, String range) {

Modified: java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TrackingMonitoring.java
 =============================================================================
--- java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TrackingMonitoring.java	(original)
+++ java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TrackingMonitoring.java	Mon Jul  6 16:36:19 2015
@@ -73,6 +73,21 @@
     IHistogram1D[] deltaTOnTrackTop = new IHistogram1D[nmodules];
     IHistogram1D[] deltaTOnTrackBot = new IHistogram1D[nmodules];
 
+    IHistogram1D trkChi2 = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Track Chi2", 50, 0, 25.0);
+    IHistogram1D nTracks = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Tracks per Event", 6, 0, 6);
+    IHistogram1D trkd0;
+    IHistogram1D trkphi;
+    IHistogram1D trkomega;
+    IHistogram1D trklam;
+    IHistogram1D trkz0;
+    IHistogram1D nHits;
+    IHistogram1D trackMeanTime;
+    IHistogram1D trackRMSTime;
+    IHistogram2D trackChi2RMSTime;
+    IHistogram1D seedRMSTime;
+    IHistogram2D trigTimeTrackTime;
+    IHistogram1D trigTime;
+
     IHistogram1D trkYAtECALTop;
     IHistogram1D trkYAtECALBot;
 
@@ -137,7 +152,7 @@
     double omegaCut = 0.0005;
     double lambdaCut = 0.1;
     double z0Cut = 1.0;
-    double timeCut=24.0;
+    double timeCut = 24.0;
 
     public void setHelicalTrackHitCollectionName(String helicalTrackHitCollectionName) {
         this.helicalTrackHitCollectionName = helicalTrackHitCollectionName;
@@ -152,18 +167,20 @@
         this.detector = detector;
         aida.tree().cd("/");
 
-        IHistogram1D trkChi2 = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Track Chi2", 50, 0, 25.0);
-        IHistogram1D nTracks = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Tracks per Event", 6, 0, 6);
-        IHistogram1D trkd0 = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "d0 ", 50, -d0Cut, d0Cut);
-        IHistogram1D trkphi = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "sinphi ", 50, -phiCut, phiCut);
-        IHistogram1D trkomega = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "omega ", 50, -omegaCut, omegaCut);
-        IHistogram1D trklam = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "tan(lambda) ", 50, -lambdaCut, lambdaCut);
-        IHistogram1D trkz0 = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "z0 ", 50, -z0Cut, z0Cut);
-        IHistogram1D nHits = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Hits per Track", 4, 3, 7);
-        IHistogram1D trackMeanTime = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Mean time of hits on track", 100, -timeCut, timeCut);
-        IHistogram1D trackRMSTime = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "RMS time of hits on track", 100, 0., 15.);
-        IHistogram2D trackChi2RMSTime = aida.histogram2D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Track chi2 vs. RMS time of hits", 100, 0., 15., 25, 0, 25.0);
-        IHistogram1D seedRMSTime = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "RMS time of hits on seed layers", 100, 0., 15.);
+        trkChi2 = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Track Chi2", 50, 0, 25.0);
+        nTracks = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Tracks per Event", 6, 0, 6);
+        trkd0 = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "d0 ", 50, -d0Cut, d0Cut);
+        trkphi = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "sinphi ", 50, -phiCut, phiCut);
+        trkomega = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "omega ", 50, -omegaCut, omegaCut);
+        trklam = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "tan(lambda) ", 50, -lambdaCut, lambdaCut);
+        trkz0 = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "z0 ", 50, -z0Cut, z0Cut);
+        nHits = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Hits per Track", 4, 3, 7);
+        trackMeanTime = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Mean time of hits on track", 100, -timeCut, timeCut);
+        trackRMSTime = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "RMS time of hits on track", 100, 0., 15.);
+        trackChi2RMSTime = aida.histogram2D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Track chi2 vs. RMS time of hits", 100, 0., 15., 25, 0, 25.0);
+        trigTimeTrackTime = aida.histogram2D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Trigger phase vs. mean time of hits", 100, -timeCut, timeCut, 6, 0, 24.0);
+        trigTime = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Trigger phase", 6, 0., 24.);
+        seedRMSTime = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "RMS time of hits on seed layers", 100, 0., 15.);
         trkYAtECALTop = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Track Y at ECAL: Top", 100, 0, 100);
         trkYAtECALBot = aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Track Y at ECAL: Bot", 100, 0, 100);
         for (int i = 1; i <= nmodules; i++) {
@@ -253,50 +270,56 @@
 
         aida.tree().cd("/");
 
-        if (!event.hasCollection(LCRelation.class, helicalTrackHitRelationsCollectionName) || !event.hasCollection(LCRelation.class, rotatedHelicalTrackHitRelationsCollectionName))
+        if (!event.hasCollection(LCRelation.class, helicalTrackHitRelationsCollectionName) || !event.hasCollection(LCRelation.class, rotatedHelicalTrackHitRelationsCollectionName)) {
             return;
+        }
         RelationalTable hittostrip = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
         List<LCRelation> hitrelations = event.get(LCRelation.class, helicalTrackHitRelationsCollectionName);
-        for (LCRelation relation : hitrelations)
-            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
+        for (LCRelation relation : hitrelations) {
+            if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
                 hittostrip.add(relation.getFrom(), relation.getTo());
+            }
+        }
 
         RelationalTable hittorotated = new BaseRelationalTable(RelationalTable.Mode.ONE_TO_ONE, RelationalTable.Weighting.UNWEIGHTED);
         List<LCRelation> rotaterelations = event.get(LCRelation.class, rotatedHelicalTrackHitRelationsCollectionName);
-        for (LCRelation relation : rotaterelations)
-            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
+        for (LCRelation relation : rotaterelations) {
+            if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
                 hittorotated.add(relation.getFrom(), relation.getTo());
-
-        if (!event.hasCollection(TrackerHit.class, helicalTrackHitCollectionName))
+            }
+        }
+
+        if (!event.hasCollection(TrackerHit.class, helicalTrackHitCollectionName)) {
             return;
+        }
 
         //check to see if this event is from the correct trigger (or "all");
-        if (!matchTrigger(event))
+        if (!matchTrigger(event)) {
             return;
+        }
         /*  This doesn't work on reco'ed files...fix me! */
         int[] topHits = {0, 0, 0, 0, 0, 0};
         int[] botHits = {0, 0, 0, 0, 0, 0};
         List<TrackerHit> hth = event.get(TrackerHit.class, helicalTrackHitCollectionName);
         for (TrackerHit hit : hth) {
-            int module = -99;
             int layer = ((RawTrackerHit) hit.getRawHits().get(0)).getLayerNumber();
-            module = layer/2 + 1;
+            int module = layer / 2 + 1;
 
             Collection<TrackerHit> htsList = hittostrip.allFrom(hit);
             double hitTimes[] = new double[2];
             for (TrackerHit hts : htsList) {
                 int stripLayer = ((HpsSiSensor) ((RawTrackerHit) hts.getRawHits().get(0)).getDetectorElement()).getLayerNumber();
-                hitTimes[stripLayer%2] = hts.getTime();
+                hitTimes[stripLayer % 2] = hts.getTime();
             }
 
             if (hit.getPosition()[1] > 0) {
                 topHits[module - 1]++;
                 xvsyTop[module - 1].fill(hit.getPosition()[0], hit.getPosition()[1]);
-                timevstimeTop[module - 1].fill(hitTimes[0],hitTimes[1]);
+                timevstimeTop[module - 1].fill(hitTimes[0], hitTimes[1]);
             } else {
                 botHits[module - 1]++;
                 xvsyBot[module - 1].fill(hit.getPosition()[0], Math.abs(hit.getPosition()[1]));
-                timevstimeBot[module - 1].fill(hitTimes[0],hitTimes[1]);
+                timevstimeBot[module - 1].fill(hitTimes[0], hitTimes[1]);
             }
         }
 
@@ -306,13 +329,13 @@
         }
 
         if (!event.hasCollection(Track.class, trackCollectionName)) {
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Tracks per Event").fill(0);
+            nTracks.fill(0);
             return;
         }
         nEvents++;
         List<Track> tracks = event.get(Track.class, trackCollectionName);
         nTotTracks += tracks.size();
-        aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Tracks per Event").fill(tracks.size());
+        nTracks.fill(tracks.size());
         int cntEle = 0;
         int cntPos = 0;
         int cntTop = 0;
@@ -321,10 +344,11 @@
         for (Track trk : tracks) {
             Hep3Vector trackPosAtEcalFace = TrackUtils.extrapolateTrack(trk, ecalFace);
             double yAtECal = trackPosAtEcalFace.y();
-            if (yAtECal > 0)
+            if (yAtECal > 0) {
                 trkYAtECALTop.fill(yAtECal);
-            else
+            } else {
                 trkYAtECALBot.fill(Math.abs(yAtECal));
+            }
             nTotHits += trk.getTrackerHits().size();
 
             double d0 = trk.getTrackStates().get(0).getD0();
@@ -332,13 +356,13 @@
             double omega = trk.getTrackStates().get(0).getOmega();
             double lambda = trk.getTrackStates().get(0).getTanLambda();
             double z0 = trk.getTrackStates().get(0).getZ0();
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Track Chi2").fill(trk.getChi2());
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Hits per Track").fill(trk.getTrackerHits().size());
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "d0 ").fill(trk.getTrackStates().get(0).getD0());
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "sinphi ").fill(Math.sin(trk.getTrackStates().get(0).getPhi()));
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "omega ").fill(trk.getTrackStates().get(0).getOmega());
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "tan(lambda) ").fill(trk.getTrackStates().get(0).getTanLambda());
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "z0 ").fill(trk.getTrackStates().get(0).getZ0());
+            trkChi2.fill(trk.getChi2());
+            nHits.fill(trk.getTrackerHits().size());
+            trkd0.fill(trk.getTrackStates().get(0).getD0());
+            trkphi.fill(Math.sin(trk.getTrackStates().get(0).getPhi()));
+            trkomega.fill(trk.getTrackStates().get(0).getOmega());
+            trklam.fill(trk.getTrackStates().get(0).getTanLambda());
+            trkz0.fill(trk.getTrackStates().get(0).getZ0());
             d0VsPhi0.fill(d0, sinphi0);
             d0Vsomega.fill(d0, omega);
             d0Vslambda.fill(d0, lambda);
@@ -393,19 +417,22 @@
                     rmsTime += Math.pow(hts.getTime() - meanTime, 2);
                     HpsSiSensor sensor = (HpsSiSensor) ((RawTrackerHit) hts.getRawHits().get(0)).getDetectorElement();
                     int layer = sensor.getLayerNumber();
-                    if (layer <= 6)
+                    if (layer <= 6) {
                         rmsSeedTime += Math.pow(hts.getTime() - meanSeedTime, 2);
+                    }
                     String sensorName = getNiceSensorName(sensor);
                     getSensorPlot(plotDir + trackCollectionName + "/" + triggerType + "/" + timeresidDir + "hitTimeResidual_", sensorName).fill((hts.getTime() - meanTime) * nStrips / (nStrips - 1)); //correct residual for bias
                 }
             }
             rmsTime = Math.sqrt(rmsTime / nStrips);
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Mean time of hits on track").fill(meanTime);
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "RMS time of hits on track").fill(rmsTime);
-            aida.histogram2D(plotDir + trackCollectionName + "/" + triggerType + "/" + "Track chi2 vs. RMS time of hits").fill(rmsTime, trk.getChi2());
+            trackMeanTime.fill(meanTime);
+            trackRMSTime.fill(rmsTime);
+            trackChi2RMSTime.fill(rmsTime, trk.getChi2());
+            trigTimeTrackTime.fill(meanTime, event.getTimeStamp() % 24);
+            trigTime.fill(event.getTimeStamp() % 24);
 
             rmsSeedTime = Math.sqrt(rmsSeedTime / nSeedStrips);
-            aida.histogram1D(plotDir + trackCollectionName + "/" + triggerType + "/" + "RMS time of hits on seed layers").fill(rmsSeedTime);
+            seedRMSTime.fill(rmsSeedTime);
 
             if (trk.getTrackStates().get(0).getOmega() < 0) {//positrons
                 trkChi2Pos.fill(trk.getChi2());
@@ -475,8 +502,9 @@
             //IHistogram1D occupancyPlot = aida.histogram1D(sensor.getName().replaceAll("Tracker_TestRunModule_", ""), 640, 0, 639);
             IHistogram1D hitTimeResidual = getSensorPlot(plotDir + trackCollectionName + "/" + triggerType + "/" + timeresidDir + "hitTimeResidual_", getNiceSensorName(sensor));
             IFitResult result = fitGaussian(hitTimeResidual, fitter, "range=\"(-20.0,20.0)\"");
-            if (result != null)
+            if (result != null) {
                 System.out.format("%s\t%f\t%f\t%d\t%d\n", getNiceSensorName(sensor), result.fittedParameters()[1], result.fittedParameters()[2], sensor.getFebID(), sensor.getFebHybridID());
+            }
         }
 
         monitoredQuantityMap.put(trackCollectionName + " " + triggerType + " " + trackingQuantNames[0], (double) nTotTracks / nEvents);
@@ -503,15 +531,17 @@
     @Override
     public void printDQMData() {
         System.out.println("ReconMonitoring::printDQMData");
-        for (Map.Entry<String, Double> entry : monitoredQuantityMap.entrySet())
+        for (Map.Entry<String, Double> entry : monitoredQuantityMap.entrySet()) {
             System.out.println(entry.getKey() + " = " + entry.getValue());
+        }
         System.out.println("*******************************");
     }
 
     @Override
     public void printDQMStrings() {
-        for (Map.Entry<String, Double> entry : monitoredQuantityMap.entrySet())
+        for (Map.Entry<String, Double> entry : monitoredQuantityMap.entrySet()) {
             System.out.println("ALTER TABLE dqm ADD " + entry.getKey() + " double;");
+        }
     }
 
     private IHistogram1D getSensorPlot(String prefix, HpsSiSensor sensor) {

Modified: java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TrackingResiduals.java
 =============================================================================
--- java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TrackingResiduals.java	(original)
+++ java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TrackingResiduals.java	Mon Jul  6 16:36:19 2015
@@ -71,8 +71,6 @@
     @Override
     public void process(EventHeader event) {
         aida.tree().cd("/");
-        if (!event.hasCollection(GenericObject.class, trackTimeDataCollectionName))
-            return;
         if (!event.hasCollection(GenericObject.class, trackResidualsCollectionName))
             return;
           //check to see if this event is from the correct trigger (or "all");
@@ -94,12 +92,16 @@
                 }
         }
 
-        List<GenericObject> ttdList = event.get(GenericObject.class, trackTimeDataCollectionName);
-        for (GenericObject ttd : ttdList) {
-            int nResid = ttd.getNDouble();
-            for (int i = 1; i <= nResid; i++)
-                aida.histogram1D(plotDir + triggerType + "/"+timeresDir + "HalfModule " + i + " t Residual").fill(ttd.getDoubleVal(i - 1));//x is the double value in the generic object               
-        }
+        if (event.hasCollection(GenericObject.class, trackTimeDataCollectionName)) {
+            List<GenericObject> ttdList = event.get(GenericObject.class, trackTimeDataCollectionName);
+            for (GenericObject ttd : ttdList) {
+                int nResid = ttd.getNDouble();
+                for (int i = 1; i <= nResid; i++) {
+                    aida.histogram1D(plotDir + triggerType + "/" + timeresDir + "HalfModule " + i + " t Residual").fill(ttd.getDoubleVal(i - 1));//x is the double value in the generic object               
+                }
+            }
+        }
+        
         if (!event.hasCollection(GenericObject.class, gblStripClusterDataCollectionName))
             return;
         List<GenericObject> gblSCDList = event.get(GenericObject.class, gblStripClusterDataCollectionName);

Modified: java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TridentMonitoring.java
 =============================================================================
--- java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TridentMonitoring.java	(original)
+++ java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/TridentMonitoring.java	Mon Jul  6 16:36:19 2015
@@ -9,17 +9,14 @@
 import hep.physics.vec.Hep3Vector;
 import hep.physics.vec.VecOp;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.Map.Entry;
+import org.hps.recon.tracking.TrackUtils;
 import org.lcsim.event.EventHeader;
-import org.lcsim.event.LCRelation;
 import org.lcsim.event.ReconstructedParticle;
 import org.lcsim.event.RelationalTable;
 import org.lcsim.event.Track;
-import org.lcsim.event.TrackerHit;
 import org.lcsim.event.Vertex;
-import org.lcsim.event.base.BaseRelationalTable;
 import org.lcsim.geometry.Detector;
 
 /**
@@ -31,8 +28,6 @@
  */
 public class TridentMonitoring extends DataQualityMonitor {
 
-    private final String helicalTrackHitRelationsCollectionName = "HelicalTrackHitRelations";
-    private final String rotatedHelicalTrackHitRelationsCollectionName = "RotatedHelicalTrackHitRelations";
     private double ebeam = 1.05;
     String finalStateParticlesColName = "FinalStateParticles";
     String unconstrainedV0CandidatesColName = "UnconstrainedV0Candidates";
@@ -41,8 +36,7 @@
     String trackListName = "MatchedTracks";
     String[] fpQuantNames = {"nV0_per_Event", "avg_BSCon_mass", "avg_BSCon_Vx", "avg_BSCon_Vy", "avg_BSCon_Vz", "sig_BSCon_Vx", "sig_BSCon_Vy", "sig_BSCon_Vz", "avg_BSCon_Chi2"};
 
-    boolean debug = false;
-    private String plotDir = "TridentMonitoring/";
+    private final String plotDir = "TridentMonitoring/";
     IHistogram2D trackTime2D;
     IHistogram1D trackTimeDiff;
     IHistogram2D vertexMassMomentum;
@@ -54,6 +48,14 @@
     IHistogram1D vertexX;
     IHistogram1D vertexY;
     IHistogram1D vertexZ;
+    IHistogram1D vertexPx;
+    IHistogram1D vertexPy;
+    IHistogram1D vertexPz;
+    IHistogram1D vertexU;
+    IHistogram1D vertexV;
+//    IHistogram1D vertexW;
+    IHistogram2D vertexVZ;
+    IHistogram2D vertexZY;
 
     IHistogram1D deltaP;
     IHistogram1D deltaPRad;
@@ -95,6 +97,10 @@
     int nPassTrkCuts = 0;
 
     int nPassClusterCuts = 0;
+
+    public void setEbeam(double ebeam) {
+        this.ebeam = ebeam;
+    }
 
     @Override
     protected void detectorChanged(Detector detector) {
@@ -131,51 +137,60 @@
         vertexX = aida.histogram1D(plotDir + triggerType + "/" + "Vertex X Position (mm)", 100, -v0VxMax, v0VxMax);
         vertexY = aida.histogram1D(plotDir + triggerType + "/" + "Vertex Y Position (mm)", 100, -v0VyMax, v0VyMax);
         vertexZ = aida.histogram1D(plotDir + triggerType + "/" + "Vertex Z Position (mm)", 100, -v0VzMax, v0VzMax);
+        vertexPx = aida.histogram1D(plotDir + triggerType + "/" + "Vertex Px (GeV)", 100, -0.1, 0.1);
+        vertexPy = aida.histogram1D(plotDir + triggerType + "/" + "Vertex Py (GeV)", 100, -0.1, 0.1);
+        vertexPz = aida.histogram1D(plotDir + triggerType + "/" + "Vertex Pz (GeV)", 100, 0.0, v0PzMax);
+        vertexU = aida.histogram1D(plotDir + triggerType + "/" + "Vertex Px over Ptot (GeV)", 100, -0.1, 0.1);
+        vertexV = aida.histogram1D(plotDir + triggerType + "/" + "Vertex Py over Ptot (GeV)", 100, -0.1, 0.1);
+//        vertexW = aida.histogram1D(plotDir + triggerType + "/" + "Vertex Pz overPtot (GeV)", 100, 0.95, 1.0);
+        vertexVZ = aida.histogram2D(plotDir + triggerType + "/" + "Vertex Py over Ptot vs. Z", 100, -v0VzMax, v0VzMax, 100, -0.1, 0.1);
+        vertexZY = aida.histogram2D(plotDir + triggerType + "/" + "Vertex Z vs. Y", 100, -v0VyMax, v0VyMax, 100, -v0VzMax, v0VzMax);
     }
 
     @Override
     public void process(EventHeader event) {
         /*  make sure everything is there */
-        if (!event.hasCollection(ReconstructedParticle.class, finalStateParticlesColName))
-            return;
-        if (!event.hasCollection(ReconstructedParticle.class, unconstrainedV0CandidatesColName))
-            return;
-        if (!event.hasCollection(ReconstructedParticle.class, beamConV0CandidatesColName))
-            return;
-        if (!event.hasCollection(ReconstructedParticle.class, targetV0ConCandidatesColName))
-            return;
-        if (!event.hasCollection(Track.class, trackListName))
-            return;
+        if (!event.hasCollection(ReconstructedParticle.class, finalStateParticlesColName)) {
+            return;
+        }
+        if (!event.hasCollection(ReconstructedParticle.class, unconstrainedV0CandidatesColName)) {
+            return;
+        }
+        if (!event.hasCollection(ReconstructedParticle.class, beamConV0CandidatesColName)) {
+            return;
+        }
+        if (!event.hasCollection(ReconstructedParticle.class, targetV0ConCandidatesColName)) {
+            return;
+        }
+        if (!event.hasCollection(Track.class, trackListName)) {
+            return;
+        }
 
         //check to see if this event is from the correct trigger (or "all");
-        if (!matchTrigger(event))
-            return;
+        if (!matchTrigger(event)) {
+            return;
+        }
 
         nRecoEvents++;
 
-        RelationalTable hittostrip = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
-        List<LCRelation> hitrelations = event.get(LCRelation.class, helicalTrackHitRelationsCollectionName);
-        for (LCRelation relation : hitrelations)
-            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
-                hittostrip.add(relation.getFrom(), relation.getTo());
-
-        RelationalTable hittorotated = new BaseRelationalTable(RelationalTable.Mode.ONE_TO_ONE, RelationalTable.Weighting.UNWEIGHTED);
-        List<LCRelation> rotaterelations = event.get(LCRelation.class, rotatedHelicalTrackHitRelationsCollectionName);
-        for (LCRelation relation : rotaterelations)
-            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
-                hittorotated.add(relation.getFrom(), relation.getTo());
+        RelationalTable hitToStrips = TrackUtils.getHitToStripsTable(event);
+        RelationalTable hitToRotated = TrackUtils.getHitToRotatedTable(event);
 
         List<Track> trks = event.get(Track.class, trackListName);
         int ntracks = trks.size();
-        if (ntracks > nTrkMax || ntracks < 2)
-            return;
+        if (ntracks > nTrkMax || ntracks < 2) {
+            return;
+        }
         List<ReconstructedParticle> fspList = event.get(ReconstructedParticle.class, finalStateParticlesColName);
         int npos = 0;
-        for (ReconstructedParticle fsp : fspList)
-            if (fsp.getCharge() > 0)
+        for (ReconstructedParticle fsp : fspList) {
+            if (fsp.getCharge() > 0) {
                 npos++;
-        if (npos < 1 || npos > nPosMax)
-            return;
+            }
+        }
+        if (npos < 1 || npos > nPosMax) {
+            return;
+        }
 
         nPassBasicCuts++;//passed some basic event-level cuts...
 
@@ -185,53 +200,56 @@
 //  v0 & vertex-quality cuts
 //            Hep3Vector v0Mom = uncV0.getMomentum();
             Hep3Vector v0Mom = VecOp.add(uncV0.getParticles().get(1).getMomentum(), uncV0.getParticles().get(0).getMomentum());
-            if (v0Mom.z() > v0PzMax || v0Mom.z() < v0PzMin)
-                break;
-            if (Math.abs(v0Mom.y()) > v0PyMax)
-                break;
-            if (Math.abs(v0Mom.x()) > v0PxMax)
-                break;
+            if (v0Mom.z() > v0PzMax || v0Mom.z() < v0PzMin) {
+                continue;
+            }
+            if (Math.abs(v0Mom.y()) > v0PyMax) {
+                continue;
+            }
+            if (Math.abs(v0Mom.x()) > v0PxMax) {
+                continue;
+            }
             Hep3Vector v0Vtx = uncVert.getPosition();
-            if (Math.abs(v0Vtx.z()) > v0VzMax)
-                break;
-            if (Math.abs(v0Vtx.y()) > v0VyMax)
-                break;
-            if (Math.abs(v0Vtx.x()) > v0VxMax)
-                break;
+            if (Math.abs(v0Vtx.z()) > v0VzMax) {
+                continue;
+            }
+            if (Math.abs(v0Vtx.y()) > v0VyMax) {
+                continue;
+            }
+            if (Math.abs(v0Vtx.x()) > v0VxMax) {
+                continue;
+            }
 
             List<Track> tracks = new ArrayList<Track>();
             ReconstructedParticle electron = null, positron = null;
-            for (ReconstructedParticle particle : uncV0.getParticles())
-//                tracks.addAll(particle.getTracks());  //add add electron first, then positron...down below
-                if (particle.getCharge() > 0)
+            for (ReconstructedParticle particle : uncV0.getParticles()) //                tracks.addAll(particle.getTracks());  //add add electron first, then positron...down below
+            {
+                if (particle.getCharge() > 0) {
                     positron = particle;
-                else if (particle.getCharge() < 0)
+                } else if (particle.getCharge() < 0) {
                     electron = particle;
-                else
+                } else {
                     throw new RuntimeException("expected only electron and positron in vertex, got something with charge 0");
+                }
+            }
+            if (electron == null || positron == null) {
+                throw new RuntimeException("vertex needs e+ and e- but is missing one or both");
+            }
             tracks.add(electron.getTracks().get(0));
             tracks.add(positron.getTracks().get(0));
-            if (tracks.size() != 2)
+            if (tracks.size() != 2) {
                 throw new RuntimeException("expected two tracks in vertex, got " + tracks.size());
+            }
             List<Double> trackTimes = new ArrayList<Double>();
             for (Track track : tracks) {
-                int nStrips = 0;
-                double meanTime = 0;
-                for (TrackerHit hit : track.getTrackerHits()) {
-                    Collection<TrackerHit> htsList = hittostrip.allFrom(hittorotated.from(hit));
-                    for (TrackerHit hts : htsList) {
-                        nStrips++;
-                        meanTime += hts.getTime();
-                    }
-                }
-                meanTime /= nStrips;
-                trackTimes.add(meanTime);
+                trackTimes.add(TrackUtils.getTrackTime(track, hitToStrips, hitToRotated));
             }
             trackTime2D.fill(trackTimes.get(0), trackTimes.get(1));
             trackTimeDiff.fill(trackTimes.get(0) - trackTimes.get(1));
             boolean trackTimeDiffCut = Math.abs(trackTimes.get(0) - trackTimes.get(1)) < trkTimeDiff;
             boolean pCut = electron.getMomentum().magnitude() > trkPzMin && positron.getMomentum().magnitude() > trkPzMin;
             boolean pTotCut = uncV0.getMomentum().magnitude() > v0PzMin && uncV0.getMomentum().magnitude() < v0PzMax;
+//            if (electron.getMomentum().y()* positron.getMomentum().y()<0) continue;
             if (trackTimeDiffCut) {
                 vertexMassMomentum.fill(uncV0.getMomentum().magnitude(), uncV0.getMass());
                 vertexedTrackMomentum2D.fill(electron.getMomentum().magnitude(), positron.getMomentum().magnitude());
@@ -249,6 +267,14 @@
                     vertexX.fill(v0Vtx.x());
                     vertexY.fill(v0Vtx.y());
                     vertexZ.fill(v0Vtx.z());
+                    vertexPx.fill(uncV0.getMomentum().x());
+                    vertexPy.fill(uncV0.getMomentum().y());
+                    vertexPz.fill(uncV0.getMomentum().z());
+                    vertexU.fill(uncV0.getMomentum().x()/uncV0.getMomentum().magnitude());
+                    vertexV.fill(uncV0.getMomentum().y()/uncV0.getMomentum().magnitude());
+//                    vertexW.fill(uncV0.getMomentum().z()/uncV0.getMomentum().magnitude());
+                    vertexVZ.fill(v0Vtx.z(), uncV0.getMomentum().y()/uncV0.getMomentum().magnitude());
+                    vertexZY.fill(v0Vtx.y(), v0Vtx.z());
                 }
             }
 //            System.out.println(tarV0.getTracks())
@@ -258,8 +284,9 @@
     @Override
     public void printDQMData() {
         System.out.println("TridentMonitoring::printDQMData");
-        for (Entry<String, Double> entry : monitoredQuantityMap.entrySet())
+        for (Entry<String, Double> entry : monitoredQuantityMap.entrySet()) {
             System.out.println(entry.getKey() + " = " + entry.getValue());
+        }
         System.out.println("*******************************");
     }
 
@@ -278,8 +305,9 @@
     @Override
     public void printDQMStrings() {
         for (int i = 0; i < 9; i++)//TODO:  do this in a smarter way...loop over the map
-
+        {
             System.out.println("ALTER TABLE dqm ADD " + fpQuantNames[i] + " double;");
+        }
     }
 
     IFitResult fitVertexPosition(IHistogram1D h1d, IFitter fitter, double[] init, String range) {

Modified: java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/V0Monitoring.java
 =============================================================================
--- java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/V0Monitoring.java	(original)
+++ java/branches/HPSJAVA-488/analysis/src/main/java/org/hps/analysis/dataquality/V0Monitoring.java	Mon Jul  6 16:36:19 2015
@@ -17,21 +17,21 @@
 import java.util.Map.Entry;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import org.hps.recon.particle.HpsReconParticleDriver;
 import org.hps.recon.tracking.TrackUtils;
 import org.hps.recon.vertexing.BilliorTrack;
 import org.hps.recon.vertexing.BilliorVertex;
 import org.hps.recon.vertexing.BilliorVertexer;
 import org.lcsim.event.EventHeader;
 import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.RelationalTable;
 import org.lcsim.event.Track;
 import org.lcsim.event.Vertex;
 import org.lcsim.geometry.Detector;
 import org.lcsim.recon.tracking.seedtracker.SeedTrack;
 
 /**
- * DQM driver V0 particles (i.e. e+e- pars) plots
- * things like number of vertex position an mass
+ * DQM driver V0 particles (i.e. e+e- pars) plots things like number of vertex
+ * position an mass
  *
  * @author mgraham on May 14, 2014
  *
@@ -54,6 +54,35 @@
     double sumVz = 0.0;
     double sumChi2 = 0.0;
 
+    /*  V0 Quantities   */
+    /*  Mass, vertex, chi^2 of fit */
+    /*  unconstrained */
+    IHistogram1D unconMass;
+    IHistogram1D unconVx;
+    IHistogram1D unconVy;
+    IHistogram1D unconVz;
+    IHistogram1D unconChi2;
+    /* beamspot constrained */
+
+    IHistogram1D nV0;
+
+    IHistogram1D v0Time;
+    IHistogram1D v0Dt;
+    IHistogram2D trigTimeV0Time;
+    IHistogram1D trigTime;
+
+    IHistogram1D bsconMass;
+    IHistogram1D bsconVx;
+    IHistogram1D bsconVy;
+    IHistogram1D bsconVz;
+    IHistogram1D bsconChi2;
+    /* target constrained */
+    IHistogram1D tarconMass;
+    IHistogram1D tarconVx;
+    IHistogram1D tarconVy;
+    IHistogram1D tarconVz;
+    IHistogram1D tarconChi2;
+
     IHistogram2D pEleVspPos;
     IHistogram2D pEleVspPosWithCut;
     IHistogram2D pyEleVspyPos;
@@ -90,8 +119,7 @@
     IHistogram1D sumChargeHisto;
     IHistogram1D numChargeHisto;
 
-    boolean debug = false;
-    private String plotDir = "V0Monitoring/";
+    private final String plotDir = "V0Monitoring/";
 
     double beamEnergy = 1.05; //GeV
     double maxFactor = 1.25;
@@ -114,25 +142,30 @@
         /*  V0 Quantities   */
         /*  Mass, vertex, chi^2 of fit */
         /*  unconstrained */
-        IHistogram1D unconMass = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Mass (GeV)", 100, 0, 0.200);
-        IHistogram1D unconVx = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Vx (mm)", 50, -10, 10);
-        IHistogram1D unconVy = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Vy (mm)", 50, -10, 10);
-        IHistogram1D unconVz = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Vz (mm)", 50, -50, 50);
-        IHistogram1D unconChi2 = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Chi2", 25, 0, 25);
+        unconMass = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Mass (GeV)", 100, 0, 0.200);
+        unconVx = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Vx (mm)", 50, -10, 10);
+        unconVy = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Vy (mm)", 50, -10, 10);
+        unconVz = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Vz (mm)", 50, -50, 50);
+        unconChi2 = aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Chi2", 25, 0, 25);
         /* beamspot constrained */
 
-        IHistogram1D nV0 = aida.histogram1D(plotDir + triggerType + "/" + "Number of V0 per event", 10, 0, 10);
-        IHistogram1D bsconMass = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Mass (GeV)", 100, 0, 0.200);
-        IHistogram1D bsconVx = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vx (mm)", 50, -10, 10);
-        IHistogram1D bsconVy = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vy (mm)", 50, -10, 10);
-        IHistogram1D bsconVz = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vz (mm)", 50, -50, 50);
-        IHistogram1D bsconChi2 = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Chi2", 25, 0, 25);
+        nV0 = aida.histogram1D(plotDir + triggerType + "/" + "Number of V0 per event", 10, 0, 10);
+        v0Time = aida.histogram1D(plotDir + triggerType + "/" + "V0 mean time", 100, -25, 25);
+        v0Dt = aida.histogram1D(plotDir + triggerType + "/" + "V0 time difference", 100, -25, 25);
+        trigTimeV0Time = aida.histogram2D(plotDir + triggerType + "/" + "Trigger phase vs. V0 mean time", 100, -25, 25, 6, 0, 24);
+        trigTime = aida.histogram1D(plotDir + triggerType + "/" + "Trigger phase", 6, 0, 24);
+
+        bsconMass = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Mass (GeV)", 100, 0, 0.200);
+        bsconVx = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vx (mm)", 50, -10, 10);
+        bsconVy = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vy (mm)", 50, -10, 10);
+        bsconVz = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vz (mm)", 50, -50, 50);
+        bsconChi2 = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Chi2", 25, 0, 25);
         /* target constrained */
-        IHistogram1D tarconMass = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Mass (GeV)", 100, 0, 0.200);
-        IHistogram1D tarconVx = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Vx (mm)", 50, -1, 1);
-        IHistogram1D tarconVy = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Vy (mm)", 50, -1, 1);
-        IHistogram1D tarconVz = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Vz (mm)", 50, -10, 10);
-        IHistogram1D tarconChi2 = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Chi2", 25, 0, 25);
+        tarconMass = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Mass (GeV)", 100, 0, 0.200);
+        tarconVx = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Vx (mm)", 50, -1, 1);
+        tarconVy = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Vy (mm)", 50, -1, 1);
+        tarconVz = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Vz (mm)", 50, -10, 10);
+        tarconChi2 = aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Chi2", 25, 0, 25);
         pEleVspPos = aida.histogram2D(plotDir + triggerType + "/" + "P(e) vs P(p)", 50, 0, beamEnergy * maxFactor, 50, 0, beamEnergy * maxFactor);
         pEleVspPosWithCut = aida.histogram2D(plotDir + triggerType + "/" + "P(e) vs P(p): Radiative", 50, 0, beamEnergy * maxFactor, 50, 0, beamEnergy * maxFactor);
         pyEleVspyPos = aida.histogram2D(plotDir + triggerType + "/" + "Py(e) vs Py(p)", 50, -0.04, 0.04, 50, -0.04, 0.04);
@@ -171,31 +204,39 @@
     @Override
     public void process(EventHeader event) {
         /*  make sure everything is there */
-        if (!event.hasCollection(ReconstructedParticle.class, finalStateParticlesColName))
+        if (!event.hasCollection(ReconstructedParticle.class, finalStateParticlesColName)) {
             return;
-        if (!event.hasCollection(ReconstructedParticle.class, unconstrainedV0CandidatesColName))
+        }
+        if (!event.hasCollection(ReconstructedParticle.class, unconstrainedV0CandidatesColName)) {
             return;
-        if (!event.hasCollection(ReconstructedParticle.class, beamConV0CandidatesColName))
+        }
+        if (!event.hasCollection(ReconstructedParticle.class, beamConV0CandidatesColName)) {
             return;
-        if (!event.hasCollection(ReconstructedParticle.class, targetV0ConCandidatesColName))
+        }
+        if (!event.hasCollection(ReconstructedParticle.class, targetV0ConCandidatesColName)) {
             return;
+        }
 
         //check to see if this event is from the correct trigger (or "all");
-        if (!matchTrigger(event))
+        if (!matchTrigger(event)) {
             return;
+        }
 
         nRecoEvents++;
+
+        RelationalTable hitToStrips = TrackUtils.getHitToStripsTable(event);
+        RelationalTable hitToRotated = TrackUtils.getHitToRotatedTable(event);
 
         List<ReconstructedParticle> unonstrainedV0List = event.get(ReconstructedParticle.class, unconstrainedV0CandidatesColName);
         for (ReconstructedParticle uncV0 : unonstrainedV0List) {
             Vertex uncVert = uncV0.getStartVertex();
-            aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Vx (mm)").fill(uncVert.getPosition().x());
-            aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Vy (mm)").fill(uncVert.getPosition().y());
-            aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Vz (mm)").fill(uncVert.getPosition().z());
-            aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Mass (GeV)").fill(uncV0.getMass());
-            aida.histogram1D(plotDir + triggerType + "/" + "Unconstrained Chi2").fill(uncVert.getChi2());
-
-            aida.histogram2D(plotDir + triggerType + "/" + "Mass vs Vz").fill(uncV0.getMass(), uncVert.getPosition().z());
+            unconVx.fill(uncVert.getPosition().x());
+            unconVy.fill(uncVert.getPosition().y());
+            unconVz.fill(uncVert.getPosition().z());
+            unconMass.fill(uncV0.getMass());
+            unconChi2.fill(uncVert.getChi2());
+
+            massVsVtxZ.fill(uncV0.getMass(), uncVert.getPosition().z());
             VtxXVsVtxZ.fill(uncVert.getPosition().x(), uncVert.getPosition().z());
             VtxYVsVtxZ.fill(uncVert.getPosition().y(), uncVert.getPosition().z());
             VtxXVsVtxY.fill(uncVert.getPosition().x(), uncVert.getPosition().y());
@@ -222,23 +263,33 @@
             }
             double pe = ele.getMomentum().magnitude();
             double pp = pos.getMomentum().magnitude();
-            aida.histogram2D(plotDir + triggerType + "/" + "P(e) vs P(p)").fill(pe, pp);
-            aida.histogram2D(plotDir + triggerType + "/" + "Px(e) vs Px(p)").fill(ele.getMomentum().x(), pos.getMomentum().x());
-            aida.histogram2D(plotDir + triggerType + "/" + "Py(e) vs Py(p)").fill(ele.getMomentum().y(), pos.getMomentum().y());
+            pEleVspPos.fill(pe, pp);
+            pxEleVspxPos.fill(ele.getMomentum().x(), pos.getMomentum().x());
+            pyEleVspyPos.fill(ele.getMomentum().y(), pos.getMomentum().y());
             if (pe < v0MaxPCut && pp < v0MaxPCut && (pe + pp) > v0ESumMinCut && (pe + pp) < v0ESumMaxCut)//enrich radiative-like events
-                aida.histogram2D(plotDir + triggerType + "/" + "P(e) vs P(p): Radiative").fill(pe, pp);
+            {
+                pEleVspPosWithCut.fill(pe, pp);
+            }
+
+            double eleT = TrackUtils.getTrackTime(ele.getTracks().get(0), hitToStrips, hitToRotated);
+            double posT = TrackUtils.getTrackTime(pos.getTracks().get(0), hitToStrips, hitToRotated);
+            double meanT = (eleT + posT) / 2.0;
+            v0Time.fill(meanT);
+            v0Dt.fill(eleT-posT);
+            trigTimeV0Time.fill(meanT, event.getTimeStamp() % 24);
+            trigTime.fill(event.getTimeStamp() % 24);
         }
 
         List<ReconstructedParticle> beamConstrainedV0List = event.get(ReconstructedParticle.class, beamConV0CandidatesColName);
-        aida.histogram1D(plotDir + triggerType + "/" + "Number of V0 per event").fill(beamConstrainedV0List.size());
+        nV0.fill(beamConstrainedV0List.size());
         for (ReconstructedParticle bsV0 : beamConstrainedV0List) {
             nTotV0++;
             Vertex bsVert = bsV0.getStartVertex();
-            aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vx (mm)").fill(bsVert.getPosition().x());
-            aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vy (mm)").fill(bsVert.getPosition().y());
-            aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vz (mm)").fill(bsVert.getPosition().z());
-            aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Mass (GeV)").fill(bsV0.getMass());
-            aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Chi2").fill(bsVert.getChi2());
+            bsconVx.fill(bsVert.getPosition().x());
+            bsconVy.fill(bsVert.getPosition().y());
+            bsconVz.fill(bsVert.getPosition().z());
+            bsconMass.fill(bsV0.getMass());
+            bsconChi2.fill(bsVert.getChi2());
             sumMass += bsV0.getMass();
             sumVx += bsVert.getPosition().x();
             sumVy += bsVert.getPosition().y();
@@ -249,32 +300,36 @@
         List<ReconstructedParticle> targetConstrainedV0List = event.get(ReconstructedParticle.class, targetV0ConCandidatesColName);
         for (ReconstructedParticle tarV0 : targetConstrainedV0List) {
             Vertex tarVert = tarV0.getStartVertex();
-            aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Vx (mm)").fill(tarVert.getPosition().x());
-            aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Vy (mm)").fill(tarVert.getPosition().y());
-            aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Vz (mm)").fill(tarVert.getPosition().z());
-            aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Mass (GeV)").fill(tarV0.getMass());
-            aida.histogram1D(plotDir + triggerType + "/" + "Target Constrained Chi2").fill(tarVert.getChi2());
+            tarconVx.fill(tarVert.getPosition().x());
+            tarconVy.fill(tarVert.getPosition().y());
+            tarconVz.fill(tarVert.getPosition().z());
+            tarconMass.fill(tarV0.getMass());
+            tarconChi2.fill(tarVert.getChi2());
         }
         List<ReconstructedParticle> finalStateParticles = event.get(ReconstructedParticle.class, finalStateParticlesColName);
-        if (debug)
+        if (debug) {
             System.out.println("This events has " + finalStateParticles.size() + " final state particles");
+        }
 
         ReconstructedParticle ele1 = null;
         ReconstructedParticle ele2 = null;
         int sumCharge = 0;
         int numChargedParticles = 0;
         for (ReconstructedParticle fsPart : finalStateParticles) {
-            if (debug)
+            if (debug) {
                 System.out.println("PDGID = " + fsPart.getParticleIDUsed() + "; charge = " + fsPart.getCharge() + "; pz = " + fsPart.getMomentum().x());
+            }
             double charge = fsPart.getCharge();
             sumCharge += charge;
             if (charge != 0) {
                 numChargedParticles++;
-                if (charge < 1)
-                    if (ele1 == null)
+                if (charge < 1) {
+                    if (ele1 == null) {
                         ele1 = fsPart;
-                    else
+                    } else if (!hasSharedStrips(ele1, fsPart, hitToStrips, hitToRotated)) {
                         ele2 = fsPart;
+                    }
+                }
             }
         }
         sumChargeHisto.fill(sumCharge);
@@ -339,8 +394,9 @@
     @Override
     public void printDQMData() {
         System.out.println("V0Monitoring::printDQMData");
-        for (Entry<String, Double> entry : monitoredQuantityMap.entrySet())
+        for (Entry<String, Double> entry : monitoredQuantityMap.entrySet()) {
             System.out.println(entry.getKey() + " = " + entry.getValue());
+        }
         System.out.println("*******************************");
     }
 
@@ -353,9 +409,6 @@
         IAnalysisFactory analysisFactory = IAnalysisFactory.create();
         IFitFactory fitFactory = analysisFactory.createFitFactory();
         IFitter fitter = fitFactory.createFitter("chi2");
-        IHistogram1D bsconVx = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vx (mm)");
-        IHistogram1D bsconVy = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vy (mm)");
-        IHistogram1D bsconVz = aida.histogram1D(plotDir + triggerType + "/" + "BS Constrained Vz (mm)");
         double[] init = {50.0, 0.0, 0.2, 1.0, 0.0};
         IFitResult resVx = fitVertexPosition(bsconVx, fitter, init, "range=\"(-0.5,0.5)\"");
         double[] init2 = {50.0, 0.0, 0.04, 1.0, 0.0};
@@ -368,8 +421,9 @@
             double[] parsVy = resVy.fittedParameters();
             double[] parsVz = resVz.fittedParameters();
 
-            for (int i = 0; i < 5; i++)
+            for (int i = 0; i < 5; i++) {
                 System.out.println("Vertex Fit Parameters:  " + resVx.fittedParameterNames()[i] + " = " + parsVx[i] + "; " + parsVy[i] + "; " + parsVz[i]);
+            }
 
             IPlotter plotter = analysisFactory.createPlotterFactory().create("Vertex Position");
             plotter.createRegions(1, 3);
@@ -383,12 +437,13 @@
             plotter.region(1).plot(resVy.fittedFunction());
             plotter.region(2).plot(bsconVz);
             plotter.region(2).plot(resVz.fittedFunction());
-            if (outputPlots)
+            if (outputPlots) {
                 try {
                     plotter.writeToFile(outputPlotDir + "vertex.png");
                 } catch (IOException ex) {
                     Logger.getLogger(V0Monitoring.class.getName()).log(Level.SEVERE, null, ex);
                 }
+            }
 
 //        monitoredQuantityMap.put(fpQuantNames[2], sumVx / nTotV0);
 //        monitoredQuantityMap.put(fpQuantNames[3], sumVy / nTotV0);
@@ -409,7 +464,9 @@
     @Override
     public void printDQMStrings() {
         for (int i = 0; i < 9; i++)//TODO:  do this in a smarter way...loop over the map
+        {
             System.out.println("ALTER TABLE dqm ADD " + fpQuantNames[i] + " double;");
+        }
     }
 
     IFitResult fitVertexPosition(IHistogram1D h1d, IFitter fitter, double[] init, String range
@@ -423,14 +480,6 @@
         return ifr;
     }
 
-    private double getMomentum(Track trk) {
-
-        double px = trk.getTrackStates().get(0).getMomentum()[0];
-        double py = trk.getTrackStates().get(0).getMomentum()[1];
-        double pz = trk.getTrackStates().get(0).getMomentum()[2];
-        return Math.sqrt(px * px + py * py + pz * pz);
-    }
-
     private BilliorVertex fitVertex(BilliorTrack electron, BilliorTrack positron) {
         // Create a vertex fitter from the magnetic field.
         double bField = 0.24;
@@ -454,4 +503,11 @@
         return vtxFitter.fitVertex(billiorTracks);
     }
 
+    private static boolean hasSharedStrips(ReconstructedParticle vertex, RelationalTable hittostrip, RelationalTable hittorotated) {
+        return hasSharedStrips(vertex.getParticles().get(0), vertex.getParticles().get(1), hittostrip, hittorotated);
+    }
+
+    private static boolean hasSharedStrips(ReconstructedParticle fs1, ReconstructedParticle fs2, RelationalTable hittostrip, RelationalTable hittorotated) {
+        return TrackUtils.hasSharedStrips(fs1.getTracks().get(0), fs2.getTracks().get(0), hittostrip, hittorotated);
+    }
 }

Modified: java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/svt/SvtBiasConditionsLoader.java
 =============================================================================
--- java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/svt/SvtBiasConditionsLoader.java	(original)
+++ java/branches/HPSJAVA-488/conditions/src/main/java/org/hps/conditions/svt/SvtBiasConditionsLoader.java	Mon Jul  6 16:36:19 2015
@@ -3,17 +3,14 @@
  */
 package org.hps.conditions.svt;
 
-import hep.aida.IDataPoint;
-import hep.aida.IDataPointSet;
-import hep.aida.IDataPointSetFactory;
-import hep.aida.IPlotter;
-import hep.aida.IPlotterStyle;
+import hep.aida.*;
 
 import java.io.File;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -27,8 +24,8 @@
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.cli.PosixParser;
+import org.hps.conditions.api.ConditionsObjectException;
 import org.hps.conditions.api.ConditionsRecord;
-import org.hps.conditions.api.DatabaseObjectException;
 import org.hps.conditions.database.DatabaseConditionsManager;
 import org.hps.conditions.run.RunRange;
 import org.hps.conditions.run.RunSpreadsheet;
@@ -38,6 +35,7 @@
 import org.hps.conditions.svt.SvtBiasMyaDumpReader.SvtBiasMyaRange;
 import org.hps.conditions.svt.SvtBiasMyaDumpReader.SvtBiasMyaRanges;
 import org.hps.conditions.svt.SvtBiasMyaDumpReader.SvtBiasRunRange;
+import org.hps.conditions.svt.SvtTimingConstants.SvtTimingConstantsCollection;
 import org.hps.util.BasicLogFormatter;
 import org.lcsim.util.aida.AIDA;
 import org.lcsim.util.log.LogUtil;
@@ -294,17 +292,21 @@
                 logger.info("No bias range for run " + range.getRun().getRun());
                 continue;
             }
-                       
+            
+            int collectionId = -1;
+            try {
+                collectionId = MANAGER.addCollection("svt_bias_constants", "whatever that is fine","run ranges for SVT HV bias ON");
+            } catch (SQLException e1) {
+               throw new RuntimeException(e1);
+            }
+            
             //create a collection
             SvtBiasConstantCollection collection = new SvtBiasConstantCollection();
-            int collectionId = -1;
             try {
-                collectionId = MANAGER.getCollectionId(collection, "run ranges for SVT HV bias ON");
-            } catch (SQLException e1) {
-               throw new RuntimeException(e1);
-            }
-
-            collection.setCollectionId(collectionId);
+                collection.setCollectionId(collectionId);
+            } catch (ConditionsObjectException e1) {
+                throw new RuntimeException("cant set collection id",e1);
+            }
             
             final ConditionsRecord condition = new ConditionsRecord();
             condition.setFieldValue("run_start", rundata.getRun());
@@ -315,8 +317,7 @@
             condition.setFieldValue("created", new Date());
             condition.setFieldValue("created_by", System.getProperty("user.name"));            
             condition.setFieldValue("collection_id", collectionId);
-               
-            try {
+            
             for (SvtBiasMyaRange biasRange : range.getRanges()) {
                 //create a constant and add to the collection
                 final SvtBiasConstant constant = new SvtBiasConstant();
@@ -327,9 +328,7 @@
                 
                 logger.info(condition.toString());
             }
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
+
 
             try {
                 try {
@@ -339,7 +338,7 @@
                 }
                 condition.insert();
 
-            } catch (DatabaseObjectException | SQLException e) {
+            } catch (ConditionsObjectException e) {
                 throw new RuntimeException(e);
             }
             

Modified: java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/AlignmentCorrection.java
 =============================================================================
--- java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/AlignmentCorrection.java	(original)
+++ java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/AlignmentCorrection.java	Mon Jul  6 16:36:19 2015
@@ -7,6 +7,7 @@
 
 import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
+import org.jdom.Element;
 
 /**
  * Class containing the final translation and rotation correction from alignment.
@@ -15,6 +16,7 @@
  *
  */
 public class AlignmentCorrection {
+    private Element node = null;
     private Rotation rotation = null;
     private Hep3Vector translation = null;
     private List<MilleParameter> milleParameters = null;
@@ -53,6 +55,11 @@
     public List<MilleParameter> getMilleParameters(){
         return milleParameters;
     }
-     
+    public void setNode(Element node) {
+        this.node = node;
+    }
+    public Element getNode() {
+        return node;
+    }
 
 }

Modified: java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTestRunTracker2014GeometryDefinition.java
 =============================================================================
--- java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTestRunTracker2014GeometryDefinition.java	(original)
+++ java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTestRunTracker2014GeometryDefinition.java	Mon Jul  6 16:36:19 2015
@@ -69,7 +69,7 @@
         CSupport cSupport = new CSupport("c_support", base);
         surveyVolumes.add(cSupport);        
         
-        AlignmentCorrection alignmentCorrectionSupportBottom = getSupportAlignmentCorrection(false);
+        AlignmentCorrection alignmentCorrectionSupportBottom = getL13UChannelAlignmentCorrection(false);
         SupportBottom supportBottom = new SupportBottom("support_bottom", base, alignmentCorrectionSupportBottom, cSupport);
         surveyVolumes.add(supportBottom);
         // The support survey positions are now with respect to its mother and not the reference coord. system.
@@ -78,7 +78,7 @@
         SupportPlateBottom supportPlateBottom = new SupportPlateBottom("support_plate_bottom", base, supportBottom, "Aluminum");
         surveyVolumes.add(supportPlateBottom);        
         
-        AlignmentCorrection alignmentCorrectionSupportTop = getSupportAlignmentCorrection(true);
+        AlignmentCorrection alignmentCorrectionSupportTop = getL13UChannelAlignmentCorrection(true);
         SupportTop supportTop = new SupportTop("support_top", base, alignmentCorrectionSupportTop, cSupport);
         surveyVolumes.add(supportTop);
         

Modified: java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTracker2014GeometryDefinition.java
 =============================================================================
--- java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTracker2014GeometryDefinition.java	(original)
+++ java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTracker2014GeometryDefinition.java	Mon Jul  6 16:36:19 2015
@@ -46,6 +46,18 @@
 
         if(isDebug()) System.out.printf("%s: constructing the geometry objects\n", this.getClass().getSimpleName());
 
+        
+        // Create alignment correction objects
+        // THis is really a ugly approach with MP corrections initialized before and 
+        // the survey corrections based on the XML node
+        // FIX THIS! //TODO
+        AlignmentCorrection alignmentCorrections = new AlignmentCorrection();
+        alignmentCorrections.setNode(node);
+        AlignmentCorrection supBotCorr = getL13UChannelAlignmentCorrection(false);
+        supBotCorr.setNode(node);
+        AlignmentCorrection supTopCorr = this.getL13UChannelAlignmentCorrection(true);
+        supTopCorr.setNode(node);
+        
         // Build the geometry from the basic building blocks in the geometry definition class
         // Keep the order correct.
         // Each item has knowledge of its mother but not its daughters
@@ -60,47 +72,38 @@
 
         SvtBoxBasePlate svtBoxBasePlate = new SvtBoxBasePlate("base_plate",svtBox,null);
         surveyVolumes.add(svtBoxBasePlate);
-        
-        //SupportRing supportRing = new SupportRing("c_support", svtBox, null, svtBoxBasePlate); 
-        //surveyVolumes.add(supportRing);
-       
-//        AlignmentCorrection supBotCorr = this.getSupportAlignmentCorrection(false);
-//        SupportRingL13BottomKinMount supportRingKinL13Bottom = new SupportRingL13BottomKinMount("c_support_kin_L13b", svtBox, supBotCorr, supportRing); 
-//        surveyVolumes.add(supportRingKinL13Bottom);
-        
-        AlignmentCorrection supBotCorr = this.getSupportAlignmentCorrection(false);
+                
+        
+        
         SupportRingL13BottomKinMount supportRingKinL13Bottom = new SupportRingL13BottomKinMount("c_support_kin_L13b", svtBox, supBotCorr); 
         surveyVolumes.add(supportRingKinL13Bottom);
         
         
-        UChannelL13 uChannelL13Bottom = new UChannelL13Bottom("support_bottom_L13", svtBox, null, supportRingKinL13Bottom); 
+        UChannelL13 uChannelL13Bottom = new UChannelL13Bottom("support_bottom_L13", svtBox, alignmentCorrections, supportRingKinL13Bottom); 
         surveyVolumes.add(uChannelL13Bottom);
         
         UChannelL13Plate uChannelL13BottomPlate = new UChannelL13BottomPlate("support_plate_bottom_L13", svtBox, null, uChannelL13Bottom); 
         surveyVolumes.add(uChannelL13BottomPlate);
 
-//        AlignmentCorrection supTopCorr = this.getSupportAlignmentCorrection(true);
-//        SupportRingL13TopKinMount supportRingKinL13Top = new SupportRingL13TopKinMount("c_support_kin_L13t", svtBox, supTopCorr, supportRing); 
-//        surveyVolumes.add(supportRingKinL13Top);
-
-        AlignmentCorrection supTopCorr = this.getSupportAlignmentCorrection(true);
+        
         SupportRingL13TopKinMount supportRingKinL13Top = new SupportRingL13TopKinMount("c_support_kin_L13t", svtBox, supTopCorr); 
         surveyVolumes.add(supportRingKinL13Top);
 
         
-        UChannelL13Top uChannelL13Top = new UChannelL13Top("support_top_L13", svtBox, null, supportRingKinL13Top); 
+        
+        UChannelL13Top uChannelL13Top = new UChannelL13Top("support_top_L13", svtBox, alignmentCorrections, supportRingKinL13Top); 
         surveyVolumes.add(uChannelL13Top);
         
         UChannelL13Plate uChannelL13TopPlate = new UChannelL13TopPlate("support_plate_top_L13", svtBox, null, uChannelL13Top); 
         surveyVolumes.add(uChannelL13TopPlate);
         
-        UChannelL46 uChannelL46Bottom = new UChannelL46Bottom("support_bottom_L46", svtBox, null);
+        UChannelL46 uChannelL46Bottom = new UChannelL46Bottom("support_bottom_L46", svtBox, alignmentCorrections);
         surveyVolumes.add(uChannelL46Bottom);
         
         UChannelL46Plate uChannelL46BottomPlate = new UChannelL46BottomPlate("support_plate_bottom_L46", svtBox, null, uChannelL46Bottom);
         surveyVolumes.add(uChannelL46BottomPlate);
 
-        UChannelL46 uChannelL46Top = new UChannelL46Top("support_top_L46", svtBox, null);
+        UChannelL46 uChannelL46Top = new UChannelL46Top("support_top_L46", svtBox, alignmentCorrections);
         surveyVolumes.add(uChannelL46Top);
         
         UChannelL46Plate uChannelL46TopPlate = new UChannelL46TopPlate("support_plate_top_L46", svtBox, null, uChannelL46Top);
@@ -114,8 +117,8 @@
             }
         }       
 
-        //System.out.printf("%s: Constructed %d geometry objects\n", this.getClass().getSimpleName(), surveyVolumes.size());
-        //System.out.printf("%s: Constructed %d module bundles\n", this.getClass().getSimpleName(),modules.size());        
+        System.out.printf("%s: Constructed %d geometry objects\n", this.getClass().getSimpleName(), surveyVolumes.size());
+        System.out.printf("%s: Constructed %d module bundles\n", this.getClass().getSimpleName(),modules.size());        
 
         if(isDebug()) {
             System.out.printf("%s: DONE constructing the geometry objects\n", this.getClass().getSimpleName());
@@ -123,18 +126,23 @@
             for(SurveyVolume bg : surveyVolumes) {
                 System.out.printf("-------\n%s\n", bg.toString());
             }
+        }
+        if(isDebug()) {
             System.out.printf("%s: List of the module bundles built\n", this.getClass().getSimpleName());
             for(BaseModuleBundle bundle : this.modules) {
                 bundle.print();
             }
-            
-        }
-
-    }
-
-    
-    /**
-     * @SurveyVolume volume defining the pair spectrometer (PS) vacuum chamber
+        }
+        
+        
+        
+        
+
+    }
+
+    
+    /**
+     * {@link SurveyVolume} volume defining the pair spectrometer (PS) vacuum chamber
      * Reference: tracking volume coordinate system
      * Origin: same as reference
      * Orientation:  u - points in x direction (towards positron side), v - points upstream
@@ -170,7 +178,7 @@
     
     
     /**
-     * @SurveyVolume volume defining the SVT box envelope 
+     * {@link SurveyVolume} volume defining the SVT box envelope 
      * Reference: PS vacuum chamber coordinate system. Note that the PS vacuum chamber box is placed w.r.t. this box and the target positions.
      * Origin: intersection of midplanes vertically and horizontally
      * Orientation: same as reference
@@ -214,8 +222,8 @@
     
     
     /**
-     * @SurveyVolume volume defining the base plate of the SVT box.
-     * Reference: @SvtBox  coordinate system.
+     * {@link SurveyVolume} volume defining the base plate of the SVT box.
+     * Reference: {@link SvtBox}  coordinate system.
      * Origin: surface of base plate intersection with center of hole for adjustment screw on positron side
      * Orientation: same as reference
      * 
@@ -262,7 +270,7 @@
     
     
     /**
-     * @SurveyVolume volume defining the coordinate system of the support ring
+     * {@link SurveyVolume} volume defining the coordinate system of the support ring
      *  Reference: @SvtBoxBasePlate
      *  Origin: pin position of support ring (electron side)
      *  Orientation: slot position is vee position (positron side) i.e u points towards the positron side and v in the upstream beam direction
@@ -309,7 +317,7 @@
     
     
     /**
-     * Abstract @SurveyVolume volume defining a coordinate system from the kinematic mount positions for support channels
+     * Abstract {@link SurveyVolume} volume defining a coordinate system from the kinematic mount positions for support channels
      *  
      * @author Per Hansson Adrian <[log in to unmask]>
      *
@@ -346,10 +354,10 @@
     }
     
     /**
-     * @SurveyVolume volume defining a coordinate system from the kinematic mount positions for support channels
-     *  Reference: {@SvtBox} coordinate system
+     * {@link SurveyVolume} volume defining a coordinate system from the kinematic mount positions for support channels
+     *  Reference: {@link SvtBox} coordinate system
      *  Origin: cone mount (it's on the electron side)
-     *  Orientation: ball is cone mount, slot mount is vee position and flat is along beamline pointing upstream
+     *  Orientation: ball is cone mount, slot mount is vee position and flat is along beam line pointing upstream
      *  
      * @author Per Hansson Adrian <[log in to unmask]>
      *
@@ -367,28 +375,11 @@
         protected double getKinMountVerticalPos() {
             return kin_mount_pos_z;
         }
-
-//        protected void setPos() {
-//            final double ball_pos_x = (7.0 - 5.444) *inch;
-//            final double ball_pos_y = 0.574*inch;
-//            final double ball_pos_z = SupportRing.plateThickness + kin_mount_offset_vertically;
-//            ballPos = new BasicHep3Vector(ball_pos_x, ball_pos_y, ball_pos_z);
-//            
-//            final double vee_pos_x = (2*7.0)*inch;
-//            final double vee_pos_y = ball_pos_y;
-//            final double vee_pos_z = ball_pos_z;
-//            veePos = new BasicHep3Vector(vee_pos_x, vee_pos_y, vee_pos_z);
-//            
-//            final double flat_pos_x = ball_pos_x;
-//            final double flat_pos_y = ball_pos_y + 1.0; // random distance
-//            final double flat_pos_z = ball_pos_z;
-//            flatPos = new BasicHep3Vector(flat_pos_x,flat_pos_y,flat_pos_z);
-//        }
-        
-    }
-    
-    /**
-     * @SurveyVolume volume defining a coordinate system from the kinematic mount positions for support channels
+        
+    }
+    
+    /**
+     * {@link SurveyVolume} volume defining a coordinate system from the kinematic mount positions for support channels
      *  Reference: @SupportRing coordinate system
      *  Origin: cone mount (it's on the electron side)
      *  Orientation: ball is cone mount, slot mount is vee position and flat is along beamline pointing upstream
@@ -430,7 +421,7 @@
     
     
     /**
-     * Abstract @SurveyVolume volume defining the coordinate system of the L1-3 u-channels 
+     * Abstract {@link SurveyVolume} volume defining the coordinate system of the L1-3 u-channels 
      *  
      *  @author Per Hansson Adrian <[log in to unmask]>
      */
@@ -460,8 +451,8 @@
     }
     
     /**
-     * @SurveyVolume volume defining the coordinate system of the bottom L1-3 u-channel 
-     *  Reference: SupportRingL13BottomKinMount coordinate system
+     * {@link SurveyVolume} volume defining the coordinate system of the bottom L1-3 u-channel 
+     *  Reference: {@link SupportRingL13BottomKinMount} coordinate system
      *  Origin: midpoint between upstream survey cones
      *  Orientation: u - width pointing towards electron side, v - pointing along the U-channel in the beam direction
      *  
@@ -520,7 +511,7 @@
         protected static final Hep3Vector fwd_right = new BasicHep3Vector(-6.493, 9.353,-.332);
         protected static final Hep3Vector bwd_right = new BasicHep3Vector(-6.253, 1.483, -.332);
         protected static final Hep3Vector fwd_left = new BasicHep3Vector( 2.836, 9.638, -.332);
-        protected static final Hep3Vector bwd_left = new BasicHep3Vector(3.076, 1.767, -.332);
+        //protected static final Hep3Vector bwd_left = new BasicHep3Vector(3.076, 1.767, -.332);
         
         protected static Hep3Vector getVeeOffset() {
             return  VecOp.mult(0.5,VecOp.sub(fwd_right, fwd_left));
@@ -531,41 +522,10 @@
     }
     
     
-    
-    
-    
-    
-//    public static class UChannelL13Bottom extends UChannelL13 {
-//        private static final double kin_mount_to_edge_of_plate_y = length-15.8*inch;
-//        private final static double cone_to_edge_of_plate_y = 12.25*inch; 
-//        //private final static double cone_to_L1_hole_y = cone_to_edge_of_plate_y - kin_mount_to_edge_of_plate_y; 
-//        public UChannelL13Bottom(String name, SurveyVolume m,
-//                AlignmentCorrection alignmentCorrection,
-//                SurveyVolume ref) {
-//            super(name, m, alignmentCorrection, ref);
-//            init();
-//        }
-//        protected void setCenter() {
-//            final double x = 0.0;
-//            final double y = cone_to_edge_of_plate_y - length/2.0;
-//            final double z = -side_plate_cone_y - UChannelL13Plate.height + height/2.0;
-//            setCenter(x,y,z);
-//        }
-//        protected void setPos() {
-//            final double ball_pos_x = 4*inch;
-//            //final double ball_pos_y = (4.175 + 2*3.937) * inch; 
-//            final double ball_pos_y =  cone_to_edge_of_plate_y - kin_mount_to_edge_of_plate_y;
-//            final double ball_pos_z = -UChannelPlate.dist_from_plate_surface_to_pivot_point + UChannelL13Plate.height + side_plate_cone_y; 
-//            
-//            ballPos = new BasicHep3Vector(ball_pos_x, ball_pos_y, ball_pos_z);
-//            veePos = new BasicHep3Vector(ballPos.x()-1, ballPos.y(), ballPos.z());
-//            flatPos = new BasicHep3Vector(ballPos.x(), ballPos.y()-1, ballPos.z());
-//        }
-//    }
-    
-    
-    /**
-     * @SurveyVolume volume defining the coordinate system of the top L1-3 u-channel 
+  
+    
+    /**
+     * {@link SurveyVolume} volume defining the coordinate system of the top L1-3 u-channel 
      *  Reference: SupportRingL13TopKinMount coordinate system
      *  Origin: midpoint between upstream survey cones
      *  Orientation: u - width pointing towards positron side, v - pointing along the U-channel in the beam direction
@@ -578,7 +538,6 @@
         private final static Hep3Vector ball_kinMount = new BasicHep3Vector(SupportRingL13TopKinMount.kin_mount_pos_x,SupportRingL13TopKinMount.kin_mount_pos_y,SupportRingL13TopKinMount.kin_mount_pos_z);
 
         private final static double length = UChannelL13.length;
-        //private static final double kin_mount_to_edge_of_plate_y = length-15.8*inch;
         private final static double cone_to_side_plate_pin_y = (14.5-3.125)*inch; 
         private final static double side_plate_pin_to_edge_of_plate_y = (16.0-14.5)*inch; 
         private final static double cone_to_edge_of_plate_y = cone_to_side_plate_pin_y + side_plate_pin_to_edge_of_plate_y;
@@ -601,9 +560,6 @@
             Hep3Vector flatOffset = UChannelL13TopSurveyBalls.getFlatOffset();
             flatPos = VecOp.add(ballPos, flatOffset);
             
-//            ballPos = VecOp.sub(UChannelL13TopSurveyBalls.ball_pos, ball_kinMount);
-//            veePos = new BasicHep3Vector(ballPos.x()+1, ballPos.y(), ballPos.z());
-//            flatPos = new BasicHep3Vector(ballPos.x(), ballPos.y()-1, ballPos.z());
         }
         protected double getLength() {
            return length;
@@ -632,7 +588,7 @@
 
         
         protected static final Hep3Vector fwd_right = new BasicHep3Vector(-6.512, 9.978, .332);
-        protected static final Hep3Vector bwd_right = new BasicHep3Vector(-6.272, 2.107, .332);
+        //protected static final Hep3Vector bwd_right = new BasicHep3Vector(-6.272, 2.107, .332);
         protected static final Hep3Vector fwd_left = new BasicHep3Vector( 2.817, 10.262, .332);
         protected static final Hep3Vector bwd_left = new BasicHep3Vector(3.057, 2.392, .332);
         
@@ -648,43 +604,9 @@
     
     
     
-//    public static class UChannelL13Top extends UChannelL13 {
-//        private final static double length = UChannelL13.length;
-//        private static final double kin_mount_to_edge_of_plate_y = length-15.8*inch;
-//        private final static double cone_to_side_plate_pin_y = (14.5-3.125)*inch; 
-//        private final static double side_plate_pin_to_edge_of_plate_y = (16.0-14.5)*inch; 
-//        private final static double cone_to_edge_of_plate_y = cone_to_side_plate_pin_y + side_plate_pin_to_edge_of_plate_y;
-//        
-//        public UChannelL13Top(String name, SurveyVolume m,
-//                AlignmentCorrection alignmentCorrection,
-//                SurveyVolume ref) {
-//            super(name, m, alignmentCorrection, ref);
-//            init();
-//        }
-//        protected void setCenter() {
-//            final double x = 0.0;
-//            final double y = cone_to_edge_of_plate_y - length/2.0;
-//            final double z = -side_plate_cone_y - UChannelL13Plate.height + height/2.0;
-//            setCenter(x,y,z);
-//        }
-//        protected void setPos() {
-//            final double ball_pos_x = 4*inch;
-//            final double ball_pos_y = cone_to_edge_of_plate_y - kin_mount_to_edge_of_plate_y;
-//            final double ball_pos_z = SupportRingL13KinMount.kin_mount_offset_vertically - side_plate_cone_y; 
-//            // Note that this coordinate system is flipped pi compared to bottom
-//            ballPos = new BasicHep3Vector(ball_pos_x, ball_pos_y, ball_pos_z);
-//            veePos = new BasicHep3Vector(ballPos.x()+1, ballPos.y(), ballPos.z());
-//            flatPos = new BasicHep3Vector(ballPos.x(), ballPos.y()-1, ballPos.z());
-//        }
-//        protected double getLength() {
-//           return length;
-//        }
-//    }
-
-    
-
-    /**
-     * Abstract @SurveyVolume volume defining the coordinate system of the u-channel plate
+
+    /**
+     * Abstract {@link SurveyVolume} volume defining the coordinate system of the u-channel plate
 
      * @author Per Hansson Adrian <[log in to unmask]>
      *
@@ -701,7 +623,7 @@
     }
 
     /**
-     * Abstract @SurveyVolume volume defining the coordinate system of the u-channel plate
+     * Abstract {@link SurveyVolume} volume defining the coordinate system of the u-channel plate
 
      * @author Per Hansson Adrian <[log in to unmask]>
      *
@@ -710,7 +632,7 @@
         private final static double pocket_depth_L1 = 0.025;
         private final static double pocket_depth_L2 = pocket_depth_L1 + 0.059;
         private final static double pocket_depth_L3 = pocket_depth_L2 + 0.059;
-        private final static double module_mounting_hole_to_hole_x =3.937*inch;
+        //private final static double module_mounting_hole_to_hole_x =3.937*inch;
         private static final double width = 9.25*inch;
         protected static final double height = 0.375*inch;
         protected final static double length = 16.0*inch;
@@ -761,7 +683,7 @@
         
     
     /**
-     * @SurveyVolume volume defining the coordinate system of the bottom u-channel plate
+     * {@link SurveyVolume} volume defining the coordinate system of the bottom u-channel plate
      * Reference:  @UChannelL13Bottom coordinate system
      * Origin:  same as reference
      * Orientation: same as reference
@@ -788,7 +710,7 @@
     }
     
     /**
-     * @SurveyVolume volume defining the coordinate system of the bottom u-channel plate
+     * {@link SurveyVolume} volume defining the coordinate system of the bottom u-channel plate
      * Reference:  @UChannelL13Bottom coordinate system
      * Origin:  same as reference
      * Orientation: same as reference
@@ -816,7 +738,7 @@
     
     
     /**
-     * Abstract @SurveyVolume volume defining the L4-6 u-channel volume
+     * Abstract {@link SurveyVolume} volume defining the L4-6 u-channel volume
      * 
      *  @author Per Hansson Adrian <[log in to unmask]>
      */
@@ -825,8 +747,8 @@
         protected static final double width = UChannelL46Plate.width;
         protected static final double length = UChannelL46Plate.length;
         protected static final double height = 2.575*inch;
-        private static final double kin_mount_to_edge_of_plate_x = width/2.0-5.75*inch;
-        private static final double kin_mount_to_edge_of_plate_y = 0.2*inch;
+        //private static final double kin_mount_to_edge_of_plate_x = width/2.0-5.75*inch;
+        //private static final double kin_mount_to_edge_of_plate_y = 0.2*inch;
         protected static final double side_plate_cone_y = 2.0*inch;
         
         public UChannelL46(String name, SurveyVolume m,
@@ -845,7 +767,7 @@
    
     
     /**
-     * @SurveyVolume volume defining the coordinate system of the u-channel 
+     * {@link SurveyVolume} volume defining the coordinate system of the u-channel 
      *  Reference: SVTBox coordinate system
      *  Origin: midpoint between upstream survey cones
      *  Orientation: u - width pointing towards electron side, v - pointing along the U-channel in the beam direction
@@ -893,9 +815,9 @@
         private static final double cone_fwd_right_y = -6.419*inch;
         private static final double cone_fwd_right_z = -0.332*inch;
 
-        private static final double cone_bwd_right_x = -6.539*inch;
-        private static final double cone_bwd_right_y = -22.159*inch;
-        private static final double cone_bwd_right_z = -0.332*inch;
+        //private static final double cone_bwd_right_x = -6.539*inch;
+        //private static final double cone_bwd_right_y = -22.159*inch;
+        //private static final double cone_bwd_right_z = -0.332*inch;
 
         private static final double cone_fwd_left_x = 6.558*inch;
         private static final double cone_fwd_left_y = -6.005*inch;
@@ -907,7 +829,7 @@
         
         protected static final Hep3Vector fwd_right = new BasicHep3Vector(cone_fwd_right_x, cone_fwd_right_y, cone_fwd_right_z);
         protected static final Hep3Vector fwd_left = new BasicHep3Vector(cone_fwd_left_x, cone_fwd_left_y, cone_fwd_left_z);
-        protected static final Hep3Vector bwd_right = new BasicHep3Vector(cone_bwd_right_x, cone_bwd_right_y, cone_bwd_right_z);
+        //protected static final Hep3Vector bwd_right = new BasicHep3Vector(cone_bwd_right_x, cone_bwd_right_y, cone_bwd_right_z);
         protected static final Hep3Vector bwd_left = new BasicHep3Vector(cone_bwd_left_x, cone_bwd_left_y, cone_bwd_left_z);
         
         protected static Hep3Vector getVeeOffset() {
@@ -920,57 +842,11 @@
     
     
     
-    
-//  public static class UChannelL46Bottom extends UChannelL46 {
-//      // Coordinates of the survey ball engaging the machined features
-//      protected static final double cone_fwd_right_x = -7.019*inch;
-//      protected static final double cone_fwd_right_y = -6.419*inch;
-//      protected static final double cone_fwd_right_z = -0.332*inch;
-//
-//      protected static final double cone_bwd_right_x = -6.539*inch;
-//      protected static final double cone_bwd_right_y = -22.159*inch;
-//      protected static final double cone_bwd_right_z = -0.332*inch;
-//
-//      protected static final double cone_fwd_left_x = 6.558*inch;
-//      protected static final double cone_fwd_left_y = -6.005*inch;
-//      protected static final double cone_fwd_left_z = -0.332*inch;
-//
-//      protected static final double cone_bwd_left_x = 7.038*inch;
-//      protected static final double cone_bwd_left_y = -21.745*inch;
-//      protected static final double cone_bwd_left_z = -0.332*inch;
-//
-//      protected static final double cone_to_edge_of_plate_y = 2.75*inch;
-//
-//      public UChannelL46Bottom(String name, SurveyVolume m,
-//              AlignmentCorrection alignmentCorrection) {
-//          super(name, m, alignmentCorrection);
-//          init();
-//      }
-//      protected void setCenter() {
-//          final double x = 0.0;
-//          final double y = -cone_to_edge_of_plate_y + length/2.0;
-//          final double z = -side_plate_cone_y - UChannelL46Plate.height + height/2.0;
-//          setCenter(x,y,z);
-//      }
-//      protected void setPos() {
-//          //locate coordinate system from cone in mother coordinate system
-//          Hep3Vector fwd_right = new BasicHep3Vector(cone_fwd_right_x, cone_fwd_right_y, cone_fwd_right_z);
-//          Hep3Vector fwd_left = new BasicHep3Vector(cone_fwd_left_x, cone_fwd_left_y, cone_fwd_left_z);
-//          Hep3Vector bwd_right = new BasicHep3Vector(cone_bwd_right_x, cone_bwd_right_y, cone_bwd_right_z);
-//          Hep3Vector bwd_left = new BasicHep3Vector(cone_bwd_left_x, cone_bwd_left_y, cone_bwd_left_z);
-//          
-//          Hep3Vector d = VecOp.mult(0.5,VecOp.sub(fwd_left, fwd_right));
-//          ballPos = VecOp.add(fwd_right, d);
-//          veePos = fwd_right;
-//          d = VecOp.mult(0.5, VecOp.sub(bwd_left, bwd_right));
-//          flatPos = VecOp.add(bwd_right, d);
-//      }
-//  }
   
     
     /**
-     * @SurveyVolume volume defining the coordinate system of the u-channel 
-     *  Reference: SVTBox coordinate system
+     * {@link SurveyVolume} volume defining the coordinate system of the u-channel 
+     *  Reference: {@link SVTBox} coordinate system
      *  Origin: midpoint between upstream survey cones
      *  Orientation: u - width pointing towards electron side, v - pointing along the U-channel in the beam direction
      *  
@@ -1041,7 +917,7 @@
         protected static final Hep3Vector fwd_right = new BasicHep3Vector(cone_fwd_right_x, cone_fwd_right_y, cone_fwd_right_z);
         protected static final Hep3Vector fwd_left = new BasicHep3Vector(cone_fwd_left_x, cone_fwd_left_y, cone_fwd_left_z);
         protected static final Hep3Vector bwd_right = new BasicHep3Vector(cone_bwd_right_x, cone_bwd_right_y, cone_bwd_right_z);
-        protected static final Hep3Vector bwd_left = new BasicHep3Vector(cone_bwd_left_x, cone_bwd_left_y, cone_bwd_left_z);
+        //protected static final Hep3Vector bwd_left = new BasicHep3Vector(cone_bwd_left_x, cone_bwd_left_y, cone_bwd_left_z);
 
         protected static Hep3Vector getVeeOffset() {
             return  VecOp.mult(0.5,VecOp.sub(fwd_left, fwd_right));
@@ -1052,61 +928,9 @@
     }
 
 
-//    public static class UChannelL46Top extends UChannelL46 {
-//        // Coordinates of the survey ball engaging the machined features
-//        protected static final double cone_fwd_right_x = -7.038*inch;
-//        protected static final double cone_fwd_right_y = -5.794*inch;
-//        protected static final double cone_fwd_right_z = 0.332*inch;
-//
-//        protected static final double cone_bwd_right_x = -6.558*inch;
-//        protected static final double cone_bwd_right_y = -21.535*inch;
-//        protected static final double cone_bwd_right_z = 0.332*inch;
-//
-//        protected static final double cone_fwd_left_x = 6.539*inch;
-//        protected static final double cone_fwd_left_y = -5.380*inch;
-//        protected static final double cone_fwd_left_z = 0.332*inch;
-//
-//        protected static final double cone_bwd_left_x = 7.019*inch;
-//        protected static final double cone_bwd_left_y = -21.121*inch;
-//        protected static final double cone_bwd_left_z = 0.332*inch;
-//        
-//        private static final double cone_to_side_plate_pin_y = (0.875-0.25)*inch;
-//        private static final double side_plate_pin_to_edge_of_plate_y = 1.5*inch;
-//        
-//        protected static final double cone_to_edge_of_plate_y = cone_to_side_plate_pin_y + side_plate_pin_to_edge_of_plate_y;
-//        
-//        public UChannelL46Top(String name, SurveyVolume m,
-//                AlignmentCorrection alignmentCorrection) {
-//            super(name, m, alignmentCorrection);
-//            init();
-//        }
-//        protected void setCenter() {
-//            final double x = 0.0;
-//            final double y = -cone_to_edge_of_plate_y + length/2.0;
-//            final double z = -side_plate_cone_y - UChannelL46Plate.height + height/2.0;
-//            setCenter(x,y,z);
-//        }
-//        protected void setPos() {
-//            
-//          //locate coordinate system from cone in mother coordinate system
-//            Hep3Vector fwd_right = new BasicHep3Vector(cone_fwd_right_x, cone_fwd_right_y, cone_fwd_right_z);
-//            Hep3Vector fwd_left = new BasicHep3Vector(cone_fwd_left_x, cone_fwd_left_y, cone_fwd_left_z);
-//            Hep3Vector bwd_right = new BasicHep3Vector(cone_bwd_right_x, cone_bwd_right_y, cone_bwd_right_z);
-//            Hep3Vector bwd_left = new BasicHep3Vector(cone_bwd_left_x, cone_bwd_left_y, cone_bwd_left_z);
-//            
-//            Hep3Vector d = VecOp.mult(0.5,VecOp.sub(fwd_left, fwd_right));
-//            ballPos = VecOp.add(fwd_right, d);
-//            veePos = fwd_left;
-//            d = VecOp.mult(0.5, VecOp.sub(bwd_left, bwd_right));
-//            flatPos = VecOp.add(bwd_right, d);
-//            
-//        }
-//    }
-
-    
-    
-    /**
-     * Abstract @SurveyVolume  defining the coordinate system of the u-channel plates
+    
+    /**
+     * Abstract {@link SurveyVolume}  defining the coordinate system of the u-channel plates
 
      * @author Per Hansson Adrian <[log in to unmask]>
      *
@@ -1164,7 +988,7 @@
     }
     
     /**
-     * @SurveyVolume  defining the coordinate system of the bottom u-channel plate
+     * {@link SurveyVolume}  defining the coordinate system of the bottom u-channel plate
      * Reference:  @UChannelL13Bottom coordinate system
      * Origin:  same as reference
      * Orientation: same as reference
@@ -1192,7 +1016,7 @@
     
     
     /**
-     * @SurveyVolume defining the coordinate system of the top u-channel plate
+     * {@link SurveyVolume} defining the coordinate system of the top u-channel plate
      * Reference:  @UChannelL13Top coordinate system
      * Origin:  same as reference
      * Orientation: same as reference
@@ -1221,7 +1045,7 @@
     
 
     /**
-     * @SurveyVolume volume defining the coordinate system of module L1-3
+     * {@link SurveyVolume} volume defining the coordinate system of module L1-3
      * Reference:  @UChannelL13Bottom coordinate system
      * Origin:  hole position on mounting surface (on electron side)
      * Orientation: u - is normal to the surface pointing vertically down, v - points along module away from hybrid side (i.e. positron direction).
@@ -1406,7 +1230,7 @@
    
     
     /**
-     * Abstract @SurveyVolume volume defining the coordinate system of module L4-6
+     * Abstract {@link SurveyVolume} volume defining the coordinate system of module L4-6
      * 
      * @author Per Hansson Adrian <[log in to unmask]>
      *
@@ -1446,7 +1270,7 @@
     
     
     /**
-     * Abstract @SurveyVolume volume defining the coordinate system of bottom modules for L4-6
+     * Abstract {@link SurveyVolume} volume defining the coordinate system of bottom modules for L4-6
      * Reference:  @UChannelL46Bottom coordinate system
      * Origin:  hole position on mounting surface (electron side)
      * Orientation: u - is normal to the mounting surface pointing vertically down, v - points along module towards positron side.
@@ -1471,7 +1295,7 @@
     }
     
     /**
-     * Abstract @SurveyVolume volume defining the coordinate system of top modules for L4-6
+     * Abstract {@link SurveyVolume} volume defining the coordinate system of top modules for L4-6
      * Reference:  @UChannelL46Top coordinate system
      * Origin:  hole position on mounting surface (electron side when installed)
      * Orientation: u - is normal to the mounting surface pointing vertically down, v - points along module towards electron side when installed.
@@ -1798,7 +1622,7 @@
     
 
     /**
-     * @SurveyVolume volume defining the coordinate system of the axial half-module in module L1-3
+     * {@link SurveyVolume} volume defining the coordinate system of the axial half-module in module L1-3
      * Reference:  @ModuleL13Bot coordinate system
      * Origin:  sensor center
      * Orientation: w - is normal to the surface pointing from p-side to n-side, v - points along strips away from signal bond pads
@@ -1838,7 +1662,7 @@
     
    
     /**
-     * @SurveyVolume volume defining the coordinate system of the stereo half-module in module L1-3
+     * {@link SurveyVolume} volume defining the coordinate system of the stereo half-module in module L1-3
      * Reference:  @ModuleL13Bot coordinate system
      * Origin:  sensor center
      * Orientation: same as axial - the module is rotated later.
@@ -1957,7 +1781,8 @@
         // created through it's references we don't need more than one reference to reach the mother coordinate system
         final SurveyVolume mother = getSurveyVolume(SvtBox.class);
         final SurveyVolume ref;
-        AlignmentCorrection alignmentCorrection = null;
+        AlignmentCorrection alignmentCorrection = new AlignmentCorrection();
+        alignmentCorrection.setNode(node);
         if(half == "bottom") {
             if(layer < 4) {
                 ref = getSurveyVolume(UChannelL13Bottom.class);
@@ -2121,7 +1946,8 @@
         
         // find alignment correction to this volume
         AlignmentCorrection alignmentCorrection =  getHalfModuleAlignmentCorrection(isTopLayer, millepedeLayer);
-        
+        alignmentCorrection.setNode(node);
+       
         
         // find the module bundle that it will be added to
         //TestRunModuleBundle bundle  = (TestRunModuleBundle)getModuleBundle(mother);

Modified: java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerBuilder.java
 =============================================================================
--- java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerBuilder.java	(original)
+++ java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerBuilder.java	Mon Jul  6 16:36:19 2015
@@ -7,6 +7,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.hps.conditions.database.DatabaseConditionsManager;
 import org.jdom.DataConversionException;
@@ -172,7 +174,7 @@
      * @param isTopLayer - top or bottom layer
      * @return the alignment correction
      */
-    protected AlignmentCorrection getSupportAlignmentCorrection(boolean isTopLayer) {
+    protected AlignmentCorrection getL13UChannelAlignmentCorrection(boolean isTopLayer) {
         double r[] = {0, 0, 0};
         double t[] = {0, 0, 0};
         for (MilleParameter p_loop : milleparameters) {
@@ -256,6 +258,11 @@
         }
     }
 
+    
+    public static boolean isTopFromName(String name) {
+        return getHalfFromName(name).equals("top") ? true : false;
+    }
+    
     public static String getHalfFromName(String name) {
         String half = "";
         if (name.contains("bottom")) {
@@ -271,18 +278,13 @@
         }
         // check for other signatures
         if (half.isEmpty()) {
-            // 6 layers is arbitrary here
-            for (int layer = 1; layer <= 6; ++layer) {
-                if (name.contains(String.format("L%db", layer))) {
+            Pattern pattern = Pattern.compile(".*_L[1-6][1-6]?([a-z]).*");
+            Matcher matcher = pattern.matcher(name);
+            if(matcher.matches()) {
+                if(matcher.group(1).equals("t")) {
+                    half = "top";
+                } else if(matcher.group(1).equals("b")) {
                     half = "bottom";
-                    break;
-                }
-                if (name.contains(String.format("L%dt", layer))) {
-                    if (half.equals("bottom")) {
-                        throw new RuntimeException("found both halfs from name  " + name);
-                    }
-                    half = "top";
-                    break;
                 }
             }
         }
@@ -324,7 +326,40 @@
         }
         return false;
     }
-
+    
+    public static boolean isModule(String name) {
+        return Pattern.matches("module_L[1-6][bt]$", name);
+    }
+    
+    public static int getUChannelSupportLayer(String name) {
+        if(isUChannelSupport(name)) {
+            Pattern patter = Pattern.compile("^support_[a-z]*_L([1-6])[1-6]$");
+            Matcher matcher = patter.matcher(name);
+            if(matcher.matches() ) {
+                int layer = Integer.parseInt(matcher.group(1));
+                return layer;
+            } else {
+                throw new RuntimeException("this is not a valid u-channel name: " + name);
+            }
+        } else {
+            throw new RuntimeException("this is not a valid u-channel name: " + name);
+        }
+    }
+    
+    
+    public static boolean isUChannelSupport(String name) {
+        Pattern patter = Pattern.compile("^support_[a-z]*_L(4|1)(6|3)$");
+        Matcher matcher = patter.matcher(name);
+        return matcher.matches();
+    }
+
+    public static boolean isSupportRingKinMount(String name) {
+        Pattern patter = Pattern.compile("^c_support_kin_L13(b|t)$");
+        Matcher matcher = patter.matcher(name);
+        return matcher.matches();
+    }    
+    
+    
     public static boolean isSensor(String name) {
         if (name.endsWith("sensor")) {
             return true;
@@ -532,6 +567,48 @@
         }
         return transformToParent(vec_mother_coord, geometry.getMother(), targetName);
     }
+    
+    
+    /**
+     * Find the vector in a mother volume coordinate system.
+     * 
+     * @param vec - vector to transform
+     * @param geometry - geometry where vector is defined.
+     * @return transformed vector.
+     */
+    public static Hep3Vector rotateToParent(Hep3Vector vec, SurveyVolume geometry, String targetName) {
+        int debug = 0;
+        if (debug > 0)
+            System.out.printf("\nrotateToParent: vec %s in local coordiantes of %s\n", vec.toString(),
+                    geometry.getName());
+        if (geometry.getMother() == null) {
+            if (debug > 0)
+                System.out.printf("\nrotateToParent: no mother, return null\n", vec.toString(), geometry.getName());
+            return null;
+        }
+        if (debug > 0)
+            System.out.printf("\nrotateToParent: vec %s in local coordinates of %s with mother %s\n",
+                    vec.toString(), geometry.getName(), geometry.getMother().getName().toString());
+        SurveyCoordinateSystem coord = geometry.getCoord();
+        if (coord == null) {
+            throw new RuntimeException("rotateToParent: no coordinate system found for %s, return null "
+                    + geometry.getName());
+        }
+        Hep3Vector vec_mother_coord = coord.getTransformation().rotated(vec);
+        if (debug > 0)
+            System.out.printf("vec_mother_coord %s\n", vec_mother_coord.toString());
+        if (geometry.getMother().getName().equals(targetName)) {
+            if (debug > 0)
+                System.out.printf("reached target \"%s\"tracking volume. Return \n", targetName);
+            return vec_mother_coord;
+        } else {
+            if (debug > 0)
+                System.out.printf("continue searching.\n");
+        }
+        return rotateToParent(vec_mother_coord, geometry.getMother(), targetName);
+    }
+
+    
 
     /**
      * Get axial or stereo key name from string

Modified: java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerGeometryDefinition.java
 =============================================================================
--- java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerGeometryDefinition.java	(original)
+++ java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerGeometryDefinition.java	Mon Jul  6 16:36:19 2015
@@ -36,7 +36,7 @@
 
 
     //General
-    static final double inch = 25.4; //mm
+    protected static final double inch = 25.4; //mm
     protected static final boolean useSiStripsConvention = true;
     protected static final boolean use30mradRotation = true;
     protected static final boolean useFakeHalfModuleAxialPos = false;
@@ -106,7 +106,7 @@
     
         // find alignment correction to this volume
         AlignmentCorrection alignmentCorrection =  getHalfModuleAlignmentCorrection(isTopLayer, millepedeLayer);
-        
+        alignmentCorrection.setNode(node);
         
         // find the module bundle that it will be added to
         //TestRunModuleBundle bundle  = (TestRunModuleBundle)getModuleBundle(mother);

Modified: java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerLCDDBuilder.java
 =============================================================================
--- java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerLCDDBuilder.java	(original)
+++ java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/HPSTrackerLCDDBuilder.java	Mon Jul  6 16:36:19 2015
@@ -10,7 +10,7 @@
 
 public abstract class HPSTrackerLCDDBuilder  implements IHPSTrackerLCDDBuilder {
 
-	public boolean _debug = true;
+	public boolean _debug = false;
 	protected LCDD lcdd = null;
 	protected LCDDSurveyVolume baseSurveyVolume;
 	protected List<LCDDSurveyVolume> lcddSurveyVolumes = new ArrayList<LCDDSurveyVolume>();

Modified: java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyCoordinateSystem.java
 =============================================================================
--- java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyCoordinateSystem.java	(original)
+++ java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyCoordinateSystem.java	Mon Jul  6 16:36:19 2015
@@ -13,7 +13,7 @@
 import org.lcsim.detector.Translation3D;
 
      /**
-	 * Class describing a simple coordinate system used to define the [log in to unmask]
+	 * Class describing a simple coordinate system used to define the {@link SurveyVolume}.
 	 * 
 	 *    @author Per Hansson Adrian <[log in to unmask]>
 	 */

Modified: java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyVolume.java
 =============================================================================
--- java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyVolume.java	(original)
+++ java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/SurveyVolume.java	Mon Jul  6 16:36:19 2015
@@ -7,12 +7,16 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
+import org.jdom.Element;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.geometry.compact.converter.HPSTracker2014GeometryDefinition.SvtBox;
 import org.lcsim.geometry.util.TransformationUtils;
 
 /**
  * 
- * Class containing the basic geometry information for building a volume based on survey positions.
+ * Contains the geometry information that is used to build any volume. 
  * 
  */
 public abstract class SurveyVolume {
@@ -53,6 +57,14 @@
 	protected abstract void setCenter();
 	protected abstract void setBoxDim();
 
+	/**
+	 * 
+	 * Initialize the volume. 
+	 * This needs to be called at the top level implementation of the {@link SurveyVolume} to properly setup
+	 * the coordinate systems. It takes care of applying user supplied custom transformations and alignment corrections
+	 * in the order given in the function below. That order must be preserved to get a uniform behavior. 
+	 * 
+	 */
 	protected void init() {
 	    if(debug) System.out.printf("%s: init SurveyVolume %s\n",this.getClass().getSimpleName(),getName());
         setPos();
@@ -69,10 +81,312 @@
 	}
 	
 
+    private void applySurvey(Element node) {
+
+        if(debug) System.out.printf("%s: apply survey from compact.\n", this.getClass().getSimpleName());
+
+        // Check that XML file is read into memory and available
+        if(node==null) {
+            
+            if(debug) System.out.printf("%s: WARNING: no XML file for survey information available.\n", this.getClass().getSimpleName());
+    
+        } else {
+            
+            SurveyResult surveyResult = SurveyResult.findResultFromDetector(node, getName());
+            
+            if(surveyResult!=null) {
+                if(debug) System.out.printf("%s: found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+                
+                // Adjust coordinate system to match the one used in the geometry.
+                // This depends on the particular volume we are in.
+                
+                if(HPSTrackerBuilder.isModule(name)) {
+
+                    if(HPSTrackerBuilder.isTopFromName(name)) {
+                        
+                        if(debug) System.out.printf("%s: treating it as a top module\n", this.getClass().getSimpleName());
+                        
+                        // The U-channel coordinate system is flipped 90deg clockwise around survey x-axis
+                        
+                        Rotation rotation1 = new Rotation(new Vector3D(1, 0, 0),-Math.PI/2.0);
+                        surveyResult.rotateOrigin(rotation1);
+                        surveyResult.rotateUnitVectors(rotation1);
+                        
+                        if(debug) System.out.printf("%s: UPDATE1 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+                        
+                        // The unit vectors of the survey module coordinate system (pin bases) are different:
+                        // survey x-axis is module v-axis
+                        // survey y-axis is module -1*u-axis
+                        // survey z-axis is module w-axis
+
+                        Hep3Vector y = new BasicHep3Vector(surveyResult.getX().v());
+                        Hep3Vector x = new BasicHep3Vector(VecOp.mult(-1, surveyResult.getY()).v());
+                        surveyResult.setX(x);
+                        surveyResult.setY(y);
+                        
+                    }
+                    else {
+                    
+                        if(debug) System.out.printf("%s: treating it as a bottom module\n", this.getClass().getSimpleName());
+
+                        // The survey u-channel coordinate system needs two rotations to correspond to the one used here
+                        Rotation rotation1 = new Rotation(new Vector3D(1, 0, 0), Math.PI/2.0);
+                        Rotation rotation2 = new Rotation(new Vector3D(0, 0, 1), Math.PI);
+                        Rotation rotation = rotation2.applyTo(rotation1);
+                        surveyResult.rotateOrigin(rotation);
+                        surveyResult.rotateUnitVectors(rotation);
+
+                        if(debug) System.out.printf("%s: UPDATE1 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+                        
+                        // The unit vectors of the survey module coordinate system (pin bases) are different:
+                        // survey x-axis is module v-axis
+                        // survey y-axis is module -1*u-axis
+                        // survey z-axis is module w-axis
+                        
+                        Hep3Vector x = new BasicHep3Vector( VecOp.mult(-1, surveyResult.getY()).v());
+                        Hep3Vector y = new BasicHep3Vector( surveyResult.getX().v() );
+                        surveyResult.setX(x);
+                        surveyResult.setY(y);
+
+                        if(debug) System.out.printf("%s: UPDATE2 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+                    }
+                   
+
+
+                } else if(HPSTrackerBuilder.isHalfModule(name)) {
+
+                    if(debug) System.out.printf("%s: treating it as a half-module\n", this.getClass().getSimpleName());
+
+                    // Adjust origin to the sensor center
+                    surveyResult.setOrigin(VecOp.add(surveyResult.getOrigin(), VecOp.mult(-0.160, surveyResult.getZ())));
+
+                    // rotate and flip axis to adhere to the definitions of the u,v,w used for the SurveyVolume
+                    Rotation rotation = new Rotation(new Vector3D(0,0,1),Math.PI/2.0);
+                    surveyResult.rotateOrigin(rotation);                
+                    surveyResult.rotateUnitVectors(rotation);
+                    Hep3Vector x = new BasicHep3Vector( VecOp.mult(-1, surveyResult.getY()).v());
+                    Hep3Vector y = new BasicHep3Vector( surveyResult.getX().v() );
+                    surveyResult.setX(x);
+                    surveyResult.setY(y);
+
+                    if(debug) System.out.printf("%s: updated found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+                
+                    
+                    
+                    
+                    
+                } else if(HPSTrackerBuilder.isSupportRingKinMount(name)) {
+
+                    if(debug) System.out.printf("%s: treating it as support ring kinematic mount\n", this.getClass().getSimpleName());
+
+
+
+                    // Survey SVT box origin  translated to the edge of the SVT box
+                    surveyResult.setOrigin(VecOp.sub(surveyResult.getOrigin(), new BasicHep3Vector(0, 0, -0.375*HPSTrackerGeometryDefinition.inch)));
+
+                    if(debug) System.out.printf("%s: UPDATE1 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+
+
+                    // Survey SVT box origin translated to the center of the Svt Box used in the geometry
+                    surveyResult.setOrigin(VecOp.sub(surveyResult.getOrigin(),new BasicHep3Vector(0, 0, SvtBox.length/2.0)));
+
+
+                    if(debug) System.out.printf("%s: UPDATE2 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+
+                    // rotate origin into the SVT box coordinates
+                    Rotation r1 = new Rotation(new Vector3D(1, 0, 0), Math.PI/2.0);
+                    surveyResult.rotateOrigin(r1);
+                    surveyResult.rotateUnitVectors(r1);
+
+                    if(debug) System.out.printf("%s: UPDATE3 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+
+
+
+                    // Swap definition of unit axis to the one used in the U-channels
+                    if(HPSTrackerBuilder.isTopFromName(name)) {
+
+                      //Hep3Vector x = new BasicHep3Vector( VecOp.mult(-1,surveyResult.getX()).v() );
+                        Hep3Vector y = new BasicHep3Vector( VecOp.mult(-1,surveyResult.getZ()).v() );
+                        Hep3Vector z = new BasicHep3Vector( surveyResult.getY().v() );
+                        //surveyResult.setX(x);
+                        surveyResult.setY(y);
+                        surveyResult.setZ(z);
+
+                    } else {
+
+                        //Hep3Vector x = new BasicHep3Vector( VecOp.mult(-1,surveyResult.getX()).v() );
+                        Hep3Vector y = new BasicHep3Vector( VecOp.mult(-1,surveyResult.getZ()).v() );
+                        Hep3Vector z = new BasicHep3Vector( surveyResult.getY().v() );
+                        //surveyResult.setX(x);
+                        surveyResult.setY(y);
+                        surveyResult.setZ(z);
+
+                    }
+
+
+
+
+                } else if(HPSTrackerBuilder.isUChannelSupport(name) ) {
+
+                   
+                    
+                    int layer = HPSTrackerBuilder.getUChannelSupportLayer(name);
+
+                    if(layer >= 4 ) {
+                        if(debug) System.out.printf("%s: treating it as a L4-6 U-channel (%d)\n", this.getClass().getSimpleName(), layer);
+
+
+                        // Survey SVT box origin  translated to the edge of the SVT box
+                        surveyResult.setOrigin(VecOp.sub(surveyResult.getOrigin(), new BasicHep3Vector(0, 0, -0.375*HPSTrackerGeometryDefinition.inch)));
+
+                        if(debug) System.out.printf("%s: UPDATE1 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+
+                        // Survey SVT box origin translated to the center of the Svt Box used in the geometry
+                        surveyResult.setOrigin(VecOp.sub(surveyResult.getOrigin(),new BasicHep3Vector(0, 0, SvtBox.length/2.0)));
+
+
+                        if(debug) System.out.printf("%s: UPDATE2 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+
+                        // rotate origin into the SVT box coordinates
+                        Rotation r1 = new Rotation(new Vector3D(1, 0, 0), Math.PI/2.0);
+                        surveyResult.rotateOrigin(r1);
+                        surveyResult.rotateUnitVectors(r1);
+
+                        if(debug) System.out.printf("%s: UPDATE3 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+
+                        // Swap definition of unit axis to the one used in the U-channels
+                        if(HPSTrackerBuilder.isTopFromName(name)) {
+
+                            Hep3Vector y = new BasicHep3Vector( surveyResult.getZ().v() );
+                            Hep3Vector z = new BasicHep3Vector( VecOp.mult(-1, surveyResult.getY()).v() );
+                            surveyResult.setY(y);
+                            surveyResult.setZ(z);
+
+                        } else {
+
+                            Hep3Vector x = new BasicHep3Vector( VecOp.mult(-1,surveyResult.getX()).v() );
+                            Hep3Vector y = new BasicHep3Vector( surveyResult.getZ().v() );
+                            Hep3Vector z = new BasicHep3Vector( surveyResult.getY().v() );
+                            surveyResult.setX(x);
+                            surveyResult.setY(y);
+                            surveyResult.setZ(z);
+
+                        }
+                        
+
+                    } else {
+                        
+                        if(debug) System.out.printf("%s: treating it as a L1-3 U-channel (%d)\n", this.getClass().getSimpleName(), layer);
+                        
+                        // Rotate the survey origin into the kinematic mount coordinate frame used here
+                        Rotation r = new Rotation(new Vector3D(1,0,0), Math.PI/2.0);
+                        surveyResult.rotateOrigin(r);
+                        surveyResult.rotateUnitVectors(r);
+                        
+                        if(debug) System.out.printf("%s: UPDATE1 found survey results: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+
+                        
+                        // Swap definition of unit axis to the one used in the U-channels
+                        if(HPSTrackerBuilder.isTopFromName(name)) {
+
+                            Hep3Vector y = new BasicHep3Vector( surveyResult.getZ().v() );
+                            Hep3Vector z = new BasicHep3Vector( VecOp.mult(-1, surveyResult.getY()).v() );
+                            surveyResult.setY(y);
+                            surveyResult.setZ(z);
+
+                        } else {
+
+                            Hep3Vector y = new BasicHep3Vector( surveyResult.getZ().v() );
+                            Hep3Vector z = new BasicHep3Vector( surveyResult.getY().v() );
+                            Hep3Vector x = new BasicHep3Vector( VecOp.mult(-1,surveyResult.getX()).v() );
+                            surveyResult.setX(x);
+                            surveyResult.setY(y);
+                            surveyResult.setZ(z);
+
+                        }
+                        
+                    }
+
+
+                    
+                    
+                } else {
+                    
+                    throw new RuntimeException("I don't think there is a surveyresult defined for this type from " + name);
+                    
+                }
+                
+                if(debug) System.out.printf("%s:  survey results after corrections: \n%s \n", this.getClass().getSimpleName(), surveyResult.toString());
+
+                
+                
+                // Need to go through the reference/ghost geometries if they exist
+                
+                if(referenceGeom!=null) {
+                    if(debug) System.out.printf("%s: apply reference transformation for %s\n",this.getClass().getSimpleName(),getName());
+                    if(debug) System.out.printf("%s: survey system before %d ref transformations:\n%s\n",this.getClass().getSimpleName(),referenceGeom.size(),surveyResult.toString());
+                    for(SurveyVolume ref : referenceGeom) {
+                        if(debug) {
+                            System.out.printf("%s: survey system before ref %s transform:\n%s\n",this.getClass().getSimpleName(),ref.getName(),surveyResult.toString());
+                            System.out.printf("%s: Ref %s coord\n%s\n",this.getClass().getSimpleName(), ref.getName(),ref.getCoord().toString());
+                        }
+                        surveyResult.transform(ref.getCoord().getTransformation());
+                        
+                        if(debug) System.out.printf("%s: survey system after ref %s transform:\n%s\n",this.getClass().getSimpleName(),ref.getName(),surveyResult.toString());
+
+                    }
+
+                    if(debug) System.out.printf("%s: survey system after ref transformations:\n%s\n",this.getClass().getSimpleName(),surveyResult.toString());
+
+                } else {
+
+                    if(debug) System.out.printf("%s: no reference transformation exists for %s\n",this.getClass().getSimpleName(),getName());
+
+                }
+
+
+                if(debug) System.out.printf("%s: apply to \n%s \n", this.getClass().getSimpleName(), this.getCoord().toString());
+
+                // get translation and apply it
+                Translation3D transToSurvey = surveyResult.getTranslationFrom(getCoord());
+                getCoord().translate(transToSurvey);
+
+                if(debug) System.out.printf("%s: after translation to survey \n%s \n", this.getClass().getSimpleName(), this.getCoord().toString());
+
+                // get rotation and apply it
+                Rotation rotToSurvey = surveyResult.getRotationFrom(getCoord());
+                getCoord().rotateApache(rotToSurvey);
+
+                if(debug) System.out.printf("%s: after rotation to survey \n%s \n", this.getClass().getSimpleName(), this.getCoord().toString());
+
+                
+                
+                
+                
+
+            } else {
+                if(debug) System.out.printf("%s: no survey results for %s in node %s \n", this.getClass().getSimpleName(), getName(), node.getName());
+            }
+        }
+        
+        if(debug) System.out.printf("%s: DONE apply survey from compact.\n", this.getClass().getSimpleName());
+
+        
+    }
+
+    /**
+     * Apply a generic correction to the coordinate system of this volume. 
+     */
     protected void applyGenericCoordinateSystemCorrections() {
 	    //do nothing here unless overridden
 	   
 	}
+    
+	/**
+	 * Applies a user supplied reference transformation to the module. 
+	 * This is convenient as it allows for intermediary "virtual" mother volumes to be used 
+	 * in referencing a volume to it's physcial mother volume.
+	 */
 	protected void applyReferenceTransformation() {
 
 	        	    
@@ -106,7 +420,12 @@
 
 	}
 	
+	/**
+	 * Apply @link AlignmentCorrection to the volume if they are supplied. 
+	 * 
+	 */
 	private void applyLocalAlignmentCorrections() {
+	    
 	    // Apply alignment corrections to local coordinate system that is already built
 	    boolean debug_local = false;
 	    if(this.coord==null) 
@@ -114,6 +433,21 @@
 
 	    if(alignmentCorrections!=null) {
 
+	        
+	        if(alignmentCorrections.getNode()!=null) {
+	            
+	            if(debug_local || debug) System.out.printf("%s: Apply survey results to %s\n",this.getClass().getSimpleName(),this.getName());
+	            
+	            applySurvey(alignmentCorrections.getNode());
+
+	            if(debug_local || debug) System.out.printf("%s: DONE Apply survey results to %s\n",this.getClass().getSimpleName(),this.getName());
+                
+	        }
+	        
+	        
+	        
+	        
+	        
 	        if(debug_local || debug) System.out.printf("%s: Apply alignment corrections to %s\n",this.getClass().getSimpleName(),this.getName());
 
 	        // translate
@@ -163,36 +497,7 @@
                 }
 
 	            
-	            // Do some gymnastics from Apache rotation to use the rotation class
-	            //double matMP_v[][] = alignmentCorrections.getRotation().getMatrix();
-                //Hep3Matrix matMP = new BasicHep3Matrix(matMP_v[0][0], matMP_v[0][1], matMP_v[0][2], 
-                //                                       matMP_v[1][0], matMP_v[1][1], matMP_v[1][2],
-                //                                       matMP_v[2][0], matMP_v[2][1], matMP_v[2][2]);
-                //
-                //Rotation3D rotMP = new Rotation3D(matMP);
-
-                // get the rotation correction in the mother coordinate system
-                //Rotation3D r = Rotation3D.multiply(getCoord().getTransformation().getRotation(),rotMP);
-	            
-//                if(debug_local || debug) {
-//	                System.out.printf("%s: Apply rotation matrix:\n", this.getClass().getSimpleName());             
-//	                double mat[][] = alignmentCorrections.getRotation().getMatrix();
-//	                TransformationUtils.printMatrix(mat);
-//	                System.out.printf("%s: corresponding Rotation3D object:\n%s\n",this.getClass().getSimpleName(), rotMP.toString());
-//	                // Get the Cardan angles of the rotation
-//	                double res[] = alignmentCorrections.getRotation().getAngles(RotationOrder.ZYX);
-//	                // Since the rotation was created based on active transformations convert to passive right here. 
-//	                // This conversion is simply to reverse the order of rotations.
-//	                Hep3Vector res_passive = new BasicHep3Vector(res[2],res[1],res[0]);
-//	                System.out.printf("%s: Corresponding LCDD Cardan angles: %s\n", this.getClass().getSimpleName(), res_passive.toString());             
-//	                System.out.printf("%s: Apply local to mother rotation\n%s\n",this.getClass().getSimpleName(), getCoord().getTransformation().getRotation().toString());
-//	                System.out.printf("%s: resulting rotation correction to apply\n%s\n",this.getClass().getSimpleName(), r.toString());
-//                    
-//	            }
-
-                // Apply correction to coordinate system
-	            //getCoord().rotateApache(alignmentCorrections.getRotation());
-                //getCoord().rotate(r);
+	            
 
 	        } else {
 	            if(debug_local || debug) System.out.printf("%s: No rotation to coordinate system\n", this.getClass().getSimpleName());
@@ -304,7 +609,9 @@
 		if( getCenter()!=null) s += "Center of box: " + getCenter().toString() + "\n";
         if( getBoxDim()!=null) s += "Box dimensions: " + getBoxDim().toString() + "\n";
 		if(this.coord==null)   s += " No coord system \n";
-		else s += "Coordinate system:" + getCoord().toString() + "\n";
+		else {
+		    s += getName() + " origin " + getCoord().origin() + " u " + getCoord().u()+ " v " + getCoord().v()+ " w " + getCoord().w();
+		}
         s += "AlignmentCorrections: \n";
 		if(this.alignmentCorrections!=null) {
 		    s += "Milleparameters: ";
@@ -320,9 +627,16 @@
 		SurveyVolume m = getMother();
 		while(m!=null) {    
             Hep3Vector origin_m = HPSTrackerBuilder.transformToParent(new BasicHep3Vector(0, 0, 0), this, m.getName());
-            s += String.format("%s origin in %s : %s (mm)\n",getName(), m.getName(), origin_m.toString());            
-            origin_m = VecOp.mult(0.0393701, origin_m);
-            s += String.format("%s origin in %s : (%.4f %.4f %.4f) (inch)\n",getName(), m.getName(), origin_m.x(),origin_m.y(),origin_m.z());            
+            String unitVecStr = "";
+            if(getCoord()!=null) {
+                Hep3Vector u_m = HPSTrackerBuilder.rotateToParent(getCoord().u(), this, m.getName());
+                Hep3Vector v_m = HPSTrackerBuilder.rotateToParent(getCoord().v(), this, m.getName());
+                Hep3Vector w_m = HPSTrackerBuilder.rotateToParent(getCoord().w(), this, m.getName());
+                unitVecStr += String.format("u %s v %s w %s", u_m.toString(), v_m.toString(), w_m.toString());            
+            }
+            s += String.format("%s origin in %s : %s (mm) %s\n",getName(), m.getName(), origin_m.toString(), unitVecStr);            
+            //origin_m = VecOp.mult(0.0393701, origin_m);
+            //s += String.format("%s origin in %s : (%.4f %.4f %.4f) (inch)\n",getName(), m.getName(), origin_m.x(),origin_m.y(),origin_m.z());            
             m = m.getMother();
 		}
 		
@@ -330,15 +644,6 @@
 		return s;
 	}
 	
-//	private void printCoordInfo() {
-//	    if(debug) {
-//	        SurveyVolume m = getMother();
-//	        while(m!=null) {    
-//	            Hep3Vector origin_m = HPSTrackerBuilder.transformToParent(getCoord().origin(), this, m.getName());
-//	            System.out.printf("%s: %s final coord system in %s : %s\n",this.getClass().getSimpleName(),getName(), getMother()==null?" <no mother> ":getMother().getName(),getCoord().toString());            
-//	        }
-//	        System.out.printf("%s: init of SurveyVolume %s DONE\n",this.getClass().getSimpleName(),getName());            
-//	    }
-//	}
+
 	
 }

Modified: java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2014Base.java
 =============================================================================
--- java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2014Base.java	(original)
+++ java/branches/HPSJAVA-488/detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/HPSTracker2014Base.java	Mon Jul  6 16:36:19 2015
@@ -32,7 +32,7 @@
  */
 public abstract class HPSTracker2014Base extends LCDDSubdetector {
 
-    protected boolean _debug = true;
+    protected boolean _debug = false;
     protected static HPSTrackerLCDDBuilder builder;
     private final boolean buildBeamPlane = false;
     private final double beamPlaneWidth = 385.00;

Modified: java/branches/HPSJAVA-488/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java
 =============================================================================
--- java/branches/HPSJAVA-488/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java	(original)
+++ java/branches/HPSJAVA-488/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterUtilities.java	Mon Jul  6 16:36:19 2015
@@ -531,4 +531,13 @@
         }
         return sort(clusters, new ClusterEnergyComparator(), true, true).get(0);
     }
+    
+    /**
+     * Return the time of the seed hit.
+     * @param cluster
+     * @return the seed hit time
+     */
+    public static double getSeedHitTime(Cluster cluster) {
+        return findSeedHit(cluster).getTime();
+    }
 }

Modified: java/branches/HPSJAVA-488/evio/src/main/java/org/hps/evio/LCSimEngRunEventBuilder.java
 =============================================================================
--- java/branches/HPSJAVA-488/evio/src/main/java/org/hps/evio/LCSimEngRunEventBuilder.java	(original)
+++ java/branches/HPSJAVA-488/evio/src/main/java/org/hps/evio/LCSimEngRunEventBuilder.java	Mon Jul  6 16:36:19 2015
@@ -4,8 +4,8 @@
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-
 import org.hps.recon.ecal.triggerbank.AbstractIntData;
+import org.hps.recon.ecal.triggerbank.HeadBankData;
 import org.hps.recon.ecal.triggerbank.SSPData;
 import org.hps.recon.ecal.triggerbank.TDCData;
 import org.hps.recon.ecal.triggerbank.TIData;
@@ -51,6 +51,7 @@
         intBanks = new ArrayList<IntBankDefinition>();
         intBanks.add(new IntBankDefinition(SSPData.class, new int[] {sspCrateBankTag, sspBankTag}));
         intBanks.add(new IntBankDefinition(TIData.class, new int[] {sspCrateBankTag, 0xe10a}));
+        intBanks.add(new IntBankDefinition(HeadBankData.class, new int[] {sspCrateBankTag, 0xe10f}));
         intBanks.add(new IntBankDefinition(TDCData.class, new int[] {0x3a, 0xe107}));
         // ecalReader = new ECalEvioReader(0x25, 0x27);
         triggerConfigReader = new TriggerConfigEvioReader();

Modified: java/branches/HPSJAVA-488/integration-tests/src/test/java/org/hps/test/it/EcalSimReconTest.java
 =============================================================================
--- java/branches/HPSJAVA-488/integration-tests/src/test/java/org/hps/test/it/EcalSimReconTest.java	(original)
+++ java/branches/HPSJAVA-488/integration-tests/src/test/java/org/hps/test/it/EcalSimReconTest.java	Mon Jul  6 16:36:19 2015
@@ -33,7 +33,7 @@
     /**
      * Steering resource file for readout simulation.
      */    
-    private static final String READOUT_STEERING = "/org/hps/steering/readout/EngineeringRun2015TrigPairs1.lcsim";
+    private static final String READOUT_STEERING = "/org/hps/steering/readout/EngineeringRun2015TrigSingles1.lcsim";
     
     /**
      * Steering resource file for running reconstruction.
@@ -44,6 +44,36 @@
      * Run number for conditions system.
      */
     private static final Integer RUN = 5000;
+    
+    /**
+     * Expected mean of high cluster energy in GeV.
+     */
+    private static final double HIGH_CLUS_MEAN_E = 1.00;
+    
+    /**
+     * Acceptable delta of high cluster mean energy in GeV.
+     */
+    private static final double HIGH_CLUS_DELTA_E = 0.02;
+    
+    /**
+     * Expected mean time of primary cluster in nanoseconds.
+     */
+    private static final double CLUS_MEAN_T = 150;   
+    
+    /**
+     * Acceptable delta of cluster time in nanoseconds.
+     */    
+    private static final double CLUS_DELTA_T = 10;
+    
+    /**
+     * Expected number of triggers.
+     */
+    private static final int TRIGGERS = 650;
+    
+    /**
+     * Acceptable delta of trigger count.
+     */
+    private static final int TRIGGER_DELTA = 3;
     
     /**
      * Run the test.
@@ -81,10 +111,14 @@
         // Check the recon output.
         LCSimLoop loop = new LCSimLoop();
         loop.setLCIORecordSource(reconFile);
-        loop.add(new EcalSimReconCheckDriver());
+        EcalSimReconCheckDriver checkDriver = new EcalSimReconCheckDriver();
+        loop.add(checkDriver);
         loop.loop(-1);
         loop.dispose();
         System.out.println("EcalSimReconCheckDriver ran on " + loop.getTotalCountableConsumed() + " events");
+        
+        // Check the number of triggers.
+        TestCase.assertEquals("Number of triggers out of range.", TRIGGERS, loop.getTotalCountableConsumed(), TRIGGER_DELTA);
     }
     
     /**
@@ -117,8 +151,8 @@
         /**
          * First hit time in highest energy cluster.
          */
-        private final IHistogram1D clusTimeH1D = aida.histogram1D("Cluster Time", 500, -0.5, 499.5);
-                
+        private final IHistogram1D clusTimeH1D = aida.histogram1D("Cluster Time", 500, -0.5, 499.5);        
+              
         /**
          * Process events and fill histograms from cluster collection.
          */
@@ -135,22 +169,28 @@
         }
         
         /**
-         * Save histograms and perform checks on histogram statistics.
+         * Save histograms and perform checks on statistics.
          */
         public void endOfData() {
             
-            System.out.println("clusCountH1D mean: " + clusCountH1D.mean()); 
+            // Print some statistics.
+            System.out.println("clusCountH1D mean: " + clusCountH1D.mean());
             System.out.println("clusEnergyH1D mean: " + clusEnergyH1D.mean());
             System.out.println("clusHighEnergyH1D mean: " + clusHighEnergyH1D.mean());
             System.out.println("clusTimeH1D mean: " + clusTimeH1D.mean());
             
-            // TODO: Add test assertions here.
-            
+            // Save plots to AIDA file.
             try {
                 aida.saveAs(new TestOutputFile(EcalSimReconTest.class, "plots.aida"));
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
+            
+            // Check high cluster energy mean.
+            TestCase.assertEquals("High cluster energy was not within range.", HIGH_CLUS_MEAN_E, clusHighEnergyH1D.mean(), HIGH_CLUS_DELTA_E);
+            
+            // Check high cluster time mean.
+            TestCase.assertEquals("High cluster mean time was not within range.", CLUS_MEAN_T, clusTimeH1D.mean(), CLUS_DELTA_T);            
         }
     }    
 }

Modified: java/branches/HPSJAVA-488/parent/pom.xml
 =============================================================================
--- java/branches/HPSJAVA-488/parent/pom.xml	(original)
+++ java/branches/HPSJAVA-488/parent/pom.xml	Mon Jul  6 16:36:19 2015
@@ -12,7 +12,7 @@
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <org.lcsim.cacheDir>${user.home}</org.lcsim.cacheDir>
-        <lcsimVersion>3.1.1</lcsimVersion>
+        <lcsimVersion>3.1.3</lcsimVersion>
         <skipSite>false</skipSite>
         <skipPlugin>false</skipPlugin>
     </properties>

Modified: java/branches/HPSJAVA-488/plugin/pom.xml
 =============================================================================
--- java/branches/HPSJAVA-488/plugin/pom.xml	(original)
+++ java/branches/HPSJAVA-488/plugin/pom.xml	Mon Jul  6 16:36:19 2015
@@ -42,7 +42,7 @@
                         </property>
                         <property>
                             <name>org.jlab.coda:*</name>
-                            <value>http://srs.slac.stanford.edu/nexus/content/groups/lcsim-maven2-public/</value>
+                            <value>https://coda.jlab.org/maven/</value>
                         </property>
                     </urls>
                     <redirectUrls>

Modified: java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/JCacheManager.java
 =============================================================================
--- java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/JCacheManager.java	(original)
+++ java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/JCacheManager.java	Mon Jul  6 16:36:19 2015
@@ -50,6 +50,11 @@
          * The current status from executing the 'jcache request' command.
          */
         private String status;
+        
+        /**
+         * The xml node with request data.
+         */
+        private Element xml;
 
         /**
          * Create a new <code>CacheStatus</code> object.
@@ -94,7 +99,7 @@
                 throw new RuntimeException(e);
             }
             // LOGGER.finer("raw XML: " + xmlString);
-            xmlString = xmlString.substring(xmlString.trim().indexOf("<?xml") + 1);
+            xmlString = xmlString.substring(xmlString.trim().indexOf("<jcache>"));
             // LOGGER.finer("cleaned XML: " + xmlString);
             return buildDocument(xmlString).getRootElement();
         }
@@ -122,38 +127,58 @@
         }
 
         /**
-         * Return </code>true</code> if status is "done".
-         *
-         * @return </code>true</code> if status is "done"
+         * Return <code>true</code> if status is "done".
+         *
+         * @return <code>true</code> if status is "done"
          */
         boolean isDone() {
             return "done".equals(this.status);
         }
 
         /**
-         * Return </code>true</code> if status is "hit".
-         *
-         * @return </code>true</code> if status is "hit"
+         * Return <code>true</code> if status is "hit".
+         *
+         * @return <code>true</code> if status is "hit"
          */
         boolean isHit() {
             return "hit".equals(this.status);
         }
 
         /**
-         * Return </code>true</code> if status is "pending".
-         *
-         * @return </code>true</code> if status is "pending"
+         * Return <code>true</code> if status is "pending".
+         *
+         * @return <code>true</code> if status is "pending"
          */
         boolean isPending() {
             return "pending".equals(this.status);
         }
-
-        /**
-         * Request the file status string using the 'jcache request' command.
-         *
-         * @return the file status string
-         */
-        private String requestFileStatus() {
+        
+        /**
+         * Return <code>true</code> if status is "failed".
+         */
+        boolean isFailed() {
+            return "failed".equals(this.status);
+        }
+        
+        /**
+         * Get the error message from the XML request.
+         * 
+         * @return the error message from the XML request
+         */
+        String getErrorMessage() {
+            if (this.xml.getChild("request").getChild("file").getChild("error") != null) {
+                return this.xml.getChild("request").getChild("file").getChild("error").getText();
+            } else {
+                return "";
+            }
+        }
+      
+        /**
+         * Run the <i>jcache request</i> command for this request ID and return the XML output.
+         * 
+         * @return the XML output from the <i>jcache request</i> command
+         */
+        private Element request() {
             Process process = null;
             try {
                 process = new ProcessBuilder(JCACHE_COMMAND, "request", this.requestId.toString()).start();
@@ -169,15 +194,22 @@
             if (status != 0) {
                 throw new RuntimeException("The jcache request returned an error status: " + status);
             }
-            return this.getRequestXml(process.getInputStream()).getChild("request").getChild("file").getChildText("status");
+            return this.getRequestXml(process.getInputStream());            
         }
 
         /**
          * Update the cache status.
          */
         void update() {
-            this.status = this.requestFileStatus();
+            // Request status update and get the XML from that process.
+            this.xml = request();
+            
+            // Update the status from the XML.
+            this.status = this.xml.getChild("request").getChild("file").getChildText("status");
+            
+            // Is request done or file already in cache?
             if (this.isDone() || this.isHit()) {
+                // Flag file as cached.
                 this.cached = true;
             }
         }
@@ -210,6 +242,7 @@
      * @return the XML document
      */
     private static Document buildDocument(final String xmlString) {
+        LOGGER.fine("building doc from string: " + xmlString);
         final SAXBuilder builder = new SAXBuilder();
         Document document = null;
         try {
@@ -343,6 +376,13 @@
                 } else {
                     // Log that this file is now cached. It will not be checked next time.
                     LOGGER.info(cacheStatus.getFile().getPath() + " is cached with status " + cacheStatus.getStatus(false));
+                }
+                
+                // Did the request fail?
+                if (cacheStatus.isFailed()) {
+                    // Cache failure is a fatal error.
+                    LOGGER.severe("cache request failed with error: " + cacheStatus.getErrorMessage());
+                    throw new RuntimeException("Cache request failed.");
                 }
             } else {
                 LOGGER.info(cacheStatus.getFile().getPath() + " is already cached");

Modified: java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunLog.java
 =============================================================================
--- java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunLog.java	(original)
+++ java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunLog.java	Mon Jul  6 16:36:19 2015
@@ -11,8 +11,9 @@
 import org.lcsim.util.log.LogUtil;
 
 /**
- * This class contains summary information about a series of runs that are themselves modeled with the {@link RunSummary} class. These can be looked
- * up by their run number {@link #getRunSummary(int)}.
+ * This class contains summary information about a series of runs which are modeled with the {@link RunSummary} class.
+ * <p> 
+ * These can be looked up by their run number {@link #getRunSummary(int)}.
  *
  * @author Jeremy McCormick, SLAC
  */

Modified: java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunLogUpdater.java
 =============================================================================
--- java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunLogUpdater.java	(original)
+++ java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunLogUpdater.java	Mon Jul  6 16:36:19 2015
@@ -5,13 +5,12 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.hps.conditions.database.ConnectionParameters;
 import org.lcsim.util.log.LogUtil;
 
 /**
  * Updates the run database with information from the crawler job.
  * <p>
- * The {@link RunSummaryUpdater} is used to insert rows for each run.
+ * The {@link RunSummaryUpdater} is used to insert the data for each run.
  * 
  * @author Jeremy McCormick, SLAC
  */
@@ -38,47 +37,26 @@
     private boolean allowUpdates = false;
     
     /**
-     * <code>true</code> if EPICS data should be put into the database (skipped if not).
-     */
-    private boolean insertEpicsData = true;
-
-    /**
      * Create a new updater.
      * 
      * @param runLog the run information
      * @param allowUpdates <code>true</code> if updates should be allowed
      */
-    RunLogUpdater(RunLog runLog, boolean allowUpdates) {
+    RunLogUpdater(Connection connection, RunLog runLog, boolean allowUpdates) {
+        
+        // Set the DB connection.
+        this.connection = connection;
+        
+        // Set the run log with the run info to update.
         this.runLog = runLog;
         
-        // Create database connection to use in this session.
-        final ConnectionParameters cp = new ConnectionParameters("root", "derp", "hps_run_db", "localhost");
-        connection = cp.createConnection();
+        // Set whether db updates are allowed (replacement of existing records).
+        this.allowUpdates = allowUpdates;
     }
-    
+            
     /**
-     * Set to <code>true</code> if EPICS data should be inserted.
-     * 
-     * @param insertEpicsData <code>true</code> 
-     */
-    void setInsertEpicsData(boolean insertEpicsData) {
-        this.insertEpicsData = insertEpicsData;
-    }
-    
-    /**
-     * Close the database connection.
-     */
-    void close() {
-        try {
-            connection.close();
-        } catch (SQLException e) {
-            e.printStackTrace();
-        }
-    }
-    
-    /**
-     * Insert the run summary information into the database, including updating the run_log_files
-     * and run_log_epics tables.
+     * Insert the run summary information into the database, including updating the <i>run_log_files</i>
+     * and <i>run_log_epics</i> tables.
      *
      * @param connection the database connection
      * @throws SQLException if there is an error querying the database
@@ -96,68 +74,21 @@
                 
                 // Get the RunSummary data for the run.
                 RunSummary runSummary = runLog.getRunSummary(run);
-                
+                                               
                 LOGGER.info("updating " + runSummary);
                                 
                 // Create the db updater for the RunSummary.
-                RunSummaryUpdater runUpdater = new RunSummaryUpdater(connection, runSummary);      
-                                
-                // Does a row already exist for the run?
-                if (runUpdater.runExists()) {
-                    LOGGER.info("record for " + run + " exists already");
-                    // Are updates allowed?
-                    if (allowUpdates) {
-                        LOGGER.info("existing row for " + run + " will be updated");
-                        // Update existing row.
-                        runUpdater.updateRun();
-                    } else {
-                        // Row exists and updates not allowed which is an error.
-                        throw new RuntimeException("Row already exists for run " + run + " and allowUpdates is false.");
-                    }
-                } else {                
-                                        
-                    LOGGER.info("inserting new row in runs for run " + run + " ...");
-                    
-                    // Insert new record into run_log.
-                    runUpdater.insertRun();
-                }
+                RunSummaryUpdater runUpdater = new RunSummaryUpdater(connection, runSummary);
+                                                
+                // Set whether existing records can be replaced.
+                runUpdater.setAllowDeleteExisting(allowUpdates);
                 
-                // Do records exist in the run_log_files table?
-                if (runUpdater.filesExist()) {
-                    // Are updates disallowed?
-                    if (!allowUpdates) { 
-                        // File records exist for the run but updating is allowed so throw an exception.
-                        throw new RuntimeException("Cannot delete existing records in run_log_files because allowUpdates is false.");
-                    } else {
-                        // Delete the file log.
-                        runUpdater.deleteFiles();
-                    }
-                }
-                                
-                // Insert records into run_log_files now that existing records were deleted, if necessary.
-                runUpdater.insertFiles();
+                LOGGER.info("allow updates: " + allowUpdates);
                 
-                // Is EPICS data processing enabled?
-                if (insertEpicsData) {
-                    // Does the EPICS data already exist?
-                    if (runUpdater.epicsExists()) {
-                        // Is replacing data disallowed?
-                        if (!allowUpdates) {
-                            // EPICS data exists but updating is not allowed so throw exception.
-                            throw new RuntimeException("EPICS run log already exists and allowUpdates is false.");
-                        } else {
-                            // Delete existing EPICS data.
-                            runUpdater.deleteEpics();
-                        }
-                    }
-                    
-                    // Insert EPICS data processed in the job for this run.
-                    runUpdater.insertEpics();
-                }
+                // Insert the run records.
+                runUpdater.insert();
                 
-                // Commit the transactions for this run.
-                LOGGER.info("committing transaction for run " + run);
-                connection.commit();
+                LOGGER.info("run " + runSummary.getRun() + " summary inserted successfully");
             }
             
         } catch (final SQLException e) {
@@ -168,13 +99,7 @@
                 LOGGER.log(Level.SEVERE, "error rolling back transaction", e2);
                 throw new RuntimeException(e);
             }
-        } finally {
-            try {
-                connection.close();
-            } catch (final SQLException e) {
-                throw new RuntimeException(e);
-            }
-        }
+        } 
         
         LOGGER.info("done inserting run data");
     }             

Modified: java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunProcessor.java
 =============================================================================
--- java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunProcessor.java	(original)
+++ java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunProcessor.java	Mon Jul  6 16:36:19 2015
@@ -10,6 +10,7 @@
 
 import org.hps.record.evio.EvioEventConstants;
 import org.hps.record.evio.EvioEventProcessor;
+import org.hps.record.scalers.ScalersEvioProcessor;
 import org.jlab.coda.jevio.EvioEvent;
 import org.jlab.coda.jevio.EvioException;
 import org.jlab.coda.jevio.EvioReader;
@@ -17,7 +18,7 @@
 import org.lcsim.util.log.LogUtil;
 
 /**
- * Processes all the EVIO files from a run in order to extract various information including start and end dates.
+ * Processes EVIO files from a run in order to extract various meta data information including start and end dates.
  * <p>
  * This class is a wrapper for activating different sub-tasks, including optionally caching all files from the JLAB MSS to the cache disk.
  * <p>
@@ -33,6 +34,42 @@
     private static final Logger LOGGER = LogUtil.create(RunProcessor.class, new DefaultLogFormatter(), Level.FINE);
 
     /**
+     * Create the processor for a single run.
+     *
+     * @param runSummary the run summary for the run
+     * @return the run processor
+     */
+    static RunProcessor createRunProcessor(final JCacheManager cacheManager, final RunSummary runSummary, CrawlerConfig config) {
+
+        // Create new run processor.
+        final RunProcessor processor = new RunProcessor(runSummary, cacheManager);
+
+        // EPICS processor.
+        processor.addProcessor(new EpicsLog(runSummary));
+
+        // Scaler data processor.
+        final ScalersEvioProcessor scalersProcessor = new ScalersEvioProcessor();
+        scalersProcessor.setResetEveryEvent(false);
+        processor.addProcessor(scalersProcessor);
+
+        // Event log processor.
+        processor.addProcessor(new EventTypeLog(runSummary));
+
+        // Max files.
+        if (config.maxFiles() != -1) {
+            processor.setMaxFiles(config.maxFiles());
+        }
+
+        // Enable file caching.
+        processor.useFileCache(config.useFileCache());
+
+        // Set event printing interval.
+        processor.setEventPrintInterval(config.eventPrintInterval());
+
+        return processor;
+    }
+
+    /**
      * The cache manager.
      */
     private final JCacheManager cacheManager;
@@ -107,7 +144,7 @@
 
     /**
      * Get the event count from the current <code>EvioReader</code>.
-     * 
+     *
      * @param reader the current <code>EvioReader</code>
      * @return the event count
      * @throws IOException if there is a generic IO error
@@ -142,22 +179,30 @@
         return this.processors;
     }
 
-    /**
-     * Return <code>true</code> if a valid CODA <i>END</i> event can be located in the
-     * <code>EvioReader</code>'s current file. 
-     * 
+    ScalersEvioProcessor getScalersProcessor() {
+        for (final EvioEventProcessor processor : this.processors) {
+            if (processor instanceof ScalersEvioProcessor) {
+                return ScalersEvioProcessor.class.cast(processor);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return <code>true</code> if a valid CODA <i>END</i> event can be located in the <code>EvioReader</code>'s current file.
+     *
      * @param reader the EVIO reader
      * @return <code>true</code> if valid END event is located
      * @throws Exception if there are IO problems using the reader
      */
     boolean isEndOkay(final EvioReader reader) throws Exception {
         LOGGER.info("checking is END okay ...");
-        
+
         boolean endOkay = false;
-        
+
         // Go to second to last event for searching.
         reader.gotoEventNumber(reader.getEventCount() - 2);
-        
+
         // Look for END event.
         EvioEvent event = null;
         while ((event = reader.parseNextEvent()) != null) {
@@ -170,8 +215,8 @@
     }
 
     /**
-     * Process the run by executing the registered {@link org.hps.record.evio.EvioEventProcessor}s and 
-     * performing special tasks such as the extraction of start and end dates.
+     * Process the run by executing the registered {@link org.hps.record.evio.EvioEventProcessor}s and performing special tasks such as the extraction
+     * of start and end dates.
      * <p>
      * This method will also activate file caching, if enabled by the {@link #useFileCache} option.
      *
@@ -230,13 +275,13 @@
                 this.runSummary.setStartDate(runStart);
             }
 
-            // Compute event count for the file and store the value in the run summary's file list.
+            // Compute the event count for the file and store the value in the run summary's file list.
             LOGGER.info("getting event count for " + file.getPath() + "...");
             final int eventCount = this.computeEventCount(reader);
             this.runSummary.getEvioFileList().setEventCount(file, eventCount);
             LOGGER.info("set event count " + eventCount + " for " + file.getPath());
 
-            // Process the events using the list of EVIO processors.
+            // Process the events using the EVIO processors.
             LOGGER.info("running EVIO processors ...");
             reader.gotoEventNumber(0);
             int nProcessed = 0;
@@ -266,6 +311,12 @@
                 LOGGER.info("found end date " + endDate);
             }
 
+            // Pull scaler data from EVIO processor into run summary.
+            final ScalersEvioProcessor scalersProcessor = this.getScalersProcessor();
+            if (scalersProcessor != null) {
+                runSummary.setScalerData(scalersProcessor.getScalerData());
+            }
+
         } finally {
             if (reader != null) {
                 reader.close();
@@ -306,5 +357,42 @@
         this.useFileCache = cacheFiles;
         LOGGER.config("file caching enabled");
     }
-
+    
+    /**
+     * Process all the runs that were found.
+     *
+     * @param runs the run log containing the list of run summaries
+     * @throws Exception if there is an error processing one of the runs
+     */
+    static void processRuns(JCacheManager cacheManager, final RunLog runs, CrawlerConfig config) throws Exception {
+        
+        // Configure max wait time of jcache manager.
+        if (config.waitTime() != null && config.waitTime() > 0L) {
+            cacheManager.setWaitTime(config.waitTime());
+            LOGGER.config("JCacheManager max wait time set to " + config.waitTime());
+        }                                
+        
+        // Process all of the runs that were found.
+        for (final int run : runs.getSortedRunNumbers()) {
+            
+            // Get the run summary.
+            RunSummary runSummary = runs.getRunSummary(run);
+            
+            // Clear the cache manager.
+            if (config.useFileCache()) {
+                cacheManager.clear();
+            }
+
+            // Create a processor to process all the EVIO events in the run.
+            final RunProcessor runProcessor = RunProcessor.createRunProcessor(cacheManager, runSummary, config);
+
+            for (final EvioEventProcessor processor : config.processors()) {
+                runProcessor.addProcessor(processor);
+                LOGGER.config("added extra EVIO processor " + processor.getClass().getName());
+            }
+
+            // Process all of the runs files.
+            runProcessor.process();
+        }
+    }
 }

Modified: java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunSummary.java
 =============================================================================
--- java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunSummary.java	(original)
+++ java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunSummary.java	Mon Jul  6 16:36:19 2015
@@ -2,16 +2,21 @@
 
 import java.io.File;
 import java.io.PrintStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.GregorianCalendar;
 import java.util.Map;
+import java.util.TimeZone;
 import java.util.logging.Logger;
 
 import org.hps.record.epics.EpicsData;
+import org.hps.record.scalers.ScalerData;
 import org.lcsim.util.log.LogUtil;
 
 /**
- * This class models the run summary information which is persisted as a row in the <i>run_log</i> table
- * of the run database.
+ * This class models the run summary information which is persisted as a row in the <i>run_log</i>
+ * table of the run database.
  * <p>
  * This information includes:
  * <ul>
@@ -26,8 +31,16 @@
  *
  * @author Jeremy McCormick, SLAC
  */
-final class RunSummary {
-
+public final class RunSummary {
+
+    /**
+     * Set up date formatting to display EST (GMT-4).
+     */
+    private static final DateFormat DATE_DISPLAY = new SimpleDateFormat();
+    static {
+        DATE_DISPLAY.setCalendar(new GregorianCalendar(TimeZone.getTimeZone("America/New_York")));
+    }
+    
     /**
      * Setup logger.
      */
@@ -62,6 +75,11 @@
      * The run number.
      */
     private final int run;
+
+    /**
+     * The scaler data from the last physics event in the run.
+     */
+    private ScalerData scalerData;
 
     /**
      * The start date of the run.
@@ -101,7 +119,7 @@
      *
      * @return the date when the run ended
      */
-    Date getEndDate() {
+    public Date getEndDate() {
         return this.endDate;
     }
 
@@ -112,7 +130,7 @@
      *
      * @return the EPICS data summary
      */
-    EpicsData getEpicsData() {
+    public EpicsData getEpicsData() {
         return this.epics;
     }
 
@@ -121,7 +139,7 @@
      *
      * @return the counts of different event types
      */
-    Map<Object, Integer> getEventTypeCounts() {
+    public Map<Object, Integer> getEventTypeCounts() {
         return this.eventTypeCounts;
     }
 
@@ -130,25 +148,34 @@
      *
      * @return the list of EVIO files in this run
      */
-    EvioFileList getEvioFileList() {
+    public EvioFileList getEvioFileList() {
         return this.files;
     }
-
+    
     /**
      * Get the run number.
      *
      * @return the run number
      */
-    int getRun() {
+    public int getRun() {
         return this.run;
     }
 
     /**
+     * Get the scaler data of this run (last event only).
+     * 
+     * @return the scaler data of this run from the last event
+     */
+    public ScalerData getScalerData() {
+        return this.scalerData;
+    }
+
+    /**
      * Get the start date of the run.
      *
      * @return the start date of the run
      */
-    Date getStartDate() {
+    public Date getStartDate() {
         return this.startDate;
     }
 
@@ -157,19 +184,47 @@
      *
      * @return the total events in the run
      */
-    int getTotalEvents() {
+    public int getTotalEvents() {
         if (this.totalEvents == -1) {
             this.totalEvents = this.files.getTotalEvents();
         }
         return this.totalEvents;
     }
+    
+    /**
+     * Get the number of seconds in the run which is the difference between the start and end times.
+     * 
+     * @return the total seconds in the run
+     */
+    public long getTotalSeconds() {
+        if (this.getStartDate() == null) {
+            throw new RuntimeException("missing start date");
+        }
+        if (this.getEndDate() == null) {
+            throw new RuntimeException("missing end date");
+        }
+        return (getEndDate().getTime() - getStartDate().getTime()) / 1000;
+    }
+    
+    /**
+     * Get the event rate (effectively the trigger rate) which is the total events divided by the number
+     * of seconds in the run.
+     * 
+     * @return the event rate
+     */
+    public double getEventRate() {
+        if (this.getTotalEvents() <= 0) {
+            throw new RuntimeException("Total events is zero or invalid.");
+        }
+        return (double) this.getTotalEvents() / (double) this.getTotalSeconds();
+    }
 
     /**
      * Return <code>true</code> if END event was found in the data.
      *
      * @return <code>true</code> if END event was in the data
      */
-    boolean isEndOkay() {
+    public boolean isEndOkay() {
         return this.endOkay;
     }
 
@@ -178,19 +233,21 @@
      *
      * @param ps the print stream for output
      */
-    void printRunSummary(final PrintStream ps) {
+    public void printRunSummary(final PrintStream ps) {
         ps.println("--------------------------------------------");
         ps.println("run: " + this.run);
         ps.println("first file: " + this.files.first());
         ps.println("last file: " + this.files.last());
-        ps.println("started: " + this.getStartDate());
-        ps.println("ended: " + this.getEndDate());
+        ps.println("started: " + DATE_DISPLAY.format(this.getStartDate()));
+        ps.println("ended: " + DATE_DISPLAY.format(this.getEndDate()));
         ps.println("total events: " + this.getTotalEvents());
+        ps.println("end OK: " + this.isEndOkay());
+        ps.println("event rate: " + this.getEventRate());
         ps.println("event types");
         for (final Object key : this.eventTypeCounts.keySet()) {
             ps.println("  " + key + ": " + this.eventTypeCounts.get(key));
         }
-        ps.println("files " + this.files.size());
+        ps.println(this.files.size() + " files");
         for (final File file : this.files) {
             ps.println("  " + file.getPath());
         }
@@ -232,6 +289,10 @@
         this.eventTypeCounts = eventTypeCounts;
     }
 
+    void setScalerData(final ScalerData scalerData) {
+        this.scalerData = scalerData;
+    }
+
     /**
      * Set the start date of the run.
      *
@@ -247,9 +308,15 @@
     void sortFiles() {
         this.files.sort();
     }
-    
+
+    /**
+     * Convert this object to a string.
+     * 
+     * @return this object converted to a string
+     */
+    @Override
     public String toString() {
-        return "RunSummary { run: " + this.run + ", started: " + this.getStartDate() + ", ended: " + this.getEndDate() + ", events: " 
+        return "RunSummary { run: " + this.run + ", started: " + this.getStartDate() + ", ended: " + this.getEndDate() + ", events: "
                 + this.getTotalEvents() + ", endOkay: " + endOkay + " }";
     }
 }

Modified: java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryUpdater.java
 =============================================================================
--- java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryUpdater.java	(original)
+++ java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/RunSummaryUpdater.java	Mon Jul  6 16:36:19 2015
@@ -13,7 +13,7 @@
 
 /**
  * Updates the run database tables with information from a single run.
- * 
+ *
  * @author Jeremy McCormick, SLAC
  */
 public class RunSummaryUpdater {
@@ -22,105 +22,190 @@
      * Setup logging.
      */
     private static final Logger LOGGER = LogUtil.create(RunSummaryUpdater.class);
-    
+
+    /**
+     * Flag to allow deletion/replacement of existing records; disallowed by default.
+     */
+    private boolean allowDeleteExisting = false;
+
+    /**
+     * The database connection.
+     */
+    private final Connection connection;
+
+    /**
+     * The run number (read from the summary in the constructor for convenience).
+     */
+    private int run = -1;
+
     /**
      * The run summary to update or insert.
      */
-    private RunSummary runSummary;   
-    
-    /**
-     * The database connection.
-     */
-    private Connection connection;
-    
-    /**
-     * The run number (read from the summary in the constructor for convenience).
-     */
-    private int run = -1;
-        
+    private final RunSummary runSummary;
+
     /**
      * Create a <code>RunSummaryUpdater</code> for the given <code>RunSummary</code>.
-     * 
+     *
      * @param connection the database connection
      * @param runSummary the run summary to update or insert
      */
-    RunSummaryUpdater(Connection connection, RunSummary runSummary) {
+    RunSummaryUpdater(final Connection connection, final RunSummary runSummary) {
 
         if (connection == null) {
             throw new IllegalArgumentException("connection is null");
         }
         this.connection = connection;
-        
+
         if (runSummary == null) {
             throw new IllegalArgumentException("runSummary is null");
         }
         this.runSummary = runSummary;
+
+        // Cache run number.
+        this.run = this.runSummary.getRun();
+    }
+
+    private void delete() throws SQLException {
+
+        LOGGER.info("deleting existing information for run " + runSummary.getRun());
+
+        // Delete EPICS log.
+        this.deleteEpics();
+
+        // Delete scaler data.
+        this.deleteScalerData();
         
-        this.run = this.runSummary.getRun();
-    }
+        // Delete file list.
+        this.deleteFiles();
+
+        // Delete run log.
+        this.deleteRun();
+                
+        LOGGER.info("deleted run " + runSummary.getRun() + " info successfully");
+    }
+
+    /**
+     * Delete existing EPICS data from the run_log_epics table.
+     *
+     * @throws SQLException if there is an error performing the db query
+     */
+    private void deleteEpics() throws SQLException {
+        final PreparedStatement statement = connection.prepareStatement("DELETE FROM run_epics WHERE run = ?");
+        statement.setInt(1, this.run);
+        statement.executeUpdate();
+    }
+    
+    /**
+     * Delete existing EPICS data from the run_log_epics table.
+     *
+     * @throws SQLException if there is an error performing the db query
+     */
+    private void deleteScalerData() throws SQLException {
+        final PreparedStatement statement = connection.prepareStatement("DELETE FROM run_scalers WHERE run = ?");
+        statement.setInt(1, this.run);
+        statement.executeUpdate();
+    }
+
+    /**
+     * Delete the records of the files associated to this run.
+     *
+     * @param files the list of files
+     * @throws SQLException if there is an error executing the SQL query
+     */
+    private void deleteFiles() throws SQLException {
+        LOGGER.info("deleting rows from run_files for " + run + " ...");
+        final PreparedStatement s = connection.prepareStatement("DELETE FROM run_files where run = ?");
+        s.setInt(1, run);
+        s.executeUpdate();
+        LOGGER.info("done deleting rows from run_files for " + run);
+    }
+
+    /**
+     * Delete the row for this run from the <i>runs</i> table.
+     * <p>
+     * This doesn't delete the rows from <i>run_epics</i> or <i>run_files</i>.
+     *
+     * @throws SQLException if there is an error executing the SQL query
+     */
+    private void deleteRun() throws SQLException {
+        LOGGER.info("deleting record from runs for " + run + " ...");
+        final PreparedStatement s = connection.prepareStatement("DELETE FROM runs where run = ?");
+        s.setInt(1, run);
+        s.executeUpdate();
+        LOGGER.info("deleted rows from runs for " + run);
+    }
+
+    void insert() throws SQLException {
         
-    /**
-     * Execute a SQL update to modify an existing row in the database.
-     * 
-     * @throws SQLException if there is an error executing the SQL statement
-     */
-    void updateRun() throws SQLException {
-        
-        PreparedStatement runLogStatement = null;
-        runLogStatement = 
-                connection.prepareStatement("UPDATE runs SET start_date = ?, end_date = ?, nevents = ?, nfiles = ?, end_ok = ? where run = ?");        
-        LOGGER.info("preparing to update run " + run + " in runs table ..");
-        runLogStatement.setTimestamp(1, new java.sql.Timestamp(runSummary.getStartDate().getTime()));
-        runLogStatement.setTimestamp(2, new java.sql.Timestamp(runSummary.getEndDate().getTime()));
-        runLogStatement.setInt(3, runSummary.getTotalEvents());
-        runLogStatement.setInt(4, runSummary.getEvioFileList().size());
-        runLogStatement.setBoolean(5, runSummary.isEndOkay());
-        runLogStatement.setInt(6, run);
-        runLogStatement.executeUpdate();
-        LOGGER.info("run " + run + " was updated");
-    }
-    
-    /**
-     * Insert a new row in the <i>runs</i> table.
-     *
-     * @param connection the database connection
-     * @throws SQLException if there is an error querying the database
-     */
-    void insertRun() throws SQLException {
-        PreparedStatement statement = 
-                connection.prepareStatement("INSERT INTO runs (run, start_date, end_date, nevents, nfiles, end_ok) VALUES(?, ?, ?, ?, ?, ?)");
-        LOGGER.info("preparing to insert run " + run + " into runs table ..");
-        statement.setInt(1, run);
-        statement.setTimestamp(2, new java.sql.Timestamp(runSummary.getStartDate().getTime()));
-        statement.setTimestamp(3, new java.sql.Timestamp(runSummary.getEndDate().getTime()));
-        statement.setInt(4, runSummary.getTotalEvents());
-        statement.setInt(5, runSummary.getEvioFileList().size());
-        statement.setBoolean(6, runSummary.isEndOkay());
-        statement.executeUpdate();
-        LOGGER.info("inserted run " + run + " to runs table");
-    }
-    
-    /**
-     * Return <code>true</code> if there is an existing row for this run summary.
-     * 
-     * @return <code>true</code> if there is an existing row for this run summary.
-     * @throws SQLException if there is an error executing the SQL query
-     */
-    boolean runExists() throws SQLException {
-        PreparedStatement s = connection.prepareStatement("SELECT run FROM runs where run = ?");
-        s.setInt(1, run);        
-        ResultSet rs = s.executeQuery();
-        return rs.first();
-    }
-    
-    /**
-     * Insert the file names into the run database.    
+        LOGGER.info("performing db insert for " + runSummary);
+
+        // Turn auto-commit off as this whole method is a single transaction.
+        connection.setAutoCommit(false);
+
+        // Does the run exist in the database already?
+        if (this.runExists()) {
+            // Is deleting existing rows allowed?
+            if (this.allowDeleteExisting) {
+                // Delete the existing rows.
+                this.delete();
+            } else {
+                // Rows exist but updating is disallowed which is a fatal error.
+                final RuntimeException x = new RuntimeException("Run " + runSummary.getRun() + " already exists and deleting is not allowed.");
+                LOGGER.log(Level.SEVERE, x.getMessage(), x);
+                throw x;
+            }
+        }
+
+        // Insert basic run log info.
+        this.insertRun();
+
+        // Insert list of files.
+        this.insertFiles();
+
+        // Insert EPICS data.
+        this.insertEpics();
+
+        // Insert scaler data.
+        if (runSummary.getScalerData() != null) {
+            new ScalerDataUpdater(connection, runSummary.getScalerData(), run).insert();
+        }
+
+        // Commit the transactions for this run.
+        LOGGER.info("committing transaction for run " + run);
+        connection.commit();
+
+        // Turn auto-commit back on.
+        connection.setAutoCommit(true);
+    }
+
+    /**
+     * Insert EPICS data into the run_log_epics table.
+     *
+     * @throws SQLException if there is an error performing the db query
+     */
+    private void insertEpics() throws SQLException {
+        final PreparedStatement statement = connection.prepareStatement("INSERT INTO run_epics (run, variable_name, value) values (?, ?, ?)");
+        final EpicsData data = runSummary.getEpicsData();
+        if (data != null) {
+            for (final String variableName : data.getUsedNames()) {
+                statement.setInt(1, this.run);
+                statement.setString(2, variableName);
+                statement.setDouble(3, data.getValue(variableName));
+                statement.executeUpdate();
+            }
+        } else {
+            LOGGER.warning("skipped inserting EPICS data (none found in RunSummary)");
+        }
+    }
+
+    /**
+     * Insert the file names into the run database.
      *
      * @param connection the database connection
      * @param run the run number
      * @throws SQLException if there is a problem executing one of the database queries
      */
-    void insertFiles() throws SQLException {
+    private void insertFiles() throws SQLException {
         LOGGER.info("updating file list ...");
         PreparedStatement filesStatement = null;
         filesStatement = connection.prepareStatement("INSERT INTO run_files (run, directory, name) VALUES(?, ?, ?)");
@@ -134,90 +219,42 @@
             filesStatement.executeUpdate();
         }
         LOGGER.info("run_files was updated");
-    }    
-    
-    /**
-     * Delete the records of the files associated to this run.
-     * 
-     * @param files the list of files
-     * @throws SQLException if there is an error executing the SQL query
-     */
-    void deleteFiles() throws SQLException {        
-        LOGGER.info("deleting rows from run_files for " + run + " ...");
-        PreparedStatement s = connection.prepareStatement("DELETE FROM run_files where run = ?");
-        s.setInt(1, run);
-        s.executeUpdate();
-        LOGGER.info("done deleting rows from run_files for " + run);
-    }
-    
-    /**
-     * Delete the row for this run from the <i>runs</i> table.
-     * <p>
-     * This doesn't delete the rows from <i>run_epics</i> or <i>run_files</i>.
-     * 
-     * @throws SQLException if there is an error executing the SQL query
-     */
-    void deleteRun() throws SQLException {
-        LOGGER.info("deleting record from runs for " + run + " ...");
-        PreparedStatement s = connection.prepareStatement("DELETE FROM runs where run = ?");
-        s.setInt(1, run);
-        s.executeUpdate();
-        LOGGER.info("deleted rows from runs for " + run);
-    }
-    
-    /**
-     * Return <code>true</code> if there is a row for at least one file for the run.
-     * @return <code>true</code> if there are file rows for this run
-     * @throws SQLException if there is an error executing the SQL query
-     */
-    boolean filesExist() throws SQLException {
-        PreparedStatement s = connection.prepareStatement("SELECT run FROM run_files where run = ?");
-        s.setInt(1, run);        
-        ResultSet rs = s.executeQuery();
-        return rs.first();
-    }
-    
-    /**
-     * Insert EPICS data into the run_log_epics table.
-     * 
-     * @throws SQLException if there is an error performing the db query
-     */
-    void insertEpics() throws SQLException {
-        PreparedStatement statement = connection.prepareStatement("INSERT INTO run_epics (run, variable_name, value) values (?, ?, ?)");
-        EpicsData data = runSummary.getEpicsData();
-        if (data != null) {
-            for (String variableName : data.getUsedNames()) {
-                statement.setInt(1, this.run);
-                statement.setString(2, variableName);
-                statement.setDouble(3, data.getValue(variableName));
-                statement.executeUpdate();
-            }
-        } else {
-            LOGGER.warning("skipped inserting EPICS data (none found in RunSummary)");
-        }
-    }
-    
-    /**
-     * Delete existing EPICS data from the run_log_epics table.
-     * 
-     * @throws SQLException if there is an error performing the db query
-     */
-    void deleteEpics() throws SQLException {
-        PreparedStatement statement = connection.prepareStatement("DELETE FROM run_epics WHERE run = ?");
-        statement.setInt(1, this.run);
+    }
+
+    /**
+     * Insert a new row in the <i>runs</i> table.
+     *
+     * @param connection the database connection
+     * @throws SQLException if there is an error querying the database
+     */
+    private void insertRun() throws SQLException {
+        final PreparedStatement statement = connection
+                .prepareStatement("INSERT INTO runs (run, start_date, end_date, nevents, nfiles, end_ok, created) VALUES(?, ?, ?, ?, ?, ?, NOW())");
+        LOGGER.info("preparing to insert run " + run + " into runs table ..");
+        statement.setInt(1, run);
+        statement.setTimestamp(2, new java.sql.Timestamp(runSummary.getStartDate().getTime()));
+        statement.setTimestamp(3, new java.sql.Timestamp(runSummary.getEndDate().getTime()));
+        statement.setInt(4, runSummary.getTotalEvents());
+        statement.setInt(5, runSummary.getEvioFileList().size());
+        statement.setBoolean(6, runSummary.isEndOkay());
         statement.executeUpdate();
-    }
-    
+        LOGGER.info("inserted run " + run + " to runs table");
+    }
+
     /**
      * Return <code>true</code> if there is an existing row for this run summary.
-     * 
+     *
      * @return <code>true</code> if there is an existing row for this run summary.
      * @throws SQLException if there is an error executing the SQL query
      */
-    boolean epicsExists() throws SQLException {
-        PreparedStatement s = connection.prepareStatement("SELECT run from run_epics where run = ?");
+    private boolean runExists() throws SQLException {
+        final PreparedStatement s = connection.prepareStatement("SELECT run FROM runs where run = ?");
         s.setInt(1, run);
-        ResultSet rs = s.executeQuery();
+        final ResultSet rs = s.executeQuery();
         return rs.first();
     }
-}
+
+    void setAllowDeleteExisting(final boolean allowDeleteExisting) {
+        this.allowDeleteExisting = allowDeleteExisting;
+    }
+}

Modified: java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/package-info.java
 =============================================================================
--- java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/package-info.java	(original)
+++ java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/evio/crawler/package-info.java	Mon Jul  6 16:36:19 2015
@@ -1,5 +1,8 @@
 /**
- * Implements an EVIO file crawler to extract run and configuration information, including run start and end dates, event counts, etc.
+ * Implements an EVIO file crawler to extract run and configuration information.
+ * <p>
+ * This information includes run start and end dates, event counts, EPICS data, scaler data, 
+ * and the list of associated EVIO files.
  *
  * @author Jeremy McCormick, SLAC
  */

Modified: java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/scalers/ScalersEvioProcessor.java
 =============================================================================
--- java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/scalers/ScalersEvioProcessor.java	(original)
+++ java/branches/HPSJAVA-488/record-util/src/main/java/org/hps/record/scalers/ScalersEvioProcessor.java	Mon Jul  6 16:36:19 2015
@@ -24,6 +24,8 @@
      */
     private ScalerData data;
 
+    boolean resetEveryEvent = true;
+
     /**
      * Get the current scaler data or null if there was none in the last event processed.
      *
@@ -41,7 +43,9 @@
      */
     @Override
     public void process(final EvioEvent evio) {
-        this.data = null;
+        if (resetEveryEvent) {
+            this.data = null;
+        }
         for (final BaseStructure bank : evio.getChildrenList()) {
             // Does the crate tag match?
             if (bank.getHeader().getTag() == EvioEventConstants.SCALERS_CRATE_TAG) {
@@ -61,4 +65,8 @@
             }
         }
     }
+
+    public void setResetEveryEvent(final boolean resetEveryEvent) {
+        this.resetEveryEvent = resetEveryEvent;
+    }
 }

Modified: java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/readout/EngineeringRun2015TrigPairs1.lcsim
 =============================================================================
--- java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/readout/EngineeringRun2015TrigPairs1.lcsim	(original)
+++ java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/readout/EngineeringRun2015TrigPairs1.lcsim	Mon Jul  6 16:36:19 2015
@@ -42,9 +42,9 @@
             <numSamplesBefore>5</numSamplesBefore>
             <readoutThreshold>12</readoutThreshold>
             <triggerThreshold>12</triggerThreshold>
-<!--            <readoutWindow>50</readoutWindow>
+            <readoutWindow>50</readoutWindow>
             <readoutLatency>75</readoutLatency>
-            <mode>1</mode>-->
+            <mode>1</mode>
         </driver>
         <driver name="EcalConverter" type="org.hps.recon.ecal.EcalRawConverterDriver">
             <rawCollectionName>EcalRawHits</rawCollectionName>
@@ -55,35 +55,42 @@
             <use2014Gain>false</use2014Gain> 
         </driver>   
         <driver name="EcalClustererGTP" type="org.hps.recon.ecal.cluster.GTPClusterDriver">
+            <!--
+            Hit Time Coincidence:         +/-16 ns
+            Seed Energy Threshold:           50 MeV
+            -->
             <inputHitCollectionName>EcalCorrectedHits</inputHitCollectionName>
             <outputClusterCollectionName>EcalClustersGTP</outputClusterCollectionName>            
-            <clusterWindow>1</clusterWindow>
+            <clusterWindow>4</clusterWindow>
+            <seedEnergyThreshold>0.050</seedEnergyThreshold>
             <logLevel>SEVERE</logLevel>
         </driver>
         <driver name="PairTrigger1" type="org.hps.readout.ecal.FADCPrimaryTriggerDriver">
             <!--      
-           Hit Count: 2
-           Seed Energy: 50 MeV
-           Cluster Energy: 60 MeV (Low) and 630 MeV (High)
-           Energy Sum: 200 MeV (Low) and 860 MeV (High)
-           Energy Difference: 540 MeV
-           Energy Slope: 600 MeV (with F = 5.5 MeV/mm)
-           Coplanarity: 30 Degrees
-           Time Coincidence: 16 ms 
+            Hits Per Cluster Min:             1
+            Cluster Time Coincidence:     +/-12 ns
+            Cluster Energy Min:              54 MeV
+            Cluster Energy Max:             630 MeV
+            2-Cluster Energy-Sum Min:       180 MeV
+            2-Cluster Energy-Sum Min:       860 MeV
+            2-Cluster Energy-Diff Max:      540 MeV
+            Coplanarity Maximum:             30 deg
+            Energy-Dist Slope:              5.5 MeV/mm
+            Energy-Dist Minimum:            600 MeV
             -->
             <clusterCollectionName>EcalClustersGTP</clusterCollectionName>
             <deadTime>32</deadTime>
-            <minHitCount>2</minHitCount>
-            <pairCoincidence>4</pairCoincidence>
-            <clusterEnergyHigh>0.63</clusterEnergyHigh>
-            <clusterEnergyLow>0.06</clusterEnergyLow>
-            <energySumHigh>0.86</energySumHigh>
-            <energySumLow>0.2</energySumLow>
-            <energyDifferenceHigh>0.54</energyDifferenceHigh>
+            <seedEnergyLow>0.050</seedEnergyLow>
+            <minHitCount>1</minHitCount>
+            <pairCoincidence>3</pairCoincidence>
+            <clusterEnergyLow>0.054</clusterEnergyLow>
+            <clusterEnergyHigh>0.630</clusterEnergyHigh>
+            <energySumLow>0.180</energySumLow>
+            <energySumHigh>0.860</energySumHigh>
+            <energyDifferenceHigh>0.540</energyDifferenceHigh>
             <coplanarityHigh>30</coplanarityHigh>
-            <seedEnergyLow>0.05</seedEnergyLow>
             <energySlopeParamF>0.0055</energySlopeParamF>
-            <energySlopeLow>0.6</energySlopeLow>
+            <energySlopeLow>0.600</energySlopeLow>
             <prescale>1</prescale>
             <outputFileName>${outputFile}.triggers.pairs1</outputFileName>
             <!--<verbose>true</verbose>-->
@@ -103,7 +110,7 @@
             <outputFile>${outputFile}.slcio</outputFile>
             <rejectBackground>false</rejectBackground>
             <writeSvtData>true</writeSvtData>
-            <!--<ecalMode>1</ecalMode>-->
+            <ecalMode>1</ecalMode>
         </driver>
     </drivers>
 </lcsim>

Modified: java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/readout/EngineeringRun2015TrigSingles1.lcsim
 =============================================================================
--- java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/readout/EngineeringRun2015TrigSingles1.lcsim	(original)
+++ java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/readout/EngineeringRun2015TrigSingles1.lcsim	Mon Jul  6 16:36:19 2015
@@ -42,6 +42,9 @@
             <numSamplesBefore>5</numSamplesBefore>
             <readoutThreshold>12</readoutThreshold>
             <triggerThreshold>12</triggerThreshold>    
+            <readoutWindow>50</readoutWindow>
+            <readoutLatency>75</readoutLatency>
+            <mode>1</mode>
         </driver>
         <driver name="EcalConverter" type="org.hps.recon.ecal.EcalRawConverterDriver">
             <rawCollectionName>EcalRawHits</rawCollectionName>
@@ -52,30 +55,36 @@
             <use2014Gain>false</use2014Gain> 
         </driver>   
         <driver name="EcalClustererGTP" type="org.hps.recon.ecal.cluster.GTPClusterDriver">
+            <!--
+            Hit Time Coincidence:         +/-16 ns
+            Seed Energy Threshold:           50 MeV
+            -->
             <inputHitCollectionName>EcalCorrectedHits</inputHitCollectionName>
             <outputClusterCollectionName>EcalClustersGTP</outputClusterCollectionName>            
-            <clusterWindow>1</clusterWindow>
-            <seedEnergyThreshold>0.05</seedEnergyThreshold>
+            <clusterWindow>4</clusterWindow>
+            <seedEnergyThreshold>0.050</seedEnergyThreshold>
             <logLevel>SEVERE</logLevel>
         </driver>
         <driver name="SinglesTrigger1" type="org.hps.readout.ecal.SinglesTriggerDriver">
-            <!--                  
-                  # Singles 1 trigger
-                SSP_HPS_SINGLES_EMIN  1  400  1
-                SSP_HPS_SINGLES_EMAX  1  1100 1
-                SSP_HPS_SINGLES_NMIN  1  3    1
+            <!--      
+            Hits Per Cluster Min:             3
+            Cluster Energy Min:             400 MeV
+            Cluster Energy Max:            1100 MeV
             -->
             <clusterCollectionName>EcalClustersGTP</clusterCollectionName>
             <deadTime>32</deadTime>
+            <seedEnergyLowThreshold>0.050</seedEnergyLowThreshold>
             <hitCountThreshold>3</hitCountThreshold>
-            <seedEnergyLowThreshold>0.05</seedEnergyLowThreshold>
-            <clusterEnergyLowThreshold>0.4</clusterEnergyLowThreshold>
-            <clusterEnergyHighThreshold>1.1</clusterEnergyHighThreshold>
+            <clusterEnergyLowThreshold>0.400</clusterEnergyLowThreshold>
+            <clusterEnergyHighThreshold>1.100</clusterEnergyHighThreshold>
             <prescale>1</prescale>
             <outputFileName>${outputFile}.triggers.singles1</outputFileName>
             <!--<verbose>true</verbose>-->
         </driver>                                    
-        <driver name="SimpleSVTReadout" type="org.hps.readout.svt.SimpleSvtReadout" />
+        <driver name="SimpleSVTReadout" type="org.hps.readout.svt.SimpleSvtReadout">
+            <enablePileupCut>false</enablePileupCut>
+            <useTimingConditions>true</useTimingConditions>
+        </driver>
         <driver name="RawTrackerHitSensorSetup" type="org.lcsim.recon.tracking.digitization.sisim.config.RawTrackerHitSensorSetup" />
 
         <driver name="AidaSaveDriver" type="org.lcsim.job.AidaSaveDriver">
@@ -87,6 +96,7 @@
             <outputFile>${outputFile}.slcio</outputFile>
             <rejectBackground>false</rejectBackground>
             <writeSvtData>true</writeSvtData>
+            <ecalMode>1</ecalMode>
         </driver>
     </drivers>
 </lcsim>

Modified: java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/recon/EngineeringRun2015FullReconGbl2.lcsim
 =============================================================================
--- java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/recon/EngineeringRun2015FullReconGbl2.lcsim	(original)
+++ java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/recon/EngineeringRun2015FullReconGbl2.lcsim	Mon Jul  6 16:36:19 2015
@@ -91,7 +91,7 @@
         <driver name="ReconClusterer" type="org.hps.recon.ecal.cluster.ReconClusterDriver">
             <logLevel>WARNING</logLevel>
             <outputClusterCollectionName>EcalClusters</outputClusterCollectionName>
-            <hitEnergyThreshold>0.01</hitEnergyThreshold>
+            <hitEnergyThreshold>0.0075</hitEnergyThreshold>
             <seedEnergyThreshold>0.050</seedEnergyThreshold> 
             <clusterEnergyThreshold>0.100</clusterEnergyThreshold>
             <minTime>0.0</minTime>
@@ -109,7 +109,7 @@
         <driver name="CopyCluster" type="org.hps.recon.ecal.cluster.CopyClusterCollectionDriver">
             <inputCollectionName>EcalClusters</inputCollectionName>
             <outputCollectionName>EcalClustersCorr</outputCollectionName>
-    		<storeHits>false</storeHits>
+    		<storeHits>true</storeHits>
         </driver>
         <driver name="ReconParticle" type="org.hps.recon.particle.HpsReconParticleDriver">  
             <ecalClusterCollectionName>EcalClustersCorr</ecalClusterCollectionName>        

Modified: java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/recon/EngineeringRun2015FullReconMC.lcsim
 =============================================================================
--- java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/recon/EngineeringRun2015FullReconMC.lcsim	(original)
+++ java/branches/HPSJAVA-488/steering-files/src/main/resources/org/hps/steering/recon/EngineeringRun2015FullReconMC.lcsim	Mon Jul  6 16:36:19 2015
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <!-- 
   Offline reconstruction for 2015 (engineering run with SVT+ECal) data.
   @author Sho Uemura <[log in to unmask]>
@@ -70,17 +71,17 @@
             <use2014Gain>false</use2014Gain>
             <useTimestamps>false</useTimestamps>
             <useTruthTime>false</useTruthTime>
-<!--            <useRunningPedestal>false</useRunningPedestal>
+            <useRunningPedestal>false</useRunningPedestal>
             <useTimeWalkCorrection>false</useTimeWalkCorrection>
             <emulateFirmware>true</emulateFirmware>
-            <emulateMode7>true</emulateMode7>-->
+            <emulateMode7>true</emulateMode7>
             <leadingEdgeThreshold>12</leadingEdgeThreshold>
             <nsa>100</nsa>
             <nsb>20</nsb>
-<!--            <nPeak>3</nPeak>
+            <nPeak>3</nPeak>
             <useFit>true</useFit>
             <fixShapeParameter>true</fixShapeParameter>
-            <globalFixedPulseWidth>2.4</globalFixedPulseWidth>-->
+            <globalFixedPulseWidth>2.4</globalFixedPulseWidth>
             <!--<debug>true</debug>-->
         </driver>       
         <driver name="ReconClusterer" type="org.hps.recon.ecal.cluster.ReconClusterDriver">

Modified: java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java
 =============================================================================
--- java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java	(original)
+++ java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java	Mon Jul  6 16:36:19 2015
@@ -4,11 +4,15 @@
 import hep.physics.vec.BasicHep3Vector;
 import hep.physics.vec.Hep3Vector;
 import hep.physics.vec.VecOp;
+
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+
 import org.hps.recon.tracking.axial.HelicalTrack2DHit;
 import org.lcsim.detector.IDetectorElement;
 import org.lcsim.detector.ITransform3D;
@@ -24,6 +28,7 @@
 import org.lcsim.event.RawTrackerHit;
 import org.lcsim.event.RelationalTable;
 import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.TrackerHit;
 import org.lcsim.event.base.BaseRelationalTable;
 import org.lcsim.event.base.MyLCRelation;
 import org.lcsim.fit.helicaltrack.HelicalTrackCross;
@@ -61,6 +66,7 @@
     private boolean _saveAxialHits = false;
     private String _axialname = "AxialTrackHits";
     private String _axialmcrelname = "AxialTrackHitsMCRelations";
+    private boolean rejectGhostHits = false;
 
     public enum LayerGeometryType {
 
@@ -74,6 +80,7 @@
     public HelicalTrackHitDriver() {
         _crosser.setMaxSeparation(20.0);
         _crosser.setTolerance(0.1);
+        _crosser.setEpsParallel(0.013);
         _colnames.add("StripClusterer_SiTrackerHitStrip1D");
     }
 
@@ -104,6 +111,16 @@
     }
 
     /**
+     * Drop any HelicalTrackHit containing a 1D hit that is also used in another
+     * HelicalTrackHit.
+     *
+     * @param rejectGhostHits
+     */
+    public void setRejectGhostHits(boolean rejectGhostHits) {
+        this.rejectGhostHits = rejectGhostHits;
+    }
+
+    /**
      *
      * @param subdetectorName
      */
@@ -119,6 +136,14 @@
         this._debug = debug;
     }
 
+    public void setEpsParallel(double eps) {
+        this._crosser.setEpsParallel(eps);
+    }
+
+    public void setEpsStereo(double eps) {
+        this._crosser.setEpsStereoAngle(eps);
+    }
+    
     /**
      *
      * @param trans
@@ -207,7 +232,7 @@
                     // Cast the hit as a 1D strip hit and find the
                     // identifier for the detector/layer combo
                     SiTrackerHitStrip1D h = (SiTrackerHitStrip1D) hit;
-                    if (clusterAmplitudeCut > 0 && h.getdEdx()/DopedSilicon.ENERGY_EHPAIR < clusterAmplitudeCut) {
+                    if (clusterAmplitudeCut > 0 && h.getdEdx() / DopedSilicon.ENERGY_EHPAIR < clusterAmplitudeCut) {
                         continue;
                     }
                     if (_clusterTimeCut > 0 && Math.abs(h.getTime()) > _clusterTimeCut) {
@@ -386,6 +411,29 @@
                 }
                 if (_debug) {
                     System.out.printf("%s: cross at %.2f,%.2f,%.2f \n", this.getClass().getSimpleName(), cross.getPosition()[0], cross.getPosition()[1], cross.getPosition()[2]);
+                }
+            }
+
+            if (rejectGhostHits) {
+                RelationalTable hittostrip = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+                for (HelicalTrackCross cross : helicalTrackCrosses) {
+                    for (HelicalTrackStrip strip : cross.getStrips()) {
+                        hittostrip.add(cross, stripmap.get(strip));
+                    }
+                }
+                crossLoop:
+                for (Iterator<HelicalTrackCross> iter = helicalTrackCrosses.listIterator(); iter.hasNext();) {
+                    HelicalTrackCross cross = iter.next();
+                    Collection<TrackerHit> htsList = hittostrip.allFrom(cross);
+                    for (TrackerHit strip : htsList) {
+                        Set<HelicalTrackHit> sharedCrosses = hittostrip.allTo(strip);
+                        System.out.println(sharedCrosses.size());
+                        if (sharedCrosses.size() > 1) {
+//                    this.getLogger().warning(String.format("removing possible ghost hit"));
+                            iter.remove();
+                            continue crossLoop;
+                        }
+                    }
                 }
             }
 
@@ -581,7 +629,16 @@
                     System.out.printf("%s: adding rotated strip with origin %s and u %s v %s w %s \n", getClass().toString(), newstrip.origin().toString(), newstrip.u().toString(), newstrip.v().toString(), newstrip.w().toString());
                 }
             }
-            HelicalTrackCross newhit = new HelicalTrackCross(rotatedstriphits.get(0), rotatedstriphits.get(1));
+            List<HelicalTrackStrip> strip1 = new ArrayList<HelicalTrackStrip>();
+            List<HelicalTrackStrip> strip2 = new ArrayList<HelicalTrackStrip>();
+            strip1.add(rotatedstriphits.get(0));
+            strip2.add(rotatedstriphits.get(1));
+            List<HelicalTrackCross> newhits = _crosser.MakeHits(strip1, strip2);
+            if(newhits.size()!=1) {
+                throw new RuntimeException("no rotated cross was created!?");
+            }
+            HelicalTrackCross newhit  = newhits.get(0);
+            //HelicalTrackCross newhit = new HelicalTrackCross(rotatedstriphits.get(0), rotatedstriphits.get(1));
             for (MCParticle mcp : cross.getMCParticles()) {
                 newhit.addMCParticle(mcp);
             }

Modified: java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java
 =============================================================================
--- java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java	(original)
+++ java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java	Mon Jul  6 16:36:19 2015
@@ -6,12 +6,12 @@
 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 org.hps.recon.tracking.EventQuality.Quality;
 import org.hps.recon.tracking.gbl.HelicalTrackStripGbl;
 import org.lcsim.detector.ITransform3D;
@@ -20,11 +20,15 @@
 import org.lcsim.detector.solids.Polygon3D;
 import org.lcsim.detector.tracker.silicon.HpsSiSensor;
 import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCRelation;
 import org.lcsim.event.MCParticle;
 import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.RelationalTable;
 import org.lcsim.event.Track;
 import org.lcsim.event.TrackState;
 import org.lcsim.event.TrackerHit;
+import org.lcsim.event.base.BaseRelationalTable;
 import org.lcsim.fit.helicaltrack.HelicalTrackFit;
 import org.lcsim.fit.helicaltrack.HelicalTrackHit;
 import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
@@ -859,5 +863,57 @@
         BarrelEndcapFlag beflag = BarrelEndcapFlag.BARREL;
         return new HelicalTrackHit(pos, hitcov, dedx, time, type, rhits, detname, layer, beflag);
     }
-
+    
+    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;
+    }
+
+    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;
+    }
+
+    public static double getTrackTime(Track track, RelationalTable hitToStrips, RelationalTable hitToRotated) {
+        int nStrips = 0;
+        double meanTime = 0;
+        for (TrackerHit hit : track.getTrackerHits()) {
+            Set<TrackerHit> htsList = hitToStrips.allFrom(hitToRotated.from(hit));
+            for (TrackerHit hts : htsList) {
+                nStrips++;
+                meanTime += hts.getTime();
+            }
+        }
+        meanTime /= nStrips;
+        return meanTime;
+    }
+    
+    public static boolean hasSharedStrips(Track track1, Track track2, RelationalTable hitToStrips, RelationalTable hitToRotated) {
+        Set<TrackerHit> track1hits = new HashSet<TrackerHit>();
+        for (TrackerHit hit : track1.getTrackerHits()) {
+            track1hits.addAll(hitToStrips.allFrom(hitToRotated.from(hit)));
+        }
+        for (TrackerHit hit : track2.getTrackerHits()) {
+            for (TrackerHit hts : (Set<TrackerHit>) hitToStrips.allFrom(hitToRotated.from(hit))) {
+                if (track1hits.contains(hts)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 }

Modified: java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLFileIO.java
 =============================================================================
--- java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLFileIO.java	(original)
+++ java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLFileIO.java	Mon Jul  6 16:36:19 2015
@@ -250,6 +250,10 @@
         addLine(String.format("Strip 3D hit pos %.10f %.10f %.10f",pos.x(),pos.y(),pos.z()));
     }
 
+    public void printStripIso(double stripIsoMin) {
+        addLine(String.format("Strip iso %.10f", stripIsoMin));
+    }
+
 
 
 }

Modified: java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutput.java
 =============================================================================
--- java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutput.java	(original)
+++ java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutput.java	Mon Jul  6 16:36:19 2015
@@ -29,6 +29,7 @@
 import org.hps.recon.tracking.TrackerHitUtils;
 import org.lcsim.constants.Constants;
 import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ITransform3D;
 import org.lcsim.detector.tracker.silicon.HpsSiSensor;
 import org.lcsim.event.MCParticle;
 import org.lcsim.event.RawTrackerHit;
@@ -41,6 +42,8 @@
 import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
 import org.lcsim.fit.helicaltrack.HelixUtils;
 import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.digitization.sisim.TrackerHitType;
 import org.lcsim.recon.tracking.seedtracker.ScatterAngle;
 import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
 import org.lcsim.recon.tracking.seedtracker.SeedTrack;
@@ -119,7 +122,7 @@
 
 
     
-    void printGBL(Track trk, GBLTrackData gtd, List<GBLStripClusterData> stripClusterDataList, List<MCParticle> mcParticles, List<SimTrackerHit> simTrackerHits, boolean isMC) {
+    void printGBL(Track trk, List<SiTrackerHitStrip1D> stripHits, GBLTrackData gtd, List<GBLStripClusterData> stripClusterDataList, List<MCParticle> mcParticles, List<SimTrackerHit> simTrackerHits, boolean isMC) {
 
         SeedTrack st = (SeedTrack)trk;
         SeedCandidate seed = st.getSeedCandidate();
@@ -381,6 +384,24 @@
                 stripData.setTrackLambda(lambda);
                 
                 
+                // calculate isolation to other strip clusters
+                double stripIsoMin = 9999.9;
+                for (SiTrackerHitStrip1D stripHit : stripHits) {
+                    if(stripHit.getRawHits().get(0).getDetectorElement().getName().equals(de.getName())) {
+                        SiTrackerHitStrip1D local = stripHit.getTransformedHit(TrackerHitType.CoordinateSystem.SENSOR);
+                        double d = Math.abs(strip.umeas() - local.getPosition()[0]);
+                        if (d<stripIsoMin && d>0) {
+                            stripIsoMin = d;
+                        }
+                    }
+                }
+                
+                if(_debug>0) System.out.printf("%s: stripIsoMin = %f \n", this.getClass().getSimpleName(), stripIsoMin);
+                
+                // Add isolation to text file output
+                if(textFile != null) {
+                    textFile.printStripIso(stripIsoMin);
+                }
                 
                 
                 //Print residual in measurement system

Modified: java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutputDriver.java
 =============================================================================
--- java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutputDriver.java	(original)
+++ java/branches/HPSJAVA-488/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutputDriver.java	Mon Jul  6 16:36:19 2015
@@ -18,6 +18,7 @@
 import org.lcsim.event.Track;
 import org.lcsim.event.base.MyLCRelation;
 import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
 import org.lcsim.util.Driver;
 import org.lcsim.util.aida.AIDA;
 
@@ -85,6 +86,10 @@
              }
         }
 
+        List<SiTrackerHitStrip1D> stripHits = event.get(SiTrackerHitStrip1D.class, "StripClusterer_SiTrackerHitStrip1D");
+        if(_debug>0) System.out.printf("%s: Got %d SiTrackerHitStrip1D in this event\n", stripHits.size());
+        
+       
 
         List<MCParticle> mcParticles = new ArrayList<MCParticle>();
         if(event.hasCollection(MCParticle.class,this.MCParticleCollectionName)) {
@@ -134,7 +139,7 @@
             
             //print to text file
             gbl.printTrackID(iTrack);
-            gbl.printGBL(trk,gblTrackData,gblStripDataList,mcParticles,simTrackerHits,this.isMC);
+            gbl.printGBL(trk, stripHits, gblTrackData,gblStripDataList,mcParticles,simTrackerHits,this.isMC);
             
             //GBLDATA
             //add relation to normal track object

Modified: java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/luca/FeeCalibHistCreator.java
 =============================================================================
--- java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/luca/FeeCalibHistCreator.java	(original)
+++ java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/luca/FeeCalibHistCreator.java	Mon Jul  6 16:36:19 2015
@@ -5,16 +5,26 @@
  */
 package org.hps.users.luca;
 import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import java.io.FileWriter;
+import java.io.IOException;
 
 import java.util.ArrayList;
 import java.util.List;
+import org.hps.conditions.database.DatabaseConditionsManager;
+import org.hps.conditions.ecal.EcalChannel;
 
 import org.hps.conditions.ecal.EcalChannel.EcalChannelCollection;
+import org.hps.conditions.ecal.EcalChannelConstants;
 import org.hps.conditions.ecal.EcalConditions;
+import org.hps.recon.ecal.triggerbank.AbstractIntData;
+import org.hps.recon.ecal.triggerbank.TIData;
 import org.lcsim.conditions.ConditionsManager;
 import org.lcsim.event.CalorimeterHit;
 import org.lcsim.event.Cluster;
 import org.lcsim.event.EventHeader;
+import org.lcsim.event.GenericObject;
+import org.lcsim.geometry.Detector;
 import org.lcsim.geometry.Subdetector;
 import org.lcsim.util.Driver;
 import org.lcsim.util.aida.AIDA;
@@ -24,10 +34,13 @@
  */
 public class FeeCalibHistCreator extends Driver {
     
-double energyThreshold=0;
-    protected String clusterCollectionName = "EcalClustersGTP";
+    double energyThreshold=0.5;
+    protected String clusterCollectionName = "GTPEcalClusters";
+    //create the writer to write the gains on txt
+    private FileWriter writer;
+    String outputFileName = "gains.txt";
     
-    
+    //things you need to get the gains
     private EcalConditions ecalConditions = null;
     final private String ecalName = "Ecal";
     private Subdetector ecal;
@@ -36,35 +49,50 @@
     
     //Declaration of histograms array
     AIDA aida = AIDA.defaultInstance();
-    ArrayList<IHistogram1D> GTPHists = new ArrayList<IHistogram1D>(442);
-    ArrayList<IHistogram1D> GTPSeedHists = new ArrayList<IHistogram1D>(442);
+    ArrayList<IHistogram2D> GTPHists = new ArrayList<IHistogram2D>(442);
+   
     
     
     public void setEnergyThreshold (double threshold){
     this.energyThreshold=threshold;
        }
   
+  public void setOutputFileName(String outputFileName){
+  this.outputFileName = outputFileName+".txt";
+  }
   
-  
-  
+  @Override
+    public void detectorChanged(Detector detector) {
+        // Get the Subdetector.
+        ecal = detector.getSubdetector(ecalName);
+        
+      /*  // ECAL combined conditions object.
+        ecalConditions = ConditionsManager.defaultInstance()
+                .getCachedConditions(EcalConditions.class, TableConstants.ECAL_CONDITIONS).getCachedData();*/
+                       
+        ecalConditions = DatabaseConditionsManager.getInstance().getEcalConditions();
+         channels = ecalConditions.getChannelCollection();
+    }  
 
    @Override   
 public void startOfData(){
    //initialize histograms  
       for(int t=0; t<442; t++){
       String cristallo=String.valueOf(t+1);  
-      String GTPhistName="GTP Cluster Energy(Run)" + cristallo;
-      String GTPSeedHistName="GTP Seed Energy(Run)"+ cristallo;
-      
-      
-      IHistogram1D GTPseedhisto=aida.histogram1D(GTPSeedHistName, 200, 0.0,2.5);
-      IHistogram1D GTPclushisto=aida.histogram1D(GTPhistName, 200, 0.0,2.5);
-     
+      String GTPhistName="GTPCluster-Seeds Energy " + cristallo;
+      IHistogram2D GTPclushisto=aida.histogram2D(GTPhistName, 150, 0.0,1.5,150,0.0,1.5);
       GTPHists.add(GTPclushisto);
-      GTPSeedHists.add(GTPseedhisto);
-   
       }
-    
+   //initialize writer
+      try{
+         //initialize the writers
+         writer=new FileWriter(outputFileName);
+         //Clear the files
+         writer.write("");
+      }
+      catch(IOException e ){
+      System.err.println("Error initializing output file for gains.");
+      }
     
 }
 
@@ -72,10 +100,36 @@
 
     @Override
     public void endOfData(){
- 
+    
+        for(int t=0;t<442;t++){
+      int id =t+1;
+      try{  writer.append(id + " " + gain[t] + "\n");}
+      catch(IOException e){
+      System.err.println("Error closing output file.");}
+      }
+      //close the file writer.  
+      try{
+      writer.close();
+      }
+      catch(IOException e){
+      System.err.println("Error closing utput file.");
+      }
 } 
     @Override
     public void process (EventHeader event){
+        
+          if (event.hasCollection(GenericObject.class, "TriggerBank")) {
+            List<GenericObject> triggerList = event.get(GenericObject.class, "TriggerBank");
+            for (GenericObject data : triggerList)
+                if (AbstractIntData.getTag(data) == TIData.BANK_TAG) {
+                    TIData triggerData = new TIData(data);
+                    if (!triggerData.isSingle1Trigger())//only process singles0 triggers...
+
+                        return;
+                }
+        } else //if (debug)
+            System.out.println(this.getClass().getSimpleName() + ":  No trigger bank found...running over all trigger types");
+  
         
         //here it writes the GTP clusters info
         if(event.hasCollection(Cluster.class,"EcalClustersGTP"))
@@ -85,15 +139,19 @@
            
            
            idBack=getDBID(cluster);
-           
+           EcalChannel channel = channels.findGeometric(cluster.getCalorimeterHits().get(0).getCellID());
+           EcalChannelConstants channelConstants = ecalConditions.getChannelConstants(channel);
+           gain[idBack-1]=channelConstants.getGain().getGain();
            
            //riempio gli istogrammi
            if(cluster.getEnergy()>energyThreshold){
-           GTPHists.get(idBack -1).fill(cluster.getEnergy());
-           GTPSeedHists.get(idBack-1).fill(cluster.getCalorimeterHits().get(0).getCorrectedEnergy());
+           GTPHists.get(idBack -1).fill(cluster.getEnergy(),cluster.getCalorimeterHits().get(0).getCorrectedEnergy());
+          
+           //System.out.println("Clu = " + cluster.getEnergy() + " Seed = " + cluster.getCalorimeterHits().get(0).getCorrectedEnergy() + "\n");
            }         
          }
         }
+       
        
     }
     

Modified: java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/omoreno/SvtClusterAnalysis.java
 =============================================================================
--- java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/omoreno/SvtClusterAnalysis.java	(original)
+++ java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/omoreno/SvtClusterAnalysis.java	Mon Jul  6 16:36:19 2015
@@ -4,6 +4,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.Set;
 
 import hep.aida.IAnalysisFactory;
 import hep.aida.IHistogram2D;
@@ -15,17 +16,19 @@
 import hep.aida.ITree;
 import hep.aida.ref.rootwriter.RootFileStore;
 
-import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
 import org.lcsim.util.Driver; 
-import org.lcsim.fit.helicaltrack.HelicalTrackCross;
-import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
 import org.lcsim.geometry.Detector;
 import org.lcsim.detector.tracker.silicon.HpsSiSensor;
 import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCRelation;
 import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.RelationalTable;
 import org.lcsim.event.Track;
 import org.lcsim.event.TrackerHit;
+import org.lcsim.event.base.BaseRelationalTable;
 import org.hps.recon.tracking.FittedRawTrackerHit;
+import org.hps.recon.tracking.TrackUtils;
 
 /**
  * 
@@ -41,8 +44,8 @@
     }
 
     private List<HpsSiSensor> sensors;
-    private Map<RawTrackerHit, FittedRawTrackerHit> fittedRawTrackerHitMap 
-        = new HashMap<RawTrackerHit, FittedRawTrackerHit>();
+    private Map<RawTrackerHit, LCRelation> fittedRawTrackerHitMap = new HashMap<RawTrackerHit, LCRelation>();
+    private Map<Track, ReconstructedParticle> reconParticleMap = new HashMap<Track, ReconstructedParticle>();
   
     // Plotting
     ITree tree; 
@@ -50,18 +53,24 @@
 	IPlotterFactory plotterFactory = IAnalysisFactory.create().createPlotterFactory();
 	protected Map<String, IPlotter> plotters = new HashMap<String, IPlotter>(); 
 	
-	private Map<HpsSiSensor, IHistogram1D> clusterChargePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> singleHitClusterChargePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> multHitClusterChargePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> trackClusterChargePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> signalToNoisePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> singleHitSignalToNoisePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> multHitSignalToNoisePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> trackHitSignalToNoisePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> clusterMultiplicityPlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> clusterTimePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram1D> trackClusterTimePlots = new HashMap<HpsSiSensor, IHistogram1D>();
-	private Map<HpsSiSensor, IHistogram2D> clusterChargeVsTimePlots = new HashMap<HpsSiSensor, IHistogram2D>();
+	// All clusters
+	private Map<String, IHistogram1D> clusterChargePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram1D> singleHitClusterChargePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram1D> multHitClusterChargePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram1D> signalToNoisePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram1D> singleHitSignalToNoisePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram1D> multHitSignalToNoisePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram1D> clusterSizePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram1D> clusterTimePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram2D> clusterChargeVsTimePlots = new HashMap<String, IHistogram2D>();
+
+	// Clusters on track
+	private Map<String, IHistogram1D> trackClusterChargePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram1D> trackHitSignalToNoisePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram1D> trackClusterTimePlots = new HashMap<String, IHistogram1D>();
+	private Map<String, IHistogram2D> trackClusterChargeVsMomentum = new HashMap<String, IHistogram2D>();
+	private Map<String, IHistogram2D> trackClusterChargeVsCosTheta = new HashMap<String, IHistogram2D>();
+	private Map<String, IHistogram2D> trackClusterChargeVsSinPhi = new HashMap<String, IHistogram2D>();
 	
     // Detector name
     private static final String SUBDETECTOR_NAME = "Tracker";
@@ -69,6 +78,9 @@
     // Collections
     private String clusterCollectionName = "StripClusterer_SiTrackerHitStrip1D";
     private String fittedHitsCollectionName = "SVTFittedRawTrackerHits";
+    private String stereoHitRelationsColName = "HelicalTrackHitRelations";
+    private String rotatedHthRelationsColName = "RotatedHelicalTrackHitRelations";
+    private String fsParticlesCollectionName = "FinalStateParticles";
     
     private int runNumber = -1; 
         
@@ -135,67 +147,106 @@
         plotters.put("Cluster Amplitude vs Cluster Time", plotterFactory.create("Cluster Amplitude vs Cluster Time"));
         plotters.get("Cluster Amplitude vs Cluster Time").createRegions(6, 6);
         
+        plotters.put("Cluster Amplitude vs Momentum", plotterFactory.create("Cluster Amplitude vs Momentum"));
+        plotters.get("Cluster Amplitude vs Momentum").createRegions(6, 6);
+        
+        plotters.put("Cluster Amplitude vs cos(theta)", plotterFactory.create("Cluster Amplitude vs cos(theta)"));
+        plotters.get("Cluster Amplitude vs cos(theta)").createRegions(6, 6);
+        
+        plotters.put("Cluster Amplitude vs sin(phi0)", plotterFactory.create("Cluster Amplitude vs sin(phi0)"));
+        plotters.get("Cluster Amplitude vs sin(phi0)").createRegions(6, 6);
+
         for (HpsSiSensor sensor : sensors) { 
             
-            clusterChargePlots.put(sensor, 
+            clusterChargePlots.put(sensor.getName(), 
                     histogramFactory.createHistogram1D(sensor.getName() + " - Cluster Charge", 100, 0, 5000));
             plotters.get("Cluster Amplitude").region(this.computePlotterRegion(sensor))
-                                             .plot(clusterChargePlots.get(sensor), this.createStyle(1, "Cluster Amplitude [ADC Counts]", ""));
-       
-            singleHitClusterChargePlots.put(sensor, 
+                                             .plot(clusterChargePlots
+                                             .get(sensor.getName()), this.createStyle(1, "Cluster Amplitude [ADC Counts]", ""));
+       
+            singleHitClusterChargePlots.put(sensor.getName(), 
                     histogramFactory.createHistogram1D(sensor.getName() + " - Single Hit Cluster Charge", 100, 0, 5000));
             plotters.get("Cluster Amplitude").region(this.computePlotterRegion(sensor))
-                                             .plot(singleHitClusterChargePlots.get(sensor), this.createStyle(2, "Cluster Amplitude [ADC Counts]", ""));
-
-            multHitClusterChargePlots.put(sensor, 
+                                             .plot(singleHitClusterChargePlots
+                                             .get(sensor.getName()), this.createStyle(2, "Cluster Amplitude [ADC Counts]", ""));
+
+            multHitClusterChargePlots.put(sensor.getName(), 
                     histogramFactory.createHistogram1D(sensor.getName() + " - Multiple Hit Cluster Charge", 100, 0, 5000));
             plotters.get("Cluster Amplitude").region(this.computePlotterRegion(sensor))
-                                             .plot(multHitClusterChargePlots.get(sensor), this.createStyle(2, "Cluster Amplitude [ADC Counts]", ""));
-
-            trackClusterChargePlots.put(sensor, 
+                                             .plot(multHitClusterChargePlots
+                                             .get(sensor.getName()), this.createStyle(2, "Cluster Amplitude [ADC Counts]", ""));
+
+            signalToNoisePlots.put(sensor.getName(), 
+                    histogramFactory.createHistogram1D(sensor.getName() + " - Signal to Noise", 50, 0, 50));
+            plotters.get("Signal to Noise").region(this.computePlotterRegion(sensor))
+                                           .plot(signalToNoisePlots
+                                           .get(sensor.getName()), this.createStyle(1, "Signal to Noise", ""));
+
+            singleHitSignalToNoisePlots.put(sensor.getName(), 
+                    histogramFactory.createHistogram1D(sensor.getName() + " - Single Hit Signal to Noise", 50, 0, 50));
+            plotters.get("Signal to Noise").region(this.computePlotterRegion(sensor))
+                                           .plot(singleHitSignalToNoisePlots
+                                           .get(sensor.getName()), this.createStyle(2, "Signal to Noise", ""));
+        
+            multHitSignalToNoisePlots.put(sensor.getName(), 
+                    histogramFactory.createHistogram1D(sensor.getName() + " - Multiple Hit Signal to Noise", 50, 0, 50));
+            plotters.get("Signal to Noise").region(this.computePlotterRegion(sensor))
+                                           .plot(multHitSignalToNoisePlots
+                                           .get(sensor.getName()), this.createStyle(2, "Signal to Noise", ""));
+
+            clusterSizePlots.put(sensor.getName(),
+                    histogramFactory.createHistogram1D(sensor.getName() + " - Cluster Multiplicity", 10, 0, 10));
+            plotters.get("Cluster Multiplicity").region(this.computePlotterRegion(sensor))
+                                                .plot(clusterSizePlots
+                                                .get(sensor.getName()), this.createStyle(1, "Cluster Multiplicity", ""));
+            
+            clusterTimePlots.put(sensor.getName(),
+                    histogramFactory.createHistogram1D(sensor.getName() + " - Cluster Time", 100, -100, 100));
+            plotters.get("Cluster Time").region(this.computePlotterRegion(sensor))
+                                        .plot(clusterTimePlots
+                                        .get(sensor.getName()), this.createStyle(1, "Cluster Time [ns]", ""));
+
+            trackClusterTimePlots.put(sensor.getName(),
+                    histogramFactory.createHistogram1D(sensor.getName() + " - Track Cluster Time", 100, -100, 100));
+            plotters.get("Cluster Time").region(this.computePlotterRegion(sensor))
+                                        .plot(trackClusterTimePlots
+                                        .get(sensor.getName()), this.createStyle(3, "Cluster Time [ns]", ""));
+            
+            clusterChargeVsTimePlots.put(sensor.getName(),
+                    histogramFactory.createHistogram2D(sensor.getName() + " - Cluster Amplitude vs Time", 100, 0, 5000, 100, -100, 100));
+            plotters.get("Cluster Amplitude vs Cluster Time").region(this.computePlotterRegion(sensor))
+                                                             .plot(clusterChargeVsTimePlots
+                                                             .get(sensor.getName()));
+        
+            trackClusterChargePlots.put(sensor.getName(), 
                     histogramFactory.createHistogram1D(sensor.getName() + " - Tracker Cluster Charge", 100, 0, 5000));
             plotters.get("Cluster Amplitude").region(this.computePlotterRegion(sensor))
-                                             .plot(trackClusterChargePlots.get(sensor), this.createStyle(3, "Cluster Amplitude [ADC Counts]", ""));
-            
-            signalToNoisePlots.put(sensor, 
-                    histogramFactory.createHistogram1D(sensor.getName() + " - Signal to Noise", 50, 0, 50));
-            plotters.get("Signal to Noise").region(this.computePlotterRegion(sensor))
-                                           .plot(signalToNoisePlots.get(sensor), this.createStyle(1, "Signal to Noise", ""));
-
-            singleHitSignalToNoisePlots.put(sensor, 
-                    histogramFactory.createHistogram1D(sensor.getName() + " - Single Hit Signal to Noise", 50, 0, 50));
-            plotters.get("Signal to Noise").region(this.computePlotterRegion(sensor))
-                                           .plot(singleHitSignalToNoisePlots.get(sensor), this.createStyle(2, "Signal to Noise", ""));
-        
-            multHitSignalToNoisePlots.put(sensor, 
-                    histogramFactory.createHistogram1D(sensor.getName() + " - Multiple Hit Signal to Noise", 50, 0, 50));
-            plotters.get("Signal to Noise").region(this.computePlotterRegion(sensor))
-                                           .plot(multHitSignalToNoisePlots.get(sensor), this.createStyle(2, "Signal to Noise", ""));
-
-            trackHitSignalToNoisePlots.put(sensor, 
+                                             .plot(trackClusterChargePlots
+                                             .get(sensor.getName()), this.createStyle(3, "Cluster Amplitude [ADC Counts]", ""));
+        
+            trackHitSignalToNoisePlots.put(sensor.getName(), 
                     histogramFactory.createHistogram1D(sensor.getName() + " - Track Signal to Noise", 50, 0, 50));
             plotters.get("Signal to Noise").region(this.computePlotterRegion(sensor))
-                                           .plot(trackHitSignalToNoisePlots.get(sensor), this.createStyle(3, "Signal to Noise", ""));
-            
-            clusterMultiplicityPlots.put(sensor,
-                    histogramFactory.createHistogram1D(sensor.getName() + " - Cluster Multiplicity", 10, 0, 10));
-            plotters.get("Cluster Multiplicity").region(this.computePlotterRegion(sensor))
-                                                .plot(clusterMultiplicityPlots.get(sensor), this.createStyle(1, "Cluster Multiplicity", ""));
-            
-            clusterTimePlots.put(sensor,
-                    histogramFactory.createHistogram1D(sensor.getName() + " - Cluster Time", 100, -100, 100));
-            plotters.get("Cluster Time").region(this.computePlotterRegion(sensor))
-                                        .plot(clusterTimePlots.get(sensor), this.createStyle(1, "Cluster Time [ns]", ""));
-
-            trackClusterTimePlots.put(sensor,
-                    histogramFactory.createHistogram1D(sensor.getName() + " - Track Cluster Time", 100, -100, 100));
-            plotters.get("Cluster Time").region(this.computePlotterRegion(sensor))
-                                        .plot(trackClusterTimePlots.get(sensor), this.createStyle(3, "Cluster Time [ns]", ""));
-            
-            clusterChargeVsTimePlots.put(sensor,
-                    histogramFactory.createHistogram2D(sensor.getName() + " - Cluster Amplitude vs Time", 100, 0, 5000, 100, -100, 100));
-            plotters.get("Cluster Amplitude vs Cluster Time").region(this.computePlotterRegion(sensor))
-                                                             .plot(clusterChargeVsTimePlots.get(sensor));
+                                           .plot(trackHitSignalToNoisePlots
+                                           .get(sensor.getName()), this.createStyle(3, "Signal to Noise", ""));
+        
+            trackClusterChargeVsMomentum.put(sensor.getName(),
+                    histogramFactory.createHistogram2D(sensor.getName() + " - Cluster Amplitude vs Momentum", 100, 0, 1.5, 100, 0, 5000));
+            plotters.get("Cluster Amplitude vs Momentum").region(this.computePlotterRegion(sensor))
+                                                         .plot(trackClusterChargeVsMomentum
+                                                         .get(sensor.getName()));
+        
+            trackClusterChargeVsCosTheta.put(sensor.getName(),
+                    histogramFactory.createHistogram2D(sensor.getName() + " - Cluster Amplitude vs cos(theta)", 100, -0.1, 0.1, 100, 0, 5000));
+            plotters.get("Cluster Amplitude vs cos(theta)").region(this.computePlotterRegion(sensor))
+                                                         .plot(trackClusterChargeVsCosTheta
+                                                         .get(sensor.getName()));
+
+            trackClusterChargeVsSinPhi.put(sensor.getName(),
+                    histogramFactory.createHistogram2D(sensor.getName() + " - Cluster Amplitude vs sin(phi0)", 100, -0.2, 0.2, 100, 0, 5000));
+            plotters.get("Cluster Amplitude vs sin(phi0)").region(this.computePlotterRegion(sensor))
+                                                          .plot(trackClusterChargeVsSinPhi
+                                                          .get(sensor.getName()));
         }
         
 		for (IPlotter plotter : plotters.values()) { 
@@ -203,41 +254,45 @@
 		}
     }
 
+	@SuppressWarnings({ "unchecked", "rawtypes" })
     public void process(EventHeader event) { 
      
         if (runNumber == -1) runNumber = event.getRunNumber();
         
         // If the event doesn't contain fitted raw hits, skip it
-        if (!event.hasCollection(FittedRawTrackerHit.class, fittedHitsCollectionName)) return;
+        if (!event.hasCollection(LCRelation.class, fittedHitsCollectionName)) return;
         
         // Get the list of fitted hits from the event
-        List<FittedRawTrackerHit> fittedHits = event.get(FittedRawTrackerHit.class, fittedHitsCollectionName);
+        List<LCRelation> fittedHits = event.get(LCRelation.class, fittedHitsCollectionName);
         
         // Map the fitted hits to their corresponding raw hits
         this.mapFittedRawHits(fittedHits);
         
         // If the event doesn't contain any clusters, skip it
-        if (!event.hasCollection(SiTrackerHitStrip1D.class, clusterCollectionName)) return;
+        if (!event.hasCollection(TrackerHit.class, clusterCollectionName)) return;
         
         // Get the list of clusters in the event
-        List<SiTrackerHitStrip1D> clusters = event.get(SiTrackerHitStrip1D.class, clusterCollectionName);
+        List<TrackerHit> clusters = event.get(TrackerHit.class, clusterCollectionName);
         System.out.println("Number of clusters: " + clusters.size()); 
        
-        for (SiTrackerHitStrip1D cluster : clusters) { 
+        for (TrackerHit cluster : clusters) { 
            
             // Get the sensor associated with this cluster
-            HpsSiSensor sensor = (HpsSiSensor) cluster.getSensor();
+            HpsSiSensor sensor = (HpsSiSensor) ((RawTrackerHit) cluster.getRawHits().get(0)).getDetectorElement();
             
             // Get the raw hits composing this cluster and use them to calculate the amplitude of the hit
-            double amplitude = 0;
+            double amplitudeSum = 0;
             double noise = 0;
-            for (RawTrackerHit rawHit : cluster.getRawHits()) {
+            for (Object rawHitObject : cluster.getRawHits()) {
+
+                RawTrackerHit rawHit = (RawTrackerHit) rawHitObject; 
                 
                 // Get the channel of the raw hit
                 int channel = rawHit.getIdentifierFieldValue("strip");
                 
                 // Add the amplitude of that channel to the total amplitude
-                amplitude += this.getFittedHit(rawHit).getAmp();
+                double amplitude = FittedRawTrackerHit.getAmp(this.getFittedHit(rawHit));
+                amplitudeSum += FittedRawTrackerHit.getAmp(this.getFittedHit(rawHit));
                 
                 // Calculate the mean noise for the channel
                 double channelNoise = 0;
@@ -246,53 +301,88 @@
                 }
                 channelNoise = channelNoise/6;
                 
-                noise += channelNoise * this.getFittedHit(rawHit).getAmp();
+                noise += channelNoise * amplitude;
             }
       
-            clusterMultiplicityPlots.get(sensor).fill(cluster.getRawHits().size());
+            clusterSizePlots.get(sensor.getName()).fill(cluster.getRawHits().size());
             
             // Calculate the signal weighted noise
-            noise = noise/amplitude;
+            noise = noise/amplitudeSum;
             
             // Fill all plots
-            clusterChargePlots.get(sensor).fill(amplitude);
-            signalToNoisePlots.get(sensor).fill(amplitude/noise);
-            clusterTimePlots.get(sensor).fill(cluster.getTime());
-            clusterChargeVsTimePlots.get(sensor).fill(amplitude, cluster.getTime());
+            clusterChargePlots.get(sensor.getName()).fill(amplitudeSum);
+            signalToNoisePlots.get(sensor.getName()).fill(amplitudeSum/noise);
+            clusterTimePlots.get(sensor.getName()).fill(cluster.getTime());
+            clusterChargeVsTimePlots.get(sensor.getName()).fill(amplitudeSum, cluster.getTime());
             
             if (cluster.getRawHits().size() == 1) { 
-                singleHitClusterChargePlots.get(sensor).fill(amplitude);
-                singleHitSignalToNoisePlots.get(sensor).fill(amplitude/noise);
+                singleHitClusterChargePlots.get(sensor.getName()).fill(amplitudeSum);
+                singleHitSignalToNoisePlots.get(sensor.getName()).fill(amplitudeSum/noise);
             } else { 
-                multHitClusterChargePlots.get(sensor).fill(amplitude);
-                multHitSignalToNoisePlots.get(sensor).fill(amplitude/noise);
+                multHitClusterChargePlots.get(sensor.getName()).fill(amplitudeSum);
+                multHitSignalToNoisePlots.get(sensor.getName()).fill(amplitudeSum/noise);
             }
         }
-        
+       
         if (!event.hasCollection(Track.class, "MatchedTracks")) return;
         
         List<Track> tracks = event.get(Track.class, "MatchedTracks");
         
-        for (Track track : tracks) { 
-            
-            for (TrackerHit stereoHit : track.getTrackerHits()) { 
-               
-                for (HelicalTrackStrip cluster : ((HelicalTrackCross) stereoHit).getStrips()) {
-                    
+        // Get the collection of LCRelations between a stereo hit and the strips making it up
+        List<LCRelation> stereoHitRelations = event.get(LCRelation.class, stereoHitRelationsColName);
+        BaseRelationalTable stereoHitToClusters = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        for (LCRelation relation : stereoHitRelations) { 
+            if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+                stereoHitToClusters.add(relation.getFrom(), relation.getTo());
+            }
+        }
+        
+        // Get the collection of LCRelations relating RotatedHelicalTrackHits to
+        // HelicalTrackHits
+        List<LCRelation> rotatedHthToHthRelations = event.get(LCRelation.class, rotatedHthRelationsColName);
+        BaseRelationalTable hthToRotatedHth = new BaseRelationalTable(RelationalTable.Mode.ONE_TO_ONE, RelationalTable.Weighting.UNWEIGHTED);
+        for (LCRelation relation : rotatedHthToHthRelations) {
+            if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+                hthToRotatedHth.add(relation.getFrom(), relation.getTo());
+            }
+        }
+        
+        // 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);
+       
+        // Loop over all of the tracks in the event
+    	for(Track track : tracks){
+
+            // Calculate the momentum of the track
+            double p = this.getReconstructedParticle(track).getMomentum().magnitude();
+    	    
+    	    for (TrackerHit rotatedStereoHit : track.getTrackerHits()) { 
+    	    
+    	        // Get the HelicalTrackHit corresponding to the RotatedHelicalTrackHit
+    	        // associated with a track
+                Set<TrackerHit> trackClusters = stereoHitToClusters.allFrom(hthToRotatedHth.from(rotatedStereoHit));
+    	        
+    	        for (TrackerHit trackCluster : trackClusters) { 
+                
                     // Get the raw hits composing this cluster and use them to calculate the amplitude of the hit
-                    double amplitude = 0;
+                    double amplitudeSum = 0;
                     double noise = 0;
                     HpsSiSensor sensor = null;
-                    for (Object hit : cluster.rawhits()) { 
-                        RawTrackerHit rawHit = (RawTrackerHit) hit;
-                   
+
+                    for (Object rawHitObject : trackCluster.getRawHits()) {
+                        RawTrackerHit rawHit = (RawTrackerHit) rawHitObject; 
+                        
                         sensor = (HpsSiSensor) rawHit.getDetectorElement();
-                        
+                       
                         // Get the channel of the raw hit
                         int channel = rawHit.getIdentifierFieldValue("strip");
                 
                         // Add the amplitude of that channel to the total amplitude
-                        amplitude += this.getFittedHit(rawHit).getAmp();
+                        double amplitude = FittedRawTrackerHit.getAmp(this.getFittedHit(rawHit));
+                        amplitudeSum += FittedRawTrackerHit.getAmp(this.getFittedHit(rawHit));
                 
                         // Calculate the mean noise for the channel
                         double channelNoise = 0;
@@ -301,19 +391,23 @@
                         }
                         channelNoise = channelNoise/6;
                 
-                        noise += channelNoise * this.getFittedHit(rawHit).getAmp();
+                        noise += channelNoise * amplitude;
+                        
                     }
-                    
+
                     // Calculate the signal weighted noise
-                    noise = noise/amplitude;
+                    noise = noise/amplitudeSum;
                    
                     // Fill all plots
-                    trackClusterChargePlots.get(sensor).fill(amplitude);
-                    trackHitSignalToNoisePlots.get(sensor).fill(amplitude/noise);
-                    trackClusterTimePlots.get(sensor).fill(cluster.time());
-                }
-            }
-        }
+                    trackClusterChargePlots.get(sensor.getName()).fill(amplitudeSum);
+                    trackHitSignalToNoisePlots.get(sensor.getName()).fill(amplitudeSum/noise);
+                    trackClusterChargeVsMomentum.get(sensor.getName()).fill(p, amplitudeSum);
+                    trackClusterChargeVsCosTheta.get(sensor.getName()).fill(TrackUtils.getCosTheta(track), amplitudeSum);
+                    trackClusterChargeVsSinPhi.get(sensor.getName()).fill(Math.sin(TrackUtils.getPhi0(track)), amplitudeSum);
+                    //trackClusterTimePlots.get(sensor.getName()).fill(trackCluster.time());
+    	        }
+    	    }
+    	}
     }
     
     public void endOfData() { 
@@ -327,6 +421,8 @@
         } catch (IOException e) {
             e.printStackTrace();
         }
+    
+    
     }
     
     /**
@@ -334,26 +430,42 @@
      *  
      * @param fittedHits : List of fitted hits to map
      */
-    private void mapFittedRawHits(List<FittedRawTrackerHit> fittedHits) { 
+    private void mapFittedRawHits(List<LCRelation> fittedHits) { 
         
         // Clear the fitted raw hit map of old values
         fittedRawTrackerHitMap.clear();
        
         // Loop through all fitted hits and map them to their corresponding raw hits
-        for (FittedRawTrackerHit fittedHit : fittedHits) { 
-            fittedRawTrackerHitMap.put(fittedHit.getRawTrackerHit(), fittedHit);
-        }
-    }
-  
+        for (LCRelation fittedHit : fittedHits) { 
+            fittedRawTrackerHitMap.put(FittedRawTrackerHit.getRawTrackerHit(fittedHit), fittedHit);
+        }
+    }
+    
     /**
      * 
      * @param rawHit
      * @return
      */
-    private FittedRawTrackerHit getFittedHit(RawTrackerHit rawHit) { 
+    private LCRelation getFittedHit(RawTrackerHit rawHit) { 
         return fittedRawTrackerHitMap.get(rawHit);
     }
     
+    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);
+               }
+           }
+       }
+    }
+    
+    private ReconstructedParticle getReconstructedParticle(Track track) {
+        return reconParticleMap.get(track);
+    }
+   
     IPlotterStyle createStyle(int color, String xAxisTitle, String yAxisTitle) { 
        
         // Create a default style

Modified: java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/omoreno/SvtHitEfficiency.java
 =============================================================================
--- java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/omoreno/SvtHitEfficiency.java	(original)
+++ java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/omoreno/SvtHitEfficiency.java	Mon Jul  6 16:36:19 2015
@@ -11,7 +11,6 @@
 import hep.aida.IPlotter;
 import hep.aida.IHistogram1D;
 import hep.aida.ITree;
-
 import hep.physics.vec.BasicHep3Vector;
 import hep.physics.vec.Hep3Vector;
 import hep.physics.vec.VecOp;
@@ -27,9 +26,10 @@
 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.HelicalTrackHit;
 import org.lcsim.geometry.Detector;
 import org.lcsim.util.Driver;
 
@@ -56,13 +56,14 @@
     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<Integer, SvtStereoLayer> topStereoLayers = new HashMap<Integer, SvtStereoLayer>();
-    private Map<Integer, SvtStereoLayer> bottomStereoLayers = new HashMap<Integer, SvtStereoLayer>();
+    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>>();
 
     TrackerHitUtils trackerHitUtils = new TrackerHitUtils();
     
@@ -90,6 +91,7 @@
     
     // Collections
     private String trackCollectionName = "MatchedTracks";
+    private String fsParticlesCollectionName = "FinalStateParticles";
     private String stereoHitCollectionName = "HelicalTrackHits";
     private String ecalClustersCollectionName = "EcalClusters";
    
@@ -150,34 +152,45 @@
         List<SvtStereoLayer> stereoLayers 
             = ((HpsTracker2) detector.getSubdetector(SUBDETECTOR_NAME).getDetectorElement()).getStereoPairs();
         for (SvtStereoLayer stereoLayer : stereoLayers) { 
-            if (stereoLayer.getAxialSensor().isTopLayer()) { 
-                topStereoLayers.put(stereoLayer.getLayerNumber(), stereoLayer);
+            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 { 
-                bottomStereoLayers.put(stereoLayer.getLayerNumber(), stereoLayer);
-            }
-        }
-    
-        /*
-        String title = null;
-        IHistogram2D histo2D = null;
-        IHistogram1D histo1D = null;
-        ICloud2D cloud2D = null;
-        */
-
-        if (enableMomentumPlots) { 
-            
-           plotters.put("Track Momentum", plotterFactory.create("Track Momentum"));
-           plotters.get("Track Momentum").createRegions(1, 2);
-
-           trackMomentumPlots.put("Track Momentum", histogramFactory.createHistogram1D("Track Momentum", 50, 0, 5));
-           plotters.get("Track Momentum").region(0).plot(trackMomentumPlots.get("Track Momentum"));
+                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"));
+
+        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, 1.5));
+        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, 5));
-           plotters.get("Track Momentum").region(0)
-                                         .plot(trackMomentumPlots.get("Track Momentum - Tracks Within Acceptance"));
-        }
-
+        trackMomentumPlots.put("Track Momentum - Tracks Within Acceptance",
+                histogramFactory.createHistogram1D("Track Momentum - Tracks Within Acceptance", 50, 0, 1.5));
+        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, 1.5));
+        plotters.get("Track Momentum").region(2)
+                                      .plot(trackMomentumPlots.get("Track Momentum - All Layers Hit"));
+        
         // Create a Map from sensor to bad channels and from bad channels to
         // strip position
         /*
@@ -274,17 +287,6 @@
         return stripPositions.get(sensor).get(physicalChannel);
     }*/
 
-    /**
-     * Print a debug message if they are enabled.
-     * 
-     * @param debugMessage : message to be printed
-     */ 
-    private void printDebug(String debugMessage){
-        if(debug){
-            System.out.println(this.getClass().getSimpleName() + ": " + debugMessage);
-        }
-    }
-    
     public void process(EventHeader event){
         
         // If the event does not have tracks, skip it
@@ -293,7 +295,19 @@
         // Get the list of tracks from the event
         List<Track> tracks = event.get(Track.class, trackCollectionName);
         
-        if(tracks.size() >= 2 ) return;
+        // 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);
@@ -308,23 +322,76 @@
             }
            
             // Calculate the momentum of the track
-            double momentum = (new BasicHep3Vector(track.getTrackStates().get(0).getMomentum())).magnitude();
-
-            if (enableMomentumPlots) {
-                trackMomentumPlots.get("Track Momentum").fill(momentum); 
-            }
-
+            double p = this.getReconstructedParticle(track).getMomentum().magnitude();
+
+            trackMomentumPlots.get("Track Momentum").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);
 
             // Extrapolate the track to the unused layer and check that it lies
             // within the acceptance of that layer.  If it doesn't, move on
             // to the next event
             if(!isWithinAcceptance(track, unusedLayer)) continue;
 
-            if (enableMomentumPlots) { 
-                trackMomentumPlots.get("Track Momentum - Tracks Within Acceptance").fill(momentum); 
-            }
+            HpsSiSensor trackSensor = (HpsSiSensor) ((RawTrackerHit)track.getTrackerHits().get(0).getRawHits().get(0)).getDetectorElement();
+            
+            if (trackSensor.isTopLayer()) {
+                numberOfTopTracks++;
+            } else { 
+                numberOfBottomTracks++;
+            }
+            
+            trackMomentumPlots.get("Track Momentum - Tracks Within Acceptance").fill(p); 
+           
+            // Check if there is a stereo hit within some distance of the track 
+            // in the unused layer
+            for (TrackerHit stereoHit : stereoHits) {
+                
+                // Retrieve the sensor associated with one of the hits.  This will
+                // be used to retrieve the layer number
+                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) { 
+                    trackMomentumPlots.get("Track Momentum - All Layers Hit").fill(p);
+                    
+                    if (hitSensor.isTopLayer()) { 
+                        numberOfTopTracksWithHitOnMissingLayer++;
+                    } else { 
+                        numberOfBottomTracksWithHitOnMissingLayer++;
+                    }
+                    
+                    return;
+                }
+            }
+            
+            /* 
+            for(HelicalTrackHit stereoHit : stereoHits){
+                if(layer == stereoHit.Layer()){
+                    if(debug) System.out.println(this.getClass().getSimpleName() + ": Track has five layers hit");
+                    if(TrackUtils.getZ0(track) > 0){
+                        topTracksWithHitOnMissingLayer[arrayPosition]++;
+                    } else {
+                        bottomTracksWithHitOnMissingLayer[arrayPosition]++;
+                    }
+                    if(enableMomentumPlots)
+                        aida.histogram1D("Track Momentum - Tracks With All Layers Hit").fill(momentum);
+                    if(enableChiSquaredPlots)
+                        aida.histogram1D("Chi Squared - Tracks With All Layers Hit").fill(track.getChi2());
+                    
+                    return;
+                }
+            }*/
+            
+            
             //ecalClusterTrackMatch = false;
             
             // Check if there is an Ecal cluster in the same detector volume as the track
@@ -346,39 +413,9 @@
             }*/
             
             
-            //int arrayPosition = (layer - 1)/2;
-            
-            //if(TrackUtils.getZ0(track) > 0){
-                //numberOfTopTracks++;
-                //topTracksPerMissingLayer[arrayPosition]++;
-            //} else {
-                //numberOfBottomTracks++;
-                //bottomTracksPerMissingLayer[arrayPosition]++;
-            //}
-
             //if(enableChiSquaredPlots)
             //    aida.histogram1D("Chi Squared - Tracks Within Acceptance").fill(track.getChi2());
             
-            // Find if there is a stereo hit within that layer
-            /*List<HelicalTrackHit> stereoHits = event.get(HelicalTrackHit.class, stereoHitCollectionName);
-            for(HelicalTrackHit stereoHit : stereoHits){
-                if(layer == stereoHit.Layer()){
-                    if(debug) System.out.println(this.getClass().getSimpleName() + ": Track has five layers hit");
-                    if(TrackUtils.getZ0(track) > 0){
-                        numberOfTopTracksWithHitOnMissingLayer++;
-                        topTracksWithHitOnMissingLayer[arrayPosition]++;
-                    } else {
-                        numberOfBottomTracksWithHitOnMissingLayer++;
-                        bottomTracksWithHitOnMissingLayer[arrayPosition]++;
-                    }
-                    if(enableMomentumPlots)
-                        aida.histogram1D("Track Momentum - Tracks With All Layers Hit").fill(momentum);
-                    if(enableChiSquaredPlots)
-                        aida.histogram1D("Chi Squared - Tracks With All Layers Hit").fill(track.getChi2());
-                    
-                    return;
-                }
-            }*/
             
             /*int layerNumber = (layer - 1)/2 + 1;
             if(enableTrackPositionPlots){
@@ -413,59 +450,102 @@
      *  @param hits : List of stereo hits associated with a track
      *  @return Layer not used in the track fit
      */
-    private int getUnusedSvtLayer(List<TrackerHit> hits) {
+    private int getUnusedSvtLayer(List<TrackerHit> stereoHits) {
         
         int[] svtLayer = new int[6];
-        for (TrackerHit hit : hits) {
-            HelicalTrackHit stereoHit = (HelicalTrackHit) hit;
-            int  layer = (stereoHit.Layer() - 1)/2;
-            svtLayer[layer]++;
-        }
-        
+        
+        // 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) return (2*layer + 1);
-        }
-        
+            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;
     }
    
     /**
-     *  Check if a track lies within the acceptance of a layer.
-     *
-     */
-    // TODO: Move this to a utility class 
+     * 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) {
        
-        
-
-        List<HpsSiSensor> sensors = new ArrayList<HpsSiSensor>();
-        /*if(TrackUtils.getZ0(track) > 0){
-           //sensors.add(SvtUtils.getInstance().getTopSensor(layer, 0));
-           //sensors.add(SvtUtils.getInstance().getTopSensor(layer + 1, 0));
+        // 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 {
-           //sensors.add(SvtUtils.getInstance().getBottomSensor(layer, 0));
-           //sensors.add(SvtUtils.getInstance().getBottomSensor(layer + 1, 0));
-        }*/
-        
-        Hep3Vector frontSensorPos = sensors.get(0).getGeometry().getPosition();
-        Hep3Vector rearSensorPos = sensors.get(1).getGeometry().getPosition();
-        
-        this.frontTrackPos = TrackUtils.extrapolateTrack(track,frontSensorPos.z());
-        this.rearTrackPos = TrackUtils.extrapolateTrack(track,rearSensorPos.z());
-        
-        if(this.sensorContainsTrack(frontTrackPos, sensors.get(0)) && this.sensorContainsTrack(rearTrackPos, sensors.get(1))){
-//          if(this.sensorContainsTrack(trackPos, sensor))
-            if(enableTrackPositionPlots){
-                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());
-            }
-            return true;
-        } 
-        
+            //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()); */
+        
     }
     
     /**
@@ -477,13 +557,13 @@
         //--------------------------------------------------------------------------//
     
         //Rotate the track position to the JLab coordinate system
-        this.printDebug("Track position in tracking frame: " + trackPosition.toString());
+        //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());
+        //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());
+        //this.printDebug("Track position in sensor electrodes frame " + trackPositionDet.toString());
 
         // Find the closest channel to the track position
         double deltaY = Double.MAX_VALUE;
@@ -516,7 +596,7 @@
             if(sensor.isBadChannel(intersectingChannel) 
                     || sensor.isBadChannel(intersectingChannel+1) 
                     || sensor.isBadChannel(intersectingChannel-1)){
-                this.printDebug("Track intersects a bad channel!");
+                //this.printDebug("Track intersects a bad channel!");
                 return false;
             }
         }
@@ -536,45 +616,44 @@
                 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()));
-                if(debug){
-                    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());
-                }
+               //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()));
-                if(debug){
-                System.out.println(this.getClass().getSimpleName() + ": Vertex 2 Position: " + vertices.get(1).toString());
+                //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()));
-                if(debug){
-                System.out.println(this.getClass().getSimpleName() + ": Vertex 3 Position: " + vertices.get(2).toString());
+                //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()));
-                if(debug){
-                System.out.println(this.getClass().getSimpleName() + ": Vertex 4 Position: " + vertices.get(3).toString());
+                //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;
     } 
@@ -619,4 +698,31 @@
         }*/
         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);
+    }
+
 }

Modified: java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/phansson/TrackingReconstructionPlots.java
 =============================================================================
--- java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/phansson/TrackingReconstructionPlots.java	(original)
+++ java/branches/HPSJAVA-488/users/src/main/java/org/hps/users/phansson/TrackingReconstructionPlots.java	Mon Jul  6 16:36:19 2015
@@ -6,7 +6,6 @@
 import hep.aida.IPlotter;
 import hep.aida.IPlotterStyle;
 import hep.aida.IProfile;
-import hep.physics.matrix.SymmetricMatrix;
 import hep.physics.vec.BasicHep3Vector;
 import hep.physics.vec.Hep3Vector;
 
@@ -18,21 +17,15 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.apache.commons.lang3.tuple.Pair;
-import org.hps.readout.ecal.FADCEcalReadoutDriver.PulseShape;
 import org.hps.recon.tracking.BeamlineConstants;
 import org.hps.recon.tracking.DumbShaperFit;
 import org.hps.recon.tracking.FittedRawTrackerHit;
 import org.hps.recon.tracking.HelixConverter;
-import org.hps.recon.tracking.ShapeFitParameters;
 import org.hps.recon.tracking.ShaperFitAlgorithm;
 import org.hps.recon.tracking.StraightLineTrack;
 import org.hps.recon.tracking.TrackUtils;
 import org.hps.recon.tracking.gbl.HelicalTrackStripGbl;
-import org.hps.recon.tracking.gbl.HpsGblRefitter;
 import org.hps.util.BasicLogFormatter;
-import org.lcsim.constants.Constants;
-import org.lcsim.detector.IDetectorElement;
 import org.lcsim.detector.tracker.silicon.HpsSiSensor;
 import org.lcsim.detector.tracker.silicon.SiSensor;
 import org.lcsim.event.Cluster;
@@ -51,6 +44,7 @@
 import org.lcsim.geometry.IDDecoder;
 import org.lcsim.geometry.compact.converter.HPSTrackerBuilder;
 import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.digitization.sisim.TrackerHitType;
 import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
 import org.lcsim.recon.tracking.seedtracker.SeedTrack;
 import org.lcsim.util.Driver;
@@ -69,14 +63,10 @@
 
     
     private AIDA aida = AIDA.defaultInstance();
-    private String rawTrackerHitCollectionName = "SVTRawTrackerHits";
-    private String fittedTrackerHitCollectionName = "SVTFittedRawTrackerHits";
-    private String trackerHitCollectionName = "StripClusterer_SiTrackerHitStrip1D";
     private String helicalTrackHitCollectionName = "HelicalTrackHits";
-    private String rotatedTrackHitCollectionName = "RotatedHelicalTrackHits";
-    private String helicalTrackHitRelationsCollectionName = "HelicalTrackHitRelations";
+    private String stripClusterCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+    
     private String trackCollectionName = "MatchedTracks";
-    private String trackerName = "Tracker";
     String ecalSubdetectorName = "Ecal";
     String ecalCollectionName = "EcalClusters";
     IDDecoder dec;
@@ -103,6 +93,7 @@
     IPlotter plotter66;
     IPlotter plotter7;
     IPlotter plotter8;
+    IPlotter plotter88;
     IPlotter plotter9;
     IPlotter top1;
     IPlotter top2;
@@ -776,8 +767,6 @@
         style5.dataStyle().errorBarStyle().setVisible(false);
         plotter5.createRegions(1, 2);
 
-        IHistogram1D charge = aida.histogram1D("Charge", 3, -1, 1);
-
         IHistogram2D l1Pos = aida.histogram2D("Layer 1 HTH Position:  Top", 50, -55, 55, 55, -25, 25);
         IHistogram2D l7Pos = aida.histogram2D("Layer 7 HTH Position:  Top", 50, -55, 55, 55, -25, 25);
 
@@ -813,8 +802,8 @@
         style55.dataStyle().markerStyle().setSize(20);
         plotter55.createRegions(1, 2);
 
-        IProfile avgLayersTopPlot = aida.profile1D("Number of Stereo Hits per layer in Top Half", 5, 1, 11);
-        IProfile avgLayersBottomPlot = aida.profile1D("Number of Stereo Hits per layer in Bottom Half", 5, 1, 11);
+        IProfile avgLayersTopPlot = aida.profile1D("Number of Stereo Hits per layer in Top Half", 13, 0, 13);
+        IProfile avgLayersBottomPlot = aida.profile1D("Number of Stereo Hits per layer in Bottom Half", 13, 0, 13);
 
         plotter55.region(0).plot(avgLayersTopPlot);
         plotter55.region(1).plot(avgLayersBottomPlot);
@@ -888,7 +877,7 @@
         
         if(showPlots) plotter7.show();
         
-        plotter8 = fac.createPlotterFactory().create("HPS Strip Hit Multiplicity");
+        plotter8 = fac.createPlotterFactory().create("HPS Strip Hit From Stereo Multiplicity");
         plotter8.setTitle("Strip Hit Multiplicity");
         //plotterFrame.addPlotter(plotter8);
         IPlotterStyle style8 = plotter8.style();
@@ -897,12 +886,26 @@
         plotter8.createRegions(6, 6);
         i=0;
         for(SiSensor sensor : sensors) {
-            IHistogram1D resX = aida.histogram1D(sensor.getName() + " strip hits", 10, 0, 10);
+            IHistogram1D resX = aida.histogram1D(sensor.getName() + " strip hits from stereo", 10, 0, 10);
             plotter8.region(i).plot(resX);
             i++;
         }
 
         if(showPlots) plotter8.show();
+        
+        plotter88 = fac.createPlotterFactory().create("HPS Strip Hit Multiplicity");
+        plotter88.setTitle("Strip Hit Multiplicity");
+        //plotterFrame.addPlotter(plotter88);
+        plotter88.setStyle(style8);
+        plotter88.createRegions(6, 6);
+        i=0;
+        for(SiSensor sensor : sensors) {
+            IHistogram1D resX = aida.histogram1D(sensor.getName() + " strip hits", 10, 0, 10);
+            plotter88.region(i).plot(resX);
+            i++;
+        }
+
+        if(showPlots) plotter88.show();
         
         
         plotter9 = fac.createPlotterFactory().create("HPS Strip Hit On Track Multiplicity");
@@ -936,20 +939,6 @@
         this.showPlots  = show;
     }
 
-    
-    
-    public void setRawTrackerHitCollectionName(String rawTrackerHitCollectionName) {
-        this.rawTrackerHitCollectionName = rawTrackerHitCollectionName;
-    }
-
-    public void setFittedTrackerHitCollectionName(String fittedTrackerHitCollectionName) {
-        this.fittedTrackerHitCollectionName = fittedTrackerHitCollectionName;
-    }
-
-    public void setTrackerHitCollectionName(String trackerHitCollectionName) {
-        this.trackerHitCollectionName = trackerHitCollectionName;
-    }
-
     public void setHelicalTrackHitCollectionName(String helicalTrackHitCollectionName) {
         this.helicalTrackHitCollectionName = helicalTrackHitCollectionName;
     }
@@ -965,19 +954,41 @@
 //            System.out.println(helicalTrackHitCollectionName + " does not exist; skipping event");
             return;
         }
+        
+        List<SiTrackerHitStrip1D> stripClusters = event.get(SiTrackerHitStrip1D.class, stripClusterCollectionName);
+        //System.out.printf("%s: Got %d SiTrackerHitStrip1D in this event\n", stripHits.size());
+        Map<HpsSiSensor, Integer> stripHits = new HashMap<HpsSiSensor, Integer>();
+        for (SiTrackerHitStrip1D stripHit : stripClusters) {
+            HpsSiSensor sensor = (HpsSiSensor) stripHit.getRawHits().get(0).getDetectorElement();
+            int n;
+            if(stripHits.containsKey(sensor)) {
+                n = stripHits.get(sensor);
+            } else {
+                n=0;
+            }
+            n++;
+            stripHits.put(sensor, n);
+        }
+        
+        for(Map.Entry<HpsSiSensor,Integer> sensor : stripHits.entrySet()) {
+            aida.histogram1D(sensor.getKey().getName() + " strip hits").fill(sensor.getValue());
+        }
+        
+        
+        
         List<HelicalTrackHit> hthList = event.get(HelicalTrackHit.class, helicalTrackHitCollectionName);
         int[] layersTop = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
         int[] layersBot = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-        Map<HpsSiSensor, Integer> stripHits = new HashMap<HpsSiSensor, Integer>();
+        Map<HpsSiSensor, Integer> stripHitsFromStereoHits = new HashMap<HpsSiSensor, Integer>();
         for (HelicalTrackHit hth : hthList) {
             HelicalTrackCross htc = (HelicalTrackCross) hth;
             HpsSiSensor sensor = ((HpsSiSensor) ((RawTrackerHit) htc.getRawHits().get(0)).getDetectorElement());
             for(HelicalTrackStrip strip : htc.getStrips()) {
                 HpsSiSensor stripsensor = (HpsSiSensor) ((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement();
-                if(stripHits.containsKey(stripsensor)) {
-                    stripHits.put(stripsensor, stripHits.get(stripsensor) + 1);
+                if(stripHitsFromStereoHits.containsKey(stripsensor)) {
+                    stripHitsFromStereoHits.put(stripsensor, stripHitsFromStereoHits.get(stripsensor) + 1);
                 } else {
-                    stripHits.put(stripsensor, 0);
+                    stripHitsFromStereoHits.put(stripsensor, 0);
                 }
             }
             if(sensor.isTopLayer()){
@@ -986,8 +997,8 @@
                 layersBot[htc.Layer() - 1]++;
             }
         }
-        for(Map.Entry<HpsSiSensor,Integer> sensor : stripHits.entrySet()) {
-            aida.histogram1D(sensor.getKey().getName() + " strip hits").fill(sensor.getValue());
+        for(Map.Entry<HpsSiSensor,Integer> sensor : stripHitsFromStereoHits.entrySet()) {
+            aida.histogram1D(sensor.getKey().getName() + " strip hits from stereo").fill(sensor.getValue());
         }
         
         for (int i = 0; i < 12; i++) {
@@ -1008,8 +1019,8 @@
             List<Cluster> clusters = event.get(Cluster.class, ecalCollectionName);
             for (Cluster cluster : clusters) {
              // Get the ix and iy indices for the seed.
-                final int ix = cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
-                final int iy = cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
+//                final int ix = cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("ix");
+//                final int iy = cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("iy");
  
                 //System.out.println("cluser position = ("+cluster.getPosition()[0]+","+cluster.getPosition()[1]+") with energy = "+cluster.getEnergy());
                 if (cluster.getPosition()[1] > 0) {
@@ -1475,10 +1486,8 @@
     }
 
     public int[] getStripClustersPerLayer(List<SiTrackerHitStrip1D> trackerHits, String side) {
-        String si_side;
         String name;
         int l;
-        int i;
         int n[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
         boolean ddd = false;
 
@@ -1580,8 +1589,6 @@
             double[] clPos = cluster.getPosition();
             double clEne = cluster.getEnergy();
             double dist = Math.sqrt(Math.pow(clPos[0] - posonhelix.x(), 2) + Math.pow(clPos[1] - posonhelix.y(), 2)); //coordinates!!!
-            double distX = Math.abs(clPos[0] - posonhelix.x());
-            double distY = Math.abs(clPos[1] - posonhelix.y());
             if (dist < minDist && clEne > 0.4) {
                 closest = cluster;
                 minDist = dist;