LISTSERV mailing list manager LISTSERV 16.5

Help for HPS-SVN Archives


HPS-SVN Archives

HPS-SVN Archives


HPS-SVN@LISTSERV.SLAC.STANFORD.EDU


View:

Message:

[

First

|

Previous

|

Next

|

Last

]

By Topic:

[

First

|

Previous

|

Next

|

Last

]

By Author:

[

First

|

Previous

|

Next

|

Last

]

Font:

Proportional Font

LISTSERV Archives

LISTSERV Archives

HPS-SVN Home

HPS-SVN Home

HPS-SVN  July 2015

HPS-SVN July 2015

Subject:

r3231 - in /java/branches/HPSJAVA-488: ./ analysis/src/main/java/org/hps/analysis/dataquality/ conditions/ conditions/src/main/java/org/hps/conditions/svt/ detector-data/detectors/HPS-EngRun2015-Nominal-v2/ detector-model/src/main/java/org/lcsim/geometry/compact/converter/ detector-model/src/main/java/org/lcsim/geometry/compact/converter/lcdd/ detector-model/src/test/java/org/lcsim/geometry/compact/converter/lcdd/ detector-model/src/test/resources/org/lcsim/geometry/subdetector/ ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/ evio/src/main/java/org/hps/evio/ integration-tests/ integration-tests/src/test/java/org/hps/test/it/ monitoring-drivers/src/main/java/org/hps/monitoring/drivers/svt/ parent/ plugin/ recon/src/main/java/org/hps/recon/filtering/ record-util/src/main/java/org/hps/record/evio/crawler/ record-util/src/main/java/org/hps/record/scalers/ steering-files/src/main/resources/org/hps/steering/production/ steering-files/src/main/resources/org/hps/steering/readout/ steering-files/src/main/resources/org/hps/steering/recon/ steering-files/src/main/resources/org/hps/steering/users/meeg/ tracking/src/main/java/org/hps/recon/tracking/ tracking/src/main/java/org/hps/recon/tracking/gbl/ tracking/src/main/resources/org/hps/recon/tracking/strategies/ users/src/main/java/org/hps/users/kmccarty/ users/src/main/java/org/hps/users/luca/ users/src/main/java/org/hps/users/meeg/ users/src/main/java/org/hps/users/omoreno/ users/src/main/java/org/hps/users/phansson/

From:

[log in to unmask]

Reply-To:

Notification of commits to the hps svn repository <[log in to unmask]>

Date:

Mon, 6 Jul 2015 23:37:56 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (6455 lines)

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;

Top of Message | Previous Page | Permalink

Advanced Options


Options

Log In

Log In

Get Password

Get Password


Search Archives

Search Archives


Subscribe or Unsubscribe

Subscribe or Unsubscribe


Archives

November 2017
August 2017
July 2017
January 2017
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013

ATOM RSS1 RSS2



LISTSERV.SLAC.STANFORD.EDU

Secured by F-Secure Anti-Virus CataList Email List Search Powered by the LISTSERV Email List Manager

Privacy Notice, Security Notice and Terms of Use