Commit in java/trunk/users on MAIN
pom.xml+26added 52
src/main/java/org/lcsim/hps/users/homer/HPSTrackerEvent.java+183added 52
                                       /HPSTrackerSample.java+66added 52
src/main/java/org/lcsim/hps/users/meeg/FilterMCBunches.java+302added 52
                                      /HPSEcalAnalogPrintDriver.java+87added 52
                                      /HPSEcalDigitalPrintDriver.java+90added 52
                                      /HPSEcalPrintDriver.java+108added 52
                                      /HPSEcalRawTrackerHitPrintDriver.java+88added 52
                                      /HPSGenericRawTrackerHitPrintDriver.java+60added 52
                                      /HitTimePrintDriver.java+31added 52
                                      /KinkAnalysisDriver.java+311added 52
                                      /LCIOTrackAnalysis.java+167added 52
                                      /MergeMCBunches.java+192added 52
                                      /NoiselessReadoutChip.java+314added 52
                                      /SimpleTrackerDigiDriver.java+71added 52
src/main/java/org/lcsim/hps/users/mgraham/DetailedAnalysisDriver.java+1598added 52
                                         /ElwinsTrackingRecon.java+1559added 52
                                         /ExamplePlotter.java+113added 52
                                         /FastTrackAnalysisDriver.java+937added 52
                                         /HPSTrackerHit.java+43added 52
                                         /HelicalTrackHitResidualsDriver.java+328added 52
                                         /HitTimePlotter.java+487added 52
                                         /JasAnalysisDriver.java+1017added 52
                                         /KalmanFilterDriver.java+248added 52
                                         /KalmanGeom.java+564added 52
                                         /MainJASDriver.java+55added 52
                                         /MyLCIOWriterDriver.java+90added 52
                                         /PropXYXY_Test.java+530added 52
                                         /SingleSensorHelicalTrackHitDriver.java+383added 52
                                         /SingleSensorTrackerReconDriver.java+173added 52
                                         /TestAnalysisDriver.java+134added 52
                                         /TrackExtrapolationAnalysis.java+476added 52
                                         /TwoTrackAnalysis.java+988added 52
src/main/java/org/lcsim/hps/users/mgraham/alignment/AlignmentParameters.java+559added 52
                                                   /HPSStrips.java+482added 52
                                                   /RunAlignment.java+97added 52
                                                   /SiTrackerSpectrometerSensorSetup.java+265added 52
src/main/java/org/lcsim/hps/users/mgraham/jlabrotation/DetailedAnalysisDriver.java+1523added 52
src/main/java/org/lcsim/hps/users/omoreno/EcalHitPosition.java+57added 52
                                         /EventDataDriver.java+56added 52
                                         /PlotUtils.java+112added 52
                                         /ReconstructedParticleChecker.java+123added 52
                                         /SimpleSvtTrigger.java+152added 52
                                         /SvtHitCorrelations.java+196added 52
                                         /SvtHitEfficiency.java+573added 52
                                         /SvtPerformance.java+452added 52
                                         /SvtQA.java+875added 52
                                         /SvtTrackAnalysis.java+426added 52
                                         /SvtTrackRecoEfficiency.java+488added 52
                                         /SvtTrackingPerformance.java+95added 52
                                         /TestRunTrackReconEfficiency.java+414added 52
src/main/java/org/lcsim/hps/users/phansson/AlignmentUtils.java+1648added 52
                                          /BeamCurrentData.java+49added 52
                                          /CmpGenToFittedTracksDriver.java+192added 52
                                          /Count.java+47added 52
                                          /DAQDeadTimeData.java+41added 52
                                          /DumpAIDATextFiles.java+162added 52
                                          /ECalGainDriver.java+521added 52
                                          /ECalHitMapPlots.java+320added 52
                                          /FastTrack.java+142added 52
                                          /FastTrackResidualDriver.java+817added 52
                                          /GlobalParameter.java+116added 52
                                          /GlobalParameters.java+77added 52
                                          /MPAlignmentInputCalculator.java+133added 52
                                          /ModuleMPAlignmentInput.java+710added 52
                                          /MultScatAnalysis.java+2441added 52
                                          /ParticleHelixProducer.java+317added 52
                                          /PolarCount.java+69added 52
                                          /ResLimit.java+101added 52
                                          /RunMPAlignment.java+231added 52
                                          /SimpleHPSConditions.java+133added 52
                                          /SimpleResiduals.java+749added 52
                                          /StripMPAlignmentInput.java+1127added 52
                                          /TestSort.java+79added 52
                                          /TrigRateAna.java+1275added 52
                                          /TrigRateDriver.java+476added 52
                                          /TriggerTurnOnAnalysis.java+392added 52
                                          /TruthMomentumResolutionDriver.java+417added 52
                                          /TwoTrackAnlysis.java+1061added 52
                                          /WTrack.java+339added 52
                                          /dataMCPlots.java+373added 52
                                          /ecalGainAna.java+455added 52
                                          /ecalPlots.java+336added 52
                                          /mergeSimpleAIDA.java+199added 52
                                          /trigRate.java+292added 52
src/main/java/org/lcsim/hps/users/sarah/ExamplePlotter.java+71added 52
+34672
86 added files
copying user packages to separate Maven module

java/trunk/users
pom.xml added at 52
--- java/trunk/users/pom.xml	                        (rev 0)
+++ java/trunk/users/pom.xml	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>hps-users</artifactId>
+    <groupId>org.hps</groupId>
+    <name>users</name>
+    <version>1.0-SNAPSHOT</version>
+    <description>HPS user code packages</description>
+    <parent>
+        <groupId>org.lcsim</groupId>
+        <artifactId>lcsim-parent</artifactId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <scm>
+        <connection>svn://svn.freehep.org/hps/java/trunk/users</connection>
+        <developerConnection>svn://svn.freehep.org/hps/java/trunk/users</developerConnection>
+        <url>http://bogus.hps.org/</url>
+    </scm>
+    <dependencies>
+        <dependency>
+            <groupId>org.hps</groupId>
+            <artifactId>hps-java</artifactId>
+            <version>3.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+</project>

java/trunk/users/src/main/java/org/lcsim/hps/users/homer
HPSTrackerEvent.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/homer/HPSTrackerEvent.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/homer/HPSTrackerEvent.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,183 @@
+/*
+ * Description : based on the C++ version from Ryan Herbst
+ * 
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ *  Description :
+ * Event Container
+ * Event Data consists of the following: Z[xx:xx] = Zeros
+ *    Frame Size = 1 x 32-bits (32-bit dwords)
+ *    Header = 8 x 32-bits
+ *    Header[0] = T[0], Z[14:0], FpgaAddress[15:0] - T = 1 For TI FPGA
+ *    Header[1] = Sequence[31:0]
+//
+ * The rest of the event header depends on the T flag, For T = 0:
+//
+ *    Header[2] = TempB[15:0], TempA[15:0]
+ *    Header[3] = TempD[15:0], TempC[15:0]
+ *    Header[4] = TempF[15:0], TempE[15:0]
+ *    Header[5] = TempH[15:0], TempG[15:0]
+ *    Header[6] = TempJ[15:0], TempI[15:0]
+ *    Header[7] = TempL[15:0], TempK[15:0]
+ *       Samples... (See HPSTrackerSample.java)
+ *   Tail = 1 x 32-bits
+ *       Should be zero
+ */
+package org.lcsim.hps.users.homer;
+
+/**
+ *
+ * @author neal
+ */
+public class HPSTrackerEvent extends HPSTrackerSample {
+
+    double temp;
+    double tk;
+    double res;
+    double volt;
+    int idx;
+    
+    // Temperature Constants
+    double coeffA_ = -1.4141963e1;
+    double coeffB_ = 4.4307830e3;
+    double coeffC_ = -3.4078983e4;
+    double coeffD_ = -8.8941929e6;
+    double t25_ = 10000.0;
+    double k0_ = 273.15;
+    double vmax_ = 2.5;
+    double vref_ = 2.5;
+    double rdiv_ = 10000;
+    double minTemp_ = -50;
+    double maxTemp_ = 150;
+    double incTemp_ = 0.01;
+    int adcCnt_ = 4096;
+    
+    // Temperature lookup table
+    double tempTable_[] = new double[adcCnt_];
+    
+    // Local trigger data
+    int tiData_[] = new int[7]; // What size can this grow to????
+    
+    // Frame Constants
+    int headSize_ = 8;
+    int tailSize_ = 1;
+    int sampleSize_ = 4;
+    
+    // frame size must be set externally
+    int size_ = 0;
+
+    public void TrackerEvent() {
+
+        // Fill temperature lookup table
+        temp = minTemp_;
+        while (temp < maxTemp_) {
+            tk = k0_ + temp;
+            res = t25_ * Math.exp(coeffA_ + (coeffB_ / tk) + (coeffC_ / (tk * tk)) + (coeffD_ / (tk * tk * tk)));
+            volt = (res * vmax_) / (rdiv_ + res);
+            idx = (int) ((volt / vref_) * (double) (adcCnt_ - 1));
+            if (idx < adcCnt_) {
+                tempTable_[idx] = temp;
+            }
+            temp += incTemp_;
+        }
+    }
+
+    // Get TI flag from header
+    public boolean isTiFrame() {
+        return ((data_[0] & 0x80000000) != 0);
+    }
+
+// Get FpgaAddress value from header.
+    public int fpgaAddress() {
+        return (data_[0] & 0xFFFF);
+    }
+
+// Get sequence count from header.
+    public int sequence() {
+        return (data_[1]);
+    }
+
+// Get trigger block from header.
+    int[] tiData() {
+        for (int iti = 0; iti < tiData_.length; iti++) {
+            tiData_[iti] = data_[2 + iti];
+        }
+        return (tiData_);
+    }
+
+    // Set address of data buffer
+    public void setData(int indat[]) {
+        data_ = indat;
+    }
+
+// Set frame size
+    public void setSize(int sz) {
+        size_ = sz;
+    }
+
+    // Get sample size value from header.
+    public int sampleSize() {
+        return ((data_[0] >> 8) & 0xF);
+    }
+
+// Get temperature values from header.
+    public double temperature(int index) {
+        if (isTiFrame()) {
+            return (0.0);
+        } else {
+            switch (index) {
+                case 0:
+                    return (tempTable_[(data_[2] & 0x3FFF)]);
+                case 1:
+                    return (tempTable_[((data_[2] >> 16) & 0x3FFF)]);
+                case 2:
+                    return (tempTable_[(data_[3] & 0x3FFF)]);
+                case 3:
+                    return (tempTable_[((data_[3] >> 16) & 0x3FFF)]);
+                case 4:
+                    return (tempTable_[(data_[4] & 0x3FFF)]);
+                case 5:
+                    return (tempTable_[((data_[4] >> 16) & 0x3FFF)]);
+                case 6:
+                    return (tempTable_[(data_[5] & 0x3FFF)]);
+                case 7:
+                    return (tempTable_[((data_[5] >> 16) & 0x3FFF)]);
+                case 8:
+                    return (tempTable_[(data_[6] & 0x3FFF)]);
+                case 9:
+                    return (tempTable_[((data_[6] >> 16) & 0x3FFF)]);
+                case 10:
+                    return (tempTable_[(data_[7] & 0x3FFF)]);
+                case 11:
+                    return (tempTable_[((data_[7] >> 16) & 0x3FFF)]);
+                default:
+                    return (0.0);
+            }
+        }
+
+    }
+
+// Get sample count
+    public int count() {
+//        return (128);
+//        int size_ = sampleSize();
+//        System.out.println("count: size_ = " + size_);
+        return ((size_ - (headSize_ + tailSize_)) / sampleSize_);
+    }
+// Get sample at index
+
+    public HPSTrackerSample sample(int index) {
+        if (index >= count()) { // should be count()
+            return (null);
+        } else {
+            HPSTrackerSample sample_ = new HPSTrackerSample();
+            for (int ii = 0; ii < sampleSize_; ii++) {
+                ldata_[ii] = data_[headSize_ + (index * sampleSize_) + ii];
+//                System.out.println("ldata[" + ii + "] = " + ldata_[ii]);
+            }
+//            sample_.setData(data_[headSize_ + (index * sampleSize_)]);
+            sample_.setData(ldata_);
+            return (sample_);
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/homer
HPSTrackerSample.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/homer/HPSTrackerSample.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/homer/HPSTrackerSample.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,66 @@
+/*
+ * Description : based on the C++ version from Ryan Herbst
+ * Sample Container
+ * Sample Data consists of the following: Z[xx:xx] = Zeros, O[xx:xx] = Ones
+ *    Sample[0] = O[0], Z[0], Hybrid[1:0], Z[0], ApvChip[2:0], Z[0], Channel[6:0], FpgaAddress[15:0]
+ *    Sample[1] = Z[1:0], Sample1[13:0]], Z[1:0], Sample0[13:0]
+ *    Sample[2] = Z[1:0], Sample3[13:0]], Z[1:0], Sample2[13:0]
+ *    Sample[3] = Z[1:0], Sample5[13:0]], Z[1:0], Sample4[13:0]
+ * 
+ */
+package org.lcsim.hps.users.homer;
+
+/**
+ *
+ * @author neal
+ */
+public class HPSTrackerSample {
+    // Local data
+
+    protected int ldata_[] = new int[4];
+    // Data pointer
+    protected int data_[];
+
+    public void setData(int data[]) {
+        data_ = data;
+    }
+    //! Get hybrid index.
+    public int hybrid() {
+        return ((data_[0] >> 28) & 0x3);
+    }
+    //! Get apv index.
+
+    public int apv() {
+        return ((data_[0] >> 24) & 0x7);
+    }
+
+    //! Get channel index.
+    public int channel() {
+        return ((data_[0] >> 16) & 0x7F);
+    }
+
+    //! Get FpgaAddress value from header.
+    public int fpgaAddress() {
+        return (data_[0] & 0xFFFF);
+    }
+    //! Get adc value at index.
+
+    public int value(int index) {
+        switch (index) {
+            case 0:
+                return (data_[1] & 0x3FFF);
+            case 1:
+                return ((data_[1] >> 16) & 0x3FFF);
+            case 2:
+                return (data_[2] & 0x3FFF);
+            case 3:
+                return ((data_[2] >> 16) & 0x3FFF);
+            case 4:
+                return (data_[3] & 0x3FFF);
+            case 5:
+                return ((data_[3] >> 16) & 0x3FFF);
+            default:
+                return (0);
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
FilterMCBunches.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/FilterMCBunches.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/FilterMCBunches.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,302 @@
+package org.lcsim.hps.users.meeg;
+
+import java.io.*;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawCalorimeterHit;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimCalorimeterHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseLCSimEvent;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.lcio.LCIOReader;
+import org.lcsim.lcio.LCIOWriter;
+import org.lcsim.util.loop.LCSimConditionsManagerImplementation;
+
+/**
+ * Selects LCIO events passing a cut; spaces out these events with blank events.
+ * Intended use is to clean up a photon-run MC file before running trigger and readout sim.
+ * Can also be used to chain multiple LCIO files together.
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: FilterMCBunches.java,v 1.9 2013/02/25 21:53:42 meeg Exp $
+ */
+public class FilterMCBunches {
+
+    /**
+     * Defines command line options for this program.
+     *
+     * @return The command line options.
+     */
+    private static Options createCommandLineOptions() {
+        Options options = new Options();
+        Option opt_e = new Option("e", true, "Interval between non-empty events");
+        opt_e.setRequired(true);
+        options.addOption(opt_e);
+        //options.addOption(new Option("e", true, "Interval between non-empty events"));
+        options.addOption(new Option("n", true, "Number of events to read"));
+        options.addOption(new Option("a", false, "All events - no cuts"));
+        options.addOption(new Option("t", false, "Filter based on SimTrackerHits"));
+        options.addOption(new Option("r", false, "Filter based on RawTrackerHits"));
+        options.addOption(new Option("E", true, "Energy cut for EcalHit cut"));
+        return options;
+    }
+
+    public static void main(String[] args) {
+        // Set up command line parsing.
+        Options options = createCommandLineOptions();
+        CommandLineParser parser = new PosixParser();
+
+        // Parse command line arguments.
+        CommandLine cl = null;
+        try {
+            cl = parser.parse(options, args);
+        } catch (ParseException e) {
+            throw new RuntimeException("Problem parsing command line options.", e);
+        }
+
+        String[] parsedArgs = cl.getArgs();
+
+        if (parsedArgs.length < 2) {
+            System.out.println("FilterMCBunches <input files> <output file>");
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", options);
+            System.exit(1);
+        }
+
+        String outFileName = parsedArgs[parsedArgs.length - 1];
+
+        LCIOWriter writer = null;
+        try {
+            writer = new LCIOWriter(new File(outFileName));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        EventTester tester = null;
+        if (!cl.hasOption("a")) {
+            if (cl.hasOption("E")) {
+                tester = new EcalEventTester(Double.valueOf(cl.getOptionValue("E")));
+            } else {
+                tester = new EcalEventTester(0.05);
+            }
+        }
+        if (cl.hasOption("t")) {
+            tester = new TrackerEventTester();
+        }
+        if (cl.hasOption("r")) {
+            tester = new RTHEventTester();
+        }
+
+
+        int nEmpty = 0;
+        if (cl.hasOption("e")) {
+            nEmpty = Integer.valueOf(cl.getOptionValue("e"));
+        } else {
+            System.out.println("You need to specify the number of empty bunches!");
+            System.exit(1);
+        }
+
+        int nEvents = -1;
+        if (cl.hasOption("n")) {
+            nEvents = Integer.valueOf(cl.getOptionValue("n"));
+        }
+        int readEvents = 0;
+        int writtenEvents = 0;
+
+        String detectorName = null;
+
+        fileLoop:
+        for (int fileNumber = 0; fileNumber < parsedArgs.length - 1; fileNumber++) {
+            LCIOReader reader = null;
+            String inFileName = parsedArgs[fileNumber];
+            try {
+                reader = new LCIOReader(new File(inFileName));
+                System.out.println("Opened input file " + inFileName);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+
+            eventLoop:
+            while (true) {
+                if (nEvents != -1 && readEvents == nEvents) {
+                    break fileLoop;
+                }
+                EventHeader event;
+                try {
+                    event = reader.read();
+                } catch (IOException e) {
+                    break eventLoop;
+                }
+                readEvents++;
+
+                if (detectorName == null) {
+                    detectorName = event.getDetectorName();
+                }
+
+                if (tester == null || tester.goodEvent(event)) {
+                    writtenEvents++;
+                    try {
+                        writer.write(event);
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+
+                    for (int i = 1; i < nEmpty; i++) {
+                        try {
+                            writer.write(new BaseLCSimEvent(event.getRunNumber(), event.getEventNumber(), detectorName));
+                        } catch (IOException e) {
+                            throw new RuntimeException(e);
+                        }
+                    }
+                }
+            }
+            try {
+                reader.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        System.out.format("Read %d events, wrote %d of them\n", readEvents, writtenEvents);
+        if (tester != null) {
+            tester.endOfRun();
+        }
+
+        try {
+            writer.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static int countPairs(Set<Integer> ints) {
+        int pairs = 0;
+        while (!ints.isEmpty()) {
+            Integer next = ints.iterator().next();
+            ints.remove(next);
+            if (ints.remove(next ^ 1)) {
+                pairs++;
+            }
+        }
+        return pairs;
+    }
+
+    private static abstract class EventTester {
+
+        abstract boolean goodEvent(EventHeader event);
+
+        void endOfRun() {
+        }
+//        abstract boolean goodEvent(List<SimCalorimeterHit> ecalHits, List<SimTrackerHit> trackerHits);
+    }
+
+    private static class RTHEventTester extends EventTester {
+
+        int nEvents = 0;
+        int nEcal = 0;
+        int nRTH = 0;
+
+        public RTHEventTester() {
+            LCSimConditionsManagerImplementation.register();
+        }
+
+        @Override
+        public boolean goodEvent(EventHeader event) {
+            nEvents++;
+            List<RawCalorimeterHit> ecalHits = event.get(RawCalorimeterHit.class, "EcalReadoutHits");
+            List<RawTrackerHit> trackerHits = event.get(RawTrackerHit.class, "SVTRawTrackerHits");
+            nEcal += ecalHits.size();
+            nRTH += trackerHits.size();
+
+            Set<Integer> topLayers = new HashSet<Integer>();
+            Set<Integer> botLayers = new HashSet<Integer>();
+            for (RawTrackerHit hit : trackerHits) {
+                IDDecoder dec = hit.getIDDecoder();
+                dec.setID(hit.getCellID());
+                if (dec.getValue("module") % 2 == 0) {
+                    topLayers.add(dec.getValue("layer"));
+                } else {
+                    botLayers.add(dec.getValue("layer"));
+                }
+            }
+
+//            System.out.format("%d SimCalorimeterHits, %d SimTrackerHits, %d top layers, %d bottom layers\n", ecalHits.size(), trackerHits.size(), topLayers.size(), botLayers.size());
+            return (countPairs(topLayers) >= 4 && countPairs(botLayers) >= 4);
+        }
+
+        @Override
+        void endOfRun() {
+            System.out.format("%d events, %f RawCalorimeterHits and %f RawTrackerHits on average\n", nEvents, ((double) nEcal) / nEvents, ((double) nRTH) / nEvents);
+        }
+    }
+
+    private static class TrackerEventTester extends EventTester {
+
+        public TrackerEventTester() {
+            LCSimConditionsManagerImplementation.register();
+        }
+
+        @Override
+        public boolean goodEvent(EventHeader event) {
+            List<SimCalorimeterHit> ecalHits = event.getSimCalorimeterHits("EcalHits");
+            List<SimTrackerHit> trackerHits = event.getSimTrackerHits("TrackerHits");
+
+            Set<Integer> topLayers = new HashSet<Integer>();
+            Set<Integer> botLayers = new HashSet<Integer>();
+            for (SimTrackerHit hit : trackerHits) {
+                IDDecoder dec = hit.getIDDecoder();
+                dec.setID(hit.getCellID());
+                if (dec.getValue("module") % 2 == 0) {
+                    topLayers.add(dec.getValue("layer"));
+                } else {
+                    botLayers.add(dec.getValue("layer"));
+                }
+            }
+
+//            System.out.format("%d SimCalorimeterHits, %d SimTrackerHits, %d top layers, %d bottom layers\n", ecalHits.size(), trackerHits.size(), topLayers.size(), botLayers.size());
+            return (countPairs(topLayers) >= 4 && countPairs(botLayers) >= 4);
+        }
+    }
+
+    private static class EcalEventTester extends EventTester {
+
+        double eCut;
+
+        public EcalEventTester(double eCut) {
+            this.eCut = eCut;
+        }
+
+        @Override
+        public boolean goodEvent(EventHeader event) {
+            List<SimCalorimeterHit> ecalHits = event.getSimCalorimeterHits("EcalHits");
+            List<SimTrackerHit> trackerHits = event.getSimTrackerHits("TrackerHits");
+
+            double maxE = 0;
+            double totalE = 0;
+            for (SimCalorimeterHit hit : ecalHits) {
+                totalE += hit.getRawEnergy();
+                if (hit.getRawEnergy() > maxE) {
+                    maxE = hit.getRawEnergy();
+                }
+            }
+
+//        System.out.format("%d SimCalorimeterHits, %d SimTrackerHits, maxE %f, totalE %f\n", ecalHits.size(), trackerHits.size(), maxE, totalE);
+
+
+//        return (ecalHits.size() + trackerHits.size() != 0);
+//        return (totalE > 0.05 || !trackerHits.isEmpty());
+            return (totalE > eCut);
+        }
+    }
+}
\ No newline at end of file

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
HPSEcalAnalogPrintDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSEcalAnalogPrintDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSEcalAnalogPrintDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,87 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.meeg;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: HPSEcalAnalogPrintDriver.java,v 1.3 2012/04/27 22:13:52 meeg Exp $
+ */
+public class HPSEcalAnalogPrintDriver extends Driver {
+
+	Subdetector ecal;
+	IDDecoder dec;
+	String ecalName;
+	String ecalReadoutName = "EcalHits";
+	String ecalCollectionName = null;
+	String outputFileName;
+	PrintWriter outputStream = null;
+	int flags;
+
+	public HPSEcalAnalogPrintDriver() {
+	}
+
+	public void setEcalCollectionName(String ecalCollectionName) {
+		this.ecalCollectionName = ecalCollectionName;
+	}
+
+	public void setEcalName(String ecalName) {
+		this.ecalName = ecalName;
+	}
+
+	public void setOutputFileName(String outputFileName) {
+		this.outputFileName = outputFileName;
+	}
+
+	@Override
+	public void startOfData() {
+		if (ecalCollectionName == null) {
+			throw new RuntimeException("The parameter ecalCollectionName was not set!");
+		}
+
+		if (ecalName == null) {
+			throw new RuntimeException("The parameter ecalName was not set!");
+		}
+
+		if (outputFileName != null) {
+			try {
+				outputStream = new PrintWriter(outputFileName);
+			} catch (IOException ex) {
+				throw new RuntimeException("Invalid outputFilePath!");
+			}
+		} else {
+			outputStream = new PrintWriter(System.out, true);
+		}
+	}
+
+	public void detectorChanged(Detector detector) {
+		// Get the Subdetector.
+		ecal = (Subdetector) detector.getSubdetector(ecalName);
+		dec = ecal.getIDDecoder();
+	}
+
+	@Override
+	public void process(EventHeader event) {
+		// Get the list of ECal hits.
+		if (event.hasCollection(CalorimeterHit.class, ecalCollectionName)) {
+			//outputStream.println("Reading RawTrackerHits from event " + event.getEventNumber());
+			List<CalorimeterHit> hits = event.get(CalorimeterHit.class, ecalCollectionName);
+			for (CalorimeterHit hit : hits) {
+				dec.setID(hit.getCellID());
+				outputStream.printf("%d\t%d\t%f\t%f\n", dec.getValue("ix"), dec.getValue("iy"), hit.getTime(), hit.getRawEnergy());
+			}
+		}
+	}
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
HPSEcalDigitalPrintDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSEcalDigitalPrintDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSEcalDigitalPrintDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,90 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.meeg;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawCalorimeterHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: HPSEcalDigitalPrintDriver.java,v 1.5 2012/04/27 22:13:52 meeg Exp $
+ */
+public class HPSEcalDigitalPrintDriver extends Driver {
+
+	Subdetector ecal;
+	IDDecoder dec;
+	String ecalName = "Ecal";
+	String ecalReadoutName = "EcalHits";
+	String ecalCollectionName = "EcalRawHits";
+	String outputFileName;
+	PrintWriter outputStream = null;
+	int timeScale = 1;
+	int flags;
+
+	public HPSEcalDigitalPrintDriver() {
+	}
+
+	public void setTimeScale(int timeScale) {
+		this.timeScale = timeScale;
+	}
+
+	public void setEcalCollectionName(String ecalCollectionName) {
+		this.ecalCollectionName = ecalCollectionName;
+	}
+
+	public void setEcalName(String ecalName) {
+		this.ecalName = ecalName;
+	}
+
+	public void setOutputFileName(String outputFileName) {
+		this.outputFileName = outputFileName;
+	}
+
+	public void startOfData() {
+		if (ecalCollectionName == null) {
+			throw new RuntimeException("The parameter ecalCollectionName was not set!");
+		}
+
+		if (ecalName == null) {
+			throw new RuntimeException("The parameter ecalName was not set!");
+		}
+
+		if (outputFileName != null) {
+			try {
+				outputStream = new PrintWriter(outputFileName);
+			} catch (IOException ex) {
+				throw new RuntimeException("Invalid outputFilePath!");
+			}
+		} else {
+			outputStream = new PrintWriter(System.out, true);
+		}
+	}
+
+	public void detectorChanged(Detector detector) {
+		// Get the Subdetector.
+		ecal = (Subdetector) detector.getSubdetector(ecalName);
+		dec = ecal.getIDDecoder();
+	}
+
+	public void process(EventHeader event) {
+		// Get the list of ECal hits.
+		if (event.hasCollection(RawCalorimeterHit.class, ecalCollectionName)) {
+			List<RawCalorimeterHit> hits = event.get(RawCalorimeterHit.class, ecalCollectionName);
+			//outputStream.println("Reading RawCalorimeterHit from event " + event.getEventNumber());
+			for (RawCalorimeterHit hit : hits) {
+				dec.setID(hit.getCellID());
+				outputStream.printf("%d\t%d\t%d\t%d\n", dec.getValue("ix"), dec.getValue("iy"), hit.getTimeStamp() * timeScale, hit.getAmplitude());
+			}
+		}
+	}
+}
\ No newline at end of file

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
HPSEcalPrintDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSEcalPrintDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSEcalPrintDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,108 @@
+package org.lcsim.hps.users.meeg;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+import org.lcsim.hps.util.ClockSingleton;
+import org.lcsim.util.Driver;
+
+/**
+ * Performs readout of ECal hits.
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: HPSEcalPrintDriver.java,v 1.1 2012/04/29 02:10:05 meeg Exp $
+ */
+public class HPSEcalPrintDriver extends Driver {
+
+    HPSEcal3 ecal;
+    IDDecoder dec;
+    String ecalCollectionName;
+    String ecalName;
+    String ecalReadoutName = "EcalHits";
+    String outputFilePath;
+    PrintWriter outputStream = null;
+    int nx, ny;
+
+    public void setEcalReadoutName(String ecalReadoutName) {
+        this.ecalReadoutName = ecalReadoutName;
+    }
+
+    public void setEcalCollectionName(String ecalCollectionName) {
+        this.ecalCollectionName = ecalCollectionName;
+    }
+
+    public void setEcalName(String ecalName) {
+        this.ecalName = ecalName;
+    }
+
+    public void setOutputFilePath(String outputFilePath) {
+        this.outputFilePath = outputFilePath;
+    }
+
+    public void startOfData() {
+        if (ecalCollectionName == null)
+            throw new RuntimeException("The parameter ecalCollectionName was not set!");
+
+        if (ecalName == null)
+            throw new RuntimeException("The parameter ecalName was not set!");
+
+        try {
+            outputStream = new PrintWriter(outputFilePath);
+        } catch (IOException ex) {
+            throw new RuntimeException("Invalid outputFilePath!");
+        }
+    }
+
+    public void endOfData() {
+        if (outputStream != null)
+            outputStream.close();
+    }
+
+    public void detectorChanged(Detector detector) {
+        // Get the Subdetector.
+        ecal = (HPSEcal3) detector.getSubdetector(ecalName);
+        dec = ecal.getIDDecoder();
+        nx = (int) ecal.nx();
+        ny = (int) ecal.ny();
+    }
+
+    public void process(EventHeader event) {
+        //System.out.println(this.getClass().getCanonicalName() + " - process");
+        // Get the list of ECal hits.
+        List<CalorimeterHit> hits = event.get(CalorimeterHit.class, ecalCollectionName);
+
+        if (hits == null)
+            throw new RuntimeException("Event is missing ECal hits collection!");
+
+        if (!hits.isEmpty()) {
+            double hitArray[][] = new double[nx][2 * ny];
+            for (CalorimeterHit hit : hits) {
+                dec.setID(hit.getCellID());
+                int ix = dec.getValue("ix");
+                int iy = dec.getValue("iy");
+                if (nx % 2 == 0) {
+                    hitArray[ix > 0 ? nx / 2 + ix - 1 : nx / 2 + ix][iy > 0 ? ny + iy - 1 : ny + iy] += hit.getRawEnergy();
+                } else {
+                    hitArray[ix > 0 ? nx / 2 + ix : nx / 2 + ix][iy > 0 ? ny + iy - 1 : ny + iy] += hit.getRawEnergy();
+                }
+            }
+
+            outputStream.printf("Event %d\n", ClockSingleton.getClock());
+            for (int x = 0; x < nx; x++) {
+                for (int y = 0; y < 2 * ny; y++) {
+                    if (hitArray[x][y] == 0)
+                        outputStream.printf("0\t");
+                    else
+                        outputStream.printf("%4.3f\t", hitArray[x][y]);
+                }
+                outputStream.println();
+            }
+        }
+    }
+}
\ No newline at end of file

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
HPSEcalRawTrackerHitPrintDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSEcalRawTrackerHitPrintDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSEcalRawTrackerHitPrintDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,88 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.meeg;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: HPSEcalRawTrackerHitPrintDriver.java,v 1.3 2012/04/27 22:13:52 meeg Exp $
+ */
+public class HPSEcalRawTrackerHitPrintDriver extends Driver {
+
+	Subdetector ecal;
+	IDDecoder dec;
+	String ecalName = "Ecal";
+	String ecalReadoutName = "EcalHits";
+	String ecalCollectionName = "EcalRawHits";
+	String outputFileName;
+	PrintWriter outputStream = null;
+	int flags;
+
+	public HPSEcalRawTrackerHitPrintDriver() {
+	}
+
+	public void setEcalCollectionName(String ecalCollectionName) {
+		this.ecalCollectionName = ecalCollectionName;
+	}
+
+	public void setEcalName(String ecalName) {
+		this.ecalName = ecalName;
+	}
+
+	public void setOutputFileName(String outputFileName) {
+		this.outputFileName = outputFileName;
+	}
+
+	public void startOfData() {
+		if (ecalCollectionName == null) {
+			throw new RuntimeException("The parameter ecalCollectionName was not set!");
+		}
+
+		if (ecalName == null) {
+			throw new RuntimeException("The parameter ecalName was not set!");
+		}
+
+		if (outputFileName != null) {
+			try {
+				outputStream = new PrintWriter(outputFileName);
+			} catch (IOException ex) {
+				throw new RuntimeException("Invalid outputFilePath!");
+			}
+		} else {
+			outputStream = new PrintWriter(System.out, true);
+		}
+	}
+
+	public void detectorChanged(Detector detector) {
+		// Get the Subdetector.
+		ecal = (Subdetector) detector.getSubdetector(ecalName);
+		dec = ecal.getIDDecoder();
+	}
+
+	public void process(EventHeader event) {
+		// Get the list of ECal hits.
+		if (event.hasCollection(RawTrackerHit.class, ecalCollectionName)) {
+			//outputStream.println("Reading RawTrackerHits from event " + event.getEventNumber());
+			List<RawTrackerHit> hits = event.get(RawTrackerHit.class, ecalCollectionName);
+			for (RawTrackerHit hit : hits) {
+				dec.setID(hit.getCellID());
+				outputStream.printf("%d\t%d\t%d\t%d\n", dec.getValue("ix"), dec.getValue("iy"), hit.getTime(), hit.getADCValues().length);
+				for (int i = 0; i < hit.getADCValues().length; i++) {
+					outputStream.printf("%d\n", hit.getADCValues()[i]);
+				}
+			}
+		}
+	}
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
HPSGenericRawTrackerHitPrintDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSGenericRawTrackerHitPrintDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HPSGenericRawTrackerHitPrintDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,60 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.meeg;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: HPSGenericRawTrackerHitPrintDriver.java,v 1.1 2012/04/10
+ * 01:00:13 meeg Exp $
+ */
+public class HPSGenericRawTrackerHitPrintDriver extends Driver {
+
+	String outputFileName;
+	PrintWriter outputStream = null;
+
+	public HPSGenericRawTrackerHitPrintDriver() {
+	}
+
+	public void setOutputFileName(String outputFileName) {
+		this.outputFileName = outputFileName;
+	}
+
+	public void startOfData() {
+		if (outputFileName != null) {
+			try {
+				outputStream = new PrintWriter(outputFileName);
+			} catch (IOException ex) {
+				throw new RuntimeException("Invalid outputFilePath!");
+			}
+		} else {
+			outputStream = new PrintWriter(System.out, true);
+		}
+	}
+
+	public void process(EventHeader event) {
+		// Get the list of ECal hits.
+		if (event.hasCollection(RawTrackerHit.class)) {
+			//outputStream.println("Reading RawTrackerHits from event " + event.getEventNumber());
+			List<List<RawTrackerHit>> listOfLists = event.get(RawTrackerHit.class);
+			for (List<RawTrackerHit> hits : listOfLists) {
+				outputStream.printf("List with %d RawTrackerHits:\n", hits.size());
+				for (RawTrackerHit hit : hits) {
+					outputStream.printf("%d\t%d\n", hit.getCellID(), hit.getADCValues().length);
+					for (int i = 0; i < hit.getADCValues().length; i++) {
+						outputStream.printf("%d\n", hit.getADCValues()[i]);
+					}
+				}
+			}
+		}
+	}
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
HitTimePrintDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HitTimePrintDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/HitTimePrintDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,31 @@
+package org.lcsim.hps.users.meeg;
+
+import java.util.List;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.hps.readout.ecal.ReadoutTimestamp;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: HitTimePrintDriver.java,v 1.1 2013/03/20 00:09:43 meeg Exp $
+ */
+public class HitTimePrintDriver extends Driver {
+
+    @Override
+    protected void process(EventHeader event) {
+
+        List<TrackerHit> trackerHits = event.get(TrackerHit.class, "StripClusterer_SiTrackerHitStrip1D");
+        List<CalorimeterHit> ecalHits = event.get(CalorimeterHit.class, "EcalCalHits");
+
+        System.out.println("Event with ECal timestamp " + ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_ECAL, event) + ", SVT timestamp " + ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_TRACKER, event));
+        for (CalorimeterHit hit : ecalHits) {
+            System.out.println("Ecal: " + (hit.getTime() + ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_ECAL, event)));
+        }
+        for (TrackerHit hit : trackerHits) {
+            System.out.println("SVT: " + (hit.getTime() + ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_TRACKER, event)));
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
KinkAnalysisDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/KinkAnalysisDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/KinkAnalysisDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,311 @@
+package org.lcsim.hps.users.meeg;
+
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.Vertex;
+import org.lcsim.geometry.Detector;
+import org.lcsim.units.clhep.PhysicalConstants;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/*
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: KinkAnalysisDriver.java,v 1.3 2013/10/24 18:11:43 meeg Exp $
+ */
+public class KinkAnalysisDriver extends Driver {
+
+    private AIDA aida = AIDA.defaultInstance();
+    IHistogram2D dThetaLayer;
+    IHistogram2D dThetaLayerLargestT;
+    IHistogram2D dThetaLayerLargestE;
+    IHistogram2D dThetaLayerScatter;
+    IHistogram2D dThetaLayerNoScatter;
+    IHistogram1D dThetaLargestT;
+    IHistogram1D dThetaLargestE;
+    IHistogram1D layerLargestT;
+    IHistogram1D layerLargestE;
+    IHistogram2D frontDPDT;
+    IHistogram1D frontDP;
+    IHistogram1D frontDT;
+    IHistogram1D bsZ;
+    IHistogram2D twoTrackFrontDT;
+    IHistogram1D frontDTSum;
+    int neventsWithScatter = 0;
+    int hardScatterIsLargestScatter = 0;
+
+    @Override
+    protected void detectorChanged(Detector detector) {
+        dThetaLayer = aida.histogram2D("deflection in Y vs. layer", 12, 0.5, 12.5, 1000, -0.02, 0.02);
+        dThetaLayerScatter = aida.histogram2D("deflection in Y vs. layer, with hard scatter", 12, 0.5, 12.5, 1000, -0.02, 0.02);
+        dThetaLayerNoScatter = aida.histogram2D("deflection in Y vs. layer, no hard scatter", 12, 0.5, 12.5, 1000, -0.02, 0.02);
+        dThetaLayerLargestT = aida.histogram2D("deflection in Y vs. layer, largest scatter in track", 12, 0.5, 12.5, 1000, -0.02, 0.02);
+        dThetaLayerLargestE = aida.histogram2D("deflection in Y vs. layer, largest scatter in event", 12, 0.5, 12.5, 1000, -0.02, 0.02);
+        dThetaLargestT = aida.histogram1D("largest deflection in Y in track", 1000, -0.02, 0.02);
+        dThetaLargestE = aida.histogram1D("largest deflection in Y in event", 1000, -0.02, 0.02);
+        layerLargestT = aida.histogram1D("layer of largest deflection in Y in track", 12, 0.5, 12.5);
+        layerLargestE = aida.histogram1D("layer of largest deflection in Y in event", 12, 0.5, 12.5);
+        frontDPDT = aida.histogram2D("deflection in Y vs. energy loss, front layers", 200, 0.0, 3.0, 1000, -0.02, 0.02);
+        frontDP = aida.histogram1D("energy loss, front layers", 200, 0.0, 3.0);
+        frontDT = aida.histogram1D("deflection in Y, front layers", 1000, -0.02, 0.02);
+        bsZ = aida.histogram1D("vertex Z, BS constrained", 200, -10.0, 20.0);
+        twoTrackFrontDT = aida.histogram2D("deflection in Y, two tracks", 200, -0.02, 0.02, 200, -0.02, 0.02);
+        frontDTSum = aida.histogram1D("sum of deflections in Y, two tracks", 500, -0.02, 0.02);
+    }
+
+    @Override
+    public void process(EventHeader event) {
+
+//        for (List<ReconstructedParticle> list : event.get(ReconstructedParticle.class)) {
+//            for (ReconstructedParticle particle : list) {
+//                Vertex vertex = particle.getStartVertex();
+//                if (vertex != null) {
+//                    System.out.format("%s: z %f, chisq %f\n", event.getMetaData(list).getName(), vertex.getPosition().x(), vertex.getChi2());
+//                }
+//            }
+//        }
+
+        if (event.hasCollection(ReconstructedParticle.class, "AprimeBeamspotConstrained")) {
+            List<ReconstructedParticle> particles = event.get(ReconstructedParticle.class, "AprimeBeamspotConstrained");
+            int nvertices = 0;
+            Vertex theVertex = null;
+            for (ReconstructedParticle particle : particles) {
+                Vertex vertex = particle.getStartVertex();
+                if (vertex != null) {
+                    nvertices++;
+                    theVertex = vertex;
+//                    System.out.println(vertex.getPosition().x());
+                }
+            }
+            if (nvertices == 1) {
+                bsZ.fill(theVertex.getPosition().x());
+            }
+        }
+
+        List<MCParticle> MCParticles = event.getMCParticles();
+        List<Hep3Vector> hardScatters = new ArrayList<Hep3Vector>();
+
+        for (MCParticle particle : MCParticles) {
+            if (particle.getOrigin().magnitude() > 10.0) {
+                hardScatters.add(VecOp.neg(particle.getOrigin()));
+            }
+        }
+
+
+        List<SimTrackerHit> trackerHits = event.getSimTrackerHits("TrackerHits");
+
+//        Map<MCParticle, List<SimTrackerHit>> hitMap = new HashMap<MCParticle, List<SimTrackerHit>>();
+        Map<MCParticle, Map<Integer, SimTrackerHit>> trackMap = new HashMap<MCParticle, Map<Integer, SimTrackerHit>>();
+
+        for (SimTrackerHit hit : trackerHits) {
+//            List hitList = hitMap.get(hit.getMCParticle());
+//            if (hitList == null) {
+//                hitList = new ArrayList<SimTrackerHit>();
+//                hitMap.put(hit.getMCParticle(), hitList);
+//            }
+//            hitList.add(hit);
+
+            Map<Integer, SimTrackerHit> layerMap = trackMap.get(hit.getMCParticle());
+            if (layerMap == null) {
+                layerMap = new HashMap<Integer, SimTrackerHit>();
+                trackMap.put(hit.getMCParticle(), layerMap);
+            }
+            int layer = hit.getIdentifierFieldValue("layer");
+            if (layerMap.containsKey(layer)) {
+                boolean nearHardScatter = false;
+                for (Hep3Vector scatter : hardScatters) {
+                    if (VecOp.add(hit.getPositionVec(), scatter).magnitude() < 5.0) {
+                        nearHardScatter = true;
+                    }
+                }
+                if (!nearHardScatter) {
+                    hardScatters.add(VecOp.neg(hit.getPositionVec()));
+                }
+//                System.out.format("Double hit in layer %d, %s\n", layer, nearHardScatter ? "near hard scatter" : "not near hard scatter");
+                if (layerMap.get(layer).getPathLength() < hit.getPathLength()) {
+                    continue;
+                }
+            }
+            layerMap.put(layer, hit);
+        }
+
+        List<MCParticle> particlesWithoutTracks = new ArrayList<MCParticle>();
+        for (MCParticle particle : trackMap.keySet()) {
+            Set<Integer> layers = trackMap.get(particle).keySet();
+            int pairCount = 0;
+            for (Integer layer : layers) {
+                if (layer % 2 == 0 && layers.contains(layer - 1)) {
+                    pairCount++;
+                }
+            }
+            if (pairCount < 4) {
+                particlesWithoutTracks.add(particle);
+            }
+        }
+        for (MCParticle particle : particlesWithoutTracks) {
+            trackMap.remove(particle);
+        }
+
+        MCParticle electron = null, positron = null;
+        for (MCParticle particle : trackMap.keySet()) {
+            if (particle.getCharge() > 0) {
+                if (positron != null) {
+                    return;
+                }
+                positron = particle;
+            }
+            if (particle.getCharge() < 0) {
+                if (electron != null) {
+                    return;
+                }
+                electron = particle;
+            }
+        }
+        if (electron == null || positron == null) {
+            return;
+        }
+
+        double maxEventDT = 0.0;
+        int maxEventDTLayer = 0;
+        boolean maxEventDTHardScatter = false;
+
+        double deflection12_ele = deflection(trackMap.get(electron), 0, 4);
+        double deflection12_pos = deflection(trackMap.get(positron), 0, 4);
+        twoTrackFrontDT.fill(deflection12_ele, deflection12_pos);
+        frontDTSum.fill(deflection12_ele + deflection12_pos);
+
+        for (MCParticle particle : trackMap.keySet()) {
+            Map<Integer, SimTrackerHit> layerMap = trackMap.get(particle);
+            List<Integer> layers = new ArrayList<Integer>(layerMap.keySet());
+            Collections.sort(layers);
+            double maxDT = 0.0;
+            int maxDTLayer = 0;
+            boolean maxDTHardScatter = false;
+
+            double angle1 = angle(layers, layerMap, 0, 1);
+            Hep3Vector p1 = particle.getMomentum();
+
+            double angle2 = angle(layers, layerMap, 4, 5);
+            Hep3Vector p2 = new BasicHep3Vector(layerMap.get(layers.get(1)).getMomentum());
+
+            double deflection12 = (angle2 - angle1) * Math.signum(angle1);
+
+            frontDPDT.fill(p1.magnitude() - p2.magnitude(), deflection12);
+            frontDP.fill(p1.magnitude() - p2.magnitude());
+            frontDT.fill(deflection12);
+
+
+            for (int i = 0; i < layers.size() - 1; i++) {
+                SimTrackerHit hit = layerMap.get(layers.get(i));
+
+                boolean nearHardScatter = false;
+                for (Hep3Vector scatter : hardScatters) {
+                    if (VecOp.add(hit.getPositionVec(), scatter).magnitude() < 5.0) {
+                        nearHardScatter = true;
+                    }
+                }
+
+                SimTrackerHit lastHit = null;
+                if (i > 0) {
+                    lastHit = layerMap.get(layers.get(i - 1));
+//                    double theta = Constants.fieldConversion*0.5*PhysicalConstants.c_light;
+                }
+
+                SimTrackerHit nextHit = layerMap.get(layers.get(i + 1));
+
+                double inAngle = angle(lastHit, hit);
+                double outAngle = angle(hit, nextHit);
+
+                double deflectionY = (outAngle - inAngle) * Math.signum(inAngle);
+//                    System.out.format("in: %f, out: %f, delta: %f\n", inAngle,outAngle,deflectionY);
+                dThetaLayer.fill(layers.get(i), deflectionY);
+                if (nearHardScatter) {
+                    dThetaLayerScatter.fill(layers.get(i), deflectionY);
+                } else {
+                    dThetaLayerNoScatter.fill(layers.get(i), deflectionY);
+                }
+                if (Math.abs(deflectionY) > Math.abs(maxDT)) {
+                    maxDT = deflectionY;
+                    maxDTLayer = layers.get(i);
+                    maxDTHardScatter = nearHardScatter;
+                }
+            }
+            if (maxDT != 0.0) {
+                dThetaLargestT.fill(maxDT);
+                layerLargestT.fill(maxDTLayer);
+                dThetaLayerLargestT.fill(maxDTLayer, maxDT);
+            }
+
+            if (Math.abs(maxDT) > Math.abs(maxEventDT)) {
+                maxEventDT = maxDT;
+                maxEventDTLayer = maxDTLayer;
+                maxEventDTHardScatter = maxDTHardScatter;
+            }
+        }
+
+        if (maxEventDT != 0.0) {
+            dThetaLargestE.fill(maxEventDT);
+            layerLargestE.fill(maxEventDTLayer);
+            dThetaLayerLargestE.fill(maxEventDTLayer, maxEventDT);
+            neventsWithScatter++;
+            if (maxEventDTHardScatter) {
+                hardScatterIsLargestScatter++;
+            }
+        }
+    }
+
+    private double angle(SimTrackerHit hit1, SimTrackerHit hit2) {
+        double y1 = hit2.getMCParticle().getOriginY();
+//        double z1 = hit2.getMCParticle().getOriginZ();
+        double s1 = hit2.getMCParticle().getProductionTime() * PhysicalConstants.c_light;
+        if (hit1 != null) {
+            y1 = hit1.getPosition()[1];
+//            z1 = hit1.getPosition()[2];
+            s1 = hit1.getTime() * PhysicalConstants.c_light;
+        }
+
+        double y2 = hit2.getPosition()[1];
+//        double z2 = hit2.getPosition()[2];
+        double s2 = hit2.getTime() * PhysicalConstants.c_light;
+//                double outAngle = Math.atan2((nextY - y), (nextZ - z));
+
+        return Math.asin((y2 - y1) / (s2 - s1));
+    }
+
+    private double angle(List<Integer> layers, Map<Integer, SimTrackerHit> layerMap, int layer1, int layer2) {
+        SimTrackerHit hit1 = null;
+        if (layer1 > 0) {
+            hit1 = layerMap.get(layers.get(layer1 - 1));
+        }
+        SimTrackerHit hit2 = layerMap.get(layers.get(layer2 - 1));
+
+        return angle(hit1, hit2);
+    }
+
+    private double deflection(Map<Integer, SimTrackerHit> layerMap, int layer1, int layer2) {
+        List<Integer> layers = new ArrayList<Integer>(layerMap.keySet());
+        Collections.sort(layers);
+
+        double angle1 = angle(layers, layerMap, layer1, layer1 + 1);
+        double angle2 = angle(layers, layerMap, layer2, layer2 + 1);
+
+        return (angle2 - angle1) * Math.signum(angle1);
+    }
+
+    @Override
+    protected void endOfData() {
+        System.out.format("%d events, %d had hard scatter as largest scatter\n", neventsWithScatter, hardScatterIsLargestScatter);
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
LCIOTrackAnalysis.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/LCIOTrackAnalysis.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/LCIOTrackAnalysis.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,167 @@
+package org.lcsim.hps.users.meeg;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.Identifier;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.hps.recon.tracking.SvtUtils;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: LCIOTrackAnalysis.java,v 1.3 2013/10/24 18:11:43 meeg Exp $
+ */
+public class LCIOTrackAnalysis {
+
+    protected Track track;
+    protected MCParticle _mcp = null;
+    protected double _purity;
+    protected int _nhits;
+    protected int _nbadhits;
+    private int _nAxialhits;
+    private int _nZhits;
+    protected boolean _hasLayerOne;
+    private int[] _nStripHitsPerLayer = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    protected Map<Integer, Hep3Vector> _hitLocationPerLayer = new HashMap<Integer, Hep3Vector>();
+    protected int _nhitsNew;
+
+    public Track getTrack() {
+        return track;
+    }
+
+    public LCIOTrackAnalysis(Track trk, RelationalTable hittomc, RelationalTable hittostrip, RelationalTable hittorotated) {
+        track = trk;
+
+        //  Get the number of hits on the track
+        _nhits = trk.getTrackerHits().size();
+
+        //  Create a map containing the number of hits for each MCParticle associated with the track
+        Map<MCParticle, Integer> mcmap = new HashMap<MCParticle, Integer>();
+        _hasLayerOne = false;
+        //  Loop over the hits on the track (HelicalTrackHits)
+        for (TrackerHit rotatedHit : trk.getTrackerHits()) {
+            TrackerHit hit = (TrackerHit) hittorotated.from(rotatedHit);
+            //  get the set of MCParticles associated with this hit and update the hit count for each MCParticle
+            Set<MCParticle> mclist = hittomc.allFrom(hit);
+//            System.out.println("MCParticle count: " + mclist.size());
+            for (MCParticle mcp : mclist) {
+                if (mcp != null) {
+//                System.out.println(mcp.getOrigin());
+                    Integer mchits = 0;
+                    if (mcmap.containsKey(mcp)) {
+                        mchits = mcmap.get(mcp);
+                    }
+                    mchits++;
+                    mcmap.put(mcp, mchits);
+                }
+            }
+
+            Set<TrackerHit> hitlist = hittostrip.allFrom(hit);
+            for (TrackerHit cl : hitlist) {
+                int layer = -1;
+                int module = -1;
+                List<RawTrackerHit> rawHits = cl.getRawHits();
+//                System.out.println("RawHits: " + rawHits.size());
+                for (RawTrackerHit rawHit : rawHits) {
+//                    System.out.println(rawHit.getCellID());
+                    IIdentifier id = new Identifier(rawHit.getCellID());
+                    int newLayer = SvtUtils.getInstance().getHelper().getValue(id, "layer");
+                    if (layer != -1 && layer != newLayer) {
+                        System.out.format("TrackerHit has hits from multiple layers: %d and %d\n", layer, newLayer);
+                    }
+                    layer = newLayer;
+                    int newModule = SvtUtils.getInstance().getHelper().getValue(id, "module");
+                    if (module != -1 && module != newModule) {
+                        System.out.format("TrackerHit has hits from multiple modules: %d and %d\n", module, newModule);
+                    }
+                    module = newModule;
+//                    System.out.println(SvtUtils.getInstance().getHelper().getValue(id, "strip"));
+                }
+//                System.out.format("layer %d, module %d\n", layer, module);
+                if (layer == 1) {
+                    _hasLayerOne = true;
+                }
+
+
+                _nStripHitsPerLayer[layer - 1] = rawHits.size();
+                _hitLocationPerLayer.put(layer, new BasicHep3Vector(cl.getPosition()));
+                _nhitsNew++;
+
+                boolean isAxial = SvtUtils.getInstance().isAxial(SvtUtils.getInstance().getSensor(module, layer - 1));
+                if (isAxial) {
+                    _nAxialhits++;
+                } else {
+                    _nZhits++;
+
+                }
+            }
+        }
+
+        //  Find the MCParticle that has the most hits on the track
+
+        int nbest = 0;
+        MCParticle mcbest = null;
+        for (MCParticle mcp : mcmap.keySet()) {
+            int count = mcmap.get(mcp);
+            if (count > nbest) {
+                nbest = count;
+                mcbest = mcp;
+            }
+        }
+
+        if (nbest > 0) {
+            _mcp = mcbest;
+        }
+        _purity = (double) nbest / (double) _nhits;
+        _nbadhits = _nhits - nbest;
+    }
+
+    public MCParticle getMCParticle() {
+        return _mcp;
+    }
+
+    public int getNHits() {
+        return _nhits;
+    }
+
+    public int getNBadHits() {
+        return _nbadhits;
+    }
+
+    public double getPurity() {
+        return _purity;
+    }
+
+    public int getNHitsNew() {
+        return _nhitsNew;
+    }
+
+    public int getNAxialHits() {
+        return _nAxialhits;
+    }
+
+    public int getNZHits() {
+        return _nZhits;
+    }
+
+    public boolean hasLayerOne() {
+        return _hasLayerOne;
+    }
+
+    public Hep3Vector getClusterPosition(Integer layer) {
+        return _hitLocationPerLayer.get(layer);
+    }
+
+    public int getNumberOfStripHits(int layer) {
+        return _nStripHitsPerLayer[layer - 1];
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
MergeMCBunches.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/MergeMCBunches.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/MergeMCBunches.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,192 @@
+package org.lcsim.hps.users.meeg;
+
+import hep.physics.event.generator.MCEvent;
+import java.io.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.SimCalorimeterHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseLCSimEvent;
+import org.lcsim.lcio.LCIOReader;
+import org.lcsim.lcio.LCIOWriter;
+
+/**
+ * Selects LCIO events passing a cut; spaces out these events with blank events.
+ * Intended use is to clean up a photon-run MC file before running trigger and readout sim.
+ * Can also be used to chain multiple LCIO files together.
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: MergeMCBunches.java,v 1.1 2012/11/06 00:10:30 meeg Exp $
+ */
+public class MergeMCBunches {
+
+    /**
+     * Defines command line options for this program.
+     *
+     * @return The command line options.
+     */
+    private static Options createCommandLineOptions() {
+        Options options = new Options();
+        options.addOption(new Option("f", true, "Number of bunches merged for front SVT layers (default 4)"));
+        options.addOption(new Option("r", true, "Number of bunches merged for rear SVT layers (default 8)"));
+        options.addOption(new Option("s", true, "LCIO file containing signal events"));
+        options.addOption(new Option("n", true, "Number of events to read"));
+        return options;
+    }
+
+    public static void main(String[] args) {
+        // Set up command line parsing.
+        Options options = createCommandLineOptions();
+        CommandLineParser parser = new PosixParser();
+
+        // Parse command line arguments.
+        CommandLine cl = null;
+        try {
+            cl = parser.parse(options, args);
+        } catch (ParseException e) {
+            throw new RuntimeException("Problem parsing command line options.", e);
+        }
+
+        String[] parsedArgs = cl.getArgs();
+
+        if (parsedArgs.length < 2) {
+            System.out.println("FilterMCBunches <input files> <output file>");
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", options);
+            System.exit(1);
+        }
+
+        String outFileName = parsedArgs[parsedArgs.length - 1];
+
+        LCIOWriter writer = null;
+        try {
+            writer = new LCIOWriter(new File(outFileName));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        int nEvents = -1;
+        if (cl.hasOption("n")) {
+            nEvents = Integer.valueOf(cl.getOptionValue("n"));
+        }
+        int readEvents = 0;
+        int writtenEvents = 0;
+
+        int mergeN = 8;
+        if (cl.hasOption("r")) {
+            mergeN = Integer.valueOf(cl.getOptionValue("r"));
+        }
+        int mergeFront = 4;
+        if (cl.hasOption("f")) {
+            mergeFront = Integer.valueOf(cl.getOptionValue("f"));
+        }
+        int frontLayers = 6;
+
+        LCIOReader signalReader = null;
+        if (cl.hasOption("s")) {
+            try {
+                signalReader = new LCIOReader(new File(cl.getOptionValue("s")));
+                System.out.println("Opened input file " + cl.getOptionValue("s"));
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        String detectorName = null;
+
+        List<MCParticle> mcParticles = new ArrayList<MCParticle>();
+        List<SimTrackerHit> trackerHits = new ArrayList<SimTrackerHit>();
+        List<SimCalorimeterHit> ecalHits = new ArrayList<SimCalorimeterHit>();
+
+        fileLoop:
+        for (int fileNumber = 0; fileNumber < parsedArgs.length - 1; fileNumber++) {
+            LCIOReader reader = null;
+            String inFileName = parsedArgs[fileNumber];
+            try {
+                reader = new LCIOReader(new File(inFileName));
+                System.out.println("Opened input file " + inFileName);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+
+            eventLoop:
+            while (true) {
+                if (nEvents != -1 && readEvents == nEvents) {
+                    break fileLoop;
+                }
+                EventHeader event;
+                try {
+                    event = reader.read();
+                } catch (IOException e) {
+                    break eventLoop;
+                }
+                readEvents++;
+                mcParticles.addAll(event.get(MCParticle.class, MCEvent.MC_PARTICLES));
+                ecalHits.addAll(event.get(SimCalorimeterHit.class, "EcalHits"));
+//                trackerHits.addAll(event.get(SimTrackerHit.class, "TrackerHits"));
+                for (SimTrackerHit hit : event.get(SimTrackerHit.class, "TrackerHits")) {
+                    if (hit.getLayer() < frontLayers) {
+                        if (readEvents % mergeN < mergeFront) {
+                            trackerHits.add(hit);
+                        }
+                    } else {
+                        trackerHits.add(hit);
+                    }
+                }
+
+                if (detectorName == null) {
+                    detectorName = event.getDetectorName();
+                }
+
+                if (readEvents % mergeN == 0) {
+                    EventHeader newEvent = new BaseLCSimEvent(event.getRunNumber(), event.getEventNumber(), detectorName);
+                    if (cl.hasOption("s")) {
+                        EventHeader signalEvent = null;
+                        try {
+                            signalEvent = signalReader.read();
+                        } catch (IOException e) {
+                            break fileLoop;
+                        }
+                        mcParticles.addAll(signalEvent.get(MCParticle.class, MCEvent.MC_PARTICLES));
+                        ecalHits.addAll(signalEvent.get(SimCalorimeterHit.class, "EcalHits"));
+                        trackerHits.addAll(signalEvent.get(SimTrackerHit.class, "TrackerHits"));
+                    }
+                    newEvent.put(MCEvent.MC_PARTICLES, mcParticles);
+                    newEvent.put("EcalHits", ecalHits);
+                    newEvent.put("TrackerHits", trackerHits);
+                    try {
+                        writer.write(newEvent);
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                    writtenEvents++;
+                    mcParticles.clear();
+                    ecalHits.clear();
+                    trackerHits.clear();
+                }
+            }
+            try {
+                reader.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        System.out.format("Read %d events, wrote %d\n", readEvents, writtenEvents);
+        try {
+            writer.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
\ No newline at end of file

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
NoiselessReadoutChip.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/NoiselessReadoutChip.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/NoiselessReadoutChip.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,314 @@
+/*
+ * Class BasicReadoutChip
+ */
+package org.lcsim.hps.users.meeg;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.hps.recon.tracking.HPSSVTCalibrationConstants;
+import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip;
+import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip.ReadoutChannel;
+import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeData;
+import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeDataCollection;
+
+/**
+ * Basic readout chip class.  This class supports the minimal functions expected of
+ * a readout chip.  The charge on a strip/pixel is digitized as an integer number
+ * with a simple ADC with programmable resolution and dynamic range.  A chip with
+ * 1-bit ADC resolution (binary readout) is treated as a special case.
+ * 
+ * Noise is added to strips with charge and random noise hits are generated as well.
+ * Methods are provided to decode the charge and time (although the current
+ * implementation always returns a time of 0).
+ *
+ * This implementation has thresholds that are settable in units of RMS noise of
+ * each channel to enable simluation of highly optimized readout chains.  If
+ * absolute thresholds are desired, GenericReadoutChip should be used instead.
+ *
+ * @author Tim Nelson
+ */
+public class NoiselessReadoutChip implements ReadoutChip {
+
+    private BasicChannel _channel = new BasicChannel();
+    private ADC _adc = new ADC();
+    private boolean dropBadChannels = false;
+
+    /** Creates a new instance of BasicReadoutChip */
+    public NoiselessReadoutChip() {
+    }
+
+    public void setDropBadChannels(boolean dropBadChannels) {
+        this.dropBadChannels = dropBadChannels;
+    }
+
+    /**
+     * Set the noise intercept (i.e., the noise for 0 strip/pixel capacitance).
+     * Units are electrons of noise.
+     *
+     * @param noise_intercept noise for 0 capacitance
+     */
+    public void setNoiseIntercept(double noise_intercept) {
+        _channel.setNoiseIntercept(noise_intercept);
+    }
+
+    /**
+     * Set the noise slope (i.e., the proportionality between noise and capacitance).
+     * Units are electrons of noise per fF of capacitance.
+     *
+     * @param noise_slope noise slope per unit capacitance
+     */
+    public void setNoiseSlope(double noise_slope) {
+        _channel.setNoiseSlope(noise_slope);
+    }
+
+    /**
+     * Set the number of bits of ADC resolution
+     *
+     * @param nbits
+     */
+    public void setNbits(int nbits) {
+        getADC().setNbits(nbits);
+    }
+
+    /**
+     * Set the dynamic range of the ADC
+     *
+     * @param dynamic_range in fC
+     */
+    public void setDynamicRange(double dynamic_range) {
+        getADC().setDynamicRange(dynamic_range);
+    }
+
+    /**
+     * Return the BasicChannel associated with a given channel number.
+     * For the basic readout, there is a single instance of BasicChannel
+     * and thus the channel number is ignored.
+     *
+     * @param channel_number channel number
+     * @return associated BasicReadoutChannel
+     */
+    public BasicChannel getChannel(int channel_number) {
+        return _channel;
+    }
+
+    private ADC getADC() {
+        return _adc;
+    }
+
+    /**
+     * Given a collection of electrode data (i.e., charge on strips/pixels),
+     * return a map associating the channel and it's list of raw data.
+     *
+     * @param data  electrode data from the charge distribution
+     * @param electrodes  strip or pixel electrodes
+     * @return  map containing the ADC counts for this sensor
+     */
+    public SortedMap<Integer, List<Integer>> readout(SiElectrodeDataCollection data, SiSensorElectrodes electrodes) {
+
+        //  If there is no electrode data for this readout chip,  create an empty
+        //  electrode data collection
+        if (data == null) {
+            data = new SiElectrodeDataCollection();
+        }
+
+        //  Add noise hits to the electrode data collection
+//        addNoise(data, electrodes);
+
+        //  return the digitized charge data as a map that associates a hit
+        //  channel with a list of raw data for the channel
+        return digitize(data, electrodes);
+    }
+
+    /**
+     * Decode the hit charge stored in the RawTrackerHit
+     *
+     * @param hit raw hit
+     * @return hit charge in units of electrons
+     */
+    public double decodeCharge(RawTrackerHit hit) {
+        return getADC().decodeCharge(hit.getADCValues()[0]);
+    }
+
+    /**
+     * Decode the hit time.  Currently, the basic readout chip ignores the
+     * hit time and returns 0.
+     *
+     * @param hit raw hit data
+     * @return hit time
+     */
+    public int decodeTime(RawTrackerHit hit) {
+        return 0;
+    }
+
+    /**
+     * Digitizes the hit channels in a SiElectrodeDataCollection.
+     *
+     * The SiElectrodeDataCollection is a map that associates a given channel with
+     * it's SiElectrodeData.  The SiElectrodeData encapsulates the deposited charge
+     * on an strip/pixel and any associated SimTrackerHits.
+     *
+     * The output of this class is a map that associates a channel number with
+     * a list of raw data
+     *
+     * @param data electrode data collection
+     * @return map associating channels with a list of raw data
+     */
+    private SortedMap<Integer, List<Integer>> digitize(SiElectrodeDataCollection data,
+            SiSensorElectrodes electrodes) {
+        //  Create the map that associates a given sensor channel with it's list of raw data
+        SortedMap<Integer, List<Integer>> chip_data = new TreeMap<Integer, List<Integer>>();
+
+        //  Loop over the channels contained in the SiElectrodeDataCollection
+        for (Integer channel : data.keySet()) {
+            if (dropBadChannels && HPSSVTCalibrationConstants.isBadChannel((SiSensor) electrodes.getDetectorElement(), channel)) {
+//                System.out.format("%d bad\n", channel);
+                continue;
+            }
+//                System.out.format("%d OK\n", channel);
+            //  Fetch the electrode data for this channel
+            SiElectrodeData eldata = data.get(channel);
+
+            //  Get the charge in units of electrons
+            double charge = eldata.getCharge();
+
+            //  Calculate the ADC value for this channel and make sure it is positive
+            int adc = getADC().convert(charge);
+            if (adc <= 0) {
+                continue;
+            }
+
+            //  Create a list containing the adc value - for the basic readout
+            //  there is only 1 word of raw data
+            List<Integer> channel_data = new ArrayList<Integer>();
+            channel_data.add(adc);
+
+            //  Save the list of raw data in the chip_data map
+            chip_data.put(channel, channel_data);
+        }
+
+        return chip_data;
+    }
+
+    /**
+     * BasicChannel class representing a single channel's behavior
+     *
+     * Note that binary readout is a special case.  Anything positive value
+     * passed to a binary ADC for digitization is assumed to have crossed t
+     * hreshold and is assigned a value of 1.  Decoding binary readout results
+     * in either 0 or dynamic_range.
+     */
+    private class BasicChannel implements ReadoutChannel {
+
+        private double _noise_intercept = 0.;
+        private double _noise_slope = 0.;
+
+        /**
+         * Set the noise (in electrons) for 0 capacitance
+         *
+         * @param noise_intercept noise intercept
+         */
+        private void setNoiseIntercept(double noise_intercept) {
+            _noise_intercept = noise_intercept;
+        }
+
+        /**
+         * Set the capacitative noise slope (in electrons / pF)
+         *
+         * @param noise_slope noise slope
+         */
+        private void setNoiseSlope(double noise_slope) {
+            _noise_slope = noise_slope;
+        }
+
+        /**
+         * Return the noise in electrons for a given strip/pixel capacitance
+         *
+         * @param capacitance capacitance in pF
+         * @return noise in electrons
+         */
+        public double computeNoise(double capacitance) {
+            return _noise_intercept + _noise_slope * capacitance;
+        }
+    }
+
+    /**
+     * ADC class representing analog to digital converter.
+     */
+    private class ADC {
+
+        private int _nbits = 8;
+        private double _dynamic_range = 20.;
+
+        /**
+         * Set the ADC resolution in number of bits.
+         *
+         * @param nbits number of bits
+         */
+        private void setNbits(int nbits) {
+            _nbits = nbits;
+        }
+
+        /**
+         * Set the dynamic range in fC
+         *
+         * @param dynamic range
+         */
+        private void setDynamicRange(double dynamic_range) {
+            _dynamic_range = dynamic_range;
+        }
+
+        /**
+         * Compute the maximum ADC value
+         *
+         * @return largest possible ADC value according to # of bits
+         */
+        private int maxADCValue() {
+            return (int) Math.pow(2, _nbits) - 1;
+        }
+
+        /**
+         * Compute the conversion constant in ADC/fC
+         *
+         * @return conversion constant for ADC
+         */
+        private double conversionConstant() {
+            return maxADCValue() / _dynamic_range;
+        }
+
+        /**
+         * Perform analog to digital conversion
+         *
+         * @return digital ADC output between 0 and maxADCValue
+         */
+        public int convert(double charge) {
+            if (_nbits != 1) {
+                return Math.max(0, Math.min(maxADCValue(), (int) Math.floor(charge * 1.602e-4 * conversionConstant())));
+            } else {
+                if (charge <= 0.0) {
+                    return 0;
+                } else {
+                    return 1;
+                }
+            }
+        }
+
+        /**
+         * Decode charge from ADC value
+         *
+         * @return charge specified by a given ADC value
+         */
+        public double decodeCharge(int adc_value) {
+            if (_nbits != 1) {
+                return (adc_value + 0.5) / (1.602e-4 * conversionConstant());
+            } else {
+                return adc_value * _dynamic_range;
+            }
+
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/meeg
SimpleTrackerDigiDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/SimpleTrackerDigiDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/meeg/SimpleTrackerDigiDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,71 @@
+package org.lcsim.hps.users.meeg;
+
+import org.lcsim.hps.recon.tracking.TrackerDigiDriver;
+import org.lcsim.recon.tracking.digitization.sisim.CDFSiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.NearestNeighborRMS;
+import org.lcsim.recon.tracking.digitization.sisim.RawTrackerHitMaker;
+import org.lcsim.recon.tracking.digitization.sisim.StripHitMaker;
+
+/**
+ * This Driver runs the tracker digitization to create raw hits and strip hits
+ * from simulated data. The output can be used by a track reconstruction
+ * algorithm like Seed Tracker.
+ * 
+ * Copied from org.lcsim.hps.recon.tracking.TrackerDigiDriver, with the difference that this driver does not make noise hits or add noise to hits, and drops bad channels.
+ * 
+ * @author [log in to unmask]
+ * @version $Id: SimpleTrackerDigiDriver.java,v 1.3 2012/11/20 19:59:35 meeg Exp $
+ */
+public class SimpleTrackerDigiDriver extends TrackerDigiDriver {
+
+    private boolean dropBadChannels = false;
+
+    public void setDropBadChannels(boolean dropBadChannels) {
+        this.dropBadChannels = dropBadChannels;
+    }
+
+    /**
+     * Initializes this Driver's objects with the job parameters.
+     */
+    @Override
+    protected void initialize() {
+
+        // Create the sensor simulation.
+        CDFSiSensorSim stripSim = new CDFSiSensorSim();
+
+        // Create the readout chips and set the noise parameters.
+        NoiselessReadoutChip stripReadout = new NoiselessReadoutChip();
+        stripReadout.setDropBadChannels(dropBadChannels);
+        stripReadout.setNoiseIntercept(readoutNoiseIntercept);
+        stripReadout.setNoiseSlope(readoutNoiseSlope);
+        stripReadout.setNbits(readoutNBits);
+        stripReadout.setDynamicRange(readoutDynamicRange);
+
+        // Create the digitizer that produces the raw hits
+        stripDigitizer = new RawTrackerHitMaker(stripSim, stripReadout);
+
+        // Create Strip clustering algorithm.
+        NearestNeighborRMS stripClusteringAlgo = new NearestNeighborRMS();
+        stripClusteringAlgo.setSeedThreshold(clusterSeedThreshold);
+        stripClusteringAlgo.setNeighborThreshold(clusterNeighborThreshold);
+        stripClusteringAlgo.setClusterThreshold(clusterThreshold);
+
+        // Create the clusterers and set hit-making parameters.
+        stripClusterer = new StripHitMaker(stripSim, stripReadout, stripClusteringAlgo);
+        stripClusterer.setMaxClusterSize(clusterMaxSize);
+        stripClusterer.setCentralStripAveragingThreshold(clusterCentralStripAveragingThreshold);
+
+        // Set the cluster errors.
+        stripClusterer.SetOneClusterErr(oneClusterErr);
+        stripClusterer.SetTwoClusterErr(twoClusterErr);
+        stripClusterer.SetThreeClusterErr(threeClusterErr);
+        stripClusterer.SetFourClusterErr(fourClusterErr);
+        stripClusterer.SetFiveClusterErr(fiveClusterErr);
+
+        // Set the readout to process.
+        readouts.add(readoutCollectionName);
+
+        // Set the detector to process.
+        processPaths.add(subdetectorName);
+    }
+}
\ No newline at end of file

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
DetailedAnalysisDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/DetailedAnalysisDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/DetailedAnalysisDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,1598 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.mgraham;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import hep.aida.*;
+
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.vec.VecOp;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Set;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCRelation;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.Track;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.fit.helicaltrack.HelixParamCalculator;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.fit.helicaltrack.TrackDirection;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.recon.vertexing.BilliorTrack;
+import org.lcsim.hps.recon.vertexing.BilliorVertex;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.hps.recon.tracking.FindableTrack;
+import org.lcsim.hps.recon.tracking.TrackAnalysis;
+import org.lcsim.hps.recon.vertexing.BilliorVertexer;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author mgraham
+ */
+public class DetailedAnalysisDriver extends Driver {
+
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    private IProfile1D phifake;
+    private IProfile1D pfake;
+    private IProfile1D cthfake;
+    private IProfile1D peffFindable;
+    private IProfile1D thetaeffFindable;
+    private IProfile1D phieffFindable;
+    private IProfile1D ctheffFindable;
+    private IProfile1D d0effFindable;
+    private IProfile1D z0effFindable;
+    private IProfile1D peffElectrons;
+    private IProfile1D thetaeffElectrons;
+    private IProfile1D phieffElectrons;
+    private IProfile1D ctheffElectrons;
+    private IProfile1D d0effElectrons;
+    private IProfile1D z0effElectrons;
+    private IProfile1D peffAxial;
+    private IProfile1D thetaeffAxial;
+    private IProfile1D phieffAxial;
+    private IProfile1D ctheffAxial;
+    private IProfile1D d0effAxial;
+    private IProfile1D z0effAxial;
+    private IHistogram1D fakes;
+    private IHistogram1D nfakes;
+    private IProfile1D HitEffdEdX;
+    private IProfile1D ClHitEffdEdX;
+    private IProfile1D ClHitEffY;
+    private IProfile1D ClHitEffZ;
+    private IProfile1D STdEdXY;
+    private IProfile1D STdEdXZ;
+    private IProfile1D frdEdXY;
+    private IProfile1D VxEff;
+    private IProfile1D VyEff;
+    private IProfile1D VzEff;
+    private IProfile1D VxEffFindable;
+    private IProfile1D VyEffFindable;
+    private IProfile1D VzEffFindable;
+    public String outputPlots = "myplots.aida";
+    Map<String, IProfile1D> clsizeMap = new HashMap<String, IProfile1D>();
+    String[] detNames = {"Tracker"};
+    Integer[] nlayers = {12};
+    int trk_count = 0;
+    int nevt = 0;
+    int _nmcTrk = 0;
+    double _nrecTrk = 0;
+    double phiTrkCut = 0.3;
+    double cosThTrkCutMax = 0.2;
+    double cosThTrkCutMin = 0.05;
+    double pTrkCut = 0.5; //GeV
+    double d0TrkCut = 2.0; //mm
+    double z0TrkCut = 2.0; //mm
+    double etaTrkCut = 2.5;
+    int totelectrons = 0;
+    double foundelectrons = 0;
+    int findableelectrons = 0;
+    int findableTracks = 0;
+    double foundTracks = 0;
+    double beamP = 2.2;
+    public String outputTextName = "myevents.txt";
+    FileWriter fw;
+    PrintWriter pw;
+    double[] beamsize = {0.001, 0.02, 0.02};
+    int flipsign = 1;
+    public String _rawHitsName = "SVTRawTrackerHits";
+
+    public DetailedAnalysisDriver(int layers) {
+//        nlayers[0] = layers;
+        //  Define the efficiency histograms
+        IHistogramFactory hf = aida.histogramFactory();
+
+
+        peffFindable = hf.createProfile1D("Findable Efficiency vs p", "", 20, 0., beamP);
+        thetaeffFindable = hf.createProfile1D("Findable Efficiency vs theta", "", 20, 80, 100);
+        phieffFindable = hf.createProfile1D("Findable Efficiency vs phi", "", 25, -0.25, 0.25);
+        ctheffFindable = hf.createProfile1D("Findable Efficiency vs cos(theta)", "", 25, -0.25, 0.25);
+        d0effFindable = hf.createProfile1D("Findable Efficiency vs d0", "", 50, -2., 2.);
+        z0effFindable = hf.createProfile1D("Findable Efficiency vs z0", "", 50, -2., 2.);
+
+        peffElectrons = hf.createProfile1D("Electrons Efficiency vs p", "", 20, 0., beamP);
+        thetaeffElectrons = hf.createProfile1D("Electrons Efficiency vs theta", "", 20, 80, 100);
+        phieffElectrons = hf.createProfile1D("Electrons Efficiency vs phi", "", 25, -0.25, 0.25);
+        ctheffElectrons = hf.createProfile1D("Electrons Efficiency vs cos(theta)", "", 25, -0.25, 0.25);
+        d0effElectrons = hf.createProfile1D("Electrons Efficiency vs d0", "", 20, -1., 1.);
+        z0effElectrons = hf.createProfile1D("Electrons Efficiency vs z0", "", 20, -1., 1.);
+        /*
+         * peffAxial = hf.createProfile1D("Axial Efficiency vs p", "", 20, 0.,
+         * beamP); thetaeffAxial = hf.createProfile1D("Axial Efficiency vs
+         * theta", "", 20, 80, 100); phieffAxial = hf.createProfile1D("Axial
+         * Efficiency vs phi", "", 25, -0.25, 0.25); ctheffAxial =
+         * hf.createProfile1D("Axial Efficiency vs cos(theta)", "", 25, -0.25,
+         * 0.25); d0effAxial = hf.createProfile1D("Axial Efficiency vs d0", "",
+         * 20, -1., 1.); z0effAxial = hf.createProfile1D("Axial Efficiency vs
+         * z0", "", 20, -1., 1.);
+         */
+        cthfake = hf.createProfile1D("Fake rate vs  cos(theta)", "", 25, -0.25, 0.25);
+        phifake = hf.createProfile1D("Fake rate vs phi", "", 25, -0.25, 0.25);
+        pfake = hf.createProfile1D("Fake rate vs p", "", 20, 0, 6);
+
+        fakes = hf.createHistogram1D("Number of mis-matched hits (unnormalized)", "", 10, 0., 10.);
+        nfakes = hf.createHistogram1D("Number of mis-matched hits (normalized)", "", 10, 0., 10.);
+
+        HitEffdEdX = hf.createProfile1D("Strip Hit Efficiency vs dEdX", "", 50, 0, 0.3);
+        ClHitEffdEdX = hf.createProfile1D("Cluster Hit Efficiency vs dEdX", "", 50, 0, 0.3);
+        ClHitEffY = hf.createProfile1D("Cluster Hit Efficiency vs y", "", 50, -100, 100);
+        ClHitEffZ = hf.createProfile1D("Cluster Hit Efficiency vs z", "", 50, -100, 100);
+        STdEdXY = hf.createProfile1D("SimTHit dEdX vs y", "", 50, -100, 100);
+        frdEdXY = hf.createProfile1D("fractional dEdX vs y", "", 50, -100, 100);
+        STdEdXZ = hf.createProfile1D("SimTHit dEdX vs z", "", 50, -100, 100);
+
+        VxEff = hf.createProfile1D("Aprime Efficiency vs Vx", "", 25, 0., 50.);
+        VyEff = hf.createProfile1D("Aprime Efficiency vs Vy", "", 40, -0.2, 0.2);
+        VzEff = hf.createProfile1D("Aprime Efficiency vs Vz", "", 40, -0.2, 0.2);
+
+        VxEffFindable = hf.createProfile1D("Aprime Efficiency vs Vx: Findable", "", 25, 0., 50.);
+        VyEffFindable = hf.createProfile1D("Aprime Efficiency vs Vy: Findable", "", 40, -0.2, 0.2);
+        VzEffFindable = hf.createProfile1D("Aprime Efficiency vs Vz: Findable", "", 40, -0.2, 0.2);
+
+        int i, j;
+        for (i = 0; i < 1; i++) {
+            for (j = 0; j < nlayers[i]; j++) {
+                int laynum = j + 1;
+                String profname = detNames[i] + "_layer" + laynum + " cluster size vs y";
+                String key = detNames[i] + "_layer" + laynum;
+                clsizeMap.put(key, hf.createProfile1D(profname, 20, -15, 15));
+            }
+        }
+    }
+
+    @Override
+    public void detectorChanged(Detector detector) {
+        // Setup default stereo pairings, which should work for even number of
+        // modules.
+        nlayers[0] = detector.getSubdetector("Tracker").getLayering().getLayers().getNumberOfLayers();
+        System.out.println("Setting nlayers to " + nlayers[0]);
+    }
+
+    public void setRawHitsName(String rhname) {
+        _rawHitsName = rhname;
+    }
+
+    @Override
+    public void process(
+            EventHeader event) {
+        if (nevt == 0) {
+            try {
+//open things up
+                fw = new FileWriter(outputTextName);
+                pw = new PrintWriter(fw);
+            } catch (IOException ex) {
+                Logger.getLogger(DetailedAnalysisDriver.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+        //  Increment the event counter
+        nevt++;
+        String resDir = "residualsPlots/";
+        String resDirBar = "residualsBarrelPlots/";
+        String resDirEC = "residualsEndcapPlots/";
+        String simDir = "STHitPlots/";
+        String debugDir = "debugPlots/";
+        String occDir = "occupancyPlots/";
+        //  Get the magnetic field
+        Hep3Vector IP = new BasicHep3Vector(0., 0., 1.);
+        double bfield = event.getDetector().getFieldMap().getField(IP).y();
+//        System.out.println("bfield = " + bfield);
+        if (bfield < 0) {
+//            System.out.println("Flipping signs of reconstructed tracks!");
+            flipsign = -1;
+        }
+
+        List<RawTrackerHit> rawHits = event.get(RawTrackerHit.class, _rawHitsName);
+        List<SiTrackerHitStrip1D> stripHits = event.get(SiTrackerHitStrip1D.class, "StripClusterer_SiTrackerHitStrip1D");
+        //for (SiTrackerHitStrip1D cluster : stripHits) {
+        //    Hep3Vector measPos = cluster.getPositionAsVector();
+        //    double measdedx = cluster.getdEdx() * 1000.0;
+        //    Set<SimTrackerHit> SthFromRth = cluster.getSimHits();
+        //    if (SthFromRth.size() > 0) {
+        //        Hep3Vector mcPos = SthFromRth.iterator()
+        //then do somthing with mcPos & measPos...
+        //    }            
+        //}
+        System.out.println("RawHits Size = " + rawHits.size());
+
+        // dump SThit information      
+        String[] input_hit_collections = {"TrackerHits"};
+        for (String input : input_hit_collections) {
+            List<SimTrackerHit> sthits = event.getSimTrackerHits(input);
+            int[] nhits = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+            for (SimTrackerHit st : sthits) {
+                String detector = st.getDetectorElement().getName();
+                int layer = st.getLayerNumber();
+                double[] hp = st.getPoint();
+                Hep3Vector hitPos = new BasicHep3Vector(hp[0], hp[1], hp[2]);
+                double r = Math.sqrt(hp[0] * hp[0] + hp[1] * hp[1]);
+                double theta = Math.atan2(r, hp[2]);
+                double eta = -Math.log(Math.tan(theta / 2));
+                double phi = Math.atan2(hp[1], hp[0]);
+                nhits[layer]++;
+                double hitwgt = 0;
+                double clhitwgt = 0;
+
+                for (RawTrackerHit rth : rawHits) {
+                    List<SimTrackerHit> SthFromRth = rth.getSimTrackerHits();
+                    if (SthFromRth != null && SthFromRth.contains(st)) {
+                        hitwgt = 1.0;
+                    }
+                }
+                for (SiTrackerHitStrip1D cluster : stripHits) {
+                    double measdedx = cluster.getdEdx() * 1000.0;
+
+                    List<RawTrackerHit> RthFromSith = cluster.getRawHits();
+
+                    for (RawTrackerHit rth : RthFromSith) {
+                        List<SimTrackerHit> SthFromRth = rth.getSimTrackerHits();
+                        if (SthFromRth != null && SthFromRth.contains(st)) {
+                            clhitwgt = 1.0;
+                            double totdedx = 0;
+                            for (SimTrackerHit sthtemp : SthFromRth) {
+                                totdedx = totdedx + sthtemp.getdEdx() * 1000.0;
+                            }
+                            aida.histogram1D(simDir + "delta dEdX", 50, -0.2, 0.2).fill(measdedx - totdedx);
+                            aida.histogram1D(simDir + "fractional dEdX", 50, -1, 1.).fill((measdedx - totdedx) / totdedx);
+                            aida.cloud1D(simDir + "fractional dEdX Cloud").fill((measdedx - totdedx) / totdedx);
+                            //          if (Math.abs((measdedx - dedx) / dedx) < 1)
+                            frdEdXY.fill(hp[1], (measdedx - totdedx) / totdedx);
+                            //          if (dedx == 0)
+                            //              System.out.println("*****************         dedx==0    ********");
+                        }
+                    }
+                }
+                //HitEffdEdX.fill(dedx, hitwgt);
+                //ClHitEffdEdX.fill(dedx, clhitwgt);
+                ClHitEffY.fill(hp[1], clhitwgt);
+                ClHitEffZ.fill(hp[2], clhitwgt);
+                //STdEdXY.fill(hp[1], dedx);
+                //STdEdXZ.fill(hp[2], dedx);
+                //aida.histogram1D(simDir + " dedx", 50, 0, 0.3).fill(dedx);
+//                if (hitwgt == 0) {
+//                    System.out.println("TrackAnalysis:  found an inefficiency hit:  " + dedx);
+//                }
+
+                //aida.cloud1D(simDir + input + " layer " + layer + " STHit p").fill(mom);
+                aida.cloud1D(simDir + input + " layer " + layer + " STHit y").fill(hp[1]);
+                aida.cloud1D(simDir + input + " layer " + layer + " STHit z").fill(hp[2]);
+                aida.cloud2D(simDir + input + " layer " + layer + " STHit y vs z").fill(hp[2], hp[1]);
+                aida.histogram2D(simDir + input + " layer " + layer + " STHit y vs z occupancy", 100, -15, 15, 500, -15, 15).fill(hp[2], hp[1]);
+
+            }
+            int i = 0;
+            while (i < nlayers[0]) {
+                if (nhits[i] > 0) {
+                    aida.cloud1D(simDir + input + "layer " + i + " number of ST hits").fill(nhits[i]);
+                }
+                i++;
+            }
+        }
+
+
+//        List<HelicalTrackHit> hthits = event.get(HelicalTrackHit.class, "MatchedHTHits");
+        List<HelicalTrackHit> NonRotatedHits = event.get(HelicalTrackHit.class, "HelicalTrackHits");
+        List<HelicalTrackHit> toththits = event.get(HelicalTrackHit.class, "RotatedHelicalTrackHits");
+        //    List<HelicalTrackHit> axialhits = event.get(HelicalTrackHit.class, "AxialTrackHits");
+
+//        int nAxialHitsTotal = axialhits.size();
+        int nL1Hits = 0;
+//        for (HelicalTrackHit hth : axialhits)
+//            if (hth.Layer() == 1)
+//                nL1Hits++;
+
+        Map<String, Integer> occupancyMap = new HashMap<String, Integer>();
+        for (RawTrackerHit rh : rawHits) {
+            IDetectorElement rhDetE = rh.getDetectorElement();
+
+            String rhDetName = rhDetE.getName();
+            int rhLayer = rh.getLayerNumber();
+
+            for (String myname : detNames) {
+                if (rhDetName.contains(myname)) {
+                    String detlayer = myname + "_" + rhLayer;
+                    Integer myint = occupancyMap.get(detlayer);
+                    if (myint == null) {
+                        myint = 1;
+                    }
+                    myint++;
+                    occupancyMap.put(detlayer, myint);
+                }
+            }
+        }
+        Set<String> mykeyset = (Set<String>) occupancyMap.keySet();
+        for (String keys : mykeyset) {
+            aida.cloud1D(occDir + keys + " # of hits").fill(occupancyMap.get(keys));
+        }
+
+        for (SiTrackerHitStrip1D stripCluster : stripHits) {
+            Hep3Vector strCluPos = stripCluster.getPositionAsVector();
+            stripCluster.getMeasuredCoordinate();
+            Hep3Vector measVec = stripCluster.getMeasuredCoordinate();
+            double umeas = VecOp.dot(strCluPos, measVec);
+
+            double yHit = strCluPos.y();
+            Set<MCParticle> mcparts = stripCluster.getMCParticles();
+            aida.cloud1D(occDir + "associated MC Particles").fill(mcparts.size());
+            List<RawTrackerHit> rthList = stripCluster.getRawHits();
+            int nhits = rthList.size();
+            String detlayer = "Foobar";
+            Hep3Vector sthPos = new BasicHep3Vector();
+            for (RawTrackerHit rth : rthList) {
+                List<SimTrackerHit> sth = rth.getSimTrackerHits();
+                if (sth != null && sth.size() > 0) {
+                    sthPos = sth.get(0).getPositionVec();
+                }
+                IDetectorElement rhDetE = rth.getDetectorElement();
+                String rhDetName = rhDetE.getName();
+                int rhLayer = rth.getLayerNumber();
+                for (String myname : detNames) {
+                    if (rhDetName.contains(myname)) {
+                        detlayer = myname + "_layer" + rhLayer;
+                    }
+                }
+            }
+            Hep3Vector resid = VecOp.sub(strCluPos, sthPos);
+            double magResid = resid.magnitude();
+            clsizeMap.get(detlayer).fill(yHit, nhits);
+            aida.cloud1D(occDir + detlayer + "associated MC Particles").fill(mcparts.size());
+            aida.cloud1D(occDir + detlayer + " cluster size").fill(nhits);
+        }
+
+        //  Create a relational table that maps TrackerHits to MCParticles
+        RelationalTable hittomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        // List<LCRelation> mcrelations = event.get(LCRelation.class, "HelicalTrackMCRelations");
+        List<LCRelation> mcrelations = event.get(LCRelation.class, "RotatedHelicalTrackMCRelations");
+
+        for (LCRelation relation : mcrelations) {
+            if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+                hittomc.add(relation.getFrom(), relation.getTo());
+            }
+        }
+
+//        RelationalTable hittomcAxial = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+////        List<LCRelation> mcrelations = event.get(LCRelation.class, "HelicalTrackMCRelations");
+//        List<LCRelation> mcrelationsAxial = event.get(LCRelation.class, "AxialTrackMCRelations");
+//        for (LCRelation relation : mcrelationsAxial)
+//            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
+//                hittomcAxial.add(relation.getFrom(), relation.getTo());
+
+        //  Instantiate the class that determines if a track is "findable"
+        FindableTrack findable = new FindableTrack(event);
+
+        //  Create a map between tracks and the associated MCParticle
+        List<Track> tracklist = event.get(Track.class, "MatchedTracks");
+        //   List<Track> axialtracklist = event.get(Track.class, "AxialTracks");
+
+        aida.cloud1D("Matched Tracks per Event").fill(tracklist.size());
+        //       aida.cloud1D("Axial Tracks per Event").fill(axialtracklist.size());
+        aida.cloud1D("HelicalTrackHits per Event").fill(toththits.size());
+        RelationalTable trktomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        RelationalTable trktomcAxial = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        int _nchRec = 0;
+        int _neleRec = 0;
+        int _nposRec = 0;
+        int _neleTru = 0;
+        int _nposTru = 0;
+        int _neleFake = 0;
+        int _nposFake = 0;
+
+        RelationalTable mcHittomcP = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        //  Get the collections of SimTrackerHits
+        List<List<SimTrackerHit>> simcols = event.get(SimTrackerHit.class);
+
+        //  Loop over the SimTrackerHits and fill in the relational table
+        for (List<SimTrackerHit> simlist : simcols) {
+            for (SimTrackerHit simhit : simlist) {
+                if (simhit.getMCParticle() != null) {
+                    mcHittomcP.add(simhit, simhit.getMCParticle());
+                }
+            }
+        }
+
+        Map<Track, TrackAnalysis> tkanalMap = new HashMap<Track, TrackAnalysis>();
+        RelationalTable nearestHitToTrack = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        Map<Track, Double> l1Isolation = new HashMap<Track, Double>();
+        Map<Track, Double> l1DeltaZ = new HashMap<Track, Double>();
+        Map<Track, BilliorTrack> btMap = new HashMap<Track, BilliorTrack>();
+//        String atrackdir = "TrackInfoAxial/";
+//        //  Analyze the tracks in the event
+//        for (Track atrack : axialtracklist) {
+//            double apx = atrack.getPX();
+//            aida.cloud1D(atrackdir + "pX").fill(apx);
+//        }
+        String trackdir = "TrackInfo/";
+        //  Analyze the tracks in the event
+        for (Track track : tracklist) {
+            //  Calculate the track pT and cos(theta)
+            double d0 = track.getTrackParameter(HelicalTrackFit.dcaIndex);
+            double z0 = track.getTrackParameter(HelicalTrackFit.z0Index);
+            double phi0 = track.getTrackParameter(HelicalTrackFit.phi0Index);
+            double slope = track.getTrackParameter(HelicalTrackFit.slopeIndex);
+            double curve = track.getTrackParameter(HelicalTrackFit.curvatureIndex);
+            double d0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.dcaIndex, HelicalTrackFit.dcaIndex));
+            double z0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.z0Index, HelicalTrackFit.z0Index));
+            double phi0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.phi0Index, HelicalTrackFit.phi0Index));
+            double slopeErr = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.slopeIndex, HelicalTrackFit.slopeIndex));
+            double curveErr = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.curvatureIndex, HelicalTrackFit.curvatureIndex));
+            _nchRec++;
+            if (track.getCharge() * flipsign < 0) {
+                _neleRec++;
+            }
+            if (track.getCharge() * flipsign > 0) {
+                _nposRec++;
+            }
+
+            SeedTrack stEle = (SeedTrack) track;
+            SeedCandidate seedEle = stEle.getSeedCandidate();
+            HelicalTrackFit ht = seedEle.getHelix();
+            TrackAnalysis tkanal = new TrackAnalysis(track, hittomc);
+
+            tkanalMap.put(track, tkanal);
+            BilliorTrack bt = new BilliorTrack(ht);
+
+            btMap.put(track, bt);
+            double xoca = ht.x0();
+            double yoca = ht.y0();
+            double[] poca = {xoca, yoca, z0};
+            double mom[] = track.getMomentum();
+            double px = mom[0];
+            double py = mom[1];
+            double pz = mom[2];
+            double pperp = Math.sqrt(py * py + pz * pz);
+            double pt = Math.sqrt(px * px + py * py);
+            double p = Math.sqrt(pt * pt + pz * pz);
+            double phi = Math.atan2(py, px);
+            double cth = pz / Math.sqrt(pt * pt + pz * pz);
+            double sth = pt / Math.sqrt(pt * pt + pz * pz);
+            double th = Math.atan2(pt, pz);
+            double eta = -Math.log(Math.tan(th / 2));
+
+
+
+            double s = HelixUtils.PathLength(ht, (HelicalTrackHit) track.getTrackerHits().get(0));
+            double y1 = HelixUtils.PointOnHelix(ht, s).y();
+            double z1 = HelixUtils.PointOnHelix(ht, s).z();
+
+            int nhits = tkanal.getNHitsNew();
+            double purity = tkanal.getPurityNew();
+            int nbad = tkanal.getNBadHitsNew();
+            //  int nbadAxial = tkanal.getNBadAxialHits();
+            int nbadZ = tkanal.getNBadZHits();
+            // int nAxial = tkanal.getNAxialHits();
+            int nZ = tkanal.getNZHits();
+            List<Integer> badLayers = tkanal.getBadHitList();
+            Integer badLayerEle = encodeBadHitList(badLayers);
+            if (badLayers.size() > 0) {
+//                System.out.println(badLayers.toString());
+//                System.out.println("Bad Layer code:  " + badLayerEle);
+            }
+            aida.cloud1D(trackdir + "Mis-matched hits for all tracks").fill(nbad);
+            aida.cloud1D(trackdir + "purityNew for all tracks").fill(purity);
+            // aida.cloud1D(trackdir + "Bad Axial hits for all tracks").fill(nbadAxial);
+            aida.cloud1D(trackdir + "Bad Z hits for all tracks").fill(nbadZ);
+            //  aida.cloud1D(trackdir + "Number of Axial hits for all tracks").fill(nAxial);
+            aida.cloud1D(trackdir + "Number of Z hits for all tracks").fill(nZ);
+
+            for (Integer bhit : badLayers) {
+                aida.histogram1D(trackdir + "Layer of Bad Hit", nlayers[0], 1, nlayers[0] + 1).fill(bhit);
+            }
+
+            //  Generate a normalized histogram after 1000 events
+            trk_count++;
+            if (nevt <= 1000) {
+                fakes.fill(nbad);
+            }
+
+            //  Make plots for fake, non-fake, and all tracks
+            if (purity < 0.5) {
+                if (track.getCharge() * flipsign < 0) {
+                    _neleFake++;
+                }
+                if (track.getCharge() * flipsign > 0) {
+                    _nposFake++;
+                }
+                cthfake.fill(cth, 1.0);
+                phifake.fill(phi, 1.0);
+                pfake.fill(p, 1.0);
+
+                fillTrackInfo(trackdir, "fake tracks", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, d0, xoca, yoca, z0);
+
+            } else {
+                if (track.getCharge() * flipsign < 0) {
+                    _neleTru++;
+                }
+                if (track.getCharge() * flipsign > 0) {
+                    _nposTru++;
+                }
+                cthfake.fill(cth, 0.0);
+                phifake.fill(phi, 0.0);
+                pfake.fill(p, 0.0);
+
+                fillTrackInfo(trackdir, "non-fake tracks", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, d0, xoca, yoca, z0);
+
+
+
+            }
+            fillTrackInfo(trackdir, "all tracks", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, d0, xoca, yoca, z0);
+            if (nbadZ == 3) {
+                fillTrackInfo(trackdir, "3 Bad Z-hits", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, d0, xoca, yoca, z0);
+            }
+
+//            System.out.println("Track info :");
+//            System.out.println("\t charge = " + track.getCharge() * flipsign);
+//            System.out.println("\t d0 = " + d0);
+//            System.out.println("\t z0 = " + z0);
+//            System.out.println("\t phi0 = " + phi0);
+//            System.out.println("\t slope = " + slope);
+//            System.out.println("\t curve = " + curve);
+            //  Now analyze MC Particles on this track
+            MCParticle mcp = tkanal.getMCParticleNew();
+            if (mcp != null) {
+
+                //  Create a map between the tracks found and the assigned MC particle
+                trktomc.add(track, tkanal.getMCParticleNew());
+
+                //  Calculate the MC momentum and polar angle
+                Hep3Vector Pmc = mcp.getMomentum();
+                double pxmc = Pmc.x();
+                double pymc = Pmc.y();
+                double pzmc = Pmc.z();
+                double ptmc = Math.sqrt(pxmc * pxmc + pymc * pymc);
+                double pmc = Math.sqrt(ptmc * ptmc + pzmc * pzmc);
+                double pxtk = track.getPX();
+                double pytk = track.getPY();
+                double pztk = track.getPZ();
+                double pttk = Math.sqrt(pxtk * pxtk + pytk * pytk);
+                double ptk = Math.sqrt(pttk * pttk + pztk * pztk);
+
+                //  Calculate the helix parameters for this MC particle and pulls in pT, d0
+                HelixParamCalculator helix = new HelixParamCalculator(mcp, bfield);
+                double d0mc = helix.getDCA();
+                double z0mc = helix.getZ0();
+                double phi0mc = helix.getPhi0();
+                double slopemc = helix.getSlopeSZPlane();
+                double curvemc = 1 / helix.getRadius();
+                double pinvresid = (1 / ptk - 1 / pmc);
+                double presid = (ptk - pmc);
+                double z0newMC = z0mc;
+                double y0newMC = d0mc;
+                aida.histogram1D(trackdir + "d0 Pull", 200, -8, 8).fill((d0 - d0mc) / d0Err);
+                aida.histogram1D(trackdir + "z0 Pull", 200, -8, 8).fill((z0 - z0mc) / z0Err);
+                aida.histogram1D(trackdir + "phi0 Pull", 200, -8, 8).fill((phi0 - phi0mc) / phi0Err);
+                aida.histogram1D(trackdir + "slope Pull", 200, -8, 8).fill((slope - slopemc) / slopeErr);
+                aida.histogram1D(trackdir + "curvature Pull", 200, -8, 8).fill((curve - curvemc) / curveErr);
+//                System.out.println("MC Particle info :");
+//                System.out.println("\t PDGID = " + mcp.getPDGID());
+//                if (mcp.getParents().size() > 0)
+//                    System.out.println("\t mother = " + mcp.getParents().get(0).getPDGID());
+//                System.out.println("\t charge = " + mcp.getCharge());
+//                System.out.println("\t d0 = " + d0mc);
+//                System.out.println("\t z0 = " + z0mc);
+//                System.out.println("\t phi0 = " + phi0mc);
+//                System.out.println("\t slope = " + slopemc);
+//                System.out.println("\t curve = " + curvemc);
+
+
+                BasicHep3Vector axial = new BasicHep3Vector();
+                axial.setV(0, 1, 0);
+                String hitdir = "HitsOnTrack/";
+                List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+                MCParticle bestmcp = tkanal.getMCParticleNew();
+
+                String tkresid = "TrackResiduals/";
+
+                int ndaug = 0;
+                if (bestmcp != null) {
+                    ndaug = bestmcp.getDaughters().size();
+                }
+
+                double mcmom = 0;
+                double prevmom = 0;
+                double mytotchi2 = 0;
+
+                for (TrackerHit hit : hitsOnTrack) {
+
+                    int iplane = 0;
+                    HelicalTrackHit htc = (HelicalTrackHit) hit;
+                    List<MCParticle> mcpsHTH = htc.getMCParticles();
+                    int isbad = 0;
+                    if (mcpsHTH.isEmpty() || mcpsHTH.size() > 1 || !mcpsHTH.contains(bestmcp)) {
+                        isbad = 1;
+                    }
+                    double sHit = ht.PathMap().get(htc);
+                    Hep3Vector posonhelix = HelixUtils.PointOnHelix(ht, sHit);
+                    double yTr = posonhelix.y();
+                    double zTr = posonhelix.z();
+                    HelicalTrackCross cross = (HelicalTrackCross) htc;
+                    List<HelicalTrackStrip> clusterlist = cross.getStrips();
+                    TrackDirection trkdir = HelixUtils.CalculateTrackDirection(ht, sHit);
+                    cross.setTrackDirection(trkdir, ht.covariance());
+                    double y = cross.y();
+                    double z = cross.z();
+                    double yerr = Math.sqrt(cross.getCorrectedCovMatrix().e(1, 1));
+                    double zerr = Math.sqrt(cross.getCorrectedCovMatrix().e(2, 2));
+
+                    mytotchi2 += Math.pow((y - yTr) / yerr, 2);
+                    mytotchi2 += Math.pow((z - zTr) / zerr, 2);
+
+                    int htlayer = htc.Layer();
+                    if (htlayer == 1) {
+                        l1DeltaZ.put(track, z - zTr);
+                    }
+
+                    if (purity == 1 && track.getCharge() * flipsign > 0 && nhits == 10) {
+                        if (clusterlist.get(0).rawhits().size() == 1 && clusterlist.get(1).rawhits().size() == 1) {
+                            aida.cloud1D(hitdir + tkresid + "SingleStrip--Track delta y:  Layer " + htlayer).fill(y - yTr);
+                            aida.cloud1D(hitdir + tkresid + "SingleStrip--Track delta z:  Layer " + htlayer).fill(z - zTr);
+                        }
+                        aida.cloud1D(hitdir + tkresid + " Measured y:  Layer " + htlayer).fill(y);
+                        aida.cloud1D(hitdir + tkresid + " Track y:  Layer " + htlayer).fill(yTr);
+                        aida.cloud1D(hitdir + tkresid + " Measured z:  Layer " + htlayer).fill(z);
+                        aida.cloud1D(hitdir + tkresid + " Track z:  Layer " + htlayer).fill(zTr);
+                        aida.cloud1D(hitdir + tkresid + " Measured y ").fill(y);
+                        aida.cloud1D(hitdir + tkresid + " Track delta y:  Layer " + htlayer + "; ndaug=" + ndaug).fill(y - yTr);
+                        aida.cloud1D(hitdir + tkresid + " Track delta z:  Layer " + htlayer + "; ndaug=" + ndaug).fill(z - zTr);
+                        aida.cloud2D(hitdir + tkresid + " Track deltay vs delta z:  Layer " + htlayer).fill(z - zTr, y - yTr);
+                        if (htlayer == 1) {
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltay vs xoca").fill(poca[0], y - yTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltay vs yoca").fill(poca[1], y - yTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltay vs zoca").fill(poca[2], y - yTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltaz vs xoca").fill(poca[0], z - zTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltaz vs yoca").fill(poca[1], z - zTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltaz vs zoca").fill(poca[2], z - zTr);
+                        }
+                        aida.cloud2D(hitdir + tkresid + " Track vs measured y:  Layer " + htlayer).fill(y, yTr);
+                        aida.cloud2D(hitdir + tkresid + " Track vs measured z:  Layer " + htlayer).fill(z, zTr);
+                        aida.cloud2D(hitdir + tkresid + " Track deltay vs S ").fill(sHit, y - yTr);
+                        aida.cloud2D(hitdir + tkresid + " Track deltaz vs S ").fill(sHit, z - zTr);
+                        aida.histogram1D(hitdir + tkresid + " Track pull y:  Layer " + htlayer, 200, -8, 8).fill((y - yTr) / yerr);
+                        aida.histogram1D(hitdir + tkresid + " Track pull z:  Layer " + htlayer, 200, -8, 8).fill((z - zTr) / zerr);
+                        aida.histogram2D(hitdir + tkresid + " Track pull y vs p:  Layer " + htlayer, 200, -8, 8, 200, 0, 5).fill((y - yTr) / yerr, pmc);
+                        aida.histogram2D(hitdir + tkresid + " Track pull z vs p:  Layer " + htlayer, 200, -8, 8, 200, 0, 5).fill((z - zTr) / zerr, pmc);
+
+
+                    }
+                    for (HelicalTrackStrip cl : clusterlist) {
+                        int ilayer = 0;
+                        List<MCParticle> mcps = cl.MCParticles();
+
+                        Hep3Vector corigin = cl.origin();
+                        Hep3Vector u = cl.u();
+                        double umeas = cl.umeas();
+                        Hep3Vector uvec = VecOp.mult(umeas, u);
+                        Hep3Vector clvec = VecOp.add(corigin, uvec);
+                        int layer = cl.layer();
+                        HelicalTrackStrip nearest = getNearestHit(cl, toththits);
+                        if (layer == 1) {
+                            Double l1Dist = getNearestDistance(cl, toththits);
+                            if (l1Dist != null) {
+                                l1Isolation.put(track, l1Dist);
+                            }
+                        }
+                        if (nearest != null) {
+                            nearestHitToTrack.add(track, nearest);
+                        }
+
+                        int badCl = 0;
+                        if (mcps.isEmpty() || mcps.size() > 1 || !mcps.contains(bestmcp)) {
+                            badCl = 1;
+                        }
+                        if (badCl == 1) {
+                            if (mcps.size() > 0 && mcps.get(0) != null) {
+                                MCParticle tmpmc = mcps.get(0);
+                                aida.cloud1D(hitdir + layer + " Momentum of bad hit ").fill(tmpmc.getMomentum().magnitude());
+                                aida.cloud1D(hitdir + layer + " PDGID of bad hit ").fill(tmpmc.getPDGID());
+                                for (MCParticle mymc : tmpmc.getParents()) {
+                                    aida.cloud1D(hitdir + layer + " PDGID of bad hit mother ").fill(mymc.getPDGID());
+                                }
+                            }
+                        }
+                        String label = "False hit";
+                        if (badCl == 0) {
+                            label = "True Hit ";
+                        }
+
+                        SimTrackerHit mcbesthit;
+                        Set<SimTrackerHit> mchitlist = mcHittomcP.allTo(bestmcp);
+
+                        double ymc = 0, zmc = 0;
+                        for (SimTrackerHit sthbest : mchitlist) {
+                            int slayer = sthbest.getLayer();
+                            if (layer == slayer) {
+                                mcbesthit = sthbest;
+                                ymc = mcbesthit.getPoint()[1];
+                                zmc = mcbesthit.getPoint()[2];
+                                mcmom = getMag(mcbesthit.getMomentum());
+                                if (prevmom > 0 && badCl == 0) {
+                                    aida.histogram1D(hitdir + layer + " MC energy difference ", 100, -0.005, 0.0).fill(mcmom - prevmom);
+                                    aida.histogram1D(hitdir + " MC energy difference ", 100, -0.005, 0.0).fill(mcmom - prevmom);
+                                }
+                                prevmom = mcmom;
+
+                            }
+                        }
+
+                        double axdotu = VecOp.dot(cl.u(), axial);
+                        boolean isAxial = false;
+                        if (axdotu > 0.5) {
+                            isAxial = true;
+                        }
+//                    aida.cloud2D(hitdir + layer + " y vs z " + label).fill(z, y);
+                        if (isAxial) {
+                            aida.cloud1D(hitdir + layer + " y " + label).fill(clvec.y());
+                            aida.cloud1D(hitdir + layer + " deltay " + label).fill(clvec.y() - ymc);
+                            aida.cloud2D(hitdir + layer + " y vs yMC " + label).fill(ymc, clvec.y());
+                        } else {
+                            aida.cloud1D(hitdir + layer + " z " + label).fill(clvec.z());
+                            aida.cloud1D(hitdir + layer + " deltaz " + label).fill(clvec.z() - zmc);
+                            aida.cloud2D(hitdir + layer + " z vs zMC " + label).fill(zmc, clvec.z());
+                        }
+                        Set<MCParticle> mclist = hittomc.allFrom(hit);
+                        aida.cloud1D(hitdir + layer + " Associated MC particles").fill(mclist.size());
+
+
+                    }
+                }
+                aida.histogram2D(hitdir + "trkChi2 vs my chi2", 100, 0, 100, 100, 0, 100).fill(track.getChi2(), mytotchi2);
+
+            }
+        }
+
+        //  Make the normalized fake plot after the specified number of events
+        if (nevt == 1000) {
+            double wgt = 1. / trk_count;
+            for (int i = 0; i < 10; i++) {
+                System.out.println(" Entries: " + fakes.binEntries(i) + " for mismatches: " + i);
+                for (int j = 0; j < fakes.binHeight(i); j++) {
+                    nfakes.fill(i, wgt);
+                }
+            }
+            System.out.println("Normalization: " + nfakes.sumAllBinHeights() + " after ntrk = " + trk_count);
+        }
+
+//analyze the axial only tracks
+//        for (Track track : axialtracklist) {
+//            TrackAnalysis tkanal = new TrackAnalysis(track, hittomcAxial);
+//            MCParticle mcp = tkanal.getMCParticle();
+//            if (mcp != null)
+//                //  Create a map between the tracks found and the assigned MC particle
+//                trktomcAxial.add(track, tkanal.getMCParticle());
+//
+//        }
+//        for (HelicalTrackHit hit : toththits) {
+        for (HelicalTrackHit hit : NonRotatedHits) {
+
+            int nAssHits = hit.getRawHits().size();
+            aida.cloud1D(debugDir + hit.Detector() + " nAssHits").fill(nAssHits);
+            Hep3Vector HTHPos = hit.getCorrectedPosition();
+            double rHit = Math.sqrt(HTHPos.x() * HTHPos.x() + HTHPos.y() * HTHPos.y());
+            double zHit = HTHPos.z();
+            double etaHit = -Math.log(Math.tan(Math.atan2(rHit, zHit) / 2));
+            double hitchisq = hit.chisq();
+
+            if (hit instanceof HelicalTrackCross) {
+                HelicalTrackCross cross = (HelicalTrackCross) hit;
+                List<HelicalTrackStrip> clusterlist = cross.getStrips();
+                double du_stereo = 0;
+                double du_axial = 0;
+                for (HelicalTrackStrip cluster : clusterlist) {
+
+                    int nstrips = cluster.rawhits().size();
+                    aida.cloud1D(debugDir + hit.Detector() + " nStrips-per-layer").fill(nstrips);
+                    Hep3Vector corigin = cluster.origin();
+                    Hep3Vector u = cluster.u();
+                    List<RawTrackerHit> rawhits = cluster.rawhits();
+                    double umc = -999999;
+                    double stenergy = -999999;
+                    String stripdir = "axial";
+                    double umeas = cluster.umeas();
+                    double charge = cluster.dEdx() * 1000.0;
+                    int layer = cluster.layer();
+                    for (RawTrackerHit rhit : rawhits) {
+
+                        String deName = rhit.getDetectorElement().getName();
+                        if (deName.contains("sensor1")) {
+                            stripdir = "stereo";
+                        }
+                        //                           System.out.println("Layer number  " + rhit.getLayerNumber() + "  " + deName);
+                        List<SimTrackerHit> sthits = rhit.getSimTrackerHits();
+                        if (sthits != null) {
+                            int nsthits = sthits.size();
+                            aida.cloud1D(debugDir + hit.Detector() + " associated ST hits").fill(nsthits);
+                            aida.cloud1D(debugDir + hit.Detector() + " layer" + stripdir + " associated ST hits").fill(nsthits);
+                            if (nsthits == 1) {
+                                double[] sthitD = sthits.get(0).getPoint();
+                                BasicHep3Vector sthit = new BasicHep3Vector(sthitD);
+                                stenergy = sthits.get(0).getdEdx();
+                                Hep3Vector vdiff = VecOp.sub(sthit, corigin);
+                                umc = VecOp.dot(vdiff, u);
+                            }
+                        }
+                    }
+
+
+                    //                        System.out.println("filling...");
+                    if (umc != -999999) {
+                        aida.histogram1D(debugDir + hit.Detector() + "dedx", 50, 0, 0.3).fill(charge);
+                        if (umc < 1 && umc > -1) {
+                            aida.cloud2D(debugDir + hit.Detector() + "cluster reco vs cluster mc").fill(umeas - umc, umc);
+                        }
+                        aida.cloud2D(debugDir + hit.Detector() + "cluster vs STHit dedx").fill(stenergy, charge);
+                        aida.cloud2D(debugDir + hit.Detector() + "cluster dedx vs delte(u)").fill(umeas - umc, charge);
+                        if (stripdir.contains("stereo")) {
+                            du_stereo = umeas - umc;
+                        }
+                        if (stripdir.contains("axial")) {
+                            du_axial = umeas - umc;
+                        }
+                        aida.histogram1D(debugDir + "layer=" + layer + " delta(u)", 50, -0.03, 0.03).fill(umeas - umc);
+                        aida.histogram1D(debugDir + hit.Detector() + " delta(u)", 50, -0.03, 0.03).fill(umeas - umc);
+                        if (nstrips == 1) {
+                            aida.histogram1D(debugDir + "layer=" + layer + " delta(u)--1 strip", 50, -0.03, 0.03).fill(umeas - umc);
+                            aida.histogram1D(debugDir + hit.Detector() + " delta(u)--1 strip", 50, -0.03, 0.03).fill(umeas - umc);
+                        }
+                        if (nstrips == 2) {
+                            aida.histogram1D(debugDir + "layer=" + layer + " delta(u)--2 strip", 50, -0.03, 0.03).fill(umeas - umc);
+                            aida.histogram1D(debugDir + hit.Detector() + " delta(u)--2 strip", 50, -0.03, 0.03).fill(umeas - umc);
+                        }
+                        if (nstrips == 3) {
+                            aida.histogram1D(debugDir + "layer=" + layer + " delta(u)--3 strip", 50, -0.03, 0.03).fill(umeas - umc);
+                            aida.histogram1D(debugDir + hit.Detector() + " delta(u)--3 strip", 50, -0.03, 0.03).fill(umeas - umc);
+                        }
+                    }
+
+                }
+                aida.cloud2D(debugDir + hit.Detector() + " delta(u) stereo v axial").fill(du_stereo, du_axial);
+            }
+        }
+
+        //analyze the event
+        int ApCand = 0;
+        String apdir = "Aprime/";
+        Track eleID = null;
+        Track posID = null;
+        MCParticle eleMC = null;
+        MCParticle posMC = null;
+        for (Track track : tracklist) {
+
+            TrackAnalysis tkanal = tkanalMap.get(track);
+            //  Calculate purity and make appropriate plots
+            MCParticle mcp = tkanal.getMCParticleNew();
+            if (mcp == null) {
+                continue;
+            }
+            if (mcp.getParents().size() == 1 && mcp.getParents().get(0).getPDGID() == 622) {
+                int nhits = tkanal.getNHitsNew();
+                double px = track.getPX();
+                double py = track.getPY();
+                double pz = track.getPZ();
+                double pt = Math.sqrt(px * px + py * py);
+                double pperp = Math.sqrt(py * py + pz * pz);
+                double p = Math.sqrt(pt * pt + pz * pz);
+                double phi = Math.atan2(py, px);
+                double cth = pz / Math.sqrt(pt * pt + pz * pz);
+
+                SeedTrack stEle = (SeedTrack) track;
+                SeedCandidate seedEle = stEle.getSeedCandidate();
+                HelicalTrackFit ht = seedEle.getHelix();
+                double doca = ht.dca();
+                double[] poca = {ht.x0(), ht.y0(), ht.z0()};
+                if (mcp.getCharge() > 0) {
+                    posID = track;
+                    posMC = mcp;
+                    fillTrackInfo(apdir, "positron", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, doca, poca[0], poca[1], poca[2]);
+
+                } else {
+                    eleID = track;
+                    eleMC = mcp;
+                    fillTrackInfo(apdir, "electron", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, doca, poca[0], poca[1], poca[2]);
+                }
+            }
+
+        }
+        String vertex = "Vertexing/";
+        String selected = "Selection/";
+        String nhitsTotal = "NumberOfHits/";
+        List<BilliorTrack> btlist = new ArrayList<BilliorTrack>();
+        for (Track track1 : tracklist) {
+            Track ele = null;
+            Track pos = null;
+            int ch1 = track1.getCharge() * flipsign;
+            int index = tracklist.indexOf(track1);
+            List<Track> subtracklist = tracklist.subList(index, tracklist.size());
+            for (Track track2 : subtracklist) {
+                int ch2 = track2.getCharge() * flipsign;
+                if (track1 != track2 && ch1 == -ch2) {
+                    ele = track1;
+                    pos = track2;
+//                    System.out.println("Found two oppositely charged tracks!  Lets look at them");
+                    if (ch1 > 0) {
+                        ele = track2;
+                        pos = track1;
+                    }
+                    ApCand++;
+                    int nElectron = ele.getTrackerHits().size();
+                    int nPositron = pos.getTrackerHits().size();
+                    BilliorTrack btEle = btMap.get(ele);
+                    BilliorTrack btPos = btMap.get(pos);
+                    btlist.clear();
+                    btlist.add(btEle);
+                    btlist.add(btPos);
+
+
+
+
+                    BilliorVertexer bvertexerUC = new BilliorVertexer(bfield);
+                    BilliorVertex bvertexUC = bvertexerUC.fitVertex(btlist);
+//                    bvertexUC.fitVertex(btlist);
+                    Hep3Vector bvtxPosUC =  bvertexUC.getPosition();
+                    SymmetricMatrix bvtxCovUC = bvertexUC.getCovMatrix();
+                    double invMassUC = bvertexUC.getParameters().get("invMass");
+//                    System.out.println("UnConstrained");
+//                    System.out.println("Vertex Position:  " + bvtxPosUC.toString());
+//                    System.out.println("chisq :  " + bvertexUC.getChiSq());
+                    aida.histogram1D("BilliorVertex X  -- UnConstrained", 100, -10, 20).fill(bvtxPosUC.x());
+                    aida.histogram1D("BilliorVertex Y -- UnConstrained", 100, -0.4, 0.4).fill(bvtxPosUC.y());
+                    aida.histogram1D("BilliorVertex Z -- UnConstrained", 100, -0.4, 0.4).fill(bvtxPosUC.z());
+                    aida.histogram1D("BilliorVertex ChiSq -- UnConstrained", 100, 0, 50).fill(bvertexUC.getChi2());
+                    aida.histogram1D("BilliorVertex X Pull -- UnConstrained", 100, -4, 4).fill(bvtxPosUC.x() / Math.sqrt(bvtxCovUC.e(0, 0)));
+                    aida.histogram1D("BilliorVertex Y Pull-- UnConstrained", 100, -4, 4).fill(bvtxPosUC.y() / Math.sqrt(bvtxCovUC.e(1, 1)));
+                    aida.histogram1D("BilliorVertex Z Pull-- UnConstrained", 100, -4, 4).fill(bvtxPosUC.z() / Math.sqrt(bvtxCovUC.e(2, 2)));
+
+
+                    aida.cloud1D(apdir + "e+e- Invariant Mass").fill(invMassUC);
+                    if (eleMC != null && posMC != null && ele == eleID && pos == posID) {
+                        aida.cloud1D(apdir + "Matched A' Invariant Mass").fill(invMassUC);
[truncated at 1000 lines; 601 more skipped]

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
ElwinsTrackingRecon.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/ElwinsTrackingRecon.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/ElwinsTrackingRecon.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,1559 @@
+package org.lcsim.hps.users.mgraham;
+
+import Jama.*;
+import hep.aida.*;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.Hep3Vector;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.*;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.hps.event.BeamlineConstants;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.monitoring.deprecated.Resettable;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.hps.recon.tracking.*;
+import org.lcsim.hps.recon.vertexing.HelixConverter;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author elwinm
+ */
+public class ElwinsTrackingRecon extends Driver implements Resettable {
+
+    private AIDAFrame plotterFrame;
+    private AIDAFrame topFrame;
+    private AIDAFrame bottomFrame;
+    private AIDAFrame chargeFrame;
+    private AIDAFrame twotrackFrame;
+    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 trackCollectionName = "MatchedTracks";
+    private String trackerName = "Tracker";
+    String ecalSubdetectorName = "Ecal";
+    String ecalCollectionName = "EcalClusters";
+    private Detector detector = null;
+    IDDecoder dec;
+    private int eventCount;
+    private List<SiSensor> sensors;
+    private String outputPlots = null;
+    IPlotter plotter;
+    IPlotter plotter2;
+    IPlotter plotter22;
+    IPlotter plotter222;
+    IPlotter plotter3;
+    IPlotter plotter3_1;
+    IPlotter plotter3_2;
+    IPlotter plotter4;
+    IPlotter plotter5;
+    IPlotter plotter5_1;
+    IPlotter plotter55;
+    IPlotter plotter6;
+    IPlotter plotter7;
+    IPlotter plotter9000;
+    IPlotter plotter9001;
+    IPlotter plotter9002;
+    IPlotter plotter9003;
+    IPlotter plotter9004;
+    IPlotter plotter9005;
+    IPlotter plotter9006;
+    IPlotter plotter9007;
+    IPlotter plotter9008;
+    IPlotter plotter9009;
+    IPlotter plotter9010;
+    IPlotter plotter9011;
+    IPlotter plotter9012;
+    IPlotter plotter9013;
+    IPlotter plotter9014;
+    IPlotter plotter9015;
+    IPlotter plotter9016;
+    IPlotter plotter9017;
+    IPlotter twotrkextra;
+    IPlotter twotrkextra2;
+    IPlotter threetrack;
+    IPlotter top1;
+    IPlotter top2;
+    IPlotter top3;
+    IPlotter top4;
+    IPlotter bot1;
+    IPlotter bot2;
+    IPlotter bot3;
+    IPlotter charge;
+    IPlotter bot4;
+    double zEcal = 1500;
+    double zAtDownStrPairSpec = 914.0; //mm
+    double zAtColl = -1500;
+    IHistogram1D trkPx;
+    IHistogram1D nTracks;
+    HPSShaperFitAlgorithm _shaper = new DumbShaperFit();
+
+    protected void detectorChanged(Detector detector) {
+        this.detector = detector;
+        aida.tree().cd("/");
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("HPS Tracking Plots");
+
+        twotrackFrame = new AIDAFrame();
+        twotrackFrame.setTitle("Two Track Plots");
+
+        sensors = detector.getSubdetector(trackerName).getDetectorElement().findDescendants(SiSensor.class);
+
+        IAnalysisFactory fac = aida.analysisFactory();
+        plotter = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter.setTitle("Momentum");
+        IPlotterStyle style = plotter.style();
+        style.dataStyle().fillStyle().setColor("yellow");
+        style.dataStyle().errorBarStyle().setVisible(false);
+        plotter.createRegions(2, 2);
+        plotterFrame.addPlotter(plotter);
+
+        trkPx = aida.histogram1D("Track X Momentum", 25, -0.25, 0.25);
+        IHistogram1D trkPy = aida.histogram1D("Track Y Momentum", 25, -0.1, 0.1);
+        IHistogram1D trkPz = aida.histogram1D("Track Z Momentum", 25, 0, 3.5);
+        IHistogram1D trkChi2 = aida.histogram1D("Track Chi2", 25, 0, 25.0);
+
+        plotter.region(0).plot(trkPx);
+        plotter.region(1).plot(trkPy);
+        plotter.region(2).plot(trkPz);
+        plotter.region(3).plot(trkChi2);
+
+
+        plotter2 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter2.setTitle("Track extrapolation");
+        plotterFrame.addPlotter(plotter2);
+        IPlotterStyle style2 = plotter2.style();
+        style2.dataStyle().fillStyle().setColor("yellow");
+        style2.dataStyle().errorBarStyle().setVisible(false);
+        plotter2.createRegions(2, 4);
+        IHistogram1D xAtConverter = aida.histogram1D("X (mm) @ Z=-60cm", 50, -50, 50);
+        IHistogram1D yAtConverter = aida.histogram1D("Y (mm) @ Z=-60cm", 50, -20, 20);
+        IHistogram1D xAtColl = aida.histogram1D("X (mm) @ Z=-150cm", 50, -200, 200);
+        IHistogram1D yAtColl = aida.histogram1D("Y (mm) @ Z=-150cm", 50, -200, 200);
+        IHistogram1D xAtEcal = aida.histogram1D("X (mm) @ ECAL", 50, -500, 500);
+        IHistogram1D yAtEcal = aida.histogram1D("Y (mm) @ ECAL", 50, -100, 100);
+        IHistogram1D xAtConvert = aida.histogram1D("X (mm) @ Converter", 50, -50, 50);
+        IHistogram1D yAtConvert = aida.histogram1D("Y (mm) @ Converter", 50, -20, 20);
+
+        plotter2.region(0).plot(xAtConverter);
+        plotter2.region(4).plot(yAtConverter);
+        plotter2.region(1).plot(xAtColl);
+        plotter2.region(5).plot(yAtColl);
+        plotter2.region(2).plot(xAtEcal);
+        plotter2.region(6).plot(yAtEcal);
+        plotter2.region(3).plot(xAtConvert);
+        plotter2.region(7).plot(yAtConvert);
+
+        twotrkextra = fac.createPlotterFactory().create("Two Trk Extrapolation");
+        twotrkextra.setTitle("Stuff");
+        plotterFrame.addPlotter(twotrkextra);
+        IPlotterStyle styletwo = twotrkextra.style();
+        styletwo.dataStyle().fillStyle().setColor("blue");
+        styletwo.dataStyle().errorBarStyle().setVisible(false);
+        twotrkextra.createRegions(3, 2);
+        IHistogram1D x1AtTarget = aida.histogram1D("Trk1 X @ Target", 50, 0, 50);
+        IHistogram1D y1AtTarget = aida.histogram1D("Trk1 Y @ Target", 50, -5, 5);
+        IHistogram1D x2AtTarget = aida.histogram1D("Trk2 X @ Target", 50, 0, 50);
+        IHistogram1D y2AtTarget = aida.histogram1D("Trk2 Y @ Target", 50, -5, 5);
+        IHistogram1D distatt = aida.histogram1D("Distance btwn Trks @ Target", 40, 0, 40);
+        IHistogram1D zdiff = aida.histogram1D("Z Diff", 40, -.1, .1);
+
+        twotrkextra.region(0).plot(x1AtTarget);
+        twotrkextra.region(1).plot(y1AtTarget);
+        twotrkextra.region(2).plot(x2AtTarget);
+        twotrkextra.region(3).plot(y2AtTarget);
+        twotrkextra.region(4).plot(distatt);
+        twotrkextra.region(5).plot(zdiff);
+
+
+        plotter222 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter222.setTitle("Other");
+        plotterFrame.addPlotter(plotter222);
+        IPlotterStyle style222 = plotter222.style();
+        style222.dataStyle().fillStyle().setColor("yellow");
+        style222.dataStyle().errorBarStyle().setVisible(false);
+        plotter222.createRegions(2, 3);
+
+        IHistogram1D nHits = aida.histogram1D("Hits per Track", 2, 4, 6);
+        IHistogram1D amp = aida.histogram1D("Amp (HitOnTrack)", 50, 0, 5000);
+        IHistogram1D ampcl = aida.histogram1D("Amp (CluOnTrack)", 50, 0, 5000);
+        IHistogram1D amp2 = aida.histogram1D("Amp Pz>1000 (HitOnTrack)", 50, 0, 5000);
+        IHistogram1D ampcl2 = aida.histogram1D("Amp Pz>1000 (CluOnTrack)", 50, 0, 5000);
+        nTracks = aida.histogram1D("Tracks per Event", 3, 0, 3);
+
+        plotter222.region(0).plot(nHits);
+        plotter222.region(3).plot(nTracks);
+        plotter222.region(1).plot(amp);
+        plotter222.region(4).plot(amp2);
+        plotter222.region(2).plot(ampcl);
+        plotter222.region(5).plot(ampcl2);
+
+
+        plotterFrame.pack();
+        plotterFrame.setVisible(true);
+
+
+        twotrkextra2 = fac.createPlotterFactory().create("Two Trk Uncertainties");
+        twotrkextra2.setTitle("Uncertainties");
+        plotter9000 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9000.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks = plotter9000.style();
+        plotter9001 = fac.createPlotterFactory().create("Two Track Plots 2");
+        plotter9001.setTitle("Two Track Plots Test 2");
+        IPlotterStyle TwoTracks1 = plotter9001.style();
+        plotter9002 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9002.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks2 = plotter9002.style();
+        plotter9003 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9003.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks3 = plotter9003.style();
+        plotter9004 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9004.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks4 = plotter9004.style();
+        plotter9005 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9005.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks5 = plotter9005.style();
+        plotter9006 = fac.createPlotterFactory().create("Two Track Versus");
+        plotter9006.setTitle("Two Track Versus");
+        IPlotterStyle TwoTracks6 = plotter9006.style();
+        plotter9007 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9007.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks7 = plotter9007.style();
+        plotter9008 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9008.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks8 = plotter9000.style();
+        plotter9009 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9009.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks9 = plotter9000.style();
+        plotter9010 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9010.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks10 = plotter9010.style();
+        plotter9011 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9011.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks11 = plotter9011.style();
+        plotter9012 = fac.createPlotterFactory().create("Two Track Plotz");
+        plotter9012.setTitle("Two Track Plotz Test");
+        IPlotterStyle TwoTracks12 = plotter9012.style();
+        plotter9013 = fac.createPlotterFactory().create("Two Track Plotz");
+        plotter9013.setTitle("Two Track Plotz Test");
+        IPlotterStyle TwoTracks13 = plotter9013.style();
+        plotter9014 = fac.createPlotterFactory().create("Two Track Plotz");
+        plotter9014.setTitle("Two Track Plotz Test");
+        IPlotterStyle TwoTracks14 = plotter9014.style();
+        plotter9015 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9015.setTitle("Two Track Plots Test");
+        IPlotterStyle TwoTracks15 = plotter9015.style();
+        plotter9016 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9016.setTitle("Test");
+        IPlotterStyle TwoTracks16 = plotter9016.style();
+        plotter9017 = fac.createPlotterFactory().create("Two Track Plots");
+        plotter9017.setTitle("Residuals");
+        IPlotterStyle TwoTracks17 = plotter9017.style();
+        threetrack = fac.createPlotterFactory().create("Three Track Plots");
+        threetrack.setTitle("Invariant Mass");
+
+
+        TwoTracks.dataStyle().fillStyle().setColor("green");
+        TwoTracks.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks.setParameter("hist2DStyle", "colorMap");
+        TwoTracks.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks1.dataStyle().fillStyle().setColor("green");
+        TwoTracks1.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks1.setParameter("hist2DStyle", "colorMap");
+        TwoTracks1.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks2.dataStyle().fillStyle().setColor("green");
+        TwoTracks2.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks2.setParameter("hist2DStyle", "colorMap");
+        TwoTracks2.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks3.dataStyle().fillStyle().setColor("green");
+        TwoTracks3.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks3.setParameter("hist2DStyle", "colorMap");
+        TwoTracks3.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks4.dataStyle().fillStyle().setColor("green");
+        TwoTracks4.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks4.setParameter("hist2DStyle", "colorMap");
+        TwoTracks4.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks5.dataStyle().fillStyle().setColor("green");
+        TwoTracks5.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks5.setParameter("hist2DStyle", "colorMap");
+        TwoTracks5.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks6.dataStyle().fillStyle().setColor("green");
+        TwoTracks6.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks6.setParameter("hist2DStyle", "colorMap");
+        TwoTracks6.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks7.dataStyle().fillStyle().setColor("green");
+        TwoTracks7.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks7.setParameter("hist2DStyle", "colorMap");
+        TwoTracks7.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks8.dataStyle().fillStyle().setColor("green");
+        TwoTracks8.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks8.setParameter("hist2DStyle", "colorMap");
+        TwoTracks8.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks9.dataStyle().fillStyle().setColor("green");
+        TwoTracks9.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks9.setParameter("hist2DStyle", "colorMap");
+        TwoTracks9.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks10.dataStyle().fillStyle().setColor("green");
+        TwoTracks10.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks10.setParameter("hist2DStyle", "colorMap");
+        TwoTracks10.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks11.dataStyle().fillStyle().setColor("green");
+        TwoTracks11.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks11.setParameter("hist2DStyle", "colorMap");
+        TwoTracks11.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks12.dataStyle().fillStyle().setColor("green");
+        TwoTracks12.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks13.dataStyle().fillStyle().setColor("green");
+        TwoTracks13.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks14.dataStyle().fillStyle().setColor("green");
+        TwoTracks14.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks15.dataStyle().fillStyle().setColor("green");
+        TwoTracks15.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks15.setParameter("hist2DStyle", "colorMap");
+        TwoTracks15.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        TwoTracks16.dataStyle().fillStyle().setColor("green");
+        TwoTracks16.dataStyle().errorBarStyle().setVisible(false);
+        TwoTracks16.setParameter("hist2DStyle", "colorMap");
+        TwoTracks16.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        IPlotterStyle styletwotwo = twotrkextra2.style();
+        styletwotwo.dataStyle().fillStyle().setColor("blue");
+        styletwotwo.dataStyle().errorBarStyle().setVisible(false);
+
+        IPlotterStyle threesty = threetrack.style();
+        threesty.dataStyle().fillStyle().setColor("blue");
+        threesty.dataStyle().errorBarStyle().setVisible(false);
+
+
+
+        twotrkextra2.createRegions(3, 2);
+        plotter9000.createRegion();
+        plotter9001.createRegion();
+        plotter9002.createRegions(2, 1);
+        plotter9003.createRegion();
+        plotter9004.createRegion();
+        plotter9005.createRegion();
+        plotter9006.createRegions(1, 3);
+        plotter9007.createRegions(2, 3);
+        plotter9008.createRegions(2, 2);
+        plotter9009.createRegions(2, 2);
+        plotter9010.createRegions(2, 2);
+        plotter9011.createRegions(2, 2);
+        plotter9012.createRegions(2, 2);
+        //   plotter9013.createRegions(2, 2);
+        //    plotter9014.createRegions(2, 2);
+        plotter9015.createRegions(2, 2);
+        plotter9016.createRegions(2, 2);
+        plotter9017.createRegions(2, 2);
+        threetrack.createRegion();
+
+        twotrackFrame.addPlotter(plotter9000);
+        twotrackFrame.addPlotter(plotter9001);
+        twotrackFrame.addPlotter(plotter9002);
+        twotrackFrame.addPlotter(plotter9003);
+        twotrackFrame.addPlotter(plotter9004);
+        twotrackFrame.addPlotter(plotter9005);
+        twotrackFrame.addPlotter(plotter9006);
+        twotrackFrame.addPlotter(plotter9007);
+        twotrackFrame.addPlotter(plotter9008);
+        twotrackFrame.addPlotter(plotter9009);
+        twotrackFrame.addPlotter(plotter9010);
+        twotrackFrame.addPlotter(plotter9011);
+        twotrackFrame.addPlotter(plotter9012);
+        //   twotrackFrame.addPlotter(plotter9013);
+        //  twotrackFrame.addPlotter(plotter9014);
+        twotrackFrame.addPlotter(plotter9015);
+        twotrackFrame.addPlotter(plotter9016);
+        twotrackFrame.addPlotter(plotter9017);
+        twotrackFrame.addPlotter(twotrkextra2);
+        twotrackFrame.addPlotter(threetrack);
+
+        IHistogram1D trkbins = aida.histogram1D("Track Distributions", 5, -2, 3);
+        IHistogram2D twtrkptot = aida.histogram2D("Total P+ vs. P-", 60, 0, 4, 60, 0, 4);
+        IHistogram1D sumtrks = aida.histogram1D("Sum of Track's Momentums", 100, -1, 7);
+        IHistogram1D invarmass = aida.histogram1D("Invariant Mass", 50, 0, .2);
+        IHistogram1D perptrks = aida.histogram1D("Perpendicular Momentum", 100, 0, .1);
+        IHistogram2D pyppm = aida.histogram2D("Py+ vs. Py-", 60, -.1, .1, 60, -.1, .1);
+        IHistogram2D pzppm = aida.histogram2D("Pz+ vs. Pz-", 60, -.1, .1, 60, -.1, .1);
+        IHistogram1D px = aida.histogram1D("Two Track X Momentum", 40, 0, 4);
+        IHistogram1D py = aida.histogram1D("Two Track Y Momentum", 40, -.1, .1);
+        IHistogram1D pz = aida.histogram1D("Two Track Z Momentum", 40, -.1, .1);
+        IHistogram1D chi2 = aida.histogram1D("Tracks Chi2", 25, 0, 25.0);
+        IHistogram1D bbpx = aida.histogram1D("Big Bump Track Momenta (Px)", 40, 0, 4);
+        IHistogram1D bbpy = aida.histogram1D("Big Bump Track Momenta (Py)", 40, -.1, .1);
+        IHistogram1D bbpz = aida.histogram1D("Big Bump Track Momenta (Pz)", 40, -.1, .1);
+        IHistogram1D bbchi2 = aida.histogram1D("Big Bump Tracks Chi2", 25, 0, 25.0);
+        IHistogram1D spx = aida.histogram1D("Split Track Momenta (Px)", 40, 0, 4);
+        IHistogram1D spy = aida.histogram1D("Split Track Momenta (Py)", 40, -.1, .1);
+        IHistogram1D spz = aida.histogram1D("Split Track Momenta (Pz)", 40, -.1, .1);
+        IHistogram1D schi2 = aida.histogram1D("Split Tracks Chi2", 25, 0, 25.0);
+        IHistogram1D bbsumtrks = aida.histogram1D("Big Bump Sum of Track's Momentums", 50, -1, 7);
+        IHistogram2D bbpppm = aida.histogram2D("Big Bump P+ vs. P-", 50, 0, 4, 50, 0, 4);
+        IHistogram2D lbpppm = aida.histogram2D("Little Bump P+ vs. P-", 50, 0, 4, 50, 0, 4);
+        IHistogram1D lbsumtrks = aida.histogram1D("Little Bump Sum of Track's Momentums", 50, -1, 7);
+        IHistogram1D lbpx = aida.histogram1D("Little Bump Track Momenta (Px)", 40, 0, 4);
+        IHistogram1D lbpy = aida.histogram1D("Little Bump Track Momenta (Py)", 40, -.1, .1);
+        IHistogram1D lbpz = aida.histogram1D("Little Bump Track Momenta (Pz)", 40, -.1, .1);
+        IHistogram1D lbchi2 = aida.histogram1D("Little Bump Tracks Chi2", 25, 0, 25.0);
+        //     IHistogram1D q0spx = aida.histogram1D("Net Charge 0 Split Track Momenta (Px)", 40, 0, 4);
+        //     IHistogram1D q0spy = aida.histogram1D("Net Charge 0 Split Track Momenta (Py)", 40, -.1, .1);
+        //     IHistogram1D q0spz = aida.histogram1D("Net Charge 0 Split Track Momenta (Pz)", 40, -.1, .1);
+        //     IHistogram1D q0schi2 = aida.histogram1D("Net Charge 0 Split Tracks Chi2", 25, 0, 25.0);
+        IHistogram2D xyemt = aida.histogram2D("X v Y - e- Top", 50, -30, 50, 50, -35, 30);
+        IHistogram2D xzemt = aida.histogram2D("X v Z - e- Top", 50, -30, 50, 50, -800, -450);
+        IHistogram2D yzemt = aida.histogram2D("Y v Z - e- Top", 50, -35, 30, 50, -800, -450);
+        IHistogram1D qbins = aida.histogram1D("Charge Distributions", 5, -2, 3);
+        IHistogram1D lbtp = aida.histogram1D("Little Bump Track Parity", 7, 0, 7);
+        IHistogram1D bbtp = aida.histogram1D("Big Bump Track Parity", 7, 0, 7);
+        IHistogram1D xvert = aida.histogram1D("XVertex", 40, -30, 50);
+        IHistogram1D yvert = aida.histogram1D("YVertex", 40, -35, 30);
+        IHistogram1D zvert = aida.histogram1D("ZVertex", 40, -800, -450);
+        IHistogram1D dist = aida.histogram1D("Distance btwn Trks @ Solution", 40, 0, 20);
+        IHistogram1D xres = aida.histogram1D("X Res Trk1", 40, -0.25, 0.25);
+        IHistogram1D yres = aida.histogram1D("Y Res Trk1", 40, -0.25, 0.25);
+        IHistogram1D xres2 = aida.histogram1D("X Res Trk2", 40, -0.25, 0.25);
+        IHistogram1D yres2 = aida.histogram1D("Y Res Trk2", 40, -0.25, 0.25);
+        IHistogram1D unx1 = aida.histogram1D("Uncert X Trk 1", 50, 0, 10);
+        IHistogram1D uny1 = aida.histogram1D("Uncert Y Trk 1", 50, 0, 10);
+        IHistogram1D unz1 = aida.histogram1D("Uncert Z Trk 1", 50, 0, 40);
+        IHistogram1D unx2 = aida.histogram1D("Uncert X Trk 2", 50, 0, 10);
+        IHistogram1D uny2 = aida.histogram1D("Uncert Y Trk 2", 50, 0, 10);
+        IHistogram1D unz2 = aida.histogram1D("Uncert Z Trk 2", 50, 0, 40);
+        IHistogram2D xy = aida.histogram2D("X v Y", 50, -30, 50, 50, -35, 30);
+        IHistogram2D xz = aida.histogram2D("X v Z", 50, -30, 50, 50, -800, -450);
+        IHistogram2D yz = aida.histogram2D("Y v Z", 50, -35, 30, 50, -800, -450);
+        IHistogram2D xyept = aida.histogram2D("X v Y - e+ Top", 50, -30, 50, 50, -35, 30);
+        IHistogram2D xzept = aida.histogram2D("X v Z - e+ Top", 50, -30, 50, 50, -800, -450);
+        IHistogram2D yzept = aida.histogram2D("Y v Z - e+ Top", 50, -35, 30, 50, -800, -450);
+        IHistogram1D three = aida.histogram1D("Three Track Invariant Mass", 50, 0, .4);
+
+        twotrackFrame.pack();
+        twotrackFrame.setVisible(true);
+
+        plotter9000.region(0).plot(trkbins);
+        plotter9001.region(0).plot(twtrkptot);
+        plotter9002.region(0).plot(sumtrks);
+        plotter9002.region(1).plot(invarmass);
+        plotter9003.region(0).plot(perptrks);
+        plotter9004.region(0).plot(pyppm);
+        plotter9005.region(0).plot(pzppm);
+        plotter9006.region(0).plot(xy);
+        plotter9006.region(1).plot(xz);
+        plotter9006.region(2).plot(yz);
+        plotter9007.region(0).plot(xyemt);
+        plotter9007.region(1).plot(xzemt);
+        plotter9007.region(2).plot(yzemt);
+        plotter9007.region(3).plot(xyept);
+        plotter9007.region(4).plot(xzept);
+        plotter9007.region(5).plot(yzept);
+        plotter9008.region(0).plot(px);
+        plotter9008.region(1).plot(py);
+        plotter9008.region(2).plot(pz);
+        plotter9008.region(3).plot(chi2);
+        plotter9009.region(0).plot(bbpx);
+        plotter9009.region(1).plot(bbpy);
+        plotter9009.region(2).plot(bbpz);
+        plotter9009.region(3).plot(bbchi2);
+        plotter9010.region(0).plot(spx);
+        plotter9010.region(1).plot(spy);
+        plotter9010.region(2).plot(spz);
+        plotter9010.region(3).plot(schi2);
+        plotter9011.region(0).plot(bbsumtrks);
+        plotter9011.region(1).plot(bbpppm);
+        plotter9011.region(2).plot(lbpppm);
+        plotter9011.region(3).plot(lbsumtrks);
+        plotter9012.region(0).plot(lbpx);
+        plotter9012.region(1).plot(lbpy);
+        plotter9012.region(2).plot(lbpz);
+        plotter9012.region(3).plot(lbchi2);
+        //    plotter9013.region(0).plot(q0spx);
+        //    plotter9013.region(1).plot(q0spy);
+        //    plotter9013.region(2).plot(q0spz);
+        //    plotter9013.region(3).plot(q0schi2);
+        plotter9015.region(0).plot(qbins);
+        plotter9015.region(1).plot(lbtp);
+        plotter9015.region(2).plot(bbtp);
+        plotter9016.region(0).plot(xvert);
+        plotter9016.region(1).plot(yvert);
+        plotter9016.region(2).plot(zvert);
+        plotter9016.region(3).plot(dist);
+        plotter9017.region(0).plot(xres);
+        plotter9017.region(1).plot(yres);
+        plotter9017.region(2).plot(xres2);
+        plotter9017.region(3).plot(yres2);
+
+        twotrkextra2.region(0).plot(unx1);
+        twotrkextra2.region(1).plot(uny1);
+        twotrkextra2.region(2).plot(unz1);
+        twotrkextra2.region(3).plot(unx2);
+        twotrkextra2.region(4).plot(uny2);
+        twotrkextra2.region(5).plot(unz2);
+        threetrack.region(0).plot(three);
+
+
+
+    }
+
+    public ElwinsTrackingRecon() {
+    }
+
+    public void setOutputPlots(String output) {
+        this.outputPlots = output;
+    }
+
+    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;
+    }
+
+    public void setTrackCollectionName(String trackCollectionName) {
+        this.trackCollectionName = trackCollectionName;
+    }
+
+    public void process(EventHeader event) {
+        aida.tree().cd("/");
+        if (!event.hasCollection(HelicalTrackHit.class, helicalTrackHitCollectionName)) {
+            //       System.out.println(helicalTrackHitCollectionName + " does not exist; skipping event");
+            return;
+        }
+        if (event.get(Track.class, trackCollectionName).size() < 2) {
+            //    System.out.println(trackCollectionName + " has less than two tracks; skipping event");
+            return;
+        }
+
+        List<HelicalTrackHit> rotList = event.get(HelicalTrackHit.class, rotatedTrackHitCollectionName);
+        for (HelicalTrackHit hth : rotList) {
+            HelicalTrackCross htc = (HelicalTrackCross) hth;
+//            System.out.println("TrackingReconstructionPlots::original helical track position = "+hth.getPosition()[0]+","+hth.getPosition()[1]+","+hth.getPosition()[2]);
+//            System.out.println("TrackingReconstructionPlots::corrected helical track position = "+htc.getCorrectedPosition().toString());
+        }
+
+        List<HelicalTrackHit> hthList = event.get(HelicalTrackHit.class, helicalTrackHitCollectionName);
+        int[] layersTop = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        int[] layersBot = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        for (HelicalTrackHit hth : hthList) {
+            HelicalTrackCross htc = (HelicalTrackCross) hth;
+//            System.out.println("TrackingReconstructionPlots::original helical track position = "+hth.getPosition()[0]+","+hth.getPosition()[1]+","+hth.getPosition()[2]);
+//            System.out.println("TrackingReconstructionPlots::corrected helical track position = "+htc.getCorrectedPosition().toString());
+            //These Helical Track Hits are in the JLAB frame
+//            htc.resetTrackDirection();
+            double x = htc.getPosition()[0];
+            double y = htc.getPosition()[1];
+            SiSensor sensor = ((SiSensor) ((RawTrackerHit) htc.getRawHits().get(0)).getDetectorElement());
+            if (SvtUtils.getInstance().isTopLayer(sensor)) {
+                layersTop[htc.Layer() - 1]++;
+                Hep3Vector sensorPos = ((SiSensor) ((RawTrackerHit) htc.getRawHits().get(0)).getDetectorElement()).getGeometry().getPosition();
+                if (htc.Layer() == 1) {
+//                    System.out.println(sensorPos.toString());
+//                    System.out.println("Hit X = " + x + "; Hit Y = " + y);
+//                    aida.histogram2D("Layer 1 HTH Position:  Top").fill(x - sensorPos.x(), y - sensorPos.y());
+                }
+//                if (htc.Layer() == 7)
+//                    aida.histogram2D("Layer 7 HTH Position:  Top").fill(x - sensorPos.x(), y - sensorPos.y());
+            } else {
+                layersBot[htc.Layer() - 1]++;
+                Hep3Vector sensorPos = ((SiSensor) ((RawTrackerHit) htc.getRawHits().get(0)).getDetectorElement()).getGeometry().getPosition();
+                if (htc.Layer() == 1) {
+//                    System.out.println(sensorPos.toString());
+//                    System.out.println("Hit X = " + x + "; Hit Y = " + y);
+//                    aida.histogram2D("Layer 1 HTH Position:  Bottom").fill(x - sensorPos.x(), y - sensorPos.y());
+                }
+//                if (htc.Layer() == 7)
+//                    aida.histogram2D("Layer 7 HTH Position:  Bottom").fill(x - sensorPos.x(), y - sensorPos.y());
+            }
+        }
+
+        if (!event.hasCollection(Track.class, trackCollectionName)) {
+//            System.out.println(trackCollectionName + " does not exist; skipping event");
+            //      aida.histogram1D("Number Tracks/Event").fill(0);
+            return;
+        }
+
+
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+        nTracks.fill(tracks.size());
+
+
+        if (tracks.size() == 2) { //uncert can be used here  && (Ytrue || Ytrue2) && (Xtrue || Xtrue2)
+
+            Track trk1 = tracks.get(0);
+            Track trk2 = tracks.get(1);
+            int isTrk1Top = -1;
+            if (trk1.getTrackerHits().get(0).getPosition()[2] > 0) {
+                isTrk1Top = 1;
+            }
+            int isTrk2Top = -1;
+            if (trk2.getTrackerHits().get(0).getPosition()[2] > 0) {
+                isTrk2Top = 1;
+            }
+            boolean topbot = false;
+            if ((isTrk1Top + isTrk2Top) == 0) {
+                topbot = true;
+            }
+
+            SeedTrack stEle1 = (SeedTrack) trk1;
+            SeedCandidate seedEle1 = stEle1.getSeedCandidate();
+            HelicalTrackFit ht1 = seedEle1.getHelix();
+            HelixConverter converter1 = new HelixConverter(0);
+            StraightLineTrack slt1 = converter1.Convert(ht1);
+
+            SeedTrack stEle2 = (SeedTrack) trk2;
+            SeedCandidate seedEle2 = stEle2.getSeedCandidate();
+            HelicalTrackFit ht2 = seedEle2.getHelix();
+            HelixConverter converter2 = new HelixConverter(0);
+            StraightLineTrack slt2 = converter2.Convert(ht2);
+
+            HPSTrack hpstrack1 = new HPSTrack(ht1);
+            Hep3Vector[] trkatconver1 = hpstrack1.getPositionAtZMap(100, BeamlineConstants.HARP_POSITION_TESTRUN, 1);
+            HPSTrack hpstrack2 = new HPSTrack(ht2);
+            Hep3Vector[] trkatconver2 = hpstrack2.getPositionAtZMap(100, BeamlineConstants.HARP_POSITION_TESTRUN, 1);
+
+
+
+            List<TrackerHit> hitsOnTrack1 = trk1.getTrackerHits();
+            int layer1;
+            double y1 = 0;
+            double y2 = 0;
+            double z1 = 0;
+            double z2 = 0;
+            double dely1 = 0;
+            double dely2 = 0;
+            for (TrackerHit hit : hitsOnTrack1) {
+                HelicalTrackHit htc1 = (HelicalTrackHit) hit;
+                layer1 = htc1.Layer();
+                int y1layer = 0;
+                int y2layer = 0;
+                if (y1 == 0) {
+                    y1 = htc1.getPosition()[2]; //
+                    z1 = htc1.getPosition()[0]; // z1 is jlab but the get position refers to hps-tracking
+                    y1layer = layer1;
+                    SymmetricMatrix ErrorHitOne = htc1.getCorrectedCovMatrix();
+                    dely1 = Math.sqrt(ErrorHitOne.diagonal(2)); //y in jlab is z in hps
+                } else {
+
+                    if ((layer1 > y1layer) && (y2layer == 0)) {
+                        y2 = htc1.getPosition()[2]; //
+                        z2 = htc1.getPosition()[0]; // see above comments!
+                        y2layer = layer1;
+                        SymmetricMatrix ErrorHitTwo = htc1.getCorrectedCovMatrix();
+                        dely2 = Math.sqrt(ErrorHitTwo.diagonal(2));
+                    }
+
+                }
+
+            }
+            List<TrackerHit> hitsOnTrack2 = trk2.getTrackerHits();
+
+            double my1 = 0;
+            double my2 = 0;
+            double mz1 = 0;
+            double mz2 = 0;
+            double delymy1 = 0;
+            double delymy2 = 0;
+            int layer2;
+            for (TrackerHit hit : hitsOnTrack2) {
+                HelicalTrackHit htc2 = (HelicalTrackHit) hit;
+//            if (htc.getPosition()[2] < 0) {
+
+                layer2 = htc2.Layer();
+                int my1layer = 0;
+                int my2layer = 0;
+                if (my1 == 0) {
+                    my1 = htc2.getPosition()[2]; //see above comments
+                    mz1 = htc2.getPosition()[0];
+                    my1layer = layer2;
+                    SymmetricMatrix ErrorHitOne = htc2.getCorrectedCovMatrix();
+                    delymy1 = Math.sqrt(ErrorHitOne.diagonal(2));
+                } else {
+                    if ((layer2 > my1layer) && (my2layer == 0)) {
+                        my2 = htc2.getPosition()[2];
+                        mz2 = htc2.getPosition()[0];
+                        my2layer = layer2;
+                        SymmetricMatrix ErrorHitTwo = htc2.getCorrectedCovMatrix();
+                        delymy2 = Math.sqrt(ErrorHitTwo.diagonal(2));
+                    }
+                }
+            }
+            //   double dely = .00001; //mm
+            double b1;
+            double m1;
+            double b2;
+            double m2;
+            boolean check1 = true;
+            if (y1 == 0) {
+                check1 = false;
+            }
+            boolean check2 = true;
+            if (my1 == 0) {
+                check2 = false;
+            }
+            boolean check3 = true;
+            if (my2 == 0) {
+                check3 = false;
+            }
+
+
+
+
+            double X1 = slt1.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[0];
+            double Y1 = slt1.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[1];
+
+            //   boolean Y1top = false;
+            //    boolean X1plus = false;
+            //     boolean Y1bot = false;
+            //      boolean X1minus = false;
+            boolean X1cent = false;
+            boolean Y1cent = false; //for simulation
+
+            if (11 < X1 && X1 < 29) {
+                X1cent = true;
+            }
+            if (-3.5 < Y1 && Y1 < 3.5) {
+                Y1cent = true;
+            }
+
+            //    if (1 < Y1 && Y1 < 6) { //1 < Y1 && Y1 < 6 +-2.5
+            //       Y1top = true;
+            //  }
+            //     if (11 < X1 && X1 < 29) { // 4 < X1 && X1 < 16 +-6
+            //           X1minus = true;
+            //      }
+            //        if (-5 < Y1 && Y1 < 0) { // -5 < Y1 && Y1 < 0 +-2.5
+            //           Y1bot = true;
+            //      }
+            //       if (11 < X1 && X1 < 29) { // 24 < X1 && X1 < 36 +-6
+            //          X1plus = true;
+            //     }
+            double X2 = slt2.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[0];
+            double Y2 = slt2.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[1];
+
+            //      boolean Y2top = false; //for data
+            //     boolean X2plus = false;
+            //    boolean Y2bot = false; //in general
+            //      boolean X2minus = false;
+            boolean X2cent = false;
+            boolean Y2cent = false; //for simulation
+            if (11 < X2 && X2 < 29) {
+                X2cent = true;
+            }
+            if (-3.5 < Y2 && Y2 < 3.5) {
+                Y2cent = true;
+            }
+            //       if (1 < Y2 && Y2 < 6) {
+            //          Y2top = true;
+            //     }
+            //      if (11 < X2 && X2 < 29) {
+            //           X2minus = true;
+            //      }
+            //   if (-5 < Y2 && Y2 < 0) {
+            //      Y2bot = true;
+            // }
+            //       if (11 < X2 && X2 < 29) {
+            //           X2plus = true;
+            //       }
+
+
+            //      boolean Trk1Top = false;
+            //     boolean Trk2Top = false;
+            //    boolean Trk1Bot = false;
+            //   boolean Trk2Bot = false;
+            //  if (isTrk1Top == 1) {
+            //             Trk1Top = true;
+            //       }
+            //     if (isTrk2Top == 1) {
+            //       Trk2Top = true;
+            //         }
+            //       if (isTrk1Top == -1) {
+            //         Trk1Bot = true;
+            //   }
+            //  if (isTrk2Top == -1) {
+            //    Trk2Bot = true;
+            //      }
+            //  boolean Trk1goodTop = false;
+            //   boolean Trk2goodTop = false;
+            // boolean Trk1goodBot = false;
+            //   boolean Trk2goodBot = false;
+            //      if (Trk1Top && Y1top) {
+            //         Trk1goodTop = true;
+            //    }
+            //   if (Trk2Top && Y2top) {
+            //            Trk2goodTop = true;
+            //   }
+            //   if (Trk1Bot && Y1bot) {
+            //      Trk1goodBot = true;
+            //   }
+            //   if (Trk2Bot && Y2bot) {
+            //      Trk2goodBot = true;
+            //  }
+
+            int qtrk1 = trk1.getCharge();
+            int qtrk2 = trk2.getCharge();
+            boolean pm = false;
+            if ((qtrk1 + qtrk2) == 0) {
+                pm = true;
+            }
+
+            //   boolean Trk1Plus = false;
+            //    boolean Trk2Plus = false;
+            //      boolean Trk1Minus = false;
+            //       boolean Trk2Minus = false;
+            //       if (qtrk1 > 0) {
+            //           Trk1Plus = true;
+            //        } else {
+            //             Trk1Minus = true;
+            //        }
+            //       if (qtrk2 > 0) {
+            //           Trk2Plus = true;
+            //      } else {
+            //          Trk2Minus = true;
+            //     }
+
+            //    boolean Trk1goodPlus = false;
+            //     boolean Trk2goodPlus = false;
+            //     boolean Trk1goodMinus = false;
+            //    boolean Trk2goodMinus = false;
+
+            //       if (Trk1Plus && X1plus) {
+            //          Trk1goodPlus = true;
+            //       }
+            //       if (Trk2Plus && X2plus) {
+            //           Trk2goodPlus = true;
+            //        }
+            //       if (Trk1Minus && X1minus) {
+            //        Trk1goodMinus = true;
+            //       }
+            //        if (Trk2Minus && X2minus) {
+            //          Trk2goodMinus = true;
+            //       }
+            if (topbot && pm) {
+
+                double b1p;
+                double b2p;
+                double m1p;
+                double m2p;
+
+                if (check1 && check2 && check3) {
+                    if (isTrk1Top == 1) {
+                        double zc = -1 * z1 / (z2 - z1);
+                        b1 = (zc * (y2 - y1 + .5 * (dely2 + dely1))) + y1 - (.5 * dely1);
+                        m1 = (y2 - y1 + .5 * (dely2 + dely1)) / (z2 - z1);
+                        m1p = (y2 - y1 - .5 * (dely2 + dely1)) / (z2 - z1);
+                        b1p = y1 - (m1p * z1) + (.5 * dely1);
+                    } else {
+                        double zc = -1 * z1 / (z2 - z1);
+                        b1 = (zc * (y2 - y1 - .5 * (dely2 + dely1))) + y1 + (.5 * dely1);
+                        m1 = (y2 - y1 - .5 * (dely2 + dely1)) / (z2 - z1);
+                        m1p = (y2 - y1 + .5 * (dely2 + dely1)) / (z2 - z1);
+                        b1p = y1 - (m1p * z1) - (.5 * dely1);
+                    }
+
+                    if (isTrk2Top == 1) {
+                        double zc = -1 * mz1 / (mz2 - mz1);
+                        b2 = (zc * (my2 - my1 + .5 * (delymy2 + delymy1))) + my1 - (.5 * delymy1);
+                        m2 = (my2 - my1 + .5 * (delymy2 + delymy1)) / (mz2 - mz1);
+                        m2p = (my2 - my1 - .5 * (delymy2 + delymy1)) / (mz2 - mz1);
+                        b2p = my1 - (m2p * mz1) + (.5 * delymy1);
+                    } else {
+                        double zc = -1 * mz1 / (mz2 - mz1);
+                        b2 = (zc * (my2 - my1 - .5 * (delymy2 + delymy1))) + my1 + (.5 * delymy1);
+                        m2 = (my2 - my1 - .5 * (delymy2 + delymy1)) / (mz2 - mz1);
+                        m2p = (my2 - my1 + .5 * (delymy2 + delymy1)) / (mz2 - mz1);
+                        b2p = my1 - (m2p * mz1) - (.5 * delymy1);
+                    }
+                    //    System.out.println("y1 = " + y1);
+                    //    System.out.println("y2 = " + y2);
+                    //    System.out.println("y'1 = " + my1);
+                    //    System.out.println("y'2 = " + my2);
+                    double zi = (b2 - b1) / (m1 - m2);
+                    double zr = Math.abs(zi - BeamlineConstants.HARP_POSITION_TESTRUN);
+                    double zs = 2 * zr / 100;
+                    //      System.out.println("Closest Possible Z to Tracker");
+                    //      System.out.println(zi);
+
+
+                    List<double[]> Trk1 = new ArrayList<double[]>();
+                    for (int i = 0; i < 100; i++) {
+                        double z = BeamlineConstants.HARP_POSITION_TESTRUN - zr + (zs * i);
+                        double[] posvec = new double[3];
+                        Hep3Vector[] trk1atz = hpstrack1.getPositionAtZMap(100, z, 1);
+                        posvec[0] = trk1atz[0].x();
+                        posvec[1] = trk1atz[0].y();
+                        posvec[2] = z;
+
+                        Trk1.add(posvec);
+                    }
+                    //  System.out.println("Vectors ");
+
+                    //  System.out.println(Trk1);
+
+                    double xbar = 0;
+                    double ybar = 0;
+                    double zbar = 0;
+                    double xsqbar = 0;
+                    double ysqbar = 0;
+                    double zsqbar = 0;
+                    int n = 0;
+                    for (double[] inttrk : Trk1) {
+                        //      System.out.println(inttrk[0]);
+                        //    System.out.println(inttrk[1]);
+                        //    System.out.println(inttrk[2]);
+                        xbar = xbar + inttrk[0];
+                        ybar = ybar + inttrk[1];
+                        zbar = zbar + inttrk[2];
+                        n = n + 1;
+                    }
+                    //   System.out.println("n " + n);
+                    xbar = xbar / n;
+                    ybar = ybar / n;
+                    zbar = zbar / n;
+                    //    System.out.println("Xbar is " + xbar);
+                    //    System.out.println("Ybar is " + ybar);
+                    //    System.out.println("Zbar is " + zbar);
+                    Matrix d;
+                    Matrix A = Matrix.random(n, 3);
+                    int j1 = 0;
+                    for (double[] inttrk : Trk1) {
+                        A.set(j1, 0, inttrk[0] - xbar);
+                        A.set(j1, 1, inttrk[1] - ybar);
+                        A.set(j1, 2, inttrk[2] - zbar);
+                        j1++;
+                    }
+
+                    //           System.out.println("Matrix A");
+                    //           A.print(9, 6);
+                    A.svd();
+                    SingularValueDecomposition s = A.svd();
+                    Matrix S = s.getS();
+                    //         System.out.println("S Matrix");
+                    //         S.print(9, 6);
+                    Matrix V = s.getV();
+                    //         System.out.println("V Matrix");
+                    //         V.print(9, 6);
+                    d = V.getMatrix(0, 2, 0, 0);
+                    double[] dd;
+                    dd = new double[3];
+
+                    dd[0] = d.get(0, 0);
+                    dd[1] = d.get(1, 0);
+                    dd[2] = d.get(2, 0);
+                    double nd = Math.sqrt((Math.pow(dd[0], 2)) + (Math.pow(dd[1], 2)) + (Math.pow(dd[2], 2)));
+
+                    for (double[] inttrk : Trk1) {
+                        double t1 = (inttrk[2] - zbar) / dd[2];
+                        double restrk1[];
+                        restrk1 = new double[3];
+                        restrk1[0] = xbar + (t1) * dd[0] - inttrk[0];
+                        restrk1[1] = ybar + (t1) * dd[1] - inttrk[1];
+                        restrk1[2] = zbar + (t1) * dd[2] - inttrk[2];
+                        aida.histogram1D("X Res Trk1").fill(restrk1[0]);
+                        aida.histogram1D("Y Res Trk1").fill(restrk1[1]);
+                    }
+
+                    List<double[]> Trk2 = new ArrayList<double[]>();
+                    for (int i = 0; i < 100; i++) {
+                        double z = BeamlineConstants.HARP_POSITION_TESTRUN - zr + (zs * i);
+                        double[] posvec2 = new double[3];
+                        Hep3Vector[] trk2atz = hpstrack2.getPositionAtZMap(100, z, 1);
+                        posvec2[0] = trk2atz[0].x();
+                        posvec2[1] = trk2atz[0].y();
+                        posvec2[2] = z;
+                        Trk2.add(posvec2);
+                        //      System.out.println("Components");
+                        //      System.out.println(posvec2[0]);
+                        //      System.out.println(posvec2[1]);
+                        //      System.out.println(posvec2[2]);
+                    }
+                    double xbar2 = 0;
+                    double ybar2 = 0;
+                    double zbar2 = 0;
[truncated at 1000 lines; 562 more skipped]

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
ExamplePlotter.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/ExamplePlotter.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/ExamplePlotter.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,113 @@
+package org.lcsim.hps.users.mgraham;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogram1D;
+import hep.aida.IPlotter;
+import hep.aida.IPlotterStyle;
+import hep.physics.vec.Hep3Vector;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.event.BeamlineConstants;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.monitoring.deprecated.Resettable;
+import org.lcsim.hps.recon.tracking.HPSTrack;
+import org.lcsim.hps.recon.vertexing.HelixConverter;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+
+ @author mgraham
+ */
+public class ExamplePlotter extends Driver implements Resettable {
+
+    private AIDAFrame plotterFrame;
+    private AIDA aida = AIDA.defaultInstance();
+    IPlotter plotter;
+    IAnalysisFactory fac = aida.analysisFactory();
+    private String trackCollectionName = "MatchedTracks";
+    private String outputPlots = null;
+
+    protected void detectorChanged(Detector detector) {
+        aida.tree().cd("/");
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("HPS Tracking Plots");
+
+        plotter = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter.setTitle("Momentum");
+        IPlotterStyle style = plotter.style();
+        style.dataStyle().fillStyle().setColor("yellow");
+        style.dataStyle().errorBarStyle().setVisible(false);
+        plotter.createRegions(2, 3);
+        plotterFrame.addPlotter(plotter);
+
+        IHistogram1D trkPx = aida.histogram1D("Track Momentum (Px)", 25, -0.25, 0.25);
+        IHistogram1D trkPy = aida.histogram1D("Track Momentum (Py)", 25, -0.1, 0.1);
+        IHistogram1D trkPz = aida.histogram1D("Track Momentum (Pz)", 25, 0, 3.5);
+        IHistogram1D trkChi2 = aida.histogram1D("Track Chi2", 25, 0, 25.0);
+        IHistogram1D xAtConvert = aida.histogram1D("X (mm) @ Converter", 50, -50, 50);
+        IHistogram1D yAtConvert = aida.histogram1D("Y (mm) @ Converter", 50, -20, 20);
+        plotter.region(0).plot(trkPx);
+        plotter.region(1).plot(trkPy);
+        plotter.region(2).plot(trkPz);
+        plotter.region(3).plot(trkChi2);
+        plotter.region(4).plot(xAtConvert);
+        plotter.region(5).plot(yAtConvert);
+
+        plotterFrame.pack();
+        plotterFrame.setVisible(true);
+    }
+
+    public void process(EventHeader event) {
+        aida.tree().cd("/");
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+        for (Track trk : tracks) {
+            aida.histogram1D("Track Momentum (Px)").fill(trk.getPY());
+            aida.histogram1D("Track Momentum (Py)").fill(trk.getPZ());
+            aida.histogram1D("Track Momentum (Pz)").fill(trk.getPX());
+            aida.histogram1D("Track Chi2").fill(trk.getChi2());
+
+            SeedTrack stEle = (SeedTrack) trk;
+            SeedCandidate seedEle = stEle.getSeedCandidate();
+            HelicalTrackFit ht = seedEle.getHelix();
+            HelixConverter converter = new HelixConverter(0);
+            StraightLineTrack slt = converter.Convert(ht);
+            HPSTrack hpstrack = new HPSTrack(ht);
+            Hep3Vector[] trkatconver = hpstrack.getPositionAtZMap(100, BeamlineConstants.HARP_POSITION_TESTRUN, 1);
+            aida.histogram1D("X (mm) @ Converter").fill(trkatconver[0].x()); // y tracker frame?
+            aida.histogram1D("Y (mm) @ Converter").fill(trkatconver[0].y()); // z tracker frame?
+
+        }
+    }
+
+    @Override
+    public void reset() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    public void setOutputPlots(String output) {
+        this.outputPlots = output;
+    }
+
+    public void endOfData() {
+        System.out.println("Output");
+        if (outputPlots != null) {
+            try {
+                aida.saveAs(outputPlots);
+            } catch (IOException ex) {
+                Logger.getLogger(ElwinsTrackingRecon.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
FastTrackAnalysisDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/FastTrackAnalysisDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/FastTrackAnalysisDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,937 @@
+package org.lcsim.hps.users.mgraham;
+
+import hep.aida.IAnalysisFactory;
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+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.SimTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.fit.helicaltrack.TrackDirection;
+import org.lcsim.hps.recon.vertexing.BilliorTrack;
+import org.lcsim.hps.recon.vertexing.BilliorVertex;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.hps.recon.tracking.FindableTrack;
+import org.lcsim.hps.recon.tracking.TrackAnalysis;
+import org.lcsim.hps.recon.vertexing.BilliorVertexer;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+
+ @author mgraham
+ */
+public class FastTrackAnalysisDriver extends Driver {
+
+    String[] detNames = {"Tracker"};
+    Integer _minLayers = 10;
+    Integer[] nlayers = {12};
+    int nevt = 0;
+    double xref = 50.0; //mm
+    public String outputTextName = "myevents.txt";
+    FileWriter fw;
+    PrintWriter pw;
+    double[] beamsize = {0.001, 0.2, 0.02};
+    String _config = "Test";
+// flipSign is a kludge...
+//  HelicalTrackFitter doesn't deal with B-fields in -ive Z correctly
+//  so we set the B-field in +iveZ and flip signs of fitted tracks
+//  note:  this should be -1 for Test configurations and +1 for Full (v3.X and lower) configurations
+//  this is set by the _config variable (detType in HeavyPhotonDriver)
+    int flipSign = 1;
+    boolean makePlots = true;
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+
+    public FastTrackAnalysisDriver(int trackerLayers, int mintrkLayers, String config) {
+        nlayers[0] = trackerLayers;
+        _minLayers = mintrkLayers;
+        _config = config;
+    }
+
+    public FastTrackAnalysisDriver() {
+    }
+
+    public void setNLayers(int trackerLayers) {
+        nlayers[0] = trackerLayers;
+    }
+
+    public void setMinLayers(int mintrkLayers) {
+        _minLayers = mintrkLayers;
+    }
+
+
+    public void setBeamSigmaX(double sigma){
+        beamsize[1]=sigma;  //the beamsize[] array is in tracking frame
+    }
+    
+     public void setBeamSigmaY(double sigma){
+        beamsize[2]=sigma;   //the beamsize[] array is in tracking frame
+    }
+      
+
+    public void process(
+            EventHeader event) {
+        if (nevt == 0) {
+            try {
+//open things up
+                fw = new FileWriter(outputTextName);
+                pw = new PrintWriter(fw);
+            } catch (IOException ex) {
+                Logger.getLogger(FastTrackAnalysisDriver.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+        //  Increment the event counter
+        nevt++;
+
+
+
+        Hep3Vector IP = new BasicHep3Vector(0., 0., 1.);
+        double bfield = event.getDetector().getFieldMap().getField(IP).y();
+        if (bfield < 0) {
+            flipSign = -1;
+        }
+
+        List<RawTrackerHit> rawHits = event.get(RawTrackerHit.class, "RawTrackerHitMaker_RawTrackerHits");
+        List<SiTrackerHitStrip1D> stripHits = event.get(SiTrackerHitStrip1D.class, "StripClusterer_SiTrackerHitStrip1D");
+        List<HelicalTrackHit> toththits = event.get(HelicalTrackHit.class, "RotatedHelicalTrackHits");
+//        List<HelicalTrackHit> toththits = event.get(HelicalTrackHit.class, "HelicalTrackHits");
+//        List<HelicalTrackHit> axialhits = event.get(HelicalTrackHit.class, "AxialTrackHits");
+
+        int nAxialHitsTotal = stripHits.size();
+        int nL1Hits = 0;
+        for (SiTrackerHitStrip1D str : stripHits) {
+            if (str.getRawHits().get(0).getLayerNumber() == 1) {
+                nL1Hits++;
+            }
+        }
+
+
+        //  Create a relational table that maps TrackerHits to MCParticles
+        RelationalTable hittomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        List<LCRelation> mcrelations = event.get(LCRelation.class, "RotatedHelicalTrackMCRelations");
+
+        for (LCRelation relation : mcrelations) {
+            if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+                hittomc.add(relation.getFrom(), relation.getTo());
+            }
+        }
+        /*
+         RelationalTable hittomcAxial = new
+         BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY,
+         RelationalTable.Weighting.UNWEIGHTED); // List<LCRelation> mcrelations
+         = event.get(LCRelation.class, "HelicalTrackMCRelations");
+         List<LCRelation> mcrelationsAxial = event.get(LCRelation.class,
+         "AxialTrackMCRelations"); for (LCRelation relation : mcrelationsAxial)
+         { if (relation != null && relation.getFrom() != null &&
+         relation.getTo() != null) { hittomcAxial.add(relation.getFrom(),
+         relation.getTo()); } }
+         */
+        //  Instantiate the class that determines if a track is "findable"
+        FindableTrack findable = new FindableTrack(event);
+
+        //  Create a map between tracks and the associated MCParticle
+        List<Track> tracklist = event.get(Track.class, "MatchedTracks");
+//        List<Track> lltracklist = event.get(Track.class, "LLTracks");
+//        List<Track> axialtracklist = event.get(Track.class, "AxialTracks");
+//        tracklist.addAll(lltracklist);
+
+        RelationalTable trktomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        RelationalTable mcHittomcP = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        //  Get the collections of SimTrackerHits
+        List<List<SimTrackerHit>> simcols = event.get(SimTrackerHit.class);
+
+        //  Loop over the SimTrackerHits and fill in the relational table
+        for (List<SimTrackerHit> simlist : simcols) {
+            for (SimTrackerHit simhit : simlist) {
+                if (simhit.getMCParticle() != null) {
+                    mcHittomcP.add(simhit, simhit.getMCParticle());
+                }
+            }
+        }
+
+        Map<Track, TrackAnalysis> tkanalMap = new HashMap<Track, TrackAnalysis>();
+        Map<Track, BilliorTrack> btMap = new HashMap<Track, BilliorTrack>();
+        RelationalTable nearestHitToTrack = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        Map<Track, Double> l1Isolation = new HashMap<Track, Double>();
+        Map<Track, Double> l1DeltaZ = new HashMap<Track, Double>();
+        Map<Track, Double> l123KinkAngle = new HashMap<Track, Double>();
+        int _neleRec = 0;
+        int _nposRec = 0;
+        //  Analyze the tracks in the event
+        for (Track track : tracklist) {
+            if (track.getCharge() < 0) {
+                _neleRec++;
+            }
+            if (track.getCharge() > 0) {
+                _nposRec++;
+            }
+            //extrapolate straight back...
+            SeedTrack stEle = (SeedTrack) track;
+            SeedCandidate seedEle = stEle.getSeedCandidate();
+            HelicalTrackFit ht = seedEle.getHelix();
+
+            BilliorTrack bt = new BilliorTrack(ht);
+
+            TrackAnalysis tkanal = new TrackAnalysis(track, hittomc);
+
+            tkanalMap.put(track, tkanal);
+            btMap.put(track, bt);
+
+
+            //  Now analyze MC Particles on this track
+            MCParticle mcp = tkanal.getMCParticleNew();
+            if (mcp != null) //  Create a map between the tracks found and the assigned MC particle
+            {
+                trktomc.add(track, tkanal.getMCParticleNew());
+            }
+            BasicHep3Vector axial = new BasicHep3Vector();
+            axial.setV(0, 1, 0);
+            List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+            double[] zlist = {0, 0, 0};
+            for (TrackerHit hit : hitsOnTrack) {
+                HelicalTrackHit htc = (HelicalTrackHit) hit;
+                List<MCParticle> mcpsHTH = htc.getMCParticles();
+                double sHit = ht.PathMap().get(htc);
+                Hep3Vector posonhelix = HelixUtils.PointOnHelix(ht, sHit);
+                double yTr = posonhelix.y();
+                double zTr = posonhelix.z();
+                HelicalTrackCross cross = (HelicalTrackCross) htc;
+                List<HelicalTrackStrip> clusterlist = cross.getStrips();
+                TrackDirection trkdir = HelixUtils.CalculateTrackDirection(ht, sHit);
+                cross.setTrackDirection(trkdir, ht.covariance());
+                double y = cross.y();
+                double z = cross.z();
+                double yerr = Math.sqrt(cross.getCorrectedCovMatrix().e(1, 1));
+                double zerr = Math.sqrt(cross.getCorrectedCovMatrix().e(2, 2));
+
+                int htlayer = htc.Layer();
+                if (htlayer == 1) {
+                    zlist[0] = z;
+                }
+                if (htlayer == 3) {
+                    zlist[1] = z;
+                }
+                if (htlayer == 5) {
+                    zlist[2] = z;
+                }
+                if (htlayer == 1) {
+                    l1DeltaZ.put(track, z - zTr);
+                }
+                for (HelicalTrackStrip cl : clusterlist) {
+                    int layer = cl.layer();
+                    HelicalTrackStrip nearest = getNearestHit(cl, toththits);
+                    if (layer == 1) {
+                        Double l1Dist = getNearestDistance(cl, toththits);
+                        if (l1Dist != null) {
+                            l1Isolation.put(track, l1Dist);
+                        }
+                    }
+                    if (nearest != null) {
+                        nearestHitToTrack.add(track, nearest);
+                    }
+                }
+            }
+            double layerDist = 10;//cm
+            double theta12 = Math.atan2(zlist[1] - zlist[0], layerDist);
+            double theta13 = Math.atan2(zlist[2] - zlist[0], 2 * layerDist);
+            double theta23 = Math.atan2(zlist[2] - zlist[1], layerDist);
+            l123KinkAngle.put(track, theta23 - theta12);
+        }
+
+
+
+
+        //analyze the event
+        int ApCand = 0;
+        Track eleID = null;
+        Track posID = null;
+        MCParticle eleMC = null;
+        MCParticle posMC = null;
+        for (Track track : tracklist) {
+
+            TrackAnalysis tkanal = tkanalMap.get(track);
+            BilliorTrack bt = btMap.get(track);
+            //  Calculate purity and make appropriate plots
+            MCParticle mcp = tkanal.getMCParticleNew();
+            if (mcp == null) {
+                continue;
+            }
+            if (mcp.getParents().size() == 1 && mcp.getParents().get(0).getPDGID() == 622) {
+                int nhits = tkanal.getNHitsNew();
+                double px = track.getPX();
+                double py = track.getPY();
+                double pz = track.getPZ();
+                double pt = Math.sqrt(px * px + py * py);
+                double pperp = Math.sqrt(py * py + pz * pz);
+                double p = Math.sqrt(pt * pt + pz * pz);
+                double phi = Math.atan2(py, px);
+                double cth = pz / Math.sqrt(pt * pt + pz * pz);
+
+//                double doca = slt.Doca();
+//                double[] poca = slt.Poca();
+
+                if (mcp.getCharge() > 0) {
+                    posID = track;
+                    posMC = mcp;
+
+                } else {
+                    eleID = track;
+                    eleMC = mcp;
+                }
+            }
+
+        }
+        for (Track track1 : tracklist) {
+            Track ele = null;
+            Track pos = null;
+            int ch1 = track1.getCharge() * flipSign;
+            int index = tracklist.indexOf(track1);
+            List<Track> subtracklist = tracklist.subList(index, tracklist.size());
+            for (Track track2 : subtracklist) {
+                int ch2 = track2.getCharge() * flipSign;
+                if (track1 != track2 && ch1 == -ch2) {
+                    ele = track1;
+                    pos = track2;
+//                    System.out.println("Found two oppositely charged tracks!  Lets look at them");
+                    if (ch1 > 0) {
+                        ele = track2;
+                        pos = track1;
+                    }
+                    ApCand++;
+                    // int nElectron = ele.getTrackerHits().size();
+                    // int nPositron = pos.getTrackerHits().size();
+
+                    SeedTrack stEle = (SeedTrack) ele;
+                    SeedCandidate seedEle = stEle.getSeedCandidate();
+                    HelicalTrackFit htEle = seedEle.getHelix();
+
+                    SeedTrack stPos = (SeedTrack) pos;
+                    SeedCandidate seedPos = stPos.getSeedCandidate();
+                    HelicalTrackFit htPos = seedPos.getHelix();
+
+                    double d0E = htEle.dca();
+                    double z0E = htEle.z0();
+                    double phi0E = htEle.phi0();
+                    double RE = htEle.R();
+                    double slopeE = htEle.slope();
+                    double d0P = htPos.dca();
+                    double z0P = htPos.z0();
+                    double phi0P = htPos.phi0();
+                    double RP = htPos.R();
+                    double slopeP = htPos.slope();
+
+                    double pxE = ele.getPX();
+                    double pyE = ele.getPY();
+                    double pzE = ele.getPZ();
+                    double pxP = pos.getPX();
+                    double pyP = pos.getPY();
+                    double pzP = pos.getPZ();
+
+                    List<BilliorTrack> btlist = new ArrayList<BilliorTrack>();
+
+                    BilliorTrack btEle = btMap.get(ele);
+                    BilliorTrack btPos = btMap.get(pos);
+
+                    btlist.add(btEle);
+                    btlist.add(btPos);
+
+
+
+                   BilliorVertexer vtxfitter = new BilliorVertexer(bfield);
+                    vtxfitter.doBeamSpotConstraint(false);
+                    vtxfitter.setBeamSize(beamsize);
+
+                    BilliorVertexer vtxfitterCon = new BilliorVertexer(bfield);
+                    vtxfitterCon.doBeamSpotConstraint(true);
+                    vtxfitterCon.setBeamSize(beamsize);
+
+                    BilliorVertexer vtxfitterBSCon = new BilliorVertexer(bfield);
+                    vtxfitterBSCon.doTargetConstraint(true);
+                    vtxfitterBSCon.setBeamSize(beamsize);
+
+
+                    BilliorVertex vtxfit = vtxfitter.fitVertex(btlist);
+                    Map<String, Double> vtxMap = vtxfit.getParameters();
+
+                    double vtxpxE = vtxMap.get("p1X");
+                    double vtxpyE = vtxMap.get("p1Y");
+                    double vtxpzE = vtxMap.get("p1Z");
+                    double vtxpxP = vtxMap.get("p2X");
+                    double vtxpyP = vtxMap.get("p2Y");
+                    double vtxpzP = vtxMap.get("p2Z");
+                    double chisq = vtxfit.getChi2();
+                    Hep3Vector vtx =  vtxfit.getPosition();
+                    SymmetricMatrix vtxcov = vtxfit.getCovMatrix();
+                    double chisqE = ele.getChi2();
+                    double chisqP = pos.getChi2();
+
+                    BilliorVertex confit = vtxfitterCon.fitVertex(btlist);
+                    Map<String, Double> conMap = confit.getParameters();
+                    double conpxE = conMap.get("p1X");
+                    double conpyE = conMap.get("p1Y");
+                    double conpzE = conMap.get("p1Z");
+                    double conpxP = conMap.get("p2X");
+                    double conpyP = conMap.get("p2Y");
+                    double conpzP = conMap.get("p2Z");
+                    double conchisq = confit.getChi2();
+                    Hep3Vector conVtx =  confit.getPosition();
+                    SymmetricMatrix conVtxCov = confit.getCovMatrix();
+
+                    BilliorVertex bsconfit = vtxfitterBSCon.fitVertex(btlist);
+                    Map<String, Double> bsconMap = bsconfit.getParameters();
+                    double bsconpxE = bsconMap.get("p1X");
+                    double bsconpyE = bsconMap.get("p1Y");
+                    double bsconpzE = bsconMap.get("p1Z");
+                    double bsconpxP = bsconMap.get("p2X");
+                    double bsconpyP = bsconMap.get("p2Y");
+                    double bsconpzP = bsconMap.get("p2Z");
+                    double bsconchisq = bsconfit.getChi2();
+                    Hep3Vector bsconVtx =  bsconfit.getPosition();
+                    SymmetricMatrix bsconVtxCov =  bsconfit.getCovMatrix();
+
+                    double l1minE = -99;
+                    double l1minP = -99;
+                    if (l1Isolation.get(ele) != null) {
+                        l1minE = l1Isolation.get(ele);
+                    }
+                    if (l1Isolation.get(pos) != null) {
+                        l1minP = l1Isolation.get(pos);
+                    }
+
+                    TrackAnalysis tkanalEle = tkanalMap.get(ele);
+                    TrackAnalysis tkanalPos = tkanalMap.get(pos);
+//                    Integer nElectron = tkanalEle.getNHitsNew();
+//                    Integer nPositron = tkanalPos.getNHitsNew();                    
+                    List<Integer> layersEle = tkanalEle.getTrackLayerList();
+                    List<Integer> layersPos = tkanalPos.getTrackLayerList();
+                    Integer nElectron = encodeLayers(layersEle);
+                    Integer nPositron = encodeLayers(layersPos);
+                    List<Integer> badhitsEle = tkanalEle.getBadHitList();
+                    List<Integer> badhitsPos = tkanalPos.getBadHitList();
+                    Integer badLayerEle = encodeLayers(badhitsEle);
+                    Integer badLayerPos = encodeLayers(badhitsPos);
+//                        int nMCL1Ele = tkanalEle.getNumberOfMCParticles(1);
+//                       int nMCL1Pos = tkanalPos.getNumberOfMCParticles(1);
+                    List<Integer> sharedhitsEle = tkanalEle.getSharedHitList();
+                    List<Integer> sharedhitsPos = tkanalPos.getSharedHitList();
+                    Integer sharedLayerEle = encodeLayers(sharedhitsEle);
+                    Integer sharedLayerPos = encodeLayers(sharedhitsPos);
+                    int nStripsL1Ele = -99;
+                    int nStripsL1Pos = -99;
+                    Integer l1 = 1;
+                    double zvalEle = -99;
+                    double zvalPos = -99;
+                    if (tkanalEle.hasLayerOne()) {
+                        zvalEle = tkanalEle.getClusterPosition(l1).z();
+                        nStripsL1Ele = tkanalEle.getNumberOfStripHits(1);
+                    }
+                    if (tkanalPos.hasLayerOne()) {
+                        zvalPos = tkanalPos.getClusterPosition(l1).z();
+                        nStripsL1Pos = tkanalPos.getNumberOfStripHits(1);
+                    }
+
+                    int eleFromAp = 0;
+                    int posFromAp = 0;
+                    if (eleMC != null && ele == eleID) {
+                        eleFromAp = 1;
+                    }
+                    if (posMC != null && pos == posID) {
+                        posFromAp = 1;
+                    }
+                    MCParticle mcEle = tkanalEle.getMCParticleNew();
+                    MCParticle mcPos = tkanalPos.getMCParticleNew();
+                    double[] pmcEle = {-99, -99, -99};
+                    double[] pmcPos = {-99, -99, -99};
+                    double[] pocamcE = {-99, -99, -99};
+                    double[] pocamcP = {-99, -99, -99};
+                    if (mcEle != null && mcPos != null) {
+                        pmcEle[0] = mcEle.getPX();
+                        pmcEle[1] = mcEle.getPY();
+                        pmcEle[2] = mcEle.getPZ();
+                        pmcPos[0] = mcPos.getPX();
+                        pmcPos[1] = mcPos.getPY();
+                        pmcPos[2] = mcPos.getPZ();
+                    }
+                    double[] ApVertexMC = {-99, -99, -99};
+                    if (eleFromAp == 1 && posFromAp == 1) {
+                        ApVertexMC[0] = eleMC.getOriginX();
+                        ApVertexMC[1] = eleMC.getOriginY();
+                        ApVertexMC[2] = eleMC.getOriginZ();
+                    }
+
+
+                    //print out the vertex;
+                    double l1dzE = -99;
+                    double l1dzP = -99;
+                    if (l1DeltaZ.get(ele) != null) {
+                        l1dzE = l1DeltaZ.get(ele);
+                    }
+                    if (l1DeltaZ.get(pos) != null) {
+                        l1dzP = l1DeltaZ.get(pos);
+                    }
+                    double l123KinkE = -99;
+                    double l123KinkP = -99;
+                    if (l123KinkAngle.get(ele) != null) {
+                        l123KinkE = l123KinkAngle.get(ele);
+                    }
+                    if (l123KinkAngle.get(pos) != null) {
+                        l123KinkP = l123KinkAngle.get(pos);
+                    }
+//                    
+//                    if (!tkanalEle.hasLayerOne()) {
+//                        nElectron = -nElectron;
+//                    }
+//                    if (!tkanalPos.hasLayerOne()) {
+//                        nPositron = -nPositron;
+//                    }
+                    pw.format("%d %5.5f %5.5f %5.5f ", nevt, pxE, pyE, pzE);
+                    pw.format("%5.5f  %5.5f %5.5f %5.5f  %5.5f ", d0E, z0E, slopeE, phi0E, RE);
+                    pw.format("%5.5f  %5.5f %5.5f %5.5f ", chisqE, l1minE, l1dzE, l123KinkE);
+                    pw.format("%d %d  %5.5f ", sharedLayerEle, nStripsL1Ele, zvalEle);
+                    pw.format("%d %d %d ", nElectron, badLayerEle, eleFromAp);
+                    pw.format("%5.5f %5.5f %5.5f ", pxP, pyP, pzP);
+                    pw.format("%5.5f  %5.5f %5.5f %5.5f  %5.5f ", d0P, z0P, slopeP, phi0P, RP);
+                    pw.format("%5.5f  %5.5f %5.5f %5.5f ", chisqP, l1minP, l1dzP, l123KinkP);
+                    pw.format("%d %d  %5.5f ", sharedLayerPos, nStripsL1Pos, zvalPos);
+                    pw.format("%d %d %d ", nPositron, badLayerPos, posFromAp);
+                    pw.format("%5.5f %5.5f %5.5f ", vtxpxE, vtxpyE, vtxpzE);
+                    pw.format("%5.5f %5.5f %5.5f ", vtxpxP, vtxpyP, vtxpzP);
+                    pw.format("%5.5f %5.5f %5.5f %5.5f %5.5f %5.5f ", vtx.x(), Math.sqrt(vtxcov.e(0, 0)), vtx.y(), Math.sqrt(vtxcov.e(1, 1)), vtx.z(), Math.sqrt(vtxcov.e(2, 2)));
+                    pw.format("%5.5f ", chisq);
+                    pw.format("%5.5f %5.5f %5.5f ", conpxE, conpyE, conpzE);
+                    pw.format("%5.5f %5.5f %5.5f ", conpxP, conpyP, conpzP);
+
+                    //   get the errors on the constrained vertex an make sure they aren't NaN
+                    //   there must be something wrong in the constraint...hopefully just the error calc
+                    double conErrX = getErr(conVtxCov.e(0, 0));
+                    double conErrY = getErr(conVtxCov.e(1, 1));
+                    double conErrZ = getErr(conVtxCov.e(2, 2));
+
+                    pw.format("%5.5f %5.5f %5.5f %5.5f %5.5f %5.5f ", conVtx.x(), conErrX, conVtx.y(), conErrY, conVtx.z(), conErrZ);
+                    pw.format("%5.5f ", conchisq);
+
+                    pw.format("%5.5f %5.5f %5.5f ", bsconpxE, bsconpyE, bsconpzE);
+                    pw.format("%5.5f %5.5f %5.5f ", bsconpxP, bsconpyP, bsconpzP);
+
+                    //   get the errors on the bsconstrained vertex an make sure they aren't NaN
+                    //   there must be somethihhhhfang wrong in the bsconstraint...hopefully just the error calc
+                    double bsconErrX = getErr(bsconVtxCov.e(0, 0));
+                    double bsconErrY = getErr(bsconVtxCov.e(1, 1));
+                    double bsconErrZ = getErr(bsconVtxCov.e(2, 2));
+
+                    pw.format("%5.5f %5.5f %5.5f %5.5f %5.5f %5.5f ", bsconVtx.x(), bsconErrX, bsconVtx.y(), bsconErrY, bsconVtx.z(), bsconErrZ);
+                    pw.format("%5.5f ", bsconchisq);
+
+
+//  print out MC information
+                    pw.format("%5.5f %5.5f %5.5f ", pmcEle[0], pmcEle[1], pmcEle[2]);
+                    pw.format("%5.5f %5.5f %5.5f ", pocamcE[0], pocamcE[1], pocamcE[2]);
+                    pw.format("%5.5f %5.5f %5.5f ", pmcPos[0], pmcPos[1], pmcPos[2]);
+                    pw.format("%5.5f %5.5f %5.5f ", pocamcP[0], pocamcP[1], pocamcP[2]);
+                    pw.format("%5.5f %5.5f %5.5f ", ApVertexMC[0], ApVertexMC[1], ApVertexMC[2]);
+//  print out some event information
+                    pw.format("%d %d %d %d", _neleRec, _nposRec, nAxialHitsTotal, nL1Hits);
+                    pw.println();
+                    if (makePlots) {
+                        aida.histogram1D("Event Number", 50, 0, 100000).fill(nevt);
+                        aida.histogram1D("pxE", 50, 0, 2.5).fill(pxE);
+                        aida.histogram1D("pyE", 50, -0.1, 0.1).fill(pyE);
+                        aida.histogram1D("pzE", 50, -0.1, 0.1).fill(pzE);
+                        aida.histogram1D("d0E", 50, -1.0, 1.0).fill(d0E);
+                        aida.histogram1D("z0E", 50, -1.0, 1.0).fill(z0E);
+                        aida.histogram1D("slopeE", 50, -0.1, 0.1).fill(slopeE);
+                        aida.histogram1D("sin(phi0E)", 50, -0.2, 0.2).fill(Math.sin(phi0E));
+                        aida.histogram1D("RE", 50, 0, 20000).fill(RE);
+                        aida.histogram1D("chisqE", 50, 0, 25).fill(chisqE);
+                        aida.histogram1D("l1minE", 50, -10, 10).fill(l1minE);
+                        aida.histogram1D("l1dzE", 50, -0.1, 0.1).fill(l1dzE);
+                        aida.histogram1D("l123KinkE", 50, -0.1, 0.1).fill(l123KinkE);
+                        aida.histogram1D("eleFromAp", 2, 0, 2).fill(eleFromAp);
+                        
+                        
+                        aida.histogram1D("pxP", 50, 0, 2.5).fill(pxP);
+                        aida.histogram1D("pyP", 50, -0.1, 0.1).fill(pyP);
+                        aida.histogram1D("pzP", 50, -0.1, 0.1).fill(pzP);
+                        aida.histogram1D("d0P", 50, -1.0, 1.0).fill(d0P);
+                        aida.histogram1D("z0P", 50, -1.0, 1.0).fill(z0P);
+                        aida.histogram1D("slopeP", 50, -0.1, 0.1).fill(slopeP);
+                        aida.histogram1D("sin(phi0P)", 50, -0.2, 0.2).fill(Math.sin(phi0P));
+                        aida.histogram1D("RP", 50, 0, 20000).fill(RP);
+                        aida.histogram1D("chisqP", 50, 0, 25).fill(chisqP);
+                        aida.histogram1D("l1minP", 50, -10, 10).fill(l1minP);
+                        aida.histogram1D("l1dzP", 50, -10, 10).fill(l1dzP);
+                        aida.histogram1D("l123KinkP", 50, -0.1, 0.1).fill(l123KinkP);
+                        aida.histogram1D("posFromAp", 2, 0, 2).fill(posFromAp);
+
+                        aida.histogram1D("vtxpxE", 50, 0, 2.5).fill(vtxpxE);
+                        aida.histogram1D("vtxpyE", 50, -0.1, 0.1).fill(vtxpyE);
+                        aida.histogram1D("vtxpzE", 50, -0.1, 0.1).fill(vtxpzE);
+                        aida.histogram1D("vtxpxP", 50, 0, 2.5).fill(vtxpxP);
+                        aida.histogram1D("vtxpyP", 50, -0.1, 0.1).fill(vtxpyP);
+                        aida.histogram1D("vtxpzP", 50, -0.1, 0.1).fill(vtxpzP);
+
+                        aida.histogram1D("vtxX", 50, -20, 20).fill(vtx.x());
+                        aida.histogram1D("vtxY", 50, -0.5, 0.5).fill(vtx.y());
+                        aida.histogram1D("vtxZ", 50, -0.5, 0.5).fill(vtx.z());
+
+                        aida.histogram1D("pxmcE", 50, 0, 2.5).fill(pmcEle[0]);
+                        aida.histogram1D("pymcE", 50, -0.1, 0.1).fill(pmcEle[1]);
+                        aida.histogram1D("pzmcE", 50, -0.1, 0.1).fill(pmcEle[2]);
+                    }
+
+                }
+            }
+        }
+
+//ok, fill MC Aprime info
+        List<MCParticle> mclist = event.getMCParticles();
+        MCParticle mcEle = null;
+        MCParticle mcPos = null;
+        MCParticle mcApr = null;
+        for (MCParticle mcp : mclist) {
+//            System.out.print("PDG ID = "+mcp.getPDGID());
+            if (mcp.getPDGID() == 622) {
+                mcApr = mcp;
+            }
+            if (mcp.getParents().size() == 1 && mcp.getParents().get(0).getPDGID() == 622) {
+                if (mcp.getPDGID() == -11) {
+                    mcPos = mcp;
+                }
+                if (mcp.getPDGID() == 11) {
+                    mcEle = mcp;
+                }
+            }
+        }
+//should probably check that each MC particles are found, but they should be...
+        double pxMCE = -99;
+        double pyMCE = -99;
+        double pzMCE = -99;
+        double pxMCP = -99;
+        double pyMCP = -99;
+        double pzMCP = -99;
+        double pxMCA = -99;
+        double pyMCA = -99;
+        double pzMCA = -99;
+        double mMCA = -99;
+        Hep3Vector decayMCA = new BasicHep3Vector();
+        int findableE = 0;
+        int findableP = 0;
+        int foundE = 0;
+        int foundP = 0;
+        if (mcEle != null) {
+            pxMCE = mcEle.getPX();
+            pyMCE = mcEle.getPY();
+            pzMCE = mcEle.getPZ();
+            if (findable.InnerTrackerIsFindable(mcEle, _minLayers)) {
+                findableE = 1;
+            }
+            Set<Track> trklistE = trktomc.allTo(mcEle);
+            foundE = trklistE.size();//can be greater than 1 if more than 1 track shares hits
+        } else {
+            System.out.println("!!!!!   WHAT, no mcEle      !!!!!!!!!");
+        }
+        if (mcPos != null) {
+            pxMCP = mcPos.getPX();
+            pyMCP = mcPos.getPY();
+            pzMCP = mcPos.getPZ();
+            if (findable.InnerTrackerIsFindable(mcPos, _minLayers)) {
+                findableP = 1;
+            }
+            Set<Track> trklistP = trktomc.allTo(mcPos);
+            foundP = trklistP.size();//can be greater than 1 if more than 1 track shares hits
+        } else {
+            System.out.println("!!!!!   WHAT, no mcPos      !!!!!!!!!");
+        }
+        if (mcApr != null) {
+            pxMCA = mcApr.getPX();
+            pyMCA = mcApr.getPY();
+            pzMCA = mcApr.getPZ();
+            mMCA = mcApr.getMass();
+            decayMCA = mcApr.getEndPoint();
+        } else {
+            System.out.println("!!!!!   WHAT, no mvApr      !!!!!!!!!");
+        }
+        pw.format(
+                "%d %5.5f %5.5f %5.5f %d %d ", -666, pxMCE, pyMCE, pzMCE, findableE, foundE);
+        pw.format(
+                "%5.5f %5.5f %5.5f %d %d ", pxMCP, pyMCP, pzMCP, findableP, foundP);
+        pw.format(
+                "%5.5f %5.5f %5.5f %5.5f %5.5f %5.5f %5.5f", pxMCA, pyMCA, pzMCA, mMCA, decayMCA.x(), decayMCA.y(), decayMCA.z());
+        pw.println();
+
+
+
+
+        return;
+
+    }
+
+    public void endOfData() {
+
+        pw.close();
+        try {
+            fw.close();
+        } catch (IOException ex) {
+            Logger.getLogger(FastTrackAnalysisDriver.class.getName()).log(Level.SEVERE, null, ex);
+        }
+    }
+
+    public void setOutputPlots(String output) {
+    }
+
+    public void setOutputText(String output) {
+        this.outputTextName = output;
+    }
+
+    private double getInvMass(Track track1, StraightLineTrack slt1, Track track2, StraightLineTrack slt2) {
+        double esum = 0.;
+        double pxsum = 0.;
+        double pysum = 0.;
+        double pzsum = 0.;
+        double chargesum = 0.;
+        double me = 0.000511;
+        // Loop over jets
+
+        double p1x = track1.getPX();
+        double p1y = track1.getPY();
+        double p1z = track1.getPZ();
+        double p1mag2 = p1x * p1x + p1y * p1y + p1z * p1z;
+        double e1 = Math.sqrt(p1mag2 + me * me);
+        double dydx1 = slt1.dydx();
+        double dzdx1 = slt1.dzdx();
+        double s1sq = 1 + 1 / (dydx1 * dydx1) + (dzdx1 * dzdx1) / (dydx1 * dydx1);
+        double truep1y = Math.sqrt(p1mag2 / s1sq);
+        if (dydx1 < 0) {
+            truep1y = -truep1y;
+        }
+        double truep1x = truep1y / dydx1;
+        double truep1z = dzdx1 * truep1x;
+
+        double p2x = track2.getPX();
+        double p2y = track2.getPY();
+        double p2z = track2.getPZ();
+        double p2mag2 = p2x * p2x + p2y * p2y + p2z * p2z;
+        double e2 = Math.sqrt(p2mag2 + me * me);
+
+        double dydx2 = slt2.dydx();
+        double dzdx2 = slt2.dzdx();
+        double s2sq = 1 + 1 / (dydx2 * dydx2) + (dzdx2 * dzdx2) / (dydx2 * dydx2);
+        double truep2y = Math.sqrt(p2mag2 / s2sq);
+        if (dydx2 < 0) {
+            truep2y = -truep2y;
+        }
+        double truep2x = truep2y / dydx2;
+        double truep2z = dzdx2 * truep2x;
+
+        pxsum =
+                truep1x + truep2x;
+        pysum =
+                truep1y + truep2y;
+        pzsum =
+                truep1z + truep2z;
+
+        esum =
+                e1 + e2;
+//        double p1dotp2 = p1x * p2x + p1y * p2y + p1z * p2z;
+        double p1dotp2 = truep1x * truep2x + truep1y * truep2y + truep1z * truep2z;
+        double e1e2 = e1 * e2;
+        double invmass = Math.sqrt(2 * me * me + 2 * (e1e2 - p1dotp2));
+        // Compute total momentum and hence event mass
+        double psum = Math.sqrt(pxsum * pxsum + pysum * pysum + pzsum * pzsum);
+        double evtmass = Math.sqrt(esum * esum - psum * psum);
+//        System.out.println("invmass= " + invmass + "; evtmass=" + evtmass);
+        return invmass;
+    }
+
+//find the DOCA to the beamline extrpolating linearly from the reference point
+    private double findDoca(double y, double z, double px, double py, double pz) {
+        double xoca = 0;
+        double sy = py / px;
+        double sz = pz / px;
+        xoca =
+                -(y * sy + z * sz) / (sy * sy + sz + sz);
+        double doca = Math.sqrt(Math.pow(y + sy * xoca, 2) + Math.pow(z + sz * xoca, 2));
+        return doca;
+    }
+
+//find the XOCA to the beamline extrpolating linearly from the reference point
+    private double findXoca(double y, double z, double px, double py, double pz) {
+        double xoca = 0;
+        double sy = py / px;
+        double sz = pz / px;
+        xoca =
+                -(y * sy + z * sz) / (sy * sy + sz + sz);
+        return xoca;
+    }
+
+    private double[] findPoca(double y, double z, double px, double py, double pz) {
+        double poca[] = {0, 0, 0};
+        double sy = py / px;
+        double sz = pz / px;
+        poca[0] = -(y * sy + z * sz) / (sy * sy + sz * sz);
+        poca[1] = y + sy * poca[0];
+        poca[2] = z + sz * poca[0];
+        return poca;
+    }
+
+    private Hep3Vector getV0Momentum(Track track1, StraightLineTrack slt1, Track track2, StraightLineTrack slt2) {
+
+
+        Hep3Vector p1 = getTrueMomentum(track1, slt1);
+        Hep3Vector p2 = getTrueMomentum(track2, slt2);
+        Hep3Vector pV0 = VecOp.add(p1, p2);
+
+        return pV0;
+
+    }
+
+    private double getV0OpeningAngle(Track track1, StraightLineTrack slt1, Track track2, StraightLineTrack slt2) {
+
+        Hep3Vector p1 = getTrueMomentum(track1, slt1);
+        Hep3Vector p2 = getTrueMomentum(track2, slt2);
+
+        return VecOp.dot(p1, p2) / (p1.magnitude() * p2.magnitude());
+
+    }
+
+    private Hep3Vector getTrueMomentum(Track track1, StraightLineTrack slt1) {
+        double[] truep = {0, 0, 0};
+        double me = 0.000511;
+        double p1x = track1.getPX();
+        double p1y = track1.getPY();
+        double p1z = track1.getPZ();
+        double p1mag2 = p1x * p1x + p1y * p1y + p1z * p1z;
+        double e1 = Math.sqrt(p1mag2 + me * me);
+        double dydx1 = slt1.dydx();
+        double dzdx1 = slt1.dzdx();
+        double s1sq = 1 + 1 / (dydx1 * dydx1) + (dzdx1 * dzdx1) / (dydx1 * dydx1);
+        truep[1] = Math.sqrt(p1mag2 / s1sq);
+        if (dydx1 < 0) {
+            truep[1] = -truep[1];
+        }
+        truep[0] = truep[1] / dydx1;
+        truep[2] = dzdx1 * truep[0];
+        return new BasicHep3Vector(truep[0], truep[1], truep[2]);
+    }
+
+    private double getCosAlpha(Hep3Vector vertex, Hep3Vector pV0) {
+        return VecOp.dot(vertex, pV0) / (vertex.magnitude() * pV0.magnitude());
+    }
+
+    private double getMag(double[] vec) {
+        return Math.sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
+    }
+
+    private HelicalTrackStrip getNearestHit(HelicalTrackStrip cl, List<HelicalTrackHit> toththits) {
+        Hep3Vector corigin = cl.origin();
+        Hep3Vector u = cl.u();
+        double umeas = cl.umeas();
+        Hep3Vector uvec = VecOp.mult(umeas, u);
+        Hep3Vector clvec = VecOp.add(corigin, uvec);
+        int layer = cl.layer();
+        HelicalTrackStrip nearest = null;
+        double mindist = 99999999;
+        for (HelicalTrackHit hth : toththits) {
+            HelicalTrackCross cross = (HelicalTrackCross) hth;
+            for (HelicalTrackStrip str : cross.getStrips()) {
+                if (str != cl) {
+                    Hep3Vector strorigin = str.origin();
+                    Hep3Vector stru = str.u();
+                    double strumeas = str.umeas();
+                    Hep3Vector struvec = VecOp.mult(strumeas, stru);
+                    Hep3Vector strvec = VecOp.add(strorigin, struvec);
+                    int strlayer = cl.layer();
+                    if (layer == strlayer && VecOp.sub(clvec, strvec).magnitude() < mindist) {
+                        mindist = VecOp.sub(clvec, strvec).magnitude();
+                        nearest =
+                                str;
+                    }
+
+                }
+            }
+        }
+
+        return nearest;
+    }
+
+    private Double getNearestDistance(HelicalTrackStrip cl, List<HelicalTrackHit> toththits) {
+        Hep3Vector corigin = cl.origin();
+        Hep3Vector u = cl.u();
+        double umeas = cl.umeas();
+        Hep3Vector uvec = VecOp.mult(umeas, u);
+        Hep3Vector clvec = VecOp.add(corigin, uvec);
+        int layer = cl.layer();
+        HelicalTrackStrip nearest = null;
+        Double mindist = 99999999.0;
+        for (HelicalTrackHit hth : toththits) {
+            HelicalTrackCross cross = (HelicalTrackCross) hth;
+            for (HelicalTrackStrip str : cross.getStrips()) {
+                if (str != cl) {
+                    Hep3Vector strorigin = str.origin();
+                    Hep3Vector stru = str.u();
+                    double strumeas = str.umeas();
+                    Hep3Vector struvec = VecOp.mult(strumeas, stru);
+                    Hep3Vector strvec = VecOp.add(strorigin, struvec);
+                    int strlayer = str.layer();
+                    //for some reason (str!=cl) not working anymore...so make sure the distance between hits isn't 0
+                    if (layer == strlayer && VecOp.sub(clvec, strvec).magnitude() < Math.abs(mindist) && VecOp.sub(clvec, strvec).magnitude() != 0) {
+                        mindist = VecOp.sub(clvec, strvec).magnitude();
+                        if (Math.abs(clvec.z()) > Math.abs(strvec.z())) {
+                            mindist = -mindist;
+                        }
+                        nearest = str;
+                    }
+
+                }
+            }
+        }
+        return mindist;
+    }
+
+    private Integer encodeLayers(List<Integer> trackLayers) {
+        Integer hitsEncoded = 0;
+        for (Integer layer : trackLayers) {
+            hitsEncoded += (int) Math.pow(2, layer - 1);
+        }
+        return hitsEncoded;
+    }
+
+    private double getErr(double errSquared) {
+        if (errSquared > 0) {
+            return Math.sqrt(errSquared);
+        } else {
+            return -99;
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
HPSTrackerHit.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/HPSTrackerHit.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/HPSTrackerHit.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,43 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.mgraham;
+
+import org.lcsim.detector.identifier.Identifier;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.base.BaseRawTrackerHit;
+
+/**
+ *
+ * @author mgraham
+ */
+public class HPSTrackerHit extends BaseRawTrackerHit{
+        double t0;
+        double amp;                
+      public HPSTrackerHit(
+    		long id,
+    		int time,
+    		short[] adcValues, double t0, double Amp) {
+    	this.cellId = id;
+    	this.compactId = new Identifier(id);
+    	this.time = time;
+    	this.adcValues = adcValues;
+        this.t0=t0;
+        this.amp=Amp;        
+    }
+      
+      public HPSTrackerHit(
+    		RawTrackerHit rth, double t0, double Amp) {
+    	this.cellId = rth.getCellID();
+    	this.compactId = new Identifier(rth.getCellID());
+    	this.time = rth.getTime();
+    	this.adcValues = rth.getADCValues();
+        this.t0=t0;
+        this.amp=Amp;        
+    }
+      
+      public double getT0(){return t0;}
+       public double getAmp(){return amp;}               
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
HelicalTrackHitResidualsDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/HelicalTrackHitResidualsDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/HelicalTrackHitResidualsDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,328 @@
+package org.lcsim.hps.recon.tracking;
+
+import hep.aida.IDataPointSet;
+import hep.aida.IDataPointSetFactory;
+import hep.aida.IHistogram1D;
+import hep.aida.IPlotter;
+import hep.aida.ref.plotter.PlotterRegion;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.*;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.tracking.SvtUtils;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.hps.users.phansson.TrigRateDriver;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author mgraham
+ */
+public class HelicalTrackHitResidualsDriver extends Driver {
+
+    private AIDA aida = AIDA.defaultInstance();
+    private int totalTracks=0;
+    private int totalTracksProcessed=0;
+    private String outputPlotFileName="";
+    private String trackCollectionName="MatchedTracks";
+    private boolean hideFrame = false;
+    private boolean _debug = false;
+    private boolean _includeMS = true;
+    
+    private AIDAFrame plotterFrame;
+//    ICloud1D[] _h_resz_track_top = new ICloud1D[5];
+//    ICloud1D[] _h_resz_track_bottom = new ICloud1D[5];
+//    ICloud1D[] _h_resy_track_top = new ICloud1D[5];
+//    ICloud1D[] _h_resy_track_bottom = new ICloud1D[5];
+    private IHistogram1D[] _h_resz_track_top = new IHistogram1D[5];
+    private IHistogram1D[] _h_resz_track_bottom = new IHistogram1D[5];
+    private IHistogram1D[] _h_resy_track_top = new IHistogram1D[5];
+    private IHistogram1D[] _h_resy_track_bottom = new IHistogram1D[5];
+    private IDataPointSet dps_hth_y_b;
+    private IDataPointSet dps_hth_y_t;
+    private IDataPointSet dps_hth_z_b;
+    private IDataPointSet dps_hth_z_t;
+    private IPlotter _plotter_resz_top;
+    private IPlotter _plotter_resy_top;
+    private IPlotter _plotter_resz_bottom;
+    private IPlotter _plotter_resy_bottom;
+    private IPlotter _plotter_mean_res;
+    
+       
+    
+    
+    public void setDebug(boolean v) {
+        this._debug = v;
+    }
+    
+    public void setTrackCollectionName(String trackCollectionName) {
+        this.trackCollectionName = trackCollectionName;
+    }
+
+    public void setOutputPlotFileName(String filename) {
+        outputPlotFileName = filename;
+    }
+    
+    public void setHideFrame(boolean hide) {
+        hideFrame = hide;
+    }
+    
+    public void setIncludeMS(boolean inc) {
+        this._includeMS = inc;
+    }
+    
+    public HelicalTrackHitResidualsDriver() {
+    
+    }
+    
+
+    
+    @Override
+    public void detectorChanged(Detector detector) {
+        
+        Hep3Vector IP = new BasicHep3Vector(0., 0., 1.);
+        Hep3Vector _bfield = new BasicHep3Vector(0,0,detector.getFieldMap().getField(IP).y());
+
+        makePlots();
+       
+        
+    }
+    
+   
+
+    
+    @Override
+    public void process(EventHeader event) {
+
+        List<Track> tracklist = new ArrayList<Track>();
+        if(event.hasCollection(Track.class,this.trackCollectionName)) {        
+            tracklist = event.get(Track.class, this.trackCollectionName);
+             if(_debug) {
+                System.out.println(this.getClass().getSimpleName() + ": Number of Tracks = " + tracklist.size());
+             }
+        }
+
+        
+        
+        for (Track track : tracklist) {
+            
+            if(!TrackUtils.isGoodTrack(track, tracklist, EventQuality.Quality.MEDIUM)) {
+                continue;
+            }
+            
+            SeedTrack st = (SeedTrack) track;
+            SeedCandidate seed = st.getSeedCandidate();
+            HelicalTrackFit trk = seed.getHelix();
+            List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+            for(TrackerHit hit : hitsOnTrack) {
+                HelicalTrackHit hth = (HelicalTrackHit) hit;
+                //HelicalTrackCross htc = (HelicalTrackCross) hth;
+                //System.out.printf("%s: getHitMap: hth position before trkdir: (%.3f,%.3f,%.3f)\n",this.getClass().getSimpleName(),hth.x(),hth.y(),hth.z());
+                //htc.setTrackDirection(trk);
+                Map<String,Double> res_track = TrackUtils.calculateTrackHitResidual(hth, trk, this._includeMS);
+                boolean isTop = false;
+                if(SvtUtils.getInstance().isTopLayer((SiSensor)((RawTrackerHit)hth.getRawHits().get(0)).getDetectorElement())) {
+                    isTop = true;
+                }
+                int layer = hth.Layer();
+                if(_debug) System.out.println(this.getClass().getSimpleName() + ": residual for hit at " + hth.toString() + " and layer " + layer);
+                if(layer%2==0) {
+                    System.out.println(this.getClass().getSimpleName() + ": HTH layer is not odd!" + layer);
+                    System.exit(1);
+                }
+                int layer_idx = (layer-1)/2;
+                if(isTop) {
+                    this._h_resz_track_top[layer_idx].fill(res_track.get("resz"));
+                    this._h_resy_track_top[layer_idx].fill(res_track.get("resy"));
+                } else {
+                    this._h_resz_track_bottom[layer_idx].fill(res_track.get("resz"));
+                    this._h_resy_track_bottom[layer_idx].fill(res_track.get("resy"));
+                }
+
+//                if(Math.abs(res_track.get("resy"))>0.02) {
+//                    System.out.println(this.getClass().getSimpleName() + ": this has large y res = " + res_track.get("resy"));
+//                    System.exit(1);
+//                }
+                
+            }
+            
+        }
+        totalTracks++;
+        totalTracksProcessed++;
+
+        
+
+        if(totalTracks%50==0) this.updatePlots();
+
+        
+        
+    }
+
+    public void endOfData() {
+        this.updatePlots();
+        //try {
+            System.out.println(this.getClass().getSimpleName() + ": Total Number of Tracks Found = "+totalTracks);
+            System.out.println(this.getClass().getSimpleName() + ": Total Number of Tracks Processed = "+totalTracksProcessed);
+//        } catch (IOException ex) {
+//            Logger.getLogger(CmpGenToFittedTracksDriver.class.getName()).log(Level.SEVERE, null, ex);
+//        }
+        if (!"".equals(outputPlotFileName))
+        try {
+            aida.saveAs(outputPlotFileName);
+        } catch (IOException ex) {
+            Logger.getLogger(TrigRateDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+        }
+        
+    }
+    
+   
+    private void makePlots() {
+        
+        int nbins = 50;
+        double bins_resz_min[] = {-0.15,-0.4,-0.6,-1.0,-1.5};
+        double bins_resz_max[] = {0.15,0.4,0.6,1.0,1.5};
+        double bins_resy_min[] = {-0.4,-0.6,-1.0,-1.5,-1.8};
+        double bins_resy_max[] = {0.4,0.6,1.0,1.5,1.8};
+        
+        
+        _plotter_resz_top = aida.analysisFactory().createPlotterFactory().create();
+        _plotter_resz_top.setTitle("res z top");
+        _plotter_resz_top.createRegions(5,1);
+        _plotter_resy_top = aida.analysisFactory().createPlotterFactory().create();
+        _plotter_resy_top.setTitle("res y top");
+        _plotter_resy_top.createRegions(5,1);
+        for(int i=1;i<6;++i) {
+//            _h_resz_track_top[i-1] = aida.cloud1D("h_resz_track_top_layer"+i);
+//            _h_resy_track_top[i-1] = aida.cloud1D("h_resy_track_top_layer"+i);
+            _h_resz_track_top[i-1] = aida.histogram1D("h_resz_track_top_layer"+i,nbins,bins_resz_min[i-1],bins_resz_max[i-1]);
+            _h_resy_track_top[i-1] = aida.histogram1D("h_resy_track_top_layer"+i,nbins,bins_resy_min[i-1],bins_resy_max[i-1]);
+            _plotter_resz_top.region(i-1).plot(_h_resz_track_top[i-1]);
+            _plotter_resy_top.region(i-1).plot(_h_resy_track_top[i-1]);
+        }
+        
+        _plotter_resz_bottom = aida.analysisFactory().createPlotterFactory().create();
+        _plotter_resz_bottom.setTitle("res z bottom");
+        _plotter_resz_bottom.createRegions(5,1);
+        _plotter_resy_bottom = aida.analysisFactory().createPlotterFactory().create();
+        _plotter_resy_bottom.setTitle("res y bottom");
+        _plotter_resy_bottom.createRegions(5,1);
+        for(int i=1;i<6;++i) {
+            _h_resz_track_bottom[i-1] = aida.histogram1D("h_resz_track_bottom_layer"+i,nbins,bins_resz_min[i-1],bins_resz_max[i-1]);
+            _h_resy_track_bottom[i-1] = aida.histogram1D("h_resy_track_bottom_layer"+i,nbins,bins_resy_min[i-1],bins_resy_max[i-1]);
+//            _h_resz_track_bottom[i-1] = aida.cloud1D("h_resz_track_bottom_layer"+i);
+//            _h_resy_track_bottom[i-1] = aida.cloud1D("h_resy_track_bottom_layer"+i);
+            _plotter_resz_bottom.region(i-1).plot(_h_resz_track_bottom[i-1]);
+            _plotter_resy_bottom.region(i-1).plot(_h_resy_track_bottom[i-1]);
+        
+        }
+        
+        _plotter_mean_res = aida.analysisFactory().createPlotterFactory().create();
+        _plotter_mean_res.setTitle("Mean res y");
+        _plotter_mean_res.createRegions(2,2);
+        
+        IDataPointSetFactory dpsf = aida.analysisFactory().createDataPointSetFactory(null);
+        
+        dps_hth_y_b = dpsf.create("dps_hth_y_b", "Mean of y residual bottom",2);
+        dps_hth_y_t = dpsf.create("dps_hth_y_t", "Mean of y residual top",2);
+        _plotter_mean_res.region(1).plot(dps_hth_y_b);
+        _plotter_mean_res.region(0).plot(dps_hth_y_t);
+
+        dps_hth_z_b = dpsf.create("dps_hth_z_b", "Mean of z residual bottom",2);
+        dps_hth_z_t = dpsf.create("dps_hth_z_t", "Mean of z residual top",2);
+        _plotter_mean_res.region(3).plot(dps_hth_z_b);
+        _plotter_mean_res.region(2).plot(dps_hth_z_t);
+
+        ((PlotterRegion)_plotter_mean_res.region(0)).getPlot().setAllowUserInteraction(true);
+        ((PlotterRegion) _plotter_mean_res.region(0)).getPlot().setAllowPopupMenus(true);
+        ((PlotterRegion)_plotter_mean_res.region(1)).getPlot().setAllowUserInteraction(true);
+        ((PlotterRegion) _plotter_mean_res.region(1)).getPlot().setAllowPopupMenus(true);
+        
+        
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("HTH Residuals");
+        plotterFrame.addPlotter(_plotter_resz_top);
+        plotterFrame.addPlotter(_plotter_resz_bottom);
+        plotterFrame.addPlotter(_plotter_resy_top);
+        plotterFrame.addPlotter(_plotter_resy_bottom);
+        plotterFrame.addPlotter(_plotter_mean_res);
+        plotterFrame.pack();
+        plotterFrame.setVisible(!hideFrame);
+        
+    }
+    
+    
+    void updatePlots() {
+        dps_hth_y_t.clear();
+        dps_hth_z_t.clear();
+        dps_hth_z_b.clear();
+        dps_hth_z_t.clear();
+        
+         for(int i=1;i<6;++i) {
+                
+            double mean = this._h_resy_track_bottom[i-1].mean();
+            double stddev = this._h_resy_track_bottom[i-1].rms();
+            double N =  this._h_resy_track_bottom[i-1].entries();
+            double error = N >0 ? stddev/Math.sqrt(N) : 0; 
+            dps_hth_y_b.addPoint();
+            dps_hth_y_b.point(i-1).coordinate(1).setValue(mean);
+            dps_hth_y_b.point(i-1).coordinate(1).setErrorPlus(error);
+            dps_hth_y_b.point(i-1).coordinate(0).setValue(i);
+            dps_hth_y_b.point(i-1).coordinate(0).setErrorPlus(0);
+            
+            mean = this._h_resy_track_top[i-1].mean();
+            stddev = this._h_resy_track_top[i-1].rms();
+            N =  this._h_resy_track_top[i-1].entries();
+            error = N >0 ? stddev/Math.sqrt(N) : 0; 
+            dps_hth_y_t.addPoint();
+            dps_hth_y_t.point(i-1).coordinate(1).setValue(mean);
+            dps_hth_y_t.point(i-1).coordinate(1).setErrorPlus(error);
+            dps_hth_y_t.point(i-1).coordinate(0).setValue(i);
+            dps_hth_y_t.point(i-1).coordinate(0).setErrorPlus(0);
+            
+            mean = this._h_resz_track_top[i-1].mean();
+            stddev = this._h_resz_track_top[i-1].rms();
+            N =  this._h_resz_track_top[i-1].entries();
+            error = N >0 ? stddev/Math.sqrt(N) : 0; 
+            dps_hth_z_t.addPoint();
+            dps_hth_z_t.point(i-1).coordinate(1).setValue(mean);
+            dps_hth_z_t.point(i-1).coordinate(1).setErrorPlus(error);
+            dps_hth_z_t.point(i-1).coordinate(0).setValue(i);
+            dps_hth_z_t.point(i-1).coordinate(0).setErrorPlus(0);
+
+            mean = this._h_resz_track_bottom[i-1].mean();
+            stddev = this._h_resz_track_bottom[i-1].rms();
+            N =  this._h_resz_track_bottom[i-1].entries();
+            error = N >0 ? stddev/Math.sqrt(N) : 0; 
+            dps_hth_z_b.addPoint();
+            dps_hth_z_b.point(i-1).coordinate(1).setValue(mean);
+            dps_hth_z_b.point(i-1).coordinate(1).setErrorPlus(error);
+            dps_hth_z_b.point(i-1).coordinate(0).setValue(i);
+            dps_hth_z_b.point(i-1).coordinate(0).setErrorPlus(0);
+            
+            
+           
+            
+
+         }
+        
+        
+        
+        
+    }
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
HitTimePlotter.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/HitTimePlotter.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/HitTimePlotter.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,487 @@
+package org.lcsim.hps.users.mgraham;
+
+import hep.aida.*;
+import hep.physics.vec.Hep3Vector;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.*;
+import org.lcsim.event.base.BaseTrack;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.monitoring.deprecated.Resettable;
+import org.lcsim.hps.readout.ecal.ReadoutTimestamp;
+import org.lcsim.hps.recon.tracking.HPSSVTCalibrationConstants;
+import org.lcsim.hps.recon.tracking.HPSTrack;
+import org.lcsim.hps.recon.vertexing.HelixConverter;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author mgraham
+ */
+public class HitTimePlotter extends Driver implements Resettable {
+
+    private AIDAFrame plotterFrame;
+    private AIDA aida = AIDA.defaultInstance();
+    IPlotter plotter;
+    IPlotter plotter2;
+    IPlotter plotter3;
+    IPlotter plotter4;
+    IPlotter plotter5;
+    IPlotter plotter6;
+    IPlotter plotter7;
+    IAnalysisFactory fac = aida.analysisFactory();
+    private String trackCollectionName = "MatchedTracks";
+    private String outputPlots = null;
+    private Map<String, Integer> sensorRegionMap;
+    private String trackerName = "Tracker";
+    private List<SiSensor> sensors;
+
+    protected void detectorChanged(Detector detector) {
+        aida.tree().cd("/");
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("HPS Tracking Plots");
+        sensors = detector.getSubdetector(trackerName).getDetectorElement().findDescendants(SiSensor.class);
+        sensorRegionMap = new HashMap<String, Integer>();
+        for (SiSensor sensor : sensors) {
+            int region = computePlotterRegion(sensor);
+            sensorRegionMap.put(sensor.getName(), region);
+        }
+
+        plotter = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter.setTitle("Hit Times");
+        IPlotterStyle style = plotter.style();
+        style.dataStyle().fillStyle().setColor("yellow");
+        style.dataStyle().errorBarStyle().setVisible(false);
+        plotter.createRegions(3, 2);
+        plotterFrame.addPlotter(plotter);
+
+        IHistogram1D ecalHT = aida.histogram1D("ECAL Hit Time", 100, 0, 400);
+        IHistogram1D svtHT = aida.histogram1D("SVT Hit Time", 125, -50, 75);
+        IHistogram1D svtHTCorrected = aida.histogram1D("Trigger Corrected SVT Hit Time", 120, -240, -120);
+        IHistogram1D svtHTModCorrected = aida.histogram1D("Module Corrected SVT Hit Time", 120, -50, 70);
+        IHistogram1D svtHTCorrectedZoom = aida.histogram1D("Trigger Corrected SVT Hit Time Zoom", 80, -206, -166);
+        IHistogram1D svtHTModCorrectedZoom = aida.histogram1D("Module Corrected SVT Hit Time Zoom", 80, -20, 20);
+        plotter.region(0).plot(ecalHT);
+        plotter.region(1).plot(svtHT);
+        plotter.region(2).plot(svtHTCorrected);
+        plotter.region(3).plot(svtHTModCorrected);
+            plotter.region(4).plot(svtHTCorrectedZoom);
+        plotter.region(5).plot(svtHTModCorrectedZoom);
+        /*
+         * plotter.setTitle("Momentum"); IPlotterStyle style = plotter.style();
+         * style.dataStyle().fillStyle().setColor("yellow");
+         * style.dataStyle().errorBarStyle().setVisible(false);
+         * plotter.createRegions(2, 3); plotterFrame.addPlotter(plotter);
+         *
+         * IHistogram1D trkPx = aida.histogram1D("Track Momentum (Px)", 25,
+         * -0.25, 0.25); IHistogram1D trkPy = aida.histogram1D("Track Momentum
+         * (Py)", 25, -0.1, 0.1); IHistogram1D trkPz = aida.histogram1D("Track
+         * Momentum (Pz)", 25, 0, 3.5); IHistogram1D trkChi2 =
+         * aida.histogram1D("Track Chi2", 25, 0, 25.0); IHistogram1D xAtConvert
+         * = aida.histogram1D("X (mm) @ Converter", 50, -50, 50); IHistogram1D
+         * yAtConvert = aida.histogram1D("Y (mm) @ Converter", 50, -20, 20);
+         * plotter.region(0).plot(trkPx); plotter.region(1).plot(trkPy);
+         * plotter.region(2).plot(trkPz); plotter.region(3).plot(trkChi2);
+         * plotter.region(4).plot(xAtConvert);
+         * plotter.region(5).plot(yAtConvert);
+         */
+
+        plotter2 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter2.setTitle("Inner Tracker");
+        IPlotterStyle style2 = plotter2.style();
+        style2.dataStyle().fillStyle().setColor("yellow");
+        style2.dataStyle().errorBarStyle().setVisible(false);
+        plotter2.createRegions(6, 2);
+        plotterFrame.addPlotter(plotter2);
+
+        plotter3 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter3.setTitle("Outer Tracker");
+        plotter3.setStyle(style2);
+        plotter3.createRegions(6, 4);
+        plotterFrame.addPlotter(plotter3);
+
+        plotter4 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter4.setTitle("Corrected Times:  Inner Tracker");
+        IPlotterStyle style4 = plotter4.style();
+        style4.dataStyle().fillStyle().setColor("yellow");
+        style4.dataStyle().errorBarStyle().setVisible(false);
+        plotter4.createRegions(6, 2);
+        plotterFrame.addPlotter(plotter4);
+
+        plotter5 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter5.setTitle("Outer Tracker");
+        plotter5.setStyle(style2);
+        plotter5.createRegions(6, 4);
+        plotterFrame.addPlotter(plotter5);
+
+
+        int region = 0;
+        for (SiSensor sensor : sensors) {
+            IHistogram1D svtTimePlot = aida.histogram1D(sensor.getName() + "_Time", 60, -200, -170);
+            IHistogram1D svtCorTimePlot = aida.histogram1D(sensor.getName() + "_CorrectedTime", 100, -100, 100);
+//            int region = sensorRegionMap.get(sensor.getName());  // this doesn't work anymore...
+            IIdentifierHelper helper = sensor.getIdentifierHelper();
+            IIdentifier id = sensor.getIdentifier();
+
+            int layer = helper.getValue(id, "layer"); // 1-12; axial layers are odd layers; stereo layers are even
+            int module = helper.getValue(id, "module");
+
+            svtTimePlot.setTitle("Layer " + layer + " Module " + module);
+            if (region < 12) {
+                plotter2.region(region).plot(svtTimePlot);
+                plotter4.region(region).plot(svtCorTimePlot);
+                region++;
+            } else {
+                plotter3.region(region - 12).plot(svtTimePlot);
+                plotter5.region(region - 12).plot(svtCorTimePlot);
+                region++;
+            }
+        }
+
+
+        plotter6 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter6.setTitle("Tracks");
+        plotter6.setStyle(style2);
+        plotter6.createRegions(2, 2);
+        plotterFrame.addPlotter(plotter6);
+        IHistogram1D px = aida.histogram1D("Track Momentum(Px)", 50, -0.2, 0.2);
+        IHistogram1D py = aida.histogram1D("Track Momentum(Py)", 50, -0.2, 0.2);
+        IHistogram1D pz = aida.histogram1D("Track Momentum(Pz)", 50, 0, 2.2);
+        IHistogram1D chi2 = aida.histogram1D("TrackChi2", 50, 0, 25);
+        plotter6.region(0).plot(px);
+        plotter6.region(1).plot(py);
+        plotter6.region(2).plot(pz);
+        plotter6.region(3).plot(chi2);
+
+
+        plotter7 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter7.setTitle("Per Event");
+        plotter7.setStyle(style2);
+        plotter7.createRegions(2, 2);
+        plotterFrame.addPlotter(plotter7);
+
+        IHistogram1D nclus = aida.histogram1D("Strip Clusters per Event", 100, 0, 99);
+        IHistogram1D nhth = aida.histogram1D("Stereo Hits per Event", 100, 0, 99);
+        IHistogram1D ntrk = aida.histogram1D("Tracks per Event", 40, 0, 39);
+
+        plotter7.region(0).plot(nclus);
+        plotter7.region(1).plot(nhth);
+        plotter7.region(2).plot(ntrk);
+
+
+
+        plotterFrame.pack();
+        plotterFrame.setVisible(true);
+    }
+
+    public void process(EventHeader event) {
+        aida.tree().cd("/");
+
+        List<TrackerHit> trackerHits = event.get(TrackerHit.class, "StripClusterer_SiTrackerHitStrip1D");
+        List<CalorimeterHit> ecalHits = event.get(CalorimeterHit.class, "EcalCalHits");
+
+
+        List<HelicalTrackHit> hth = event.get(HelicalTrackHit.class, "HelicalTrackHits");
+        //        System.out.println("Event with ECal timestamp " + ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_ECAL, event)
+//                + ", SVT timestamp " + ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_TRACKER, event)
+//                + ", Trigger timestamp " + ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_TRIGGER, event));
+        double t0Ecal = ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_ECAL, event);
+        double t0Svt = ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_TRACKER, event);
+        double t0Trig = ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_TRIGGER, event);
+        for (CalorimeterHit hit : ecalHits) {
+            double cor = hit.getTime() + (t0Ecal - t0Trig);
+            aida.histogram1D("ECAL Hit Time").fill(hit.getTime());
+//            aida.histogram1D("Trigger Corrected ECAL Hit Time").fill(cor);
+//            System.out.println("Ecal: " + (hit.getTime()) + ";  Corrected = " + cor);
+        }
+        for (TrackerHit hit : trackerHits) {
+
+            IIdentifierHelper helper = ((RawTrackerHit) hit.getRawHits().get(0)).getIdentifierHelper();
+            IIdentifier id = ((RawTrackerHit) hit.getRawHits().get(0)).getIdentifier();
+            int layer = helper.getValue(id, "layer"); // 1-10; axial layers are odd layers; stereo layers are even
+            int module = helper.getValue(id, "module"); // 0-1; module number is top or bottom
+
+            String sensorName = ((RawTrackerHit) hit.getRawHits().get(0)).getDetectorElement().getName();
+            double cor = hit.getTime() + (t0Svt - t0Trig);
+            double corMod = cor - getT0Shift(layer, module);
+            aida.histogram1D("SVT Hit Time").fill(hit.getTime());
+            aida.histogram1D("Trigger Corrected SVT Hit Time").fill(cor);
+            aida.histogram1D("Module Corrected SVT Hit Time").fill(corMod);
+             aida.histogram1D("Trigger Corrected SVT Hit Time Zoom").fill(cor);
+            aida.histogram1D("Module Corrected SVT Hit Time Zoom").fill(corMod);
+            aida.histogram1D(sensorName + "_Time").fill(cor);
+            aida.histogram1D(sensorName + "_CorrectedTime").fill(corMod);
+
+            //System.out.println("Svt: " + (hit.getTime()) + ";  Corrected = " + cor+";  Module Corrected = " + corMod);
+        }
+        if (!event.hasCollection(Track.class, trackCollectionName)) {
+            return;
+        }
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+
+        for (Track trk : tracks) {
+            aida.histogram1D("Track Momentum(Px)").fill(trk.getPY());
+            aida.histogram1D("Track Momentum(Py)").fill(trk.getPZ());
+            aida.histogram1D("Track Momentum(Pz)").fill(trk.getPX());
+            aida.histogram1D("TrackChi2").fill(trk.getChi2());
+        }
+
+        aida.histogram1D("Strip Clusters per Event").fill(trackerHits.size());
+        aida.histogram1D("Stereo Hits per Event").fill(hth.size());
+        aida.histogram1D("Tracks per Event").fill(tracks.size());
+
+    }
+
+    private int computePlotterRegion(SiSensor sensor) {
+
+        IIdentifierHelper helper = sensor.getIdentifierHelper();
+        IIdentifier id = sensor.getIdentifier();
+
+        int layer = helper.getValue(id, "layer"); // 1-12; axial layers are odd layers; stereo layers are even
+        int module = helper.getValue(id, "module"); // 0-1; module number is top (evens) or bottom (odds)
+        int region = -99;
+        // Compute the sensor's x and y grid coordinates and then translate to region number.
+        int ix, iy;
+        if (layer < 7) {
+            ix = (layer - 1) / 2;
+            iy = 0;
+            if (module > 0) {
+                iy += 2;
+            }
+            if (layer % 2 == 0) {
+                iy += 1;
+            }
+            region = ix * 2 + iy;
+        } else {
+            ix = (layer - 7) / 2;
+            iy = module;
+
+            region = ix * 4 + iy;
+            region += 100;
+        }
+        System.out.println(sensor.getName() + "; lyr=" + layer + "; mod=" + module + " -> xy[" + ix + "][" + iy + "] -> reg=" + region);
+
+        return region;
+    }
+
+    @Override
+    public void reset() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    public void setOutputPlots(String output) {
+        this.outputPlots = output;
+    }
+
+    public void endOfData() {
+        System.out.println("Output");
+        IFitFactory fitFactory = fac.createFitFactory();
+        IFitter fitter = fitFactory.createFitter("chi2");
+
+        for (SiSensor sensor : sensors) {
+            IHistogram1D svtTimePlot = aida.histogram1D(sensor.getName() + "_Time", 150, -250, -100);
+            IHistogram1D svtCorTimePlot = aida.histogram1D(sensor.getName() + "_CorrectedTime", 100, -100, 100);
+//            int region = sensorRegionMap.get(sensor.getName());  // this doesn't work anymore...
+            IIdentifierHelper helper = sensor.getIdentifierHelper();
+            IIdentifier id = sensor.getIdentifier();
+
+            int layer = helper.getValue(id, "layer"); // 1-12; axial layers are odd layers; stereo layers are even
+            int module = helper.getValue(id, "module");
+            IHistogram1D hist = aida.histogram1D(sensor.getName() + "_Time");
+            System.out.println("Number of entries = " + hist.allEntries());
+            IFitResult result = fitter.fit(hist, "g");
+
+//            System.out.println(sensor.getName() + " Peak Position = " + getPeakPosition(aida.histogram1D(sensor.getName() + "_Time")));
+            System.out.println(sensor.getName() + " " + result.fittedParameterNames()[0] + " = " + result.fittedParameters()[0] + " +/- " + result.errors()[0]);
+            System.out.println(sensor.getName() + " " + result.fittedParameterNames()[1] + " = " + result.fittedParameters()[1] + " +/- " + result.errors()[1]);
+            System.out.println(sensor.getName() + " " + result.fittedParameterNames()[2] + " = " + result.fittedParameters()[2] + " +/- " + result.errors()[2]);
+
+        }
+        
+          IHistogram1D hist = aida.histogram1D("Trigger Corrected SVT Hit Time Zoom");
+           System.out.println("Number of entries = " + hist.allEntries());
+            IFitResult result = fitter.fit(hist, "g");
+
+//            System.out.println(sensor.getName() + " Peak Position = " + getPeakPosition(aida.histogram1D(sensor.getName() + "_Time")));
+            System.out.println("Trigger Corrected SVT Hit Time Zoom "  + result.fittedParameterNames()[0] + " = " + result.fittedParameters()[0] + " +/- " + result.errors()[0]);
+            System.out.println("Trigger Corrected SVT Hit Time Zoom "  + result.fittedParameterNames()[1] + " = " + result.fittedParameters()[1] + " +/- " + result.errors()[1]);
+            System.out.println("Trigger Corrected SVT Hit Time Zoom "  + result.fittedParameterNames()[2] + " = " + result.fittedParameters()[2] + " +/- " + result.errors()[2]);
+
+           hist = aida.histogram1D("Module Corrected SVT Hit Time Zoom");
+           System.out.println("Number of entries = " + hist.allEntries());
+             result = fitter.fit(hist, "g");
+
+//            System.out.println(sensor.getName() + " Peak Position = " + getPeakPosition(aida.histogram1D(sensor.getName() + "_Time")));
+            System.out.println("Module Corrected SVT Hit Time Zoom "  + result.fittedParameterNames()[0] + " = " + result.fittedParameters()[0] + " +/- " + result.errors()[0]);
+            System.out.println("Module Corrected SVT Hit Time Zoom "  + result.fittedParameterNames()[1] + " = " + result.fittedParameters()[1] + " +/- " + result.errors()[1]);
+            System.out.println("Module Corrected SVT Hit Time Zoom "  + result.fittedParameterNames()[2] + " = " + result.fittedParameters()[2] + " +/- " + result.errors()[2]);
+
+        
+        if (outputPlots != null) {
+            try {
+                aida.saveAs(outputPlots);
+            } catch (IOException ex) {
+                Logger.getLogger(HitTimePlotter.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+    }
+
+    private double getPeakPosition(IHistogram1D hist) {
+        int nbins = hist.axis().bins();
+        int maxBin = -99;
+        int max = -99;
+        for (int i = 0; i < nbins; i++) {
+            if (hist.binEntries(i) > max) {
+                maxBin = i;
+                max = hist.binEntries(i);
+            }
+        }
+        return hist.binMean(maxBin);
+
+    }
+
+    private double getT0Shift(int layer, int module) {
+        double value = 0;
+        switch (module) {
+            case 0:
+                switch (layer) {
+                    case 1:
+                        value = -186.1;
+                        break;
+                    case 2:
+                        value = -186.1;
+                        break;
+                    case 3:
+                        value = -185.8;
+                        break;
+                    case 4:
+                        value = -185.9;
+                        break;
+                    case 5:
+                        value = -185.8;
+                        break;
+                    case 6:
+                        value = -185.8;
+                        break;
+                    case 7:
+                        value = -185.8;
+                        break;
+                    case 8:
+                        value = -185.9;
+                        break;
+                    case 9:
+                        value = -185.8;
+                        break;
+                    case 10:
+                        value = -185.8;
+                        break;
+                    case 11:
+                        value = -185.6;
+                        break;
+                    case 12:
+                        value = -186.0;
+                        break;
+                }
+                break;
+            case 1:
+                switch (layer) {
+                    case 1:
+                        value = -185.6;
+                        break;
+                    case 2:
+                        value = -185.3;
+                        break;
+                    case 3:
+                        value = -185.9;
+                        break;
+                    case 4:
+                        value = -185.7;
+                        break;
+                    case 5:
+                        value = -185.6;
+                        break;
+                    case 6:
+                        value = -185.9;
+                        break;
+                    case 7:
+                        value = -185.8;
+                        break;
+                    case 8:
+                        value = -186.1;
+                        break;
+                    case 9:
+                        value = -186.0;
+                        break;
+                    case 10:
+                        value = -185.9;
+                        break;
+                    case 11:
+                        value = -185.9;
+                        break;
+                    case 12:
+                        value = -186.1;
+                        break;
+                }
+                break;
+            case 2:
+                switch (layer) {
+                    case 7:
+                        value = -185.7;
+                        break;
+                    case 8:
+                        value = -185.7;
+                        break;
+                    case 9:
+                        value = -185.9;
+                        break;
+                    case 10:
+                        value = -186.0;
+                        break;
+                    case 11:
+                        value = -185.8;
+                        break;
+                    case 12:
+                        value = -185.9;
+                        break;
+                }
+                break;
+            case 3:
+                switch (layer) {
+                    case 7:
+                        value = -185.5;
+                        break;
+                    case 8:
+                        value = -185.6;
+                        break;
+                    case 9:
+                        value = -185.5;
+                        break;
+                    case 10:
+                        value = -185.5;
+                        break;
+                    case 11:
+                        value = -186.6;
+                        break;
+                    case 12:
+                        value = -186.7;
+                        break;
+                }
+                break;
+        }
+        return value;
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
JasAnalysisDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/JasAnalysisDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/JasAnalysisDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,1017 @@
+package org.lcsim.hps.users.mgraham;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogramFactory;
+import hep.aida.IProfile1D;
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+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.SimTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelixParamCalculator;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.hps.recon.vertexing.BFitter;
+import org.lcsim.hps.recon.vertexing.BilliorTrack;
+import org.lcsim.hps.recon.vertexing.BilliorVertex;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.hps.recon.tracking.FindableTrack;
+import org.lcsim.hps.recon.tracking.TrackAnalysis;
+import org.lcsim.hps.recon.vertexing.*;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.spacegeom.SpacePoint;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+
+ @author partridge
+ */
+public class JasAnalysisDriver extends Driver {
+
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    private IProfile1D peffFindable;
+    private IProfile1D thetaeffFindable;
+    private IProfile1D phieffFindable;
+    private IProfile1D ctheffFindable;
+    private IProfile1D d0effFindable;
+    private IProfile1D z0effFindable;
+    private IProfile1D peffElectrons;
+    private IProfile1D thetaeffElectrons;
+    private IProfile1D phieffElectrons;
+    private IProfile1D ctheffElectrons;
+    private IProfile1D d0effElectrons;
+    private IProfile1D z0effElectrons;
+    private IProfile1D peffAxial;
+    private IProfile1D thetaeffAxial;
+    private IProfile1D phieffAxial;
+    private IProfile1D ctheffAxial;
+    private IProfile1D d0effAxial;
+    private IProfile1D z0effAxial;
+    private IProfile1D VxEff;
+    private IProfile1D VyEff;
+    private IProfile1D VzEff;
+    private IProfile1D VxEffFindable;
+    private IProfile1D VyEffFindable;
+    private IProfile1D VzEffFindable;
+    public String outputPlots = "myplots.aida";
+    Map<String, IProfile1D> clsizeMap = new HashMap<String, IProfile1D>();
+    String[] detNames = {"Tracker"};
+    Integer[] nlayers = {8};
+    int trk_count = 0;
+    int nevt = 0;
+    int _nmcTrk = 0;
+    double _nrecTrk = 0;
+    double phiTrkCut = 0.3;
+    double cosThTrkCutMax = 0.2;
+    double cosThTrkCutMin = 0.05;
+    double pTrkCut = 0.5; //GeV
+    double d0TrkCut = 2.0; //mm
+    double z0TrkCut = 2.0; //mm
+    double etaTrkCut = 2.5;
+    int totelectrons = 0;
+    double foundelectrons = 0;
+    int findableelectrons = 0;
+    int findableTracks = 0;
+    double foundTracks = 0;
+    double xref = 0.0; //mm
+    public String outputTextName = "myevents.txt";
+    FileWriter fw;
+    PrintWriter pw;
+    boolean isBeamConstrain = false;
+    double[] beamsize = {0.001, 0.02, 0.02};
+
+    public JasAnalysisDriver(int layers) {
+        //  Define the efficiency histograms
+        IHistogramFactory hf = aida.histogramFactory();
+
+
+        peffFindable = hf.createProfile1D("Findable Efficiency vs p", "", 50, 0., 2.2);
+        thetaeffFindable = hf.createProfile1D("Findable Efficiency vs theta", "", 20, 80, 100);
+        phieffFindable = hf.createProfile1D("Findable Efficiency vs phi", "", 25, -0.25, 0.25);
+        ctheffFindable = hf.createProfile1D("Findable Efficiency vs cos(theta)", "", 25, -0.25, 0.25);
+        d0effFindable = hf.createProfile1D("Findable Efficiency vs d0", "", 50, -2., 2.);
+        z0effFindable = hf.createProfile1D("Findable Efficiency vs z0", "", 50, -2., 2.);
+
+        peffElectrons = hf.createProfile1D("Electrons Efficiency vs p", "", 50, 0., 2.2);
+        thetaeffElectrons = hf.createProfile1D("Electrons Efficiency vs theta", "", 20, 80, 100);
+        phieffElectrons = hf.createProfile1D("Electrons Efficiency vs phi", "", 25, -0.25, 0.25);
+        ctheffElectrons = hf.createProfile1D("Electrons Efficiency vs cos(theta)", "", 25, -0.25, 0.25);
+        d0effElectrons = hf.createProfile1D("Electrons Efficiency vs d0", "", 20, -1., 1.);
+        z0effElectrons = hf.createProfile1D("Electrons Efficiency vs z0", "", 20, -1., 1.);
+
+        peffAxial = hf.createProfile1D("Axial Efficiency vs p", "", 50, 0., 2.2);
+        thetaeffAxial = hf.createProfile1D("Axial Efficiency vs theta", "", 20, 80, 100);
+        phieffAxial = hf.createProfile1D("Axial Efficiency vs phi", "", 25, -0.25, 0.25);
+        ctheffAxial = hf.createProfile1D("Axial Efficiency vs cos(theta)", "", 25, -0.25, 0.25);
+        d0effAxial = hf.createProfile1D("Axial Efficiency vs d0", "", 20, -1., 1.);
+        z0effAxial = hf.createProfile1D("Axial Efficiency vs z0", "", 20, -1., 1.);
+
+        VxEff = hf.createProfile1D("Aprime Efficiency vs Vx", "", 25, 0., 50.);
+        VyEff = hf.createProfile1D("Aprime Efficiency vs Vy", "", 40, -0.2, 0.2);
+        VzEff = hf.createProfile1D("Aprime Efficiency vs Vz", "", 40, -0.2, 0.2);
+
+        VxEffFindable = hf.createProfile1D("Aprime Efficiency vs Vx: Findable", "", 25, 0., 50.);
+        VyEffFindable = hf.createProfile1D("Aprime Efficiency vs Vy: Findable", "", 40, -0.2, 0.2);
+        VzEffFindable = hf.createProfile1D("Aprime Efficiency vs Vz: Findable", "", 40, -0.2, 0.2);
+        nlayers[0] = layers;
+    }
+
+    public void process(
+            EventHeader event) {
+        if (nevt == 0)
+            try {
+//open things up
+                fw = new FileWriter(outputTextName);
+                pw = new PrintWriter(fw);
+            } catch (IOException ex) {
+                Logger.getLogger(FastTrackAnalysisDriver.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        //  Increment the event counter
+        nevt++;
+        List<RawTrackerHit> rawHits = event.get(RawTrackerHit.class, "RawTrackerHitMaker_RawTrackerHits");
+        List<SiTrackerHitStrip1D> stripHits = event.get(SiTrackerHitStrip1D.class, "StripClusterer_SiTrackerHitStrip1D");
+
+
+        Hep3Vector IP = new BasicHep3Vector(0., 0., 0.);
+
+        //  Get the magnetic field
+//        double bfield = event.getDetector().getFieldMap().getField(IP).z();
+        double bfield = 0.5;
+
+//        List<HelicalTrackHit> hthits = event.get(HelicalTrackHit.class, "MatchedHTHits");
+//        String sfile = StrategyXMLUtils.getDefaultStrategiesPrefix() + "DarkPhoton-Final.xml";
+//        String strategyPrefix = "/nfs/sulky21/g.ec.u12/users/mgraham/AtlasUpgrade/hps-java/src/main/resources/";
+//        String sfile = "DarkPhoton-Final.xml";
+//        List<SeedStrategy> slist = StrategyXMLUtils.getStrategyListFromResource(sfile);
+//        List<SeedStrategy> slist = StrategyXMLUtils.getStrategyListFromFile(new File(strategyPrefix + sfile));
+        List<HelicalTrackHit> toththits = event.get(HelicalTrackHit.class, "HelicalTrackHits");
+//        List<HelicalTrackHit> remaininghits = event.get(HelicalTrackHit.class, "RemainingHits");
+
+        //  Create a relational table that maps TrackerHits to MCParticles
+        RelationalTable hittomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        List<LCRelation> mcrelations = event.get(LCRelation.class, "HelicalTrackMCRelations");
+
+        for (LCRelation relation : mcrelations) {
+            if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+                hittomc.add(relation.getFrom(), relation.getTo());
+            }
+        }
+
+//        RelationalTable hittomcRemaining = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+//        List<LCRelation> mcrelations = event.get(LCRelation.class, "HelicalTrackMCRelations");
+//        List<LCRelation> mcrelationsRemaining = event.get(LCRelation.class, "RemainingMCRelations");
+//        for (LCRelation relation : mcrelationsRemaining)
+//            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
+//                hittomcRemaining.add(relation.getFrom(), relation.getTo());
+
+        //  Instantiate the class that determines if a track is "findable"
+        FindableTrack findable = new FindableTrack(event);
+
+        //  Create a map between tracks and the associated MCParticle
+//        List<Track> tracklist = event.getTracks();
+        List<Track> tracklist = event.get(Track.class, "MatchedTracks");
+        //      List<Track> lltracklist = event.get(Track.class, "LLTracks");
+
+        RelationalTable trktomcAxial = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        aida.cloud1D("Matched Tracks per Event").fill(tracklist.size());
+//        aida.cloud1D("Long Lived Tracks per Event").fill(lltracklist.size());
+        aida.cloud1D("HelicalTrackHits per Event").fill(toththits.size());
+        RelationalTable trktomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+//        RelationalTable trktomcLL = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        //       tracklist.addAll(lltracklist);
+
+        RelationalTable mcHittomcP = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        //  Get the collections of SimTrackerHits
+        List<List<SimTrackerHit>> simcols = event.get(SimTrackerHit.class);
+
+        //  Loop over the SimTrackerHits and fill in the relational table
+        for (List<SimTrackerHit> simlist : simcols) {
+            for (SimTrackerHit simhit : simlist) {
+                if (simhit.getMCParticle() != null) {
+                    mcHittomcP.add(simhit, simhit.getMCParticle());
+                }
+            }
+        }
+
+
+        String occDir = "occupancyPlots/";
+
+        for (SiTrackerHitStrip1D stripCluster : stripHits) {
+
+
+            Set<MCParticle> mcparts = stripCluster.getMCParticles();
+
+            List<RawTrackerHit> rthList = stripCluster.getRawHits();
+            int nhits = rthList.size();
+
+            aida.cloud1D(occDir + "associated MC Particles").fill(mcparts.size());
+            aida.cloud1D(occDir + " cluster size").fill(nhits);
+
+            if (mcparts.size() == 1)
+                aida.cloud1D(occDir + " cluster size MC Particles = 1").fill(nhits);
+            if (mcparts.size() == 2)
+                aida.cloud1D(occDir + " cluster size MC Particles = 2").fill(nhits);
+        }
+
+        Map<Track, TrackAnalysis> tkanalMap = new HashMap<Track, TrackAnalysis>();
+        Map<Track, StraightLineTrack> sltMap = new HashMap<Track, StraightLineTrack>();
+        Map<Track, BilliorTrack> btMap = new HashMap<Track, BilliorTrack>();
+        String trackdir = "TrackInfo/";
+        //  Analyze the tracks in the event
+        aida.histogram1D("number of tracks", 11, 0, 10).fill(tracklist.size());
+        for (Track track : tracklist) {
+
+            //  Calculate the track pT and cos(theta)
+            double d0 = track.getTrackParameter(HelicalTrackFit.dcaIndex);
+            double z0 = track.getTrackParameter(HelicalTrackFit.z0Index);
+            double phi0 = track.getTrackParameter(HelicalTrackFit.phi0Index);
+            double slope = track.getTrackParameter(HelicalTrackFit.slopeIndex);
+            double curve = track.getTrackParameter(HelicalTrackFit.curvatureIndex);
+            double d0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.dcaIndex, HelicalTrackFit.dcaIndex));
+            double z0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.z0Index, HelicalTrackFit.z0Index));
+            double phi0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.phi0Index, HelicalTrackFit.phi0Index));
+            double slopeErr = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.slopeIndex, HelicalTrackFit.slopeIndex));
+            double curveErr = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.curvatureIndex, HelicalTrackFit.curvatureIndex));
+            double chisq = track.getChi2();
+            //plot the helix parameters
+            aida.cloud1D("d0").fill(d0);
+            aida.cloud1D("z0").fill(z0);
+            aida.cloud1D("phi0").fill(phi0);
+            aida.cloud1D("slope").fill(slope);
+            aida.cloud1D("curve").fill(curve);
+            aida.cloud1D("chi2").fill(chisq);
+
+            double mom[] = track.getMomentum();
+
+            SeedTrack stEle = (SeedTrack) track;
+            SeedCandidate seedEle = stEle.getSeedCandidate();
+            HelicalTrackFit ht = seedEle.getHelix();
+
+            TrackAnalysis tkanal = new TrackAnalysis(track, hittomc);
+            tkanalMap.put(track, tkanal);
+
+            BilliorTrack bt = new BilliorTrack(ht);
+//            System.out.println(bt.toString());
+//            System.out.println(ht.toString());
+            btMap.put(track, bt);
+
+            double eps = bt.eps();
+            double z0B = bt.z0();
+            double phi0B = bt.phi0();
+            double theta = bt.theta();
+            double curveB = bt.curvature();
+            double epsErr = bt.getEpsError();
+            double z0BErr = bt.getZ0Error();
+            double phi0BErr = bt.getPhi0Error();
+            double thetaErr = bt.getThetaError();
+            double curveBErr = bt.getCurveError();
+
+
+            double s = HelixUtils.PathLength(ht, (HelicalTrackHit) track.getTrackerHits().get(0));
+            double y1 = HelixUtils.PointOnHelix(ht, s).y();
+            double z1 = HelixUtils.PointOnHelix(ht, s).z();
+
+            int nhits = tkanal.getNHitsNew();
+            double purity = tkanal.getPurityNew();
+            int nbad = tkanal.getNBadHitsNew();
+            int nbadAxial = tkanal.getNBadAxialHits();
+            int nbadZ = tkanal.getNBadZHits();
+            int nAxial = tkanal.getNAxialHits();
+            int nZ = tkanal.getNZHits();
+            List<Integer> badLayers = tkanal.getBadHitList();
+
+            aida.cloud1D(trackdir + "Mis-matched hits for all tracks").fill(nbad);
+            aida.cloud1D(trackdir + "purityNew for all tracks").fill(purity);
+            aida.cloud1D(trackdir + "Bad Axial hits for all tracks").fill(nbadAxial);
+            aida.cloud1D(trackdir + "Bad Z hits for all tracks").fill(nbadZ);
+            aida.cloud1D(trackdir + "Number of Axial hits for all tracks").fill(nAxial);
+            aida.cloud1D(trackdir + "Number of Z hits for all tracks").fill(nZ);
+
+            for (Integer bhit : badLayers) {
+                aida.histogram1D(trackdir + "Layer of Bad Hit", nlayers[0], 1, nlayers[0] + 1).fill(bhit);
+            }
+
+            //  Generate a normalized histogram after 1000 events
+            trk_count++;
+
+
+            //  Now analyze MC Particles on this track
+            MCParticle mcp = tkanal.getMCParticle();
+            if (mcp != null) {
+
+                //  Create a map between the tracks found and the assigned MC particle
+                trktomc.add(track, tkanal.getMCParticle());
+
+                //  Calculate the MC momentum and polar angle
+                Hep3Vector Pmc = mcp.getMomentum();
+                double pxmc = Pmc.x();
+                double pymc = Pmc.y();
+                double pzmc = Pmc.z();
+                double ptmc = Math.sqrt(pxmc * pxmc + pymc * pymc);
+                double pmc = Math.sqrt(ptmc * ptmc + pzmc * pzmc);
+                double pxtk = track.getPX();
+                double pytk = track.getPY();
+                double pztk = track.getPZ();
+                double pttk = Math.sqrt(pxtk * pxtk + pytk * pytk);
+                double ptk = Math.sqrt(pttk * pttk + pztk * pztk);
+
+
+
+                //  Calculate the helix parameters for this MC particle and pulls in pT, d0
+                HelixParamCalculator helix = new HelixParamCalculator(mcp, bfield);
+
+
+                double d0mc = helix.getDCA();
+                double z0mc = helix.getZ0();
+                double phi0mc = helix.getPhi0();
+                double slopemc = helix.getSlopeSZPlane();
+                double curvemc = 1 / helix.getRadius();
+                double pinvresid = (1 / ptk - 1 / pmc);
+                double presid = (ptk - pmc);
+                double z0newMC = z0mc;
+                double y0newMC = d0mc;
+                aida.histogram1D(trackdir + "d0 Pull", 200, -8, 8).fill((d0 - d0mc) / d0Err);
+                aida.histogram1D(trackdir + "z0 Pull", 200, -8, 8).fill((z0 - z0mc) / z0Err);
+                aida.histogram1D(trackdir + "phi0 Pull", 200, -8, 8).fill((phi0 - phi0mc) / phi0Err);
+                aida.histogram1D(trackdir + "slope Pull", 200, -8, 8).fill((slope - slopemc) / slopeErr);
+                aida.histogram1D(trackdir + "curvature Pull", 200, -8, 8).fill((curve - curvemc) / curveErr);
+
+
+                double epsmc = -d0mc;
+                double thetamc = Math.PI / 2 - Math.atan(slopemc);
+
+
+                aida.histogram1D(trackdir + "Billior eps Pull", 200, -8, 8).fill((eps - epsmc) / epsErr);
+                aida.histogram1D(trackdir + "Billior z0 Pull", 200, -8, 8).fill((z0B - z0mc) / z0BErr);
+                aida.histogram1D(trackdir + "Billior phi0 Pull", 200, -8, 8).fill((phi0B - phi0mc) / phi0BErr);
+                aida.histogram1D(trackdir + "Billior theta Pull", 200, -8, 8).fill((theta - thetamc) / thetaErr);
+                aida.histogram1D(trackdir + "Billior curvature Pull", 200, -8, 8).fill((curveB - curvemc) / curveBErr);
+
+                BasicHep3Vector axial = new BasicHep3Vector();
+                axial.setV(0, 1, 0);
+                String hitdir = "HitsOnTrack/";
+                List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+                MCParticle bestmcp = tkanal.getMCParticleNew();
+
+                String tkresid = "TrackResiduals/";
+
+                int ndaug = 0;
+                if (bestmcp != null) {
+                    ndaug = bestmcp.getDaughters().size();
+                }
+                int imain = 0;
+            }
+        }
+
+
+        // Fitting procedure: Creat BilloirFitter. Pass two matched tracks from track
+        // list into the fitter with the Space Point set as the Interaction Point.
+        // BilloirFitter returns a Vertex object
+
+        BFitter bFit = new BFitter(bfield);
+        SpacePoint SP = new SpacePoint(IP);
+        List<Track> vlist = new ArrayList<Track>();
+        List<BilliorTrack> btlist = new ArrayList<BilliorTrack>();
+        for (Track track1 : tracklist) {
+            for (Track track2 : tracklist) {
+                if (track1 != track2 && track1.getCharge() > 0 && track2.getCharge() < 0) {
+                    /*
+                     vlist.clear(); vlist.add(track1); vlist.add(track2); Vertex
+                     vtx = bFit.fit(vlist, SP, isBeamConstrain);
+                     System.out.println(vtx.toString()); double vtxChi2 =
+                     vtx._chi2; double[] vtxPos = vtx._xyzf;
+                     aida.histogram1D("Vertex Chi2", 100, 0,
+                     1000).fill(vtxChi2); aida.histogram1D("Vertex X", 100, -20,
+                     50).fill(vtxPos[0]); aida.histogram1D("Vertex Y", 100, -1,
+                     1).fill(vtxPos[1]); aida.histogram1D("Vertex Z", 100, -1,
+                     1).fill(vtxPos[2]);
+                     */
+
+
+                    BilliorTrack bt1 = btMap.get(track1);
+                    BilliorTrack bt2 = btMap.get(track2);
+                    btlist.clear();
+                    btlist.add(bt1);
+                    btlist.add(bt2);
+                    /*
+                     BilliorVertex bvertex = new BilliorVertex(1.0);
+                     bvertex.fitVertex(btlist); BasicMatrix bvtxPos =
+                     (BasicMatrix) bvertex.getVertexPosition(); BasicMatrix
+                     bvtxCov = (BasicMatrix) bvertex.getVertexCovariance();
+                     System.out.println("Constrained");
+                     System.out.println("Vertex Position: " +
+                     bvtxPos.toString()); System.out.println("chisq : " +
+                     bvertex.getChiSq());
+
+                     aida.histogram1D("BilliorVertex X -- Constrained", 100,
+                     -10, 20).fill(bvtxPos.e(0, 0));
+                     aida.histogram1D("BilliorVertex Y -- Constrained", 100,
+                     -0.4, 0.4).fill(bvtxPos.e(1, 0));
+                     aida.histogram1D("BilliorVertex Z -- Constrained", 100,
+                     -0.4, 0.4).fill(bvtxPos.e(2, 0));
+                     aida.histogram1D("BilliorVertex ChiSq -- Constrained", 100,
+                     0, 50).fill(bvertex.getChiSq());
+                     aida.histogram1D("BilliorVertex X Pull -- Constrained",
+                     100, -4, 4).fill(bvtxPos.e(0, 0) / Math.sqrt(bvtxCov.e(0,
+                     0))); aida.histogram1D("BilliorVertex Y Pull--
+                     Constrained", 100, -4, 4).fill(bvtxPos.e(1, 0) /
+                     Math.sqrt(bvtxCov.e(1, 1)));
+                     aida.histogram1D("BilliorVertex Z Pull-- Constrained", 100,
+                     -4, 4).fill(bvtxPos.e(2, 0) / Math.sqrt(bvtxCov.e(2, 2)));
+                     */
+                    /*
+                     BilliorVertex bvertexUC = new BilliorVertex(1.0);
+                     bvertexUC.doBeamSpotConstraint(false);
+                     bvertexUC.fitVertex(btlist); BasicMatrix bvtxPosUC =
+                     (BasicMatrix) bvertexUC.getVertexPosition(); BasicMatrix
+                     bvtxCovUC = (BasicMatrix) bvertexUC.getVertexCovariance();
+                     System.out.println("UnConstrained");
+                     System.out.println("Vertex Position: " +
+                     bvtxPosUC.toString()); System.out.println("chisq : " +
+                     bvertexUC.getChiSq()); aida.histogram1D("BilliorVertex X --
+                     UnConstrained", 100, -10, 20).fill(bvtxPosUC.e(0, 0));
+                     aida.histogram1D("BilliorVertex Y -- UnConstrained", 100,
+                     -0.4, 0.4).fill(bvtxPosUC.e(1, 0));
+                     aida.histogram1D("BilliorVertex Z -- UnConstrained", 100,
+                     -0.4, 0.4).fill(bvtxPosUC.e(2, 0));
+                     aida.histogram1D("BilliorVertex ChiSq -- UnConstrained",
+                     100, 0, 50).fill(bvertexUC.getChiSq());
+                     aida.histogram1D("BilliorVertex X Pull -- UnConstrained",
+                     100, -4, 4).fill(bvtxPosUC.e(0, 0) /
+                     Math.sqrt(bvtxCovUC.e(0, 0)));
+                     aida.histogram1D("BilliorVertex Y Pull-- UnConstrained",
+                     100, -4, 4).fill(bvtxPosUC.e(1, 0) /
+                     Math.sqrt(bvtxCovUC.e(1, 1)));
+                     aida.histogram1D("BilliorVertex Z Pull-- UnConstrained",
+                     100, -4, 4).fill(bvtxPosUC.e(2, 0) /
+                     Math.sqrt(bvtxCovUC.e(2, 2)));
+                     */
+                    BilliorVertexer bvertexerUC = new BilliorVertexer(bfield);
+                    BilliorVertex bvertexUC = bvertexerUC.fitVertex(btlist);
+//                    bvertexUC.fitVertex(btlist);
+                    BasicMatrix bvtxPosUC = (BasicMatrix) bvertexUC.getPosition();
+                    SymmetricMatrix bvtxCovUC = bvertexUC.getCovMatrix();
+                    double invMassUC = bvertexUC.getParameters().get("invMass");
+//                    System.out.println("UnConstrained");
+//                    System.out.println("Vertex Position:  " + bvtxPosUC.toString());
+//                    System.out.println("chisq :  " + bvertexUC.getChiSq());
+                    aida.histogram1D("BilliorVertex X  -- UnConstrained", 100, -10, 20).fill(bvtxPosUC.e(0, 0));
+                    aida.histogram1D("BilliorVertex Y -- UnConstrained", 100, -0.4, 0.4).fill(bvtxPosUC.e(1, 0));
+                    aida.histogram1D("BilliorVertex Z -- UnConstrained", 100, -0.4, 0.4).fill(bvtxPosUC.e(2, 0));
+                    aida.histogram1D("BilliorVertex ChiSq -- UnConstrained", 100, 0, 50).fill(bvertexUC.getChi2());
+                    aida.histogram1D("BilliorVertex X Pull -- UnConstrained", 100, -4, 4).fill(bvtxPosUC.e(0, 0) / Math.sqrt(bvtxCovUC.e(0, 0)));
+                    aida.histogram1D("BilliorVertex Y Pull-- UnConstrained", 100, -4, 4).fill(bvtxPosUC.e(1, 0) / Math.sqrt(bvtxCovUC.e(1, 1)));
+                    aida.histogram1D("BilliorVertex Z Pull-- UnConstrained", 100, -4, 4).fill(bvtxPosUC.e(2, 0) / Math.sqrt(bvtxCovUC.e(2, 2)));
+
+
+                    BilliorVertexer bvertexer = new BilliorVertexer(bfield);
+                    bvertexer.setBeamSize(beamsize);
+                    bvertexer.doBeamSpotConstraint(true);
+
+                    BilliorVertex bvertex = bvertexer.fitVertex(btlist);
+                    BasicMatrix bvtxPos = (BasicMatrix) bvertex.getPosition();
+                    SymmetricMatrix bvtxCov = bvertex.getCovMatrix();
+                    double invMass = bvertex.getParameters().get("invMass");
+
+//                    System.out.println("Constrained");
+//                    System.out.println("Vertex Position:  " + bvtxPos.toString());
+//                    System.out.println("chisq :  " + bvertex.getChiSq());
+                    aida.histogram1D("BilliorVertex X  -- Constrained", 100, -10, 20).fill(bvtxPos.e(0, 0));
+                    aida.histogram1D("BilliorVertex Y -- Constrained", 100, -0.4, 0.4).fill(bvtxPos.e(1, 0));
+                    aida.histogram1D("BilliorVertex Z -- Constrained", 100, -0.4, 0.4).fill(bvtxPos.e(2, 0));
+                    aida.histogram1D("BilliorVertex ChiSq -- Constrained", 100, -10, 50).fill(bvertex.getChi2());
+                    aida.histogram1D("BilliorVertex X Pull -- Constrained", 100, -4, 4).fill(bvtxPos.e(0, 0) / Math.sqrt(bvtxCov.e(0, 0)));
+                    aida.histogram1D("BilliorVertex Y Pull-- Constrained", 100, -4, 4).fill(bvtxPos.e(1, 0) / Math.sqrt(bvtxCov.e(1, 1)));
+                    aida.histogram1D("BilliorVertex Z Pull-- Constrained", 100, -4, 4).fill(bvtxPos.e(2, 0) / Math.sqrt(bvtxCov.e(2, 2)));
+
+                    aida.histogram1D("BilliorVertex Mass  -- Constrained", 250, 0.0, 0.25).fill(invMass);
+                    aida.histogram1D("BilliorVertex Mass  -- UnConstrained", 250, 0.0, 0.25).fill(invMassUC);
+
+
+                    BilliorVertexer bconvertexer = new BilliorVertexer(bfield);
+                    bconvertexer.setBeamSize(beamsize);
+                    bconvertexer.doTargetConstraint(true);
+
+                    BilliorVertex bsconfit = bconvertexer.fitVertex(btlist);
+//                    bvertexUC.fitVertex(btlist);
+                    BasicMatrix bsconvtxPos = (BasicMatrix) bsconfit.getPosition();
+                    SymmetricMatrix bsconvtxCov = bsconfit.getCovMatrix();
+                    double invMassBSCon = bsconfit.getParameters().get("invMass");
+
+
+                    aida.histogram1D("BilliorVertex X  -- BS Constrained", 100, -10, 20).fill(bsconvtxPos.e(0, 0));
+                    aida.histogram1D("BilliorVertex Y -- BS Constrained", 100, -0.4, 0.4).fill(bsconvtxPos.e(1, 0));
+                    aida.histogram1D("BilliorVertex Z -- BS Constrained", 100, -0.4, 0.4).fill(bsconvtxPos.e(2, 0));
+                    aida.histogram1D("BilliorVertex ChiSq -- BS Constrained", 100, -10, 50).fill(bsconfit.getChi2());
+                    aida.histogram1D("BilliorVertex X Pull -- BS Constrained", 100, -4, 4).fill(bsconvtxPos.e(0, 0) / Math.sqrt(bsconvtxCov.e(0, 0)));
+                    aida.histogram1D("BilliorVertex Y Pull-- BS Constrained", 100, -4, 4).fill(bsconvtxPos.e(1, 0) / Math.sqrt(bsconvtxCov.e(1, 1)));
+                    aida.histogram1D("BilliorVertex Z Pull-- BS Constrained", 100, -4, 4).fill(bsconvtxPos.e(2, 0) / Math.sqrt(bsconvtxCov.e(2, 2)));
+
+                    aida.histogram1D("BilliorVertex Mass  -- BS Constrained", 100, 0.08, 0.12).fill(invMassBSCon);
+                }
+            }
+        }
+
+
+        //  Now loop over all MC Particles
+        List<MCParticle> mclist = event.getMCParticles();
+        pw.format("%d ", nevt);
+
+        for (MCParticle mcp : mclist) {
+            if (mcp.getParents().size() > 0) {
+                if (mcp.getParents().get(0).getPDGID() == 622) {
+//                    boolean find= findable.InnerTrackerIsFindable(mcp, nlayers[0],true);
+//                    System.out.println("A' Track Findable? "+find+";  nlayers = "+nlayers[0]);
+                    boolean find = findable.InnerTrackerIsFindable(mcp, nlayers[0]);
+                    int ifind = 0;
+                    if (find)
+                        ifind = 1;
+                    double ch = mcp.getCharge();
+                    pw.format("%d  %2.0f ", ifind, ch);
+                    Set<SimTrackerHit> mchitlist = mcHittomcP.allTo(mcp);
+
+                    for (int i = 0; i < 10; i++) {
+                        if (mchitlist.size() > i + 1) {
+                            SimTrackerHit sth = (SimTrackerHit) mchitlist.toArray()[i];
+
+                            if (sth != null)
+                                pw.format("%d %5.5f %5.5f %5.5f ", sth.getLayer(), sth.getPoint()[1], sth.getPoint()[2], sth.getPoint()[0]);
+                            else
+                                pw.format("%d %5.5f %5.5f %5.5f ", 99, -666, -666, -666);
+                        } else {
+                            pw.format("%d %5.5f %5.5f %5.5f ", 99, -666.6, -666.6, -666.6);
+                        }
+                    }
+                }
+            }
+
+        }
+        pw.println();
+        int _nchMCP = 0;
+        int _nchMCPBar = 0;
+        for (MCParticle mcp : mclist) {
+
+            //  Calculate the pT and polar angle of the MC particle
+            double px = mcp.getPX();
+            double py = mcp.getPY();
+            double pz = mcp.getPZ();
+            double pt = Math.sqrt(px * px + py * py);
+            double p = Math.sqrt(pt * pt + pz * pz);
+            double cth = pz / p;
+            double theta = 180. * Math.acos(cth) / Math.PI;
+            double eta = -Math.log(Math.tan(Math.atan2(pt, pz) / 2));
+            double phi = Math.atan2(py, px);
+            int pdgid = mcp.getPDGID();
+            //  Find the number of layers hit by this mc particle
+//            System.out.println("MC pt=" + pt);
+            int nhits = findable.LayersHit(mcp);
+            Set<SimTrackerHit> mchitlist = mcHittomcP.allTo(mcp);
+            boolean isFindable = findable.InnerTrackerIsFindable(mcp, nlayers[0] - 2);
+//            boolean isFindable = findable.InnerTrackerIsFindable(mcp, nlayers[0]);
+            Set<HelicalTrackCross> hitlist = hittomc.allTo(mcp);
+
+            //  Calculate the helix parameters for this MC particle
+            HelixParamCalculator helix = new HelixParamCalculator(mcp, bfield);
+            double d0 = helix.getDCA();
+            double z0 = helix.getZ0();
+
+
+            //  Check cases where we have multiple tracks associated with this MC particle
+            Set<Track> trklist = trktomc.allTo(mcp);
+            int ntrk = trklist.size();
+
+
+            Set<Track> trklistAxial = trktomcAxial.allTo(mcp);
+            int ntrkAxial = trklistAxial.size();
+
+            if (mcp.getPDGID() == 622) {
+                boolean bothreco = true;
+                boolean bothfindable = true;
+                //it's the A'...let's see if we found both tracks.
+                List<MCParticle> daughters = mcp.getDaughters();
+                for (MCParticle d : daughters) {
+                    if (trktomc.allTo(d).size() == 0) {
+                        bothreco = false;
+                    }
+                    if (!findable.InnerTrackerIsFindable(d, nlayers[0] - 2)) {
+//                    if (!findable.InnerTrackerIsFindable(d, nlayers[0])) {
+                        bothfindable = false;
+                    }
+                }
+                double vtxWgt = 0;
+                if (bothreco) {
+                    vtxWgt = 1.0;
+                }
+                VxEff.fill(mcp.getOriginX(), vtxWgt);
+                VyEff.fill(mcp.getOriginY(), vtxWgt);
+                VzEff.fill(mcp.getOriginZ(), vtxWgt);
+                if (bothfindable) {
+                    VxEffFindable.fill(mcp.getOriginX(), vtxWgt);
+                    VyEffFindable.fill(mcp.getOriginY(), vtxWgt);
+                    VzEffFindable.fill(mcp.getOriginZ(), vtxWgt);
+                }
+            }
+
+            if (ntrk > 1) {
+                //  Count tracks where the assigned MC particle has more than 1 hit
+                int nmulthits = 0;
+                for (Track trk : trklist) {
+                    TrackAnalysis tkanal = tkanalMap.get(trk);
+                    if (tkanal.getNBadHits() < tkanal.getNHits() - 1) {
+                        nmulthits++;
+                    }
+                }
+                //  Flag any anomalous cases that we find
+                if (nmulthits > 1) {
+                    System.out.println("2 tracks associated with a single MC Particle");
+                }
+            }
+
+            if (isFindable) {
+                _nchMCP++;
+                findableTracks++;
+                double wgt = 0.;
+                if (ntrk > 0) {
+                    wgt = 1.;
+                }
+                foundTracks += wgt;
+                peffFindable.fill(p, wgt);
+                phieffFindable.fill(phi, wgt);
+                thetaeffFindable.fill(theta, wgt);
+                ctheffFindable.fill(cth, wgt);
+                d0effFindable.fill(d0, wgt);
+                z0effFindable.fill(z0, wgt);
+                //              if (wgt == 0)
+//                    System.out.println("Missed a findable track!");
+
+                double wgtAxial = 0.;
+                if (ntrkAxial > 0) {
+                    wgtAxial = 1.;
+                }
+                peffAxial.fill(p, wgtAxial);
+                phieffAxial.fill(phi, wgtAxial);
+                thetaeffAxial.fill(theta, wgtAxial);
+                ctheffAxial.fill(cth, wgtAxial);
+                d0effAxial.fill(d0, wgtAxial);
+                z0effAxial.fill(z0, wgtAxial);
+
+
+            }
+
+            if (mcp.getParents().size() == 1 && mcp.getParents().get(0).getPDGID() == 622) {
+                totelectrons++;
+
+                if (isFindable) {
+                    findableelectrons++;
+                    double wgt = 0.;
+                    if (ntrk > 0) {
+                        wgt = 1.;
+                    }
+                    foundelectrons += wgt;
+                    peffElectrons.fill(p, wgt);
+                    phieffElectrons.fill(phi, wgt);
+                    thetaeffElectrons.fill(theta, wgt);
+                    ctheffElectrons.fill(cth, wgt);
+                    d0effElectrons.fill(d0, wgt);
+                    z0effElectrons.fill(z0, wgt);
+                    if (wgt == 0 && pdgid > 0) {
+                        System.out.println("Missed a findable ELECTRON!!!!!");
+                    }
+                    if (wgt == 0 && pdgid < 0) {
+                        System.out.println("Missed a findable POSITRON!!!!!");
+                    }
+
+                    double wgtAxial = 0.;
+                    if (ntrkAxial > 0) {
+                        wgtAxial = 1.;
+                    }
+                    peffAxial.fill(p, wgtAxial);
+                    phieffAxial.fill(phi, wgtAxial);
+                    thetaeffAxial.fill(theta, wgtAxial);
+                    ctheffAxial.fill(cth, wgtAxial);
+                    d0effAxial.fill(d0, wgtAxial);
+                    z0effAxial.fill(z0, wgtAxial);
+                }
+            }
+
+
+        }
+
+        return;
+    }
+
+    public void endOfData() {
+        try {
+            aida.saveAs(outputPlots);
+        } catch (IOException ex) {
+            Logger.getLogger(JasAnalysisDriver.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        pw.close();
+        try {
+            fw.close();
+        } catch (IOException ex) {
+            Logger.getLogger(JasAnalysisDriver.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        System.out.println("# of reco tracks = " + foundTracks + "; # of MC tracks = " + findableTracks + "; Efficiency = " + foundTracks / findableTracks);
+        System.out.println("# of reco ele/pos = " + foundelectrons + "; # of findable ele/pos = " + findableelectrons + "; Efficiency = " + foundelectrons / findableelectrons);
+    }
+
+    public void setOutputPlots(String output) {
+        this.outputPlots = output;
+    }
+
+    public void setOutputText(String output) {
+        this.outputTextName = output;
+    }
+
+    private double getr(double x, double y) {
+        return Math.sqrt(x * x + y * y);
+    }
+
+    protected double drcalc(Hep3Vector pos, SymmetricMatrix cov) {
+        double x = pos.x();
+        double y = pos.y();
+        double r2 = x * x + y * y;
+        return Math.sqrt((x * x * cov.e(0, 0) + y * y * cov.e(1, 1) + 2. * x * y * cov.e(0, 1)) / r2);
+    }
+
+    protected double drphicalc(Hep3Vector pos, SymmetricMatrix cov) {
+        double x = pos.x();
+        double y = pos.y();
+        double r2 = x * x + y * y;
+        return Math.sqrt((y * y * cov.e(0, 0) + x * x * cov.e(1, 1) - 2. * x * y * cov.e(0, 1)) / r2);
+    }
+
+    private double getphi(double x, double y) {
+        double phi = Math.atan2(y, x);
+        if (phi < 0.) {
+            phi += 2. * Math.PI;
+        }
+        return phi;
+    }
+
+    private double getdxdy(Hep3Vector hitpos, Hep3Vector posonhelix) {
+        return Math.sqrt(Math.pow(hitpos.x() - posonhelix.x(), 2) + Math.pow(hitpos.y() - posonhelix.y(), 2));
+    }
+
+    private double getdxdyErr(Hep3Vector hitpos, Hep3Vector posonhelix, SymmetricMatrix cov) {
+        double dxdySq = Math.pow(hitpos.x() - posonhelix.x(), 2) + Math.pow(hitpos.y() - posonhelix.y(), 2);
+        double ErrSqDxDySq = 4 * (cov.e(0, 0) * Math.pow(hitpos.x() - posonhelix.x(), 2) + cov.e(1, 1) * Math.pow(hitpos.y() - posonhelix.y(), 2));
+        double error = Math.sqrt(ErrSqDxDySq / dxdySq) / 2;
+        return error;
+    }
+
+    private void fillClouds(String dir, String species, int nhits, double p, double cth, double y0, double z0, double doca, double[] poca, double pinvresid, double presid, double y0resid, double z0resid, double docaresid, double[] pocaresid) {
+        double nbins = 4;
+        double[] pBins = {1, 2, 3, 4, 5};
+
+        aida.cloud1D(dir + "Hits for all " + species).fill(nhits);
+        aida.cloud1D(dir + "p for all " + species).fill(p);
+        aida.cloud1D(dir + "cos(theta) for all " + species).fill(cth);
+        aida.cloud1D(dir + "y0 for all " + species).fill(y0);
+        aida.cloud1D(dir + "z0 for all " + species).fill(z0);
+        aida.cloud1D(dir + "doca for all " + species).fill(doca);
+        aida.cloud1D(dir + "xoca for all " + species).fill(poca[0]);
+        aida.cloud1D(dir + "yoca for all " + species).fill(poca[1]);
+        aida.cloud1D(dir + "zoca for all " + species).fill(poca[2]);
+        aida.histogram1D(dir + "p^-1 Residual for all " + species, 50, -0.1, 0.1).fill(pinvresid);
+        aida.cloud1D(dir + "p Residual for all " + species).fill(presid);
+        aida.histogram1D(dir + "y0 Residual for all " + species, 50, -1, 1).fill(y0resid);
+        aida.histogram1D(dir + "z0 Residual for all " + species, 50, -1, 1).fill(z0resid);
+
+        if (p > pBins[0] && p < pBins[1]) {
+            aida.histogram1D(dir + "doca Residual for 1<p<2 " + species, 50, -0.5, 0.5).fill(docaresid);
+            aida.histogram1D(dir + "xoca Residual for 1<p<2 " + species, 50, -0.5, 0.5).fill(pocaresid[0]);
+            aida.histogram1D(dir + "yoca Residual for 1<p<2 " + species, 50, -0.5, 0.5).fill(pocaresid[1]);
+            aida.histogram1D(dir + "zoca Residual for 1<p<2 " + species, 50, -0.5, 0.5).fill(pocaresid[2]);
+        } else if (p > pBins[1] && p < pBins[2]) {
+            aida.histogram1D(dir + "doca Residual for 2<p<3 " + species, 50, -0.5, 0.5).fill(docaresid);
+            aida.histogram1D(dir + "xoca Residual for 2<p<3 " + species, 50, -0.5, 0.5).fill(pocaresid[0]);
+            aida.histogram1D(dir + "yoca Residual for 2<p<3 " + species, 50, -0.5, 0.5).fill(pocaresid[1]);
+            aida.histogram1D(dir + "zoca Residual for 2<p<3 " + species, 50, -0.5, 0.5).fill(pocaresid[2]);
+        } else if (p > pBins[2] && p < pBins[3]) {
+            aida.histogram1D(dir + "doca Residual for 3<p<4 " + species, 50, -0.5, 0.5).fill(docaresid);
+            aida.histogram1D(dir + "xoca Residual for 3<p<4 " + species, 50, -0.5, 0.5).fill(pocaresid[0]);
+            aida.histogram1D(dir + "yoca Residual for 3<p<4 " + species, 50, -0.5, 0.5).fill(pocaresid[1]);
+            aida.histogram1D(dir + "zoca Residual for 3<p<4 " + species, 50, -0.5, 0.5).fill(pocaresid[2]);
+        } else if (p > pBins[3] && p < pBins[4]) {
+            aida.histogram1D(dir + "doca Residual for 4<p<5 " + species, 50, -0.5, 0.5).fill(docaresid);
+            aida.histogram1D(dir + "xoca Residual for 4<p<5 " + species, 50, -0.5, 0.5).fill(pocaresid[0]);
+            aida.histogram1D(dir + "yoca Residual for 4<p<5 " + species, 50, -0.5, 0.5).fill(pocaresid[1]);
+            aida.histogram1D(dir + "zoca Residual for 4<p<5 " + species, 50, -0.5, 0.5).fill(pocaresid[2]);
+        }
+
+        aida.histogram1D(dir + "doca Residual for all " + species, 50, -0.5, 0.5).fill(docaresid);
+        aida.histogram1D(dir + "xoca Residual for all " + species, 50, -0.5, 0.5).fill(pocaresid[0]);
+        aida.histogram1D(dir + "yoca Residual for all " + species, 50, -0.5, 0.5).fill(pocaresid[1]);
+        aida.histogram1D(dir + "zoca Residual for all " + species, 50, -0.5, 0.5).fill(pocaresid[2]);
+    }
+
+    private void fillTrackInfo(String dir, String species, double chi2, int nhits, double p, double pperp, double px, double py, double pz, double phi, double cth, double doca, double xoca, double yoca, double zoca) {
+        aida.cloud1D(dir + "total chi^2 for  " + species).fill(chi2);
+
+//                aida.cloud1D(trackdir + "circle chi^2 for  " + species).fill(ht.chisq()[0]);
+//                aida.cloud1D(trackdir + "linear chi^2 for  " + species).fill(ht.chisq()[1]
+        aida.cloud1D(dir + "Hits for  " + species).fill(nhits);
+        aida.cloud1D(dir + "p for  " + species).fill(p);
+        aida.cloud1D(dir + "pperp for  " + species).fill(pperp);
+        aida.cloud1D(dir + "px for  " + species).fill(px);
+        aida.cloud1D(dir + "py for  " + species).fill(py);
+        aida.cloud1D(dir + "pz for  " + species).fill(pz);
+        aida.cloud1D(dir + "phi for  " + species).fill(phi);
+        aida.cloud1D(dir + "cos(theta) for  " + species).fill(cth);
+        aida.cloud1D(dir + "DOCA for  " + species).fill(doca);
+        aida.cloud1D(dir + "XOCA for  " + species).fill(xoca);
+        aida.cloud1D(dir + "YOCA for  " + species).fill(yoca);
+        aida.cloud1D(dir + "ZOCA for  " + species).fill(zoca);
+        aida.cloud2D(dir + "doca vs xoca for  " + species).fill(xoca, doca);
+    }
+
+    private void fillVertexInfo(String apdir, String vertex, double chisq, Hep3Vector vtx, SymmetricMatrix vtxcov, double invMass, double deltaPhi, double oAngle, double cosAlpha) {
+        aida.histogram1D(apdir + vertex + " vertex chi^2", 50, 0, 1000).fill(chisq);
+        aida.histogram1D(apdir + vertex + " vertex X", 50, -10, 10).fill(vtx.x());
+        aida.histogram1D(apdir + vertex + " vertex X Wide", 100, -10, 50).fill(vtx.x());
+        aida.histogram1D(apdir + vertex + " vertex sigma X", 50, 0, 1).fill(Math.sqrt(vtxcov.e(0, 0)));
+        aida.histogram1D(apdir + vertex + " vertex signifigance X", 50, -100, 100).fill(vtx.x() / Math.sqrt(vtxcov.e(0, 0)));
+        aida.histogram1D(apdir + vertex + " vertex X Positive Tail", 50, 10, 110).fill(vtx.x());
+        aida.histogram1D(apdir + vertex + " vertex Y", 50, -1, 1).fill(vtx.y());
+        aida.histogram1D(apdir + vertex + " vertex sigma Y", 50, 0, 0.1).fill(Math.sqrt(vtxcov.e(1, 1)));
+        aida.histogram1D(apdir + vertex + " vertex Z", 50, -1, 1).fill(vtx.z());
+        aida.histogram1D(apdir + vertex + " vertex sigma Z", 50, 0, 0.1).fill(Math.sqrt(vtxcov.e(2, 2)));
+        aida.histogram1D(apdir + vertex + " e+e- Invariant Mass", 100, 0.05, 0.25).fill(invMass);
+        aida.histogram1D(apdir + vertex + " vertex deltaPhi", 50, -0.2, 0.2).fill(deltaPhi);
+        aida.histogram1D(apdir + vertex + " vertex cos(opening angle)", 50, 0.8, 1).fill(oAngle);
+        aida.histogram1D(apdir + vertex + " vertex cos(Alpha)", 100, 0.5, 1).fill(cosAlpha);
+
+    }
+
+    private double getInvMass(Track track1, StraightLineTrack slt1, Track track2, StraightLineTrack slt2) {
+        double esum = 0.;
+        double pxsum = 0.;
+        double pysum = 0.;
+        double pzsum = 0.;
+        double chargesum = 0.;
+        double me = 0.000511;
+        // Loop over jets
+
+        double p1x = track1.getPX();
+        double p1y = track1.getPY();
+        double p1z = track1.getPZ();
+        double p1mag2 = p1x * p1x + p1y * p1y + p1z * p1z;
+        double e1 = Math.sqrt(p1mag2 + me * me);
+        double dydx1 = slt1.dydx();
+        double dzdx1 = slt1.dzdx();
+        double s1sq = 1 + 1 / (dydx1 * dydx1) + (dzdx1 * dzdx1) / (dydx1 * dydx1);
+        double truep1y = Math.sqrt(p1mag2 / s1sq);
+        if (dydx1 < 0) {
+            truep1y = -truep1y;
+        }
+        double truep1x = truep1y / dydx1;
+        double truep1z = dzdx1 * truep1x;
+
+        double p2x = track2.getPX();
+        double p2y = track2.getPY();
+        double p2z = track2.getPZ();
+        double p2mag2 = p2x * p2x + p2y * p2y + p2z * p2z;
+        double e2 = Math.sqrt(p2mag2 + me * me);
+
+        double dydx2 = slt2.dydx();
+        double dzdx2 = slt2.dzdx();
+        double s2sq = 1 + 1 / (dydx2 * dydx2) + (dzdx2 * dzdx2) / (dydx2 * dydx2);
+        double truep2y = Math.sqrt(p2mag2 / s2sq);
+        if (dydx2 < 0) {
+            truep2y = -truep2y;
+        }
+        double truep2x = truep2y / dydx2;
+        double truep2z = dzdx2 * truep2x;
+
+        pxsum =
+                truep1x + truep2x;
+        pysum =
+                truep1y + truep2y;
+        pzsum =
+                truep1z + truep2z;
+
+        esum =
+                e1 + e2;
+//        double p1dotp2 = p1x * p2x + p1y * p2y + p1z * p2z;
+        double p1dotp2 = truep1x * truep2x + truep1y * truep2y + truep1z * truep2z;
+        double e1e2 = e1 * e2;
+        double invmass = Math.sqrt(2 * me * me + 2 * (e1e2 - p1dotp2));
+        // Compute total momentum and hence event mass
+        double psum = Math.sqrt(pxsum * pxsum + pysum * pysum + pzsum * pzsum);
+        double evtmass = Math.sqrt(esum * esum - psum * psum);
+//        System.out.println("invmass= " + invmass + "; evtmass=" + evtmass);
+        return invmass;
+    }
+
+//find the DOCA to the beamline extrpolating linearly from the reference point
+    private double findDoca(double y, double z, double px, double py, double pz) {
+        double xoca = 0;
+        double sy = py / px;
+        double sz = pz / px;
+        xoca =
+                -(y * sy + z * sz) / (sy * sy + sz + sz);
+        double doca = Math.sqrt(Math.pow(y + sy * xoca, 2) + Math.pow(z + sz * xoca, 2));
+        return doca;
+    }
+
+//find the XOCA to the beamline extrpolating linearly from the reference point
+    private double findXoca(double y, double z, double px, double py, double pz) {
+        double xoca = 0;
+        double sy = py / px;
+        double sz = pz / px;
+        xoca =
+                -(y * sy + z * sz) / (sy * sy + sz + sz);
+        return xoca;
+    }
+
+    private double[] findPoca(double y, double z, double px, double py, double pz) {
+        double poca[] = {0, 0, 0};
+        double sy = py / px;
+        double sz = pz / px;
+        poca[0] = -(y * sy + z * sz) / (sy * sy + sz * sz);
+        poca[1] = y + sy * poca[0];
+        poca[2] = z + sz * poca[0];
+        return poca;
+    }
+
+    private Hep3Vector getV0Momentum(Track track1, StraightLineTrack slt1, Track track2, StraightLineTrack slt2) {
+
+
+        Hep3Vector p1 = getTrueMomentum(track1, slt1);
+        Hep3Vector p2 = getTrueMomentum(track2, slt2);
+        Hep3Vector pV0 = VecOp.add(p1, p2);
+
+        return pV0;
+
+    }
+
+    private double getV0OpeningAngle(Track track1, StraightLineTrack slt1, Track track2, StraightLineTrack slt2) {
+
+        Hep3Vector p1 = getTrueMomentum(track1, slt1);
+        Hep3Vector p2 = getTrueMomentum(track2, slt2);
+
+        return VecOp.dot(p1, p2) / (p1.magnitude() * p2.magnitude());
+
+    }
+
+    private Hep3Vector getTrueMomentum(Track track1, StraightLineTrack slt1) {
+        double[] truep = {0, 0, 0};
+        double me = 0.000511;
+        double p1x = track1.getPX();
+        double p1y = track1.getPY();
+        double p1z = track1.getPZ();
+        double p1mag2 = p1x * p1x + p1y * p1y + p1z * p1z;
+        double e1 = Math.sqrt(p1mag2 + me * me);
+        double dydx1 = slt1.dydx();
[truncated at 1000 lines; 20 more skipped]

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
KalmanFilterDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/KalmanFilterDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/KalmanFilterDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,248 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.mgraham;
+
+import hep.physics.vec.Hep3Vector;
+import java.util.List;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCRelation;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.Track;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.recon.tracking.kalman.FullFitKalman;
+import org.lcsim.hps.recon.tracking.kalman.ShapeDispatcher;
+import org.lcsim.hps.recon.tracking.kalman.TrackUtils;
+import org.lcsim.recon.tracking.trfbase.ETrack;
+import org.lcsim.util.Driver;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.hps.recon.tracking.TrackAnalysis;
+import org.lcsim.recon.tracking.trfbase.PropDir;
+import org.lcsim.recon.tracking.trfbase.Propagator;
+import org.lcsim.recon.tracking.trfbase.TrackError;
+import org.lcsim.recon.tracking.trfbase.TrackVector;
+import org.lcsim.recon.tracking.trfbase.VTrack;
+import org.lcsim.recon.tracking.trfdca.SurfDCA;
+import org.lcsim.recon.tracking.trffit.HTrack;
+import org.lcsim.recon.tracking.trfxyp.SurfXYPlane;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author ecfine ([log in to unmask])
+ */
+/* Takes Matched Tracks from the Track Reconstruction Driver, and makes TRF
+ * HTracks. Adds hits from the original tracks to the new HTrack, and runs a
+ * Kalman filter over the HTrack.
+ *
+ * This only does a forward fit, and multiple scattering is only included at
+ * interacting planes, and just by assuming that each plane is .01 radiation
+ * lengths. Energy loss is not accounted for. Additionally, the method for
+ * constructing hits assumes that every hit occurs at an XY plane, while ideally,
+ * there would be a method which checks the lcsim detector geometry and then
+ * decides what kind of surface to model the shape as. There may be some methods
+ * in the ShapeHelper interface (particularly in TrdHelper) that would be useful
+ * for this, but nothing completed. Additionally, to run realistic multiple
+ * scattering with non-interacting detector elements, there would need to be a
+ * way to find the intercepts between a specific track and the detector elements.
+ *
+ * Also, magnetic field is just set at 1.0 in each class. It should be taken from
+ * the detector geometry. */
+public class KalmanFilterDriver extends Driver {
+
+    boolean _debug = false;
+    private AIDA aida = AIDA.defaultInstance();
+    ShapeDispatcher shapeDis = new ShapeDispatcher();
+    TrackUtils trackUtils = new TrackUtils();
+    Propagator prop = null;
+    FullFitKalman fitk = null;
+    KalmanGeom geom = null;
+    Detector detector = null;
+    HTrack ht = null;
+    double bz = 0.5;
+
+    public void detectorChanged(Detector det) {
+        detector = det;
+        geom = new KalmanGeom(detector); // new geometry containing detector info
+        prop = geom.newPropagator();
+        trackUtils.setBZ(geom.bz);
+        System.out.println("geom field = " + geom.bz + ", trackUtils field = " + trackUtils.bz);
+
+        fitk = new FullFitKalman(prop);
+//        PropXYXY_Test foobar = new PropXYXY_Test();
+//        foobar.testPropXYXY();
+        //
+    }
+
+    public void process(EventHeader event) {
+        /* Get the tracklist for each event, and then for each track
+         * get the starting track parameters and covariance matrix for an
+         * outward fit from the seedtracker. */
+        String kaldir = "KalmanFit/";
+        String kaldirPos = "KalmanFit/GoodChi2/";
+        String kaldirBad = "KalmanFit/BadChi2/";
+        String bkwdkaldir = "KalmanFit/BackwardFit/";
+        RelationalTable hittomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        List<LCRelation> mcrelations = event.get(LCRelation.class, "HelicalTrackMCRelations");
+
+        for (LCRelation relation : mcrelations)
+            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
+                hittomc.add(relation.getFrom(), relation.getTo());
+
+        if (event.hasItem("MatchedTracks")) {
+            List<Track> trklist = (List<Track>) event.get("MatchedTracks");
+            if (_debug)
+                System.out.println("number of tracks: " + trklist.size());
+            for (int i = 0; i < trklist.size(); i++) {
+
+                /* Start with a HelicalTrackFit, turn it into a VTrack,
+                 * turn that into an ETrack, and turn that into an HTrack.
+                 * Then add detector hits from the original track. */
+                if (_debug)
+                    System.out.println("Making tracks...");
+                Track track = trklist.get(i);
+                TrackAnalysis tkanal = new TrackAnalysis(track, hittomc);
+                HelicalTrackFit helicalTrack = shapeDis.trackToHelix(track);
+                VTrack vt = trackUtils.makeVTrack(helicalTrack);
+                TrackError initialError = trackUtils.getInitalError(helicalTrack);
+                ETrack et = new ETrack(vt, initialError);
+                ht = new HTrack(et);
+
+                /* Add hits from original track */
+                for (int k = 0; k < track.getTrackerHits().size(); k++) {
+                    TrackerHit thit = track.getTrackerHits().get(k);
+//                    System.out.println("Adding hit...");
+                    ht = geom.addTrackerHit(thit, ht, helicalTrack, vt);
+                }
+                /* Once we have an HTrack with the ordered list of hits, we pass
+                 * this to the Kalman fitter. */
+//                System.out.println("Running Kalman fit...");
+
+
+
+                /*
+
+                int fstarf = fitk.fit(ht);
+                double kfchi2 = ht.chisquared();
+
+
+                SurfXYPlane srfc = new SurfXYPlane(0.001, 0);
+                 */
+
+                //                System.out.println("Nominal Fit Vector : "+vt.toString());
+                TrackVector nomFit = vt.vector();
+                double nomDCA = nomFit.get(0);
+                double nomz0 = nomFit.get(1);
+                double nomphi0 = Math.sin(nomFit.get(2));
+                double nomslope = nomFit.get(3);
+                double nomqOverpt = nomFit.get(4);
+
+
+                /*
+                ETrack fitET = ht.newTrack();
+                if (kfchi2 < 10000 && kfchi2 > 0) {
+                //                    ht.propagate(prop, srfc);
+                if(_debug)  System.out.println("Fitted Track Before Propagation:  "+ht.toString());
+                //                    ht.propagate(prop, srfc, PropDir.BACKWARD_MOVE);
+                ht.propagate(prop, s, PropDir.BACKWARD);
+
+                if(_debug)    System.out.println("Fitted Track After Propagation:  "+ht.toString());
+
+                TrackError fitErr = fitET.error();
+                double kfDCA = fitET.vector().get(0);
+                double kfz0 = fitET.vector().get(1);
+                double kfphi0 = Math.sin(fitET.vector().get(2));
+                double kfslope = fitET.vector().get(3);
+                double kfqOverpt = fitET.vector().get(4);
+                aida.histogram1D(kaldir + "Kalman Fit Chi2", 50, 0, 100).fill(kfchi2);
+                aida.histogram1D(kaldir + "Kalman Fit DCA", 50, -0.5, 0.5).fill(kfDCA);
+                aida.histogram1D(kaldir + "Kalman Fit z0", 50, -0.25, 0.25).fill(kfz0);
+                aida.histogram1D(kaldir + "Kalman Fit sin(phi0)", 50, -0.2, 0.2).fill(kfphi0);
+                aida.histogram1D(kaldir + "Kalman Fit tanlambda", 50, -0.1, 0.1).fill(kfslope);
+                aida.histogram1D(kaldir + "Kalman Fit qOverpt", 50, -5, 5).fill(kfqOverpt);
+                aida.histogram1D(kaldir + "Kalman-Nominal DCA", 50, -.5, 0.5).fill(kfDCA - nomDCA);
+                aida.histogram1D(kaldir + "Kalman-Nominal z0", 50, -0.5, 0.5).fill(kfz0 - nomz0);
+                aida.histogram1D(kaldir + "Kalman-Nominal sin(phi0)", 50, -0.05, 0.05).fill(kfphi0 - nomphi0);
+                aida.histogram1D(kaldir + "Kalman-Nominal slope", 50, -0.05, 0.05).fill(kfslope - nomslope);
+                aida.histogram1D(kaldir + "Kalman-Nominal qOverpt", 50, -0.1, 0.1).fill(kfqOverpt - nomqOverpt);
+
+
+                }
+                 */
+
+                double d0 = helicalTrack.dca();
+                double z0 = helicalTrack.z0();
+                double slope = helicalTrack.slope();
+                double phi0 = helicalTrack.phi0();
+                double R = helicalTrack.R();
+                double sTarg = HelixUtils.PathToXPlane(helicalTrack, 0, 1e4, 1).get(0);
+                double phi = sTarg / R - phi0;
+
+
+                int fstarfBkg = fitk.fitBackward(ht);
+                double bkwdkfchi2 = ht.chisquared();
+
+                double mmTocm = 0.1;
+                double dcaX = mmTocm * HelixUtils.PointOnHelix(helicalTrack, 0).x();
+                double dcaY = mmTocm * HelixUtils.PointOnHelix(helicalTrack, 0).y();
+                if (_debug)
+                    System.out.println("Kalman Filter Driver:  DCA X=" + dcaX + "; Y=" + dcaY);
+//                SurfDCA s = new SurfDCA(dcaX, dcaY);
+                SurfDCA s = new SurfDCA(0, 0);
+//                 SurfXYPlane srfc = new SurfXYPlane(0.001, 0);
+
+                ht.propagate(prop, s, PropDir.BACKWARD);
+                ETrack bkwdET = ht.newTrack();
+                TrackError bkwdfitErr = bkwdET.error();
+                double bkwdkfDCA = bkwdET.vector().get(0);
+                double bkwdkfz0 = bkwdET.vector().get(1);
+                double bkwdkfphi0 = Math.sin(bkwdET.vector().get(2));
+                double bkwdkfslope = bkwdET.vector().get(3);
+                double bkwdkfqOverpt = bkwdET.vector().get(4);
+
+                aida.histogram1D(bkwdkaldir + "Kalman Fit Chi2", 50, 0, 100).fill(bkwdkfchi2);
+                aida.histogram1D(kaldir + "Nominal Fit Chi2", 50, 0, 100).fill(track.getChi2());
+                if (bkwdkfchi2 > 0) {
+
+                    aida.histogram1D(bkwdkaldir + "Kalman Fit DCA", 50, -0.1, 0.1).fill(bkwdkfDCA);
+                    aida.histogram1D(bkwdkaldir + "Kalman Fit z0", 50, -0.1, 0.1).fill(bkwdkfz0);
+                    aida.histogram1D(bkwdkaldir + "Kalman Fit sin(phi0)", 50, -0.2, 0.2).fill(bkwdkfphi0);
+                    aida.histogram1D(bkwdkaldir + "Kalman Fit tanlambda", 50, -0.1, 0.1).fill(bkwdkfslope);
+                    aida.histogram1D(bkwdkaldir + "Kalman Fit qOverpt", 50, -5, 5).fill(bkwdkfqOverpt);
+                    aida.histogram1D(bkwdkaldir + "Kalman-Nominal DCA", 50, -.1, 0.1).fill(bkwdkfDCA - nomDCA);
+                    aida.histogram1D(bkwdkaldir + "Kalman-Nominal z0", 50, -0.1, 0.1).fill(bkwdkfz0 - nomz0);
+                    aida.histogram1D(bkwdkaldir + "Kalman-Nominal sin(phi0)", 50, -0.05, 0.05).fill(bkwdkfphi0 - nomphi0);
+                    aida.histogram1D(bkwdkaldir + "Kalman-Nominal slope", 50, -0.05, 0.05).fill(bkwdkfslope - nomslope);
+                    aida.histogram1D(bkwdkaldir + "Kalman-Nominal qOverpt", 50, -0.1, 0.1).fill(bkwdkfqOverpt - nomqOverpt);
+                    aida.histogram1D(kaldir + "Nominal Fit DCA", 50, -0.1, 0.1).fill(nomDCA);
+                    aida.histogram1D(kaldir + "Nominal Fit z0", 50, -0.1, 0.1).fill(nomz0);
+                    aida.histogram1D(kaldir + "Nominal Fit sin(phi0)", 50, -0.2, 0.2).fill(nomphi0);
+                    aida.histogram1D(kaldir + "Nominal Fit tanlambda", 50, -0.1, 0.1).fill(nomslope);
+                    aida.histogram1D(kaldir + "Nominal Fit qOverpt", 50, -5, 5).fill(nomqOverpt);
+                }
+
+                MCParticle mcp=tkanal.getMCParticle();
+                VTrack vmcp=trackUtils.makeVTrack(mcp);
+                Hep3Vector pmc=trackUtils.getMomentum(vmcp);
+                Hep3Vector pkal=trackUtils.getMomentum(bkwdET);
+                Hep3Vector pnom=trackUtils.getMomentum(vt);
+
+                double pkaldiff=pkal.magnitude()-pmc.magnitude();
+                double pnomdiff=pnom.magnitude()-pmc.magnitude();
+                 aida.histogram1D(kaldir + "Kalman-MC Momentum Difference", 50, -0.2, 0.2).fill(pkaldiff);
+                    aida.histogram1D(kaldir + "Nominal-MC Momentum Difference", 50, -0.2, 0.2).fill(pnomdiff);
+                    
+            }
+        }
+
+
+    }
+//        } else {
+//            System.out.println("No tracks!");
+//        }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
KalmanGeom.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/KalmanGeom.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/KalmanGeom.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,564 @@
+package org.lcsim.hps.users.mgraham;
+
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ILogicalVolume;
+import org.lcsim.detector.IPhysicalVolume;
+import org.lcsim.detector.IReadout;
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.solids.ISolid;
+import org.lcsim.detector.solids.Point3D;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.recon.tracking.kalman.KalmanSurface;
+import org.lcsim.hps.recon.tracking.kalman.PropDCAXY;
+import org.lcsim.hps.recon.tracking.kalman.PropXYDCA;
+import org.lcsim.hps.recon.tracking.kalman.PropXYXY;
+import org.lcsim.hps.recon.tracking.kalman.ShapeDispatcher;
+import org.lcsim.hps.recon.tracking.kalman.util.PropDCAZ;
+import org.lcsim.recon.tracking.trfbase.ETrack;
+import org.lcsim.recon.tracking.trfbase.PropDispatch;
+import org.lcsim.recon.tracking.trfbase.Propagator;
+import org.lcsim.recon.tracking.trfbase.VTrack;
+import org.lcsim.recon.tracking.trfcyl.PropCyl;
+import org.lcsim.recon.tracking.trfcyl.SurfCylinder;
+import org.lcsim.recon.tracking.trfcylplane.PropCylZ;
+import org.lcsim.recon.tracking.trfcylplane.PropZCyl;
+import org.lcsim.recon.tracking.trfdca.PropCylDCA;
+import org.lcsim.recon.tracking.trfdca.PropDCACyl;
+import org.lcsim.recon.tracking.trfdca.SurfDCA;
+import org.lcsim.recon.tracking.trffit.HTrack;
+import org.lcsim.recon.tracking.trfxyp.ClusXYPlane2;
+import org.lcsim.recon.tracking.trfxyp.HitXYPlane2;
+import org.lcsim.recon.tracking.trfxyp.SurfXYPlane;
+import org.lcsim.recon.tracking.trfzp.PropZZ;
+import org.lcsim.recon.tracking.trfzp.SurfZPlane;
+
+/**
+ *
+ * Extract needed information from the geometry system and serve it
+ * to the callers in a convenient form.
+ *
+ *
+ *@author $Author: mgraham $
+ *@version $Id: KalmanGeom.java,v 1.5 2011/11/16 18:00:04 mgraham Exp $
+ *
+ * Date $Date: 2011/11/16 18:00:04 $
+ *
+ */
+/* To make the Kalman filter work for any detector, the type of hit that is
+ * added to the HTrack has to be determined based on the lcsim detector
+ * geometry. Additionally, this class has to be able to find the intersections
+ * between a track and the detector elements to be able to implement more
+ * realistic multiple scattering. Currently this class does not support
+ * any of this functionality, and just adds hits. However there are methods for
+ * looping through detector elements, etc. that may be useful for finding
+ * intersections at some point. (ecfine) */
+public class KalmanGeom {
+    boolean _DEBUG=false;
+//      boolean _DEBUG=true;
+    // TRF wants distances in cm, not mm.
+    private double mmTocm = 0.1;
+    // this flag is a temporary fix to avoid making a surface behind the origin in x.
+    private double flag = 0;
+//    //    private Array radius = null;
+//    private Subdetector sd_tbar  = null;
+//    private Subdetector sd_vbar  = null;
+//    private Subdetector sd_tec   = null;
+//    private Subdetector sd_vec   = null;
+//    private Subdetector sd_tfor  = null;
+//    private Subdetector sd_bpipe = null;
+//
+//    private IDetectorElement de_tbar  = null;
+//    private IDetectorElement de_vbar  = null;
+//    private IDetectorElement de_tec   = null;
+//    private IDetectorElement de_vec   = null;
+//    private IDetectorElement de_tfor  = null;
+    // Nominal magnetic field.
+    public double bz = 0.5;
+    // Lists of interesting surfaces.
+    public List<KalmanSurface> Surf = new ArrayList<KalmanSurface>();
+    KalmanSurface surf = null;
+    // Specific surface type A to surface type B propagators.
+    private PropCyl propcyl = null;
+    private PropZZ propzz = null;
+    private PropDCACyl propdcacyl = null;
+    private PropCylDCA propcyldca = null;
+    private PropZCyl propzcyl = null;
+    private PropCylZ propcylz = null;
+    private PropXYXY propxyxy = null;
+    private PropDCAZ propdcaz = null;
+    private PropDCAXY propdcaxy = null;
+    private PropXYDCA propxydca = null;
+//    private PropZDCA propzdca     = null;
+    // The master propagator that can go between any pair of surfaces.
+    private PropDispatch pDispatch = null;
+    // The run time configuration system.
+    //ToyConfig config;
+    // Information from the run time configuration system.
+//    double  respixel;
+//    double  resstrip;
+//    boolean trackerbarrel2d;         
+//    double  zres2dTrackerBarrel;
+//    boolean vtxFwdEquivStrips;
+    // Does this detector have forward tracking.
+    boolean hasforward = false;
+    // Stuff for adding surfaces
+    static ArrayList physicalVolumes = new ArrayList();
+    ILogicalVolume logical;
+    ShapeDispatcher shapeDispatcher = new ShapeDispatcher();
+    Detector detector = null;
+
+    public KalmanGeom(Detector det) {
+        detector = det;
+        System.out.println("New detector: " + detector.getName());
+        logical = detector.getTrackingVolume().getLogicalVolume();
+
+        // Extract information from the run time configuration system.
+        //	try{
+        //	    ToyConfig config = ToyConfig.getInstance();
+        //	    respixel            = config.getDouble("respixel");
+        //	    resstrip            = config.getDouble("resstrip");
+        //	    trackerbarrel2d     = config.getBoolean("trackerbarrel2d");
+        //	    zres2dTrackerBarrel = config.getDouble("zres2dTrackerBarrel");
+        //	    vtxFwdEquivStrips   = config.getBoolean("vtxFwdEquivStrips");
+        //
+        //	} catch (ToyConfigException e){
+        //            System.out.println (e.getMessage() );
+        //            System.out.println ("Stopping now." );
+        //            System.exit(-1);
+        //        }
+
+
+
+        //	Map<String, Subdetector> subDetMap = detector.getSubdetectors();
+        //
+        //	Subdetector sd_tbar = subDetMap.get("TrackerBarrel");
+        //	Subdetector sd_vbar = subDetMap.get("VertexBarrel");
+        //	Subdetector sd_tec  = subDetMap.get("TrackerEndcap");
+        //	Subdetector sd_vec  = subDetMap.get("VertexEndcap");
+        //	Subdetector sd_tfor = subDetMap.get("TrackerForward");
+        //	Subdetector sd_bpipe  = subDetMap.get("BeamPipe");
+        //	System.out.println ("Checking .... " + sd_tbar + " | " + sd_tfor);
+        // Don't use subdetectors anymore...
+
+        //	 Check for forward tracking system.
+        //	if ( sd_tfor == null ) {
+        //	    System.out.println ("Checking 1 .... " );
+        //	    if ( detector.getName().compareTo("sid00") != 0 ){
+        //		System.out.println("Expected to find a TrackerForward Subdetector but did not!");
+        //		System.exit(-1);
+        //	    }
+        //	}else{
+        //	    System.out.println ("Checking 2  .... " );
+        //
+        //	    hasforward = true;
+        //	}           // I may want to implement something like this at some point but not now.
+
+        //	if ( hasforward ){
+        //	    de_tfor = sd_tfor.getDetectorElement();
+        //	}
+
+        /* Cycle through detector and add all surfaces to the surface list. */
+        //    addAllSurfaces();
+
+        System.out.println("Number of surfaces: " + Surf.size());
+        for (KalmanSurface surf : Surf) {
+            surf.Print();
+        }
+
+
+        double[] origin = {0., 0., 0.};
+
+//    	Map<String,Field> fields = detector.getFields();
+//    	Set<String> keys = fields.keySet();
+//    	for ( String key : keys ){
+//    	    Field field = fields.get(key);
+//    	    String classname = field.getClass().getName();
+//    	    String shortname = classname.replaceAll( "org.lcsim.geometry.field.", "");
+//    	    if ( shortname.compareTo("Solenoid") != 0 ){
+//    		System.out.println("Expected, but did not find, a solenoid: " + shortname );
+////    		System.exit(-1);
+//    	    }
+//    	    Solenoid s = (Solenoid)field;
+//    	    bz = s.getInnerField()[2];
+//    	    if ( bz == 0. ){
+//    		System.out.println("This code will not work with a magnetic field of 0: " + shortname );
+////    		System.exit(-1);
+//    	    }
+//    	    break;
+//    	}
+
+        // Instantiate surface-pair specific propagators.
+        propcyl = new PropCyl(bz);
+        propzz = new PropZZ(bz);
+        propdcacyl = new PropDCACyl(bz);
+        propcyldca = new PropCylDCA(bz);
+        propzcyl = new PropZCyl(bz);
+        propcylz = new PropCylZ(bz);
+        propxyxy = new PropXYXY(bz);
+        propdcaxy = new PropDCAXY(bz);
+        propxydca = new PropXYDCA(bz);
+        //	propdcaz   = new PropDCAZ(bz);
+        //	propzdca   = new PropZDCA(bz);
+        // Again, need xy plane propagators!
+
+        // Instantiate and configure the general purpose propagator.
+        pDispatch = new PropDispatch();
+        pDispatch.addPropagator(SurfZPlane.staticType(), SurfZPlane.staticType(), propzz);
+        pDispatch.addPropagator(SurfCylinder.staticType(), SurfCylinder.staticType(), propcyl);
+        pDispatch.addPropagator(SurfDCA.staticType(), SurfCylinder.staticType(), propdcacyl);
+        pDispatch.addPropagator(SurfCylinder.staticType(), SurfDCA.staticType(), propcyldca);
+        pDispatch.addPropagator(SurfZPlane.staticType(), SurfCylinder.staticType(), propzcyl);
+        pDispatch.addPropagator(SurfCylinder.staticType(), SurfZPlane.staticType(), propcylz);
+        pDispatch.addPropagator(SurfXYPlane.staticType(), SurfXYPlane.staticType(), propxyxy);
+        pDispatch.addPropagator(SurfDCA.staticType(), SurfXYPlane.staticType(), propdcaxy);
+        pDispatch.addPropagator(SurfXYPlane.staticType(), SurfDCA.staticType(), propxydca);
+        //	pDispatch.addPropagator( SurfDCA.staticType(),      SurfZPlane.staticType(),   propdcaz);
+        //	pDispatch.addPropagator( SurfZPlane.staticType(),   SurfDCA.staticType(),      propzdca);
+
+    }
+
+    public Propagator newPropagator() {
+        // Clone not supported for pDispatch.
+        //return pDispatch.newPropagator();
+        return (Propagator) pDispatch;
+    }
+
+//    public List<RKSurf> getCylinders(){
+//	return Surf;
+//    }
+//    public List<RKSurf> getZplus(){
+//	return ZSurfplus;
+//    }
+//
+//    public List<RKSurf> getZMinus(){
+//	return ZSurfminus;
+//    }   
+    public double getBz() {
+        return bz;
+    }
+
+    public void setBz(double bfield) {
+        bz = bfield;
+    }
+
+//   Return a list of z surfaces, going foward along the track.
+//    public List<RKSurf> getZ( double z0, double cz ){
+//	List<RKSurf> zlist = new ArrayList<RKSurf>();
+//	if ( cz > 0 ){
+//	    for ( Iterator ihit=ZSurfAll.iterator(); ihit.hasNext(); ){
+//		RKSurf s = (RKSurf) ihit.next();
+//		if ( s.zc >= z0 ){
+//		    zlist.add(s);
+//		}
+//	    }
+//	} else if ( cz < 0 ){
+//	    for ( ListIterator ihit=ZSurfAll.listIterator(ZSurfAll.size());
+//		  ihit.hasPrevious(); ){
+//		RKSurf s = (RKSurf) ihit.previous();
+//		if ( s.zc <= z0 ){
+//		    zlist.add(s);
+//		}
+//	    }
+//	}
+//
+//	return zlist;
+//    }  
+    // Adds all surfaces to the surface list
+    private void addAllSurfaces() {
+        addDaughterSurfaces(logical);
+    }
+
+    private void addDaughterSurfaces(ILogicalVolume logical) {
+        if (logical.getDaughters().size() == 0) {
+            // need to avoid making surface for target. for now, flag..
+            flag++;
+            if (flag > 5) {
+                surf = shapeDispatcher.getKalmanSurf(logical.getSolid());
+                Surf.add(surf);
+            }
+        }
+        for (int n = 0; n < logical.getNumberOfDaughters(); n++) {
+            IPhysicalVolume physical = logical.getDaughter(n);
+            addDaughterSurfaces(physicalToLogical(physical));
+            physicalVolumes.remove(physicalVolumes.size() - 1);
+        }
+    }
+
+    // Given a point, find the solid that contains it. Doesn't work.
+    private ISolid findSolidFromPoint(Point3D hitPoint) {
+        ISolid solid = checkDaughterSurfaces(logical, hitPoint);
+        return solid;
+    }
+
+    private ISolid checkDaughterSurfaces(ILogicalVolume logical, Point3D hitPoint) {
+        if (logical.getDaughters().size() == 0) {
+            if (pointIsOnSolid(logical.getSolid(), hitPoint)) {
+                return logical.getSolid();
+            }
+        }
+        for (int n = 0; n < logical.getNumberOfDaughters(); n++) {
+            IPhysicalVolume physical = logical.getDaughter(n);
+            checkDaughterSurfaces(physicalToLogical(physical), hitPoint);
+            physicalVolumes.remove(physicalVolumes.size() - 1);
+        }
+        System.out.print("This hit isn't on a solid!");
+        return null;
+    }
+
+    // Given a TrackerHit, return the surface the hit should be placed on. Doesn't work.
+    private KalmanSurface findTrackerHitSurface(TrackerHit thit) {
+        double[] position = thit.getPosition();
+        Point3D hitPoint = new Point3D(position[0], position[1], position[2]);
+        ISolid hitSolid = findSolidFromPoint(hitPoint);
+        KalmanSurface hitSurf = getKSurfFromSolid(hitSolid);
+        return hitSurf;
+    }
+
+    private KalmanSurface getKSurfFromSolid(ISolid hitSolid) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    // Adds the physical volume to the physicalVolumes ArrayList.
+    private ILogicalVolume physicalToLogical(IPhysicalVolume physical) {
+        physicalVolumes.add(physical.getTransform());
+        return physical.getLogicalVolume();
+    }
+
+    // Adds intercepts between a HTrack and the detector. Doesn't work.
+    public void addIntercepts(HTrack ht, Detector detector) {
+        logical = detector.getTrackingVolume().getLogicalVolume();
+        addDaughterIntercepts(logical, ht);
+    }
+
+    private void addDaughterIntercepts(ILogicalVolume logical, HTrack ht) {
+        if (logical.getDaughters().size() == 0) {
+            ht = shapeDispatcher.addIntercept(logical.getSolid(), ht);
+        }
+        for (int n = 0; n < logical.getNumberOfDaughters(); n++) {
+            IPhysicalVolume physical = logical.getDaughter(n);
+            addDaughterIntercepts(physicalToLogical(physical), ht);
+            physicalVolumes.remove(physicalVolumes.size() - 1);
+        }
+    }
+
+    // Add a hit from an lcsim Track to a trf HTrack.
+    public HTrack addTrackerHit(TrackerHit thit, HTrack htrack, HelicalTrackFit track,
+            VTrack vtrack) {
+        /* This should check the kind of solid that got hit and model it as the
+         * correct surface based on the solid dimensions. For now it just
+         * assumes XY planes. */
+
+        double[] position = thit.getPosition();
+        if (position.length != 3) {
+            System.out.println("Position has more than 3 coordinates?!");
+        }
+
+
+//        // For checking surfaces
+//        KalmanSurface surface= findTrackerHitSurface(thit);
+//        PropStat prop = new PropStat();
+//        prop.setForward();
+//        double path = (position[2] - track.z0())/track.slope();
+//        KalmanHit khit = new KalmanHit(track, surface, vtrack, prop, path);
+//        Hit hit = khit.MakeHit();
+//        Point3D hitPoint = new Point3D(position[0], position[1], position[2]);
+//        ISolid hitSolid = findSolidFromPoint(hitPoint);
+
+        // Need an ETrack to add hits from clusters.
+        ETrack tre = htrack.newTrack();
+
+        // This also assumes the hit in question is a Helical Track Cross.
+        HelicalTrackCross htrackcross = (HelicalTrackCross) thit;
+        HelicalTrackStrip strip1 = (HelicalTrackStrip) htrackcross.getStrips().get(0);
+        HelicalTrackStrip strip2 = (HelicalTrackStrip) htrackcross.getStrips().get(1);
+
+        double dist1 = dotProduct(strip1.origin(), strip1.w());
+        double dist2 = dotProduct(strip2.origin(), strip2.w());
+      
+            if(_DEBUG)System.out.println("TrackerHit Position = [" + thit.getPosition()[0] + "," + thit.getPosition()[1] + "," + thit.getPosition()[2]);
+
+
+
+
+        /*
+        double phi1 = Math.atan2(strip1.w().y()*dist1*strip1.origin().y(), strip1.w().x()*dist1*strip1.origin().x());
+        double phi2 = Math.atan2(strip2.w().y()*dist2*strip2.origin().y(), strip2.w().x()*dist2*strip2.origin().x());
+        // phi needs to be between 0 and 2PI. Additionally, it seemed like
+        // rounding errors caused problems for very small negative values of phi,
+        // so these are approximated as 0.
+        if (phi1 < 0){
+        if (phi1 > -0.00000001){
+        phi1 = 0;
+        } else{
+        phi1 = phi1 + 2*Math.PI;
+        }
+        }
+        if(phi2 < 0 ){
+        if(phi2 > -0.00000001) {
+        phi2 = 0;
+        } else{
+        phi2 = phi2 + 2*Math.PI;
+        }
+        }
+         */
+        //set phis to 0 ... normal parallel to x-axis (mis-alignment can change this)
+        double phi1 = 0;
+        double phi2 = 0;
+
+        if(_DEBUG){
+        System.out.println("Origin of strip1: " + strip1.origin());
+        System.out.println("Origin of strip2: " + strip2.origin());
+        System.out.println("dist1: " + dist1 + ", phi1: " + phi1);
+        System.out.println("dist2: " + dist2 + ", phi2: " + phi2);
+        System.out.println("Strip 1 Measurement   "+strip1.umeas());
+        System.out.println("Strip 2 Measurement   "+strip2.umeas());
+        }
+        /*
+        // ClusXYPlane needs wz, wv, avz, phi and dist to create a cluster.
+        double wz1 = strip1.u().z();
+        double wz2 = strip2.u().z();
+        double wv1 = strip1.u().x() * (-Math.sin(phi1)) + strip1.u().y() * Math.cos(phi1);
+        double wv2 = strip2.u().x() * (-Math.sin(phi2)) + strip2.u().y() * Math.cos(phi2);         
+         */
+/*
+
+        double avz1 = strip1.umeas()
+                - (dist1 * (Math.cos(phi1) * strip1.u().x() + Math.sin(phi1) * strip1.u().y())
+                - (strip1.origin().x() * strip1.u().x() + strip1.origin().y() * strip1.u().y()
+                + strip1.origin().z() * strip1.u().z()));
+        double avz2 = strip2.umeas()
+                - (dist2 * (Math.cos(phi2) * strip2.u().x() + Math.sin(phi2) * strip2.u().y())
+                - (strip2.origin().x() * strip2.u().x() + strip2.origin().y() * strip2.u().y()
+                + strip2.origin().z() * strip2.u().z()));
+        double davz1 = strip1.du();
+        double davz2 = strip2.du();
+
+*/
+//        if(_DEBUG)System.out.println("wz1 = " + wz1 + ", wv1 = " + wv1 + ", avz1 = " + avz1 + ", davz1 =" + davz1);
+//        if(_DEBUG)System.out.println("wz2 = " + wz2 + ", wv2 = " + wv2 + ", avz2 = " + avz2 + ", davz2 =" + davz2);
+//        ClusXYPlane1 cluster1 = new ClusXYPlane1(dist1, phi1, wv1, wz1, avz1, davz1);
+//        ClusXYPlane1 cluster2 = new ClusXYPlane1(dist2, phi2, wv2, wz2, avz2, davz2);
+
+        //Creat a ClusXYPlane2 ... needs v(=y),z, dy,dz
+        Hep3Vector sorigin1 = strip1.origin();
+        Hep3Vector u1 = strip1.u();
+        double umeas1 = strip1.umeas();
+        Hep3Vector uvec1 = VecOp.mult(umeas1, u1);
+        Hep3Vector clvec1 = VecOp.add(sorigin1, uvec1);
+        double dumeas1 = strip1.du();
+        double dustrip1 = (strip1.vmax() - strip1.vmin()) / Math.sqrt(12);
+
+        Hep3Vector sorigin2 = strip2.origin();
+        Hep3Vector u2 = strip2.u();
+        double umeas2 = strip2.umeas();
+        Hep3Vector uvec2 = VecOp.mult(umeas2, u2);
+        Hep3Vector clvec2 = VecOp.add(sorigin2, uvec2);
+        double dumeas2 = strip2.du();
+        double dustrip2 = (strip2.vmax() - strip2.vmin()) / Math.sqrt(12);
+
+        double z1 = clvec1.z();
+        double z2 = clvec2.z();
+        //this is the non-z distance of the cluster (in our case, phi=0, so it's just y)
+        double v1 = clvec1.x() * (-Math.sin(phi1)) + clvec1.y() * Math.cos(phi1);
+        double v2 = clvec2.x() * (-Math.sin(phi2)) + clvec2.y() * Math.cos(phi2);
+
+        //transform umeas, ustrip to z and v
+        ITransform3D t1 = getLocalToGlobal((RawTrackerHit) strip1.rawhits().get(0));
+        ITransform3D t2 = getLocalToGlobal((RawTrackerHit) strip2.rawhits().get(0));
+        SymmetricMatrix tmpcov1 = new SymmetricMatrix(3);
+        tmpcov1.setElement(0, 0, dumeas1 * dumeas1);
+        tmpcov1.setElement(2, 2, dustrip1 * dustrip1);
+        SymmetricMatrix tmpcov2 = new SymmetricMatrix(3);
+        tmpcov2.setElement(0, 0, dumeas2 * dumeas2);
+        tmpcov2.setElement(2, 2, dustrip2 * dustrip2);
+
+
+
+        t1.rotate(tmpcov1);
+        t2.rotate(tmpcov2);
+        double dz1 = tmpcov1.e(2, 2);
+        double dz2 = tmpcov2.e(2, 2);
+        double dv1 = tmpcov1.e(1, 1);
+        double dv2 = tmpcov2.e(1, 1);
+
+        double dzv1 = tmpcov1.e(1, 2);
+        double dzv2 = tmpcov2.e(1, 2);
+        if(_DEBUG){
+            System.out.println("z1 = " + z1 + "+/-" + Math.sqrt(dz1) + ", v1 = " + v1 + "+/-" + Math.sqrt(dv1) + ", cov(z,v) = " + dzv1);
+            System.out.println("z2 = " + z2 + "+/-" + Math.sqrt(dz2) + ", v2 = " + v2 + "+/-" + Math.sqrt(dv2) + ", cov(z,v) = " + dzv2);
+        }
+//        ClusXYPlane2 cluster1 = new ClusXYPlane2(dist1, phi1, v1, z1, dv1, dz1,dzv1);
+//        ClusXYPlane2 cluster2 = new ClusXYPlane2(dist2, phi2, v2, z2, dv2, dz2,dzv2);
+
+        ClusXYPlane2 cluster1 = new ClusXYPlane2(dist1 * mmTocm, phi1, v1 * mmTocm, z1 * mmTocm, dv1 * mmTocm * mmTocm, dz1 * mmTocm * mmTocm, dzv1 * mmTocm * mmTocm);
+        ClusXYPlane2 cluster2 = new ClusXYPlane2(dist2 * mmTocm, phi2, v2 * mmTocm, z2 * mmTocm, dv2 * mmTocm * mmTocm, dz2 * mmTocm * mmTocm, dzv2 * mmTocm * mmTocm);
+        // Create new clusters and get hit predictions.
+        
+        List hits1 = cluster1.predict(tre);
+        List hits2 = cluster2.predict(tre);
+        HitXYPlane2 hit1 = (HitXYPlane2) hits1.get(0);
+        HitXYPlane2 hit2 = (HitXYPlane2) hits2.get(0);
+        hit1.setParentPointer(cluster1);
+        hit2.setParentPointer(cluster2);
+        if(_DEBUG){
+            System.out.println("Cluster 1:\n"+cluster1.toString());
+        System.out.println("Cluster 2:\n"+cluster2.toString());
+           System.out.println("hit1 predicted vector: " + hit1.toString());
+          System.out.println("hit2 predicted vector: " + hit2.toString());
+            System.out.println("hit position from trackerhit: [" + thit.getPosition()[0] + ", " +
+                thit.getPosition()[1] + ", " + thit.getPosition()[2] + "]");
+        }
+
+        htrack.addHit(hit1);
+        htrack.addHit(hit2);
+
+        return htrack;
+
+    }
+
+    private boolean pointIsOnSolid(ISolid solid, Point3D hitPoint) {
+        return shapeDispatcher.pointIsOnSolid(solid, hitPoint);
+    }
+
+    private double dotProduct(Hep3Vector v1, Hep3Vector v2) {
+        double dotProduct = v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z();
+        return dotProduct;
+    }
+
+    private ITransform3D getLocalToGlobal(RawTrackerHit raw_hit) {
+        ITransform3D foobar = null;
+        IIdentifier id = raw_hit.getIdentifier();
+
+        IDetectorElement detector_de = detector.getDetectorElement();
+        Set<SiSensor> _process_sensors = new HashSet<SiSensor>();
+        _process_sensors.addAll(detector_de.findDescendants(SiSensor.class));
+        for (SiSensor sensor : _process_sensors) {
+            SiSensorElectrodes electrodes = sensor.getReadoutElectrodes(ChargeCarrier.HOLE);
+            IReadout readout = sensor.getReadout();
+            List<RawTrackerHit> raw_hits = readout.getHits(RawTrackerHit.class);
+            for (RawTrackerHit rh : raw_hits)
+                if (rh.equals(raw_hit))
+                    return ((SiSensor) electrodes.getDetectorElement()).getGeometry().getLocalToGlobal();
+        }
+        System.out.println("KalmanGeom:  Didn't find the hit!");
+        return foobar;
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
MainJASDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/MainJASDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/MainJASDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,55 @@
+package org.lcsim.hps.users.mgraham;
+
+import org.lcsim.hps.recon.tracking.DataTrackerHitDriver;
+import org.lcsim.hps.conditions.CalibrationDriver;
+import org.lcsim.hps.recon.tracking.*;
+import org.lcsim.recon.tracking.digitization.sisim.config.RawTrackerHitSensorSetup;
+import org.lcsim.util.Driver;
+
+/**
+ * Driver for track reconstruction and analysis of HPS detector for execution in JAS.
+ *
+ * @author M. Graham 
+ */
+public final class MainJASDriver extends Driver {
+
+
+
+    public MainJASDriver() {
+//        add(new HPSSVTSensorSetup());
+        add(new CalibrationDriver());
+        add(new RawTrackerHitSensorSetup());
+        //   Can remove HPSRawTrackerHitFitterDriver and DataTrackerHitDriver for integrated MC
+        HPSRawTrackerHitFitterDriver hitfitter=new HPSRawTrackerHitFitterDriver();
+        hitfitter.setCorrectT0Shift(true);
+        hitfitter.setFitAlgorithm("Analytic");
+        add(hitfitter);
+        add(new DataTrackerHitDriver());
+        
+//        add(new TrackerDigiDriver());  //add for integrated MC
+        HelicalTrackHitDriver hth = new HelicalTrackHitDriver();
+        hth.setClusterTimeCut(8.0);
+        
+//        SingleSensorHelicalTrackHitDriver hth = new SingleSensorHelicalTrackHitDriver();
+        hth.setMaxSeperation(20.0);
+        hth.setTolerance(1.0);
+        add(hth);
+        TrackerReconDriver trd=new TrackerReconDriver();
+        
+//          trd.setStrategyResource("/org/lcsim/hps/recon/tracking/strategies/HPS-SingleSensors.xml");
+        trd.setStrategyResource("/org/lcsim/hps/recon/tracking/strategies/HPS-Full.xml");
+//    trd.setStrategyResource("/org/lcsim/hps/recon/tracking/strategies/HPS-Test-Lyr50.xml");
+        trd.setDebug(true);
+        add(trd);
+//
+        DetailedAnalysisDriver dad=new DetailedAnalysisDriver(12);
+        dad.setRawHitsName("SVTRawTrackerHits");
+        add(dad);
+
+//        add(new FastTrackAnalysisDriver());
+        
+       
+    }
+
+  
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
MyLCIOWriterDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/MyLCIOWriterDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/MyLCIOWriterDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,90 @@
+package org.lcsim.hps.users.mgraham;
+
+import java.io.IOException;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.util.Driver;
+import org.lcsim.lcio.LCIOWriter;
+
+/**
+ *
+ * @author mgraham Created 5/17/2012 really the same as
+ * org.lcsim.util.LCIODriver but only write events that pass some condition
+ * (e.g. has a reconstructed track)
+ */
+public class MyLCIOWriterDriver extends Driver {
+
+    private String outputFile;
+    private LCIOWriter writer;
+    private String trackCollectionName = "MatchedTracks";
+
+    public MyLCIOWriterDriver() {
+    }
+
+    public void setOutputFilePath(String output) {
+        this.outputFile = output;
+    }
+    
+      public void setTrackCollectionNamePath(String trackCollection) {
+        this.trackCollectionName = trackCollection;
+    }
+
+    private void setupWriter() {
+        // Cleanup existing writer.
+        if (writer != null) {
+            try {
+                writer.flush();
+                writer.close();
+                writer = null;
+            } catch (IOException x) {
+                System.err.println(x.getMessage());
+            }
+        }
+
+        // Setup new writer.
+        try {
+            writer = new LCIOWriter(outputFile);
+        } catch (IOException x) {
+            throw new RuntimeException("Error creating writer", x);
+        }
+
+
+        try {
+            writer.reOpen();
+        } catch (IOException x) {
+            throw new RuntimeException("Error rewinding LCIO file", x);
+        }
+    }
+
+    protected void startOfData() {
+        setupWriter();
+    }
+
+    protected void endOfData() {
+        try {
+            writer.close();
+        } catch (IOException x) {
+            throw new RuntimeException("Error rewinding LCIO file", x);
+        }
+    }
+
+    protected void process(EventHeader event) {
+        if (event.get(Track.class, trackCollectionName).size()>1) {
+            System.out.println("found a two track event...writing to lcio file");
+            try {
+                
+                writer.write(event);
+            } catch (IOException x) {
+                throw new RuntimeException("Error writing LCIO file", x);
+            }
+        }
+    }
+
+    protected void suspend() {
+        try {
+            writer.flush();
+        } catch (IOException x) {
+            throw new RuntimeException("Error flushing LCIO file", x);
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
PropXYXY_Test.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/PropXYXY_Test.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/PropXYXY_Test.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,530 @@
+/*
+ * PropXYXY_Test.java
+ *
+ * Created on July 24, 2007, 10:15 PM
+ *
+ * $Id: PropXYXY_Test.java,v 1.2 2011/07/07 20:57:39 mgraham Exp $
+ */
+
+package org.lcsim.hps.users.mgraham;
+
+//import junit.framework.TestCase;
+import org.lcsim.hps.recon.tracking.kalman.PropXYXY;
+import org.lcsim.recon.tracking.spacegeom.SpacePath;
+import org.lcsim.recon.tracking.spacegeom.SpacePoint;
+import org.lcsim.recon.tracking.trfbase.ETrack;
+import org.lcsim.recon.tracking.trfbase.PropDir;
+import org.lcsim.recon.tracking.trfbase.PropStat;
+import org.lcsim.recon.tracking.trfbase.Propagator;
+import org.lcsim.recon.tracking.trfbase.Surface;
+import org.lcsim.recon.tracking.trfbase.TrackDerivative;
+import org.lcsim.recon.tracking.trfbase.TrackError;
+import org.lcsim.recon.tracking.trfbase.TrackVector;
+import org.lcsim.recon.tracking.trfbase.VTrack;
+import org.lcsim.recon.tracking.trfutil.Assert;
+import org.lcsim.recon.tracking.trfxyp.SurfXYPlane;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author Norman Graf
+ */
+public class PropXYXY_Test extends Driver
+{
+    private boolean debug=true;
+    /** Creates a new instance of PropXYXY_Test */
+    public void testPropXYXY()
+    {
+        String ok_prefix = "PropXYXY (I): ";
+        String error_prefix = "PropXYXY test (E): ";
+        
+        if(debug) System.out.println( ok_prefix
+                + "-------- Testing component PropXYXY. --------" );
+        
+        
+        //********************************************************************
+        
+        if(debug) System.out.println( ok_prefix + "Test constructor." );
+        PropXYXY prop = new PropXYXY(0.5);
+        if(debug) System.out.println( prop );
+        
+        //********************************************************************
+        
+        // Here we propagate some tracks both forward and backward and then
+        // each back to the original track.  We check that the returned
+        // track parameters match those of the original track.
+        if(debug) System.out.println( ok_prefix + "Check reversibility." );
+        
+        double u1[]  ={10.,      10.,     10.,     10.,     10.,     10.,10.,10.};
+        double u2[]  ={10.,      10.,     10.,     10.,     10.,     10.,11.,11.};
+//        double phi1[]={  Math.PI/2.,    Math.PI/2.,   Math.PI/2.,   Math.PI/2.,   Math.PI/2.,   Math.PI/2., Math.PI/2.,0};
+//        double phi2[]={5*Math.PI/6.,  5*Math.PI/6., 5*Math.PI/6., 5*Math.PI/6., 5*Math.PI/6., 5*Math.PI/6., 5*Math.PI/6.,0};
+        double phi1[]={  Math.PI/2.,    Math.PI/2.,   Math.PI/2.,   Math.PI/2.,   Math.PI/2.,   Math.PI/2., 0,0};
+        double phi2[]={5*Math.PI/6.,  5*Math.PI/6., 5*Math.PI/6., 5*Math.PI/6., 5*Math.PI/6., 5*Math.PI/6., 0,0};
+        int sign_du[]={  1,       -1,      -1,       1,       1,       1 ,  1  ,1};
+        double v[]   ={ -2.,       2.,     40.,     40.,     -2.,     -2.,  2. ,2 };
+        double z[]   ={  3.,       3.,      3.,      3.,      3.,      3.,  3. ,3};
+        double dvdu[]={-1.5,     -1.5,     1.5,     1.5,    -1.5,      0.,  1.5 ,1.5 };
+        double dzdu[]={ 2.3,     -2.3,    -2.3,     2.3,     0.,       2.3,  2.3   ,-2.3};
+        double qp[]  ={ 0.05,    -0.05,    0.05,   -0.05,    0.05,     0.05, 0.05  ,0.5};
+        
+        double maxdiff = 1.e-7;
+        int ntrk = 8;
+        int i;
+        for ( i=0; i<ntrk; ++i )
+        {
+            if(debug) System.out.println( "********** Propagate track " + i + ". **********" );
+            PropStat pstat = new PropStat();
+            SurfXYPlane sxyp1 = new SurfXYPlane(u1[i],phi1[i]);
+            SurfXYPlane sxyp2= new SurfXYPlane(u2[i],phi2[i]);
+            TrackVector vec1 = new TrackVector();
+            vec1.set(SurfXYPlane.IV     ,v[i]);     // v
+            vec1.set(SurfXYPlane.IZ     ,z[i]);     // z
+            vec1.set(SurfXYPlane.IDVDU  ,dvdu[i]);  // dv/du
+            vec1.set(SurfXYPlane.IDZDU  ,dzdu[i]);  // dz/du
+            vec1.set(SurfXYPlane.IQP    ,qp[i]);    //  q/p
+            
+            VTrack trv1 = new VTrack(sxyp1.newPureSurface(),vec1);
+            if (sign_du[i]==1) trv1.setForward();
+            else trv1.setBackward();
+            if(debug) System.out.println( " starting: " + trv1 );
+            System.out.println("PropDir.FORWARD_MOVE");
+            VTrack trv2f = new VTrack(trv1);
+            pstat = prop.vecDirProp(trv2f,sxyp2,PropDir.FORWARD_MOVE);
+            if(debug) System.out.println( pstat );
+            if(debug) System.out.println("pstat= "+pstat);
+            Assert.assertTrue( pstat.forward() );
+            if(debug) System.out.println( "  forward: " + trv2f );
+            Assert.assertTrue(check_dz(trv1,trv2f)>=0.);
+
+              System.out.println("PropDir.BACKWARD");
+            VTrack trv2b = new VTrack(trv1);
+            pstat = prop.vecDirProp(trv2b,sxyp2,PropDir.BACKWARD);
+            if(debug) System.out.println( pstat );
+            Assert.assertTrue( pstat.backward() );
+            if(debug) System.out.println( " backward: " + trv2b );
+            Assert.assertTrue(check_dz(trv1,trv2b)<=0.);
+
+             System.out.println("PropDir.BACKWARD_MOVE");
+            VTrack trv2fb = new VTrack(trv2f);
+            pstat = prop.vecDirProp(trv2fb,sxyp1,PropDir.BACKWARD_MOVE);
+            if(debug) System.out.println( pstat );
+            Assert.assertTrue( pstat.backward() );
+            if(debug) System.out.println( " f return: " + trv2fb );
+            Assert.assertTrue(check_dz(trv2f,trv2fb)<=0.);
+            
+             System.out.println("PropDir.FORWARD");
+            VTrack trv2bf = new VTrack(trv2b);
+            pstat = prop.vecDirProp(trv2bf,sxyp1,PropDir.FORWARD);
+            if(debug) System.out.println( pstat );
+            Assert.assertTrue( pstat.forward() );
+            if(debug) System.out.println( " b return: " + trv2bf );
+            Assert.assertTrue(check_dz(trv2b,trv2bf)>=0.);
+            
+            double difff =
+                    sxyp1.vecDiff(trv2fb.vector(),trv1.vector()).amax();
+            double diffb =
+                    sxyp1.vecDiff(trv2bf.vector(),trv1.vector()).amax();
+            if(debug) System.out.println( "diffs: " + difff + ' ' + diffb );
+            Assert.assertTrue( difff < maxdiff );
+            Assert.assertTrue( diffb < maxdiff );
+            
+        }
+        
+        //********************************************************************
+        
+        // Repeat the above with errors.
+        if(debug) System.out.println( ok_prefix + "Check reversibility with errors." );
+        double evv[] =   {  0.01,   0.01,   0.01,   0.01,   0.01,   0.01  };
+        double evz[] =   {  0.01,  -0.01,   0.01,  -0.01,   0.01,  -0.01  };
+        double ezz[] =   {  0.25,   0.25,   0.25,   0.25,   0.25,   0.25, };
+        double evdv[] =  {  0.004, -0.004,  0.004, -0.004,  0.004, -0.004 };
+        double ezdv[] =  {  0.04,  -0.04,   0.04,  -0.04,   0.04,  -0.04, };
+        double edvdv[] = {  0.01,   0.01,   0.01,   0.01,   0.01,   0.01  };
+        double evdz[] =  {  0.004, -0.004,  0.004, -0.004,  0.004, -0.004 };
+        double edvdz[] = {  0.004, -0.004,  0.004, -0.004,  0.004, -0.004 };
+        double ezdz[] =  {  0.04,  -0.04,   0.04,  -0.04,   0.04,  -0.04  };
+        double edzdz[] = {  0.02,   0.02,   0.02,   0.02,   0.02,   0.02  };
+        double evqp[] =  {  0.004, -0.004,  0.004, -0.004,  0.004, -0.004 };
+        double ezqp[] =  {  0.004, -0.004,  0.004, -0.004,  0.004, -0.004 };
+        double edvqp[] = {  0.004, -0.004,  0.004, -0.004,  0.004, -0.004 };
+        double edzqp[] = {  0.004, -0.004,  0.004, -0.004,  0.004, -0.004 };
+        double eqpqp[] = {  0.01,   0.01,   0.01,   0.01,   0.01,   0.01  };
+        
+        maxdiff = 1.e-6;
+        
+        for ( i=0; i<ntrk; ++i )
+        {
+            if(debug) System.out.println( "********** Propagate track " + i + ". **********" );
+            PropStat pstat = new PropStat();
+            SurfXYPlane sxyp1 = new SurfXYPlane(u1[i],phi1[i]);
+            SurfXYPlane sxyp2 = new SurfXYPlane(u2[i],phi2[i]);
+            TrackVector vec1 = new TrackVector();
+            vec1.set(SurfXYPlane.IV,    v[i]);     // v
+            vec1.set(SurfXYPlane.IZ,    z[i]);     // z
+            vec1.set(SurfXYPlane.IDVDU, dvdu[i]);  // dv/du
+            vec1.set(SurfXYPlane.IDZDU, dzdu[i]);  // dz/du
+            vec1.set(SurfXYPlane.IQP,   qp[i]);    //  q/p
+            
+            TrackError err1 = new TrackError();
+            err1.set(SurfXYPlane.IV,SurfXYPlane.IV,       evv[i]);
+            err1.set(SurfXYPlane.IV,SurfXYPlane.IZ,       evz[i]);
+            err1.set(SurfXYPlane.IZ,SurfXYPlane.IZ,       ezz[i]);
+            err1.set(SurfXYPlane.IV,SurfXYPlane.IDVDU,    evdv[i]);
+            err1.set(SurfXYPlane.IZ,SurfXYPlane.IDVDU,    ezdv[i]);
+            err1.set(SurfXYPlane.IDVDU,SurfXYPlane.IDVDU, edvdv[i]);
+            err1.set(SurfXYPlane.IV,SurfXYPlane.IDZDU,    evdz[i]);
+            err1.set(SurfXYPlane.IZ,SurfXYPlane.IDZDU,    ezdz[i]);
+            err1.set(SurfXYPlane.IDVDU,SurfXYPlane.IDZDU, edvdz[i]);
+            err1.set(SurfXYPlane.IDZDU,SurfXYPlane.IDZDU, edzdz[i]);
+            err1.set(SurfXYPlane.IV,SurfXYPlane.IQP,      evqp[i]);
+            err1.set(SurfXYPlane.IZ,SurfXYPlane.IQP,      ezqp[i]);
+            err1.set(SurfXYPlane.IDVDU,SurfXYPlane.IQP,   edvqp[i]);
+            err1.set(SurfXYPlane.IDZDU,SurfXYPlane.IQP,   edzqp[i]);
+            err1.set(SurfXYPlane.IQP,SurfXYPlane.IQP,     eqpqp[i]);
+            ETrack trv1 = new ETrack(sxyp1.newPureSurface(),vec1,err1);
+            if(sign_du[i]==1) trv1.setForward();
+            else trv1.setBackward();
+            if(debug) System.out.println( " starting: " + trv1 );
+            
+            ETrack trv2f = new ETrack(trv1);
+            pstat = prop.errDirProp(trv2f,sxyp2,PropDir.FORWARD);
+            Assert.assertTrue( pstat.forward() );
+            if(debug) System.out.println( "  forward: " + trv2f );
+            ETrack trv2b = new ETrack(trv1);
+            pstat = prop.errDirProp(trv2b,sxyp2,PropDir.BACKWARD);
+            Assert.assertTrue( pstat.backward() );
+            if(debug) System.out.println( " backward: " + trv2b );
+            ETrack trv2fb = new ETrack(trv2f);
+            pstat = prop.errDirProp(trv2fb,sxyp1,PropDir.BACKWARD);
+            Assert.assertTrue( pstat.backward() );
+            if(debug) System.out.println( " f return: " + trv2fb );
+            ETrack trv2bf = new ETrack(trv2b);
+            pstat = prop.errDirProp(trv2bf,sxyp1,PropDir.FORWARD);
+            Assert.assertTrue( pstat.forward() );
+            if(debug) System.out.println( " b return: " + trv2bf );
+            double difff =
+                    sxyp1.vecDiff(trv2fb.vector(),trv1.vector()).amax();
+            double diffb =
+                    sxyp1.vecDiff(trv2bf.vector(),trv1.vector()).amax();
+            if(debug) System.out.println( "vec diffs: " + difff + ' ' + diffb );
+            Assert.assertTrue( difff < maxdiff );
+            Assert.assertTrue( diffb < maxdiff );
+            TrackError dfb = trv2fb.error().minus(trv1.error());
+            TrackError dbf = trv2bf.error().minus(trv1.error());
+            double edifff = dfb.amax();
+            double ediffb = dbf.amax();
+            if(debug) System.out.println( "err diffs: " + edifff + ' ' + ediffb );
+            Assert.assertTrue( edifff < maxdiff );
+            Assert.assertTrue( ediffb < maxdiff );
+        }
+        
+        //********************************************************************
+        
+        if(debug) System.out.println( ok_prefix + "Test Nearest Propagation" );
+        
+        PropStat pstat = new PropStat();
+        SurfXYPlane sxyp1 = new SurfXYPlane(2.,Math.PI/3.);
+        SurfXYPlane sxyp2 = new SurfXYPlane(3.,Math.PI/3.);
+        
+        TrackVector vec1 = new TrackVector();
+        
+        vec1.set(SurfXYPlane.IV     ,1.);     // v
+        vec1.set(SurfXYPlane.IZ     ,1.);     // z
+        vec1.set(SurfXYPlane.IDVDU  ,1.);     // dv/du
+        vec1.set(SurfXYPlane.IDZDU  ,1.);     // dz/du
+        vec1.set(SurfXYPlane.IQP    ,0.01);   //  q/p
+        
+        VTrack trv1 = new VTrack(sxyp1.newPureSurface(),vec1);
+        trv1.setForward();
+        
+        if(debug) System.out.println( " starting: " + trv1 );
+        VTrack trv2n = new VTrack(trv1);
+        pstat = prop.vecDirProp(trv2n,sxyp2,PropDir.NEAREST);
+        Assert.assertTrue( pstat.forward() );
+        if(debug) System.out.println( " nearest: " + trv2n );
+        
+        trv1.setBackward();
+        
+        if(debug) System.out.println( " starting: " + trv1 );
+        trv2n = new VTrack(trv1);
+        pstat = prop.vecDirProp(trv2n,sxyp2,PropDir.NEAREST);
+        Assert.assertTrue( pstat.backward() );
+        if(debug) System.out.println( " nearest: " + trv2n );
+        
+        //********************************************************************
+        
+        if(debug) System.out.println( ok_prefix + "Test XXX_MOVE and Same Surface Propagation." );
+        
+        VTrack trvt0 = new VTrack(sxyp1.newPureSurface(),vec1);
+        trvt0.setForward();
+        VTrack trvt1 = new VTrack(trvt0);
+        PropStat tst = prop.vecDirProp(trvt1,sxyp1,PropDir.NEAREST);
+        Assert.assertTrue( tst.success() && trvt1.equals(trvt0) );
+        tst = prop.vecDirProp(trvt1,sxyp1,PropDir.FORWARD);
+        Assert.assertTrue( tst.success() && trvt1.equals(trvt0) );
+        tst = prop.vecDirProp(trvt1,sxyp1,PropDir.BACKWARD);
+        Assert.assertTrue( tst.success() && trvt1.equals(trvt0) );
+        
+        trvt1 =  new VTrack(trvt0);
+        tst = prop.vecDirProp(trvt1,sxyp1,PropDir.NEAREST_MOVE);
+        Assert.assertTrue( tst.success() && !trvt1.equals(trvt0) );
+        trvt1 = new VTrack(trvt0);
+        tst = prop.vecDirProp(trvt1,sxyp1,PropDir.FORWARD_MOVE);
+        Assert.assertTrue( tst.success() && !trvt1.equals(trvt0) );
+        trvt1 = new VTrack(trvt0);
+        tst = prop.vecDirProp(trvt1,sxyp1,PropDir.BACKWARD_MOVE);
+        Assert.assertTrue( tst.success() && !trvt1.equals(trvt0) );
+        
+        //********************************************************************
+        
+        if(debug) System.out.println( ok_prefix + "Test Zero B field propagation" );
+        {
+            
+            PropXYXY prop0 = new PropXYXY(0.);
+            if(debug) System.out.println( prop0 );
+            Assert.assertTrue( prop0.bField() == 0. );
+            
+            double u=10.,phi=0.;
+            Surface srf = new SurfXYPlane(u,phi);
+            VTrack trv0 = new VTrack(srf);
+            TrackVector vec = new TrackVector();
+            vec.set(SurfXYPlane.IV, 2.);
+            vec.set(SurfXYPlane.IZ, 10.);
+            vec.set(SurfXYPlane.IDVDU, 4.);
+            vec.set(SurfXYPlane.IDZDU, 2.);
+            trv0.setVector(vec);
+            trv0.setForward();
+            u=4.;
+            
+            Surface srf_to = new SurfXYPlane(u,phi);
+            
+            VTrack trv = new VTrack(trv0);
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.FORWARD);
+            Assert.assertTrue( !pstat.success() );
+            
+            trv = new VTrack(trv0);
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.BACKWARD);
+            Assert.assertTrue( pstat.success() );
+            
+            trv = new VTrack(trv0);
+            trv.setBackward();
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.BACKWARD);
+            Assert.assertTrue( !pstat.success() );
+            
+            trv = new VTrack(trv0);
+            trv.setBackward();
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.FORWARD);
+            Assert.assertTrue( pstat.success() );
+            
+            trv = new VTrack(trv0);
+            trv.setForward();
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.NEAREST);
+            Assert.assertTrue( pstat.success() );
+            
+            Assert.assertTrue( pstat.backward() );
+            Assert.assertTrue( trv.vector(SurfXYPlane.IDVDU) == trv0.vector(SurfXYPlane.IDVDU) );
+            Assert.assertTrue( trv.vector(SurfXYPlane.IDZDU) == trv0.vector(SurfXYPlane.IDZDU) );
+            Assert.assertTrue(trv.surface().pureEqual(srf_to));
+            
+            check_zero_propagation(trv0,trv,pstat);
+            
+            srf_to = new SurfXYPlane(4.,Math.PI/16.);
+            trv = new VTrack(trv0);
+            trv.setForward();
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.NEAREST);
+            Assert.assertTrue( pstat.success() );
+            check_zero_propagation(trv0,trv,pstat);
+            
+            srf_to = new SurfXYPlane(14.,Math.PI/4.);
+            trv = new VTrack(trv0);
+            trv.setForward();
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.NEAREST);
+            Assert.assertTrue( pstat.success() );
+            check_zero_propagation(trv0,trv,pstat);
+            
+            srf_to = new SurfXYPlane(14.,Math.PI/2.);
+            trv = new VTrack(trv0);
+            trv.setForward();
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.NEAREST);
+            Assert.assertTrue( pstat.success() );
+            check_zero_propagation(trv0,trv,pstat);
+            
+            srf_to = new SurfXYPlane(14.,Math.PI);
+            trv = new VTrack(trv0);
+            trv.setForward();
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.NEAREST);
+            Assert.assertTrue( pstat.success() );
+            check_zero_propagation(trv0,trv,pstat);
+            
+            srf_to = new SurfXYPlane(14.,Math.PI*5./4.);
+            trv = new VTrack(trv0);
+            trv.setSurface(new SurfXYPlane(14.,Math.PI*7./4.));
+            trv.setForward();
+            VTrack tmp = new VTrack(trv);
+            VTrack der = new VTrack(trv);
+            pstat = prop0.vecDirProp(trv,srf_to,PropDir.NEAREST);
+            Assert.assertTrue( pstat.success() );
+            check_zero_propagation(tmp,trv,pstat);
+            check_derivatives(prop0,der,srf_to);
+            
+        }
+        
+        
+        //********************************************************************
+        
+        if(debug) System.out.println( ok_prefix + "Test cloning." );
+        Assert.assertTrue( prop.newPropagator() != null);
+        
+        //********************************************************************
+        
+        if(debug) System.out.println( ok_prefix + "Test the field." );
+        Assert.assertTrue( prop.bField() == 2.0 );
+        
+        //********************************************************************
+        
+        {
+            if(debug) System.out.println("===========================================\n");
+            PropXYXY p1 = new PropXYXY(2.);
+            PropXYXY p2 = new PropXYXY(-2.);
+            SurfXYPlane xy1 = new SurfXYPlane(5.,0.);
+            SurfXYPlane xy2 = new SurfXYPlane(3.,0.);
+            ETrack tre0 = new ETrack( xy2.newSurface() );
+            TrackVector vec = new TrackVector();
+            TrackError err = new TrackError();
+            
+            vec.set(0, 0.);
+            vec.set(1, 0.);
+            vec.set(2, 0.0);
+            vec.set(3, 0.1);
+            vec.set(4, -0.1);
+            err.set(0,0, 0.1);
+            err.set(1,1, 0.1);
+            err.set(2,2, 0.1);
+            err.set(3,3, 0.1);
+            err.set(4,4, 0.1);
+            tre0.setVector(vec);
+            tre0.setError(err);
+            tre0.setBackward();
+            
+            ETrack tre1 = new ETrack(tre0);
+            ETrack tre2 = new ETrack(tre0);
+            PropStat pstat2=p1.errDirProp(tre1,xy1,PropDir.BACKWARD);
+            Assert.assertTrue(pstat2.success());
+            pstat2=p2.errDirProp(tre2,xy1,PropDir.BACKWARD);
+            Assert.assertTrue(pstat2.success());
+            
+            if(debug) System.out.println("tre1= \n"+tre1+'\n'+"tre2= \n"+tre2+'\n');
+            if(debug) System.out.println("===========================================\n");
+            
+            
+            
+            
+            
+            
+            //********************************************************************
+            
+            if(debug) System.out.println( ok_prefix
+                    + "------------- All tests passed. -------------" );
+        }
+    }
+    
+    static void  check_zero_propagation(  VTrack trv0,  VTrack trv,  PropStat  pstat)
+    {
+        
+        SpacePoint sp = trv.spacePoint();
+        SpacePoint sp0 = trv0.spacePoint();
+        
+        SpacePath sv = trv.spacePath();
+        SpacePath sv0 = trv0.spacePath();
+        
+        Assert.assertTrue( Math.abs(sv0.dx() - sv.dx())<1e-7 );
+        Assert.assertTrue( Math.abs(sv0.dy() - sv.dy())<1e-7 );
+        Assert.assertTrue( Math.abs(sv0.dz() - sv.dz())<1e-7 );
+        
+        double x0 = sp0.x();
+        double y0 = sp0.y();
+        double z0 = sp0.z();
+        double x1 = sp.x();
+        double y1 = sp.y();
+        double z1 = sp.z();
+        
+        double dx = sv.dx();
+        double dy = sv.dy();
+        double dz = sv.dz();
+        
+        double prod = dx*(x1-x0)+dy*(y1-y0)+dz*(z1-z0);
+        double moda = Math.sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0) + (z1-z0)*(z1-z0));
+        double modb = Math.sqrt(dx*dx+dy*dy+dz*dz);
+        double st = pstat.pathDistance();
+        Assert.assertTrue( Math.abs(prod-st) < 1.e-7 );
+        Assert.assertTrue( Math.abs(Math.abs(prod) - moda*modb) < 1.e-7 );
+    }
+    
+    static void check_derivatives(  Propagator prop,  VTrack trv0,  Surface srf)
+    {
+        for(int i=0;i<4;++i)
+            for(int j=0;j<4;++j)
+                check_derivative(prop,trv0,srf,i,j);
+    }
+    
+    static void check_derivative(  Propagator  prop,  VTrack  trv0,  Surface  srf,int i,int j)
+    {
+        
+        double dx = 1.e-3;
+        VTrack trv = new VTrack(trv0);
+        TrackVector vec = trv.vector();
+        boolean forward = trv0.isForward();
+        
+        VTrack trv_0 = new VTrack(trv0);
+        TrackDerivative der = new TrackDerivative();
+        PropStat pstat = prop.vecProp(trv_0,srf,der);
+        Assert.assertTrue(pstat.success());
+        
+        TrackVector tmp= new TrackVector(vec);
+        tmp.set(j, tmp.get(j)+dx);
+        trv.setVector(tmp);
+        if(forward) trv.setForward();
+        else trv.setBackward();
+        
+        VTrack trv_pl = new VTrack(trv);
+        pstat = prop.vecProp(trv_pl,srf);
+        Assert.assertTrue(pstat.success());
+        
+        TrackVector vecpl = trv_pl.vector();
+        
+        tmp= new TrackVector(vec);
+        tmp.set(j,tmp.get(j)-dx);
+        trv.setVector(tmp);
+        if(forward) trv.setForward();
+        else trv.setBackward();
+        
+        VTrack trv_mn = new VTrack(trv);
+        pstat = prop.vecProp(trv_mn,srf);
+        Assert.assertTrue(pstat.success());
+        
+        TrackVector vecmn = trv_mn.vector();
+        
+        double dy = (vecpl.get(i)-vecmn.get(i))/2.;
+        
+        double dydx = dy/dx;
+        
+        double didj = der.get(i,j);
+        
+        if( Math.abs(didj) > 1e-10 )
+            Assert.assertTrue( Math.abs((dydx - didj)/didj) < 1e-4 );
+        else
+            Assert.assertTrue( Math.abs(dydx) < 1e-4 );
+    }
+    //**********************************************************************
+    //Checker of correct z propagation
+    
+    static double check_dz(VTrack trv1, VTrack trv2)
+    {
+        double z1    = trv1.vector().get(SurfXYPlane.IZ);
+        double z2    = trv2.vector().get(SurfXYPlane.IZ);
+        double dzdu  = trv1.vector().get(SurfXYPlane.IDZDU);
+        int sign_du = (trv1.isForward())?1:-1;
+        return (z2-z1)*dzdu*sign_du;
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
SingleSensorHelicalTrackHitDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/SingleSensorHelicalTrackHitDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/SingleSensorHelicalTrackHitDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,383 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.mgraham;
+
+import org.lcsim.hps.recon.tracking.*;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
+import org.lcsim.event.base.MyLCRelation;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCRelation;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
+import org.lcsim.hps.event.HPSTransformations;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHit;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.digitization.sisim.TrackerHitType;
+
+/**
+ *
+ * @author phansson, mgraham
+ */
+public class SingleSensorHelicalTrackHitDriver extends org.lcsim.fit.helicaltrack.HelicalTrackHitDriver {
+    private boolean _debug = false;
+    private String subdetectorName = "Tracker";
+    private Map<String,String> _stereomap = new HashMap<String,String>();
+    private List<String> _colnames = new ArrayList<String>();
+    private boolean _doTransformToTracking = true;
+    public enum LayerGeometryType { 
+        /*
+         * Each Layer in the geometry is a separate sensor
+         */
+        Split, 
+        /*
+         * Each layer in the geometry comprises top and bottom sensor
+         */
+        Common
+    }
+    private LayerGeometryType _layerGeometryType;
+
+    public SingleSensorHelicalTrackHitDriver() {
+        this.setLayerGeometryType("Common");
+        this.addCollection("StripClusterer_SiTrackerHitStrip1D");
+    }
+    public void setLayerGeometryType(String geomType) {
+        this._layerGeometryType = LayerGeometryType.valueOf(geomType);
+    }
+    
+    public void setSubdetectorName(String subdetectorName) {
+        this.subdetectorName = subdetectorName;
+    }
+    
+    public void setDebug(boolean debug) {
+        this._debug = debug;
+    }
+    
+    public void setTransformToTracking(boolean trans) {
+        this._doTransformToTracking = trans;
+    }
+    
+    public void setStripHitsCollectionName(String stripHitsCollectionName) {
+        HitRelationName(stripHitsCollectionName);
+    }
+
+    public void setHelicalTrackHitRelationsCollectionName(String helicalTrackHitRelationsCollectionName) {
+        HitRelationName(helicalTrackHitRelationsCollectionName);
+    }
+
+    public void setHelicalTrackMCRelationsCollectionName(String helicalTrackMCRelationsCollectionName) {
+        MCRelationName(helicalTrackMCRelationsCollectionName);
+    }
+
+    public void setOutputHitCollectionName(String outputHitCollectionName) {
+        OutputCollection(outputHitCollectionName);
+    }
+   
+    
+    @Override
+    public void process(EventHeader event) {
+        //super.process(event);
+
+        //  Initialize the list of HelicalTrackHits
+        List<HelicalTrackCross> stereoCrosses = new ArrayList<HelicalTrackCross>();
+        List<HelicalTrackHit> helhits = new ArrayList<HelicalTrackHit>();
+        
+        //  Create a List of LCRelations to relate HelicalTrackHits to the original hits
+        List<LCRelation> hitrelations = new ArrayList<LCRelation>();
+        //  Create a List of LCRelations to relate HelicalTrackHits to the MC particle
+        List<LCRelation> mcrelations = new ArrayList<LCRelation>();
+
+        
+        
+        for(String _colname : this._colnames) {
+            
+            if (!event.hasCollection(SiTrackerHit.class, _colname)) {
+                continue;
+            }
+
+            //  Get the list of SiTrackerHits for this collection
+            List<SiTrackerHit> hitlist = (List<SiTrackerHit>) event.get(_colname);
+            if (_debug) System.out.printf("%s: found %d SiTrackerHits = ",this.getClass().getSimpleName(),hitlist.size());
+            
+            //  Create collections for strip hits by layer and hit cross references
+            Map<String, List<HelicalTrackStrip>> striplistmap = new HashMap<String, List<HelicalTrackStrip>>();
+            Map<HelicalTrackStrip, SiTrackerHitStrip1D> stripmap = new HashMap<HelicalTrackStrip, SiTrackerHitStrip1D>();
+            
+            for(SiTrackerHit hit : hitlist) {
+                
+                if( hit instanceof SiTrackerHitStrip1D) {
+                    
+                    //  Cast the hit as a 1D strip hit and find the identifier for the detector/layer combo
+                    SiTrackerHitStrip1D h = (SiTrackerHitStrip1D) hit;
+                    IDetectorElement de = h.getSensor();
+                    String id = this.makeID(_ID.getName(de), _ID.getLayer(de));
+
+                    //  This hit should be a on a stereo pair!
+                    if (!_stereomap.containsKey(id) &&! _stereomap.containsValue(id)) {
+                        throw new RuntimeException(this.getClass().getSimpleName() + ": this " + id + " was not among the stereo modules!");
+                    }
+                    
+                    //  Create a HelicalTrackStrip for this hit
+                    HelicalTrackStrip strip = makeDigiStrip(h);
+
+                    //  Get the list of strips for this layer - create a new list if one doesn't already exist
+                    List<HelicalTrackStrip> lyrhits = striplistmap.get(id);
+                    if (lyrhits == null) {
+                        lyrhits = new ArrayList<HelicalTrackStrip>();
+                        striplistmap.put(id, lyrhits);
+                    }
+
+                    //  Add the strip to the list of strips on this sensor
+                    lyrhits.add(strip);
+
+                    //  Map a reference back to the hit needed to create the stereo hit LC relations
+                    stripmap.put(strip, h);
+
+                    if(_debug) System.out.printf("%s: added strip (org=%s,umeas=%.3f) at layer %d ",this.getClass().getSimpleName(),strip.origin().toString(),strip.umeas(),strip.layer());
+                    
+                } else {
+
+                    //  If not a 1D strip hit, make a pixel hit
+                    HelicalTrackHit hit3d = this.makeDigi3DHit(hit);
+                    helhits.add(hit3d);
+                    hitrelations.add(new MyLCRelation(hit3d, hit));
+                }
+                
+            } // Loop over SiTrackerHits
+            
+            
+            //  Create a list of stereo hits
+            //List<HelicalTrackCross> stereohits = new ArrayList<HelicalTrackCross>();
+            
+            if (_debug) System.out.println(this.getClass().getSimpleName() + ": Create stereo hits from " + striplistmap.size() + " strips (map size)");
+                        
+            //  Loop over the stereo layer pairs
+            for (String id1 : _stereomap.keySet()) {
+
+                //  Get the second layer
+                String id2 = _stereomap.get(id1);
+
+                if (_debug) {
+                    if (striplistmap.get(id1) != null && striplistmap.get(id2) != null) {
+                        System.out.println(this.getClass().getSimpleName() + ": Form stereo hits from " + id1 + " and " + id2);
+                        //for(HelicalTrackStrip strip: striplistmap.get(id1)) System.out.printf("%s: stripid1 at origin %s\n",this.getClass().getSimpleName(),strip.origin().toString());
+                        //for(HelicalTrackStrip strip: striplistmap.get(id2)) System.out.printf("%s: stripid2 at origin %s\n",this.getClass().getSimpleName(),strip.origin().toString());
+                    }
+                }
+                
+                /*
+                 * Form the stereo hits and add them to our hit list
+                 * Add LC relations for stereo hit to SiTrackHitStrip1D object 
+                 * Add LC relation between MC particle and stereo hit
+                 */
+                
+                List<HelicalTrackCross> cross_list =  _crosser.MakeHits(striplistmap.get(id1), striplistmap.get(id2));
+                
+                for(HelicalTrackCross cross : cross_list) {
+                    stereoCrosses.add(cross);
+                    if(cross.getMCParticles()!=null) {
+                        for(MCParticle mcp : cross.getMCParticles()) {
+                            mcrelations.add(new MyLCRelation((HelicalTrackHit)cross,mcp));
+                        }
+                    }
+                    for(HelicalTrackStrip strip : cross.getStrips()) {
+                        hitrelations.add(new MyLCRelation(cross,stripmap.get(strip)));
+                    }
+                    
+                }
+                
+            } // Loop over stereo pairs
+
+            if (_debug) {
+                System.out.printf("%s: added %d stereo hits from %s collection ",this.getClass().getSimpleName(),stereoCrosses.size(),_colname);
+            }
+            
+            
+        } // Loop over collection names
+        
+        
+        
+        // Add things to the event
+        // Cast crosses to HTH
+        helhits.addAll(stereoCrosses);
+        event.put(_outname, helhits, HelicalTrackHit.class, 0);
+        event.put(_hitrelname,hitrelations,LCRelation.class,0);
+        event.put(_mcrelname,mcrelations,LCRelation.class,0);       
+        if(_doTransformToTracking) addRotatedHitsToEvent(event, stereoCrosses);
+        
+        
+        
+    } //Process()
+    
+
+    public void addCollection(String colname) {
+        _colnames.add(colname);
+    }
+    public void setCollection(String colname) {
+        _colnames.clear();
+        this.addCollection(colname);
+    }
+    private String makeID(String detname, int lyr) {
+        return detname + lyr;
+    }
+    
+    public void setStereoPair(String detname, int lyr1, int lyr2) {
+        this._stereomap.put(this.makeID(detname, lyr1), this.makeID(detname, lyr2));
+    }
+    
+    @Override
+    protected void detectorChanged(Detector detector) {
+        /*
+         * Setup default pairing
+         */
+        if (_debug) System.out.printf("%s: Setup stereo hit pair modules ",this.getClass().getSimpleName());
+        
+        List<SiTrackerModule> modules = detector.getSubdetector(this.subdetectorName).getDetectorElement().findDescendants(SiTrackerModule.class);
+        if (modules.isEmpty()) {
+            throw new RuntimeException(this.getClass().getName() + ": No SiTrackerModules found in detector.");
+        }
+        int nLayersTotal = detector.getSubdetector(subdetectorName).getLayering().getLayers().getNumberOfLayers();
+        if (_debug) System.out.printf("%s: %d layers ",this.getClass().getSimpleName(),nLayersTotal);
+        if (nLayersTotal % 2 != 0) {
+            throw new RuntimeException(this.getClass().getName() + ": Don't know how to do stereo pairing for odd number of modules.");
+        }
+        if(this._layerGeometryType==LayerGeometryType.Split) {
+            int nLayers = nLayersTotal/2;
+            for(int i=1;i<=nLayers;++i) {
+                int ly1 = i;
+                int ly2 = i+10;
+                if (_debug) System.out.printf("%s: adding stereo pair from layer %d and %d ",this.getClass().getSimpleName(),ly1,ly2);
+                this.setStereoPair(subdetectorName, ly1, ly2);
+            }            
+        } else if(this._layerGeometryType==LayerGeometryType.Common) {
+            List<int[]> pairs = new ArrayList<int[]>();
+            for (int i = 1; i <= (nLayersTotal) - 1; i += 2) {
+                int[] pair = {i, i + 1};
+                if (_debug)
+                    System.out.println("Adding stereo pair: " + pair[0] + ", " + pair[1]);
+                pairs.add(pair);
+            }
+            for (int[] pair : pairs) {
+                if (_debug) System.out.printf("%s: adding stereo pair from layer %d and %d ",this.getClass().getSimpleName(),pair[0],pair[1]);
+                setStereoPair(subdetectorName, pair[0], pair[1]);
+            }
+        } else {
+            throw new RuntimeException(this.getClass().getSimpleName() + ": this layer geometry is not implemented!");
+        }
+
+        if (_debug) System.out.printf("%s: %d stereo modules added",this.getClass().getSimpleName(),this._stereomap.size());
+        
+    }
+    
+     private HelicalTrackStrip makeDigiStrip(SiTrackerHitStrip1D h) {
+        
+        if(_debug) System.out.println(this.getClass().getSimpleName() + ": makeDigiStrip--");
+        
+        SiTrackerHitStrip1D local = h.getTransformedHit(TrackerHitType.CoordinateSystem.SENSOR);
+        SiTrackerHitStrip1D global = h.getTransformedHit(TrackerHitType.CoordinateSystem.GLOBAL);
+    
+        ITransform3D trans = local.getLocalToGlobal();
+        Hep3Vector org = trans.transformed(_orgloc);
+        Hep3Vector u = global.getMeasuredCoordinate();
+        Hep3Vector v = global.getUnmeasuredCoordinate();
+         
+       
+        
+        double umeas = local.getPosition()[0];
+        double vmin = VecOp.dot(local.getUnmeasuredCoordinate(), local.getHitSegment().getStartPoint());
+        double vmax = VecOp.dot(local.getUnmeasuredCoordinate(), local.getHitSegment().getEndPoint());
+        double du = Math.sqrt(local.getCovarianceAsMatrix().diagonal(0));
+
+       
+        
+        IDetectorElement de = h.getSensor();
+        String det = _ID.getName(de);
+        int lyr = _ID.getLayer(de);
+        BarrelEndcapFlag be = _ID.getBarrelEndcapFlag(de);
+
+        double dEdx = h.getdEdx();
+        double time = h.getTime();
+        List<RawTrackerHit> rawhits = h.getRawHits();
+        HelicalTrackStrip strip = new HelicalTrackStrip(org, u, v, umeas, du,
+                vmin, vmax, dEdx, time, rawhits, det, lyr, be);
+
+        try {
+            if (h.getMCParticles() != null) {
+                for (MCParticle p : h.getMCParticles()) {
+                    strip.addMCParticle(p);
+                }
+            }
+        } catch (RuntimeException e) {
+            // Okay when MC info not present.
+        }
+       
+        if(_debug) {
+            System.out.println(this.getClass().getSimpleName() + ": produced HelicalTrackStrip with origin " + strip.origin().toString());
+        }
+
+        return strip;
+    }
+
+     private void addRotatedHitsToEvent(EventHeader event, List<HelicalTrackCross> stereohits) {
+
+        List<HelicalTrackHit> rotatedhits = new ArrayList<HelicalTrackHit>();
+        List<LCRelation> hthrelations = new ArrayList<LCRelation>();
+        List<LCRelation> mcrelations = new ArrayList<LCRelation>();
+        for (HelicalTrackCross cross : stereohits) {
+            List<HelicalTrackStrip> rotatedstriphits = new ArrayList<HelicalTrackStrip>();
+            for (HelicalTrackStrip strip : cross.getStrips()) {
+
+                Hep3Vector origin = strip.origin();
+                Hep3Vector u = strip.u();
+                Hep3Vector v = strip.v();
+                double umeas = strip.umeas();
+                double du = strip.du();
+                double vmin = strip.vmin();
+                double vmax = strip.vmax();
+                double dedx = strip.dEdx();
+                double time = strip.time();
+                List<RawTrackerHit> rthList = strip.rawhits();
+                String detname = strip.detector();
+                int layer = strip.layer();
+                BarrelEndcapFlag bec = strip.BarrelEndcapFlag();
+                Hep3Vector neworigin = HPSTransformations.transformVectorToTracking(origin);
+                Hep3Vector newu = HPSTransformations.transformVectorToTracking(u);
+                Hep3Vector newv = HPSTransformations.transformVectorToTracking(v);
+                HelicalTrackStrip newstrip = new HelicalTrackStrip(neworigin, newu, newv, umeas, du, vmin, vmax, dedx, time, rthList, detname, layer, bec);
+                for (MCParticle p : strip.MCParticles()) {
+                    newstrip.addMCParticle(p);
+                }
+                rotatedstriphits.add(newstrip);
+            }
+            HelicalTrackCross newhit = new HelicalTrackCross(rotatedstriphits.get(0), rotatedstriphits.get(1));
+            rotatedhits.add(newhit);
+            hthrelations.add(new MyLCRelation(cross, newhit));
+            for (MCParticle mcp : newhit.getMCParticles()) {
+                mcrelations.add(new MyLCRelation(newhit, mcp));
+            }
+        }
+        
+        event.put("Rotated"+_outname, rotatedhits, HelicalTrackHit.class, 0);
+        event.put("Rotated"+_hitrelname, hthrelations, LCRelation.class, 0);
+        event.put("Rotated"+_mcrelname, mcrelations, LCRelation.class, 0);
+        
+        
+        //  Create the LCRelations between HelicalTrackHits and MC particles
+
+    }
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
SingleSensorTrackerReconDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/SingleSensorTrackerReconDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/SingleSensorTrackerReconDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,173 @@
+package org.lcsim.hps.users.mgraham;
+
+import org.lcsim.hps.recon.tracking.*;
+import hep.physics.vec.BasicHep3Vector;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.event.HPSTransformations;
+import org.lcsim.recon.tracking.digitization.sisim.config.ReadoutCleanupDriver;
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+import org.lcsim.recon.tracking.seedtracker.StrategyXMLUtils;
+import org.lcsim.recon.tracking.seedtracker.diagnostic.SeedTrackerDiagnostics;
+import org.lcsim.util.Driver;
+
+/**
+ * This class runs the Track Reconstruction for the HPS Test Proposal detector.
+ * The tracker digitization must be run in front of it. It is intended to work
+ * with the {@link TrackerDigiDriver} digitization Driver.
+ *
+ * @author jeremym
+ * @version $Id: TrackerReconDriver.java,v 1.18 2012/05/03 20:50:29 mgraham Exp
+ * $
+ */
+public final class SingleSensorTrackerReconDriver extends Driver {
+
+    // Debug flag.
+    private boolean debug = false;
+    // Tracks found across all events.
+    int ntracks = 0;
+    // Number of events processed.
+    int nevents = 0;
+    // Cache detector object.
+    Detector detector = null;
+    // Default B-field value.
+    private double bfield = 0.5;
+    // TrackerHit readout name for readout cleanup.
+    private String trackerReadoutName = "TrackerHits";
+    // Tracking strategies resource path.
+    private String strategyResource = "HPS-Test-4pt1.xml";
+    // Output track collection.
+    private String trackCollectionName = "MatchedTracks";
+    // HelicalTrackHit input collection.
+    private String stInputCollectionName = "RotatedHelicalTrackHits";
+    // Include MS (done by removing XPlanes from the material manager results)
+    private boolean includeMS = true;
+    
+    public SingleSensorTrackerReconDriver() {
+    }
+
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    /**
+     * Set the tracking strategy resource.
+     *
+     * @param strategyResource The absolute path to the strategy resource in the
+     * hps-java jar.
+     */
+    public void setStrategyResource(String strategyResource) {
+        this.strategyResource = strategyResource;
+    }
+
+    public void setInputHitCollectionName(String inputHitCollectionName) {
+        this.stInputCollectionName = inputHitCollectionName;
+    }
+
+    public void setTrackCollectionName(String trackCollectionName) {
+        this.trackCollectionName = trackCollectionName;
+    }
+
+    public void setIncludeMS(boolean incMS) {
+        this.includeMS = incMS;
+    }
+   
+    /**
+     * This is used to setup the Drivers after XML config.
+     */
+    @Override
+    public void detectorChanged(Detector detector) {
+        // Cache Detector object.
+        this.detector = detector;
+
+        // Get B-field Y with no sign. Seed Tracker doesn't like signed B-field components.
+        // FIXME Is this always right?
+        this.bfield = Math.abs((detector.getFieldMap().getField(new BasicHep3Vector(0, 0, 0)).y()));
+        if (debug) {
+            System.out.printf("%s: Set B-field to %.3f",this.getClass().getSimpleName(),this.bfield);
+        }
+
+        initialize();
+
+        super.detectorChanged(detector);
+    }
+
+    /**
+     * Setup all the child Drivers necessary for track reconstruction.
+     */
+    private void initialize() {
+
+        //
+        // 1) Driver to run Seed Tracker.
+        //
+
+        if (!strategyResource.startsWith("/")) {
+            strategyResource = "/org/lcsim/hps/recon/tracking/strategies/" + strategyResource;
+        }
+        List<SeedStrategy> sFinallist = StrategyXMLUtils.getStrategyListFromInputStream(this.getClass().getResourceAsStream(strategyResource));
+        SeedTracker stFinal = new SeedTracker(sFinallist,this.includeMS);
+        stFinal.setMaterialManagerTransform(HPSTransformations.getTransform());
+        stFinal.setInputCollectionName(stInputCollectionName);
+        stFinal.setTrkCollectionName(trackCollectionName);
+        stFinal.setBField(bfield);
+        stFinal.setDiagnostics(new SeedTrackerDiagnostics());
+//        stFinal.setSectorParams(false); //this doesn't actually seem to do anything
+        stFinal.setSectorParams(1, 10000);
+        add(stFinal);
+
+        //
+        // 2) Cleanup the readouts for next event.
+        //
+        add(new ReadoutCleanupDriver(Arrays.asList(this.trackerReadoutName)));
+    }
+
+    /**
+     * This method is used to run the reconstruction and print debug
+     * information.
+     */
+    @Override
+    public void process(EventHeader event) {
+        // This call runs the track reconstruction using the sub-Drivers.
+        super.process(event);
+
+        // Debug printouts.
+        if (debug) {
+            if(event.hasCollection(HelicalTrackHit.class,stInputCollectionName)) {
+                System.out.println(this.getClass().getSimpleName() + ": The HelicalTrackHit collection " + stInputCollectionName + " has " + event.get(HelicalTrackHit.class, stInputCollectionName).size() + " hits.");
+            } else {
+                System.out.println(this.getClass().getSimpleName() + ": No HelicalTrackHit collection for this event");
+            }
+            // Check for Tracks.
+            List<Track> tracks = event.get(Track.class, trackCollectionName);
+            System.out.println(this.getClass().getSimpleName() + ": The Track collection " + trackCollectionName + " has " + tracks.size() + " tracks.");
+
+            // Print out track info.
+            for (Track track : tracks) {
+                System.out.println(this.getClass().getSimpleName() + ": " + track.toString());
+                System.out.println(this.getClass().getSimpleName() + ": number of layers = " + track.getTrackerHits().size());
+                System.out.println(this.getClass().getSimpleName() + ": chi2 = " + track.getChi2());
+            }
+        }
+
+        // Increment number of events.
+        ++nevents;
+
+        // Add to tracks found.
+        ntracks += event.get(Track.class, trackCollectionName).size();
+    }
+
+    @Override
+    public void endOfData() {
+        if (debug) {
+            System.out.println("-------------------------------------------");
+            System.out.println(this.getName() + " found " + ntracks + " tracks in " + nevents + " events which is " + ((double) ntracks / (double) nevents) + " tracks per event.");
+        }
+    }
+}
\ No newline at end of file

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
TestAnalysisDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/TestAnalysisDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/TestAnalysisDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,134 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.mgraham;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IProfile1D;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.event.*;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.hps.recon.tracking.HPSFittedRawTrackerHit;
+import org.lcsim.hps.recon.tracking.TrackAnalysis;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author mgraham
+ */
+public class TestAnalysisDriver extends Driver {
+
+    int nevents = 0;
+    int naccepted = 0;
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    public String outputPlots = "myplots.aida";
+    Map<String, IProfile1D> clsizeMap = new HashMap<String, IProfile1D>();
+    String[] detNames = {"Tracker"};
+    Integer[] nlayers = {10};
+
+    public void process(
+            EventHeader event) {
+        nevents++;
+
+        List<RawTrackerHit> rawHits = event.get(RawTrackerHit.class, "SVTRawTrackerHits");
+        List<HPSFittedRawTrackerHit> fittedrawHits = event.get(HPSFittedRawTrackerHit.class, "SVTFittedRawTrackerHits");
+
+        List<SiTrackerHitStrip1D> stripHits = event.get(SiTrackerHitStrip1D.class, "StripClusterer_SiTrackerHitStrip1D");
+    
+       
+       
+Map<Track, TrackAnalysis> tkanalMap = new HashMap<Track, TrackAnalysis>();
+        RelationalTable nearestHitToTrack = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        Map<Track, Double> l1Isolation = new HashMap<Track, Double>();
+        Map<Track, Double> l1DeltaZ = new HashMap<Track, Double>();
+        
+        String fittedHitsDir = "FittedHits/";
+        for(HPSFittedRawTrackerHit hrth:fittedrawHits){
+            double fittedAmp=hrth.getAmp();
+            double fittedT0=hrth.getT0();
+            String sensorName=hrth.getRawTrackerHit().getDetectorElement().getName();
+            aida.cloud1D(fittedHitsDir + sensorName+" fitted Amplitude").fill(fittedAmp);
+            aida.cloud1D(fittedHitsDir + sensorName+"fitted T0").fill(fittedT0);
+        }
+        
+        
+        /*
+         List<Track> tracklist = event.get(Track.class, "MatchedTracks");
+        List<HelicalTrackHit> hthits = event.get(HelicalTrackHit.class, "HelicalTrackHits");
+        aida.cloud1D("HelicalTrackHits per Event").fill(hthits.size());
+        aida.cloud1D("Matched Tracks per Event").fill(tracklist.size());
+        String trackdir = "TrackInfo/";
+        //  Analyze the tracks in the event
+        for (Track track : tracklist) {
+            //  Calculate the track pT and cos(theta)
+            double d0 = track.getTrackParameter(HelicalTrackFit.dcaIndex);
+            double z0 = track.getTrackParameter(HelicalTrackFit.z0Index);
+            double phi0 = track.getTrackParameter(HelicalTrackFit.phi0Index);
+            double slope = track.getTrackParameter(HelicalTrackFit.slopeIndex);
+            double curve = track.getTrackParameter(HelicalTrackFit.curvatureIndex);
+            double d0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.dcaIndex, HelicalTrackFit.dcaIndex));
+            double z0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.z0Index, HelicalTrackFit.z0Index));
+            double phi0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.phi0Index, HelicalTrackFit.phi0Index));
+            double slopeErr = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.slopeIndex, HelicalTrackFit.slopeIndex));
+            double curveErr = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.curvatureIndex, HelicalTrackFit.curvatureIndex));
+             SeedTrack stEle = (SeedTrack) track;
+            SeedCandidate seedEle = stEle.getSeedCandidate();
+            HelicalTrackFit ht = seedEle.getHelix();
+            
+            double xoca = ht.x0();
+            double yoca = ht.y0();
+            double[] poca = {xoca, yoca, z0};
+            double mom[] = track.getMomentum();
+            double px = mom[0];
+            double py = mom[1];
+            double pz = mom[2];
+            double pperp = Math.sqrt(py * py + pz * pz);
+            double pt = Math.sqrt(px * px + py * py);
+            double p = Math.sqrt(pt * pt + pz * pz);
+            double phi = Math.atan2(py, px);
+            double cth = pz / Math.sqrt(pt * pt + pz * pz);
+            double sth = pt / Math.sqrt(pt * pt + pz * pz);
+            double th = Math.atan2(pt, pz);
+             fillTrackInfo(trackdir, "all tracks", track.getChi2(), p, pperp, px, py, pz, phi, cth, d0, xoca, yoca, z0);
+        }        
+        */
+    }
+  private void fillTrackInfo(String dir, String species, double chi2,  double p, double pperp, double px, double py, double pz, double phi, double cth, double doca, double xoca, double yoca, double zoca) {
+        aida.cloud1D(dir + "total chi^2 for  " + species).fill(chi2);
+
+//                aida.cloud1D(trackdir + "circle chi^2 for  " + species).fill(ht.chisq()[0]);
+//                aida.cloud1D(trackdir + "linear chi^2 for  " + species).fill(ht.chisq()[1]       
+        aida.cloud1D(dir + "p for  " + species).fill(p);
+        aida.cloud1D(dir + "pperp for  " + species).fill(pperp);
+        aida.cloud1D(dir + "px for  " + species).fill(px);
+        aida.cloud1D(dir + "py for  " + species).fill(py);
+        aida.cloud1D(dir + "pz for  " + species).fill(pz);
+        aida.cloud1D(dir + "phi for  " + species).fill(phi);
+        aida.cloud1D(dir + "cos(theta) for  " + species).fill(cth);
+        aida.cloud1D(dir + "DOCA for  " + species).fill(doca);
+        aida.cloud1D(dir + "XOCA for  " + species).fill(xoca);
+        aida.cloud1D(dir + "YOCA for  " + species).fill(yoca);
+        aida.cloud1D(dir + "ZOCA for  " + species).fill(zoca);
+        aida.cloud2D(dir + "doca vs xoca for  " + species).fill(xoca, doca);
+    }
+    public void endOfData() {
+   try {
+            aida.saveAs(outputPlots);
+        } catch (IOException ex) {
+            Logger.getLogger(DetailedAnalysisDriver.class.getName()).log(Level.SEVERE, null, ex);
+        }      
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
TrackExtrapolationAnalysis.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/TrackExtrapolationAnalysis.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/TrackExtrapolationAnalysis.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,476 @@
+package org.lcsim.hps.users.mgraham;
+
+import hep.aida.*;
+import hep.physics.vec.Hep3Vector;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.event.BeamlineConstants;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.hps.recon.tracking.HPSTrack;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.hps.recon.vertexing.HelixConverter;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+
+ @author mgraham
+ */
+public class TrackExtrapolationAnalysis extends Driver {
+
+    private AIDAFrame extrapFrame;
+    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 trackCollectionName = "MatchedTracks";
+    String ecalSubdetectorName = "Ecal";
+    String ecalCollectionName = "EcalClusters";
+    private Detector detector = null;
+    IPlotter extrap0;
+    IPlotter extrap1;
+    IPlotter extrap2;
+    IPlotter extrap3;
+    IPlotter extrap4;
+    IPlotter extrap5;
+    IPlotter extrap6;
+    IPlotter extrap7;
+    IPlotter extrap8;
+    IPlotter extrap9;
+    IPlotter extrap10;
+    IPlotter extrap11;
+    IPlotter extrap12;
+    IPlotter extrap13;
+    IAnalysisFactory fac = aida.analysisFactory();
+
+    protected void detectorChanged(Detector detector) {
+        this.detector = detector;
+        aida.tree().cd("/");
+        extrapFrame = new AIDAFrame();
+        extrapFrame.setTitle("Extrapolation Debugging Plots");
+        makeExtrapolationPlots();
+
+        extrapFrame.pack();
+        extrapFrame.setVisible(true);
+
+    }
+
+    public TrackExtrapolationAnalysis() {
+    }
+
+    public void process(EventHeader event) {
+        aida.tree().cd("/");
+
+
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+        for (Track trk : tracks) {
+            double trackP = trk.getPX();
+            SeedTrack stEle = (SeedTrack) trk;
+            SeedCandidate seedEle = stEle.getSeedCandidate();
+            HelicalTrackFit ht = seedEle.getHelix();
+            HelixConverter converter = new HelixConverter(0);
+            StraightLineTrack slt = converter.Convert(ht);
+
+            Hep3Vector posAtEcal = TrackUtils.getTrackPositionAtEcal(trk);
+            Hep3Vector extendAtConverter = TrackUtils.extrapolateTrack(trk,BeamlineConstants.HARP_POSITION_TESTRUN);
+
+
+            int isTop = -1;
+            if (trk.getTrackerHits().get(0).getPosition()[2] > 0)
+                isTop = 0;//make plot look pretty
+            int charge = trk.getCharge();
+            if (charge > 0)
+                charge = 0;//make plot look pretty
+//            System.out.println("Charge = " + charge + "; isTop = " + isTop);
+
+            HPSTrack hpstrk=null;
+                hpstrk = new HPSTrack(ht);
+//            Hep3Vector posAtConv = hpstrk.getPositionAtZ(zAtConverter, -101, -100, 0.1);
+            Hep3Vector posAtConv = hpstrk.getPositionAtZMap(100,BeamlineConstants.HARP_POSITION_TESTRUN , 5.0)[0];
+            double useThisx=posAtConv.x();
+            double useThisy=posAtConv.y();
+            
+//             double useThisx=extendAtConverter.y();
+//            double useThisy=extendAtConverter.z();
+            
+            aida.histogram1D("New X (mm) @ Converter").fill(useThisx);  //this is in the JLAB frame already
+            aida.histogram1D("New Y (mm) @ Converter").fill(useThisy);
+            if (isTop == 0) {
+                aida.histogram1D("Top X (mm) @ Converter").fill(useThisx);  //this is in the JLAB frame already
+                aida.histogram1D("Top Y (mm) @ Converter").fill(useThisy);
+            } else {
+                aida.histogram1D("Bottom X (mm) @ Converter").fill(useThisx);  //this is in the JLAB frame already
+                aida.histogram1D("Bottom Y (mm) @ Converter").fill(useThisy);
+            }
+            if (charge < 0) {
+                aida.histogram1D("Negative X (mm) @ Converter").fill(useThisx);  //this is in the JLAB frame already
+                aida.histogram1D("Negative Y (mm) @ Converter").fill(useThisy);
+            }
+//            Hep3Vector posAtConvShort = hpstrk.getPositionAtZ(zAtConverter, -0.1, 0, 0.01);
+            Hep3Vector posAtConvShort = hpstrk.getPositionAtZMap(0,BeamlineConstants.HARP_POSITION_TESTRUN, 5.0)[0];
+            aida.histogram2D("Extrapolated X: short vs long fringe").fill(posAtConvShort.x(), posAtConv.x());
+            aida.histogram2D("Extrapolated Y: short vs long fringe").fill(posAtConvShort.y(), posAtConv.y());
+
+            aida.histogram2D("Extrapolated X: HPS vs SLT").fill(posAtConv.x(), slt.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[0]);
+            aida.histogram2D("Extrapolated Y: HPS vs SLT").fill(posAtConv.y(), slt.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[1]);
+
+            aida.histogram2D("Extrapolated X: Extend vs SLT").fill(extendAtConverter.y(), slt.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[0]);
+            aida.histogram2D("Extrapolated Y: Extend vs SLT").fill(extendAtConverter.z(), slt.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[1]);
+
+            List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, ecalCollectionName);
+            HPSEcalCluster clust = findClosestCluster(posAtEcal, clusters);
+
+            if (clust != null) {
+ //               System.out.println("Cluster Position = ("+clust.getPosition()[0]+","+clust.getPosition()[1]+","+clust.getPosition()[2]+")");
+                double minFringe=BeamlineConstants.DIPOLE_EDGE_TESTRUN-10;
+                double maxFringe=BeamlineConstants.DIPOLE_EDGE_TESTRUN+50;
+//                Hep3Vector posAtEcalHPS = hpstrk.getPositionAtZ(zCluster, minFringe,maxFringe, 0.1);
+//                Hep3Vector posAtEcalHPS = hpstrk.getPositionAtZMap(750,zCluster, 5.0);
+                double zCluster=clust.getPosition()[2];
+ //               double zCluster=1450.0;
+                 Hep3Vector posAtEcalHPS = hpstrk.getPositionAtZMap(750,zCluster, 5.0)[0];
+                Hep3Vector posAtEcalExtend= TrackUtils.extrapolateTrack(trk,zCluster);
+                aida.histogram2D("ECal Extrapolation X :  HPS vs Extend").fill( posAtEcalExtend.y(),posAtEcalHPS.x()-posAtEcalExtend.y());
+                aida.histogram2D("ECal Extrapolation Y :  HPS vs Extend").fill( posAtEcalExtend.z(),posAtEcalHPS.y()-posAtEcalExtend.z());
+                double dX = posAtEcalHPS.x() - clust.getPosition()[0];
+                double dY = posAtEcalHPS.y() - clust.getPosition()[1];
+//                double dX = posAtEcalExtend.y() - clust.getPosition()[0];
+//                double dY = posAtEcalExtend.z() - clust.getPosition()[1];
+                
+                
+                aida.histogram2D("ECal Extrapolation HPS vs Cluster X").fill( clust.getPosition()[0],posAtEcalHPS.x() - clust.getPosition()[0]);
+                aida.histogram2D("ECal Extrapolation HPS vs Cluster Y").fill( clust.getPosition()[1],posAtEcalHPS.y() - clust.getPosition()[1]);
+
+                if (isTop == 0) {
+                    if (charge < 0) {
+                        aida.histogram1D("Track - Cluster X:  Top -ive").fill(dX);
+                        aida.histogram1D("Track - Cluster Y:  Top -ive").fill(dY);
+                    } else {
+                        aida.histogram1D("Track - Cluster X:  Top +ive").fill(dX);
+                        aida.histogram1D("Track - Cluster Y:  Top +ive").fill(dY);
+                    }
+                } else {
+                    if (charge < 0) {
+                        aida.histogram1D("Track - Cluster X:  Bottom -ive").fill(dX);
+                        aida.histogram1D("Track - Cluster Y:  Bottom -ive").fill(dY);
+                    } else {
+                        aida.histogram1D("Track - Cluster X:  Bottom +ive").fill(dX);
+                        aida.histogram1D("Track - Cluster Y:  Bottom +ive").fill(dY);
+                    }
+                }
+
+            }
+            double zmin = 0;
+            double zmax = 500.0;
+            int nstep = 100;
+            Map<Integer, Double[]> traj = hpstrk.trackTrajectory(zmin, zmax, nstep);
+            Map<Integer, Double[]> dir = hpstrk.trackDirection(zmin, zmax, nstep);
+            for (int i = 0; i < nstep; i++) {
+                Double[] xyz = traj.get(i);
+                Double[] dxdyz = dir.get(i);
+//                System.out.println("z = " + xyz[2]
+//                        + "  (x,y) = (" + xyz[0] + "," + xyz[1] + ")"
+//                        + "  (dx,dy) = (" + dxdyz[0] + "," + dxdyz[1] + ")");
+                if (i == 0) {
+                    aida.histogram2D("Track @ 0: X vs dX").fill(xyz[0], dxdyz[0]);
+                    aida.histogram2D("Track @ 0: Y vs dY").fill(xyz[1], dxdyz[1]);
+                    if (isTop == 0) {
+                        if (charge < 0) {
+                            aida.histogram2D("X vs dX:  Top -ive").fill(xyz[0], dxdyz[0]);
+                            aida.histogram2D("X vs P:  Top -ive").fill(xyz[0], trackP);
+                            aida.histogram2D("dX vs P:  Top -ive").fill(dxdyz[0], trackP);
+                        } else {
+                            aida.histogram2D("X vs dX:  Top +ive").fill(xyz[0], dxdyz[0]);
+                            aida.histogram2D("X vs P:  Top +ive").fill(xyz[0], trackP);
+                            aida.histogram2D("dX vs P:  Top +ive").fill(dxdyz[0], trackP);
+                        }
+                    } else {
+                        if (charge < 0) {
+                            aida.histogram2D("X vs dX:  Bottom -ive").fill(xyz[0], dxdyz[0]);
+                            aida.histogram2D("X vs P:  Bottom -ive").fill(xyz[0], trackP);
+                            aida.histogram2D("dX vs P:  Bottom -ive").fill(dxdyz[0], trackP);
+                        } else {
+                            aida.histogram2D("X vs dX:  Bottom +ive").fill(xyz[0], dxdyz[0]);
+                            aida.histogram2D("X vs P:  Bottom +ive").fill(xyz[0], trackP);
+                            aida.histogram2D("dX vs P:  Bottom +ive").fill(dxdyz[0], trackP);
+                        }
+                    }
+                }
+                aida.histogram2D("Track Trajectory:  Z vs X").fill(xyz[2], xyz[0]);
+                aida.histogram2D("Track Trajectory:  Z vs Y").fill(xyz[2], xyz[1]);
+                aida.histogram2D("Track Direction:  Z vs dX").fill(dxdyz[2], dxdyz[0]);
+                aida.histogram2D("Track Direction:  Z vs dY").fill(dxdyz[2], dxdyz[1]);
+            }
+
+        }
+
+    }
+
+    private void makeExtrapolationPlots() {
+
+        extrap0 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        extrap0.setTitle("New Track extrapolation");
+        extrapFrame.addPlotter(extrap0);
+        IPlotterStyle style0 = extrap0.style();
+        style0.dataStyle().fillStyle().setColor("yellow");
+        style0.dataStyle().errorBarStyle().setVisible(false);
+        extrap0.createRegions(2, 4);
+        IHistogram1D xAtConverterNew = aida.histogram1D("New X (mm) @ Converter", 50, -20, 80);
+        IHistogram1D yAtConverterNew = aida.histogram1D("New Y (mm) @ Converter", 50, -20, 20);
+        IHistogram1D xAtCollNew = aida.histogram1D("Top X (mm) @ Converter", 50, -20, 80);
+        IHistogram1D yAtCollNew = aida.histogram1D("Top Y (mm) @ Converter", 50, -20, 20);
+        IHistogram1D xAtEcalNew = aida.histogram1D("Bottom X (mm) @ Converter", 50, -20, 80);
+        IHistogram1D yAtEcalNew = aida.histogram1D("Bottom Y (mm) @ Converter", 50, -20, 20);
+        IHistogram1D xAtEcal2New = aida.histogram1D("Negative X (mm) @ Converter", 50, -20, 80);
+        IHistogram1D yAtEcal2New = aida.histogram1D("Negative Y (mm) @ Converter", 50, -20, 20);
+
+        extrap0.region(0).plot(xAtConverterNew);
+        extrap0.region(4).plot(yAtConverterNew);
+        extrap0.region(1).plot(xAtCollNew);
+        extrap0.region(5).plot(yAtCollNew);
+        extrap0.region(2).plot(xAtEcalNew);
+        extrap0.region(6).plot(yAtEcalNew);
+        extrap0.region(3).plot(xAtEcal2New);
+        extrap0.region(7).plot(yAtEcal2New);
+
+        extrap1 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap1.setTitle("HPSTrack Plots");
+        extrapFrame.addPlotter(extrap1);
+        set2DStyle(extrap1.style());
+        extrap1.createRegions(1, 2);
+
+//        IHistogram2D quadrants = aida.histogram2D("Charge vs Slope", 2, -1, 1, 2, -1, 1);
+        IHistogram2D plot11 = aida.histogram2D("Extrapolated X: short vs long fringe", 50, -50, 50, 50, -50, 50);
+        IHistogram2D plot12 = aida.histogram2D("Extrapolated Y: short vs long fringe", 50, -20, 20, 50, -20, 20);
+        extrap1.region(0).plot(plot11);
+        extrap1.region(1).plot(plot12);
+
+
+        extrap2 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap2.setTitle("HPSTrack vs SLT Plots");
+        extrapFrame.addPlotter(extrap2);
+        set2DStyle(extrap2.style());
+        extrap2.createRegions(1, 2);
+
+//        IHistogram2D quadrants = aida.histogram2D("Charge vs Slope", 2, -1, 1, 2, -1, 1);
+        IHistogram2D plot21 = aida.histogram2D("Extrapolated X: HPS vs SLT", 50, -50, 50, 50, -50, 50);
+        IHistogram2D plot22 = aida.histogram2D("Extrapolated Y: HPS vs SLT", 50, -20, 20, 50, -20, 20);
+        extrap2.region(0).plot(plot21);
+        extrap2.region(1).plot(plot22);
+
+
+        extrap3 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap3.setTitle("Extend vs SLT Plots");
+        extrapFrame.addPlotter(extrap3);
+        set2DStyle(extrap3.style());
+        extrap3.createRegions(1, 2);
+
+        IHistogram2D plot31 = aida.histogram2D("Extrapolated X: Extend vs SLT", 50, -50, 50, 50, -50, 50);
+        IHistogram2D plot32 = aida.histogram2D("Extrapolated Y: Extend vs SLT", 50, -20, 20, 50, -20, 20);
+        extrap3.region(0).plot(plot31);
+        extrap3.region(1).plot(plot32);
+
+
+        extrap4 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap4.setTitle("Nominal Track Trajectory");
+        extrapFrame.addPlotter(extrap4);
+        set2DStyle(extrap4.style());
+        extrap4.createRegions(1, 2);
+
+        IHistogram2D plot41 = aida.histogram2D("Track Trajectory:  Z vs X", 100, 0, 500, 100, -100, 100);
+        IHistogram2D plot42 = aida.histogram2D("Track Trajectory:  Z vs Y", 100, 0, 500, 100, -75, 75);
+        extrap4.region(0).plot(plot41);
+        extrap4.region(1).plot(plot42);
+
+        extrap5 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap5.setTitle("Nominal Direction");
+        extrapFrame.addPlotter(extrap5);
+        set2DStyle(extrap5.style());
+        extrap5.createRegions(1, 2);
+
+        IHistogram2D plot51 = aida.histogram2D("Track Direction:  Z vs dX", 100, 0, 500, 100, -0.1, 0.1);
+        IHistogram2D plot52 = aida.histogram2D("Track Direction:  Z vs dY", 100, 0, 500, 100, -0.1, 0.1);
+        extrap5.region(0).plot(plot51);
+        extrap5.region(1).plot(plot52);
+
+
+
+        extrap7 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap7.setTitle("Track @ 0");
+        extrapFrame.addPlotter(extrap7);
+        set2DStyle(extrap7.style());
+
+        extrap7.createRegions(1, 2);
+
+        IHistogram2D plot71 = aida.histogram2D("Track @ 0: X vs dX", 50, -50, 50, 50, -0.04, 0.04);
+        IHistogram2D plot72 = aida.histogram2D("Track @ 0: Y vs dY", 50, -50, 50, 50, -0.04, 0.04);
+        extrap7.region(0).plot(plot71);
+        extrap7.region(1).plot(plot72);
+
+
+        extrap8 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap8.setTitle("Track X vs dX");
+        extrapFrame.addPlotter(extrap8);
+        set2DStyle(extrap8.style());
+
+        extrap8.createRegions(2, 2);
+
+        IHistogram2D plot81 = aida.histogram2D("X vs dX:  Top -ive", 50, -50, 50, 50, -0.04, 0.04);
+        IHistogram2D plot82 = aida.histogram2D("X vs dX:  Bottom -ive", 50, -50, 50, 50, -0.04, 0.04);
+        IHistogram2D plot83 = aida.histogram2D("X vs dX:  Top +ive", 50, -50, 50, 50, -0.04, 0.04);
+        IHistogram2D plot84 = aida.histogram2D("X vs dX:  Bottom +ive", 50, -50, 50, 50, -0.04, 0.04);
+        extrap8.region(0).plot(plot81);
+        extrap8.region(1).plot(plot82);
+        extrap8.region(2).plot(plot83);
+        extrap8.region(3).plot(plot84);
+
+        extrap9 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap9.setTitle("Track X vs P");
+        extrapFrame.addPlotter(extrap9);
+        set2DStyle(extrap9.style());
+
+        extrap9.createRegions(2, 2);
+
+        IHistogram2D plot91 = aida.histogram2D("X vs P:  Top -ive", 50, -50, 50, 50, 0.5, 2.0);
+        IHistogram2D plot92 = aida.histogram2D("X vs P:  Bottom -ive", 50, -50, 50, 50, 0.5, 2.0);
+        IHistogram2D plot93 = aida.histogram2D("X vs P:  Top +ive", 50, -50, 50, 50, 0.5, 2.0);
+        IHistogram2D plot94 = aida.histogram2D("X vs P:  Bottom +ive", 50, -50, 50, 50, 0.5, 2.0);
+        extrap9.region(0).plot(plot91);
+        extrap9.region(1).plot(plot92);
+        extrap9.region(2).plot(plot93);
+        extrap9.region(3).plot(plot94);
+
+        extrap10 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap10.setTitle("Track dX vs P");
+        extrapFrame.addPlotter(extrap10);
+        set2DStyle(extrap10.style());
+
+        extrap10.createRegions(2, 2);
+
+        IHistogram2D plot101 = aida.histogram2D("dX vs P:  Top -ive", 50, -0.04, 0.04, 50, 0.5, 2.0);
+        IHistogram2D plot102 = aida.histogram2D("dX vs P:  Bottom -ive", 50, -0.04, 0.04, 50, 0.5, 2.0);
+        IHistogram2D plot103 = aida.histogram2D("dX vs P:  Top +ive", 50, -0.04, 0.04, 50, 0.5, 2.0);
+        IHistogram2D plot104 = aida.histogram2D("dX vs P:  Bottom +ive", 50, -0.04, 0.04, 50, 0.5, 2.0);
+        extrap10.region(0).plot(plot101);
+        extrap10.region(1).plot(plot102);
+        extrap10.region(2).plot(plot103);
+        extrap10.region(3).plot(plot104);
+
+
+
+        extrap6 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap6.setTitle("@ ECal HPS vs Extend");
+        extrapFrame.addPlotter(extrap6);
+        set2DStyle(extrap6.style());
+
+        extrap6.createRegions(1, 2);
+
+        IHistogram2D plot61 = aida.histogram2D("ECal Extrapolation X :  HPS vs Extend", 50, -350, 350, 50, -50, 50);
+        IHistogram2D plot62 = aida.histogram2D("ECal Extrapolation Y :  HPS vs Extend", 50, -100, 100, 50, -20, 20);
+        extrap6.region(0).plot(plot61);
+        extrap6.region(1).plot(plot62);
+
+        extrap11 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap11.setTitle("@ ECal HPS vs Cluster");
+        extrapFrame.addPlotter(extrap11);
+        set2DStyle(extrap11.style());
+
+        extrap11.createRegions(1, 2);
+
+        IHistogram2D plot111 = aida.histogram2D("ECal Extrapolation HPS vs Cluster X", 50, -350, 350, 50, -50, 50);
+        IHistogram2D plot112 = aida.histogram2D("ECal Extrapolation HPS vs Cluster Y", 50, -100, 100, 50, -20, 20);
+        extrap11.region(0).plot(plot111);
+        extrap11.region(1).plot(plot112);
+
+
+
+        extrap12 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap12.setTitle("Cluster Resid X");
+        extrapFrame.addPlotter(extrap12);
+        set1DStyle(extrap10.style());
+
+        extrap12.createRegions(2, 2);
+
+        IHistogram1D plot121 = aida.histogram1D("Track - Cluster X:  Top -ive", 50, -50, 50);
+        IHistogram1D plot122 = aida.histogram1D("Track - Cluster X:  Bottom -ive", 50, -50, 50);
+        IHistogram1D plot123 = aida.histogram1D("Track - Cluster X:  Top +ive", 50, -50, 50);
+        IHistogram1D plot124 = aida.histogram1D("Track - Cluster X:  Bottom +ive", 50, -50, 50);
+        extrap12.region(0).plot(plot121);
+        extrap12.region(1).plot(plot122);
+        extrap12.region(2).plot(plot123);
+        extrap12.region(3).plot(plot124);
+
+
+        extrap13 = fac.createPlotterFactory().create("Extrapolation Debug Plots");
+        extrap13.setTitle("Cluster Resid Y");
+        extrapFrame.addPlotter(extrap13);
+        set1DStyle(extrap10.style());
+
+        extrap13.createRegions(2, 2);
+
+        IHistogram1D plot131 = aida.histogram1D("Track - Cluster Y:  Top -ive", 50, -20, 20);
+        IHistogram1D plot132 = aida.histogram1D("Track - Cluster Y:  Bottom -ive", 50, -20, 20);
+        IHistogram1D plot133 = aida.histogram1D("Track - Cluster Y:  Top +ive", 50, -20, 20);
+        IHistogram1D plot134 = aida.histogram1D("Track - Cluster Y:  Bottom +ive", 50, -20, 20);
+        extrap13.region(0).plot(plot131);
+        extrap13.region(1).plot(plot132);
+        extrap13.region(2).plot(plot133);
+        extrap13.region(3).plot(plot134);
+
+
+
+
+
+
+    }
+
+    private void set2DStyle(IPlotterStyle style) {
+        style.setParameter("hist2DStyle", "colorMap");
+        style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        style.dataStyle().fillStyle().setColor("yellow");
+        style.dataStyle().errorBarStyle().setVisible(false);
+        style.statisticsBoxStyle().setVisible(false);
+    }
+
+    private void set1DStyle(IPlotterStyle style) {
+        style.setParameter("hist2DStyle", "colorMap");
+        style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        style.dataStyle().fillStyle().setColor("yellow");
+        style.dataStyle().errorBarStyle().setVisible(false);
+        style.statisticsBoxStyle().setVisible(true);
+    }
+
+    private HPSEcalCluster findClosestCluster(Hep3Vector posonhelix, List<HPSEcalCluster> clusters) {
+        HPSEcalCluster closest = null;
+        double minDist = 9999;
+        for (HPSEcalCluster cluster : clusters) {
+            double[] clPos = cluster.getPosition();
+            double clEne = cluster.getEnergy();
+//            double dist = Math.sqrt(Math.pow(clPos[0] - posonhelix.y(), 2) + Math.pow(clPos[1] - posonhelix.z(), 2)); //coordinates!!!
+            double dist = Math.sqrt(Math.pow(clPos[1] - posonhelix.z(), 2)); //coordinates!!!
+            if (dist < minDist && clEne > 50) {
+                closest = cluster;
+                minDist = dist;
+            }
+        }
+        return closest;
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham
TwoTrackAnalysis.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/TwoTrackAnalysis.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/TwoTrackAnalysis.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,988 @@
+package org.lcsim.hps.users.mgraham;
+
+import Jama.Matrix;
+import Jama.SingularValueDecomposition;
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IPlotter;
+import hep.aida.IPlotterStyle;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.event.BeamlineConstants;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.monitoring.deprecated.Resettable;
+import org.lcsim.hps.recon.tracking.HPSTrack;
+import org.lcsim.hps.recon.vertexing.HelixConverter;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author mgraham
+ */
+public class TwoTrackAnalysis extends Driver implements Resettable {
+
+    public String outputTextName = "myevents.txt";
+    FileWriter fw;
+    PrintWriter pw;
+    private AIDAFrame plotterFrame;
+    private AIDA aida = AIDA.defaultInstance();
+    IPlotter plotter;
+    IPlotter plotter2;
+    IPlotter plotter3;
+    IPlotter plotter4;
+    IPlotter plotter5;
+    IPlotter plotter6;
+    IPlotter plotter7;
+    IPlotter plotter8;
+    IAnalysisFactory fac = aida.analysisFactory();
+    private String trackCollectionName = "MatchedTracks";
+    private String outputPlots = null;
+    private boolean isMC = true;
+    private boolean showPlots = false;
+    int nevt = 0;
+
+    protected void detectorChanged(Detector detector) {
+        aida.tree().cd("/");
+        if (showPlots) {
+            plotterFrame = new AIDAFrame();
+            plotterFrame.setTitle("HPS Tracking Plots");
+        }
+        plotter = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter.setTitle("Momentum");
+        IPlotterStyle style = plotter.style();
+        style.dataStyle().fillStyle().setColor("yellow");
+        style.dataStyle().errorBarStyle().setVisible(false);
+        plotter.createRegions(2, 2);
+        if (showPlots) {
+            plotterFrame.addPlotter(plotter);
+        }
+
+        IHistogram1D trkPx = aida.histogram1D("Track Momentum (Px)", 25, -0.25, 0.25);
+        IHistogram1D trkPy = aida.histogram1D("Track Momentum (Py)", 25, -0.1, 0.1);
+        IHistogram1D trkPz = aida.histogram1D("Track Momentum (Pz)", 25, 0, 3.5);
+        IHistogram1D trkChi2 = aida.histogram1D("Track Chi2", 25, 0, 25.0);
+
+        plotter.region(0).plot(trkPx);
+        plotter.region(1).plot(trkPy);
+        plotter.region(2).plot(trkPz);
+        plotter.region(3).plot(trkChi2);
+
+////////////////////////////////////////////////////////////////////
+
+        plotter2 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter2.setTitle("Vertex");
+
+        plotter2.style().dataStyle().fillStyle().setColor("yellow");
+        plotter2.style().dataStyle().errorBarStyle().setVisible(false);
+        plotter2.createRegions(2, 2);
+        if (showPlots) {
+            plotterFrame.addPlotter(plotter2);
+        }
+
+        IHistogram1D xvert = aida.histogram1D("XVertex", 40, -30, 50);
+        IHistogram1D yvert = aida.histogram1D("YVertex", 40, -35, 30);
+        IHistogram1D zvert = aida.histogram1D("ZVertex", 40, -800, -450);
+        IHistogram1D dist = aida.histogram1D("Distance btwn Trks @ Solution", 40, 0, 20);
+        plotter2.region(0).plot(xvert);
+        plotter2.region(1).plot(yvert);
+        plotter2.region(2).plot(zvert);
+        plotter2.region(3).plot(dist);
+        ////////////////////////////////////////////////////////////////////
+
+        plotter4 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter4.setTitle("Vertex w/cut");
+        plotter4.style().dataStyle().fillStyle().setColor("yellow");
+        plotter4.style().dataStyle().errorBarStyle().setVisible(false);
+        plotter4.createRegions(2, 2);
+        if (showPlots) {
+            plotterFrame.addPlotter(plotter4);
+        }
+
+        IHistogram1D xvertns = aida.histogram1D("XVertex with y cut", 40, -30, 50);
+        IHistogram1D yvertns = aida.histogram1D("YVertex with y cut", 40, -35, 30);
+        IHistogram1D zvertns = aida.histogram1D("ZVertex with y cut", 40, -800, -450);
+        IHistogram1D distns = aida.histogram1D("Distance btwn Trks with y cut", 40, 0, 20);
+        plotter4.region(0).plot(xvertns);
+        plotter4.region(1).plot(yvertns);
+        plotter4.region(2).plot(zvertns);
+        plotter4.region(3).plot(distns);
+////////////////////////////////////////////////////////////////////
+
+        plotter3 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter3.setTitle("Track @ Converter");
+
+        plotter3.style().dataStyle().fillStyle().setColor("yellow");
+        plotter3.style().dataStyle().errorBarStyle().setVisible(false);
+        plotter3.createRegions(2, 2);
+        if (showPlots) {
+            plotterFrame.addPlotter(plotter3);
+        }
+        IHistogram1D xAtConvert = aida.histogram1D("X (mm) @ Converter using Map", 50, -50, 50);
+        IHistogram1D yAtConvert = aida.histogram1D("Y (mm) @ Converter using Map", 50, -20, 20);
+        IHistogram1D xAtConvertSLT = aida.histogram1D("X (mm) @ Converter using SLT", 50, -50, 50);
+        IHistogram1D yAtConvertSLT = aida.histogram1D("Y (mm) @ Converter using SLT", 50, -20, 20);
+        plotter3.region(0).plot(xAtConvert);
+        plotter3.region(1).plot(yAtConvert);
+        plotter3.region(2).plot(xAtConvertSLT);
+        plotter3.region(3).plot(yAtConvertSLT);
+
+        plotter5 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter5.setTitle("Mass");
+        plotter5.style().dataStyle().fillStyle().setColor("yellow");
+        plotter5.style().dataStyle().errorBarStyle().setVisible(false);
+        //plotter5.createRegions(2, 2);
+        if (showPlots) {
+            plotterFrame.addPlotter(plotter5);
+        }
+        IHistogram1D invMass = aida.histogram1D("Invariant Mass", 50, 0, .4);
+
+        plotter5.region(0).plot(invMass);
+
+        plotter6 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter6.setTitle("correlations");
+        plotter6.style().setParameter("hist2DStyle", "colorMap");
+        plotter6.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter6.createRegions(1, 3);
+        IHistogram2D xy = aida.histogram2D("X v Y", 50, -30, 50, 50, -35, 30);
+        IHistogram2D xz = aida.histogram2D("X v Z", 50, -30, 50, 50, -800, -450);
+        IHistogram2D yz = aida.histogram2D("Y v Z", 50, -35, 30, 50, -800, -450);
+        plotter6.region(0).plot(xy);
+        plotter6.region(1).plot(xz);
+        plotter6.region(2).plot(yz);
+
+
+
+        IHistogram1D trkbins = aida.histogram1D("Track Distributions", 5, -2, 3);
+        IHistogram2D twtrkptot = aida.histogram2D("Total P+ vs. P-", 60, 0, 4, 60, 0, 4);
+        IHistogram1D sumtrks = aida.histogram1D("Sum of Track's Momentums", 100, -1, 7);
+        IHistogram1D perptrks = aida.histogram1D("Perpendicular Momentum", 100, 0, .1);
+        IHistogram2D pyppm = aida.histogram2D("Py+ vs. Py-", 60, -.1, .1, 60, -.1, .1);
+        IHistogram2D pzppm = aida.histogram2D("Pz+ vs. Pz-", 60, -.1, .1, 60, -.1, .1);
+        IHistogram1D px = aida.histogram1D("Two Track X Momentum", 40, 0, 4);
+        IHistogram1D py = aida.histogram1D("Two Track Y Momentum", 40, -.1, .1);
+        IHistogram1D pz = aida.histogram1D("Two Track Z Momentum", 40, -.1, .1);
+        IHistogram1D chi2 = aida.histogram1D("Tracks Chi2", 25, 0, 25.0);
+        IHistogram1D bbpx = aida.histogram1D("Big Bump Track Momenta (Px)", 40, 0, 4);
+        IHistogram1D bbpy = aida.histogram1D("Big Bump Track Momenta (Py)", 40, -.1, .1);
+        IHistogram1D bbpz = aida.histogram1D("Big Bump Track Momenta (Pz)", 40, -.1, .1);
+        IHistogram1D bbchi2 = aida.histogram1D("Big Bump Tracks Chi2", 25, 0, 25.0);
+        IHistogram1D spx = aida.histogram1D("Split Track Momenta (Px)", 40, 0, 4);
+        IHistogram1D spy = aida.histogram1D("Split Track Momenta (Py)", 40, -.1, .1);
+        IHistogram1D spz = aida.histogram1D("Split Track Momenta (Pz)", 40, -.1, .1);
+        IHistogram1D schi2 = aida.histogram1D("Split Tracks Chi2", 25, 0, 25.0);
+        IHistogram1D bbsumtrks = aida.histogram1D("Big Bump Sum of Track's Momentums", 50, -1, 7);
+        IHistogram2D bbpppm = aida.histogram2D("Big Bump P+ vs. P-", 50, 0, 4, 50, 0, 4);
+        IHistogram2D lbpppm = aida.histogram2D("Little Bump P+ vs. P-", 50, 0, 4, 50, 0, 4);
+        IHistogram1D lbsumtrks = aida.histogram1D("Little Bump Sum of Track's Momentums", 50, -1, 7);
+        IHistogram1D lbpx = aida.histogram1D("Little Bump Track Momenta (Px)", 40, 0, 4);
+        IHistogram1D lbpy = aida.histogram1D("Little Bump Track Momenta (Py)", 40, -.1, .1);
+        IHistogram1D lbpz = aida.histogram1D("Little Bump Track Momenta (Pz)", 40, -.1, .1);
+        IHistogram1D lbchi2 = aida.histogram1D("Little Bump Tracks Chi2", 25, 0, 25.0);
+        IHistogram2D xyemt = aida.histogram2D("X v Y - e- Top", 50, -30, 50, 50, -35, 30);
+        IHistogram2D xzemt = aida.histogram2D("X v Z - e- Top", 50, -30, 50, 50, -800, -450);
+        IHistogram2D yzemt = aida.histogram2D("Y v Z - e- Top", 50, -35, 30, 50, -800, -450);
+        IHistogram1D qbins = aida.histogram1D("Charge Distributions", 5, -2, 3);
+        IHistogram1D lbtp = aida.histogram1D("Little Bump Track Parity", 7, 0, 7);
+        IHistogram1D bbtp = aida.histogram1D("Big Bump Track Parity", 7, 0, 7);
+        IHistogram1D xres = aida.histogram1D("X Res Trk1", 40, -0.25, 0.25);
+        IHistogram1D yres = aida.histogram1D("Y Res Trk1", 40, -0.25, 0.25);
+        IHistogram1D xres2 = aida.histogram1D("X Res Trk2", 40, -0.25, 0.25);
+        IHistogram1D yres2 = aida.histogram1D("Y Res Trk2", 40, -0.25, 0.25);
+        IHistogram1D unx1 = aida.histogram1D("Uncert X Trk 1", 50, 0, 10);
+        IHistogram1D uny1 = aida.histogram1D("Uncert Y Trk 1", 50, 0, 10);
+        IHistogram1D unz1 = aida.histogram1D("Uncert Z Trk 1", 50, 0, 40);
+        IHistogram1D unx2 = aida.histogram1D("Uncert X Trk 2", 50, 0, 10);
+        IHistogram1D uny2 = aida.histogram1D("Uncert Y Trk 2", 50, 0, 10);
+        IHistogram1D unz2 = aida.histogram1D("Uncert Z Trk 2", 50, 0, 40);
+        IHistogram2D xyept = aida.histogram2D("X v Y - e+ Top", 50, -30, 50, 50, -35, 30);
+        IHistogram2D xzept = aida.histogram2D("X v Z - e+ Top", 50, -30, 50, 50, -800, -450);
+        IHistogram2D yzept = aida.histogram2D("Y v Z - e+ Top", 50, -35, 30, 50, -800, -450);
+        IHistogram1D three = aida.histogram1D("Three Track Invariant Mass", 50, 0, .4);
+
+        plotter7 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter7.setTitle("correlations e+ Top");
+        plotter7.style().setParameter("hist2DStyle", "colorMap");
+        plotter7.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter7.createRegions(1, 3);
+        plotter7.region(0).plot(xyept);
+        plotter7.region(1).plot(xzept);
+        plotter7.region(2).plot(yzept);
+
+        plotter8 = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter8.setTitle("correlations e- Top");
+        plotter8.style().setParameter("hist2DStyle", "colorMap");
+        plotter8.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter8.createRegions(1, 3);
+        plotter8.region(0).plot(xyemt);
+        plotter8.region(1).plot(xzemt);
+        plotter8.region(2).plot(yzemt);
+
+        if (showPlots) {
+            plotterFrame.pack();
+            plotterFrame.setVisible(true);
+        }
+    }
+
+    public void setIsMC(boolean setit) {
+        isMC = setit;
+    }
+
+    public void process(EventHeader event) {
+
+        if (nevt == 0) {
+            try {
+//open things up
+                fw = new FileWriter(outputTextName);
+                pw = new PrintWriter(fw);
+            } catch (IOException ex) {
+                Logger.getLogger(TwoTrackAnalysis.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+        nevt++;
+        aida.tree().cd("/");
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+        System.out.println("Staring TwoTrackAnalysis");
+        for (Track trk : tracks) {
+            aida.histogram1D("Track Momentum (Px)").fill(trk.getPY());
+            aida.histogram1D("Track Momentum (Py)").fill(trk.getPZ());
+            aida.histogram1D("Track Momentum (Pz)").fill(trk.getPX());
+            aida.histogram1D("Track Chi2").fill(trk.getChi2());
+
+            SeedTrack stEle = (SeedTrack) trk;
+            SeedCandidate seedEle = stEle.getSeedCandidate();
+            HelicalTrackFit ht = seedEle.getHelix();
+            HelixConverter converter = new HelixConverter(0);
+            StraightLineTrack slt = converter.Convert(ht);
+            HPSTrack hpstrack = new HPSTrack(ht);
+            Hep3Vector[] trkatconver = hpstrack.getPositionAtZMap(100, BeamlineConstants.HARP_POSITION_TESTRUN, 1);
+            aida.histogram1D("X (mm) @ Converter using Map").fill(trkatconver[0].x()); // y tracker frame?
+            aida.histogram1D("Y (mm) @ Converter using Map").fill(trkatconver[0].y()); // z tracker frame?
+            if (slt != null) {
+                aida.histogram1D("X (mm) @ Converter using SLT").fill(slt.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[0]); // y tracker frame?
+                aida.histogram1D("Y (mm) @ Converter using SLT").fill(slt.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[1]); // z tracker frame?
+            }
+        }
+
+        System.out.println("...checking if two tracks...");
+
+        if (tracks.size() == 2) { //uncert can be used here  && (Ytrue || Ytrue2) && (Xtrue || Xtrue2)
+            System.out.println("               ...yes!");
+
+            Track trk1 = tracks.get(0);
+            Track trk2 = tracks.get(1);
+            int isTrk1Top = -1;
+            if (trk1.getTrackerHits().get(0).getPosition()[2] > 0) {
+                isTrk1Top = 1;
+            }
+            int isTrk2Top = -1;
+            if (trk2.getTrackerHits().get(0).getPosition()[2] > 0) {
+                isTrk2Top = 1;
+            }
+            boolean topbot = false;
+            if ((isTrk1Top + isTrk2Top) == 0) {
+                topbot = true;
+            }
+
+            SeedTrack stEle1 = (SeedTrack) trk1;
+            SeedCandidate seedEle1 = stEle1.getSeedCandidate();
+            HelicalTrackFit ht1 = seedEle1.getHelix();
+            HelixConverter converter1 = new HelixConverter(0);
+            StraightLineTrack slt1 = converter1.Convert(ht1);
+
+            SeedTrack stEle2 = (SeedTrack) trk2;
+            SeedCandidate seedEle2 = stEle2.getSeedCandidate();
+            HelicalTrackFit ht2 = seedEle2.getHelix();
+            HelixConverter converter2 = new HelixConverter(0);
+            StraightLineTrack slt2 = converter2.Convert(ht2);
+
+//            HPSTrack hpstrack1 = new HPSTrack(ht1);
+//            Hep3Vector[] trkatconver1 = hpstrack1.getPositionAtZMap(100, BeamlineConstants.HARP_POSITION, 1);
+//            HPSTrack hpstrack2 = new HPSTrack(ht2);
+//            Hep3Vector[] trkatconver2 = hpstrack2.getPositionAtZMap(100, BeamlineConstants.HARP_POSITION, 1);
+
+            HPSTrack hpstrack1 = new HPSTrack(ht1);
+            Hep3Vector[] trkatconver1 = {new BasicHep3Vector(), new BasicHep3Vector(0, 0, 0)};
+            HPSTrack hpstrack2 = new HPSTrack(ht2);
+            Hep3Vector[] trkatconver2 = {new BasicHep3Vector(), new BasicHep3Vector(0, 0, 0)};;
+            if (isMC) {
+                double[] t1 = slt1.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN);
+                double[] t2 = slt2.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN);
+                trkatconver1[0] = new BasicHep3Vector(t1[0], t1[1], BeamlineConstants.HARP_POSITION_TESTRUN);
+                trkatconver2[0] = new BasicHep3Vector(t2[0], t2[1], BeamlineConstants.HARP_POSITION_TESTRUN);
+            } else {
+                trkatconver1 = hpstrack1.getPositionAtZMap(100, BeamlineConstants.HARP_POSITION_TESTRUN, 1);
+                trkatconver2 = hpstrack2.getPositionAtZMap(100, BeamlineConstants.HARP_POSITION_TESTRUN, 1);
+            }
+            List<TrackerHit> hitsOnTrack1 = trk1.getTrackerHits();
+            int layer1;
+            double y1 = 0;
+            double y2 = 0;
+            double z1 = 0;
+            double z2 = 0;
+            double dely1 = 0;
+            double dely2 = 0;
+            for (TrackerHit hit : hitsOnTrack1) {
+                HelicalTrackHit htc1 = (HelicalTrackHit) hit;
+                layer1 = htc1.Layer();
+                int y1layer = 0;
+                int y2layer = 0;
+                if (y1 == 0) {
+                    y1 = htc1.getPosition()[2]; //
+                    z1 = htc1.getPosition()[0]; // z1 is jlab but the get position refers to hps-tracking
+                    y1layer = layer1;
+                    SymmetricMatrix ErrorHitOne = htc1.getCorrectedCovMatrix();
+                    dely1 = Math.sqrt(ErrorHitOne.diagonal(2)); //y in jlab is z in hps
+                } else {
+
+                    if ((layer1 > y1layer) && (y2layer == 0)) {
+                        y2 = htc1.getPosition()[2]; //
+                        z2 = htc1.getPosition()[0]; // see above comments!
+                        y2layer = layer1;
+                        SymmetricMatrix ErrorHitTwo = htc1.getCorrectedCovMatrix();
+                        dely2 = Math.sqrt(ErrorHitTwo.diagonal(2));
+                    }
+
+                }
+
+            }
+            List<TrackerHit> hitsOnTrack2 = trk2.getTrackerHits();
+
+            double my1 = 0;
+            double my2 = 0;
+            double mz1 = 0;
+            double mz2 = 0;
+            double delymy1 = 0;
+            double delymy2 = 0;
+            int layer2;
+            for (TrackerHit hit : hitsOnTrack2) {
+                HelicalTrackHit htc2 = (HelicalTrackHit) hit;
+//            if (htc.getPosition()[2] < 0) {
+
+                layer2 = htc2.Layer();
+                int my1layer = 0;
+                int my2layer = 0;
+                if (my1 == 0) {
+                    my1 = htc2.getPosition()[2]; //see above comments
+                    mz1 = htc2.getPosition()[0];
+                    my1layer = layer2;
+                    SymmetricMatrix ErrorHitOne = htc2.getCorrectedCovMatrix();
+                    delymy1 = Math.sqrt(ErrorHitOne.diagonal(2));
+                } else {
+                    if ((layer2 > my1layer) && (my2layer == 0)) {
+                        my2 = htc2.getPosition()[2];
+                        mz2 = htc2.getPosition()[0];
+                        my2layer = layer2;
+                        SymmetricMatrix ErrorHitTwo = htc2.getCorrectedCovMatrix();
+                        delymy2 = Math.sqrt(ErrorHitTwo.diagonal(2));
+                    }
+                }
+            }
+            //   double dely = .00001; //mm
+            double b1;
+            double m1;
+            double b2;
+            double m2;
+            boolean check1 = true;
+            if (y1 == 0) {
+                check1 = false;
+            }
+            boolean check2 = true;
+            if (my1 == 0) {
+                check2 = false;
+            }
+            boolean check3 = true;
+            if (my2 == 0) {
+                check3 = false;
+            }
+
+
+
+            double X1 = -99, Y1 = -99;
+            if (slt1 != null) {
+                X1 = slt1.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[0];
+                Y1 = slt1.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[1];
+            }
+
+            boolean X1cent = false;
+            boolean Y1cent = false; //for simulation
+
+            if (11 < X1 && X1 < 29) {
+                X1cent = true;
+            }
+            if (-3.5 < Y1 && Y1 < 3.5) {
+                Y1cent = true;
+            }
+
+            double X2 = 99, Y2 = 99;
+            if (slt2 != null) {
+                X2 = slt2.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[0];
+                Y2 = slt2.getYZAtX(BeamlineConstants.HARP_POSITION_TESTRUN)[1];
+            }
+
+            boolean X2cent = false;
+            boolean Y2cent = false; //for simulation
+            if (11 < X2 && X2 < 29) {
+                X2cent = true;
+            }
+            if (-3.5 < Y2 && Y2 < 3.5) {
+                Y2cent = true;
+            }
+
+            int qtrk1 = trk1.getCharge();
+            int qtrk2 = trk2.getCharge();
+            boolean pm = false;
+            if ((qtrk1 + qtrk2) == 0) {
+                pm = true;
+            }
+
+
+            if (topbot && pm) {
+
+                double b1p;
+                double b2p;
+                double m1p;
+                double m2p;
+
+                if (check1 && check2 && check3) {
+                    if (isTrk1Top == 1) {
+                        double zc = -1 * z1 / (z2 - z1);
+                        b1 = (zc * (y2 - y1 + .5 * (dely2 + dely1))) + y1 - (.5 * dely1);
+                        m1 = (y2 - y1 + .5 * (dely2 + dely1)) / (z2 - z1);
+                        m1p = (y2 - y1 - .5 * (dely2 + dely1)) / (z2 - z1);
+                        b1p = y1 - (m1p * z1) + (.5 * dely1);
+                    } else {
+                        double zc = -1 * z1 / (z2 - z1);
+                        b1 = (zc * (y2 - y1 - .5 * (dely2 + dely1))) + y1 + (.5 * dely1);
+                        m1 = (y2 - y1 - .5 * (dely2 + dely1)) / (z2 - z1);
+                        m1p = (y2 - y1 + .5 * (dely2 + dely1)) / (z2 - z1);
+                        b1p = y1 - (m1p * z1) - (.5 * dely1);
+                    }
+
+                    if (isTrk2Top == 1) {
+                        double zc = -1 * mz1 / (mz2 - mz1);
+                        b2 = (zc * (my2 - my1 + .5 * (delymy2 + delymy1))) + my1 - (.5 * delymy1);
+                        m2 = (my2 - my1 + .5 * (delymy2 + delymy1)) / (mz2 - mz1);
+                        m2p = (my2 - my1 - .5 * (delymy2 + delymy1)) / (mz2 - mz1);
+                        b2p = my1 - (m2p * mz1) + (.5 * delymy1);
+                    } else {
+                        double zc = -1 * mz1 / (mz2 - mz1);
+                        b2 = (zc * (my2 - my1 - .5 * (delymy2 + delymy1))) + my1 + (.5 * delymy1);
+                        m2 = (my2 - my1 - .5 * (delymy2 + delymy1)) / (mz2 - mz1);
+                        m2p = (my2 - my1 + .5 * (delymy2 + delymy1)) / (mz2 - mz1);
+                        b2p = my1 - (m2p * mz1) - (.5 * delymy1);
+                    }
+
+                    double zi = (b2 - b1) / (m1 - m2);
+                    double zr = Math.abs(zi - BeamlineConstants.HARP_POSITION_TESTRUN);
+                    double zs = 2 * zr / 100;
+                    //      System.out.println("Closest Possible Z to Tracker");
+                    //      System.out.println(zi);
+
+
+                    List<double[]> Trk1 = new ArrayList<double[]>();
+                    for (int i = 0; i < 100; i++) {
+                        double z = BeamlineConstants.HARP_POSITION_TESTRUN - zr + (zs * i);
+                        double[] posvec = new double[3];
+                        if (isMC) {
+                            posvec[0] = slt1.getYZAtX(z)[0];
+                            posvec[1] = slt1.getYZAtX(z)[1];
+                            posvec[2] = z;
+                        } else {
+                            Hep3Vector[] trk1atz = hpstrack1.getPositionAtZMap(100, z, 1);
+                            posvec[0] = trk1atz[0].x();
+                            posvec[1] = trk1atz[0].y();
+                            posvec[2] = z;
+                        }
+                        Trk1.add(posvec);
+                    }
+                    //  System.out.println("Vectors ");
+
+                    //  System.out.println(Trk1);
+
+                    double xbar = 0;
+                    double ybar = 0;
+                    double zbar = 0;
+                    double xsqbar = 0;
+                    double ysqbar = 0;
+                    double zsqbar = 0;
+                    int n = 0;
+                    for (double[] inttrk : Trk1) {
+                        //      System.out.println(inttrk[0]);
+                        //    System.out.println(inttrk[1]);
+                        //    System.out.println(inttrk[2]);
+                        xbar = xbar + inttrk[0];
+                        ybar = ybar + inttrk[1];
+                        zbar = zbar + inttrk[2];
+                        n = n + 1;
+                    }
+                    //   System.out.println("n " + n);
+                    xbar = xbar / n;
+                    ybar = ybar / n;
+                    zbar = zbar / n;
+                    //    System.out.println("Xbar is " + xbar);
+                    //    System.out.println("Ybar is " + ybar);
+                    //    System.out.println("Zbar is " + zbar);
+                    Matrix d;
+                    Matrix A = Matrix.random(n, 3);
+                    int j1 = 0;
+                    for (double[] inttrk : Trk1) {
+                        A.set(j1, 0, inttrk[0] - xbar);
+                        A.set(j1, 1, inttrk[1] - ybar);
+                        A.set(j1, 2, inttrk[2] - zbar);
+                        j1++;
+                    }
+
+                    //           System.out.println("Matrix A");
+                    //           A.print(9, 6);
+                    A.svd();
+                    SingularValueDecomposition s = A.svd();
+                    Matrix S = s.getS();
+                    //         System.out.println("S Matrix");
+                    //         S.print(9, 6);
+                    Matrix V = s.getV();
+                    //         System.out.println("V Matrix");
+                    //         V.print(9, 6);
+                    d = V.getMatrix(0, 2, 0, 0);
+                    double[] dd;
+                    dd = new double[3];
+
+                    dd[0] = d.get(0, 0);
+                    dd[1] = d.get(1, 0);
+                    dd[2] = d.get(2, 0);
+                    double nd = Math.sqrt((Math.pow(dd[0], 2)) + (Math.pow(dd[1], 2)) + (Math.pow(dd[2], 2)));
+
+                    for (double[] inttrk : Trk1) {
+                        double t1 = (inttrk[2] - zbar) / dd[2];
+                        double restrk1[];
+                        restrk1 = new double[3];
+                        restrk1[0] = xbar + (t1) * dd[0] - inttrk[0];
+                        restrk1[1] = ybar + (t1) * dd[1] - inttrk[1];
+                        restrk1[2] = zbar + (t1) * dd[2] - inttrk[2];
+                        //aida.histogram1D("X Res Trk1").fill(restrk1[0]);
+                        //aida.histogram1D("Y Res Trk1").fill(restrk1[1]);
+                    }
+
+                    List<double[]> Trk2 = new ArrayList<double[]>();
+                    for (int i = 0; i < 100; i++) {
+                        double z = BeamlineConstants.HARP_POSITION_TESTRUN - zr + (zs * i);
+                        double[] posvec2 = new double[3];
+
+                        if (isMC) {
+                            posvec2[0] = slt2.getYZAtX(z)[0];
+                            posvec2[1] = slt2.getYZAtX(z)[1];
+                            posvec2[2] = z;
+                        } else {
+                            Hep3Vector[] trk2atz = hpstrack2.getPositionAtZMap(100, z, 1);
+                            posvec2[0] = trk2atz[0].x();
+                            posvec2[1] = trk2atz[0].y();
+                            posvec2[2] = z;
+                        }
+                        Trk2.add(posvec2);
+                        //      System.out.println("Components");
+                        //      System.out.println(posvec2[0]);
+                        //      System.out.println(posvec2[1]);
+                        //      System.out.println(posvec2[2]);
+                    }
+                    double xbar2 = 0;
+                    double ybar2 = 0;
+                    double zbar2 = 0;
+                    int n2 = 0;
+                    for (double[] trk : Trk2) {
+                        xbar2 = xbar2 + trk[0];
+                        ybar2 = ybar2 + trk[1];
+                        zbar2 = zbar2 + trk[2];
+                        n2 = n2 + 1;
+                    }
+                    xbar2 = xbar2 / n2;
+                    ybar2 = ybar2 / n2;
+                    zbar2 = zbar2 / n2;
+                    Matrix d2;
+                    Matrix A2 = Matrix.random(n, 3);
+
+                    int j2 = 0;
+                    for (double[] inttrk : Trk2) {
+                        A2.set(j2, 0, inttrk[0] - xbar2);
+                        A2.set(j2, 1, inttrk[1] - ybar2);
+                        A2.set(j2, 2, inttrk[2] - zbar2);
+                        j2++;
+                    }
+
+                    A2.svd();
+                    SingularValueDecomposition s2 = A2.svd();
+                    Matrix V2 = s2.getV();
+                    d2 = V2.getMatrix(0, 2, 0, 0);
+                    double[] d22;
+                    d22 = new double[3];
+                    d22[0] = d2.get(0, 0);
+                    d22[1] = d2.get(1, 0);
+                    d22[2] = d2.get(2, 0);
+                    double nd2 = Math.sqrt((Math.pow(d22[0], 2)) + (Math.pow(d22[1], 2)) + (Math.pow(d22[2], 2)));
+
+                    for (double[] inttrk : Trk2) {
+                        double t2 = (inttrk[2] - zbar2) / d22[2];
+                        double restrk2[];
+                        restrk2 = new double[3];
+                        restrk2[0] = xbar2 + (t2) * d22[0] - inttrk[0];
+                        restrk2[1] = ybar2 + (t2) * d22[1] - inttrk[1];
+                        restrk2[2] = zbar2 + (t2) * d22[2] - inttrk[2];
+                        //aida.histogram1D("X Res Trk2").fill(restrk2[0]);
+                        //aida.histogram1D("Y Res Trk2").fill(restrk2[1]);
+
+                    }
+
+                    //solution for intersection below!! 
+
+                    //starting with costant matrix b
+                    double x11 = Math.pow(nd, 2) - Math.pow(dd[0], 2);
+                    double y11 = Math.pow(nd, 2) - Math.pow(dd[1], 2);
+                    double z11 = Math.pow(nd, 2) - Math.pow(dd[2], 2);
+                    double x22 = Math.pow(nd2, 2) - Math.pow(d22[0], 2);
+                    double y22 = Math.pow(nd2, 2) - Math.pow(d22[1], 2);
+                    double z22 = Math.pow(nd2, 2) - Math.pow(d22[2], 2);
+                    double xy1 = -1 * dd[0] * dd[1];
+                    double xz1 = -1 * dd[0] * dd[2];
+                    double yz1 = -1 * dd[1] * dd[2];
+                    double xy2 = -1 * d22[0] * d22[1];
+                    double xz2 = -1 * d22[0] * d22[2];
+                    double yz2 = -1 * d22[1] * d22[2];
+                    Matrix Intersect = Matrix.random(6, 3);
+                    Intersect.set(0, 0, x11);
+                    Intersect.set(1, 0, xy1);
+                    Intersect.set(2, 0, xz1);
+                    Intersect.set(0, 1, xy1);
+                    Intersect.set(1, 1, y11);
+                    Intersect.set(2, 1, yz1);
+                    Intersect.set(0, 2, xz1);
+                    Intersect.set(1, 2, yz1);
+                    Intersect.set(2, 2, z11);
+
+                    Intersect.set(3, 0, x22);
+                    Intersect.set(4, 0, xy2);
+                    Intersect.set(5, 0, xz2);
+                    Intersect.set(3, 1, xy2);
+                    Intersect.set(4, 1, y22);
+                    Intersect.set(5, 1, yz2);
+                    Intersect.set(3, 2, xz2);
+                    Intersect.set(4, 2, yz2);
+                    Intersect.set(5, 2, z22);
+                    Matrix b = Matrix.random(6, 1);
+                    b.set(0, 0, (x11 * xbar) + (xy1 * ybar) + (xz1 * zbar));
+                    b.set(1, 0, (y11 * ybar) + (xy1 * xbar) + (yz1 * zbar));
+                    b.set(2, 0, (z11 * zbar) + (xz1 * xbar) + (yz1 * ybar));
+                    b.set(3, 0, (x22 * xbar2) + (xy2 * ybar2) + (xz2 * zbar2));
+                    b.set(4, 0, (y22 * ybar2) + (xy2 * xbar2) + (yz2 * zbar2));
+                    b.set(5, 0, (z22 * zbar2) + (xz2 * xbar2) + (yz2 * ybar2));
+
+                    Intersect.svd();
+                    SingularValueDecomposition s3 = Intersect.svd();
+                    Matrix Vint = s3.getV();
+                    Matrix Uint = s3.getU();
+                    Matrix Sint = s3.getS();
+                    //       System.out.println("S Matrix");
+                    //       Sint.print(9, 6);
+                    Matrix VT = Vint.transpose();
+                    Matrix UT = Uint.transpose();
+                    Matrix SI = Sint.inverse();
+                    //      System.out.println("Inverted S Matrix");
+                    //      SI.print(9, 6);
+                    Matrix C1 = VT.times(SI);
+                    Matrix C2 = C1.times(UT);
+                    Matrix C = C2.times(b);
+                    C.print(9, 6);
+                    aida.histogram1D("XVertex").fill(C.get(0, 0));
+                    aida.histogram1D("YVertex").fill(C.get(1, 0));
+                    aida.histogram1D("ZVertex").fill(C.get(2, 0));
+
+                    aida.histogram2D("X v Y").fill(C.get(0, 0), C.get(1, 0));
+                    aida.histogram2D("X v Z").fill(C.get(0, 0), C.get(2, 0));
+                    aida.histogram2D("Y v Z").fill(C.get(1, 0), C.get(2, 0));
+
+                    double zint = C.get(2, 0);
+                    double t1 = (zint - zbar) / dd[2];
+                    double t2 = (zint - zbar2) / d22[2];
+                    double postrk1[];
+                    postrk1 = new double[3];
+                    postrk1[0] = xbar + (t1) * dd[0];
+                    postrk1[1] = ybar + (t1) * dd[1];
+                    postrk1[2] = zbar + (t1) * dd[2];
+                    double postrk2[];
+                    postrk2 = new double[3];
+                    postrk2[0] = xbar2 + (t2) * d22[0];
+                    postrk2[1] = ybar2 + (t2) * d22[1];
+                    postrk2[2] = zbar2 + (t2) * d22[2];
+                    double distance = Math.sqrt(Math.pow(postrk2[0] - postrk1[0], 2) + Math.pow(postrk2[1] - postrk1[1], 2) + Math.pow(postrk2[2] - postrk1[2], 2));
+                    //     double distancex = Math.sqrt(Math.pow(postrk2[0] - postrk1[0], 2));
+                    //   double distancey = Math.sqrt(Math.pow(postrk2[1] - postrk1[1], 2));
+                    aida.histogram1D("Distance btwn Trks @ Solution").fill(distance);
+
+                    double pxE, pyE, pzE;
+                    double pxP, pyP, pzP;
+                    Hep3Vector[] trkatconvE;
+                    Hep3Vector[] trkatconvP;
+                    if (trk1.getCharge() > 0) {
+                        pxP = trk1.getPX();
+                        pyP = trk1.getPY();
+                        pzP = trk1.getPZ();
+                        pxE = trk2.getPX();
+                        pyE = trk2.getPY();
+                        pzE = trk2.getPZ();
+                        trkatconvP = trkatconver1;
+                        trkatconvE = trkatconver2;
+                    } else {
+                        pxP = trk2.getPX();
+                        pyP = trk2.getPY();
+                        pzP = trk2.getPZ();
+                        pxE = trk1.getPX();
+                        pyE = trk1.getPY();
+                        pzE = trk1.getPZ();
+                        trkatconvP = trkatconver2;
+                        trkatconvE = trkatconver1;
+                    }
+                    double vX = C.get(0, 0);
+                    double vY = C.get(1, 0);
+                    double vZ = C.get(2, 0);
+                    pw.format("%d %5.5f %5.5f %5.5f %5.5f %5.5f %5.5f ", nevt, pxE, pyE, pzE,trkatconvE[0].x(),trkatconvE[0].y(),trkatconvE[0].z());
+                    pw.format("%5.5f %5.5f %5.5f %5.5f %5.5f %5.5f ", pxP, pyP, pzP,trkatconvP[0].x(),trkatconvP[0].y(),trkatconvP[0].z());
+                    pw.format("%5.5f %5.5f %5.5f %5.5f ",distance,vX,vY,vZ);
+                    pw.println();
+
+                    if (trk1.getPX() > 0.25 && trk2.getPX() > 0.25 && Math.abs(C.get(1, 0)) < 6.0) {
+                        aida.histogram1D("XVertex with y cut").fill(C.get(0, 0));
+                        aida.histogram1D("YVertex with y cut").fill(C.get(1, 0));
+                        aida.histogram1D("ZVertex with y cut").fill(C.get(2, 0));
+                        aida.histogram1D("Distance btwn Trks with y cut").fill(distance);
+                    }
+                    double tt1 = (BeamlineConstants.HARP_POSITION_TESTRUN - zbar) / dd[2]; //target
+                    double tt2 = (BeamlineConstants.HARP_POSITION_TESTRUN - zbar2) / d22[2]; //target
+                    double postrk1att[];
+                    postrk1att = new double[3]; //target
+                    postrk1att[0] = xbar + (tt1) * dd[0];
+                    postrk1att[1] = ybar + (tt1) * dd[1];
+                    postrk1att[2] = zbar + (tt1) * dd[2];
+                    double postrk2att[]; //target
+                    postrk2att = new double[3];
+                    postrk2att[0] = xbar2 + (tt2) * d22[0];
+                    postrk2att[1] = ybar2 + (tt2) * d22[1];
+                    postrk2att[2] = zbar2 + (tt2) * d22[2];
+
+                    //aida.histogram1D("Trk1 X @ Target").fill(postrk1att[0]);
+                    //aida.histogram1D("Trk1 Y @ Target").fill(postrk1att[1]);
+                    //aida.histogram1D("Trk2 X @ Target").fill(postrk2att[0]);
+                    //aida.histogram1D("Trk2 Y @ Target").fill(postrk2att[1]);
+                    double distanceatt = Math.sqrt(Math.pow(postrk2att[0] - postrk1att[0], 2) + Math.pow(postrk2att[1] - postrk1att[1], 2) + Math.pow(postrk2att[2] - postrk1att[2], 2));
+                    // double zdiff = postrk2att[2] - postrk1att[2];
+                    //aida.histogram1D("Distance btwn Trks @ Target").fill(distanceatt);
+                    // aida.histogram1D("Z Diff").fill(zdiff);
+
+
+                    double uncerty = Math.abs((m1 - m2) * zint + (b1 - b2));
+                    //   double uncertx1 = Math.sqrt(uncertx1sq);
+                    double uncertz1 = Math.sqrt(zr);
+                    //   double uncertx2 = Math.sqrt(uncertx2sq);
+                    double uncertz2 = Math.sqrt(zr);
+                    //   aida.histogram1D("Uncert X Trk 1").fill(uncertx1);
+                    //aida.histogram1D("Uncert Y Trk 1").fill(uncerty);
+                    //aida.histogram1D("Uncert Z Trk 1").fill(uncertz1);
+                    // aida.histogram1D("Uncert X Trk 2").fill(uncerty2);
+                    //aida.histogram1D("Uncert Y Trk 2").fill(uncerty);
+                    //aida.histogram1D("Uncert Z Trk 2").fill(uncertz2);
+                    boolean yzbump1 = false;
+                    if (-18 < C.get(1, 0) && C.get(1, 0) < -12 && -645 < C.get(2, 0) && C.get(2, 0) < -600) {
+                        yzbump1 = true;
+                    }
+                    boolean yzbump2 = false;
+                    if (-4 < C.get(1, 0) && C.get(1, 0) < 4 && -720 < C.get(2, 0) && C.get(2, 0) < -605) {
+                        yzbump2 = true;
+                    }
+                    boolean xybump1 = false;
+                    if (-1 < C.get(0, 0) && C.get(0, 0) < 11 && -20 < C.get(1, 0) && C.get(1, 0) < -13) {
+                        xybump1 = true;
+                    }
+                    boolean xybump2 = false;
+                    if (11 < C.get(0, 0) && C.get(0, 0) < 25 && -4 < C.get(1, 0) && C.get(1, 0) < 3) {
+                        xybump2 = true;
+                    }
+                    int trksparity = 0;
+                    if (isTrk1Top == 1 && qtrk1 == 1) { //top e+ will be far right
+                        trksparity = 6;
+                    }
+                    if (isTrk1Top == 1 && qtrk1 == -1) { //top e- will be right of middle two
+                        trksparity = 4;
+                    }
+                    if (isTrk1Top == -1 && qtrk1 == 1) { // bot e+ will be left of middle two
+                        trksparity = 2;
+                    }
+                    if (isTrk1Top == -1 && qtrk1 == -1) { //bot e- will be far left
+                        trksparity = 0;
+                    }
+                    boolean eplustop = false;
+                    if ((isTrk1Top == 1 && qtrk1 == 1) || (isTrk2Top == 1 && qtrk2 == 1)) {
+                        eplustop = true;
+                    }
+                    if (yzbump1 && xybump1) {
+                        // aida.histogram1D("Little Bump Track Parity").fill(trksparity);
+                    }
+                    if (yzbump2 && xybump2) {
+                        // aida.histogram1D("Big Bump Track Parity").fill(trksparity);
+                    }
+                    if (eplustop) { //read Little bump as e+ top
+                        // aida.histogram1D("Little Bump Track Momenta (Px)").fill(trk1.getPX());
+                        // aida.histogram1D("Little Bump Track Momenta (Py)").fill(trk1.getPY());
+                        // aida.histogram1D("Little Bump Track Momenta (Pz)").fill(trk1.getPZ());
+                        // aida.histogram1D("Little Bump Tracks Chi2").fill(trk1.getChi2());
+                        // aida.histogram1D("Little Bump Track Momenta (Px)").fill(trk2.getPX());
+                        // aida.histogram1D("Little Bump Track Momenta (Py)").fill(trk2.getPY());
+                        // aida.histogram1D("Little Bump Track Momenta (Pz)").fill(trk2.getPZ());
+                        // aida.histogram1D("Little Bump Tracks Chi2").fill(trk2.getChi2());
+                        // aida.histogram1D("Little Bump Sum of Track's Momentums").fill(Math.sqrt(Math.pow((trk1.getPY() + trk2.getPY()), 2) + Math.pow((trk1.getPX() + trk2.getPX()), 2) + Math.pow((trk1.getPZ() + trk2.getPZ()), 2)));
+                        double Etrk1sq = (Math.pow(trkatconver1[1].x(), 2) + Math.pow(trkatconver1[1].y(), 2) + Math.pow(trkatconver1[1].z(), 2));
+                        double Etrk2sq = (Math.pow(trkatconver2[1].x(), 2) + Math.pow(trkatconver2[1].y(), 2) + Math.pow(trkatconver2[1].z(), 2));
+                        double Etrk1 = Math.sqrt(Etrk1sq);
+                        double Etrk2 = Math.sqrt(Etrk2sq);
+                        double p1dotp2 = (trkatconver1[1].x() * trkatconver2[1].x() + trkatconver1[1].y() * trkatconver2[1].y() + trkatconver1[1].z() * trkatconver2[1].z());
+                        aida.histogram1D("Invariant Mass").fill(Math.sqrt(2 * Etrk1 * Etrk2 - 2 * p1dotp2));
+                        if (qtrk1 == 1) {
+                            //       aida.histogram2D("Little Bump P+ vs. P-").fill(Math.sqrt((Math.pow((trk1.getPY()), 2) + Math.pow((trk1.getPX()), 2) + Math.pow((trk1.getPZ()), 2))), Math.sqrt((Math.pow((trk2.getPY()), 2) + Math.pow((trk2.getPX()), 2) + Math.pow((trk2.getPZ()), 2))));
+                        } else {
+                            //      aida.histogram2D("Little Bump P+ vs. P-").fill(Math.sqrt((Math.pow((trk2.getPY()), 2) + Math.pow((trk2.getPX()), 2) + Math.pow((trk2.getPZ()), 2))), Math.sqrt((Math.pow((trk1.getPY()), 2) + Math.pow((trk1.getPX()), 2) + Math.pow((trk1.getPZ()), 2))));
+                        }
+                        aida.histogram2D("X v Y - e+ Top").fill(C.get(0, 0), C.get(1, 0));
+                        aida.histogram2D("X v Z - e+ Top").fill(C.get(0, 0), C.get(2, 0));
+                        aida.histogram2D("Y v Z - e+ Top").fill(C.get(1, 0), C.get(2, 0));
+                    } else { //read Big bump as e- top
+//                        aida.histogram1D("Big Bump Track Momenta (Px)").fill(trk1.getPX());
+//                        aida.histogram1D("Big Bump Track Momenta (Py)").fill(trk1.getPY());
+//                        aida.histogram1D("Big Bump Track Momenta (Pz)").fill(trk1.getPZ());
+//                        aida.histogram1D("Big Bump Tracks Chi2").fill(trk1.getChi2());
+//                        aida.histogram1D("Big Bump Track Momenta (Px)").fill(trk2.getPX());
+//                        aida.histogram1D("Big Bump Track Momenta (Py)").fill(trk2.getPY());
+//                        aida.histogram1D("Big Bump Track Momenta (Pz)").fill(trk2.getPZ());
+//                        aida.histogram1D("Big Bump Tracks Chi2").fill(trk2.getChi2());
+//                        aida.histogram1D("Big Bump Sum of Track's Momentums").fill(Math.sqrt(Math.pow((trk1.getPY() + trk2.getPY()), 2) + Math.pow((trk1.getPX() + trk2.getPX()), 2) + Math.pow((trk1.getPZ() + trk2.getPZ()), 2)));
+                        double Etrk1sq = (Math.pow(trkatconver1[1].x(), 2) + Math.pow(trkatconver1[1].y(), 2) + Math.pow(trkatconver1[1].z(), 2));
+                        double Etrk2sq = (Math.pow(trkatconver2[1].x(), 2) + Math.pow(trkatconver2[1].y(), 2) + Math.pow(trkatconver2[1].z(), 2));
+                        double Etrk1 = Math.sqrt(Etrk1sq);
+                        double Etrk2 = Math.sqrt(Etrk2sq);
+                        double p1dotp2 = (trkatconver1[1].x() * trkatconver2[1].x() + trkatconver1[1].y() * trkatconver2[1].y() + trkatconver1[1].z() * trkatconver2[1].z());
+                        aida.histogram1D("Invariant Mass").fill(Math.sqrt(2 * Etrk1 * Etrk2 - 2 * p1dotp2));
+                        if (qtrk1 == 1) {
+                            //  aida.histogram2D("Big Bump P+ vs. P-").fill(Math.sqrt((Math.pow((trk1.getPY()), 2) + Math.pow((trk1.getPX()), 2) + Math.pow((trk1.getPZ()), 2))), Math.sqrt((Math.pow((trk2.getPY()), 2) + Math.pow((trk2.getPX()), 2) + Math.pow((trk2.getPZ()), 2))));
+                        } else {
+                            // aida.histogram2D("Big Bump P+ vs. P-").fill(Math.sqrt((Math.pow((trk2.getPY()), 2) + Math.pow((trk2.getPX()), 2) + Math.pow((trk2.getPZ()), 2))), Math.sqrt((Math.pow((trk1.getPY()), 2) + Math.pow((trk1.getPX()), 2) + Math.pow((trk1.getPZ()), 2))));
+                        }
+                        aida.histogram2D("X v Y - e- Top").fill(C.get(0, 0), C.get(1, 0));
+                        aida.histogram2D("X v Z - e- Top").fill(C.get(0, 0), C.get(2, 0));
+                        aida.histogram2D("Y v Z - e- Top").fill(C.get(1, 0), C.get(2, 0));
+                    }
+                }
+                boolean check4 = true;
+                if (my2 == 0) {
+                    check4 = false;
+                }
+
+//                aida.histogram1D("Track Distributions").fill(isTrk2Top + isTrk1Top);
+//                aida.histogram1D("Charge Distributions").fill(qtrk1 + qtrk2);
+
+
+                if ((isTrk2Top + isTrk1Top) == 0) {
+//                    aida.histogram1D("Split Track Momenta (Px)").fill(trk1.getPX());
+//                    aida.histogram1D("Split Track Momenta (Py)").fill(trk1.getPY());
+//                    aida.histogram1D("Split Track Momenta (Pz)").fill(trk1.getPZ());
+//                    aida.histogram1D("Split Tracks Chi2").fill(trk1.getChi2());
+//                    aida.histogram1D("Split Track Momenta (Px)").fill(trk2.getPX());
+//                    aida.histogram1D("Split Track Momenta (Py)").fill(trk2.getPY());
+//                    aida.histogram1D("Split Track Momenta (Pz)").fill(trk2.getPZ());
+//                    aida.histogram1D("Split Tracks Chi2").fill(trk2.getChi2());
+                    //     aida.histogram1D("Charge Distributions Split Tracks").fill(qtrk1 + qtrk2);
+                }
+
+                if ((isTrk2Top + isTrk1Top) == 2) {
+//                    aida.histogram1D("Top-Top Track Momenta (Px)").fill(trk1.getPX());
+//                    aida.histogram1D("Top-Top Track Momenta (Py)").fill(trk1.getPY());
+//                    aida.histogram1D("Top-Top Track Momenta (Pz)").fill(trk1.getPZ());
+//                    aida.histogram1D("Top-Top Tracks Chi2").fill(trk1.getChi2());
+//                    aida.histogram1D("Top-Top Track Momenta (Px)").fill(trk2.getPX());
+//                    aida.histogram1D("Top-Top Track Momenta (Py)").fill(trk2.getPY());
+//                    aida.histogram1D("Top-Top Track Momenta (Pz)").fill(trk2.getPZ());
+//                    aida.histogram1D("Top-Top Tracks Chi2").fill(trk2.getChi2());
+                    //     aida.histogram1D("Charge Distributions Non-Split Tracks").fill(qtrk1 + qtrk2);
+                }
+
+
+//                if ((qtrk1 + qtrk2) == 0) {
+//                    aida.histogram1D("Perpendicular Momentum").fill(Math.sqrt(Math.pow((trk1.getPY() + trk2.getPY()), 2) + Math.pow((trk1.getPZ() + trk2.getPZ()), 2)));
+//
+//                    if (qtrk1 == 1) {
+//                        aida.histogram2D("Py+ vs. Py-").fill(trk1.getPY(), trk2.getPY());
+//                        aida.histogram2D("Pz+ vs. Pz-").fill(trk1.getPZ(), trk2.getPZ());
+//                        aida.histogram2D("Total P+ vs. P-").fill(Math.sqrt((Math.pow((trk1.getPY()), 2) + Math.pow((trk1.getPX()), 2) + Math.pow((trk1.getPZ()), 2))), Math.sqrt((Math.pow((trk2.getPY()), 2) + Math.pow((trk2.getPX()), 2) + Math.pow((trk2.getPZ()), 2))));
+//
+//                    } else {
+//                        aida.histogram2D("Py+ vs. Py-").fill(trk2.getPY(), trk1.getPY());
+//                        aida.histogram2D("Pz+ vs. Pz-").fill(trk2.getPZ(), trk1.getPZ());
+//                        aida.histogram2D("Total P+ vs. P-").fill(Math.sqrt((Math.pow((trk2.getPY()), 2) + Math.pow((trk2.getPX()), 2) + Math.pow((trk2.getPZ()), 2))), Math.sqrt((Math.pow((trk1.getPY()), 2) + Math.pow((trk1.getPX()), 2) + Math.pow((trk1.getPZ()), 2))));
+//                    }
+//                }
+
+            }
+
+
+        }
+    }
+
+    @Override
+    public void reset() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    public void setOutputPlots(String output) {
+        this.outputPlots = output;
+    }
+
+    public void setShowPlots(boolean showem) {
+        this.showPlots = showem;
+    }
+
+    public void setOutputTextName(String output) {
+        this.outputTextName = output;
+    }
+
+    public void endOfData() {
+
+        pw.close();
+        try {
+            fw.close();
+        } catch (IOException ex) {
+            Logger.getLogger(TwoTrackAnalysis.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        System.out.println("Output");
+        if (outputPlots != null) {
+            try {
+                aida.saveAs(outputPlots);
+            } catch (IOException ex) {
+                Logger.getLogger(ElwinsTrackingRecon.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment
AlignmentParameters.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment/AlignmentParameters.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment/AlignmentParameters.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,559 @@
+package org.lcsim.hps.users.mgraham.alignment;
+
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.matrix.MatrixOp;
+import hep.physics.vec.BasicHep3Matrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Matrix;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.fit.helicaltrack.MultipleScatter;
+import org.lcsim.fit.helicaltrack.TrackDirection;
+import org.lcsim.hps.event.HPSTransformations;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+
+/**
+ * Class to calculate and print the residuals and derivatives
+ * of the alignment parameters...used as input for MillePede
+ * Notation follows the MillePede manual:
+ * http://www.desy.de/~blobel/Mptwo.pdf
+ *
+ * the track is measured in the HelicalTrackFit frame
+ * and residuals are in the sensor frame (u,v,w)
+ *
+ * ordering of track parameters is
+ *    double d0 = _trk.dca();
+ *    double z0 = _trk.z0();
+ *    double slope = _trk.slope();
+ *    double phi0 = _trk.phi0();
+ *    double R = _trk.R();
+ *
+ * @author mgraham
+ */
+public class AlignmentParameters {
+
+    private int _nlc = 5;  //the five track parameters
+    private int _ngl = 1; //delta(u) and delta(gamma) for each plane
+    private BasicMatrix _dfdq;
+    private BasicMatrix _dfdp;
+    private HelicalTrackFit _trk;
+    private double[] _resid = new double[3];
+    private double[] _error = new double[3];
+    private int[] _globalLabel = new int[1];
+    FileWriter fWriter;
+    PrintWriter pWriter;
+    Set<SiSensor> _process_sensors = new HashSet<SiSensor>();
+    boolean _DEBUG = false;
+    double smax = 1e3;
+
+    public AlignmentParameters(String outfile) {
+        try {
+//open things up
+            fWriter = new FileWriter(outfile);
+            pWriter = new PrintWriter(fWriter);
+        } catch (IOException ex) {
+            Logger.getLogger(RunAlignment.class.getName()).log(Level.SEVERE, null, ex);
+        }
+
+    }
+
+    public void PrintResidualsAndDerivatives(Track track) {
+        SeedTrack st = (SeedTrack) track;
+        SeedCandidate seed = st.getSeedCandidate();
+        Map<HelicalTrackHit, MultipleScatter> msmap = seed.getMSMap();
+        _trk = seed.getHelix();
+        List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+        for (TrackerHit hit : hitsOnTrack) {
+            HelicalTrackHit htc = (HelicalTrackHit) hit;
+            double msdrphi = msmap.get(htc).drphi();
+            double msdz = msmap.get(htc).dz();
+            double sHit = _trk.PathMap().get(htc);
+            HelicalTrackCross cross = (HelicalTrackCross) htc;
+            List<HelicalTrackStrip> clusterlist = cross.getStrips();
+            TrackDirection trkdir = HelixUtils.CalculateTrackDirection(_trk, sHit);
+            cross.setTrackDirection(trkdir, _trk.covariance());
+            for (HelicalTrackStrip cl : clusterlist) {
+                CalculateLocalDerivatives(cl);
+                CalculateGlobalDerivatives(cl);
+                CalculateResidual(cl, msdrphi, msdz);
+//                CalculateResidual(cl, 0,0);
+                PrintStripResiduals(cl);
+            }
+        }
+        AddTarget(0.1, 0.02);
+    }
+
+    private void CalculateLocalDerivatives(HelicalTrackStrip strip) {
+        //get track parameters.
+        double d0 = _trk.dca();
+        double z0 = _trk.z0();
+        double slope = _trk.slope();
+        double phi0 = _trk.phi0();
+        double R = _trk.R();
+//strip origin is defined in the tracking coordinate system (x=beamline)
+        double xint = strip.origin().x();
+        double s = HelixUtils.PathToXPlane(_trk, xint, smax, _nlc).get(0);
+        double phi = s / R - phi0;
+        double[][] dfdq = new double[3][5];
+        //dx/dq
+        //these are wrong for X, but for now it doesn't matter
+        dfdq[0][0] = Math.sin(phi0);
+        dfdq[0][1] = 0;
+        dfdq[0][2] = 0;
+        dfdq[0][3] = d0 * Math.cos(phi0) + R * Math.sin(phi0) - s * Math.cos(phi0);
+        dfdq[0][4] = (phi - phi0) * Math.cos(phi0);
+        double[] mydydq = dydq(R, d0, phi0, xint, s);
+        double[] mydzdq = dzdq(R, d0, phi0, xint, slope, s);
+        for (int i = 0; i < 5; i++) {
+            dfdq[1][i] = mydydq[i];
+            dfdq[2][i] = mydzdq[i];
+        }
+
+        BasicMatrix dfdqGlobal = FillMatrix(dfdq, 3, 5);
+        Hep3Matrix trkToStrip = getTrackToStripRotation(strip);
+        _dfdq = (BasicMatrix) MatrixOp.mult(trkToStrip, dfdqGlobal);
+
+        if (_DEBUG) {
+            double[] trackpars = {d0, z0, slope, phi0, R, s, xint};
+            System.out.println("Strip Origin: ");
+            System.out.println(strip.origin());
+            System.out.println("trkToStrip Rotation:");
+            System.out.println(trkToStrip.toString());
+            printDerivatives(trackpars, dfdq);
+        }
+    }
+
+    private void CalculateGlobalDerivatives(HelicalTrackStrip strip) {
+        //1st index = alignment parameter (only u so far)
+        //2nd index = residual coordinate (on du so far)
+
+        double[][] dfdpLab = new double[3][1];
+        dfdpLab[0][0] = 0; //df/dx
+        dfdpLab[1][0] = 0; //df/dy
+        dfdpLab[2][0] = 1; //df/dz
+        BasicMatrix _dfdpLab = FillMatrix(dfdpLab, 3, 1);
+        Hep3Matrix trkToStrip = getTrackToStripRotation(strip);
+        _dfdp = (BasicMatrix) MatrixOp.mult(trkToStrip, _dfdpLab);
+        if (_DEBUG) {
+            System.out.printf("dfdz = %5.5f     %5.5f   %5.5f\n", _dfdp.e(0, 0), _dfdp.e(1, 0), _dfdp.e(2, 0));
+        }
+        _globalLabel[0] = GetIdentifier(strip);
+//         _globalLabel[0] = GetIdentifierModule(strip);
+
+    }
+
+    private void CalculateResidual(HelicalTrackStrip strip, double msdrdphi, double msdz) {
+
+        Hep3Vector u = strip.u();
+        Hep3Vector v = strip.v();
+        Hep3Vector w = strip.w();
+        Hep3Vector corigin = strip.origin();
+        double phi0 = _trk.phi0();
+        double R = _trk.R();
+        double xint = strip.origin().x();
+        double s = HelixUtils.PathToXPlane(_trk, xint, smax, _nlc).get(0);
+        double phi = s / R - phi0;
+        Hep3Vector trkpos = HelixUtils.PointOnHelix(_trk, s);
+
+        //System.out.println("trkpos = "+trkpos.toString());
+        //System.out.println("origin = "+corigin.toString());
+
+        Hep3Vector mserr = new BasicHep3Vector(msdrdphi * Math.sin(phi), msdrdphi * Math.sin(phi), msdz);
+        Hep3Vector vdiffTrk = VecOp.sub(trkpos, corigin);
+        Hep3Matrix trkToStrip = getTrackToStripRotation(strip);
+        Hep3Vector vdiff = VecOp.mult(trkToStrip, vdiffTrk);
+        double umc = vdiff.x();
+        double vmc = vdiff.y();
+        double wmc = vdiff.z();
+        double umeas = strip.umeas();
+        double uError = strip.du();
+        double msuError = VecOp.dot(mserr, u);
+        double vmeas = 0;
+        double vError = (strip.vmax() - strip.vmin()) / Math.sqrt(12);
+        double wmeas = 0;
+        double wError = 0.001;
+        //System.out.println("strip error="+uError+"; ms error ="+msuError);
+        _resid[0] = umeas - umc;
+        _error[0] = Math.sqrt(uError * uError + msuError * msuError);
+        _resid[1] = vmeas - vmc;
+        _error[1] = vError;
+        _resid[2] = wmeas - wmc;
+        _error[2] = wError;
+        if (_DEBUG) {
+            System.out.println("Strip Origin: ");
+            System.out.println(corigin.toString());
+            System.out.println("Position on Track:");
+            System.out.println(trkpos.toString());
+            System.out.println("vdiff :");
+            System.out.println(vdiff.toString());
+            System.out.println("u :");
+            System.out.println(u.toString());
+            System.out.println("umeas = " + umeas + "; umc = " + umc);
+            System.out.println("udiff = " + _resid[0] + " +/- " + _error[0]);
+
+        }
+
+    }
+
+    public double[] getResidual(Track track, int layer) {
+        double[] res = new double[7];
+        SeedTrack st = (SeedTrack) track;
+        SeedCandidate seed = st.getSeedCandidate();
+        Map<HelicalTrackHit, MultipleScatter> msmap = seed.getMSMap();
+        _trk = seed.getHelix();
+        List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+        for (TrackerHit hit : hitsOnTrack) {
+            HelicalTrackHit htc = (HelicalTrackHit) hit;
+            double sHit = _trk.PathMap().get(htc);
+            HelicalTrackCross cross = (HelicalTrackCross) htc;
+            List<HelicalTrackStrip> clusterlist = cross.getStrips();
+            TrackDirection trkdir = HelixUtils.CalculateTrackDirection(_trk, sHit);
+            double msdrphi = msmap.get(htc).drphi();
+            double msdz = msmap.get(htc).dz();
+            cross.setTrackDirection(trkdir, _trk.covariance());
+            for (HelicalTrackStrip cl : clusterlist) {
+                if (cl.layer() == layer) {
+                    CalculateResidual(cl, msdrphi, msdz);
+                    res[0] = _resid[0];
+                    res[1] = _resid[1];
+                    res[2] = _resid[2];
+                    res[3] = _error[0];
+                    res[4] = _error[1];
+                    res[5] = _error[2];
+                    res[6] = layer;
+                    if(hit.getPosition()[2]<0)res[6]=layer+10;
+                }
+            }
+        }
+        return res;
+
+    }
+
+    public void AddTarget(double beamdy, double beamdz) {
+        double[][] dfdp = new double[3][1];
+        double d0 = _trk.dca();
+        double z0 = _trk.z0();
+        double slope = _trk.slope();
+        double phi0 = _trk.phi0();
+        double R = _trk.R();
+        double xint = 0; //target
+        double s = HelixUtils.PathToXPlane(_trk, xint, smax, _nlc).get(0);
+        Hep3Vector ptAtTarget = HelixUtils.PointOnHelix(_trk, s);
+        double[] mydydq = dydq(R, d0, phi0, xint, s);
+        double[] mydzdq = dzdq(R, d0, phi0, xint, slope, s);
+        _resid[0] = ptAtTarget.z();
+        _resid[1] = ptAtTarget.y();
+        _resid[2] = ptAtTarget.x();
+        _error[0] = beamdz;
+        _error[1] = beamdy;
+        _error[2] = 666;
+        dfdp[0][0] = 1;
+        dfdp[1][0] = 0;
+        dfdp[2][0] = 0;
+        _dfdp = FillMatrix(dfdp, 3, 1);
+        _globalLabel[0] = 666;
+        pWriter.printf("%4d\n", 666);
+        pWriter.printf("%5.5e %5.5e %5.5e\n", _resid[0], _resid[1], _resid[2]);
+        pWriter.printf("%5.5e %5.5e %5.5e\n", _error[0], _error[1], _error[2]);
+        for (int i = 0; i < _nlc; i++) {
+            pWriter.printf("%5.5e %5.5e -1.0\n", mydzdq[i], mydydq[i]);
+        }
+        for (int j = 0; j < _ngl; j++) {
+            pWriter.printf("%5.5e %5.5e %5.5e   %5d\n", _dfdp.e(0, j), _dfdp.e(1, j), _dfdp.e(2, j), _globalLabel[j]);
+        }
+
+    }
+
+    private void PrintStripResiduals(HelicalTrackStrip strip) {
+        if (_DEBUG) {
+            System.out.printf("Strip Layer =  %4d\n", strip.layer());
+            System.out.printf("Residuals (u,v,w) : %5.5e %5.5e %5.5e\n", _resid[0], _resid[1], _resid[2]);
+            System.out.printf("Errors (u,v,w)    : %5.5e %5.5e %5.5e\n", _error[0], _error[1], _error[2]);
+            String[] q = {"d0", "z0", "slope", "phi0", "R"};
+            System.out.println("track parameter derivatives");
+            for (int i = 0; i < _nlc; i++) {
+                System.out.printf("%s     %5.5e %5.5e %5.5e\n", q[i], _dfdq.e(0, i), _dfdq.e(1, i), _dfdq.e(2, i));
+            }
+            String[] p = {"u-displacement"};
+            System.out.println("global parameter derivatives");
+            for (int j = 0; j < _ngl; j++) {
+                System.out.printf("%s  %5.5e %5.5e %5.5e   %5d\n", p[j], _dfdp.e(0, j), _dfdp.e(1, j), _dfdp.e(2, j), _globalLabel[j]);
+            }
+
+        }
+        pWriter.printf("%4d\n", strip.layer());
+        pWriter.printf("%5.5e %5.5e %5.5e\n", _resid[0], _resid[1], _resid[2]);
+        pWriter.printf("%5.5e %5.5e %5.5e\n", _error[0], _error[1], _error[2]);
+        for (int i = 0; i < _nlc; i++) {
+            pWriter.printf("%5.5e %5.5e %5.5e\n", _dfdq.e(0, i), _dfdq.e(1, i), _dfdq.e(2, i));
+        }
+        for (int j = 0; j < _ngl; j++) {
+            pWriter.printf("%5.5e %5.5e %5.5e   %5d\n", _dfdp.e(0, j), _dfdp.e(1, j), _dfdp.e(2, j), _globalLabel[j]);
+        }
+    }
+
+    private Hep3Matrix getTrackToStripRotation(HelicalTrackStrip strip) {
+        ITransform3D detToStrip = GetGlobalToLocal(strip);
+        Hep3Matrix detToStripMatrix = (BasicHep3Matrix) detToStrip.getRotation().getRotationMatrix();
+        Hep3Matrix detToTrackMatrix = (BasicHep3Matrix) HPSTransformations.getMatrix();
+
+        if (_DEBUG) {
+            System.out.println("gblToLoc translation:");
+            System.out.println(detToStrip.getTranslation().toString());
+            System.out.println("gblToLoc Rotation:");
+            System.out.println(detToStrip.getRotation().toString());
+            System.out.println("detToTrack Rotation:");
+            System.out.println(detToTrackMatrix.toString());
+        }
+
+        return (Hep3Matrix) VecOp.mult(detToStripMatrix, VecOp.inverse(detToTrackMatrix));
+    }
+
+    private ITransform3D GetGlobalToLocal(HelicalTrackStrip strip) {
+        RawTrackerHit rth = (RawTrackerHit) strip.rawhits().get(0);
+        IDetectorElement ide = rth.getDetectorElement();
+        SiSensor sensor = ide.findDescendants(SiSensor.class).get(0);
+        SiSensorElectrodes electrodes = sensor.getReadoutElectrodes(ChargeCarrier.HOLE);
+        return electrodes.getGlobalToLocal();
+    }
+
+    private int GetIdentifier(HelicalTrackStrip strip) {
+        RawTrackerHit rth = (RawTrackerHit) strip.rawhits().get(0);
+        IDetectorElement ide = rth.getDetectorElement();
+        SiSensor sensor = ide.findDescendants(SiSensor.class).get(0);
+        //       return rth.getIdentifierFieldValue(sensor.getName());
+        return sensor.getSensorID();  //individual sensor positions
+//        int sid=sensor.getSensorID();
+//        int global=1;
+//        if(sid>10)global=2;
+//        return global;  //return top/bottom plates
+    }
+
+    private int GetIdentifierModule(HelicalTrackStrip strip) {
+        RawTrackerHit rth = (RawTrackerHit) strip.rawhits().get(0);
+        IDetectorElement ide = rth.getDetectorElement();
+        SiSensor sensor = ide.findDescendants(SiSensor.class).get(0);
+        //       return rth.getIdentifierFieldValue(sensor.getName());
+//        return sensor.getSensorID();  //individual sensor positions
+        int sid = sensor.getSensorID();
+        int gid = -1;
+        switch (sid) {
+            case 1:
+                gid = 1; break;
+            case 2:
+                gid = 1;break;
+            case 3:
+                gid = 2;break;
+            case 4:
+                gid = 2;break;
+            case 5:
+                gid = 3;break;
+            case 6:
+                gid = 3;break;
+            case 7:
+                gid = 4;break;
+            case 8:
+                gid = 4;break;
+            case 9:
+                gid = 5;break;
+            case 10:
+                gid = 5;break;
+            case 11:
+                gid = 11;break;
+            case 12:
+                gid = 11;break;
+            case 13:
+                gid = 12;break;
+            case 14:
+                gid = 12;break;
+            case 15:
+                gid = 13;break;
+            case 16:
+                gid = 13;break;
+            case 17:
+                gid = 14;break;
+            case 18:
+                gid = 14;break;
+            case 19:
+                gid = 15;break;
+            case 20:
+                gid = 15;break;
+        }
+
+        return gid;  //return top/bottom plates
+    }
+
+    private BasicMatrix FillMatrix(double[][] array, int nrow, int ncol) {
+        BasicMatrix retMat = new BasicMatrix(nrow, ncol);
+        for (int i = 0; i < nrow; i++) {
+            for (int j = 0; j < ncol; j++) {
+                retMat.setElement(i, j, array[i][j]);
+            }
+        }
+        return retMat;
+    }
+
+    public void closeFile() throws IOException {
+        pWriter.close();
+        fWriter.close();
+    }
+
+    private double dsdR(double R, double d0, double phi0, double xint) {
+        double sqrtTerm = Sqrt(R * R - Math.pow(((d0 - R) * Sin(phi0) + xint), 2));
+
+        double rsign = Math.signum(R);
+        double dsdr = (1 / sqrtTerm) * ((-rsign * xint) + (-rsign) * d0 * Sin(phi0)
+                + ArcTan(R * Cos(phi0), (-R) * Sin(phi0))
+                * sqrtTerm
+                - ArcTan(rsign * sqrtTerm, xint + (d0 - R) * Sin(phi0))
+                * sqrtTerm);
+
+
+        if (_DEBUG)
+            System.out.println("xint = " + xint + "; dsdr = " + dsdr);
+        return dsdr;
+
+    }
+
+    private double dsdphi(double R, double d0, double phi0, double xint) {
+        double sqrtTerm = Sqrt(R * R - Math.pow(((d0 - R) * Sin(phi0) + xint), 2));
+        double rsign = Math.signum(R);
+        double dsdphi = R * (sqrtTerm + rsign * d0 * Cos(phi0) - rsign * R * Cos(phi0)) / sqrtTerm;
+        if (_DEBUG)
+            System.out.println("xint = " + xint + "; dsdphi = " + dsdphi);
+        return dsdphi;
+    }
+
+    private double dsdd0(double R, double d0, double phi0, double xint) {
+        double sqrtTerm = Sqrt(R * R - Math.pow(((d0 - R) * Sin(phi0) + xint), 2));
+        double rsign = Math.signum(R);
+        double dsdd0 = rsign * (R * Sin(phi0)) / sqrtTerm;
+        if (_DEBUG)
+            System.out.println("xint = " + xint + "; dsdd0 = " + dsdd0);
+        return dsdd0;
+    }
+
+    private double[] dydq(double R, double d0, double phi0, double xint, double s) {
+        double[] dy = new double[5];
+//        dy[0] = Cos(phi0) + Cot(phi0 - s / R) * Csc(phi0 - s / R) * dsdd0(R, d0, phi0, xint);
+        dy[0] = Cos(phi0) - Sec(phi0 - s / R) * Tan(phi0 - s / R) * dsdd0(R, d0, phi0, xint);
+        dy[1] = 0;
+        dy[2] = 0;
+//        dy[3] = (-(d0 - R)) * Sin(phi0) - R * Cot(phi0 - s / R) * Csc(phi0 - s / R) * (1 - dsdphi(R, d0, phi0, xint) / R);
+        dy[3] = (-(d0 - R)) * Sin(phi0) + Sec(phi0 - s / R) * Tan(phi0 - s / R) * (R - dsdphi(R, d0, phi0, xint));
+        //        dy[4] = -Cos(phi0) + Csc(phi0 - s / R) - R * Cot(phi0 - s / R) * Csc(phi0 - s / R) * (s / (R * R) - dsdR(R, d0, phi0, xint) / R);
+        dy[4] = -Cos(phi0) + Sec(phi0 - s / R) + (1 / R) * Sec(phi0 - s / R) * Tan(phi0 - s / R) * (s - R * dsdR(R, d0, phi0, xint));
+        return dy;
+    }
+
+    private double[] dzdq(double R, double d0, double phi0, double xint, double slope, double s) {
+        double[] dz = new double[5];
+        dz[0] = slope * dsdd0(R, d0, phi0, xint);
+        dz[1] = 1;
+        dz[2] = s;
+        dz[3] = slope * dsdphi(R, d0, phi0, xint);
+        dz[4] = slope * dsdR(R, d0, phi0, xint);
+        return dz;
+    }
+
+    private double Csc(double val) {
+        return 1 / Math.sin(val);
+    }
+
+    private double Cot(double val) {
+        return 1 / Math.tan(val);
+    }
+
+    private double Sec(double val) {
+        return 1 / Math.cos(val);
+    }
+
+    private double Sin(double val) {
+        return Math.sin(val);
+    }
+
+    private double Cos(double val) {
+        return Math.cos(val);
+    }
+
+    private double Tan(double val) {
+        return Math.tan(val);
+    }
+
+    private double ArcTan(double val1, double val2) {
+        return Math.atan2(val1, val2);
+    }
+
+    private double Sign(double val) {
+        return Math.signum(val);
+    }
+
+    private double Sqrt(double val) {
+        return Math.sqrt(val);
+    }
+
+    private void printDerivatives(double[] trackpars, double[][] dfdq) {
+        System.out.println("======================================================");
+        System.out.println("s         xint");
+        System.out.printf("%5.5f %5.5f\n", trackpars[5], trackpars[6]);
+        System.out.println("             d0           z0           slope         phi0          R");
+        System.out.printf("Values       %5.5f    %5.5f     %5.5f      %5.5f      %5.5f\n", trackpars[0], trackpars[1], trackpars[2], trackpars[3], trackpars[4]);
+        System.out.printf("dzdq         ");
+        for (int i = 0; i < 5; i++) {
+            System.out.printf("%5.3e   ", dfdq[2][i]);
+        }
+        System.out.println();
+        System.out.printf("dudq         ");
+        for (int i = 0; i < _nlc; i++) {
+            System.out.printf("%5.3e   ", _dfdq.e(0, i));
+        }
+        System.out.println();
+        System.out.println();
+        System.out.printf("dydq         ");
+        for (int i = 0; i < 5; i++) {
+            System.out.printf("%5.3e   ", dfdq[1][i]);
+        }
+        System.out.println();
+        System.out.printf("dvdq         ");
+        for (int i = 0; i < _nlc; i++) {
+            System.out.printf("%5.3e   ", _dfdq.e(1, i));
+        }
+        System.out.println();
+        System.out.println();
+        System.out.printf("dxdq         ");
+        for (int i = 0; i < 5; i++) {
+            System.out.printf("%5.3e   ", dfdq[0][i]);
+        }
+        System.out.println();
+        System.out.printf("dwdq         ");
+        for (int i = 0; i < _nlc; i++) {
+            System.out.printf("%5.3e   ", _dfdq.e(2, i));
+        }
+        System.out.println();
+        //        System.out.println(        _trk.xc()+ "; "+_trk.yc());
+//          System.out.println(        _trk.x0()+ "; "+_trk.y0());
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment
HPSStrips.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment/HPSStrips.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment/HPSStrips.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,482 @@
+package org.lcsim.hps.users.mgraham.alignment;
+/*
+ * SiStrips.java
+ *
+ * Created on July 22, 2005, 4:07 PM
+ *
+ * To change this template, choose Tools | Options and locate the template under
+ * the Source Creation and Management node. Right-click the template and choose
+ * Open. You can then make changes to the template in the Source Editor.
+ */
+
+//import static org.lcsim.units.clhep.SystemOfUnits.*;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.Transform3D;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.VecOp;
+import java.util.ArrayList;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.List;
+import org.lcsim.detector.solids.GeomOp2D;
+import org.lcsim.detector.solids.GeomOp3D;
+import org.lcsim.detector.solids.Line3D;
+import org.lcsim.detector.solids.LineSegment3D;
+import org.lcsim.detector.solids.Point3D;
+import org.lcsim.detector.solids.Polygon3D;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.ChargeDistribution;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
+import org.lcsim.detector.tracker.silicon.SiStrips;
+
+/**
+ *
+ * @author tknelson
+ */
+public class HPSStrips  extends SiStrips
+{
+    
+    // Fields
+    
+    // Object definition
+    private ChargeCarrier _carrier; // charge carrier collected
+    private int _nstrips; // number of strips
+    private double _pitch; // sense pitch
+    private IDetectorElement _detector; // associated detector element
+    private ITransform3D _parent_to_local; // parent to local transform
+    private ITransform3D _local_to_global; // transformation to global coordinates
+    private ITransform3D _global_to_local; // transformation from global coordinates
+    private Polygon3D _geometry; // region in which strips are defined
+    private double _capacitance_intercept = 10.;  // fixed capacitance independent of strip length
+    private double _capacitance_slope = 0.1;  //  capacitance per unit length of strip
+    
+    // Cached for convenience
+    private double _strip_offset;
+    
+ 
+
+     public HPSStrips(ChargeCarrier carrier, double pitch, IDetectorElement detector, ITransform3D parent_to_local,ITransform3D misalignment)
+    {
+
+//        System.out.println("Plane of polygon in sensor coordinates has... ");
+//        System.out.println("                        normal: "+((SiSensor)detector).getBiasSurface(carrier).getNormal());
+//        System.out.println("                        distance: "+((SiSensor)detector).getBiasSurface(carrier).getDistance());
+
+        setCarrier(carrier);
+        setPitch(pitch);
+        setGeometry(((SiSensor)detector).getBiasSurface(carrier).transformed(parent_to_local));
+        setStripNumbering();
+        setDetectorElement(detector);
+        setParentToLocal(parent_to_local);
+        setGlobalToLocal(Transform3D.multiply(Transform3D.multiply(parent_to_local,detector.getGeometry().getGlobalToLocal()),misalignment));
+        setLocalToGlobal(getGlobalToLocal().inverse());
+    }
+
+    public HPSStrips(ChargeCarrier carrier, double pitch, int nstrips, IDetectorElement detector, ITransform3D parent_to_local,ITransform3D misalignment)
+    {
+        setCarrier(carrier);
+        setPitch(pitch);
+        setGeometry(((SiSensor)detector).getBiasSurface(carrier).transformed(parent_to_local));
+        setNStrips(nstrips);
+        setDetectorElement(detector);
+        setParentToLocal(parent_to_local);
+        setGlobalToLocal(Transform3D.multiply(Transform3D.multiply(parent_to_local,detector.getGeometry().getGlobalToLocal()),misalignment));
+        setLocalToGlobal(getGlobalToLocal().inverse());
+    }
+    
+
+    // SiSensorElectrodes interface
+    //=============================
+
+    // Mechanical properties
+    public int getNAxes()
+    {
+        return 1;
+    }
+
+    public IDetectorElement getDetectorElement()
+    {
+        return _detector;
+    }
+
+    public ITransform3D getParentToLocal()
+    {
+        return _parent_to_local;
+    }
+
+    public ITransform3D getLocalToGlobal()
+    {
+        return _local_to_global;
+    }
+
+    public ITransform3D getGlobalToLocal()
+    {
+        return _global_to_local;
+    }
+
+    public Polygon3D getGeometry()
+    {
+        return _geometry;
+    }
+
+    public Hep3Vector getMeasuredCoordinate(int axis)
+    {
+        if (axis == 0) return new BasicHep3Vector(1.0,0.0,0.0);
+        else return null;
+    }
+
+    public Hep3Vector getUnmeasuredCoordinate(int axis)
+    {
+        if (axis == 0) return new BasicHep3Vector(0.0,1.0,0.0);
+        else return null;
+    }
+
+    public int getNeighborCell(int cell, int ncells_0, int ncells_1)
+    {
+        int neighbor_cell = cell + ncells_0;
+        if (isValidCell(neighbor_cell)) return neighbor_cell;
+        else return -1;
+    }
+
+    public Set<Integer> getNearestNeighborCells(int cell)
+    {
+        Set<Integer> neighbors = new HashSet<Integer>();
+        for (int ineigh = -1 ; ineigh <= 1; ineigh=ineigh+2)
+        {
+            int neighbor_cell = getNeighborCell(cell,ineigh,0);
+            if (isValidCell(neighbor_cell)) neighbors.add(neighbor_cell);
+        }
+        return neighbors;
+    }
+
+    public boolean isValidCell(int cell)
+    {
+        return (cell >= 0 && cell < getNCells());
+    }
+
+    public int getNCells()
+    {
+        return _nstrips;
+    }
+
+    public int getNCells(int axis)
+    {
+        if (axis == 0)
+        {
+            return _nstrips;
+        }
+        else return 1;
+    }
+
+    public double getPitch(int axis)
+    {
+        if (axis == 0)
+        {
+            return _pitch;
+        }
+        else return 0;
+    }
+    public int getCellID(Hep3Vector position)
+    {
+        return (int)Math.round((position.x()+_strip_offset)/_pitch);
+    }
+
+
+    public int getRowNumber(Hep3Vector position)
+    {
+        return 0;
+    }
+
+    public int getColumnNumber(Hep3Vector position)
+    {
+        return getCellID(position);
+    }
+
+    public int getCellID(int row_number, int column_number)
+    {
+        return column_number;
+    }
+
+    public int getRowNumber(int cell_id)
+    {
+        return 0;
+    }
+
+    public int getColumnNumber(int cell_id)
+    {
+        return cell_id;
+    }
+
+    public Hep3Vector getPositionInCell(Hep3Vector position)
+    {
+        return VecOp.sub(position,getCellPosition(getCellID(position)));
+    }
+
+    public Hep3Vector getCellPosition(int strip_number)
+    {
+        return new BasicHep3Vector(strip_number*_pitch-_strip_offset,0.0,0.0);
+    }
+
+    // Electrical properties
+
+    /**
+     * Capacitance intercept parameter.  Units are pF.
+     *
+     * Capacitance is calculated as:
+     * C = capacitance_intercept + strip_length * capacitance slope
+     *
+     * @param capacitance_intercept
+     */
+    public void setCapacitanceIntercept(double capacitance_intercept) {
+        _capacitance_intercept = capacitance_intercept;
+    }
+
+    /**
+     * Capacitance per unit strip length.  Units are pF / mm.
+     *
+     * @param capacitance_slope
+     */
+    public void setCapacitanceSlope(double capacitance_slope) {
+        _capacitance_slope = capacitance_slope;
+    }
+
+    public ChargeCarrier getChargeCarrier()
+    {
+        return _carrier;
+    }
+
+    /**
+     * Capacitance for a particular cell.  Units are pF.
+     *
+     * @param cell_id
+     * @return
+     */
+    public double getCapacitance(int cell_id) // capacitance in pF
+    {
+        return _capacitance_intercept + _capacitance_slope*getStripLength(cell_id);
+    }
+
+    /**
+     * Nominal capacitance used for throwing random noise in the sensor.
+     * Calculated using middle strip.  Units are pF.
+     *
+     * @return
+     */
+    public double getCapacitance() {
+        return getCapacitance(getNCells(0) / 2);
+    }
+
+    public SortedMap<Integer,Integer> computeElectrodeData(ChargeDistribution distribution)
+    {
+        SortedMap<Integer,Integer> electrode_data = new TreeMap<Integer,Integer>();
+
+        int base_strip = getCellID(distribution.getMean());
+
+        // put charge on strips in window 3-sigma strips on each side of base strip
+        int axis = 0;
+        int window_size = (int)Math.ceil(3.0*distribution.sigma1D(getMeasuredCoordinate(axis))/getPitch(axis));
+
+        double integral_lower = distribution.getNormalization();
+        double integral_upper = distribution.getNormalization();
+
+        for (int istrip = base_strip-window_size; istrip <= base_strip+window_size; istrip++)
+        {
+            double cell_edge_upper = getCellPosition(istrip).x() + getPitch(axis)/2.0;
+
+//            System.out.println("cell_edge_upper: "+cell_edge_upper);
+
+            double integration_limit = cell_edge_upper;        //cell_edge_upper-distribution.mean().x();
+
+//            System.out.println("integration_limit: "+integration_limit);
+
+            integral_upper = distribution.upperIntegral1D(getMeasuredCoordinate(axis),integration_limit);
+
+//            System.out.println("integral_upper: "+integral_upper);
+
+            if (integral_lower<integral_upper)
+            {
+                throw new RuntimeException("Error in integrating Gaussian charge distribution!");
+            }
+
+            int strip_charge = (int)Math.round(integral_lower-integral_upper);
+
+//            System.out.println("strip_charge: "+strip_charge);
+
+            if (strip_charge != 0)
+            {
+                electrode_data.put(istrip,strip_charge);
+            }
+
+            integral_lower = integral_upper;
+        }
+
+        return electrode_data;
+
+    }
+
+    // Strip specific methods
+
+    // length of strip
+    public double getStripLength(int cell_id)
+    {
+//        System.out.println("strip_length: "+getStrip(cell_id).getLength());
+        return getStrip(cell_id).getLength();
+    }
+
+    // center of strip
+    public Hep3Vector getStripCenter(int cell_id)
+    {
+        LineSegment3D strip = getStrip(cell_id);
+        return strip.getEndPoint(strip.getLength()/2);
+    }
+
+    // line segment for strip
+    public LineSegment3D getStrip(int cell_id)
+    {
+        Line3D strip_line = new Line3D(new Point3D(getCellPosition(cell_id)),getUnmeasuredCoordinate(0));
+
+//        System.out.println("Number of strips: "+this._nstrips);
+//        System.out.println("Strip offset: "+this._strip_offset);
+//        System.out.println("Pitch: "+this._pitch);
+//        System.out.println("cell_id: "+cell_id);
+//        System.out.println("strip_line start point: "+strip_line.getStartPoint());
+//        System.out.println("strip_line direction: "+strip_line.getDirection());
+
+        List<Point3D> intersections = new ArrayList<Point3D>();
+
+        // Get intersections between strip line and edges of electrode polygon
+        for (LineSegment3D edge : _geometry.getEdges())
+        {
+//            System.out.println("edge start point: "+edge.getStartPoint());
+//            System.out.println("edge end point: "+edge.getEndPoint());
+
+            if (GeomOp2D.intersects(strip_line,edge))
+            {
+                intersections.add(GeomOp3D.lineBetween(strip_line,edge).getStartPoint());
+            }
+        }
+
+        // Check for rare occurrence of duplicates (can happen at corners of polygon)
+        List<Point3D> strip_ends = new ArrayList<Point3D>(intersections);
+        if (intersections.size() > 2)
+        {
+            for (int ipoint1 = 0; ipoint1 < intersections.size(); ipoint1++)
+            {
+                Point3D point1 = intersections.get(ipoint1);
+                for (int ipoint2 = ipoint1+1; ipoint2 < intersections.size(); ipoint2++)
+                {
+                    Point3D point2 = intersections.get(ipoint2);
+                    if (GeomOp3D.intersects(point1,point2))
+                    {
+                        strip_ends.remove(point2);
+                        if (strip_ends.size() == 2) break;
+                    }
+                }
+            }
+        }
+
+        return new LineSegment3D(strip_ends.get(0),strip_ends.get(1));
+    }
+
+    // Private setters
+    //==================
+    public void setCarrier(ChargeCarrier carrier)
+    {
+        _carrier = carrier;
+    }
+
+    public void setGeometry(Polygon3D geometry)
+    {
+//        System.out.println("Plane of polygon has... ");
+//        System.out.println("                        normal: "+geometry.getNormal());
+//        System.out.println("                        distance: "+geometry.getDistance());
+//
+//        System.out.println("Working plane has... ");
+//        System.out.println("                        normal: "+GeomOp2D.PLANE.getNormal());
+//        System.out.println("                        distance: "+GeomOp2D.PLANE.getDistance());
+
+        if (GeomOp3D.equals(geometry.getPlane(),GeomOp2D.PLANE))
+        {
+            _geometry = geometry;
+        }
+        else
+        {
+            throw new RuntimeException("Electrode geometry must be defined in x-y plane!!");
+        }
+    }
+
+    private void setStripNumbering()
+    {
+        double xmin = Double.MAX_VALUE;
+        double xmax = Double.MIN_VALUE;
+        for (Point3D vertex : _geometry.getVertices())
+        {
+            xmin = Math.min(xmin,vertex.x());
+            xmax = Math.max(xmax,vertex.x());
+        }
+
+//        System.out.println("xmin: " + xmin);
+//        System.out.println("xmax: " + xmax);
+//
+//
+//        System.out.println("# strips: " +   (int)Math.ceil((xmax-xmin)/getPitch(0)) ) ;
+
+        setNStrips(  (int)Math.ceil((xmax-xmin)/getPitch(0)) ) ;
+    }
+
+    private void setNStrips(int nstrips)
+    {
+        _nstrips = nstrips;
+        setStripOffset();
+//        _strip_offset = (_nstrips-1)*_pitch/2.;
+    }
+
+    private void setStripOffset()
+    {
+        double xmin = Double.MAX_VALUE;
+        double xmax = Double.MIN_VALUE;
+        for (Point3D vertex : _geometry.getVertices())
+        {
+            xmin = Math.min(xmin,vertex.x());
+            xmax = Math.max(xmax,vertex.x());
+        }
+
+        double strips_center = (xmin+xmax)/2;
+
+        _strip_offset = ((_nstrips-1)*_pitch)/2 - strips_center;
+
+    }
+
+    private void setPitch(double pitch)
+    {
+        _pitch = pitch;
+    }
+
+    private void setDetectorElement(IDetectorElement detector)
+    {
+        _detector = detector;
+    }
+
+    private void setParentToLocal(ITransform3D parent_to_local)
+    {
+        _parent_to_local = parent_to_local;
+    }
+
+    private void setLocalToGlobal(ITransform3D local_to_global)
+    {
+        _local_to_global = local_to_global;
+    }
+
+    private void setGlobalToLocal(ITransform3D global_to_local)
+    {
+        _global_to_local = global_to_local;
+    }
+    
+}
+
+

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment
RunAlignment.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment/RunAlignment.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment/RunAlignment.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,97 @@
+package org.lcsim.hps.users.mgraham.alignment;
+
+import hep.aida.IAnalysisFactory;
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author mgraham
+ */
+public class RunAlignment extends Driver {
+
+    private AIDA aida = AIDA.defaultInstance();
+    String[] detNames = {"Tracker"};
+    Integer _minLayers = 8;
+    Integer[] nlayers = {8};
+    int nevt = 0;
+    double[] beamsize = {0.001, 0.02, 0.02};
+    String _config = "1pt8";
+    AlignmentParameters ap;
+    int totalTracks=0;
+// flipSign is a kludge...
+//  HelicalTrackFitter doesn't deal with B-fields in -ive Z correctly
+//  so we set the B-field in +iveZ and flip signs of fitted tracks
+//  note:  this should be -1 for Test configurations and +1 for Full (v3.X and lower) configurations
+//  this is set by the _config variable (detType in HeavyPhotonDriver)
+    int flipSign = 1;
+
+    public RunAlignment(int trackerLayers, int mintrkLayers, String config) {
+        nlayers[0] = trackerLayers;
+        _minLayers = mintrkLayers;
+        _config = config;
+        if (_config.contains("Test"))
+            flipSign = -1;
+        ap = new AlignmentParameters("/Users/mgraham/HPS/align.txt");
+
+    }
+
+    public void process(
+            EventHeader event) {
+
+
+        //  Create a map between tracks and the associated MCParticle
+        List<Track> tracklist = event.get(Track.class, "MatchedTracks");
+//        System.out.println("Number of Tracks = " + tracklist.size());
+        double duRange=0.1;
+         for (Track trk : tracklist) {
+            totalTracks++;
+            ap.PrintResidualsAndDerivatives(trk);
+
+            if(1==1){
+                aida.histogram1D("Track d0",50,-0.5,0.5).fill(trk.getTrackParameter(0));
+                aida.histogram1D("Track sin(phi0)",50,-0.5,0.5).fill(Math.sin(trk.getTrackParameter(1)));
+                aida.histogram1D("Track z0",50,-0.1,0.1).fill(Math.sin(trk.getTrackParameter(3)));
+                aida.histogram1D("Track chi^2",50,0,25).fill(trk.getChi2());
+                for (int i = 1; i < 11; i++) {
+                double[] res = ap.getResidual(trk, i);
+                int mylayer=(int)res[6];
+                if(mylayer<11){
+                     aida.histogram1D("Track chi^2 Positive Side",50,0,25).fill(trk.getChi2());
+                }else{
+                     aida.histogram1D("Track chi^2 Negative Side",50,0,25).fill(trk.getChi2());
+                }
+
+                aida.histogram1D("deltaU -- Layer " + mylayer,50,-duRange,duRange).fill(res[0]);
+                aida.histogram1D("deltaU Pull-- Layer " + mylayer,50,-3,3).fill(res[0]/res[3]);
+                if(i==3&&Math.sin(trk.getTrackParameter(1))>0){
+                    aida.histogram1D("Positive phi0  deltaU -- Layer " + mylayer,50,-duRange,duRange).fill(res[0]);
+                aida.histogram1D("Positive phi0 deltaU Pull-- Layer " + mylayer,50,-3,3).fill(res[0]/res[3]);
+                }
+                if(i==3&&Math.sin(trk.getTrackParameter(1))<0){
+                    aida.histogram1D("Negative phi0  deltaU -- Layer " + mylayer,50,-duRange,duRange).fill(res[0]);
+                aida.histogram1D("Negative phi0 deltaU Pull-- Layer " + mylayer,50,-3,3).fill(res[0]/res[3]);
+                }
+ 
+             }
+            }
+ }
+
+    }
+
+    public void endOfData() {
+        try {
+            System.out.println("Total Number of Tracks Found = "+totalTracks);
+            ap.closeFile();
+        } catch (IOException ex) {
+            Logger.getLogger(RunAlignment.class.getName()).log(Level.SEVERE, null, ex);
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment
SiTrackerSpectrometerSensorSetup.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment/SiTrackerSpectrometerSensorSetup.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/alignment/SiTrackerSpectrometerSensorSetup.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,265 @@
+package org.lcsim.hps.users.mgraham.alignment;
+
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.util.List;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IRotation3D;
+import org.lcsim.detector.ITranslation3D;
+import org.lcsim.detector.RotationPassiveXYZ;
+import org.lcsim.detector.Transform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.solids.Polygon3D;
+import org.lcsim.detector.solids.Trd;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.compact.Subdetector;
+import org.lcsim.geometry.subdetector.SiTrackerSpectrometer;
+import org.lcsim.util.Driver;
+
+public class SiTrackerSpectrometerSensorSetup extends Driver {
+
+    String subdetectorName;
+
+    public SiTrackerSpectrometerSensorSetup() {
+    }
+
+    public SiTrackerSpectrometerSensorSetup(String subdetectorName) {
+        this.subdetectorName = subdetectorName;
+    }
+
+    public void setSubdetectorName(String subdetectorName) {
+        this.subdetectorName = subdetectorName;
+    }
+
+    public void detectorChanged(Detector detector) {
+        if (subdetectorName == null) {
+            throw new RuntimeException("The subdetectorName was not set.");
+        }
+
+        Subdetector subdetector = detector.getSubdetector(subdetectorName);
+        if (subdetector instanceof SiTrackerSpectrometer) {
+            setupSensorDetectorElements(subdetector);
+        } else {
+            throw new RuntimeException("The subdetector " + subdetectorName + " is not an instance of SiTrackerSpectrometer.");
+        }
+    }
+
+    private void setupSensorDetectorElements(Subdetector subdet) {
+        System.out.println(this.getClass().getCanonicalName() + " - Setting up sensors for " + subdet.getName() + " ...");
+        int sensorId = 0;
+
+        for (IDetectorElement endcap : subdet.getDetectorElement().getChildren()) {
+            for (IDetectorElement layer : endcap.getChildren()) {
+                //int nwedges = layer.getChildren().size();
+                for (IDetectorElement wedge : layer.getChildren()) {
+                    for (IDetectorElement module : wedge.getChildren()) {
+                        List<SiSensor> sensors = module.findDescendants(SiSensor.class);
+
+                        if (sensors.size() == 0) {
+                            throw new RuntimeException("No sensors found in module.");
+                        }
+
+                        for (SiSensor sensor : sensors) {
+                            Trd sensor_solid = (Trd) sensor.getGeometry().getLogicalVolume().getSolid();
+
+                            Polygon3D n_side = sensor_solid.getFacesNormalTo(new BasicHep3Vector(0, -1, 0)).get(0);
+                            Polygon3D p_side = sensor_solid.getFacesNormalTo(new BasicHep3Vector(0, 1, 0)).get(0);
+
+                            // Bias the sensor
+//                            sensor.setBiasSurface(ChargeCarrier.ELECTRON, p_side);
+//                            sensor.setBiasSurface(ChargeCarrier.HOLE, n_side);
+
+                            sensor.setBiasSurface(ChargeCarrier.HOLE, p_side);
+                            sensor.setBiasSurface(ChargeCarrier.ELECTRON, n_side);
+
+//                            double strip_angle = Math.atan2(sensor_solid.getXHalfLength2() - sensor_solid.getXHalfLength1(), sensor_solid.getZHalfLength() * 2);
+                            double strip_angle = 0.00;
+                            ITranslation3D electrodes_position = new Translation3D(VecOp.mult(-p_side.getDistance(), new BasicHep3Vector(0, 0, 1)));  // translate to outside of polygon
+                            //ITranslation3D electrodes_position = new Translation3D(VecOp.mult(n_side.getDistance(), new BasicHep3Vector(0, 0, 1)));  // translate to outside of polygon
+                            // System.out.println("SensorID = " + sensorId + "  " + electrodes_position.toString());
+                            IRotation3D electrodes_rotation = new RotationPassiveXYZ(-Math.PI / 2, 0, strip_angle);
+                            Transform3D electrodes_transform = new Transform3D(electrodes_position, electrodes_rotation);
+
+                            // Free calculation of readout electrodes, sense electrodes determined thereon
+//                            SiStrips readout_electrodes = new SiStrips(ChargeCarrier.HOLE, 0.060, sensor, electrodes_transform);
+//                            SiStrips sense_electrodes = new SiStrips(ChargeCarrier.HOLE,0.030,(readout_electrodes.getNCells()*2-1),sensor,electrodes_transform);
+                            ITranslation3D misalign_position;
+//                            System.out.println(layer.getName());
+//                            if (layer.getName().contains("3")) {
+//                            if (layer.getName().contains("3")&&layer.getName().contains("positive")) {
+/*
+                            if (layer.getName().contains("positive")) {
+                            System.out.println("Putting in a misalignment for layer "+layer.getName());
+                            misalign_position = new Translation3D(0, 0.05, 0.0);  // translate to outside of polygon
+                            } else {
+                            //                                misalign_position = new Translation3D(0, 0.0, 0.0);
+                            misalign_position = new Translation3D(0, -0.05, 0.0);
+                            }
+                             */
+
+//                            if ((layer.getName().contains("3")||layer.getName().contains("4"))&&layer.getName().contains("positive")) {
+                            //                            if (layer.getName().contains("positive")) {
+//                            System.out.println("Putting in a misalignment for layer "+layer.getName());
+//                            misalign_position = new Translation3D(0, 0.010, 0.0);
+//                            } else {
+//                            misalign_position = new Translation3D(0, 0.0, 0.0);
+                            //                                 misalign_position = new Translation3D(0, -0.05, 0.0);
+//                            }
+/*
+                            if (layer.getName().contains("positive")) {
+                            int gid = GetIdentifierModule(layer.getName());
+                            misalign_position = new Translation3D(0, 0.0, 0.0);
+                            if (gid == 1)
+                            misalign_position = new Translation3D(0, -0.0144, 0.0);
+                            if (gid == 2)
+                            misalign_position = new Translation3D(0, 0.05-0.0297, 0.0);
+                            if (gid == 3)
+                            misalign_position = new Translation3D(0, -0.0253, 0.0);
+                            if (gid == 4)
+                            misalign_position = new Translation3D(0, -0.0346, 0.0);
+                            if (gid == 5)
+                            misalign_position = new Translation3D(0, -0.0433, 0.0);
+
+                            } else {
+                            misalign_position = new Translation3D(0, 0.0, 0.0);
+                            }
+                             */
+
+                             int gid = GetIdentifierLayer(layer.getName());
+                              misalign_position = new Translation3D(0, 0.0, 0.0);
+                              /*
+                            if (layer.getName().contains("positive")) {                                                              
+                                if (gid == 1)
+                                    misalign_position = new Translation3D(0, -0.00144, 0.0);
+                                if (gid == 2)
+                                    misalign_position = new Translation3D(0, 0.005, 0.0);
+                                if (gid == 3)
+                                    misalign_position = new Translation3D(0, -0.00253, 0.0);
+                                if (gid == 4)
+                                    misalign_position = new Translation3D(0, -0.00346, 0.0);
+                                if (gid == 5)
+                                    misalign_position = new Translation3D(0, 0.00433, 0.0);
+                                 if (gid == 6)
+                                    misalign_position = new Translation3D(0, 0.0002, 0.0);
+                                if (gid == 7)
+                                    misalign_position = new Translation3D(0, 0.002, 0.0);
+                                 if (gid == 8)
+                                    misalign_position = new Translation3D(0, -0.004, 0.0);
+                                if (gid == 9)
+                                    misalign_position = new Translation3D(0, 0.006, 0.0);
+                                 if (gid == 10)
+                                    misalign_position = new Translation3D(0, -0.001, 0.0);
+                            } else {
+                                  if (gid == 1)
+                                    misalign_position = new Translation3D(0, 0.00, 0.0);
+                                if (gid == 2)
+                                    misalign_position = new Translation3D(0, 0.00, 0.0);
+                                if (gid == 3)
+                                    misalign_position = new Translation3D(0, 0.00, 0.0);
+                                if (gid == 4)
+                                    misalign_position = new Translation3D(0, 0.00, 0.0);
+                                if (gid == 5)
+                                    misalign_position = new Translation3D(0, 0.00, 0.0);
+                                 if (gid == 6)
+                                    misalign_position = new Translation3D(0, 0.00, 0.0);
+                                if (gid == 7)
+                                    misalign_position = new Translation3D(0, 0.00, 0.0);
+                                 if (gid == 8)
+                                    misalign_position = new Translation3D(0, 0.00, 0.0);
+                                if (gid == 9)
+                                    misalign_position = new Translation3D(0, 0.00, 0.0);
+                                 if (gid == 10)
+                                    misalign_position = new Translation3D(0, 0.01, 0.0);
+                            }
+
+*/
+                            IRotation3D misalign_rotation = new RotationPassiveXYZ(0, 0, 0);
+                            Transform3D misalign_transform = new Transform3D(misalign_position, misalign_rotation);
+
+                            HPSStrips readout_electrodes = new HPSStrips(ChargeCarrier.HOLE, 0.060, sensor, electrodes_transform, misalign_transform);
+                            HPSStrips sense_electrodes = new HPSStrips(ChargeCarrier.HOLE, 0.030, (readout_electrodes.getNCells() * 2 - 1), sensor, electrodes_transform, misalign_transform);
+
+
+//                            SiStrips readout_electrodes = new SiStrips(ChargeCarrier.ELECTRON, 0.060, sensor, electrodes_transform);
+//                           SiStrips sense_electrodes = new SiStrips(ChargeCarrier.ELECTRON, 0.030, (readout_electrodes.getNCells() * 2 - 1), sensor, electrodes_transform);
+
+                            //                            SiSensorElectrodes sense_electrodes = new SiStrips(ChargeCarrier.HOLE, 0.060, sensor, electrodes_transform);
+
+//pristine conditions
+/*
+                            readout_electrodes.setCapacitanceIntercept(0);
+                            readout_electrodes.setCapacitanceSlope(0.12);
+                            sense_electrodes.setCapacitanceIntercept(0);
+                            sense_electrodes.setCapacitanceSlope(0.12);
+                             */
+
+                            readout_electrodes.setCapacitanceIntercept(0);
+                            readout_electrodes.setCapacitanceSlope(0.16);
+                            sense_electrodes.setCapacitanceIntercept(0);
+                            sense_electrodes.setCapacitanceSlope(0.16);
+
+                            sensor.setSenseElectrodes(sense_electrodes);
+                            sensor.setReadoutElectrodes(readout_electrodes);
+//
+
+//                            double[][] transfer_efficiencies = {{1.0}};
+                            double[][] transfer_efficiencies = {{0.986, 0.419}};
+                            sensor.setTransferEfficiencies(ChargeCarrier.HOLE, new BasicMatrix(transfer_efficiencies));
+//                            sensor.setTransferEfficiencies(ChargeCarrier.ELECTRON, new BasicMatrix(transfer_efficiencies));
+                            // here
+
+                            sensor.setSensorID(++sensorId);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private int GetIdentifierModule(String mylayer) {
+        int gid = -1;
+        if (mylayer.contains("1") || mylayer.contains("2"))
+            gid = 1;
+        if (mylayer.contains("3") || mylayer.contains("4"))
+            gid = 2;
+        if (mylayer.contains("5") || mylayer.contains("6"))
+            gid = 3;
+        if (mylayer.contains("7") || mylayer.contains("8"))
+            gid = 4;
+        if (mylayer.contains("9") || mylayer.contains("10"))
+            gid = 5;
+
+        return gid;  //return top/bottom plates
+    }
+
+    private int GetIdentifierLayer(String mylayer) {
+        int gid = -1;
+        if (mylayer.contains("1"))
+            gid = 1;
+        if (mylayer.contains("2"))
+            gid = 2;
+        if (mylayer.contains("3"))
+            gid = 3;
+        if (mylayer.contains("4"))
+            gid = 4;
+        if (mylayer.contains("5"))
+            gid = 5;
+        if (mylayer.contains("6"))
+            gid = 6;
+        if (mylayer.contains("7"))
+            gid = 7;
+        if (mylayer.contains("8"))
+            gid = 8;
+        if (mylayer.contains("9"))
+            gid = 9;
+        if (mylayer.contains("10"))
+            gid = 10;
+
+        return gid;  //return top/bottom plates
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/jlabrotation
DetailedAnalysisDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/jlabrotation/DetailedAnalysisDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/mgraham/jlabrotation/DetailedAnalysisDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,1523 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.mgraham.jlabrotation;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import hep.aida.*;
+
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.vec.VecOp;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Set;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCRelation;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.Track;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.fit.helicaltrack.HelixParamCalculator;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.fit.helicaltrack.TrackDirection;
+import org.lcsim.hps.recon.vertexing.BilliorTrack;
+import org.lcsim.hps.recon.vertexing.BilliorVertex;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.hps.recon.tracking.FindableTrack;
+import org.lcsim.hps.recon.tracking.TrackAnalysis;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+
+ @author partridge
+ */
+public class DetailedAnalysisDriver extends Driver {
+
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    private IProfile1D phifake;
+    private IProfile1D pfake;
+    private IProfile1D cthfake;
+    private IProfile1D peffFindable;
+    private IProfile1D thetaeffFindable;
+    private IProfile1D phieffFindable;
+    private IProfile1D ctheffFindable;
+    private IProfile1D d0effFindable;
+    private IProfile1D z0effFindable;
+    private IProfile1D peffElectrons;
+    private IProfile1D thetaeffElectrons;
+    private IProfile1D phieffElectrons;
+    private IProfile1D ctheffElectrons;
+    private IProfile1D d0effElectrons;
+    private IProfile1D z0effElectrons;
+    private IProfile1D peffAxial;
+    private IProfile1D thetaeffAxial;
+    private IProfile1D phieffAxial;
+    private IProfile1D ctheffAxial;
+    private IProfile1D d0effAxial;
+    private IProfile1D z0effAxial;
+    private IHistogram1D fakes;
+    private IHistogram1D nfakes;
+    private IProfile1D HitEffdEdX;
+    private IProfile1D ClHitEffdEdX;
+    private IProfile1D ClHitEffY;
+    private IProfile1D ClHitEffZ;
+    private IProfile1D STdEdXY;
+    private IProfile1D STdEdXZ;
+    private IProfile1D frdEdXY;
+    private IProfile1D VxEff;
+    private IProfile1D VyEff;
+    private IProfile1D VzEff;
+    private IProfile1D VxEffFindable;
+    private IProfile1D VyEffFindable;
+    private IProfile1D VzEffFindable;
+    public String outputPlots = "myplots.aida";
+    Map<String, IProfile1D> clsizeMap = new HashMap<String, IProfile1D>();
+    String[] detNames = {"Tracker"};
+    Integer[] nlayers = {8};
+    int trk_count = 0;
+    int nevt = 0;
+    int _nmcTrk = 0;
+    double _nrecTrk = 0;
+    double phiTrkCut = 0.3;
+    double cosThTrkCutMax = 0.2;
+    double cosThTrkCutMin = 0.05;
+    double pTrkCut = 0.5; //GeV
+    double d0TrkCut = 2.0; //mm
+    double z0TrkCut = 2.0; //mm
+    double etaTrkCut = 2.5;
+    int totelectrons = 0;
+    double foundelectrons = 0;
+    int findableelectrons = 0;
+    int findableTracks = 0;
+    double foundTracks = 0;
+    double beamP = 2.2;
+    public String outputTextName = "myevents.txt";
+    FileWriter fw;
+    PrintWriter pw;
+    double[] beamsize = {0.001, 0.02, 0.02};
+
+    public DetailedAnalysisDriver(int layers) {
+        nlayers[0] = layers;
+
+        //  Define the efficiency histograms
+        IHistogramFactory hf = aida.histogramFactory();
+
+
+        peffFindable = hf.createProfile1D("Findable Efficiency vs p", "", 20, 0., beamP);
+        thetaeffFindable = hf.createProfile1D("Findable Efficiency vs theta", "", 20, 80, 100);
+        phieffFindable = hf.createProfile1D("Findable Efficiency vs phi", "", 25, -0.25, 0.25);
+        ctheffFindable = hf.createProfile1D("Findable Efficiency vs cos(theta)", "", 25, -0.25, 0.25);
+        d0effFindable = hf.createProfile1D("Findable Efficiency vs d0", "", 50, -2., 2.);
+        z0effFindable = hf.createProfile1D("Findable Efficiency vs z0", "", 50, -2., 2.);
+
+        peffElectrons = hf.createProfile1D("Electrons Efficiency vs p", "", 20, 0., beamP);
+        thetaeffElectrons = hf.createProfile1D("Electrons Efficiency vs theta", "", 20, 80, 100);
+        phieffElectrons = hf.createProfile1D("Electrons Efficiency vs phi", "", 25, -0.25, 0.25);
+        ctheffElectrons = hf.createProfile1D("Electrons Efficiency vs cos(theta)", "", 25, -0.25, 0.25);
+        d0effElectrons = hf.createProfile1D("Electrons Efficiency vs d0", "", 20, -1., 1.);
+        z0effElectrons = hf.createProfile1D("Electrons Efficiency vs z0", "", 20, -1., 1.);
+
+        peffAxial = hf.createProfile1D("Axial Efficiency vs p", "", 20, 0., beamP);
+        thetaeffAxial = hf.createProfile1D("Axial Efficiency vs theta", "", 20, 80, 100);
+        phieffAxial = hf.createProfile1D("Axial Efficiency vs phi", "", 25, -0.25, 0.25);
+        ctheffAxial = hf.createProfile1D("Axial Efficiency vs cos(theta)", "", 25, -0.25, 0.25);
+        d0effAxial = hf.createProfile1D("Axial Efficiency vs d0", "", 20, -1., 1.);
+        z0effAxial = hf.createProfile1D("Axial Efficiency vs z0", "", 20, -1., 1.);
+
+        cthfake = hf.createProfile1D("Fake rate vs  cos(theta)", "", 25, -0.25, 0.25);
+        phifake = hf.createProfile1D("Fake rate vs phi", "", 25, -0.25, 0.25);
+        pfake = hf.createProfile1D("Fake rate vs p", "", 20, 0, 6);
+
+        fakes = hf.createHistogram1D("Number of mis-matched hits (unnormalized)", "", 10, 0., 10.);
+        nfakes = hf.createHistogram1D("Number of mis-matched hits (normalized)", "", 10, 0., 10.);
+
+        HitEffdEdX = hf.createProfile1D("Strip Hit Efficiency vs dEdX", "", 50, 0, 0.3);
+        ClHitEffdEdX = hf.createProfile1D("Cluster Hit Efficiency vs dEdX", "", 50, 0, 0.3);
+        ClHitEffY = hf.createProfile1D("Cluster Hit Efficiency vs y", "", 50, -100, 100);
+        ClHitEffZ = hf.createProfile1D("Cluster Hit Efficiency vs z", "", 50, -100, 100);
+        STdEdXY = hf.createProfile1D("SimTHit dEdX vs y", "", 50, -100, 100);
+        frdEdXY = hf.createProfile1D("fractional dEdX vs y", "", 50, -100, 100);
+        STdEdXZ = hf.createProfile1D("SimTHit dEdX vs z", "", 50, -100, 100);
+
+        VxEff = hf.createProfile1D("Aprime Efficiency vs Vx", "", 25, 0., 50.);
+        VyEff = hf.createProfile1D("Aprime Efficiency vs Vy", "", 40, -0.2, 0.2);
+        VzEff = hf.createProfile1D("Aprime Efficiency vs Vz", "", 40, -0.2, 0.2);
+
+        VxEffFindable = hf.createProfile1D("Aprime Efficiency vs Vx: Findable", "", 25, 0., 50.);
+        VyEffFindable = hf.createProfile1D("Aprime Efficiency vs Vy: Findable", "", 40, -0.2, 0.2);
+        VzEffFindable = hf.createProfile1D("Aprime Efficiency vs Vz: Findable", "", 40, -0.2, 0.2);
+
+        int i, j;
+        for (i = 0; i < 1; i++)
+            for (j = 0; j < nlayers[i]; j++) {
+                int laynum = j + 1;
+                String profname = detNames[i] + "_layer" + laynum + " cluster size vs y";
+                String key = detNames[i] + "_layer" + laynum;
+                clsizeMap.put(key, hf.createProfile1D(profname, 20, -15, 15));
+            }
+    }
+
+    @Override
+    public void process(
+            EventHeader event) {
+        if (nevt == 0)
+            try {
+//open things up
+                fw = new FileWriter(outputTextName);
+                pw = new PrintWriter(fw);
+            } catch (IOException ex) {
+                Logger.getLogger(DetailedAnalysisDriver.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        //  Increment the event counter
+        nevt++;
+        String resDir = "residualsPlots/";
+        String resDirBar = "residualsBarrelPlots/";
+        String resDirEC = "residualsEndcapPlots/";
+        String simDir = "STHitPlots/";
+        String debugDir = "debugPlots/";
+        String occDir = "occupancyPlots/";
+        //  Get the magnetic field
+        Hep3Vector IP = new BasicHep3Vector(0., 0., 0.1);
+//        double bfield = event.getDetector().getFieldMap().getField(IP).y();
+        double bfield = 0.5;
+
+        List<RawTrackerHit> rawHits = event.get(RawTrackerHit.class, "RawTrackerHitMaker_RawTrackerHits");
+        List<SiTrackerHitStrip1D> stripHits = event.get(SiTrackerHitStrip1D.class, "StripClusterer_SiTrackerHitStrip1D");
+        // dump SThit information
+        String[] input_hit_collections = {"TrackerHits"};
+        for (String input : input_hit_collections) {
+            List<SimTrackerHit> sthits = event.getSimTrackerHits(input);
+            int[] nhits = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+            for (SimTrackerHit st : sthits) {
+                String detector = st.getDetectorElement().getName();
+                int layer = st.getLayerNumber();
+                double[] hp = st.getPoint();
+                Hep3Vector hitPos = new BasicHep3Vector(hp[0], hp[1], hp[2]);
+                double r = Math.sqrt(hp[0] * hp[0] + hp[1] * hp[1]);
+                double theta = Math.atan2(r, hp[2]);
+                double eta = -Math.log(Math.tan(theta / 2));
+                double phi = Math.atan2(hp[1], hp[0]);
+                nhits[layer]++;
+                double hitwgt = 0;
+                double clhitwgt = 0;
+                for (RawTrackerHit rth : rawHits) {
+                    List<SimTrackerHit> SthFromRth = rth.getSimTrackerHits();
+                    if (SthFromRth.contains(st))
+                        hitwgt = 1.0;
+                }
+                for (SiTrackerHitStrip1D cluster : stripHits) {
+                    double measdedx = cluster.getdEdx() * 1000.0;
+
+                    List<RawTrackerHit> RthFromSith = cluster.getRawHits();
+
+                    for (RawTrackerHit rth : RthFromSith) {
+                        List<SimTrackerHit> SthFromRth = rth.getSimTrackerHits();
+                        if (SthFromRth.contains(st)) {
+                            clhitwgt = 1.0;
+                            double totdedx = 0;
+                            for (SimTrackerHit sthtemp : SthFromRth)
+                                totdedx = totdedx + sthtemp.getdEdx() * 1000.0;
+                            aida.histogram1D(simDir + "delta dEdX", 50, -0.2, 0.2).fill(measdedx - totdedx);
+                            aida.histogram1D(simDir + "fractional dEdX", 50, -1, 1.).fill((measdedx - totdedx) / totdedx);
+                            aida.cloud1D(simDir + "fractional dEdX Cloud").fill((measdedx - totdedx) / totdedx);
+                            //          if (Math.abs((measdedx - dedx) / dedx) < 1)
+                            frdEdXY.fill(hp[1], (measdedx - totdedx) / totdedx);
+                            //          if (dedx == 0)
+                            //              System.out.println("*****************         dedx==0    ********");
+                        }
+                    }
+                }
+                //HitEffdEdX.fill(dedx, hitwgt);
+                //ClHitEffdEdX.fill(dedx, clhitwgt);
+                ClHitEffY.fill(hp[1], clhitwgt);
+                ClHitEffZ.fill(hp[2], clhitwgt);
+                //STdEdXY.fill(hp[1], dedx);
+                //STdEdXZ.fill(hp[2], dedx);
+                //aida.histogram1D(simDir + " dedx", 50, 0, 0.3).fill(dedx);
+//                if (hitwgt == 0) {
+//                    System.out.println("TrackAnalysis:  found an inefficiency hit:  " + dedx);
+//                }
+
+                //aida.cloud1D(simDir + input + " layer " + layer + " STHit p").fill(mom);
+                aida.cloud1D(simDir + input + " layer " + layer + " STHit y").fill(hp[1]);
+                aida.cloud1D(simDir + input + " layer " + layer + " STHit z").fill(hp[2]);
+                aida.cloud2D(simDir + input + " layer " + layer + " STHit y vs z").fill(hp[2], hp[1]);
+                aida.histogram2D(simDir + input + " layer " + layer + " STHit y vs z occupancy", 100, -15, 15, 500, -15, 15).fill(hp[2], hp[1]);
+
+            }
+            int i = 0;
+            while (i < nlayers[0]) {
+                if (nhits[i] > 0)
+                    aida.cloud1D(simDir + input + "layer " + i + " number of ST hits").fill(nhits[i]);
+                i++;
+            }
+        }
+
+
+//        List<HelicalTrackHit> hthits = event.get(HelicalTrackHit.class, "MatchedHTHits");
+        List<HelicalTrackHit> toththits = event.get(HelicalTrackHit.class, "HelicalTrackHits");
+        if (event.hasCollection(HelicalTrackHit.class, "AxialTrackHits")) {
+            List<HelicalTrackHit> axialhits = event.get(HelicalTrackHit.class, "AxialTrackHits");
+            int nAxialHitsTotal = axialhits.size();
+            int nL1Hits = 0;
+            for (HelicalTrackHit hth : axialhits)
+                if (hth.Layer() == 1)
+                    nL1Hits++;
+        }
+        Map<String, Integer> occupancyMap = new HashMap<String, Integer>();
+        for (RawTrackerHit rh : rawHits) {
+            IDetectorElement rhDetE = rh.getDetectorElement();
+
+            String rhDetName = rhDetE.getName();
+            int rhLayer = rh.getLayerNumber();
+
+            for (String myname : detNames)
+                if (rhDetName.contains(myname)) {
+                    String detlayer = myname + "_" + rhLayer;
+                    Integer myint = occupancyMap.get(detlayer);
+                    if (myint == null)
+                        myint = 1;
+                    myint++;
+                    occupancyMap.put(detlayer, myint);
+                }
+        }
+        Set<String> mykeyset = (Set<String>) occupancyMap.keySet();
+        for (String keys : mykeyset)
+            aida.cloud1D(occDir + keys + " # of hits").fill(occupancyMap.get(keys));
+
+        for (SiTrackerHitStrip1D stripCluster : stripHits) {
+            Hep3Vector strCluPos = stripCluster.getPositionAsVector();
+            double yHit = strCluPos.y();
+            Set<MCParticle> mcparts = stripCluster.getMCParticles();
+            aida.cloud1D(occDir + "associated MC Particles").fill(mcparts.size());
+            List<RawTrackerHit> rthList = stripCluster.getRawHits();
+            int nhits = rthList.size();
+            String detlayer = "Foobar";
+            for (RawTrackerHit rth : rthList) {
+                IDetectorElement rhDetE = rth.getDetectorElement();
+                String rhDetName = rhDetE.getName();
+                int rhLayer = rth.getLayerNumber();
+                for (String myname : detNames)
+                    if (rhDetName.contains(myname))
+                        detlayer = myname + "_layer" + rhLayer;
+            }
+            clsizeMap.get(detlayer).fill(yHit, nhits);
+            aida.cloud1D(occDir + detlayer + "associated MC Particles").fill(mcparts.size());
+            aida.cloud1D(occDir + detlayer + " cluster size").fill(nhits);
+        }
+
+        //  Create a relational table that maps TrackerHits to MCParticles
+        RelationalTable hittomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+//        List<LCRelation> mcrelations = event.get(LCRelation.class, "HelicalTrackMCRelations");
+        List<LCRelation> mcrelations = event.get(LCRelation.class, "RotatedMCRelations");
+
+        for (LCRelation relation : mcrelations)
+            if (relation != null && relation.getFrom() != null && relation.getTo() != null)
+                hittomc.add(relation.getFrom(), relation.getTo());
+
+        RelationalTable hittomcAxial = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        if (event.hasCollection(Track.class, "AxialTracks")) {
+//        List<LCRelation> mcrelations = event.get(LCRelation.class, "HelicalTrackMCRelations");
+            List<LCRelation> mcrelationsAxial = event.get(LCRelation.class, "AxialTrackMCRelations");
+            for (LCRelation relation : mcrelationsAxial)
+                if (relation != null && relation.getFrom() != null && relation.getTo() != null)
+                    hittomcAxial.add(relation.getFrom(), relation.getTo());
+        }
+        //  Instantiate the class that determines if a track is "findable"
+        FindableTrack findable = new FindableTrack(event);
+
+        //  Create a map between tracks and the associated MCParticle
+        List<Track> tracklist = event.get(Track.class, "MatchedTracks");
+        RelationalTable trktomcAxial = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        if (event.hasCollection(Track.class, "AxialTracks")) {
+            List<Track> axialtracklist = event.get(Track.class, "AxialTracks");
+            aida.cloud1D("Axial Tracks per Event").fill(axialtracklist.size());
+            String atrackdir = "TrackInfoAxial/";
+            for (Track atrack : axialtracklist) {
+                double apx = atrack.getPX();
+                aida.cloud1D(atrackdir + "pX").fill(apx);
+                TrackAnalysis tkanal = new TrackAnalysis(atrack, hittomcAxial);
+                MCParticle mcp = tkanal.getMCParticle();
+                if (mcp != null)
+                    //  Create a map between the tracks found and the assigned MC particle
+                    trktomcAxial.add(atrack, tkanal.getMCParticle());
+            }
+
+        }
+        aida.cloud1D("Matched Tracks per Event").fill(tracklist.size());
+
+        aida.cloud1D("HelicalTrackHits per Event").fill(toththits.size());
+        RelationalTable trktomc = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        int _nchRec = 0;
+        int _neleRec = 0;
+        int _nposRec = 0;
+        int _neleTru = 0;
+        int _nposTru = 0;
+        int _neleFake = 0;
+        int _nposFake = 0;
+
+        RelationalTable mcHittomcP = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+        //  Get the collections of SimTrackerHits
+        List<List<SimTrackerHit>> simcols = event.get(SimTrackerHit.class);
+
+        //  Loop over the SimTrackerHits and fill in the relational table
+        for (List<SimTrackerHit> simlist : simcols)
+            for (SimTrackerHit simhit : simlist)
+                if (simhit.getMCParticle() != null)
+                    mcHittomcP.add(simhit, simhit.getMCParticle());
+
+        Map<Track, TrackAnalysis> tkanalMap = new HashMap<Track, TrackAnalysis>();
+        RelationalTable nearestHitToTrack = new BaseRelationalTable(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        Map<Track, Double> l1Isolation = new HashMap<Track, Double>();
+        Map<Track, Double> l1DeltaZ = new HashMap<Track, Double>();
+        Map<Track, BilliorTrack> btMap = new HashMap<Track, BilliorTrack>();
+
+        //  Analyze the tracks in the event
+
+        String trackdir = "TrackInfo/";
+        //  Analyze the tracks in the event
+        for (Track track : tracklist) {
+            //  Calculate the track pT and cos(theta)
+            double d0 = track.getTrackParameter(HelicalTrackFit.dcaIndex);
+            double z0 = track.getTrackParameter(HelicalTrackFit.z0Index);
+            double phi0 = track.getTrackParameter(HelicalTrackFit.phi0Index);
+            double slope = track.getTrackParameter(HelicalTrackFit.slopeIndex);
+            double curve = track.getTrackParameter(HelicalTrackFit.curvatureIndex);
+            double d0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.dcaIndex, HelicalTrackFit.dcaIndex));
+            double z0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.z0Index, HelicalTrackFit.z0Index));
+            double phi0Err = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.phi0Index, HelicalTrackFit.phi0Index));
+            double slopeErr = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.slopeIndex, HelicalTrackFit.slopeIndex));
+            double curveErr = Math.sqrt(track.getErrorMatrix().e(HelicalTrackFit.curvatureIndex, HelicalTrackFit.curvatureIndex));
+            _nchRec++;
+            if (track.getCharge() < 0)
+                _neleRec++;
+            if (track.getCharge() > 0)
+                _nposRec++;
+
+            SeedTrack stEle = (SeedTrack) track;
+            SeedCandidate seedEle = stEle.getSeedCandidate();
+            HelicalTrackFit ht = seedEle.getHelix();
+            TrackAnalysis tkanal = new TrackAnalysis(track, hittomc);
+
+            tkanalMap.put(track, tkanal);
+            BilliorTrack bt = new BilliorTrack(ht);
+
+            btMap.put(track, bt);
+            double xoca = ht.x0();
+            double yoca = ht.y0();
+            double[] poca = {xoca, yoca, z0};
+            double mom[] = track.getMomentum();
+            double px = mom[0];
+            double py = mom[1];
+            double pz = mom[2];
+            double pperp = Math.sqrt(py * py + pz * pz);
+            double pt = Math.sqrt(px * px + py * py);
+            double p = Math.sqrt(pt * pt + pz * pz);
+            double phi = Math.atan2(py, px);
+            double cth = pz / Math.sqrt(pt * pt + pz * pz);
+            double sth = pt / Math.sqrt(pt * pt + pz * pz);
+            double th = Math.atan2(pt, pz);
+            double eta = -Math.log(Math.tan(th / 2));
+
+
+
+            double s = HelixUtils.PathLength(ht, (HelicalTrackHit) track.getTrackerHits().get(0));
+            double y1 = HelixUtils.PointOnHelix(ht, s).y();
+            double z1 = HelixUtils.PointOnHelix(ht, s).z();
+
+            int nhits = tkanal.getNHitsNew();
+            double purity = tkanal.getPurityNew();
+            int nbad = tkanal.getNBadHitsNew();
+            int nbadAxial = tkanal.getNBadAxialHits();
+            int nbadZ = tkanal.getNBadZHits();
+            int nAxial = tkanal.getNAxialHits();
+            int nZ = tkanal.getNZHits();
+            List<Integer> badLayers = tkanal.getBadHitList();
+            Integer badLayerEle = encodeBadHitList(badLayers);
+            if (badLayers.size() > 0) {
+                System.out.println(badLayers.toString());
+                System.out.println("Bad Layer code:  " + badLayerEle);
+            }
+            aida.cloud1D(trackdir + "Mis-matched hits for all tracks").fill(nbad);
+            aida.cloud1D(trackdir + "purityNew for all tracks").fill(purity);
+            aida.cloud1D(trackdir + "Bad Axial hits for all tracks").fill(nbadAxial);
+            aida.cloud1D(trackdir + "Bad Z hits for all tracks").fill(nbadZ);
+            aida.cloud1D(trackdir + "Number of Axial hits for all tracks").fill(nAxial);
+            aida.cloud1D(trackdir + "Number of Z hits for all tracks").fill(nZ);
+
+            for (Integer bhit : badLayers)
+                aida.histogram1D(trackdir + "Layer of Bad Hit", nlayers[0], 1, nlayers[0] + 1).fill(bhit);
+
+            //  Generate a normalized histogram after 1000 events
+            trk_count++;
+            if (nevt <= 1000)
+                fakes.fill(nbad);
+
+            //  Make plots for fake, non-fake, and all tracks
+            if (purity < 0.5) {
+                if (track.getCharge() < 0)
+                    _neleFake++;
+                if (track.getCharge() > 0)
+                    _nposFake++;
+                cthfake.fill(cth, 1.0);
+                phifake.fill(phi, 1.0);
+                pfake.fill(p, 1.0);
+
+                fillTrackInfo(trackdir, "fake tracks", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, d0, xoca, yoca, z0);
+
+            } else {
+                if (track.getCharge() < 0)
+                    _neleTru++;
+                if (track.getCharge() > 0)
+                    _nposTru++;
+                cthfake.fill(cth, 0.0);
+                phifake.fill(phi, 0.0);
+                pfake.fill(p, 0.0);
+
+                fillTrackInfo(trackdir, "non-fake tracks", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, d0, xoca, yoca, z0);
+
+
+
+            }
+            fillTrackInfo(trackdir, "all tracks", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, d0, xoca, yoca, z0);
+            if (nbadZ == 3)
+                fillTrackInfo(trackdir, "3 Bad Z-hits", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, d0, xoca, yoca, z0);
+
+
+            //  Now analyze MC Particles on this track
+            MCParticle mcp = tkanal.getMCParticle();
+            if (mcp != null) {
+
+                //  Create a map between the tracks found and the assigned MC particle
+                trktomc.add(track, tkanal.getMCParticle());
+
+                //  Calculate the MC momentum and polar angle
+                Hep3Vector Pmc = mcp.getMomentum();
+                double pxmc = Pmc.x();
+                double pymc = Pmc.y();
+                double pzmc = Pmc.z();
+                double ptmc = Math.sqrt(pxmc * pxmc + pymc * pymc);
+                double pmc = Math.sqrt(ptmc * ptmc + pzmc * pzmc);
+                double pxtk = track.getPX();
+                double pytk = track.getPY();
+                double pztk = track.getPZ();
+                double pttk = Math.sqrt(pxtk * pxtk + pytk * pytk);
+                double ptk = Math.sqrt(pttk * pttk + pztk * pztk);
+
+                //  Calculate the helix parameters for this MC particle and pulls in pT, d0
+                HelixParamCalculator helix = new HelixParamCalculator(mcp, bfield);
+                double d0mc = helix.getDCA();
+                double z0mc = helix.getZ0();
+                double phi0mc = helix.getPhi0();
+                double slopemc = helix.getSlopeSZPlane();
+                double curvemc = 1 / helix.getRadius();
+                double pinvresid = (1 / ptk - 1 / pmc);
+                double presid = (ptk - pmc);
+                double z0newMC = z0mc;
+                double y0newMC = d0mc;
+                aida.histogram1D(trackdir + "d0 Pull", 200, -8, 8).fill((d0 - d0mc) / d0Err);
+                aida.histogram1D(trackdir + "z0 Pull", 200, -8, 8).fill((z0 - z0mc) / z0Err);
+                aida.histogram1D(trackdir + "phi0 Pull", 200, -8, 8).fill((phi0 - phi0mc) / phi0Err);
+                aida.histogram1D(trackdir + "slope Pull", 200, -8, 8).fill((slope - slopemc) / slopeErr);
+                aida.histogram1D(trackdir + "curvature Pull", 200, -8, 8).fill((curve - curvemc) / curveErr);
+
+
+
+
+                BasicHep3Vector axial = new BasicHep3Vector();
+//                axial.setV(0, 1, 0);
+                axial.setV(1, 0, 0);
+                String hitdir = "HitsOnTrack/";
+                List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+                MCParticle bestmcp = tkanal.getMCParticleNew();
+
+                String tkresid = "TrackResiduals/";
+
+                int ndaug = 0;
+                if (bestmcp != null)
+                    ndaug = bestmcp.getDaughters().size();
+
+                double mcmom = 0;
+                double prevmom = 0;
+                double mytotchi2 = 0;
+
+                for (TrackerHit hit : hitsOnTrack) {
+
+                    int iplane = 0;
+                    HelicalTrackHit htc = (HelicalTrackHit) hit;
+                    List<MCParticle> mcpsHTH = htc.getMCParticles();
+                    int isbad = 0;
+                    if (mcpsHTH.isEmpty() || mcpsHTH.size() > 1 || !mcpsHTH.contains(bestmcp))
+                        isbad = 1;
+                    double sHit = ht.PathMap().get(htc);
+                    Hep3Vector posonhelix = HelixUtils.PointOnHelix(ht, sHit);
+                    double yTr = posonhelix.y();
+                    double zTr = posonhelix.z();
+                    HelicalTrackCross cross = (HelicalTrackCross) htc;
+                    List<HelicalTrackStrip> clusterlist = cross.getStrips();
+                    TrackDirection trkdir = HelixUtils.CalculateTrackDirection(ht, sHit);
+                    cross.setTrackDirection(trkdir, ht.covariance());
+                    double y = cross.y();
+                    double z = cross.z();
+                    double yerr = Math.sqrt(cross.getCorrectedCovMatrix().e(1, 1));
+                    double zerr = Math.sqrt(cross.getCorrectedCovMatrix().e(2, 2));
+
+                    mytotchi2 += Math.pow((y - yTr) / yerr, 2);
+                    mytotchi2 += Math.pow((z - zTr) / zerr, 2);
+
+                    int htlayer = htc.Layer();
+                    if (htlayer == 1)
+                        l1DeltaZ.put(track, z - zTr);
+
+                    if (purity == 1 && track.getCharge() > 0 && nhits == 10) {
+                        if (clusterlist.get(0).rawhits().size() == 1 && clusterlist.get(1).rawhits().size() == 1) {
+                            aida.cloud1D(hitdir + tkresid + "SingleStrip--Track delta y:  Layer " + htlayer).fill(y - yTr);
+                            aida.cloud1D(hitdir + tkresid + "SingleStrip--Track delta z:  Layer " + htlayer).fill(z - zTr);
+                        }
+                        aida.cloud1D(hitdir + tkresid + " Measured y:  Layer " + htlayer).fill(y);
+                        aida.cloud1D(hitdir + tkresid + " Track y:  Layer " + htlayer).fill(yTr);
+                        aida.cloud1D(hitdir + tkresid + " Measured z:  Layer " + htlayer).fill(z);
+                        aida.cloud1D(hitdir + tkresid + " Track z:  Layer " + htlayer).fill(zTr);
+                        aida.cloud1D(hitdir + tkresid + " Measured y ").fill(y);
+                        aida.cloud1D(hitdir + tkresid + " Track delta y:  Layer " + htlayer + "; ndaug=" + ndaug).fill(y - yTr);
+                        aida.cloud1D(hitdir + tkresid + " Track delta z:  Layer " + htlayer + "; ndaug=" + ndaug).fill(z - zTr);
+                        aida.cloud2D(hitdir + tkresid + " Track deltay vs delta z:  Layer " + htlayer).fill(z - zTr, y - yTr);
+                        if (htlayer == 1) {
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltay vs xoca").fill(poca[0], y - yTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltay vs yoca").fill(poca[1], y - yTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltay vs zoca").fill(poca[2], y - yTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltaz vs xoca").fill(poca[0], z - zTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltaz vs yoca").fill(poca[1], z - zTr);
+                            aida.cloud2D(hitdir + tkresid + " Layer 1 deltaz vs zoca").fill(poca[2], z - zTr);
+                        }
+                        aida.cloud2D(hitdir + tkresid + " Track vs measured y:  Layer " + htlayer).fill(y, yTr);
+                        aida.cloud2D(hitdir + tkresid + " Track vs measured z:  Layer " + htlayer).fill(z, zTr);
+                        aida.cloud2D(hitdir + tkresid + " Track deltay vs S ").fill(sHit, y - yTr);
+                        aida.cloud2D(hitdir + tkresid + " Track deltaz vs S ").fill(sHit, z - zTr);
+                        aida.histogram1D(hitdir + tkresid + " Track pull y:  Layer " + htlayer, 200, -8, 8).fill((y - yTr) / yerr);
+                        aida.histogram1D(hitdir + tkresid + " Track pull z:  Layer " + htlayer, 200, -8, 8).fill((z - zTr) / zerr);
+                        aida.histogram2D(hitdir + tkresid + " Track pull y vs p:  Layer " + htlayer, 200, -8, 8, 200, 0, 5).fill((y - yTr) / yerr, pmc);
+                        aida.histogram2D(hitdir + tkresid + " Track pull z vs p:  Layer " + htlayer, 200, -8, 8, 200, 0, 5).fill((z - zTr) / zerr, pmc);
+
+
+                    }
+                    for (HelicalTrackStrip cl : clusterlist) {
+                        int ilayer = 0;
+                        List<MCParticle> mcps = cl.MCParticles();
+
+                        Hep3Vector corigin = cl.origin();
+                        Hep3Vector u = cl.u();
+                        double umeas = cl.umeas();
+                        Hep3Vector uvec = VecOp.mult(umeas, u);
+                        Hep3Vector clvec = VecOp.add(corigin, uvec);
+                        int layer = cl.layer();
+                        HelicalTrackStrip nearest = getNearestHit(cl, toththits);
+                        if (layer == 1) {
+                            Double l1Dist = getNearestDistance(cl, toththits);
+                            if (l1Dist != null)
+                                l1Isolation.put(track, l1Dist);
+                        }
+                        if (nearest != null)
+                            nearestHitToTrack.add(track, nearest);
+
+                        int badCl = 0;
+                        if (mcps.isEmpty() || mcps.size() > 1 || !mcps.contains(bestmcp))
+                            badCl = 1;
+                        if (badCl == 1)
+                            if (mcps.size() > 0 && mcps.get(0) != null) {
+                                MCParticle tmpmc = mcps.get(0);
+                                aida.cloud1D(hitdir + layer + " Momentum of bad hit ").fill(tmpmc.getMomentum().magnitude());
+                                aida.cloud1D(hitdir + layer + " PDGID of bad hit ").fill(tmpmc.getPDGID());
+                                for (MCParticle mymc : tmpmc.getParents())
+                                    aida.cloud1D(hitdir + layer + " PDGID of bad hit mother ").fill(mymc.getPDGID());
+                            }
+                        String label = "False hit";
+                        if (badCl == 0)
+                            label = "True Hit ";
+
+                        SimTrackerHit mcbesthit;
+                        Set<SimTrackerHit> mchitlist = mcHittomcP.allTo(bestmcp);
+
+                        double ymc = 0, zmc = 0;
+                        for (SimTrackerHit sthbest : mchitlist) {
+                            int slayer = sthbest.getLayer();
+                            if (layer == slayer) {
+                                mcbesthit = sthbest;
+                                ymc = mcbesthit.getPoint()[1];
+                                zmc = mcbesthit.getPoint()[2];
+                                mcmom = getMag(mcbesthit.getMomentum());
+                                if (prevmom > 0 && badCl == 0) {
+                                    aida.histogram1D(hitdir + layer + " MC energy difference ", 100, -0.005, 0.0).fill(mcmom - prevmom);
+                                    aida.histogram1D(hitdir + " MC energy difference ", 100, -0.005, 0.0).fill(mcmom - prevmom);
+                                }
+                                prevmom = mcmom;
+
+                            }
+                        }
+
+                        double axdotu = VecOp.dot(cl.u(), axial);
+                        boolean isAxial = false;
+                        if (axdotu > 0.5)
+                            isAxial = true;
+//                    aida.cloud2D(hitdir + layer + " y vs z " + label).fill(z, y);
+                        if (isAxial) {
+                            aida.cloud1D(hitdir + layer + " y " + label).fill(clvec.y());
+                            aida.cloud1D(hitdir + layer + " deltay " + label).fill(clvec.y() - ymc);
+                            aida.cloud2D(hitdir + layer + " y vs yMC " + label).fill(ymc, clvec.y());
+                        } else {
+                            aida.cloud1D(hitdir + layer + " z " + label).fill(clvec.z());
+                            aida.cloud1D(hitdir + layer + " deltaz " + label).fill(clvec.z() - zmc);
+                            aida.cloud2D(hitdir + layer + " z vs zMC " + label).fill(zmc, clvec.z());
+                        }
+                        Set<MCParticle> mclist = hittomc.allFrom(hit);
+                        aida.cloud1D(hitdir + layer + " Associated MC particles").fill(mclist.size());
+
+
+                    }
+                }
+                aida.histogram2D(hitdir + "trkChi2 vs my chi2", 100, 0, 100, 100, 0, 100).fill(track.getChi2(), mytotchi2);
+
+            }
+        }
+
+        //  Make the normalized fake plot after the specified number of events
+        if (nevt == 1000) {
+            double wgt = 1. / trk_count;
+            for (int i = 0; i < 10; i++) {
+                System.out.println(" Entries: " + fakes.binEntries(i) + " for mismatches: " + i);
+                for (int j = 0; j < fakes.binHeight(i); j++)
+                    nfakes.fill(i, wgt);
+            }
+            System.out.println("Normalization: " + nfakes.sumAllBinHeights() + " after ntrk = " + trk_count);
+        }
+
+
+        for (HelicalTrackHit hit : toththits) {
+
+            int nAssHits = hit.getRawHits().size();
+            aida.cloud1D(debugDir + hit.Detector() + " nAssHits").fill(nAssHits);
+            Hep3Vector HTHPos = hit.getCorrectedPosition();
+            double rHit = Math.sqrt(HTHPos.x() * HTHPos.x() + HTHPos.y() * HTHPos.y());
+            double zHit = HTHPos.z();
+            double etaHit = -Math.log(Math.tan(Math.atan2(rHit, zHit) / 2));
+            double hitchisq = hit.chisq();
+
+            if (hit instanceof HelicalTrackCross) {
+                HelicalTrackCross cross = (HelicalTrackCross) hit;
+                List<HelicalTrackStrip> clusterlist = cross.getStrips();
+                double du_stereo = 0;
+                double du_axial = 0;
+                for (HelicalTrackStrip cluster : clusterlist) {
+
+                    int nstrips = cluster.rawhits().size();
+                    aida.cloud1D(debugDir + hit.Detector() + " nStrips-per-layer").fill(nstrips);
+                    Hep3Vector corigin = cluster.origin();
+                    Hep3Vector u = cluster.u();
+                    List<RawTrackerHit> rawhits = cluster.rawhits();
+                    double umc = -999999;
+                    double stenergy = -999999;
+                    String stripdir = "axial";
+                    double umeas = cluster.umeas();
+                    double charge = cluster.dEdx() * 1000.0;
+                    for (RawTrackerHit rhit : rawhits) {
+
+                        String deName = rhit.getDetectorElement().getName();
+                        if (deName.contains("sensor1"))
+                            stripdir = "stereo";
+                        //                           System.out.println("Layer number  " + rhit.getLayerNumber() + "  " + deName);
+                        List<SimTrackerHit> sthits = rhit.getSimTrackerHits();
+                        int nsthits = sthits.size();
+                        aida.cloud1D(debugDir + hit.Detector() + " associated ST hits").fill(nsthits);
+                        aida.cloud1D(debugDir + hit.Detector() + " layer" + stripdir + " associated ST hits").fill(nsthits);
+                        if (nsthits == 1) {
+                            double[] sthitD = sthits.get(0).getPoint();
+                            BasicHep3Vector sthit = new BasicHep3Vector(sthitD);
+                            stenergy = sthits.get(0).getdEdx();
+                            Hep3Vector vdiff = VecOp.sub(sthit, corigin);
+                            umc = VecOp.dot(vdiff, u);
+                        }
+                    }
+
+
+                    //                        System.out.println("filling...");
+                    if (umc != -999999) {
+                        aida.histogram1D(debugDir + hit.Detector() + "dedx", 50, 0, 0.3).fill(charge);
+                        if (umc < 1 && umc > -1)
+                            aida.cloud2D(debugDir + hit.Detector() + "cluster reco vs cluster mc").fill(umeas - umc, umc);
+                        aida.cloud2D(debugDir + hit.Detector() + "cluster vs STHit dedx").fill(stenergy, charge);
+                        aida.cloud2D(debugDir + hit.Detector() + "cluster dedx vs delte(u)").fill(umeas - umc, charge);
+                        if (stripdir.contains("stereo"))
+                            du_stereo = umeas - umc;
+                        if (stripdir.contains("axial"))
+                            du_axial = umeas - umc;
+                        aida.cloud1D(debugDir + hit.Detector() + "layer=" + stripdir + " delta(u)").fill(umeas - umc);
+                        aida.cloud1D(debugDir + hit.Detector() + " delta(u)").fill(umeas - umc);
+                        if (nstrips == 1) {
+                            aida.cloud1D(debugDir + hit.Detector() + "layer=" + stripdir + " delta(u)--1 strip").fill(umeas - umc);
+                            aida.cloud1D(debugDir + hit.Detector() + " delta(u)--1 strip").fill(umeas - umc);
+                        }
+                        if (nstrips == 2) {
+                            aida.cloud1D(debugDir + hit.Detector() + "layer=" + stripdir + " delta(u)--2 strip").fill(umeas - umc);
+                            aida.cloud1D(debugDir + hit.Detector() + " delta(u)--2 strip").fill(umeas - umc);
+                        }
+                        if (nstrips == 3) {
+                            aida.cloud1D(debugDir + hit.Detector() + "layer=" + stripdir + " delta(u)--3 strip").fill(umeas - umc);
+                            aida.cloud1D(debugDir + hit.Detector() + " delta(u)--3 strip").fill(umeas - umc);
+                        }
+                    }
+
+                }
+                aida.cloud2D(debugDir + hit.Detector() + " delta(u) stereo v axial").fill(du_stereo, du_axial);
+            }
+        }
+
+        //analyze the event
+        int ApCand = 0;
+        String apdir = "Aprime/";
+        Track eleID = null;
+        Track posID = null;
+        MCParticle eleMC = null;
+        MCParticle posMC = null;
+        for (Track track : tracklist) {
+
+            TrackAnalysis tkanal = tkanalMap.get(track);
+            //  Calculate purity and make appropriate plots
+            MCParticle mcp = tkanal.getMCParticle();
+            if (mcp == null)
+                continue;
+            if (mcp.getParents().size() == 1 && mcp.getParents().get(0).getPDGID() == 622) {
+                int nhits = tkanal.getNHitsNew();
+                double px = track.getPX();
+                double py = track.getPY();
+                double pz = track.getPZ();
+                double pt = Math.sqrt(px * px + py * py);
+                double pperp = Math.sqrt(py * py + pz * pz);
+                double p = Math.sqrt(pt * pt + pz * pz);
+                double phi = Math.atan2(py, px);
+                double cth = pz / Math.sqrt(pt * pt + pz * pz);
+
+                SeedTrack stEle = (SeedTrack) track;
+                SeedCandidate seedEle = stEle.getSeedCandidate();
+                HelicalTrackFit ht = seedEle.getHelix();
+                double doca = ht.dca();
+                double[] poca = {ht.x0(), ht.y0(), ht.z0()};
+                if (mcp.getCharge() > 0) {
+                    posID = track;
+                    posMC = mcp;
+                    fillTrackInfo(apdir, "positron", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, doca, poca[0], poca[1], poca[2]);
+
+                } else {
+                    eleID = track;
+                    eleMC = mcp;
+                    fillTrackInfo(apdir, "electron", track.getChi2(), nhits, p, pperp, px, py, pz, phi, cth, doca, poca[0], poca[1], poca[2]);
+                }
+            }
+
+        }
+        String vertex = "Vertexing/";
+        String selected = "Selection/";
+        String nhitsTotal = "NumberOfHits/";
+        List<BilliorTrack> btlist = new ArrayList<BilliorTrack>();
+        for (Track track1 : tracklist) {
+            Track ele = null;
+            Track pos = null;
+            int ch1 = track1.getCharge();
+            int index = tracklist.indexOf(track1);
+            List<Track> subtracklist = tracklist.subList(index, tracklist.size());
+            for (Track track2 : subtracklist) {
+                int ch2 = track2.getCharge();
+                if (track1 != track2 && ch1 == -ch2) {
+                    ele = track1;
+                    pos = track2;
+//                    System.out.println("Found two oppositely charged tracks!  Lets look at them");
+                    if (ch1 > 0) {
+                        ele = track2;
+                        pos = track1;
+                    }
+                    ApCand++;
+                    int nElectron = ele.getTrackerHits().size();
+                    int nPositron = pos.getTrackerHits().size();
+                    BilliorTrack btEle = btMap.get(ele);
+                    BilliorTrack btPos = btMap.get(pos);
+                    btlist.clear();
+                    btlist.add(btEle);
+                    btlist.add(btPos);
+
+                    /*
+
+
+                     BilliorVertex bvertexUC = new BilliorVertex(bfield);
+                     bvertexUC.doBeamSpotConstraint(false);
+                     bvertexUC.tryNewFormalism(btlist);
+
+                     BasicMatrix bvtxPosUC = (BasicMatrix)
+                     bvertexUC.getVertexPosition(); BasicMatrix bvtxCovUC =
+                     (BasicMatrix) bvertexUC.getVertexCovariance(); double
+                     invMass = bvertexUC.getInvMass();
+
+                     aida.histogram1D(vertex + "BilliorVertex X --
+                     UnConstrained", 100, -10, 20).fill(bvtxPosUC.e(0, 0));
+                     aida.histogram1D(vertex + "BilliorVertex Y --
+                     UnConstrained", 100, -0.4, 0.4).fill(bvtxPosUC.e(1, 0));
+                     aida.histogram1D(vertex + "BilliorVertex Z --
+                     UnConstrained", 100, -0.4, 0.4).fill(bvtxPosUC.e(2, 0));
+                     aida.histogram1D(vertex + "BilliorVertex ChiSq --
+                     UnConstrained", 100, 0, 50).fill(bvertexUC.getChiSq());
+                     aida.histogram1D(vertex + "BilliorVertex X Pull --
+                     UnConstrained", 100, -4, 4).fill(bvtxPosUC.e(0, 0) /
+                     Math.sqrt(bvtxCovUC.e(0, 0))); aida.histogram1D(vertex +
+                     "BilliorVertex Y Pull-- UnConstrained", 100, -4,
+                     4).fill(bvtxPosUC.e(1, 0) / Math.sqrt(bvtxCovUC.e(1, 1)));
+                     aida.histogram1D(vertex + "BilliorVertex Z Pull--
+                     UnConstrained", 100, -4, 4).fill(bvtxPosUC.e(2, 0) /
+                     Math.sqrt(bvtxCovUC.e(2, 2))); aida.histogram1D(vertex +
+                     "BilliorVertex Mass -- UnConstrained", 250, 0.0,
+                     0.25).fill(bvertexUC.getInvMass());
+
+
+                     aida.cloud1D(apdir + "e+e- Invariant Mass").fill(invMass);
+                     if (eleMC != null && posMC != null && ele == eleID && pos
+                     == posID) aida.cloud1D(apdir + "Matched A' Invariant
+                     Mass").fill(invMass);
+
+
+                     BilliorVertex bvertex = new BilliorVertex(bfield);
+                     bvertex.doBeamSpotConstraint(true);
+                     bvertex.tryNewFormalism(btlist); BasicMatrix bvtxPos =
+                     (BasicMatrix) bvertex.getVertexPosition(); BasicMatrix
+                     bvtxCov = (BasicMatrix) bvertex.getVertexCovariance();
+
+                     aida.histogram1D(vertex + "BilliorVertex X -- Constrained",
+                     100, -10, 20).fill(bvtxPos.e(0, 0));
+                     aida.histogram1D(vertex + "BilliorVertex Y -- Constrained",
+                     100, -0.4, 0.4).fill(bvtxPos.e(1, 0));
+                     aida.histogram1D(vertex + "BilliorVertex Z -- Constrained",
+                     100, -0.4, 0.4).fill(bvtxPos.e(2, 0));
+                     aida.histogram1D(vertex + "BilliorVertex ChiSq --
+                     Constrained", 100, -10, 50).fill(bvertex.getChiSq());
+                     aida.histogram1D(vertex + "BilliorVertex X Pull --
+                     Constrained", 100, -4, 4).fill(bvtxPos.e(0, 0) /
+                     Math.sqrt(bvtxCov.e(0, 0))); aida.histogram1D(vertex +
+                     "BilliorVertex Y Pull-- Constrained", 100, -4,
+                     4).fill(bvtxPos.e(1, 0) / Math.sqrt(bvtxCov.e(1, 1)));
+                     aida.histogram1D(vertex + "BilliorVertex Z Pull--
+                     Constrained", 100, -4, 4).fill(bvtxPos.e(2, 0) /
+                     Math.sqrt(bvtxCov.e(2, 2)));
+
+                     aida.histogram1D(vertex + "BilliorVertex Mass --
+                     Constrained", 250, 0.0, 0.25).fill(bvertex.getInvMass());
+
+
+
+                     BilliorVertex bsconfit = new BilliorVertex(bfield);
+                     bsconfit.setBeamSize(beamsize);
+                     bsconfit.doBeamSpotConstraint(false);
+                     bsconfit.constrainV0toBeamSpot(true);
+                     bsconfit.tryNewFormalism(btlist); BasicMatrix bsconvtxPos =
+                     (BasicMatrix) bsconfit.getVertexPosition(); BasicMatrix
+                     bsconvtxCov = (BasicMatrix) bsconfit.getVertexCovariance();
+
+                     aida.histogram1D(vertex + "BilliorVertex X -- BS
+                     Constrained", 100, -10, 20).fill(bsconvtxPos.e(0, 0));
+                     aida.histogram1D(vertex + "BilliorVertex Y -- BS
+                     Constrained", 100, -0.4, 0.4).fill(bsconvtxPos.e(1, 0));
+                     aida.histogram1D(vertex + "BilliorVertex Z -- BS
+                     Constrained", 100, -0.4, 0.4).fill(bsconvtxPos.e(2, 0));
+                     aida.histogram1D(vertex + "BilliorVertex ChiSq -- BS
+                     Constrained", 100, -10, 50).fill(bsconfit.getChiSq());
+                     aida.histogram1D(vertex + "BilliorVertex X Pull -- BS
+                     Constrained", 100, -4, 4).fill(bsconvtxPos.e(0, 0) /
+                     Math.sqrt(bvtxCov.e(0, 0))); aida.histogram1D(vertex +
+                     "BilliorVertex Y Pull-- BS Constrained", 100, -4,
+                     4).fill(bsconvtxPos.e(1, 0) / Math.sqrt(bvtxCov.e(1, 1)));
+                     aida.histogram1D(vertex + "BilliorVertex Z Pull-- BS
+                     Constrained", 100, -4, 4).fill(bsconvtxPos.e(2, 0) /
+                     Math.sqrt(bvtxCov.e(2, 2)));
+
+                     aida.histogram1D(vertex + "BilliorVertex Mass -- BS
+                     Constrained", 100, 0.08, 0.12).fill(bsconfit.getInvMass());
+                     */
+                }
+            }
+        }
+
+        aida.cloud1D(apdir + "Number of Aprime candidates found").fill(ApCand);
+        aida.cloud1D(apdir + "Number of negative candidates found").fill(_neleRec);
+        aida.cloud1D(apdir + "Number of true electrons").fill(_neleTru);
+        aida.cloud1D(apdir + "Number of fake electrons").fill(_neleFake);
+        aida.cloud1D(apdir + "Number of positive candidates found").fill(_nposRec);
+        aida.cloud1D(apdir + "Number of true positrons").fill(_nposTru);
+        aida.cloud1D(apdir + "Number of fake positrons").fill(_nposFake);
+
+        //  Now loop over all MC Particles
+        List<MCParticle> mclist = event.getMCParticles();
+        int _nchMCP = 0;
+        int _nchMCPBar = 0;
+        for (MCParticle mcp : mclist) {
+
+            //  Calculate the pT and polar angle of the MC particle
+            double px = mcp.getPX();
+            double py = mcp.getPY();
+            double pz = mcp.getPZ();
+            double pt = Math.sqrt(px * px + py * py);
+            double p = Math.sqrt(pt * pt + pz * pz);
+            double cth = pz / p;
+            double theta = 180. * Math.acos(cth) / Math.PI;
+            double eta = -Math.log(Math.tan(Math.atan2(pt, pz) / 2));
+            double phi = Math.atan2(py, px);
+            //  Find the number of layers hit by this mc particle
[truncated at 1000 lines; 526 more skipped]

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
EcalHitPosition.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/EcalHitPosition.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/EcalHitPosition.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,57 @@
+package org.lcsim.hps.users.omoreno;
+
+//--- lcsim ---//
+import org.lcsim.event.GenericObject;
+
+/**
+ * 
+ * 
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: EcalHitPosition.java,v 1.1 2013/06/02 18:24:06 omoreno Exp $
+ */
+public class EcalHitPosition implements GenericObject {
+
+	double[] position; 
+	
+	public EcalHitPosition(double[] position){
+		this.position = position; 
+	}
+	
+	/**
+	 * 
+	 */
+	@Override
+	public double getDoubleVal(int index) {
+		return position[index];
+	}
+
+	@Override
+	public float getFloatVal(int arg0) {
+		return 0;
+	}
+
+	@Override
+	public int getIntVal(int arg0) {
+		return 0;
+	}
+
+	@Override
+	public int getNDouble() {
+		return position.length;
+	}
+
+	@Override
+	public int getNFloat() {
+		return 0;
+	}
+
+	@Override
+	public int getNInt() {
+		return 0;
+	}
+
+	@Override
+	public boolean isFixedSize() {
+		return true;
+	}
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
EventDataDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/EventDataDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/EventDataDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,56 @@
+package org.lcsim.hps.users.omoreno;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.GenericObject;
+import org.lcsim.util.Driver;
+import org.lcsim.event.LCRelation; 
+import org.lcsim.event.base.BaseLCRelation;
+
+
+public class EventDataDriver extends Driver {
+
+	
+	List<EcalHitPosition> ecalHitPositions; 
+	List<LCRelation> ecalHitsToPosition; 
+	
+	// Collection Names 
+	String ecalHitsCollectionName = "EcalCalHits";
+	String ecalHitsPositionCollectionName = "EcalCalHitPositions"; 
+	String ecalHitsRelationCollectionName = "EcalCalHitsRelation";
+	
+	public EventDataDriver(){}; 
+	
+	public void process(EventHeader event){ 
+		
+		// If the event doesn't contain Ecal calorimeter hits, skip the event
+		if(!event.hasCollection(CalorimeterHit.class, ecalHitsCollectionName)) return; 
+		
+		// Get the collections of Ecal calorimeter hits from the event 
+		List<CalorimeterHit> ecalHits = event.get(CalorimeterHit.class, ecalHitsCollectionName);
+		
+		// Instantiate the list to contain all of the Ecal calorimeter hit positions
+		ecalHitPositions = new ArrayList<EcalHitPosition>(); 
+		ecalHitsToPosition = new ArrayList<LCRelation>(); 
+		
+		
+		// Loop over all of the Ecal calorimeter hits and add the hit position 
+		// to the event
+		for(CalorimeterHit ecalHit : ecalHits){
+			
+			double[] position = ecalHit.getPosition(); 
+			
+			EcalHitPosition ecalHitPosition = new EcalHitPosition(position); 
+			ecalHitPositions.add(ecalHitPosition); 
+			ecalHitsToPosition.add(new BaseLCRelation(ecalHit, ecalHitPosition)); 
+		}
+	
+		event.put(ecalHitsRelationCollectionName, ecalHitsToPosition, LCRelation.class, 0); 
+		event.put(ecalHitsPositionCollectionName, ecalHitPositions, GenericObject.class, 0);
+		
+	}
+	
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
PlotUtils.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/PlotUtils.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/PlotUtils.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,112 @@
+package org.lcsim.hps.users.omoreno;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.tracking.SvtUtils;
+import org.lcsim.util.aida.AIDA;
+
+import hep.aida.IHistogram2D;
+
+import hep.aida.ICloud2D;
+//--- hep ---//
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IPlotter;
+import hep.aida.IPlotterStyle;
+import hep.physics.vec.Hep3Vector;
+
+public class PlotUtils {
+
+	// Default ctor
+	public PlotUtils(){}	
+
+	public static IPlotter setupPlotter(String title, int regionX, int regionY){
+	    IPlotter plotter = AIDA.defaultInstance().analysisFactory().createPlotterFactory().create(title);
+	    plotter.setTitle(title);
+	    
+	    if(regionX < 0 || regionY < 0) throw new RuntimeException("Region dimensions need to be greater than 0!");
+	    else if(regionX != 0 || regionY != 0) plotter.createRegions(regionX, regionY);
+	    
+	    plotter.style().statisticsBoxStyle().setVisible(false);
+	    plotter.style().dataStyle().errorBarStyle().setVisible(false);
+	    plotter.setParameter("plotterWidth", "800");
+	    plotter.setParameter("plotterHeight", "800");
+	    
+	    return plotter;
+	    
+	}
+    
+    public static void setup2DRegion(IPlotter plotter, String title, int region, String xTitle, String yTitle, IHistogram2D histo){
+    	
+    	// Check if the specified region is valid
+    	if(region > plotter.numberOfRegions()) 
+    		throw new RuntimeException("Region is invalid! " + title + " contains " + plotter.numberOfRegions() + " regions");
+    	
+		plotter.region(region).style().xAxisStyle().setLabel(xTitle);
+		plotter.region(region).style().xAxisStyle().labelStyle().setFontSize(14);
+		plotter.region(region).style().yAxisStyle().setLabel(yTitle);
+		plotter.region(region).style().yAxisStyle().labelStyle().setFontSize(14);
+		plotter.region(region).style().xAxisStyle().setVisible(true);
+		plotter.region(region).style().yAxisStyle().setVisible(true);
+		plotter.region(region).style().setParameter("hist2DStyle", "colorMap");
+    	plotter.region(region).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+    	
+    	if(histo != null) plotter.region(region).plot(histo);
+    }
+   
+    public static void setup2DRegion(IPlotter plotter, String title, int region, String xTitle, String yTitle, ICloud2D cloud, IPlotterStyle style){
+    	
+    	// Check if the specified region is valid
+    	if(region > plotter.numberOfRegions()) 
+    		throw new RuntimeException("Region is invalid! " + title + " contains " + plotter.numberOfRegions() + " regions");
+    	
+		plotter.region(region).style().xAxisStyle().setLabel(xTitle);
+		plotter.region(region).style().xAxisStyle().labelStyle().setFontSize(14);
+		String[] pars = plotter.region(region).style().xAxisStyle().availableParameters();
+		plotter.region(region).style().yAxisStyle().setLabel(yTitle);
+		plotter.region(region).style().yAxisStyle().labelStyle().setFontSize(14);
+		plotter.region(region).style().xAxisStyle().setVisible(true);
+		plotter.region(region).style().yAxisStyle().setVisible(true);
+		plotter.region(region).style().setParameter("showAsScatterPlot", "true");
+    	
+    	if(cloud != null) plotter.region(region).plot(cloud, style);
+    }
+    
+    
+    public static void setup1DRegion(IPlotter plotter, String title, int region, String xTitle, IHistogram1D histo){
+    	
+		plotter.region(region).style().xAxisStyle().setLabel(xTitle);
+		plotter.region(region).style().xAxisStyle().labelStyle().setFontSize(14);
+		plotter.region(region).style().xAxisStyle().setVisible(true);
+		plotter.region(region).style().dataStyle().fillStyle().setVisible(false);
+		plotter.region(region).style().dataStyle().lineStyle().setThickness(3);
+		
+		if(histo != null) plotter.region(region).plot(histo);
+    }
+    
+    /**
+     * 
+     */
+    public static int getPlotterRegion(SiSensor sensor) {
+
+        int layer = SvtUtils.getInstance().getLayerNumber(sensor);
+
+        // Compute the sensor's x and y grid coordinates and then translate to region number.
+        int ix = (layer - 1) / 2;
+        int iy = 0;
+        if (!SvtUtils.getInstance().isTopLayer(sensor)) {
+            iy += 2;
+        }
+        if (layer % 2 == 0) {
+            iy += 1;
+        }
+        int region = ix * 4 + iy;
+        return region;
+    }
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
ReconstructedParticleChecker.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/ReconstructedParticleChecker.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/ReconstructedParticleChecker.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,123 @@
+package org.lcsim.hps.users.omoreno;
+
+//--- java ---//
+import java.util.ArrayList;
+import java.util.List;
+
+
+//--- hep ---//
+import hep.aida.IHistogram1D;
+import hep.aida.IPlotter;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+
+//--- lcsim ---//
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.ReconstructedParticle;
+import org.lcsim.event.Track;
+import org.lcsim.event.Cluster;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+import org.lcsim.geometry.Detector;
+
+//--- hps-java ---//
+import org.lcsim.hps.recon.tracking.TrackUtils;
+
+/**
+ * 
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: ReconstructedParticleChecker.java,v 1.3 2013/10/14 22:58:03 phansson Exp $
+ *
+ */
+public class ReconstructedParticleChecker extends Driver {
+	
+	private AIDA aida; 
+	private List<IPlotter> plotters = new ArrayList<IPlotter>(); 
+
+	IHistogram1D xPositionResidual;
+	IHistogram1D yPositionResidual;
+	IHistogram1D zPositionResidual;
+	IHistogram1D r;
+	
+	// Collection Names
+	private String finalStateParticlesCollectionName = "FinalStateParticles";
+	
+	boolean debug = true; 
+	int plotterIndex = 0; 
+	
+	public ReconstructedParticleChecker(){} 
+	
+	protected void detectorChanged(Detector detector){
+		super.detectorChanged(detector);
+		
+		// Setup AIDA
+		aida = AIDA.defaultInstance(); 
+		aida.tree().cd("/");
+		
+		plotters.add(PlotUtils.setupPlotter("Track-Cluster Position Residual", 2, 2));
+		xPositionResidual = aida.histogram1D("x Residual", 100, -100, 100);
+		yPositionResidual = aida.histogram1D("y Residual", 100, -100, 100);
+		zPositionResidual = aida.histogram1D("z Residual", 100, -100, 100);
+		r = aida.histogram1D("r", 100, -100, 100);
+		PlotUtils.setup1DRegion(plotters.get(plotterIndex), "x Residual", 0, "delta x [mm]", xPositionResidual);
+		PlotUtils.setup1DRegion(plotters.get(plotterIndex), "y Residual", 1, "delta y [mm]", yPositionResidual);
+		PlotUtils.setup1DRegion(plotters.get(plotterIndex), "z Residual", 2, "delta z [mm]", zPositionResidual);
+		PlotUtils.setup1DRegion(plotters.get(plotterIndex), "r", 3, "r [mm]", r);
+		
+		
+		for(IPlotter plotter : plotters){
+			plotter.show(); 
+		}
+	}
+	
+	public void process(EventHeader event){
+		
+		// If the event doesn't contain any final state reconstructed 
+		// particles, skip the event 
+		if(!event.hasCollection(ReconstructedParticle.class, finalStateParticlesCollectionName)){
+			this.printDebug("Event does not contain ReconstructedParticles");
+			return;
+		}
+		
+		// Get the collections of reconstructed final state particles from the
+		// event
+		List<ReconstructedParticle> finalStateParticles 
+			= event.get(ReconstructedParticle.class, finalStateParticlesCollectionName); 
+				
+	
+		// Loop over all of the reconstructed particles in the event
+		for(ReconstructedParticle finalStateParticle : finalStateParticles){
+			
+			// Get the list of clusters from the event
+			List<Cluster> ecalClusters = finalStateParticle.getClusters(); 
+				this.printDebug("Number of Ecal clusters: " + ecalClusters.size()); 
+			if(ecalClusters.isEmpty()){
+				this.printDebug("Number of Ecal clusters: " + ecalClusters.size()); 
+				this.printDebug("List of Ecal cluster is empty ... skipping");
+				continue; 
+			}
+			
+			// Get the list of tracks from the event
+			List<Track> tracks = finalStateParticle.getTracks(); 
+			if(tracks.isEmpty()){
+				this.printDebug("List of tracks is empty ... skipping");
+				continue; 
+			}
+		
+			Hep3Vector ecalPosition = new BasicHep3Vector(ecalClusters.get(0).getPosition()); 
+			Hep3Vector trackPositionAtEcal = TrackUtils.extrapolateTrack(tracks.get(0),ecalPosition.z()); 
+			xPositionResidual.fill(trackPositionAtEcal.x() - ecalPosition.x());
+			yPositionResidual.fill(trackPositionAtEcal.y() - ecalPosition.y());
+			zPositionResidual.fill(trackPositionAtEcal.z() - ecalPosition.z());
+			r.fill(VecOp.sub(trackPositionAtEcal, ecalPosition).magnitude());
+		}
+		
+	}
+	
+	private void printDebug(String debugMessage){
+		if(debug)
+			System.out.println(this.getClass().getSimpleName() + ": " + debugMessage); 
+	}
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
SimpleSvtTrigger.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SimpleSvtTrigger.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SimpleSvtTrigger.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,152 @@
+package org.lcsim.hps.users.omoreno;
+
+//--- java ---//
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+//--- lcsim ---//
+import org.lcsim.util.Driver;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.SimTrackerHit;
+
+//--- hps-java ---//
+import org.lcsim.hps.recon.tracking.FindableTrack;
+import org.lcsim.hps.recon.tracking.SvtUtils;
+import org.lcsim.hps.recon.tracking.apv25.Apv25Full;
+
+public class SimpleSvtTrigger extends Driver {
+    
+    FindableTrack findable = null;
+    
+    int eventNumber = 0;
+    int numberOfSvtLayers = 12;
+    int numberOfSvtLayersHit = 10;
+    
+    boolean debug = false;
+    
+    // Collection Names
+    String simTrackerHitCollectionName = "TrackerHits";
+
+
+    //--- Setters ---//
+    //---------------//
+    
+    /**
+     * Enable/disable debug.
+     */
+    public void setDebug(boolean debug){
+        this.debug = debug; 
+    }
+    
+    /**
+     * Set the number of SVT Layers.
+     */
+    public void setNumberOfSvtLayers(int numberOfSvtLayers){
+        this.numberOfSvtLayers = numberOfSvtLayers;
+    }
+    
+    /**
+     * Set the number of SVT Layers that an MC particle should hit.
+     */
+    public void setNumberOfSvtLayersHit(int numberOfSvtLayersHit){
+        this.numberOfSvtLayersHit = numberOfSvtLayersHit;
+    }
+
+    /**
+     * Set the SimTrackerHit collection name.
+     */
+    public void setSimTrackerHitCollectionName(String simTrackerHitCollectionName){
+        this.simTrackerHitCollectionName = simTrackerHitCollectionName;
+    }
+    
+    /**
+     * Dflt Ctor.
+     */
+    public SimpleSvtTrigger(){ 
+    }
+    
+    /**
+     *
+     */
+    public SimpleSvtTrigger(int numberOfSvtLayers, int numberOfSvtLayersHit){
+        this.numberOfSvtLayers = numberOfSvtLayers;
+        this.numberOfSvtLayersHit = numberOfSvtLayersHit;
+    }
+
+    /**
+     * 
+     */
+    protected void process(EventHeader event){
+        
+        eventNumber++;
+        
+        // If the event doesn't contain SimTrackerHits; skip the event
+        if(!event.hasCollection(SimTrackerHit.class, simTrackerHitCollectionName)){
+            this.printDebug("The event does not contain the collection " + simTrackerHitCollectionName);
+            return;
+        }
+        List<SimTrackerHit> simHits = event.get(SimTrackerHit.class, simTrackerHitCollectionName);
+        this.printDebug("The collection " + simTrackerHitCollectionName + " contains " + simHits.size() + " SimTrackerHits");
+        this.printDebug("The total number of SimTrackerHit collections " + event.get(SimTrackerHit.class).size());
+
+        // Get the MC Particles associated with the SimTrackerHits
+        List<MCParticle> mcParticles = event.getMCParticles();
+        if(debug){
+            String particleList = "[ ";
+            for(MCParticle mcParticle : mcParticles){
+                particleList += mcParticle.getPDGID() + ", ";
+            }
+            particleList += "]";
+            this.printDebug("MC Particles: " + particleList);
+        }
+        
+        // Check if the MC particle track should be found by the tracking algorithm
+        findable = new FindableTrack(event, simHits, numberOfSvtLayers);
+        
+        // Use an iterator to avoid ConcurrentModificationException
+        Iterator<MCParticle> mcParticleIterator = mcParticles.iterator();
+        while(mcParticleIterator.hasNext()){
+            MCParticle mcParticle = mcParticleIterator.next();
+            if(findable.isTrackFindable(mcParticle, numberOfSvtLayersHit)){
+                
+                // Check that all SimTrackerHits are within the same detector volume
+                Set<SimTrackerHit> trackerHits = findable.getSimTrackerHits(mcParticle);
+                if(this.isSameSvtVolume(trackerHits)){
+                    // If all hits lie within the same detector volume, then trigger the SVT
+                    // This is a redundant check but better safe than sorry
+                    this.printDebug("The SVT has been triggered on event: " + eventNumber);
+                    Apv25Full.readoutBit = true;
+                    break;
+                }
+            } else { 
+                mcParticleIterator.remove();
+            }
+        }
+    }
+    
+    /**
+     * Check that all SVT hits are within the same detector volume (either top or bottom)
+     * @param simTrackerHits
+     * @return true if the hits are within the same detector volume, false otherwise
+     */
+    private boolean isSameSvtVolume(Set<SimTrackerHit> simTrackerHits){
+        int volumeIndex = 0;
+        for(SimTrackerHit simTrackerHit : simTrackerHits){
+            if(SvtUtils.getInstance().isTopLayer((SiSensor) simTrackerHit.getDetectorElement())) volumeIndex++;
+            else volumeIndex--;
+        }
+        return Math.abs(volumeIndex) == simTrackerHits.size();
+    }
+    
+    /**
+     * print debug statements
+     */
+    public void printDebug(String debugStatement){
+        if(!debug) return;
+        System.out.println(this.getClass().getSimpleName() + ": " + debugStatement);     
+    }
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
SvtHitCorrelations.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtHitCorrelations.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtHitCorrelations.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,196 @@
+package org.lcsim.hps.users.omoreno;
+
+//--- java ---//
+import java.util.ArrayList;
+import java.util.List;
+
+//--- org.lcsim ---//
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.geometry.Detector;
+
+//--- hps-java ---//
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.tracking.SvtUtils;
+
+//--- aida ---//
+import hep.aida.IPlotter;
+
+/**
+ * 
+ * @author Omar Moreno
+ * @version $Id: SvtHitCorrelations.java,v 1.2 2013/10/25 19:45:01 jeremy Exp $
+ *
+ */
+public class SvtHitCorrelations extends Driver {
+
+	private AIDA aida;
+	private List<AIDAFrame> frames = new ArrayList<AIDAFrame>();
+	private List<IPlotter> plotters = new ArrayList<IPlotter>();
+	
+    private String rawTrackerHitCollectionName = "SVTRawTrackerHits";
+    boolean taa = true;
+    boolean tas = true;
+    boolean baa = true;
+    boolean bas = true;
+    
+    
+	protected void detectorChanged(Detector detector){
+		
+		aida = AIDA.defaultInstance();
+		aida.tree().cd("/");
+		
+		for(int index = 0; index < 4; index++) frames.add(new AIDAFrame());
+	
+		frames.get(0).setTitle("Top Correlation Plots: Axial vs Axial");
+		frames.get(1).setTitle("Top Correlation Plots: Axial vs Stereo");
+		frames.get(2).setTitle("Bottom Correlation Plots: Axial vs Axial");
+		frames.get(3).setTitle("Bottom Correlation Plots: Axial vs Stereo");
+
+		int nPlotters = 0;
+		String plotName;
+		
+		// Create top volume axial plots
+		if(taa){
+			for(int layer1 = 1; layer1 <= 5; layer1++ ){
+				for(int layer2 = 1; layer2 <= 5; layer2++){
+					plotName = "Top Channel Correlation: Axial Layer " + layer1 + " vs Axial Layer " + layer2;
+					plotters.add(aida.analysisFactory().createPlotterFactory().create(plotName));
+					plotters.get(nPlotters).region(0).plot(aida.histogram2D(plotName, 320, 0, 639, 320, 0, 639));
+					plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+					plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+					plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+					frames.get(0).addPlotter(plotters.get(nPlotters));
+					nPlotters++;
+				}
+			}
+		}
+		
+		if(tas){
+			for(int layer1 = 1; layer1 <= 5; layer1++ ){
+				for(int layer2 = 1; layer2 <= 5; layer2++){
+					plotName = "Top Channel Correlation: Axial Layer " + layer1 + " vs Stereo Layer " + layer2;
+					plotters.add(aida.analysisFactory().createPlotterFactory().create(plotName));
+					plotters.get(nPlotters).region(0).plot(aida.histogram2D(plotName, 320, 0, 639, 320, 0, 639));
+					plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+					plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+					plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+					frames.get(1).addPlotter(plotters.get(nPlotters));
+					nPlotters++;
+				}
+			}
+		}
+	
+		// Create bottom volume axial plots
+		if(baa){
+			for(int layer1 = 1; layer1 <= 5; layer1++ ){
+				for(int layer2 = 1; layer2 <= 5; layer2++){
+					plotName = "Bottom Channel Correlation: Axial Layer " + layer1 + " vs Axial Layer " + layer2;
+					plotters.add(aida.analysisFactory().createPlotterFactory().create(plotName));
+					plotters.get(nPlotters).region(0).plot(aida.histogram2D(plotName, 320, 0, 639, 320, 0, 639));
+					plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+					plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+					plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+					frames.get(2).addPlotter(plotters.get(nPlotters));
+					nPlotters++;
+				}
+			}
+		}
+		
+		if(bas){
+			for(int layer1 = 1; layer1 <= 5; layer1++ ){
+				for(int layer2 = 1; layer2 <= 5; layer2++){
+					plotName = "Bottom Channel Correlation: Axial Layer " + layer1 + " vs Stereo Layer " + layer2;
+					plotters.add(aida.analysisFactory().createPlotterFactory().create(plotName));
+					plotters.get(nPlotters).region(0).plot(aida.histogram2D(plotName, 320, 0, 639, 320, 0, 639));
+					plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+					plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+					plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+					frames.get(3).addPlotter(plotters.get(nPlotters));
+					nPlotters++;
+				}
+			}
+		}
+		
+		for(AIDAFrame frame : frames){
+        	frame.pack();
+        	frame.setVisible(true);
+        }
+	}
+	
+	/**
+	 * 
+	 */
+	public void setEnableTopAxialAxial(boolean flag){
+		this.taa = flag;
+	}
+	
+	/**
+	 * 
+	 */
+	public void setEnableTopAxialStereo(boolean flag){
+		this.tas = flag;
+	}
+	
+	/**
+	 * 
+	 */
+	public void setEnableBottomAxialAxial(boolean flag){
+		this.baa = flag;
+	}
+	
+	/**
+	 * 
+	 */
+	public void setEnableBottomAxialStereo(boolean flag){
+		this.bas = flag;
+	}
+
+	public void process(EventHeader event){
+		
+		if(!event.hasCollection(RawTrackerHit.class, rawTrackerHitCollectionName)){
+			System.out.println(this.getClass().getSimpleName() + ": Event does not have RawTrackerHits, skipping event ...");
+			return;
+		}
+	
+		List<RawTrackerHit> rawHits = event.get(RawTrackerHit.class, rawTrackerHitCollectionName);
+		
+		for(RawTrackerHit rawHit1 : rawHits){
+	
+			SiSensor sensor1 = (SiSensor) rawHit1.getDetectorElement();
+			int layer1 = (int) Math.ceil(((double) SvtUtils.getInstance().getLayerNumber(sensor1))/2);
+			int channel1 = rawHit1.getIdentifierFieldValue("strip");
+			
+			for(RawTrackerHit rawHit2 : rawHits){
+			
+				SiSensor sensor2 = (SiSensor) rawHit2.getDetectorElement();
+				int layer2 = (int) Math.ceil(((double) SvtUtils.getInstance().getLayerNumber(sensor2))/2);
+				int channel2 = rawHit2.getIdentifierFieldValue("strip");
+			
+				if(SvtUtils.getInstance().isTopLayer(sensor1) && SvtUtils.getInstance().isTopLayer(sensor2)){
+					if(SvtUtils.getInstance().isAxial(sensor1) && SvtUtils.getInstance().isAxial(sensor2) && taa){
+						String plotName = "Top Channel Correlation: Axial Layer " + layer1 + " vs Axial Layer " + layer2;
+						aida.histogram2D(plotName).fill(channel1, channel2);
+					} else if(SvtUtils.getInstance().isAxial(sensor1) && !SvtUtils.getInstance().isAxial(sensor2) && tas){
+						String plotName = "Top Channel Correlation: Axial Layer " + layer1 + " vs Stereo Layer " + layer2;
+						aida.histogram2D(plotName).fill(channel1, channel2);
+					}
+				} else if(!SvtUtils.getInstance().isTopLayer(sensor1) && !SvtUtils.getInstance().isTopLayer(sensor2) && baa){
+					if(SvtUtils.getInstance().isAxial(sensor1) && SvtUtils.getInstance().isAxial(sensor2)){
+						String plotName = "Bottom Channel Correlation: Axial Layer " + layer1 + " vs Axial Layer " + layer2;
+						aida.histogram2D(plotName).fill(channel1, channel2);
+					} else if(SvtUtils.getInstance().isAxial(sensor1) && !SvtUtils.getInstance().isAxial(sensor2) && bas){
+						String plotName = "Bottom Channel Correlation: Axial Layer " + layer1 + " vs Stereo Layer " + layer2;
+						aida.histogram2D(plotName).fill(channel1, channel2);
+					}
+				}
+			}
+		}
+	}
+	
+	
+
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
SvtHitEfficiency.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtHitEfficiency.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtHitEfficiency.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,573 @@
+package org.lcsim.hps.users.omoreno;
+
+
+//--- java ---//
+import hep.aida.ICloud2D;
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IPlotter;
+import hep.aida.IPlotterStyle;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+//--- lcsim ---//
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.solids.Point3D;
+import org.lcsim.detector.solids.Polygon3D;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiStrips;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.hps.recon.tracking.HPSSVTCalibrationConstants;
+//--- hps-java ---//
+import org.lcsim.hps.recon.tracking.SvtUtils;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.hps.recon.tracking.TrackerHitUtils;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+
+public class SvtHitEfficiency extends Driver {
+
+	private AIDA aida;
+    private List<AIDAFrame> frames = new ArrayList<AIDAFrame>();
+    private List<IHistogram1D> histos1D = new ArrayList<IHistogram1D>();
+    private List<IHistogram2D> histos2D = new ArrayList<IHistogram2D>();
+    private List<IPlotter> plotters = new ArrayList<IPlotter>();
+    private Map<SiSensor, Map<Integer, Hep3Vector>> stripPositions = new HashMap<SiSensor, Map<Integer, Hep3Vector>>(); 
+    TrackerHitUtils trackerHitUtils = new TrackerHitUtils();
+    
+    boolean debug = false;
+    boolean ecalClusterTrackMatch = false;
+    
+    // Plot flags
+    boolean enableMomentumPlots = true;
+    boolean enableChiSquaredPlots = true;
+    boolean enableTrackPositionPlots = true;
+    boolean maskBadChannels = false;
+    
+    int plotterIndex = 0;
+    
+    double numberOfTopTracks = 0;
+    double numberOfBottomTracks = 0;
+    double numberOfTopTracksWithHitOnMissingLayer = 0; 
+    double numberOfBottomTracksWithHitOnMissingLayer = 0;
+    double[] topTracksPerMissingLayer = new double[5];
+    double[] topTracksWithHitOnMissingLayer = new double[5];
+    double[] bottomTracksPerMissingLayer = new double[5];
+    double[] bottomTracksWithHitOnMissingLayer = new double[5];
+    
+    Hep3Vector trackPos = null;
+    Hep3Vector frontTrackPos = null;
+    Hep3Vector rearTrackPos = null;
+    
+    // Collections
+    private String trackCollectionName = "MatchedTracks";
+    private String stereoHitCollectionName = "HelicalTrackHits";
+    private String ecalClustersCollectionName = "EcalClusters";
+   
+    // Constants
+    public static final double SENSOR_LENGTH = 98.33; // mm
+    public static final double SENSOR_WIDTH = 38.3399; // mm
+
+    /**
+     * Default Ctor
+     */
+    public SvtHitEfficiency(){
+    }
+    
+    /**
+     *  Enable/Disable debug 
+     */
+    public void  setDebug(boolean debug){
+        this.debug = debug;
+    }
+    
+    /**
+     * Enable/Disable masking of bad channels
+     */
+    public void setMaskBadChannels(boolean maskBadChannels){
+    	this.maskBadChannels = maskBadChannels; 
+    }
+    
+    public void detectorChanged(Detector detector){
+    	
+        // setup AIDA
+        aida = AIDA.defaultInstance();
+        aida.tree().cd("/");
+
+        // Create AIDA Frames
+        for (int index = 0; index < 2; index++)
+            frames.add(new AIDAFrame());
+        
+        frames.get(0).setTitle("Track Momentum");
+        frames.get(1).setTitle("Track Positions");
+        
+        String title = null;
+        IHistogram2D histo2D = null;
+        IHistogram1D histo1D = null;
+        ICloud2D cloud2D = null;
+
+        // Create a Map from sensor to bad channels and from bad channels to
+        // strip position
+        for(ChargeCarrier carrier : ChargeCarrier.values()){
+            for(SiSensor sensor : SvtUtils.getInstance().getSensors()){ 
+                if(sensor.hasElectrodesOnSide(carrier)){ 
+                    stripPositions.put(sensor, new HashMap<Integer, Hep3Vector>());
+                    SiStrips strips = (SiStrips) sensor.getReadoutElectrodes(carrier);     
+                    ITransform3D parentToLocal = sensor.getReadoutElectrodes(carrier).getParentToLocal();
+                    ITransform3D localToGlobal = sensor.getReadoutElectrodes(carrier).getLocalToGlobal();
+                    for(int physicalChannel = 0; physicalChannel < 640; physicalChannel++){
+                        Hep3Vector localStripPosition = strips.getCellPosition(physicalChannel);
+                        Hep3Vector stripPosition = parentToLocal.transformed(localStripPosition);
+                        Hep3Vector globalStripPosition = localToGlobal.transformed(stripPosition);
+                        //this.printDebug(SvtUtils.getInstance().getDescription(sensor) + " : Channel " + physicalChannel + " : Local Strip Position " + localStripPosition.toString());
+                        //this.printDebug(SvtUtils.getInstance().getDescription(sensor) + " : Channel " + physicalChannel + " : Strip Position " + stripPosition.toString());
+                        //this.printDebug(SvtUtils.getInstance().getDescription(sensor) + " : Channel " + physicalChannel + " : Strip Position " + globalStripPosition.toString());
+                        stripPositions.get(sensor).put(physicalChannel, stripPosition);
+                    }
+                }
+            }
+        }
+        
+        //--- Momentum Plots ---//
+        //----------------------//
+        if(enableMomentumPlots){
+        	plotters.add(PlotUtils.setupPlotter("Track Momentum", 0, 0));
+        	title = "Track Momentum - All Tracks";
+        	histo1D = aida.histogram1D(title, 50, 0, 5);
+        	PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 0, "Momentum [GeV]", histo1D);
+        	title = "Track Momentum - Tracks Within Acceptance";
+        	histo1D = aida.histogram1D(title, 50, 0, 5);
+        	plotters.get(plotterIndex).region(0).plot(histo1D);
+        	title = "Track Momentum - Tracks With All Layers Hit";
+        	histo1D = aida.histogram1D(title, 50, 0, 5);
+        	plotters.get(plotterIndex).region(0).plot(histo1D);
+        	frames.get(0).addPlotter(plotters.get(plotterIndex));
+        	plotterIndex++;
+        }
+        
+        //--- Track Fit Chi Squared ---//
+        //-----------------------------//
+        if(enableChiSquaredPlots){
+        	plotters.add(PlotUtils.setupPlotter("Track Chi Squared", 0, 0));
+        	title = "Chi Squared - All Tracks";
+        	histo1D = aida.histogram1D(title, 50, 0, 50);
+        	PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 0, "Chi Squared", histo1D);
+        	title = "Chi Squared - Tracks Within Acceptance";
+        	histo1D = aida.histogram1D(title, 50, 0, 50);
+        	plotters.get(plotterIndex).region(0).plot(histo1D);
+        	title = "Chi Squared - Tracks With All Layers Hit";
+        	histo1D = aida.histogram1D(title, 50, 0, 50);
+        	plotters.get(plotterIndex).region(0).plot(histo1D);
+            frames.get(0).addPlotter(plotters.get(plotterIndex));
+            plotterIndex++;
+        }
+                
+        //--- Track Position Plots ---//
+        //----------------------------//
+        if(enableTrackPositionPlots){
+        	int layerNumber = 1; 
+        	SiSensor sensor = null;
+        	IPlotterStyle style = aida.analysisFactory().createPlotterFactory().createPlotterStyle();
+            for(int index = 1; index < 6; index++){
+                plotters.add(PlotUtils.setupPlotter("Track Position - Layer " + index, 2, 3));
+            	title = "Track Position - Layer " + index + " - Tracks Within Acceptance";
+                cloud2D = aida.cloud2D(title);
+                PlotUtils.setup2DRegion(plotters.get(plotterIndex), title, 0, "x [mm]", "y [mm]", cloud2D, style);
+                title = "Track Position - Layer " + index + " - Tracks With All Layers Hit";
+                cloud2D = aida.cloud2D(title);
+                plotters.get(plotterIndex).region(0).plot(cloud2D, style);
+                title = "Track Position - Layer " + index + " - Difference";
+                cloud2D = aida.cloud2D(title);
+                PlotUtils.setup2DRegion(plotters.get(plotterIndex), title, 1, "x [mm]", "y [mm]", cloud2D, style);
+                sensor = SvtUtils.getInstance().getBottomSensor(layerNumber, 0);
+                title = SvtUtils.getInstance().getDescription(sensor) + " - Occupancy";
+                histo1D = aida.histogram1D(title, 640, 0, 639);
+                histos1D.add(histo1D);
+                PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 2, "Channel #", histo1D);
+                sensor = SvtUtils.getInstance().getTopSensor(layerNumber, 0);
+                title = SvtUtils.getInstance().getDescription(sensor) + " - Occupancy";
+                histo1D = aida.histogram1D(title, 640, 0, 639);
+                histos1D.add(histo1D);
+                PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 4, "Channel #", histo1D);
+                layerNumber++;
+                sensor = SvtUtils.getInstance().getBottomSensor(layerNumber, 0);
+                title = SvtUtils.getInstance().getDescription(sensor) + " - Occupancy";
+                histo1D = aida.histogram1D(title, 640, 0, 639);
+                histos1D.add(histo1D);
+                PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 3, "Channel #", histo1D);
+                sensor = SvtUtils.getInstance().getTopSensor(layerNumber, 0);
+                title = SvtUtils.getInstance().getDescription(sensor) + " - Occupancy";
+                histo1D = aida.histogram1D(title, 640, 0, 639);
+                histos1D.add(histo1D);
+                PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 5, "Channel #", histo1D);
+                layerNumber++;
+                //frames.get(1).addPlotter(plotters.get(plotterIndex));
+                plotterIndex++;
+            }
+        }
+        
+        for (IPlotter plotter : plotters) {
+            plotter.show();
+        }
+    }
+
+    /**
+     * .
+     */
+    private Hep3Vector getStripPosition(SiSensor sensor, int physicalChannel){ 
+        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
+        if(!event.hasCollection(Track.class, trackCollectionName)) return;
+    
+        // Get the list of tracks from the event
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+        
+        if(tracks.size() >= 2 ) return;
+        
+        // Get the list of Ecal clusters from the event
+        List<HPSEcalCluster> ecalClusters = event.get(HPSEcalCluster.class, ecalClustersCollectionName);
+
+        for(Track track : tracks){
+        	
+            ecalClusterTrackMatch = false;
+        	
+            // Check if there is an Ecal cluster in the same detector volume as the track
+        	/*for(HPSEcalCluster ecalCluster : ecalClusters){
+        		if(ecalCluster.getPosition()[1] > 0 && trkUtil.getZ0() > 0){
+        			ecalClusterTrackMatch = true;
+        			break;
+        		}
+        		else if(ecalCluster.getPosition()[1] < 0 && trkUtil.getZ0() < 0){
+        			ecalClusterTrackMatch = true;
+        			break;
+        		}
+        	}*/
+        	
+        	/*
+        	if(!ecalClusterTrackMatch){
+        		if(debug) System.out.println(this.getClass().getSimpleName() + ": No matching Ecal cluster found");
+        		continue;
+        	}*/
+            
+            // Check that the track is associated with four hits only. This should
+            // be the case since the strategy is only requiring four hits to fit
+            // a track and is not requiring an extending layer
+            if(track.getTrackerHits().size() != 4){
+                System.out.println(this.getClass().getSimpleName() + ": This track is composed of " + track.getTrackerHits().size() + ". Skipping event..." );
+                continue;
+            }
+            
+        	// Apply a momentum cut? Probably ...
+        	// Calculate the track momentum
+        	double momentum = Math.sqrt(track.getPX()*track.getPX() + track.getPY()*track.getPY() + track.getPZ()*track.getPZ());
+        	if(momentum < 0.5 /* GeV */) continue;
+        	if(enableMomentumPlots)
+        		aida.histogram1D("Track Momentum - All Tracks").fill(momentum);
+            
+        	if(enableChiSquaredPlots)
+        		aida.histogram1D("Chi Squared - All Tracks").fill(track.getChi2());
+        	
+            // Find which layer is not being used to fit the track
+            int layer = this.findMissingFitLayer(track.getTrackerHits());
+        	int arrayPosition = (layer - 1)/2;
+            
+        	// Find if the track is within the acceptance of the layer not being used in
+            // the fit
+            if(!isWithinAcceptance(track, layer)) continue;
+            if(TrackUtils.getZ0(track) > 0){
+            	numberOfTopTracks++;
+            	topTracksPerMissingLayer[arrayPosition]++;
+            } else {
+            	numberOfBottomTracks++;
+            	bottomTracksPerMissingLayer[arrayPosition]++;
+            }
+
+            if(enableMomentumPlots)
+    			aida.histogram1D("Track Momentum - Tracks Within Acceptance").fill(momentum);
+    		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){
+            	String title = "Track Position - Layer " + layerNumber + " - Difference";
+            	//aida.histogram2D(title).fill(trackPos.y(), trackPos.z());
+                aida.cloud2D(title).fill(frontTrackPos.y(), frontTrackPos.z());
+
+                title = "Track Position - Layer " + layerNumber + " - Tracks With All Layers Hit";
+                //aida.histogram2D(title).fill(trackPos.y(), trackPos.z());
+                aida.cloud2D(title).fill(frontTrackPos.y(), frontTrackPos.z());
+            }
+    		
+    		List<SiSensor> sensors = new ArrayList<SiSensor>();
+    		if(TrackUtils.getZ0(track) > 0){
+    			sensors.add(SvtUtils.getInstance().getTopSensor(layer, 0));
+        		sensors.add(SvtUtils.getInstance().getTopSensor(layer+1, 0));
+    		} else { 
+    			sensors.add(SvtUtils.getInstance().getBottomSensor(layer, 0));
+        		sensors.add(SvtUtils.getInstance().getBottomSensor(layer+1, 0));
+    		}
+    		aida.histogram1D(SvtUtils.getInstance().getDescription(sensors.get(0)) + " - Occupancy").fill(this.findIntersectingChannel(frontTrackPos, sensors.get(0)));
+            aida.histogram1D(SvtUtils.getInstance().getDescription(sensors.get(1)) + " - Occupancy").fill(this.findIntersectingChannel(rearTrackPos, sensors.get(1)));
+    		
+           if(debug)
+        	   System.out.println(this.getClass().getSimpleName() + ": Stereo hit was not found.");
+        }
+    }
+    
+    private int findMissingFitLayer(List<TrackerHit> trkHits){
+        int[] layer = new int[5];
+        for(TrackerHit trkHit : trkHits){
+            HelicalTrackHit stereoHit = (HelicalTrackHit) trkHit;
+            int arrayPosition = (stereoHit.Layer() - 1)/2;
+            layer[arrayPosition]++;
+        }
+        
+        for(int index = 0; index < layer.length; index++){
+            if(layer[index] == 0) return (2*index + 1);
+        }
+        
+        return -1;
+    }
+    
+    private boolean isWithinAcceptance(Track track, int layer){
+        
+        
+        
+        List<SiSensor> sensors = new ArrayList<SiSensor>();
+        if(TrackUtils.getZ0(track) > 0){
+           sensors.add(SvtUtils.getInstance().getTopSensor(layer, 0));
+           sensors.add(SvtUtils.getInstance().getTopSensor(layer + 1, 0));
+        } 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;
+        } 
+        
+        
+        return false;
+    }
+    
+    /**
+     * 
+     */
+    public int findIntersectingChannel(Hep3Vector trackPosition, SiSensor sensor){
+		
+    	//--- Check that the track doesn't pass through a region of bad channels ---//
+		//--------------------------------------------------------------------------//
+    
+		//Rotate the track position to the JLab coordinate system
+		this.printDebug("Track position in tracking frame: " + trackPosition.toString());
+		Hep3Vector trackPositionDet = VecOp.mult(VecOp.inverse(this.trackerHitUtils.detToTrackRotationMatrix()), trackPosition);
+		this.printDebug("Track position in JLab frame " + trackPositionDet.toString());
+		// Rotate the track to the sensor coordinates
+		ITransform3D globalToLocal = sensor.getReadoutElectrodes(ChargeCarrier.HOLE).getGlobalToLocal();
+		globalToLocal.transform(trackPositionDet);
+		this.printDebug("Track position in sensor electrodes frame " + trackPositionDet.toString());
+
+		// Find the closest channel to the track position
+		double deltaY = Double.MAX_VALUE;
+		int intersectingChannel = 0;
+		for(int physicalChannel= 0; physicalChannel < 639; physicalChannel++){ 
+			/*this.printDebug(SvtUtils.getInstance().getDescription(sensor) + " : Channel " + physicalChannel 
+                	+ " : Strip Position " + stripPositions.get(sensor).get(physicalChannel));
+        	this.printDebug(SvtUtils.getInstance().getDescription(sensor) + ": Channel " + physicalChannel
+                	+ " : Delta Y: " + Math.abs(trackPositionDet.x() - stripPositions.get(sensor).get(physicalChannel).x()));*/
+			if(Math.abs(trackPositionDet.x() - stripPositions.get(sensor).get(physicalChannel).x()) < deltaY ){
+				deltaY = Math.abs(trackPositionDet.x() - stripPositions.get(sensor).get(physicalChannel).x()); 
+				intersectingChannel = physicalChannel;
+			}
+		}
+    
+		this.printDebug(SvtUtils.getInstance().getDescription(sensor) + ": Track intersects physical channel " + intersectingChannel);
+		
+		return intersectingChannel;
+    }
+
+    /**
+     *
+     */
+    public boolean sensorContainsTrack(Hep3Vector trackPosition, SiSensor sensor){
+
+    	
+    	if(maskBadChannels){
+    		int intersectingChannel = this.findIntersectingChannel(trackPosition, sensor);
+    		if(intersectingChannel == 0 || intersectingChannel == 638) return false;
+    	    
+    		if(HPSSVTCalibrationConstants.isBadChannel(sensor, intersectingChannel) 
+    				|| HPSSVTCalibrationConstants.isBadChannel(sensor, intersectingChannel+1) 
+    				|| HPSSVTCalibrationConstants.isBadChannel(sensor, intersectingChannel-1)){
+    			this.printDebug("Track intersects a bad channel!");
+    			return false;
+    		}
+    	}
+        
+        ITransform3D localToGlobal = sensor.getGeometry().getLocalToGlobal();
+    	
+        Hep3Vector sensorPos = sensor.getGeometry().getPosition();   
+        Box sensorSolid = (Box) sensor.getGeometry().getLogicalVolume().getSolid();
+        Polygon3D sensorFace = sensorSolid.getFacesNormalTo(new BasicHep3Vector(0, 0, 1)).get(0);
+        if(debug){
+        	System.out.println(this.getClass().getSimpleName() + ": Sensor: " + SvtUtils.getInstance().getDescription(sensor));
+        	System.out.println(this.getClass().getSimpleName() + ": Track Position: " + trackPosition.toString());
+        }
+        
+        List<Point3D> vertices = new ArrayList<Point3D>();
+        for(int index = 0; index < 4; index++){
+        	vertices.add(new Point3D());
+        }
+        for(Point3D vertex : sensorFace.getVertices()){
+            if(vertex.y() < 0 && vertex.x() > 0){
+            	localToGlobal.transform(vertex);
+                //vertices.set(0, new Point3D(vertex.y() + sensorPos.x(), vertex.x() + sensorPos.y(), vertex.z() + sensorPos.z()));
+            	vertices.set(0, new Point3D(vertex.x(), vertex.y(), vertex.z()));
+                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());
+                }
+            } 
+            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() + ": 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() + ": 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() + ": 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()); 
+        
+        if((area1 > 0 && area2 > 0 && area3 > 0 && area4 > 0) || (area1 < 0 && area2 < 0 && area3 < 0 && area4 < 0)) return true;
+        return false;
+    } 
+
+    /**
+     *
+     */
+   public double findTriangleArea(double x0, double y0, double x1, double y1, double x2, double y2){
+       return .5*(x1*y2 - y1*x2 -x0*y2 + y0*x2 + x0*y1 - y0*x1); 
+    }
+   
+    @Override
+    public void endOfData(){
+        System.out.println("%===================================================================%");
+        System.out.println("%======================  Hit Efficiencies ==========================%");
+        System.out.println("%===================================================================% \n%");
+        if(numberOfTopTracks > 0){
+        	double topEfficiency = numberOfTopTracksWithHitOnMissingLayer/numberOfTopTracks;
+        	System.out.println("% Top Hit Efficiency: " + numberOfTopTracksWithHitOnMissingLayer + "/" + 
+        						numberOfTopTracks + " = " + topEfficiency*100 + "%");
+        	System.out.println("% Top Hit Efficiency Error: sigma poisson = " 
+        						+ topEfficiency*Math.sqrt((1/numberOfTopTracksWithHitOnMissingLayer) + (1/numberOfTopTracks))*100 + "%");
+        	System.out.println("% Top Hit Efficiency Error: sigma binomial = " 
+        						+ (1/numberOfTopTracks)*Math.sqrt(numberOfTopTracksWithHitOnMissingLayer*(1-topEfficiency))*100 + "%");
+        }
+        if(numberOfBottomTracks > 0){
+        	double bottomEfficiency = numberOfBottomTracksWithHitOnMissingLayer/numberOfBottomTracks;
+        	System.out.println("% Bottom Hit Efficiency: " + numberOfBottomTracksWithHitOnMissingLayer + "/" 
+        						+ numberOfBottomTracks + " = " + bottomEfficiency*100 + "%");
+        	System.out.println("% Bottom Hit Efficiency Error: sigma poisson= " 
+        						+ bottomEfficiency*Math.sqrt((1/numberOfBottomTracksWithHitOnMissingLayer) + (1/numberOfBottomTracks))*100 + "%");
+        	System.out.println("% Top Hit Efficiency Error: sigma binomial = " 
+								+ (1/numberOfBottomTracks)*Math.sqrt(numberOfBottomTracksWithHitOnMissingLayer*(1-bottomEfficiency))*100 + "%");
+        }
+/*        for(int index = 0; index < topTracksWithHitOnMissingLayer.length; index++){
+        	if(topTracksPerMissingLayer[index] > 0)
+        		System.out.println("% Top Layer " + (index+1) + ": " + (topTracksWithHitOnMissingLayer[index]/topTracksPerMissingLayer[index])*100 + "%");
+        }
+        for(int index = 0; index < bottomTracksWithHitOnMissingLayer.length; index++){
+        	if(bottomTracksPerMissingLayer[index] > 0)
+        		System.out.println("% Bottom Layer " + (index+1) + ": " + (bottomTracksWithHitOnMissingLayer[index]/bottomTracksPerMissingLayer[index])*100 + "%");
+        }*/
+        System.out.println("% \n%===================================================================%");
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
SvtPerformance.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtPerformance.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtPerformance.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,452 @@
+package org.lcsim.hps.users.omoreno;
+
+
+import hep.aida.IHistogram1D;
+import hep.aida.IPlotter;
+import hep.physics.vec.BasicHep3Vector;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lcsim.detector.tracker.silicon.HpsSiSensor;
+import org.lcsim.geometry.Detector;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+import org.lcsim.hps.recon.tracking.HPSSVTCalibrationConstants;
+import org.lcsim.hps.recon.tracking.HPSSVTCalibrationConstants.ChannelConstants;
+import org.lcsim.hps.recon.tracking.HPSShapeFitParameters;
+import org.lcsim.hps.recon.tracking.HPSShaperAnalyticFitAlgorithm;
+
+/**
+ * Driver that looks at the performance of the SVT.
+ * 
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id:$
+ */
+public class SvtPerformance extends Driver {
+
+    private AIDA aida;
+    private List<IPlotter> plotters = new ArrayList<IPlotter>();
+    HPSShaperAnalyticFitAlgorithm shaperFitter = new HPSShaperAnalyticFitAlgorithm();
+    
+    File performanceOutputFile;
+    BufferedWriter performanceWriter;
+    File samplesOutputFile; 
+    BufferedWriter samplesWriter; 
+
+    String performanceOutputFileName = "svt_performance.dat";
+    String samplesOutputFileName = "samples.dat";
+
+    int plotterIndex = 0;
+
+    int eventNumber = 0; 
+    int runNumber = 0; 
+    double totalTracks = 0;
+    double totalTwoTrackEvents = 0;
+
+    double[] topLayers;
+    double[] bottomLayers;
+
+    boolean debug = false;
+
+    // Collection Names
+    private String trackCollectionName = "MatchedTracks";
+
+    // Plot Flags
+    boolean plotClustersPerLayer = false;
+    boolean plotMIP = false;
+    boolean plotSamples = false; 
+    boolean batchMode = true; 
+    
+    public SvtPerformance(){
+    }
+
+    // --- Setters ---//
+    // ---------------//
+
+    /**
+     * Enable/disble debug mode
+     * 
+     * @param true or false
+     * 
+     */
+    public void setDebug(boolean debug){
+        this.debug = debug;
+    }
+
+    /**
+     * Enable/disable plotting the number of clusters per layer. Only clusters
+     * from stereo hits associated with a track are used.
+     * 
+     * @param true or false
+     * 
+     */
+    public void setPlotClustersPerLayer(boolean plotClustersPerLayer){
+        this.plotClustersPerLayer = plotClustersPerLayer;
+    }
+
+    /**
+     * Enable/disable plotting the cluster charge. Only clusters from stereo
+     * hits associated with a track are used.
+     * 
+     * @param true or false
+     * 
+     */
+    public void setPlotClusterCharge(boolean plotMIP){
+        this.plotMIP = plotMIP;
+    }
+
+    /**
+     * Enable/disable plotting of raw hit samples.  Only raw hits from clusters
+     * associated with a track are used.
+     * 
+     * @param true or false
+     * 
+     */
+    public void setPlotSamples(boolean plotSamples){
+        this.plotSamples = plotSamples; 
+    }
+    
+    /**
+     * Enable/disable batch mode.  If set to true, plots are not shown.
+     *
+     * @param true or false
+     * 
+     */
+    public void setBatchMode(boolean batchMode){
+    	this.batchMode = batchMode; 
+    }
+    
+    /**
+     * Set the name of the file to which performance data will be written.
+     * 
+     * @param peformanceOutputFileName: Name of the output file
+     * 
+     */
+    public void setPerformanceOutputFileName(String performanceOutputFileName){
+        this.performanceOutputFileName = performanceOutputFileName;
+    }
+
+    /**
+     * Set the name of the file to which raw sample data will be written.
+     * 
+     * @param samplesOutputFileName : Name of the output file
+     * 
+     */
+    public void setSamplesOutputFileName(String samplesOutputFileName){
+        this.samplesOutputFileName = samplesOutputFileName;
+    }
+    
+    /**
+     * Set the run number
+     * 
+     * @param runNumber 
+     * 
+     */
+    public void setRunNumber(int runNumber){
+    	this.runNumber = runNumber; 
+    }
+    
+    protected void detectorChanged(Detector detector) {
+
+        this.printDebug("Setting up plots");
+
+        // setup AIDA
+        aida = AIDA.defaultInstance();
+        aida.tree().cd("/");
+        
+        // Get the list of sensors from the detector
+        List<HpsSiSensor> sensors = detector.getDetectorElement().findDescendants(HpsSiSensor.class);
+
+        String plotTitle = null;
+        IHistogram1D histo1D = null;
+        int regionIndex = 0;
+
+        // --- Clusters Per Layer ---//
+        // --------------------------//
+
+        if(plotClustersPerLayer){
+            
+            if(!batchMode){
+                plotters.add(PlotUtils.setupPlotter("# Clusters Per Layer", 1, 2));
+                for (HpsSiSensor sensor : sensors) {
+                    if (sensor.isTopLayer()) {
+                        plotTitle = "Top - Layer " + sensor.getLayerNumber();
+                        regionIndex = 0;
+                    } else {
+                        plotTitle = "Bottom - Layer " + sensor.getLayerNumber();
+                        regionIndex = 1;
+                    }
+                    plotTitle += " - # Clusters";
+                    histo1D = aida.histogram1D(plotTitle, 9, 1, 10);
+                    PlotUtils.setup1DRegion(plotters.get(plotterIndex), plotTitle, regionIndex, "# Clusters", histo1D);
+                }
+                plotterIndex++;
+            }
+        }
+
+        // --- MIP Plots ---//
+        // -----------------//
+        if(plotMIP){
+
+            try {
+       
+                performanceOutputFile = new File(performanceOutputFileName);
+                if (!performanceOutputFile.exists()) performanceOutputFile.createNewFile();
+            
+                performanceWriter = new BufferedWriter(new FileWriter(performanceOutputFile.getAbsoluteFile()));
+        
+            } catch (IOException exception) {
+                exception.printStackTrace();
+            }
+            
+            try{ 
+
+                performanceWriter.write("! run I\n");
+                performanceWriter.write("! event I\n");
+                performanceWriter.write("! volume I\n");
+                performanceWriter.write("! layer I\n");
+                performanceWriter.write("! channel I\n");
+                performanceWriter.write("! amplitude D\n");
+                performanceWriter.write("! noise D\n");
+                performanceWriter.write("! cluster_hits I\n");
+                performanceWriter.write("! bad_channel I\n");
+                performanceWriter.write("! chi_squared D\n");
+                performanceWriter.write("! hit_x D\n");
+                performanceWriter.write("! hit_y D\n");
+                performanceWriter.write("! trk_chi_squared D\n");
+                performanceWriter.write("! hit_time D\n");
+                
+                
+            } catch(IOException exception){
+                exception.printStackTrace();
+            }
+           
+            if(!batchMode){
+                plotters.add(PlotUtils.setupPlotter("Cluster Charge", 5, 4));
+                for (HpsSiSensor sensor : sensors) {
+                    if (sensor.isTopLayer()) {
+                        plotTitle = "Top - Layer " + sensor.getLayerNumber();
+                    } else {
+                        plotTitle = "Bottom - Layer " + sensor.getLayerNumber();
+                    }
+                    plotTitle += " - Cluster Charge";
+                    histo1D = aida.histogram1D(plotTitle, 70, 0, 5040);
+                    PlotUtils.setup1DRegion(plotters.get(plotterIndex), plotTitle, PlotUtils.getPlotterRegion(sensor), "Cluster Charge [e-]", histo1D);
+                }
+                plotterIndex++;
+            }
+        }
+       
+        //--- Sample Plots ---//
+        //--------------------//
+        if(plotSamples){
+
+            try {
+                
+                samplesOutputFile = new File(samplesOutputFileName);
+                if (!samplesOutputFile.exists()) samplesOutputFile.createNewFile();
+            
+                samplesWriter = new BufferedWriter(new FileWriter(samplesOutputFile.getAbsoluteFile()));
+                
+            } catch (IOException exception) {
+                exception.printStackTrace();
+            }
+            
+            
+            try{
+                samplesWriter.write("! run I\n");
+                samplesWriter.write("! event I\n");
+                samplesWriter.write("! volume I\n");
+                samplesWriter.write("! layer I\n");
+                samplesWriter.write("! channel I\n");
+                samplesWriter.write("! sample1 I\n");
+                samplesWriter.write("! sample2 I\n");
+                samplesWriter.write("! sample3 I\n");
+                samplesWriter.write("! sample4 I\n");
+                samplesWriter.write("! sample5 I\n");
+                samplesWriter.write("! sample6 I\n");
+                samplesWriter.write("! pedestal D\n");
+                
+                
+            } catch(IOException exception){
+                
+            }
+           
+        }
+        
+        if(batchMode) return;
+        
+        // Show the plotters        
+        for (IPlotter plotter : plotters) plotter.show();
+
+    }
+
+    public void process(EventHeader event) {
+    	eventNumber++; 
+    	
+        if (!event.hasCollection(Track.class, trackCollectionName))
+            return;
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+
+        HpsSiSensor sensor = null;
+        String plotTitle = null;
+        int channel, bad_channel;
+        int maxClusterChannel = 0; 
+        int hitsPerCluster = 0;  
+        ChannelConstants constants = null;
+        HPSShapeFitParameters fit = null;
+        double clusterAmplitude, maxClusterAmplitude;
+        double noise = 0;
+        double chiSquared = -1;
+        double trkChiSquared = 0;
+        double hitTime = 0; 
+        double hitX, hitY, pedestal; 
+        short[] samples; 
+
+        // Loop over all tracks in an event
+        for (Track track : tracks) {
+        	trkChiSquared = 0; 
+        	trkChiSquared = track.getChi2(); 
+        
+        	if((new BasicHep3Vector(track.getTrackStates().get(0).getMomentum())).magnitude() <= .500) continue;
+            
+        	double[] topClusters = new double[10];
+            double[] bottomClusters = new double[10];
+            // Loop over all stereo hits associated with a track
+            hitX = 0; hitY = 0; 
+            for (TrackerHit trackerHit : track.getTrackerHits()) {
+          	
+            	hitX = trackerHit.getPosition()[1];
+            	hitY = trackerHit.getPosition()[2];
+            	
+                // Loop over the strip hits used to crate the stereo hit
+            	hitTime = 0; 
+                for (HelicalTrackStrip stripHit : ((HelicalTrackCross) trackerHit).getStrips()) {
+                	
+                	hitTime = stripHit.time(); 
+                	
+                    sensor = (HpsSiSensor) ((RawTrackerHit) stripHit.rawhits().get(0)).getDetectorElement();
+                    if (sensor.isTopLayer())
+                        topClusters[sensor.getLayerNumber() - 1] += 1;
+                    else
+                        bottomClusters[sensor.getLayerNumber() - 1] += 1;
+
+                    maxClusterAmplitude = 0;
+                    clusterAmplitude = 0;
+                    hitsPerCluster = stripHit.rawhits().size();
+                    noise = 0;
+                    bad_channel = 0;
+                    chiSquared = -1;
+                    for (Object rh : stripHit.rawhits()) {
+
+                        RawTrackerHit rawHit = (RawTrackerHit) rh;
+                        channel = rawHit.getIdentifierFieldValue("strip");
+                        // Check if the channel neighbors a channel that has been tagged as bad
+                        if(HPSSVTCalibrationConstants.isBadChannel(sensor, channel+1) 
+                        		|| HPSSVTCalibrationConstants.isBadChannel(sensor, channel-1)){
+                        	bad_channel = 1; 
+                        }
+                        
+                        if(plotSamples){
+                            samples = rawHit.getADCValues();
+                            pedestal = sensor.getPedestal(channel);
+                            
+                            try {
+                                if(sensor.isTopLayer()){
+                                    samplesWriter.write(runNumber + " " + eventNumber + " 0 " + sensor.getLayerNumber() + " ");
+                                } else {
+                                    samplesWriter.write(runNumber + " " + eventNumber + " 1 " + sensor.getLayerNumber() + " ");
+                                }
+                                samplesWriter.write(channel + " " + samples[0] + " " + samples[1] + " " + samples[2] + " "
+                                                    + samples[3] + " " + samples[4] + " " + samples[5] +  " " + pedestal + "\n");
+                            } catch (IOException exception) {
+                                exception.printStackTrace();
+                            }
+                        }
+                        
+                        constants = HPSSVTCalibrationConstants.getChannelConstants(sensor, channel);
+                        fit = shaperFitter.fitShape(rawHit, constants);
+                        if (fit.getAmp() > maxClusterAmplitude) {
+                            maxClusterChannel = channel;
+                            maxClusterAmplitude = fit.getAmp();
+                        }
+                        if(stripHit.rawhits().size() == 1){
+                        	chiSquared = fit.getChiSq();
+                        }
+                        noise += Math.pow(sensor.getNoise(channel), 2);
+                        clusterAmplitude += fit.getAmp();
+                    }
+
+                    noise = Math.sqrt(noise);
+                    
+                    if (plotMIP) {
+                        try {
+                            if (sensor.isTopLayer()) {
+                                plotTitle = "Top - Layer " + sensor.getLayerNumber() + " - Cluster Charge";
+                                performanceWriter.write(runNumber + " " + eventNumber + " 0 " + sensor.getLayerNumber() + " ");
+                            } else {
+                                plotTitle = "Bottom - Layer " + sensor.getLayerNumber() + " - Cluster Charge";
+                                performanceWriter.write(runNumber + " " + eventNumber + " 1 " + sensor.getLayerNumber() + " ");
+                            }
+                                performanceWriter.write(maxClusterChannel + " " + clusterAmplitude + " " + noise + " " + hitsPerCluster + " " 
+                                			 + bad_channel + " " + chiSquared + " " + hitX + " " + hitY + " " + trkChiSquared + " "
+                                			 + hitTime + "\n");
+                        } catch (IOException exception) {
+                        	exception.printStackTrace(); 
+                        }
+                        if(!batchMode){
+                            aida.histogram1D(plotTitle).fill(clusterAmplitude);
+                        }
+                    }
+                }
+
+                // Fill the cluster histograms
+                if (plotClustersPerLayer) {
+                    for (int layerN = 1; layerN <= 10; layerN++) {
+                        if (topClusters[layerN - 1] > 0) {
+                            plotTitle = "Top - Layer " + layerN + " - # Clusters";
+                            aida.histogram1D(plotTitle).fill(topClusters[layerN - 1]);
+                        }
+                        if (bottomClusters[layerN - 1] > 0) {
+                            plotTitle = "Bottom - Layer " + layerN + " - # Clusters";
+                            aida.histogram1D(plotTitle).fill(bottomClusters[layerN - 1]);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * print debug statements
+     */
+    public void printDebug(String debugStatement) {
+        if (!debug)
+            return;
+        System.out.println(this.getClass().getSimpleName() + ": " + debugStatement);
+    }
+
+    @Override
+    public void endOfData() {
+
+        try {
+            performanceWriter.close();
+            samplesWriter.close(); 
+        } catch (IOException exception) {
+            exception.printStackTrace();
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
SvtQA.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtQA.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtQA.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,875 @@
+package org.lcsim.hps.users.omoreno;
+
+//--- HEP ---//
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IPlotter;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+//--- Java ---//
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+//--- lcsim ---//
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+//--- hps-java ---//
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.tracking.HPSFittedRawTrackerHit;
+import org.lcsim.hps.recon.tracking.HPSSVTCalibrationConstants;
+import org.lcsim.hps.recon.tracking.HPSSVTCalibrationConstants.ChannelConstants;
+import org.lcsim.hps.recon.tracking.HPSShapeFitParameters;
+import org.lcsim.hps.recon.tracking.HPSShaperAnalyticFitAlgorithm;
+import org.lcsim.hps.recon.tracking.SvtUtils;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.hps.util.Pair;
+import org.lcsim.hps.recon.tracking.apv25.SvtReadout;
+
+
+//--- Constants ---//
+import static org.lcsim.hps.recon.tracking.HPSSVTConstants.TOTAL_STRIPS_PER_SENSOR;
+
+/**
+ * SVT Quality Assurance Driver
+ *  
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: SvtQA.java,v 1.7 2013/10/25 19:45:01 jeremy Exp $
+ */
+public class SvtQA extends Driver {
+
+    private AIDA aida;
+    private HPSShaperAnalyticFitAlgorithm shaperFitter = new HPSShaperAnalyticFitAlgorithm();
+    private List<AIDAFrame>    frames   = new ArrayList<AIDAFrame>();
+    private List<IHistogram1D> histos1D = new ArrayList<IHistogram1D>();
+    private List<IHistogram2D> histos2D = new ArrayList<IHistogram2D>();
+    private List<IPlotter>     plotters = new ArrayList<IPlotter>();
+    private Map<String, double[]> sensorToOccupancy = new HashMap<String, double[]>();
+    private Map<String, double[]> sensorToStereoOccupancy = new HashMap<String, double[]>();
+    BufferedWriter output = null;
+
+    String outputFile = null;
+    String sensorName = null;
+
+    int channelNumber = 0;
+    int plotterIndex = 0;
+    int apvNumber = 0;	
+    double totalNumberEvents = 0;
+    double totalNumberOfRawHitEvents = 0;
+    double[] totalTopSamples = new double[6];
+    double[] totalBottomSamples = new double[6];
+    double[] topSamples = new double[6];
+    double[] bottomSamples = new double[6];
+    double totalNumberOfHits = 0;
+    
+    double maxOccupancy = 1.0;
+    double maxOccupancyVariation = 1000; // %
+
+    boolean verbose = false;
+    boolean simulation = false;
+
+    // Plot flags
+    boolean enableADCvsChannel = false;
+    boolean enableOccupancy    = false;
+    boolean enableStereoHitOccupancy = false;
+    boolean enableChannelPlots = false;
+    boolean enableAPVPlots     = false;
+    boolean enableChiSquaredvsChannel = false;
+    boolean enableSamples = false;
+    boolean enableT0Plots = false;
+    boolean enableTotalNumberOfHitsPlots = false;
+
+    // Collection Names
+    private String trackCollectionName = "MatchedTracks";
+    private String rawHitCollectionName = "SVTRawTrackerHits";
+    private String stereoHitCollectionName = "RotatedHelicalTrackHits";
+    private String fittedHitCollectionName = "SVTFittedRawTrackerHits";
+
+    /**
+     * Default Ctor
+     */
+    public SvtQA(){
+    }
+
+    //--- Setters ---//
+    //---------------//
+    /**
+     * Enable/disable occupancy plots
+     */
+    public void setEnableOccupancyPlots(boolean enableOccupancy){
+        this.enableOccupancy = enableOccupancy;
+    }
+
+    /**
+     * Enable/disable stereo hit occupancy plots
+     */
+    public void setEnableStereoHitOccupancyPlots(boolean enableStereoHitOccupancy){
+        this.enableStereoHitOccupancy = enableStereoHitOccupancy;
+    }
+
+    /**
+     * Enable/disable ADC counts vs Channel plots 
+     */
+    public void setEnableADCvsChannelPlots(boolean enableADCvsChannel){
+        this.enableADCvsChannel = enableADCvsChannel;
+    }
+
+    /**
+     * Enable/disable Channel Plots
+     */
+    public void setEnableChannelPlots(boolean enableChannelPlots){
+        this.enableChannelPlots = enableChannelPlots;
+    }
+
+    /**
+     * Enable/disable plots associated with individual APVs 
+     */
+    public void setEnableAPVPlots(boolean enableAPVPlots){
+        this.enableAPVPlots = enableAPVPlots;
+    }
+
+    /**
+     * Enable/disable Chi Squared of fit to samples vs Channel plots 
+     */
+    public void setEnableChiSquaredvsChannelPlots(boolean enableChiSquaredvsChannel){
+        this.enableChiSquaredvsChannel = enableChiSquaredvsChannel;
+    }
+
+    /**
+     * Enable/disable plots of the APV samples
+     */
+    public void setEnableSamplesPlots(boolean enableSamples){
+        this.enableSamples = enableSamples;
+    }
+
+    /**
+     * Enable/disable t0 plots 
+     */
+    public void setEnableT0Plots(boolean enableT0Plots){
+        this.enableT0Plots = enableT0Plots;
+    }
+
+    /**
+     * Set the channel number of interest 
+     */
+    public void setChannelNumber(int channelNumber){
+        this.channelNumber = channelNumber;
+    }
+
+    /**
+     * Set the sensor of interest 
+     */
+    public void setSensorName(String sensorName){
+        this.sensorName = sensorName;
+    }
+
+    /**
+     * Set the APV number of interest
+     */
+    public void setApvNumber(int apvNumber){
+        this.apvNumber = apvNumber;
+    }
+
+    /**
+     * Set the maximum occupancy a channel may have    
+     */
+    public void setMaxOccupancy(double maxOccupancy){
+        this.maxOccupancy = maxOccupancy;
+    }
+
+    /**
+     * Set the maximum channel to channel occupancy variation
+     */
+    public void setMaxOccupancyVariation(double maxOccupancyVariation){
+        this.maxOccupancyVariation = maxOccupancyVariation;
+    }
+
+    /**
+     * 
+     */
+    public void setOutputFileName(String outputFile){
+        this.outputFile = outputFile;
+    }
+
+    /**
+     *
+     */
+    public void setVerbose(boolean verbose){
+        this.verbose = verbose;
+    }
+
+    /**
+     *
+     */
+    public void setSimulation(boolean simulation){
+        this.simulation = simulation;
+    }
+    
+    /**
+     * 
+     */
+    public void setEnableTotalNumberOfHitsPlots(boolean enableTotalNumberOfHitsPlots){
+    	this.enableTotalNumberOfHitsPlots = enableTotalNumberOfHitsPlots;
+    }
+
+    /**
+     * 
+     */
+    private int getAPVNumber(int physicalChannel){
+        int apv = (int) Math.floor((physicalChannel - TOTAL_STRIPS_PER_SENSOR)/-128);
+        if(apv > 4 || apv < 0) throw new RuntimeException("Invalid APV Number: " + apv );
+        return apv;
+    }  
+
+    protected void detectorChanged(Detector detector){
+        super.detectorChanged(detector);
+
+        // setup AIDA
+        aida = AIDA.defaultInstance();
+        aida.tree().cd("/");
+
+        // Create AIDA Frames
+        for(int index = 0; index < 2; index++) frames.add(new AIDAFrame());
+
+        // Set frame titles
+        frames.get(0).setTitle("Occupancy");
+        frames.get(1).setTitle("ADC Counts");
+
+        //
+        Set<SiSensor> sensors = SvtUtils.getInstance().getSensors();
+        int plotterIndex = 0;
+        IHistogram1D histo1D = null;
+        IHistogram2D histo2D = null;
+        String title = null;
+
+        //--- Occupancy ---//
+        //-----------------//
+        if(enableOccupancy){
+            plotters.add(PlotUtils.setupPlotter("Occupancy", 5, 4));
+            for(SiSensor sensor : sensors){
+                sensorToOccupancy.put(SvtUtils.getInstance().getDescription(sensor), new double[640]);
+                title = SvtUtils.getInstance().getDescription(sensor) + " - Occupancy";
+                histo1D = aida.histogram1D(title, 640, 0, 639);
+                histos1D.add(histo1D);
+                PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, PlotUtils.getPlotterRegion(sensor), "Channel #", histo1D);
+            }
+            frames.get(0).addPlotter(plotters.get(plotterIndex));
+            plotterIndex++;
+        }
+
+        //--- Stereo Hit Occupancy ---//
+        //----------------------------//
+        if(enableStereoHitOccupancy){
+            plotters.add(PlotUtils.setupPlotter("Stereo Hit Occupancy", 5, 4));
+            for(SiSensor sensor : sensors){
+                sensorToStereoOccupancy.put(SvtUtils.getInstance().getDescription(sensor), new double[640]);
+                title = SvtUtils.getInstance().getDescription(sensor) + " - Stereo Hit Occupancy";
+                histo1D = aida.histogram1D(title, 640, 0, 639);
+                histos1D.add(histo1D);
+                PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, PlotUtils.getPlotterRegion(sensor), "Channel #", histo1D);
+            }
+            frames.get(0).addPlotter(plotters.get(plotterIndex));
+            plotterIndex++;
+        }
+
+        //--- ADC Counts vs Channel ---//
+        //-----------------------------//
+        if(enableADCvsChannel){
+            if(sensorName.equals("all")){
+                plotters.add(PlotUtils.setupPlotter("ADC Counts vs Channel #", 5, 4));
+                for(SiSensor sensor : sensors){
+                    title = SvtUtils.getInstance().getDescription(sensor) + " - ADC Counts vs Channel #";
+                    histo2D = aida.histogram2D(title, 640, 0, 639, 300, 0, 10000);
+                    histos2D.add(histo2D);
+                    PlotUtils.setup2DRegion(plotters.get(plotterIndex), title, PlotUtils.getPlotterRegion(sensor), "Channel #", "ADC Counts", histo2D);
+                }
+                frames.get(1).addPlotter(plotters.get(plotterIndex));
+                plotterIndex++;
+            } else if(sensorName != null){
+                title = sensorName + " - ADC Counts vs Channel #";
+                plotters.add(PlotUtils.setupPlotter(title, 0, 0));
+                histo2D = aida.histogram2D(title, 640, 0, 639, 300, 0, 10000);
+                histos2D.add(histo2D);
+                PlotUtils.setup2DRegion(plotters.get(plotterIndex), title, 0, "Channel #", "ADC Counts", histo2D);
+                frames.get(1).addPlotter(plotters.get(plotterIndex));
+                plotterIndex++;
+            } else {
+                throw new RuntimeException("Sensor of interest is not set!");
+            }
+        }
+
+        //--- Chi Squared vs Channel ---//
+        //------------------------------//
+        if(enableChiSquaredvsChannel){
+            title = sensorName + " - Chi Squared vs Channel #";
+            plotters.add(PlotUtils.setupPlotter(title, 0, 0));
+            histo2D = aida.histogram2D(title, 640, 0, 639, 300, 0, 100);
+            histos2D.add(histo2D);
+            PlotUtils.setup2DRegion(plotters.get(plotterIndex), title, 0, "Channel #", "Chi Squared", histo2D);
+            frames.get(1).addPlotter(plotters.get(plotterIndex));
+            plotterIndex++;
+        }
+
+
+        //--- Single Channel Plots ---//
+        //----------------------------//
+        if(enableChannelPlots){
+            if(sensorName == null) throw new RuntimeException("Sensor of interest is not set!");
+            title = sensorName + " - Channel: " + channelNumber;
+            plotters.add(PlotUtils.setupPlotter(title, 2, 2));
+            title = "ADC Counts";
+            histo1D = aida.histogram1D(title, 300, 4000, 7000);
+            histos1D.add(histo1D);
+            PlotUtils.setup1DRegion(plotters.get(plotterIndex),title , 0, "ADC Counts", histo1D);
+            title = "Shaper Signal Amplitude";
+            histo1D = aida.histogram1D(title, 300, 0, 3000);
+            histos1D.add(histo1D);
+            PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 1, "Amplitude [ADC Counts]", histo1D);
+            title = "t0";
+            histo1D = aida.histogram1D(title, 100, -150, 100);
+            histos1D.add(histo1D);
+            PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 2, "t0 [ns]", histo1D);
+            frames.get(1).addPlotter(plotters.get(plotterIndex));
+            plotterIndex++;
+        }
+
+        //--- APV Plots ---//
+        //-----------------//
+        if(enableAPVPlots){
+            if(sensorName == null) throw new RuntimeException("Sensor of interest is not set!");
+            title = sensorName + " - APV " + apvNumber;
+            plotters.add(PlotUtils.setupPlotter(title, 2, 2));
+            title = "APV " + apvNumber + " - ADC Counts";
+            histo1D = aida.histogram1D(title, 400, 0, 10000);
+            histos1D.add(histo1D);
+            PlotUtils.setup1DRegion(plotters.get(plotterIndex),title , 0, "ADC Counts", histo1D);
+            title = "APV " + apvNumber + " - Shaper Signal Amplitude";
+            histo1D = aida.histogram1D(title, 300, 0, 6000);
+            histos1D.add(histo1D);
+            PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 1, "Amplitude [ADC Counts]", histo1D);
+            title = "APV " + apvNumber + " - t0";
+            histo1D = aida.histogram1D(title, 100, -100, 100);
+            histos1D.add(histo1D);
+            PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 2, "t0 [ns]", histo1D);
+            title = "APV " + apvNumber + " - Amplitude vs t0";
+            histo2D = aida.histogram2D(title, 300, 0, 6000, 100, -100, 100);
+            histos2D.add(histo2D);
+            PlotUtils.setup2DRegion(plotters.get(plotterIndex), title, 3, "Amplitude [ADC Counts]", "t0 [ns]", histo2D);
+            frames.get(1).addPlotter(plotters.get(plotterIndex));
+            plotterIndex++;   
+        }
+
+        //--- Samples Amplitude vs Sample Number ---//
+        //------------------------------------------//
+        if(enableSamples){
+            title = "APV Sample Number vs Sample Amplitude";
+            plotters.add(PlotUtils.setupPlotter(title, 1, 2));
+            plotters.get(plotterIndex).style().zAxisStyle().setParameter("scale", "log");
+            title = "APV Sample Number vs Sample Amplitude - Top";
+            histo2D = aida.histogram2D(title, 6, 1, 7, 400, 0, 4000);
+            histos2D.add(histo2D);
+            PlotUtils.setup2DRegion(plotters.get(plotterIndex), title, 0, "Sample Number", "Amplitude [ADC Counts]", histo2D);
+            title = "APV Sample Number vs Sample Amplitude - Bottom";
+            histo2D = aida.histogram2D(title, 6, 1, 7, 400, 0, 4000);
+            histos2D.add(histo2D);
+            PlotUtils.setup2DRegion(plotters.get(plotterIndex), title, 1, "Sample Number", "Amplitude [ADC Counts]", histo2D);
+            frames.get(1).addPlotter(plotters.get(plotterIndex));
+            plotterIndex++;
+        }
+
+        //--- t0 Plots ---//
+        //----------------//
+        if(enableT0Plots){
+            if(sensorName.equals("all")){
+                plotters.add(PlotUtils.setupPlotter("t0 Resolution vs Channel #", 5, 4));
+                plotters.get(plotterIndex).style().zAxisStyle().setParameter("scale", "log");
+                for(SiSensor sensor : sensors){
+                    title = SvtUtils.getInstance().getDescription(sensor) + " - t0 Resolution vs Channel #";
+                    histo2D = aida.histogram2D(title, 640, 0, 639, 40, -20, 20);
+                    histos2D.add(histo2D);
+                    PlotUtils.setup2DRegion(plotters.get(plotterIndex), title, PlotUtils.getPlotterRegion(sensor), "Channel #", "t0 Resolution [ns]", histo2D);
+                }
+                frames.get(1).addPlotter(plotters.get(plotterIndex));
+                plotterIndex++;
+            }
+            else if(sensorName != null){
+                title = sensorName + " - Hit Time Resolution";
+                plotters.add(PlotUtils.setupPlotter(title, 0, 0));
+                plotters.get(plotterIndex).style().statisticsBoxStyle().setVisible(true);
+                histo1D = aida.histogram1D(title, 40, -20, 20);
+                histos1D.add(histo1D);
+                PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 0, "<Hit Time> - Hit Time [ns]", histo1D);
+                frames.get(1).addPlotter(plotters.get(plotterIndex));
+                plotterIndex++;
+            }
+            else throw new RuntimeException("Sensor of interest not set!");
+
+        }
+        
+        if(enableTotalNumberOfHitsPlots){
+        	title = "Total Number of RawTrackerHits";
+        	plotters.add(PlotUtils.setupPlotter(title, 0, 0));
+        	plotters.get(plotterIndex).style().statisticsBoxStyle().setVisible(true);
+        	histo1D = aida.histogram1D(title, 100, 0, 75);
+        	histos1D.add(histo1D);
+        	PlotUtils.setup1DRegion(plotters.get(plotterIndex), title, 0, "Number of RawTrackerHits", histo1D);
+        	frames.get(1).addPlotter(plotters.get(plotterIndex));
+        	plotterIndex++;
+        }
+
+        for(AIDAFrame frame : frames){
+            frame.pack();
+            frame.setVisible(true);
+        }
+    }
+
+    /**
+     * 
+     */
+    public int findPeakSamples(short[] samples){
+        int maxSample = 0;
+        int maxSampleIndex = 0;
+        for(int index = 0; index < samples.length; index++){
+            if(maxSample < samples[index]){
+                maxSample = samples[index];
+                maxSampleIndex = index;
+            }
+        }
+        return maxSampleIndex;
+    }
+
+
+
+    public void process(EventHeader event){
+
+        totalNumberEvents++;
+        String title;
+
+        // If the event doesn't contain RawTrackerHits then skip it
+        if(!event.hasCollection(RawTrackerHit.class, rawHitCollectionName )){
+            if(verbose) System.out.println("Event doesn't contain RawTrackerHits! Skipping event ...");
+            return;
+        }
+
+        // Get the RawTrackerHits from the event
+        List<RawTrackerHit> rawHits = event.get(RawTrackerHit.class, rawHitCollectionName);
+        
+        // Get the total number of RawTrackerHits in the event
+        if(enableTotalNumberOfHitsPlots && rawHits.size() != 0){
+            aida.histogram1D("Total Number of RawTrackerHits").fill(rawHits.size());
+        }
+
+        SiSensor sensor = null;
+        ChannelConstants constants = null;
+        HPSShapeFitParameters fit = null;
+        for(RawTrackerHit rawHit : rawHits){
+
+            // Get the sensor on which this hit occurred
+            sensor = (SiSensor) rawHit.getDetectorElement();
+
+            // Get the shaper signal samples
+            short[] samples = rawHit.getADCValues();
+
+            // Get the channel number
+            int channel = rawHit.getIdentifierFieldValue("strip");
+
+            // Get the APV number
+            int apv = this.getAPVNumber(channel);
+
+            // Get the constants associated with this channel
+            constants = HPSSVTCalibrationConstants.getChannelConstants(sensor, channel);
+
+            // Fit the samples associated with the RawTrackerHit
+            fit = shaperFitter.fitShape(rawHit, constants);
+
+            // Fill the occupancy plots
+            if(enableOccupancy){
+                title = SvtUtils.getInstance().getDescription(sensor) + " - Occupancy";
+                aida.histogram1D(title).fill(channel, 1);
+            }
+
+            // Fill ADC vs Channel # plots
+            if(enableADCvsChannel && sensorName.equals("all")){
+                title = SvtUtils.getInstance().getDescription(sensor) + " - ADC Counts vs Channel #";
+                for(short sample : samples){
+                    aida.histogram2D(title).fill(channel, sample);
+                }
+            } else if(enableADCvsChannel && SvtUtils.getInstance().getDescription(sensor).equals(sensorName)){
+                title = sensorName + " - ADC Counts vs Channel #";
+                for(short sample : samples){
+                    aida.histogram2D(title).fill(channel, sample);
+                }
+            }
+
+            // 
+            if(enableChannelPlots && SvtUtils.getInstance().getDescription(sensor).equals(sensorName) && channel == channelNumber){
+                title = "ADC Counts";
+                for(short sample : samples){
+                    aida.histogram1D(title).fill(sample);
+                }
+                title = "Shaper Signal Amplitude";
+                aida.histogram1D(title).fill(fit.getAmp());	    
+                System.out.println("Amplitude: " + fit.getAmp());
+                title="t0";
+                aida.histogram1D(title).fill(fit.getT0());
+                System.out.println("t0 " + fit.getT0());
+            }
+
+            if(enableAPVPlots && SvtUtils.getInstance().getDescription(sensor).equals(sensorName) && apv == apvNumber ){
+                title = "APV " + apvNumber + " - ADC Counts";
+                for(short sample : samples){
+                    aida.histogram1D(title).fill(sample);
+                }
+                title = "APV " + apvNumber + " - Shaper Signal Amplitude";
+                aida.histogram1D(title).fill(fit.getAmp());     
+                title = "APV " + apvNumber + " - t0";
+                aida.histogram1D(title).fill(fit.getT0());
+                title = "APV " + apvNumber + " - Amplitude vs t0";
+                aida.histogram2D(title).fill(fit.getAmp(), fit.getT0());
+            }
+        }
+
+        /*
+        if(enableOccupancy){
+            for(SiSensor sensor : SvtUtils.getInstance().getSensors()){
+                title = SvtUtils.getInstance().getDescription(sensor) + " - Occupancy";
+                aida.histogram1D(title).reset();
+                int nEvents = simulation ? SvtReadout.getNumberOfTriggers()  : totalNumberEvents; 
+                for(int index = 0; index < 640; index++){
+                    aida.histogram1D(title).fill(index, sensorToOccupancy.get(SvtUtils.getInstance().getDescription(sensor))[index]/nEvents);
+                }
+            }
+        }*/
+
+        // If the event doesn't contain FittedRawTrackerHits then skip it
+        if(!event.hasCollection(HPSFittedRawTrackerHit.class, fittedHitCollectionName)){
+            if(verbose) System.out.println("Event doesn't contain FittedRawTrackerHits! Skipping event ...");
+            return;
+        }
+
+        // Get the RawTrackerHits from the event
+        List<HPSFittedRawTrackerHit> fittedHits = event.get(HPSFittedRawTrackerHit.class, fittedHitCollectionName);
+        
+        //System.out.println(this.getClass().getSimpleName() + ": Number of FittedRawTrackerHits " + fittedHits.size());
+
+        for(HPSFittedRawTrackerHit fittedHit : fittedHits){
+
+
+            // Get the channel number
+            int channel = fittedHit.getRawTrackerHit().getIdentifierFieldValue("strip");
+
+            // Get the sensor number 
+            sensor = (SiSensor) fittedHit.getRawTrackerHit().getDetectorElement();
+
+            // Fill Chi Squared vs Channel # plots
+            if(enableChiSquaredvsChannel && SvtUtils.getInstance().getDescription(sensor).equals(sensorName)){
+                title = sensorName + " - Chi Squared vs Channel #";
+                aida.histogram2D(title).fill(channel, fittedHit.getShapeFitParameters().getChiSq());
+            }
+        }
+
+        // If the event does not contain stereo hits, skip the event
+        if(!event.hasCollection(HelicalTrackHit.class, stereoHitCollectionName)){
+            if(verbose) System.out.println("Event doesn't contain HelicalTrackHits! Skipping event ...");
+            return;
+        }
+
+        // Get the list of HelicalTrackHits
+        List<HelicalTrackHit> stereoHits =event.get(HelicalTrackHit.class, stereoHitCollectionName); 
+
+        for(HelicalTrackHit stereoHit : stereoHits){
+
+            double totalT0 = 0;
+
+            for(Object hit : stereoHit.getRawHits()){
+
+                RawTrackerHit rawHit = (RawTrackerHit) hit;
+
+                sensor = (SiSensor) rawHit.getDetectorElement();
+
+                // Get the channel number
+                int channel = rawHit.getIdentifierFieldValue("strip");
+
+                // Get the constants associated with this channel
+                constants = HPSSVTCalibrationConstants.getChannelConstants(sensor, channel);
+
+                // Fit the samples associated with the RawTrackerHit
+                fit = shaperFitter.fitShape(rawHit, constants);
+
+                // Get the shaper signal samples
+                short[] samples = rawHit.getADCValues();
+
+                if(enableStereoHitOccupancy){
+                    title = SvtUtils.getInstance().getDescription(sensor) + " - Stereo Hit Occupancy";
+                    sensorToStereoOccupancy.get(SvtUtils.getInstance().getDescription(sensor))[channel] += 1;
+                }
+
+                // Fill Sample Plots
+                if(enableSamples){
+                    if(fit.getAmp() > 2000 && fit.getAmp() < 6000){
+                        for(int sampleN = 1; sampleN <= samples.length; sampleN++){
+                            if((sampleN == 1 && totalNumberEvents%5 != 0) || (sampleN == 2 && totalNumberEvents%5 != 0)/* || (sampleN == 3 && totalNumberEvents%3 != 0) */) continue;
+                            if(SvtUtils.getInstance().isTopLayer(sensor)){
+                                aida.histogram2D("APV Sample Number vs Sample Amplitude - Top").fill(sampleN, samples[sampleN-1] - constants.getPedestal());
+                                totalTopSamples[sampleN-1]++;
+                                topSamples[sampleN-1] += samples[sampleN-1] - constants.getPedestal();
+                            }
+                            else{
+                            	aida.histogram2D("APV Sample Number vs Sample Amplitude - Bottom").fill(sampleN, samples[sampleN-1] - constants.getPedestal());
+                            	totalBottomSamples[sampleN-1]++;
+                            	bottomSamples[sampleN-1] += samples[sampleN - 1] - constants.getPedestal();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        /*
+        if(enableStereoHitOccupancy){
+            for(SiSensor sensor : SvtUtils.getInstance().getSensors()){
+                title = SvtUtils.getInstance().getDescription(sensor) + " - Stereo Hit Occupancy";
+                aida.histogram1D(title).reset();
+                for(int index = 0; index < 640; index++){
+                    aida.histogram1D(title).fill(index, sensorToStereoOccupancy.get(SvtUtils.getInstance().getDescription(sensor))[index]/event.getEventNumber());
+                }
+            }
+        }*/
+        if(!event.hasCollection(Track.class, trackCollectionName)) return;
+        
+        // Get the list of tracks in the event
+        List<SeedTrack> tracks = event.get(SeedTrack.class, trackCollectionName);
+
+        if(enableT0Plots){
+
+            // Loop over all tracks in the event
+            for(Track track : tracks){
+
+
+                double totalT0 = 0;
+                double totalHits = 0;
+
+                // Loop over all stereo hits comprising a track
+                for(TrackerHit crossHit : track.getTrackerHits()){
+
+                    HelicalTrackCross htc = (HelicalTrackCross) crossHit;
+
+                    for(HelicalTrackStrip hts : htc.getStrips()){
+
+                        totalT0 += hts.time();
+                        totalHits++;
+                    }
+                }
+
+                double meanT0 = totalT0/totalHits;
+
+                for(TrackerHit crossHit : track.getTrackerHits()){
+
+                    HelicalTrackCross htc = (HelicalTrackCross) crossHit;
+
+                    for(HelicalTrackStrip hts : htc.getStrips()){
+
+                        //SiSensor sensor = null;
+                        if(TrackUtils.getZ0(track) > 0){
+                            sensor = SvtUtils.getInstance().getSensor(0, hts.layer() - 1);
+                        } else if(TrackUtils.getZ0(track) < 0){
+                            sensor = SvtUtils.getInstance().getSensor(1, hts.layer() - 1);
+                        }
+
+                        int channel = ((RawTrackerHit) hts.rawhits().get(0)).getIdentifierFieldValue("strip");
+                        
+                        if(sensorName.equals("all")){
+                        	aida.histogram2D(SvtUtils.getInstance().getDescription(sensor) + " - t0 Resolution vs Channel #").fill(channel, meanT0 - hts.time());
+                        } else {
+                        if(SvtUtils.getInstance().getDescription(sensor).equals(sensorName)){
+                            aida.histogram1D(sensorName + " - Hit Time Resolution").fill(meanT0 - hts.time());
+                        }
+                        
+                        } 
+                    }
+                }
+            }
+        }
+
+    }
+
+    @Override
+        public void endOfData(){
+    		String title;
+    		
+
+    		
+            String plotName;
+    		if(enableOccupancy){
+    			for(SiSensor sensor : SvtUtils.getInstance().getSensors()){
+    				title = SvtUtils.getInstance().getDescription(sensor) + " - Occupancy";
+    				// Scale the hits per channel by the number of events
+    				aida.histogram1D(title).scale(1/totalNumberEvents);
+    				
+    				// Write the occupancies to a file
+    				if(SvtUtils.getInstance().isTopLayer(sensor)){
+    					plotName = outputFile + "_top_";
+    				} else { 
+    					plotName = outputFile + "_bottom_";
+    				}
+    				
+					if(SvtUtils.getInstance().getLayerNumber(sensor) < 10){
+						plotName += "0" + SvtUtils.getInstance().getLayerNumber(sensor) + ".dat";
+					} else {
+						plotName += SvtUtils.getInstance().getLayerNumber(sensor) + ".dat";
+					}
+    			
+	    			// Open the output files stream
+	                if(plotName != null){
+	                	try{
+	                		output = new BufferedWriter(new FileWriter(plotName)); 
+                			for(int channel = 0; channel < 640; channel++){
+                				output.write(channel + " " + aida.histogram1D(title).binHeight(channel) + "\n");
+                			}
+                			output.close();
+	                	} catch(Exception e) {
+	                		System.out.println(this.getClass().getSimpleName() + " :Error! " + e.getMessage());
+	                	}
+	                }
+    			}
+    		}
+    		
+    		if(enableT0Plots){
+    			int bins = aida.histogram1D(sensorName + " - Hit Time Resolution").axis().bins();
+    			for(int bin = 0; bin < bins; bin++){
+    				System.out.println(bin + "        " + aida.histogram1D(sensorName + " - Hit Time Resolution").binHeight(bin));
+    			}
+    		}
+    	
+            System.out.println("Total Bad Channels: " + HPSSVTCalibrationConstants.getTotalBadChannels() + "\n");
+            	
+            	/*
+                for(SiSensor sensor : SvtUtils.getInstance().getSensors()){
+                    	if(outputFile != null && sensorName.equals(SvtUtils.getInstance().getDescription(sensor))){
+                    		try{
+                    			for(int channel = 0; channel < 639; channel++){
+    								output.write(channel + " " + this.getOccupancy(sensor, channel) + "\n");
+    							}
+                    			output.close();
+                    		} catch(IOException e){
+                    			System.out.println(this.getClass().getSimpleName() + ": Error! " + e.getMessage());
+                    		}
+                    	}
+                	
+                	System.out.println("%===================================================================%");
+                    System.out.println(SvtUtils.getInstance().getDescription(sensor) + " Bad Channels");
+                    System.out.println("%===================================================================%");
+                    for(int index = 0; index < 640; index++){
+
+                        // Check is the channel can be considered bad    
+                        this.checkChannel(sensor, index);
+                    }
+                }
+                System.out.println("%===================================================================% \n");
+            }*/
+
+            if(enableStereoHitOccupancy){
+                for(SiSensor sensor : SvtUtils.getInstance().getSensors()){
+                    System.out.println("%===================================================================% \n");
+                    System.out.println(SvtUtils.getInstance().getDescription(sensor) + " Bad Channels");
+                    System.out.println("%===================================================================% \n");
+                    for(int index = 0; index < 640; index++){
+                        // Check is the channel can be considered bad    
+                        this.checkChannel(sensor, index);
+                    }
+                    System.out.println("%===================================================================% \n");
+                }
+            }
+
+            if(outputFile != null){
+                try{
+                    aida.saveAs(outputFile);
+                } catch(IOException exeption){
+                    System.out.println("File " + outputFile + " was not found!");
+                }
+            }
+            
+            if(enableSamples){
+            	double sigma = 0;
+            	double[] topMean = new double[6];
+            	double[] bottomMean = new double[6];
+            	
+                System.out.println("%===================================================================% \n");
+            	for(int index = 0; index < topSamples.length; index++){
+            		topMean[index] = topSamples[index]/totalTopSamples[index];
+            		System.out.println("Top sample " + index + " mean: " + topMean[index]);
+            	}
+            	
+                System.out.println("\n%===================================================================% \n");
+            	for(int index = 0; index < bottomSamples.length; index++){
+            		bottomMean[index] = bottomSamples[index]/totalBottomSamples[index];
+            		System.out.println("Bottom sample " + index + " mean: " + bottomMean[index]);
+            	}
+                System.out.println("\n%===================================================================% \n");
+            }
+        }
+
+    public double getOccupancy(SiSensor sensor, int channel){
+        if(!enableOccupancy) throw new RuntimeException("Occupancy calculation was not enabled!"); 
+        double nEvents = simulation ? SvtReadout.getNumberOfTriggers()  : totalNumberEvents; 
+        return sensorToOccupancy.get(SvtUtils.getInstance().getDescription(sensor))[channel]/nEvents;
+    }
+
+    public void checkChannel(SiSensor sensor, int channel){
+        if(!enableOccupancy) throw new RuntimeException("Occupancy calculation was not enabled!");
+
+        if(HPSSVTCalibrationConstants.isBadChannel(sensor, channel)) return;
+
+        // Find the occupancy of the current channel
+        double currentChannelOccu = this.getOccupancy(sensor, channel);
+
+        // If the channel exceeds the maximum allowable occupancy, then it's a bad channel
+        if(currentChannelOccu > maxOccupancy){
+            System.out.println("Channel " + channel + ": Occupancy " + currentChannelOccu + " -- Exceeds maximum");
+            return;
+        }
+
+        // Find the occupancy of the neighboring channels
+        if(channel == 0){
+            double rNeighborOccu = this.getOccupancy(sensor, channel+1);
+            if(rNeighborOccu == 0 || HPSSVTCalibrationConstants.isBadChannel(sensor, channel+1)) return; 
+            double rOccuDiff = Math.abs(rNeighborOccu - currentChannelOccu)/rNeighborOccu;
+            if(rOccuDiff >= maxOccupancyVariation)
+                System.out.println("Channel " + channel + ": Channel Variation exceeds maximum -- RVar: " + rOccuDiff);
+        } else if(channel == 638){
+            double lNeighborOccu = this.getOccupancy(sensor, channel-1);
+            if(lNeighborOccu == 0 || HPSSVTCalibrationConstants.isBadChannel(sensor, channel-1)) return;
+            double lOccuDiff = Math.abs(lNeighborOccu - currentChannelOccu)/lNeighborOccu;
+            if(lOccuDiff >= maxOccupancyVariation)
+                System.out.println("Channel " + channel + ": Channel Variation exceeds maximum -- LVar: " + lOccuDiff);
+        } else if (channel == 639){
+            return;
+        }
+        else { 
+            double rNeighborOccu = this.getOccupancy(sensor, channel+1);  
+            double lNeighborOccu = this.getOccupancy(sensor, channel-1);
+            if(rNeighborOccu == 0 || HPSSVTCalibrationConstants.isBadChannel(sensor, channel+1)
+                    || lNeighborOccu == 0 || HPSSVTCalibrationConstants.isBadChannel(sensor, channel-1)) return;
+            double rOccuDiff = Math.abs(rNeighborOccu - currentChannelOccu)/rNeighborOccu;
+            double lOccuDiff = Math.abs(lNeighborOccu - currentChannelOccu)/lNeighborOccu;
+            if(rOccuDiff >= maxOccupancyVariation && lOccuDiff >= maxOccupancyVariation){
+                System.out.println("Channel " + channel + ": Channel Variation exceeds maximum -- LVar: " + lOccuDiff + " RVar: " + rOccuDiff);
+            }
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
SvtTrackAnalysis.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtTrackAnalysis.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtTrackAnalysis.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,426 @@
+package org.lcsim.hps.users.omoreno;
+
+//--- java ---//
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+
+//--- org.lcsim ---//
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+
+
+//--- hep ---//
+import hep.aida.IPlotter;
+import hep.physics.vec.Hep3Vector;
+
+
+
+//--- hps-java ---//
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.monitoring.deprecated.Resettable;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.hps.recon.tracking.HPSFittedRawTrackerHit;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+
+/**
+ * 
+ * @author Omar Moreno
+ * @version $Id: SvtTrackAnalysis.java,v 1.7 2013/11/06 19:19:55 jeremy Exp $
+ *
+ */
+
+public class SvtTrackAnalysis extends Driver implements Resettable {
+	
+    private String trackCollectionName = "MatchedTracks";
+    private String stripHitCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+	private AIDA aida;
+	private List<AIDAFrame> frames = new ArrayList<AIDAFrame>();
+	private List<IPlotter> plotters = new ArrayList<IPlotter>();
+    
+	
+	int npositive = 0;
+	int nnegative = 0;
+	double ntracks = 0;
+	double ntracksTop = 0;
+	double ntracksBottom = 0;
+	double nTwoTracks = 0;
+	double nevents = 0;
+	
+	
+	public SvtTrackAnalysis(){
+	}
+
+	protected void detectorChanged(Detector detector){
+		
+		aida = AIDA.defaultInstance();
+		aida.tree().cd("/");
+		
+		for(int index = 0; index < 4; index++) frames.add(new AIDAFrame());
+
+		frames.get(0).setTitle("Track Position");
+		frames.get(1).setTitle("Track Parameters");
+		frames.get(2).setTitle("Track Momentum");
+		frames.get(3).setTitle("Cluster Matching");
+		
+		int nPlotters = 0;
+		
+		//--- Track Extrapolation ---//
+		//---------------------------//	
+		plotters.add(aida.analysisFactory().createPlotterFactory().create("Track Position at Ecal"));
+		plotters.get(nPlotters).region(0).plot(aida.histogram2D("Track Position at Ecal", 200, -350, 350, 200, -100, 100));
+		plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+    	plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style();
+        frames.get(0).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Track Position at Harp"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram2D("Track Position at Harp", 200, -200, 200, 100, -50, 50));
+		plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+    	plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        frames.get(0).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Track Position at Ecal: Curvature < 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram2D("Track Position at Ecal: Curvature < 0",200, -350, 350, 200, -100, 100));
+		plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+    	plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        frames.get(0).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Track Position at Harp: Curvature < 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram2D("Track Position at Harp: Curvature < 0", 200, -200, 200, 100, -50, 50));
+		plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+    	plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        frames.get(0).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Track Position at Ecal: Curvature > 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram2D("Track Position at Ecal: Curvature > 0", 200, -350, 350, 200, -100, 100));
+		plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+    	plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        frames.get(0).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Track Position at Harp: Curvature > 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram2D("Track Position at Harp: Curvature > 0", 200, -200, 200, 100, -50, 50));
+		plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+    	plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        frames.get(0).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+		plotters.add(aida.analysisFactory().createPlotterFactory().create("Track Position at Ecal: Two Tracks"));
+		plotters.get(nPlotters).region(0).plot(aida.histogram2D("Track Position at Ecal: Two Tracks", 200, -350, 350, 200, -100, 100));
+		plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+    	plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style();
+        frames.get(0).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Track Position at Harp: Two Tracks"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram2D("Track Position at Harp: Two Tracks", 200, -200, 200, 100, -50, 50));
+		plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+    	plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        frames.get(0).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        
+        //--- Track Parameters ---//
+        //------------------------//
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("DOCA"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("DOCA", 120, 0, 120));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(1).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Z0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Z0", 120, 0, 120));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(1).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("phi0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("phi0", 50, -Math.PI, Math.PI));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(1).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Curvature"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("R", 200, -10, 10));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(1).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Tan(Lambda)"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Tan(Lambda)", 100, 0, 1));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(1).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("ChiSquared"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("ChiSquared", 100, 0, 100));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(1).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        //--- Momentum ---//
+        //----------------//
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Px"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Px", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Py"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Py", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Pz"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Pz", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Px: C > 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Px: C > 0", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Py: C > 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Py: C > 0", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Pz: C > 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Pz: C > 0", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Px: C < 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Px: C < 0", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Py: C < 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Py: C < 0", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Pz: C < 0"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Pz: C < 0", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("Px: Two Tracks"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("Px: Two Tracks", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("E over P"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram1D("E over P", 100, 0, 5));
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        plotters.get(nPlotters).style().dataStyle().errorBarStyle().setVisible(false);
+        frames.get(2).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		   
+		plotters.add(aida.analysisFactory().createPlotterFactory().create("E versus P"));
+	    plotters.get(nPlotters).region(0).plot(aida.histogram2D("E versus P", 100, 0, 1500, 100, 0, 4000));
+	    plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+	    plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+	    plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+	    frames.get(2).addPlotter(plotters.get(nPlotters));
+	    nPlotters++;
+        
+        //--- Cluster Matching ---//
+        //------------------------//        
+        plotters.add(aida.analysisFactory().createPlotterFactory().create("XY Difference between Ecal Cluster and Track Position"));
+        plotters.get(nPlotters).region(0).plot(aida.histogram2D("XY Difference between Ecal Cluster and Track Position", 200, -200, 200, 100, -50, 50));
+		plotters.get(nPlotters).region(0).style().setParameter("hist2DStyle", "colorMap");
+    	plotters.get(nPlotters).region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotters.get(nPlotters).style().statisticsBoxStyle().setVisible(false);
+        frames.get(3).addPlotter(plotters.get(nPlotters));
+		nPlotters++;
+		
+        for(AIDAFrame frame : frames){
+        	frame.pack();
+        	frame.setVisible(true);
+        }
+	}
+	
+	public void process(EventHeader event){
+		nevents++;
+		
+		if(event.hasCollection(SiTrackerHitStrip1D.class, stripHitCollectionName)){
+			
+			System.out.println("Found Strip Hits!");
+			List<SiTrackerHitStrip1D> stripHits = event.get(SiTrackerHitStrip1D.class, stripHitCollectionName);
+			short[] samples = new short[6];
+			for(SiTrackerHitStrip1D stripHit : stripHits){
+				for(RawTrackerHit rawHit : stripHit.getRawHits()){
+					for(int index = 0; index < samples.length; index++){
+						samples[index] += rawHit.getADCValues()[index];
+					}
+				}
+			}
+		}
+				
+		if(!event.hasCollection(Track.class, trackCollectionName)) return;
+    	List<SeedTrack> tracks = event.get(SeedTrack.class, trackCollectionName);
+    	
+    	Map<Hep3Vector,SeedTrack> trackToEcalPosition = new HashMap<Hep3Vector, SeedTrack>();
+     	Map<SeedTrack, HPSEcalCluster> trackToCluster = new HashMap<SeedTrack, HPSEcalCluster>();
+    	List<Hep3Vector> ecalPos = new ArrayList<Hep3Vector>();
+    	
+    	for(SeedTrack track : tracks){
+    		ntracks++;
+    		Hep3Vector positionEcal = TrackUtils.getTrackPositionAtEcal(track);
+    		System.out.println("Position at Ecal: " + positionEcal);
+    		Hep3Vector positionConverter = TrackUtils.extrapolateTrack(track,-700);
+    	
+    		aida.histogram2D("Track Position at Ecal").fill(positionEcal.y(), positionEcal.z());
+    		aida.histogram2D("Track Position at Harp").fill(positionConverter.y(), positionConverter.z());
+
+    		if(positionEcal.z() > 0 ) ntracksTop++;
+    		else if(positionEcal.z() < 0) ntracksBottom++;
+    		
+    		
+    		aida.histogram1D("DOCA").fill(TrackUtils.getDoca(track));
+    		aida.histogram1D("Z0").fill(TrackUtils.getZ0(track));
+    		aida.histogram1D("phi0").fill(TrackUtils.getPhi0(track));
+    		aida.histogram1D("R").fill((1/TrackUtils.getR(track))*1000);
+    		aida.histogram1D("Tan(Lambda)").fill(TrackUtils.getTanLambda(track));
+    		
+    		aida.histogram1D("Px").fill(track.getPX());
+    		aida.histogram1D("Py").fill(track.getPY());
+    		aida.histogram1D("Pz").fill(track.getPZ());
+    		aida.histogram1D("ChiSquared").fill(track.getChi2());
+    		
+    		if(Math.signum(TrackUtils.getR(track)) < 0){
+    			aida.histogram2D("Track Position at Ecal: Curvature < 0").fill(positionEcal.y(), positionEcal.z());
+    			aida.histogram2D("Track Position at Harp: Curvature < 0").fill(positionConverter.y(), positionConverter.z());
+        		aida.histogram1D("Px: C < 0").fill(track.getPX());
+        		aida.histogram1D("Py: C < 0").fill(track.getPY());
+        		aida.histogram1D("Pz: C < 0").fill(track.getPZ());
+        		nnegative++;
+    		} else if(Math.signum(TrackUtils.getR(track)) > 0){
+    			aida.histogram2D("Track Position at Ecal: Curvature > 0").fill(positionEcal.y(), positionEcal.z());
+    			aida.histogram2D("Track Position at Harp: Curvature > 0").fill(positionConverter.y(), positionConverter.z());
+        		aida.histogram1D("Px: C > 0").fill(track.getPX());
+        		aida.histogram1D("Px: C > 0").fill(track.getPY());
+        		aida.histogram1D("Px: C > 0").fill(track.getPZ());
+        		npositive++;
+    		}
+    		
+    		if(tracks.size() > 1){
+    			aida.histogram2D("Track Position at Ecal: Two Tracks").fill(positionEcal.y(), positionEcal.z());
+    			aida.histogram2D("Track Position at Harp: Two Tracks").fill(positionConverter.y(), positionConverter.z()); 
+    			aida.histogram1D("Px: Two Tracks").fill(track.getPX());
+    			if(tracks.size() == 2) nTwoTracks++;
+    		}
+    		
+    		trackToEcalPosition.put(positionEcal, track);
+    		ecalPos.add(positionEcal);  		
+    	}
+    	
+    	if(!event.hasCollection(HPSEcalCluster.class, "EcalClusters")) return;
+    	List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, "EcalClusters");
+    	
+
+    	for(Hep3Vector ecalP : ecalPos){
+        	double xdiff = 1000; 
+        	double ydiff = 1000;
+    		for(HPSEcalCluster cluster : clusters){
+    			double xd = ecalP.y() - cluster.getPosition()[0];
+    			double yd = ecalP.z() - cluster.getPosition()[1];  
+    			if(yd < ydiff){
+    				xdiff = xd;
+    				ydiff = yd;
+    				trackToCluster.put(trackToEcalPosition.get(ecalP),cluster);
+    			}
+    		}
+    		clusters.remove(trackToCluster.get(trackToEcalPosition.get(ecalP)));
+    		aida.histogram2D("XY Difference between Ecal Cluster and Track Position").fill(xdiff, ydiff);
+    	}
+    	
+    	for(Map.Entry<SeedTrack, HPSEcalCluster> entry : trackToCluster.entrySet()){
+    		double Energy = entry.getValue().getEnergy();
+    		SeedTrack track = entry.getKey();
+    		double pTotal = Math.sqrt(track.getPX()*track.getPX() + track.getPY()*track.getPY() + track.getPZ()*track.getPZ());
+    		
+    		double ep = Energy/(pTotal*1000);
+    		
+    		System.out.println("Energy: " + Energy + "P: " + pTotal + " E over P: " + ep);
+    		
+    		aida.histogram1D("E over P").fill(ep);
+    		aida.histogram2D("E versus P").fill(Energy, pTotal*1000);
+    	}
+    	
+    	for(HPSEcalCluster cluster : clusters){
+    		double[] clusterPosition = cluster.getPosition();
+    		
+    		System.out.println("Cluster Position: [" + clusterPosition[0] + ", " + clusterPosition[1] + ", " + clusterPosition[2]+ "]");
+    	}
+    	
+    	double ratio = nnegative/npositive;
+    	System.out.println("Ratio of Negative to Position Tracks: " + ratio);
+	
+    	double tracksRatio = ntracks/nevents;
+    	double tracksTopRatio = ntracksTop/nevents;
+    	double tracksBottomRatio = ntracksBottom/nevents;
+    	double twoTrackRatio = nTwoTracks/nevents;
+    	System.out.println("Number of tracks per event: " + tracksRatio);
+    	System.out.println("Number of top tracks per event: " + tracksTopRatio);
+    	System.out.println("Number of bottom tracks per event: " + tracksBottomRatio);
+    	System.out.println("Number of two track events: " + twoTrackRatio);
+	}
+
+	@Override
+	public void reset() {
+		aida.histogram2D("Track Position at Ecal").reset();
+		aida.histogram2D("Track Position at Converter").reset();
+	}
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
SvtTrackRecoEfficiency.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtTrackRecoEfficiency.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtTrackRecoEfficiency.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,488 @@
+package org.lcsim.hps.users.omoreno;
+
+//--- java ---//
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.ArrayList;
+
+//--- aida ---//
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IPlotter;
+
+import hep.physics.vec.BasicHep3Vector;
+//--- hep ---//
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHit;
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+import org.lcsim.recon.tracking.seedtracker.StrategyXMLUtils;
+//--- lcsim ---//
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.geometry.Detector;
+
+import org.lcsim.hps.recon.tracking.FindableTrack.Ignore;
+import org.lcsim.hps.recon.tracking.HPSFittedRawTrackerHit;
+//--- hps-java ---//
+import org.lcsim.hps.recon.tracking.SvtUtils;
+import org.lcsim.hps.recon.tracking.TrackAnalysis;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.hps.recon.tracking.FindableTrack;
+
+/**
+ * 
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: SvtTrackRecoEfficiency.java,v 1.11 2013/10/14 22:58:03 phansson Exp $ 
+ */
+public class SvtTrackRecoEfficiency extends Driver {
+
+    private AIDA aida;
+    private List<IPlotter>     plotters = new ArrayList<IPlotter>();
+    private List<IHistogram1D> histo1D  = new ArrayList<IHistogram1D>();
+    private List<IHistogram2D> histo2D  = new ArrayList<IHistogram2D>();
+    private Map<Integer, List<SimTrackerHit>> topSimTrackerHitsList = new HashMap<Integer, List<SimTrackerHit>>();
+    private Map<Integer, List<SimTrackerHit>> bottomSimTrackerHitsList = new HashMap<Integer, List<SimTrackerHit>>();
+
+    FindableTrack findable = null;
+    TrackAnalysis trkAnalysis = null;
+    RelationalTable<SimTrackerHit, MCParticle> simHitToMcParticle;
+    RelationalTable<SimTrackerHit, RawTrackerHit> simHitToRawHit;
+    BufferedWriter efficiencyOutput = null;
+    BufferedWriter momentumOutput = null;
+
+    // Collection Names
+    String simTrackerHitCollectionName = "TrackerHits";
+    String rawTrackerHitCollectionName = "SVTRawTrackerHits";
+    String fittedRawTrackerHitCollectionName = "SVTFittedRawTrackerHits";
+    String trackCollectionName = "MatchedTracks";
+    String stereoHitCollectionName = "RotatedHelicalTrackHits";
+    String siTrackerHitCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+
+    int eventNumber = 0;
+    int plotterIndex, histo1DIndex, histo2DIndex;
+    int[] topSimTrackerHits;
+    int[] bottomSimTrackerHits;
+    double findableTracks, foundTracks;
+    double topPossibleTracks, bottomPossibleTracks, possibleTracks;
+    double totalTopTracks, totalBottomTracks, totalTracks;
+    int totalLayersHit = 10;
+    int totalSvtLayers = 10; 
+    
+    String efficiencyOutputFile = null;
+    String momentumOutputFile = null;
+    String strategyResourcePath = null;
+    
+    boolean debug = false;
+    boolean trackingEfficiencyPlots = true;
+    boolean trackMatch = false;
+    boolean trackIsFindable = false;
+    boolean isTopTrack  = false;
+
+    /**
+     *  Enable/Disable debug
+     */
+    public void setDebug(boolean debug){
+        this.debug = debug;
+    }
+    
+    /**
+     * Set the name of the file to output efficiency data to
+     */
+    public void setEfficiencyOutputFile(String efficiencyOutputFile){
+    	this.efficiencyOutputFile = efficiencyOutputFile;
+    }
+
+    /**
+     * Set the name of the file to output momentum data to
+     */
+    public void setMomentumOutputFile(String momentumOutputFile){
+        this.momentumOutputFile = momentumOutputFile;
+    }
+    
+    /**
+     * Set the required number of layers an MC particle must hit 
+     */
+    public void setTotalLayersHit(int totalLayersHit){
+        if(totalLayersHit%2 == 1) throw new RuntimeException(this.getClass().getSimpleName() + ": Total number of layers hit must be even");
+        this.totalLayersHit = totalLayersHit;
+    }
+
+    /**
+     * Print a debug statement
+     * 
+     * @param message : debug message
+     */
+    private void printDebug(String message){
+    	if(debug){
+    		System.out.println(this.getClass().getSimpleName() + ": " + message);
+    	}
+    }
+    
+    /**
+     * 
+     */
+    protected void detectorChanged(Detector detector){
+    	super.detectorChanged(detector);
+    	
+        // setup AIDA
+        aida = AIDA.defaultInstance();
+        aida.tree().cd("/");
+        
+        // Open the output file stream
+        if(efficiencyOutputFile != null && momentumOutputFile != null){
+        	try{
+        		efficiencyOutput = new BufferedWriter(new FileWriter(efficiencyOutputFile));
+                momentumOutput = new BufferedWriter(new FileWriter(momentumOutputFile));
+        	} catch(Exception e){
+        		System.out.println(this.getClass().getSimpleName() + ": Error! " + e.getMessage());
+        	}
+        }
+        
+        // Get the total number of SVT layers
+        // TODO: Get the total number of Si planes from the SVT geometry 
+        totalSvtLayers = SvtUtils.getInstance().getSensors().size()/2; 
+        System.out.println("The SVT has a total of " + totalSvtLayers + " layers");
+        
+        
+        // Initialize the Layer to RawTrackerHit maps
+        for(int index = 0; index < 10; index++){
+            topSimTrackerHitsList.put(index + 1, new ArrayList<SimTrackerHit>());
+            bottomSimTrackerHitsList.put(index + 1, new ArrayList<SimTrackerHit>());
+        }
+
+        if(trackingEfficiencyPlots){
+        	plotters.add(PlotUtils.setupPlotter("Track Momentum", 0, 0));
+        	histo1D.add(aida.histogram1D("Momentum - Reconstructed Tracks", 14, 0, 5.6));
+        	PlotUtils.setup1DRegion(plotters.get(plotterIndex), "Reconstructed Tracks", 0, "Momentum [GeV]", histo1D.get(histo1DIndex));
+            histo1DIndex++;            
+            histo1D.add(aida.histogram1D("Momentum - Findable Tracks", 14, 0, 5.6));
+        	PlotUtils.setup1DRegion(plotters.get(plotterIndex), "Findable Tracks", 0, "Momentum [GeV]", histo1D.get(histo1DIndex));
+        	plotterIndex++;
+        	histo1DIndex++;
+        }
+        
+        for(IPlotter plotter : plotters){
+        	plotter.show();
+        }
+    }
+    
+    private String samplesToString(short[] samples){
+    	String sampleList = "[ ";
+    	for(short sample : samples){
+    		sampleList += Short.toString(sample) + ", ";
+    	}
+    	sampleList += "]";
+    	return sampleList;
+    }
+
+    /**
+     * Dflt Ctor
+     */
+    public SvtTrackRecoEfficiency(){}
+
+    @Override
+    protected void process(EventHeader event){
+        
+    	// For now, only look at events with a single track
+        if(event.get(Track.class, trackCollectionName).size() > 1) return;
+        eventNumber++;
+
+        // If the event doesn't contain SimTrackerHits, skip the event
+        if(!event.hasCollection(SimTrackerHit.class, simTrackerHitCollectionName)) return;
+        List<SimTrackerHit> simTrackerHits = event.get(SimTrackerHit.class, simTrackerHitCollectionName);
+        this.printDebug("\nEvent " + eventNumber + " contains " + simTrackerHits.size() + " SimTrackerHits");
+    	// Loop through all SimTrackerHits and confirm that a corresponding RawTrackerHit was created
+    	for(SimTrackerHit simTrackHit : simTrackerHits){
+    		
+    		this.printDebug("SimTrackerHit Layer Number: " + simTrackHit.getLayerNumber());
+    	}
+
+        // Get the list of RawTrackerHits and add them to the sensor readout
+        List<RawTrackerHit> rawHits = event.get(RawTrackerHit.class, rawTrackerHitCollectionName);
+        String volume; 
+        for(RawTrackerHit rawHit : rawHits){
+        	if(SvtUtils.getInstance().isTopLayer((SiSensor)rawHit.getDetectorElement())){
+        		volume = "Top Volume ";
+        	} else { 
+        		volume = "Bottom Volume ";
+        	}
+    		this.printDebug(volume + "RawTrackerHit Channel #: " + rawHit.getIdentifierFieldValue("strip") + " Layer Number: " + rawHit.getLayerNumber()
+    				+ " Samples: " + samplesToString(rawHit.getADCValues()));
+            ((SiSensor) rawHit.getDetectorElement()).getReadout().addHit(rawHit);
+        }
+        
+        if(event.hasCollection(SiTrackerHit.class, siTrackerHitCollectionName)){
+        	List<SiTrackerHit> hitlist = event.get(SiTrackerHit.class, siTrackerHitCollectionName);
+        	for(SiTrackerHit siTrackerHit : hitlist){
+        		this.printDebug("Cluster layer: " + SvtUtils.getInstance().getLayerNumber(siTrackerHit.getSensor()));
+    			this.printDebug("Cluster is comprised by the following raw hits:");
+        		for(RawTrackerHit rawHit : siTrackerHit.getRawHits()){
+            		this.printDebug("RawTrackerHit Channel #: " + rawHit.getIdentifierFieldValue("strip") + " Layer Number: " + rawHit.getLayerNumber());
+        		}
+        	}
+        }
+        
+        // Get the MC Particles associated with the SimTrackerHits
+        List<MCParticle> mcParticles = event.getMCParticles();
+        if(debug){
+        	String particleList = "[ ";
+        	for(MCParticle mcParticle : mcParticles){
+        		particleList += mcParticle.getPDGID() + ", ";
+        	}
+        	particleList += "]";
+        	this.printDebug("MC Particles: " + particleList);
+        }
+        
+        // Get the magnetic field
+        Hep3Vector IP = new BasicHep3Vector(0., 0., 1.);
+        //this.printDebug("BField: " + event.getDetector().getFieldMap().getField(IP).y());
+        
+        // Check if the MC particle track should be found by the tracking algorithm
+        findable = new FindableTrack(event, simTrackerHits, totalSvtLayers);
+        
+        // Use an iterator to avoid ConcurrentModificationException
+        Iterator<MCParticle> mcParticleIterator = mcParticles.iterator();
+        trackIsFindable = false;
+        while(mcParticleIterator.hasNext()){
+            MCParticle mcParticle = mcParticleIterator.next();
+            if(findable.isTrackFindable(mcParticle, totalLayersHit)){
+                
+                // Check that all SimTrackerHits are within the same detector volume
+                Set<SimTrackerHit> trackerHits = findable.getSimTrackerHits(mcParticle);
+                if(this.isSameSvtVolume(trackerHits)){
+                    if(debug){
+                    	this.printDebug("Track is findable");
+                    	this.printDebug("MC particle momentum: " + mcParticle.getMomentum().toString());
+                    }
+                    	
+                    findableTracks++;
+                    trackIsFindable = true;      
+                }
+            } else {
+                mcParticleIterator.remove();
+            }
+        }
+        
+        // Check if the event contains a Track collection, otherwise return
+        if(!event.hasCollection(Track.class, trackCollectionName)) return;
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+        this.printDebug("Event " + eventNumber + " contains " + tracks.size() + " Tracks");
+        
+        // Relate a stereo hits to a SimTrackerHit; This is a required argument by TrackAnalysis
+        List<HelicalTrackHit> stereoHits = event.get(HelicalTrackHit.class, stereoHitCollectionName);
+        this.printDebug("Event " + eventNumber + " contains " + stereoHits.size() + " HelicalTrackHits");
+        RelationalTable<HelicalTrackHit, MCParticle> hitToMC = stereoHitToMC(stereoHits, simTrackerHits);
+        
+        // Check if an MC particle is related to a found track
+        for(Track track : tracks){
+            trkAnalysis = new TrackAnalysis(track, hitToMC);
+            if(mcParticles.contains(trkAnalysis.getMCParticle())){
+               if(debug)
+                    this.printDebug("Track match found");
+                foundTracks++;
+                if(trackingEfficiencyPlots){
+                    aida.histogram1D("Momentum - Reconstructed Tracks").fill(trkAnalysis.getMCParticle().getMomentum().magnitude());
+                    aida.histogram1D("Momentum - Findable Tracks").fill(trkAnalysis.getMCParticle().getMomentum().magnitude());
+                }
+                mcParticles.remove(trkAnalysis.getMCParticle());
+            }
+        }
+        
+        if(!mcParticles.isEmpty() && trackingEfficiencyPlots){
+            // If the list still contains MC Particles, a matching track wasn't found
+        	this.printDebug("No matching track found");
+        	
+            // Check that all stereoHits were correctly assigned to an MCParticle
+            for(MCParticle mcParticle : mcParticles){
+                
+                // Check if there is a stereo hit associated with every pair of layers hit by the MC particle
+                Set<SimTrackerHit> simHits = findable.getSimTrackerHits(mcParticle);
+                boolean[] planesHit = new boolean[totalSvtLayers];
+                
+                // Clear the sensor readout's and then add the SimTrackerHits from  the MC particles to them
+                for(SiSensor sensor : SvtUtils.getInstance().getSensors()) sensor.getReadout().clear();
+                for(SimTrackerHit simHitTrackerHit : simHits){
+                    ((SiSensor) simHitTrackerHit.getDetectorElement()).getReadout().addHit(simHitTrackerHit);
+                }
+                
+                // Clear all previously stored simTrackerHits
+                for(int index = 0; index < 10; index++){
+                    topSimTrackerHitsList.get(index+1).clear();
+                    bottomSimTrackerHitsList.get(index+1).clear();
+                }
+                
+                // Determine if the MC particle passed through the top or bottom SVT volume
+                for(SimTrackerHit simHit : simHits){
+                    if(SvtUtils.getInstance().isTopLayer((SiSensor) simHit.getDetectorElement())){
+                        this.printDebug("MC Particle passed through the top layer");
+                        isTopTrack = true;
+                        break;
+                    } else {
+                        this.printDebug("MC Particle passed through the bottom layer");
+                        isTopTrack = false;
+                        break;
+                    }
+                }
+                
+                // Check which layers have SimTrackerHits
+                // Arrange them by layers
+                for(SimTrackerHit simHit : simHits){
+                    planesHit[simHit.getLayer()-1] = true;
+                }
+                // TODO: Get the number of SVT layers from the geometry
+                boolean[] layerHit = new boolean[6];
+                int layerN = 0;
+                for(int index = 0; index < planesHit.length; index+=2){
+                    if(planesHit[index] && planesHit[index+1]){
+                        layerHit[layerN] = true;
+                        this.printDebug("Layer " + (layerN+1) + " was hit");
+                    }
+                    layerN++;
+                }
+               
+                // Check which layers have a stereo hit associated with them
+                // TODO: Get the number of detector layers from the geometry
+                boolean[] topStereoLayerHit = new boolean[6];
+                boolean[] bottomStereoLayerHit = new boolean[6];
+                for(HelicalTrackHit stereoHit : stereoHits){
+                    if(stereoHit.getCorrectedPosition().z() > 0){                    
+                        topStereoLayerHit[(stereoHit.Layer() - 1)/2] = true;
+                    } else { 
+                        bottomStereoLayerHit[(stereoHit.Layer() - 1)/2] = true;
+                    }
+                }
+      
+                aida.histogram1D("Momentum - Findable Tracks").fill(mcParticle.getMomentum().magnitude());
+                
+            }
+        }
+    }
+    
+    private boolean isSameSvtVolume(Set<SimTrackerHit> simTrackerHits)
+    {
+        int volumeIndex = 0;
+        for(SimTrackerHit simTrackerHit : simTrackerHits){
+            if(SvtUtils.getInstance().isTopLayer((SiSensor) simTrackerHit.getDetectorElement())) volumeIndex++;
+            else volumeIndex--;
+        }
+        return Math.abs(volumeIndex) == simTrackerHits.size();
+    }
+
+    private RelationalTable<HelicalTrackHit, MCParticle> stereoHitToMC(List<HelicalTrackHit> stereoHits, List<SimTrackerHit> simTrackerHits)
+    {
+        RelationalTable<HelicalTrackHit, MCParticle> hitToMC 
+            = new BaseRelationalTable<HelicalTrackHit, MCParticle>(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+        Map<Integer, List<SimTrackerHit>> layerToSimTrackerHit = new HashMap<Integer, List<SimTrackerHit>>();
+        
+        // Sort the SimTrackerHits by Layer
+        for(SimTrackerHit simTrackerHit : simTrackerHits){
+            if(!layerToSimTrackerHit.containsKey(simTrackerHit.getLayer()))
+                layerToSimTrackerHit.put(simTrackerHit.getLayer(), new ArrayList<SimTrackerHit>());
+            layerToSimTrackerHit.get(simTrackerHit.getLayer()).add(simTrackerHit);
+        }
+        
+        // 
+        for(HelicalTrackHit stereoHit : stereoHits){
+            HelicalTrackCross cross = (HelicalTrackCross) stereoHit;
+                for(HelicalTrackStrip strip : cross.getStrips()){
+                    // If there is only a single SimTrackerHit on a layer and it's in the same volume as the
+                    // stereo hit then they likely match to each other
+                    if(layerToSimTrackerHit.get(strip.layer()) != null && layerToSimTrackerHit.get(strip.layer()).size() == 1){
+                        Hep3Vector simTrackerHitPosition = layerToSimTrackerHit.get(strip.layer()).get(0).getPositionVec();
+                        if(Math.signum(simTrackerHitPosition.y()) == Math.signum(this.getClusterPosition(strip).z())){
+                            hitToMC.add(stereoHit, layerToSimTrackerHit.get(strip.layer()).get(0).getMCParticle()); 
+                            layerToSimTrackerHit.remove(strip.layer());
+                            //System.out.println(this.getClass().getSimpleName() + ": SimTrackerHit position: " + simTrackerHitPosition.toString());
+                            //System.out.println(this.getClass().getSimpleName() + ": Cluster position: " + this.getClusterPosition(strip));
+                        } else {
+                            //System.out.println(this.getClass().getSimpleName() + ": Cluster and SimTrackerHit are on different volumes");
+                        }
+                    }
+                    else if(layerToSimTrackerHit.get(strip.layer()) != null && layerToSimTrackerHit.get(strip.layer()).size() > 1){
+                        //System.out.println(this.getClass().getSimpleName() + ": Layer with multiple hits found.");
+                        double deltaZ = Double.MAX_VALUE;
+                        SimTrackerHit simTrackerHitMatch = null;
+                        for(SimTrackerHit simTrackerHit : layerToSimTrackerHit.get(strip.layer())){
+                            if(Math.abs(simTrackerHit.getPositionVec().y() - this.getClusterPosition(strip).z()) < deltaZ){
+                                deltaZ = Math.abs(simTrackerHit.getPositionVec().y() - this.getClusterPosition(strip).z());
+                                simTrackerHitMatch = simTrackerHit;
+                            }
+                        }
+                        hitToMC.add(stereoHit, simTrackerHitMatch.getMCParticle()); 
+                        layerToSimTrackerHit.remove(strip.layer()).remove(simTrackerHitMatch);
+                        //System.out.println(this.getClass().getSimpleName() + ": SimTrackerHit position: " + simTrackerHitMatch.getPositionVec().toString());
+                        //System.out.println(this.getClass().getSimpleName() + ": Cluster position: " + this.getClusterPosition(strip));
+                    }
+                }
+            }
+
+        return hitToMC;
+    }
+    
+    private List<SeedStrategy> getStrategyList(){
+        if(!strategyResourcePath.startsWith("/"))
+            strategyResourcePath = "/" + strategyResourcePath;
+    
+        return StrategyXMLUtils.getStrategyListFromInputStream(this.getClass().getResourceAsStream(strategyResourcePath));
+    }
+    
+    private Hep3Vector getClusterPosition(HelicalTrackStrip strip)
+    {
+        Hep3Vector origin = strip.origin();
+        Hep3Vector u = strip.u();
+        double umeas = strip.umeas();
+        Hep3Vector uvec = VecOp.mult(umeas, u);
+        return VecOp.add(origin, uvec);
+    }
+
+    
+   @Override
+   public void endOfData()
+   { 
+	   
+       if(trackingEfficiencyPlots && efficiencyOutputFile != null && momentumOutputFile != null){
+	   	   try{ 
+	   		   int bins = aida.histogram1D("Momentum - Findable Tracks").axis().bins();
+	   		   for(int index = 0; index < bins; index++){
+	   			   if(aida.histogram1D("Momentum - Reconstructed Tracks").binEntries(index) == 0) efficiencyOutput.write(index + " " + 0 + "\n");
+	   			   else	efficiencyOutput.write(index + " " + aida.histogram1D("Momentum - Reconstructed Tracks").binEntries(index) + "\n");
+	   			   
+                   if(aida.histogram1D("Momentum - Findable Tracks").binEntries(index) == 0) momentumOutput.write(index + " " + 0 + "\n");
+	   			   else momentumOutput.write(index + " " + aida.histogram1D("Momentum - Findable Tracks").binEntries(index) + "\n");
+	   		   }
+	   		   efficiencyOutput.close();
+               momentumOutput.close();
+	   	   } catch(IOException e){
+	   		   System.out.println(this.getClass().getSimpleName() + ": Error! " + e.getMessage());
+	   	   }
+       } 
+	   
+        System.out.println("%===============================================================%");
+        System.out.println("%============== Track Reconstruction Efficiencies ==============%");
+        System.out.println("%===============================================================%\n%");
+        if(findableTracks > 0){
+            System.out.println("% Total Track Reconstruction Efficiency: " + foundTracks + "/" + findableTracks + "=" + (foundTracks/findableTracks)*100 + "%");
+        }
+        System.out.println("%\n%===============================================================%");
+    } 
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
SvtTrackingPerformance.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtTrackingPerformance.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/SvtTrackingPerformance.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,95 @@
+package org.lcsim.hps.users.omoreno;
+
+//--- java ---//
+import java.util.ArrayList;
+import java.util.List;
+
+//--- org.lcsim ---//
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+//--- hps-java ---//
+import org.lcsim.hps.monitoring.deprecated.Resettable;
+
+/**
+ * 
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: SvtTrackingPerformance.java,v 1.2 2013/11/06 19:19:55 jeremy Exp $
+ */
+public class SvtTrackingPerformance extends Driver implements Resettable {
+
+	boolean debug;
+	int[] topLayer = new int[5];
+	int[] bottomLayer = new int[5];
+	
+	// Collection names
+	String stereoHitCollectionName = "RotatedHelicalTrackHits";
+	
+	public void reset() {
+		// TODO Auto-generated method stub
+	}
+
+	
+		protected void detectorChanged(Detector detector){
+			
+		}
+		
+		public void process(EventHeader event){
+			
+			// Check if the event has stereo hits
+			if(!event.hasCollection(HelicalTrackHit.class, stereoHitCollectionName)){
+				System.out.println(
+						this.getClass().getSimpleName() + " Stereo Hit Collection: " 
+						+ stereoHitCollectionName + " was not found! Skipping event ..." );
+			}
+			
+			// Get the list of HelicalTrackHits
+			List<HelicalTrackHit> stereoHits = new ArrayList<HelicalTrackHit>();
+			
+			for(HelicalTrackHit stereoHit : stereoHits){
+				
+				// Loop over all stereo hits and arrange them by layer and by detector
+				// volume
+				int layer = this.getLayerNumber(stereoHit);
+				
+				// 
+				if(stereoHit.y() > 0) topLayer[layer - 1]++;
+				else if(stereoHit.y() < 0) bottomLayer[layer - 1]++;
+				else throw new RuntimeException("Invalid hit position - y = " + stereoHit.y());
+			}
+			
+			// Check if there are four consecutive layers hit on either volume
+			
+			
+		}
+		
+		private int getLayerNumber(HelicalTrackHit stereoHit){
+			
+			if(debug) 
+				System.out.println(this.getClass().getSimpleName() + " : Stereo Hit z position = " + stereoHit.z());
+			
+			// Get the position along z
+			int z = Math.round((float) stereoHit.z());
+		
+			switch(z){
+				case 100: return 1;
+				case 200: return 2;
+				case 300: return 3;
+				case 500: return 4;
+				case 700: return 5;
+				default: throw new RuntimeException("Invalid value of z: " + z);
+			}
+		}
+		
+		private boolean consecutiveHits(int[] layer){
+			for(int index = 0; index < 2; index++){
+				if(layer[index] > 0 && layer[index + 1] > 0 && layer[index + 2] > 0 && layer[index +4] > 0) return true;
+			}
+			return false;
+		}
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno
TestRunTrackReconEfficiency.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/TestRunTrackReconEfficiency.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/omoreno/TestRunTrackReconEfficiency.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,414 @@
+package org.lcsim.hps.users.omoreno;
+
+//--- java ---//
+import java.util.ArrayList;
+import java.util.List;
+
+
+//--- hep ---//
+import hep.aida.IHistogram1D;
+import hep.aida.IPlotter;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+
+//--- lcsim ---//
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.event.Track;
+import org.lcsim.event.GenericObject;
+
+//--- hps-java ---//
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+
+/**
+ * Class to calculate track reconstruction efficiency using a tag and probe
+ * method. 
+ * 
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: TestRunTrackReconEfficiency.java,v 1.5 2013/10/14 22:58:04 phansson Exp $
+ */
+public class TestRunTrackReconEfficiency  extends Driver {
+    
+    private AIDA aida;
+    private List<IPlotter>     plotters = new ArrayList<IPlotter>();
+    private List<IHistogram1D> histo1D = new ArrayList<IHistogram1D>();
+    List<Track> topTracks; 
+    List<Track> botTracks;
+    
+    int plotterIndex = 0; 
+
+    double eventNumber     = 0;
+    double nOppositeVolume = 0;
+    double nWithinWindow   = 0;
+    double nAboveThreshold = 0;
+    double nTrigClusterTrackMatch = 0;
+    double findableTracks, findableTopTracks,findableBottomTracks;
+    double totalTracks, totalTopTracks, totalBottomTracks; 
+    double findableSingleTracks;
+    double findableSingleTracksQuad1, findableSingleTracksQuad2;
+    double findableSingleTracksQuad3, findableSingleTracksQuad4;
+    double foundSingleTracks;
+    double foundSingleTracksQuad1, foundSingleTracksQuad2;
+    double foundSingleTracksQuad3, foundSingleTracksQuad4;
+    double thresholdEnergy  = 0;
+    double energyDifference = 0; 
+    
+    boolean debug = false;  
+    boolean topTrackIsFindable, bottomTrackIsFindable;
+    boolean topTrigger = false;
+     
+    // Collection Names
+    String stereoHitCollectionName 		= "HelicalTrackHits";
+    String trackCollectionName 			= "MatchedTracks";
+    String ecalClustersCollectionName 	= "EcalClusters";
+    String triggerDataCollectionName 	= "TriggerBank";
+    
+    // Plots
+    IHistogram1D findableTrackMomentum; 
+    IHistogram1D totalTrackMomentum; 
+	IHistogram1D xPositionResidual;
+	IHistogram1D yPositionResidual;
+	IHistogram1D zPositionResidual;
+	IHistogram1D r;
+
+    /**
+     * Dflt Ctor
+     */
+    public TestRunTrackReconEfficiency(){};
+
+    /**
+     * Enable/disble debug mode
+     */
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+    
+    /**
+     * 
+     */
+    public void setThresholdEnergy(double thresholdEnergy){
+    	this.thresholdEnergy = thresholdEnergy;
+    }
+
+    public void setClusterEnergyDifference(double energyDifference){ 
+        this.energyDifference = energyDifference; 
+    }
+     
+    /**
+     * 
+     */
+    protected void detectorChanged(Detector detector){
+        super.detectorChanged(detector);
+
+        // setup AIDA
+        aida = AIDA.defaultInstance(); 
+        aida.tree().cd("/"); 
+
+        // Open the output file stream
+    
+        // Create plots of track reconstruction effiency vs momentum
+        plotters.add(PlotUtils.setupPlotter("Track Momentum", 0, 0));
+        findableTrackMomentum = aida.histogram1D("Momentum - Findable Tracks", 14, 0, 5.6); 
+        PlotUtils.setup1DRegion(plotters.get(plotterIndex), "Momentum - Findable Tracks", 0, "Momentum [GeV]", findableTrackMomentum); 
+        totalTrackMomentum = aida.histogram1D("Momentum - Reconstructed Tracks", 14, 0, 5.6); 
+        PlotUtils.setup1DRegion(plotters.get(plotterIndex), "Momentum - Reconstructed Tracks", 0, "Momentum [GeV]", totalTrackMomentum);
+        plotterIndex++;
+
+        // Create plot for diffence in track and cluster position
+		plotters.add(PlotUtils.setupPlotter("Track-Cluster Position Residual", 2, 2));
+		xPositionResidual = aida.histogram1D("x Residual", 100, -100, 100);
+		yPositionResidual = aida.histogram1D("y Residual", 100, -100, 100);
+		zPositionResidual = aida.histogram1D("z Residual", 100, -100, 100);
+		r = aida.histogram1D("r", 100, -100, 100);
+		PlotUtils.setup1DRegion(plotters.get(plotterIndex), "x Residual", 0, "delta x [mm]", xPositionResidual);
+		PlotUtils.setup1DRegion(plotters.get(plotterIndex), "y Residual", 1, "delta y [mm]", yPositionResidual);
+		PlotUtils.setup1DRegion(plotters.get(plotterIndex), "z Residual", 2, "delta z [mm]", zPositionResidual);
+		PlotUtils.setup1DRegion(plotters.get(plotterIndex), "r", 3, "r [mm]", r);
+        plotterIndex++; 
+
+        // Show all of the plotters
+        //for(IPlotter plotter : plotters) plotter.show(); 
+
+        
+    }
+    
+    /**
+     * 
+     */
+    protected void process(EventHeader event)
+    {
+        eventNumber++;
+        
+        // First check if the event contains a collection of Ecal clusters.  If
+        // it doesn't skip the event.
+        if(!event.hasCollection(HPSEcalCluster.class, ecalClustersCollectionName)) return;
+       
+        // Get the list of Ecal clusters in the event
+        List<HPSEcalCluster> ecalClusters = event.get(HPSEcalCluster.class, ecalClustersCollectionName);
+       
+        // Get the list of tracks from the event
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+
+        // If the event has a single Ecal cluster satisfying the threshold cut, 
+        // check if there is a track that is well matched to the cluster
+        if(ecalClusters.size() == 1){
+        	HPSEcalCluster ecalCluster = ecalClusters.get(0);
+        	
+        	// If the cluster is above the energy threshold, then the track should
+        	// be findable
+        	if(!isClusterAboveEnergyThreshold(ecalCluster)) return;
+        	findableSingleTracks++;
+        	
+        	double[] clusterPosition = ecalCluster.getPosition();
+        	
+        	if(clusterPosition[0] > 0 && clusterPosition[1] > 0) 	   findableSingleTracksQuad1++;
+        	else if(clusterPosition[0] < 0 && clusterPosition[1] > 0) findableSingleTracksQuad2++;
+        	else if(clusterPosition[0] < 0 && clusterPosition[1] < 0) findableSingleTracksQuad3++;
+        	else if(clusterPosition[0] > 0 && clusterPosition[1] < 0) findableSingleTracksQuad4++;	
+        	
+        	if(!isClusterMatchedToTrack(ecalCluster, tracks)) return;
+        	foundSingleTracks++;
+
+        	if(clusterPosition[0] > 0 && clusterPosition[1] > 0) 	   foundSingleTracksQuad1++;
+        	else if(clusterPosition[0] < 0 && clusterPosition[1] > 0) foundSingleTracksQuad2++;
+        	else if(clusterPosition[0] < 0 && clusterPosition[1] < 0) foundSingleTracksQuad3++;
+        	else if(clusterPosition[0] > 0 && clusterPosition[1] < 0) foundSingleTracksQuad4++;	
+        }
+        
+        // Only look at events which have two Ecal cluster 
+        if(ecalClusters.size() != 2) return;
+
+        // Check that the Ecal clusters are in opposite Ecal volumes. If 
+       	// they don't, skip the event.
+       	if(!hasClustersInOppositeVolumes(ecalClusters)){
+       		this.printDebug("Ecal clusters are not in opposite volumes");
+       		return;
+       	}
+       	nOppositeVolume++;
+      
+       	// Check that the Ecal clusters lie within some pre-defined window. If
+       	// they don't, skip the event. 
+        if(!isClusterWithinWindow(ecalClusters.get(0)) || !isClusterWithinWindow(ecalClusters.get(1))){
+        		this.printDebug("Ecal cluster falls outside of window.");
+        		return;        	
+        }
+        nWithinWindow++;
+       
+        // Check that the Ecal clusters are above the threshold energy.  If 
+        // they don't, skip the event.
+        if(!isClusterAboveEnergyThreshold(ecalClusters.get(0)) || !isClusterAboveEnergyThreshold(ecalClusters.get(1))){
+        		this.printDebug("Ecal cluster energies are below threshold.");
+        		return;        	        	
+        }
+       	nAboveThreshold++;
+ 
+       	// Check that the difference between the Ecal cluster energies is 
+        // reasonable
+       	double energyDiff = Math.abs(ecalClusters.get(0).getEnergy() - ecalClusters.get(1).getEnergy()); 
+       	if(energyDiff > energyDifference){
+       		this.printDebug("The energy difference between the two clusters is too great.");
+       		return;
+       	}
+       
+        // Check if the event contains a collection of tracks.  If it doesn't,
+        // move on to the next event.
+        if(!event.hasCollection(Track.class, trackCollectionName)){
+        	this.printDebug("Event doesn't contain a collection of tracks!");
+        	return;
+        }
+
+
+        // If there are no tracks in the collection, move on to the next event. 
+        if(tracks.isEmpty()){
+        	this.printDebug("Event doesn't contain any tracks!");
+        	return;  
+        }
+       
+        // Sort the tracks by SVT volume
+    	topTracks = new ArrayList<Track>();
+    	botTracks = new ArrayList<Track>();
+        for(Track track : tracks){
+    		if(track.getTrackStates().get(0).getZ0() > 0)  topTracks.add(track);
+    		else if(track.getTrackStates().get(0).getZ0() < 0) botTracks.add(track);
+    	}
+        
+       	// Get the trigger information from the event
+       	List<GenericObject> triggerData = event.get(GenericObject.class, triggerDataCollectionName);
+       	GenericObject triggerDatum = triggerData.get(0);
+       	if(triggerDatum.getIntVal(4) > 0){
+       		this.printDebug("Ecal triggered by top cluster");
+       		topTrigger = true;
+       	} else if(triggerDatum.getIntVal(5) > 0){
+       		this.printDebug("Ecal triggered by bottom cluster");       		
+       		topTrigger = false;
+       	}
+       	
+       	// Match a track to the trigger cluster
+       	HPSEcalCluster matchedCluster = null; 
+       	for(HPSEcalCluster ecalCluster : ecalClusters){
+       		if(ecalCluster.getPosition()[1] > 0 && topTrigger){
+       			if(!isClusterMatchedToTrack(ecalCluster, topTracks)){
+       				this.printDebug("Trigger cluster-track match was not found.");
+       				return;
+       			}
+       			matchedCluster = ecalCluster; 
+       			findableBottomTracks++;
+       			break;
+       		} else if( ecalCluster.getPosition()[1] < 0 && !topTrigger){
+       			if(!isClusterMatchedToTrack(ecalCluster, botTracks)){
+       				this.printDebug("Trigger cluster-track match was not found.");
+       				return;
+       			}
+       			matchedCluster = ecalCluster;
+       			findableTopTracks++;
+       			break;
+       		}
+       	}
+       	if(matchedCluster != null) ecalClusters.remove(matchedCluster);
+       	nTrigClusterTrackMatch++;
+       	
+        // If the cluster passes all requirements, then there is likely a track
+        // associated with it
+        findableTracks++;
+        
+        // Now check if a track is associated with the non-trigger cluster
+        if(topTrigger){
+       			if(!isClusterMatchedToTrack(ecalClusters.get(0), botTracks)){
+       				this.printDebug("Non trigger cluster-track match was not found.");
+       				return;
+       			}
+       			totalBottomTracks++;
+        } else if(!topTrigger){
+       			if(!isClusterMatchedToTrack(ecalClusters.get(0), topTracks)){
+       				this.printDebug("Non trigger cluster-track match was not found.");
+       				return;
+       			}        	       
+       			totalTopTracks++;
+        } 
+        ++totalTracks; 
+    }    
+
+    /**
+     * 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);
+        }
+    }
+    
+    /**
+     * 
+     */
+    private boolean isClusterWithinWindow(HPSEcalCluster clusterPosition){
+    	return true;
+    }
+    
+    /**
+     * 
+     */
+    private boolean isClusterAboveEnergyThreshold(HPSEcalCluster ecalCluster){
+    	if(ecalCluster.getEnergy() > thresholdEnergy) return true;
+    	return false;
+    }
+     
+    /**
+     * 
+     */
+    private boolean hasClustersInOppositeVolumes(List<HPSEcalCluster> ecalClusters){
+    	this.printPosition(ecalClusters.get(0).getPosition());
+    	this.printPosition(ecalClusters.get(1).getPosition());
+    	if((ecalClusters.get(0).getPosition()[1] > 0 && ecalClusters.get(1).getPosition()[1] < 0)
+    			|| (ecalClusters.get(0).getPosition()[1] < 0 && ecalClusters.get(1).getPosition()[1] > 0)){
+    		return true; 	
+    	}
+    	return false;
+    }
+    
+    /**
+     * 
+     */
+    private boolean isClusterMatchedToTrack(HPSEcalCluster cluster, List<Track> tracks){
+    	Hep3Vector clusterPos = new BasicHep3Vector(cluster.getPosition());
+    	double rMax = Double.MAX_VALUE;
+    	Track matchedTrack = null; 
+    	for(Track track : tracks){
+    		
+    		Hep3Vector trkPosAtShowerMax = TrackUtils.extrapolateTrack(track,clusterPos.z());
+    		if(Double.isNaN(trkPosAtShowerMax.x()) || Double.isNaN(trkPosAtShowerMax.y())){
+    			this.printDebug("Invalid track position");
+    			return false; 
+    		}
+    		this.printDebug("Track position at shower max: " + trkPosAtShowerMax.toString());
+ 
+    		// Find the distance between the track position at shower
+    		// max and the cluster position
+    		double r = VecOp.sub(trkPosAtShowerMax, clusterPos).magnitude();
+    		this.printDebug("Distance between Ecal cluster and track position at shower max: " + r + " mm");
+        	
+    		// Check if the track is the closest to the cluster.  If it is, then
+    		// save the track and contineu looping over all other tracks
+    		if (r < rMax /*&& r <= maxTrackClusterDistance*/) {
+    			rMax = r;
+    			matchedTrack = track;
+    		}
+    	}
+    	if(matchedTrack != null) return true;
+    	return false;
+    }
+    
+    /**
+     * 
+     */
+    private void printPosition(double[] position){
+    	this.printDebug("[ " + position[0] + ", " + position[1] + ", " + position[2] + " ]");
+    }
+    
+    
+    @Override
+    public void endOfData(){ 
+        System.out.println("%===================================================================% \n");
+        if(findableSingleTracks > 0){
+        	System.out.println("% Total single track efficiency: " + foundSingleTracks + " / " + findableSingleTracks + " = " + (foundSingleTracks/findableSingleTracks)*100 + "%");
+        }
+        if(findableSingleTracksQuad1 > 0){
+        	System.out.println("% Total single track efficiency - Quad 1: " + foundSingleTracksQuad1 + " / " + findableSingleTracksQuad1 + " = " + (foundSingleTracksQuad1/findableSingleTracksQuad1)*100 + "%");
+        }
+        if(findableSingleTracksQuad2 > 0){
+        	System.out.println("% Total single track efficiency - Quad 2: " + foundSingleTracksQuad2 + " / " + findableSingleTracksQuad2 + " = " + (foundSingleTracksQuad2/findableSingleTracksQuad2)*100 + "%");
+        }
+        if(findableSingleTracksQuad3 > 0){
+        	System.out.println("% Total single track efficiency - Quad 3: " + foundSingleTracksQuad3 + " / " + findableSingleTracksQuad3 + " = " + (foundSingleTracksQuad3/findableSingleTracksQuad3)*100 + "%");
+        }
+        if(findableSingleTracksQuad4 > 0){
+        	System.out.println("% Total single track efficiency - Quad 4: " + foundSingleTracksQuad4 + " / " + findableSingleTracksQuad4 + " = " + (foundSingleTracksQuad4/findableSingleTracksQuad4)*100 + "%");
+        }
+        if(nOppositeVolume > 0){
+        	System.out.println("% Total events passing opposite volume requirement: " + nOppositeVolume + " / " + eventNumber + " = " + (nOppositeVolume/eventNumber)*100 + "%");
+        }
+        if(nAboveThreshold > 0){
+        	System.out.println("% Total events with both clusters above energy threshold: " + nAboveThreshold + " / " + eventNumber + " = " + (nAboveThreshold/eventNumber)*100 + "%");
+        }
+        if(nTrigClusterTrackMatch > 0){
+        	System.out.println("% Total events with a trigger cluster-track match: " + nTrigClusterTrackMatch + " / " + eventNumber + " = " + (nTrigClusterTrackMatch/eventNumber)*100 + "%");
+        }
+        if(findableTracks > 0){
+            System.out.println("% Total Track Reconstruction Efficiency: " + totalTracks + " / " + findableTracks + " = " + (totalTracks / findableTracks) * 100 + "%");
+        }
+        if(findableTopTracks > 0){
+            System.out.println("% Total Top Track Reconstruction Efficiency: " + totalTopTracks + " / " + findableTopTracks + " = " + (totalTopTracks / findableTopTracks)* 100 + "%");
+        }
+        if(findableBottomTracks > 0){
+            System.out.println("% Total Bottom Track Reconstruction Efficiency: " + totalBottomTracks + " / " + findableBottomTracks + " = " + (totalBottomTracks / findableBottomTracks) * 100 + "%");
+        }
+        System.out.println("\n%===================================================================% \n");
+    }
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
AlignmentUtils.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/AlignmentUtils.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/AlignmentUtils.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,1648 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.matrix.MatrixOp;
+import hep.physics.vec.*;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+
+/**
+ *
+ * @author phansson
+ */
+public class AlignmentUtils {
+    
+    
+    private int _debug;
+    
+
+    public AlignmentUtils() {
+        _debug = 0;
+    }
+    public AlignmentUtils(boolean debug) {
+        _debug = debug ? 1 : 0;
+    }
+    public void setDebug(boolean debug) {
+        _debug = debug ? 1 : 0;
+    }
+    public void setDebug(int debug) {
+        _debug = debug;
+    }
+
+    public Hep3Matrix getRotationMatrix(String axis, double angle) {
+        Hep3Matrix m;
+        if(axis.equalsIgnoreCase("x")) m = new BasicHep3Matrix(1,0,0,0,Math.cos(angle),Math.sin(angle),0,-Math.sin(angle),Math.cos(angle));
+        else if(axis.equalsIgnoreCase("y")) m = new BasicHep3Matrix(Math.cos(angle),0,-Math.sin(angle),0,1,0,Math.sin(angle),0,Math.cos(angle));
+        else if (axis.equalsIgnoreCase("z")) m = new BasicHep3Matrix(Math.cos(angle),Math.sin(angle),0,-Math.sin(angle),Math.cos(angle),0,0,0,1);
+        else throw new RuntimeException(this.getClass().getSimpleName()+": axis " + axis + " is not valid!!");
+        return m;
+    }
+    
+    
+    public Hep3Matrix getRotationMatrixAroundX(double angle) {
+        return  new BasicHep3Matrix(1,0,0,0,Math.cos(angle),-Math.sin(angle),0,Math.sin(angle),Math.cos(angle));
+    }
+
+    
+    
+    public BasicMatrix calculateLocalHelixDerivatives(HelicalTrackFit trk, double xint) {
+        
+        // Calculate the derivative w.r.t. to the track parameters (in order/index):
+        // d0, z0, slope, phi0, R
+        // for a change in x,y,z
+        //
+        // All the below is in the tracking coordonates:
+        // x-axis is beamline direction
+        // y-axis is bend direction
+        // z-axis is non-bend direction
+        //
+        // The return object is a 3-by-5 matrix with the derivatives.
+        //
+        // Input:
+        double xr = 0.0; // reference position - typically set top PCA i.e. (x0,y0)
+        double yr = 0.0; // reference position - typically set top PCA i.e. (x0,y0)
+        double d0 = trk.dca();
+        double phi0 = trk.phi0();
+        double R = trk.R();
+        double slope = trk.slope();
+        double s = HelixUtils.PathToXPlane(trk, xint, 0, 0).get(0);
+        double phi = -s/R + phi0;
+        BasicMatrix dfdq = new BasicMatrix(3,5); //3-dim,ntrackparams
+        
+        
+        dfdq.setElement(0, 0, this.dx_dd0(xint, d0, phi0, R, phi));
+        dfdq.setElement(0, 1, this.dx_dz0(R, phi));
+        dfdq.setElement(0, 2, this.dx_dslope(R, phi));
+        dfdq.setElement(0, 3, this.dx_dphi0(xint, d0, phi0, R, phi));
+        dfdq.setElement(0, 4, this.dx_dR(xint, xr, yr, d0, phi0, R, phi));
+        
+        
+        dfdq.setElement(1, 0, this.dy_dd0(xint, d0, phi0, R, phi));
+        dfdq.setElement(1, 1, this.dy_dz0(R, phi));
+        dfdq.setElement(1, 2, this.dy_dslope(R, phi));
+        dfdq.setElement(1, 3, this.dy_dphi0(xint, d0, phi0, R, phi));
+        dfdq.setElement(1, 4, this.dy_dR(xint, d0, phi0, R, phi));
+        
+        
+        dfdq.setElement(2, 0, this.dz_dd0(xint, d0, phi0, slope, R));
+        dfdq.setElement(2, 1, this.dz_dz0());
+        dfdq.setElement(2, 2, this.dz_dslope(phi0, R, phi));
+        dfdq.setElement(2, 3, this.dz_ddphi0(s, d0, phi0, slope, R));
+        dfdq.setElement(2, 4, this.dz_dR(xint, d0, phi0, slope, R, phi));
+        
+        
+        return dfdq;
+        
+    }
+
+    
+    private BasicMatrix FillMatrix(double[][] array, int nrow, int ncol) {
+        BasicMatrix retMat = new BasicMatrix(nrow, ncol);
+        for (int i = 0; i < nrow; i++) {
+            for (int j = 0; j < ncol; j++) {
+                retMat.setElement(i, j, array[i][j]);
+            }
+        }
+        return retMat;
+    }
+
+    
+    
+    
+    //-----------------------------------
+    // Local derivatives of f in the x-direction
+    
+    
+    public double dx_dd0(double x, double d0, double phi0, double R, double phi) {
+        return -Math.sin(phi0) - R * Math.cos(phi)*dphi_dd0(x,d0,phi0,R);
+    }
+    public double dx_dz0(double R, double phi) {
+        return -R*Math.cos(phi)*dphi_dz0();
+    }
+    public double dx_dslope(double R, double phi) {
+        return R*Math.cos(phi)*dphi_dslope();
+    }
+    public double dx_dphi0(double x, double d0, double phi0, double R, double phi) {
+        return (R-d0)*Math.cos(phi0) - R*Math.cos(phi)*dphi_dphi0(x,d0,phi0,R);
+    }
+    public double dx_dR(double x, double xr, double yr, double d0, double phi0, double R, double phi) {
+        return Math.sin(phi0) - R*Math.cos(phi)*dphi_dR(x,d0,phi0,R) - Math.sin(phi);
+    }
+    
+    //-----------------------------------
+    
+    //-----------------------------------
+    // Local derivatives of f in the y-direction
+    
+    public double dy_dd0(double x, double d0, double phi0, double R, double phi) {
+        return Math.cos(phi0) - R*Math.sin(phi)*dphi_dd0(x, d0, phi0, R);
+    }
+    public double dy_dz0(double R, double phi) {
+        return -R*Math.sin(phi)*this.dphi_dz0();
+    }
+    public double dy_dslope(double R, double phi) {
+        return -R*Math.sin(phi)*this.dphi_dslope();
+    }
+    
+    public double dy_dphi0(double x, double d0, double phi0, double R, double phi) {
+        return (R-d0)*Math.sin(phi0) - R*Math.sin(phi)*this.dphi_dphi0(x, d0, phi0, R);
+    }
+    public double dy_dR(double x, double d0, double phi0, double R, double phi) {
+        return -Math.cos(phi0) - R*Math.sin(phi)*this.dphi_dR(x, d0, phi0, R) + Math.cos(phi);
+    }
+    
+    
+     //-----------------------------------
+    // Local derivatives of f in the z-direction
+
+    
+    public double dz_dd0(double x, double d0, double phi0, double slope, double R) {                
+        return -R*slope*this.dphi_dd0(x, d0, phi0, R);
+    }
+        
+    public double dz_dz0() {
+        return 1.0;
+    }
+
+    public double dz_dslope(double phi0, double R, double phi) {        
+        return -R*(phi-phi0);
+    }
+
+    public double dz_ddphi0(double x, double d0, double phi0, double slope, double R) {                
+        return -R*slope*(this.dphi_dphi0(x, d0, phi0, R)-1);
+    }
+    
+    public double dz_dR(double x, double d0, double phi0, double slope, double R, double phi) {
+        return -slope*(phi-phi0+R*this.dphi_dR(x, d0, phi0, R));
+    }
+
+    
+    //-----------------------------------
+    // Derivatives of phi w.r.t. track parameters
+
+    public double dphi_dd0(double x,double d0, double phi0, double R) {
+        double num = -1*Math.sin(phi0);
+        double den = R*Math.sqrt( 1 - Math.pow(x+(d0-R)*Math.sin(phi0), 2)/Math.pow(R,2));
+        return num/den;
+    }
+    
+    public double dphi_dz0() {
+        return 0;
+    }
+    public double dphi_dslope() {
+        return 0;
+    }
+    public double dphi_dphi0(double x,double d0, double phi0, double R) {
+        double num = -1*(d0-R)*Math.cos(phi0);
+        double den = R*Math.sqrt( 1 - Math.pow(x+(d0-R)*Math.sin(phi0),2)/Math.pow(R, 2));
+        return num/den;
+    }
+    
+    public double dphi_dR(double x,double d0, double phi0, double R) {
+        double num = x + d0*Math.sin(phi0);
+        double den = Math.pow(R, 2)*Math.sqrt( 1 - Math.pow(x+(d0-R)*Math.sin(phi0),2)/Math.pow(R, 2));
+        return num/den;
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    public double dphi_dx(double xint, double d0, double phi0, double R) {
+        double num = -1.0;
+        double A_x = -xint + (-d0+R)*Math.sin(phi0);
+        double den = R*Math.sqrt(1-(A_x*A_x)/(R*R));
+        return num/den;
+//        double num = -Math.pow(R, 2)*sign(R);
+//        double den1 = Math.sqrt( Math.pow(R, 2) - Math.pow(xint+(d0-R)*Math.sin(phi0), 2)   );
+//        double den2 = -Math.pow(xint+(d0-R)*Math.sin(phi0),2);
+//        double den3 = sign(R)*sign(R)*(-Math.pow(R, 2)+Math.pow(xint, 2)+2*(d0-R)*xint*Math.sin(phi0)+Math.pow(d0-R,2)*Math.pow(Math.sin(phi0),2) );
+//        return num/(den1*(den2+den3));
+    }
+
+    public double dphi_dy(double y, double d0, double phi0, double R, double phi) {    
+        double A_y = y + (-d0+R)*Math.cos(phi0);
+        double num = A_y * Math.signum(R);
+        double den = R*Math.sqrt(R*R-A_y*A_y)*Math.sqrt( 1 - (R*R-A_y*A_y)/(R*R));
+        return num/den; 
+//        double c0 = Math.cos(phi0);
+//        double num = Math.pow(R,2)*sign(R)*sign(R);
+//        double den1 = Math.sqrt(Math.pow(R, 2)-Math.pow(y+(d0-R)*c0, 2));
+//        double den2 = -Math.pow(y+(d0-R)*c0,2);
+//        double den3 =  (-Math.pow(R,2) + Math.pow(y, 2) + 2*(d0-R)*y*c0 + Math.pow(d0-R, 2)*Math.pow(c0, 2))*sign(R)*sign(R);        
+//        return num/(den1*(den2+den3));
+    }
+
+    public double dphi_dz(double slope, double R) {
+        return -1/(R*slope);
+    }
+
+    
+    
+    
+    
+    
+    //-----------------------------------
+    // Derivatives for translation
+    
+    public double dx_dx() {
+        return 1;
+    }
+    
+    public double dy_dx(double xint, double d0, double phi0, double R, double phi) { 
+        return -R*Math.sin(phi)*this.dphi_dx(xint, d0, phi0, R);
+    }
+    
+    public double dz_dx(double xint, double xr,double yr,double d0, double phi0, double slope, double R) {   
+        return -R*slope*this.dphi_dx(xint, d0, phi0, R);
+    }
+    
+    public double dx_dy(double y, double d0, double phi0, double R, double phi) {
+        return -R*Math.cos(phi)*this.dphi_dy(y, d0, phi0, R, phi);
+    }
+     
+    public double dy_dy() {
+        return 1;
+    }
+    
+    public double dz_dy(double y,double d0, double phi0, double slope, double R, double phi) {
+        return -R*slope*this.dphi_dy(y, d0, phi0, R, phi);
+    }
+     
+
+    public double dx_dz(double slope, double R, double phi) {
+        return -R*Math.cos(phi)*this.dphi_dz(slope, R);
+        //return sign(R)*R*Math.cos(phi)*this.dphi_dz(slope, R);
+    }   
+    
+    public double dy_dz(double slope, double R, double phi) {     
+        return -R*Math.sin(phi)*this.dphi_dz(slope, R);
+        //return -sign(R)*R*Math.sin(phi)*this.dphi_dz(slope, R);
+    }
+    
+    public double dz_dz() {
+        return 1;
+    }
+    
+    
+   
+    
+    public Hep3Matrix rotationDer_da() {
+        /*
+         * Derivative w.r.t. a of a rotation matrix with small Euler angles a,b,c around axis x,y,z
+         * Small angle limit
+         */
+        return new BasicHep3Matrix(0,0,0,0,0,1,0,-1,0);
+    }
+    public Hep3Matrix rotationDer_db() {
+        /*
+         * Derivative w.r.t. b of a rotation matrix with Euler angles a,b,c around axis x,y,z
+         * Small angle limit
+         */
+        return new BasicHep3Matrix(0,0,-1,0,0,0,1,0,0);
+    }
+    public Hep3Matrix rotationDer_dc() {
+        /*
+         * Derivative w.r.t. c of a rotation matrix with Euler angles a,b,c around axis x,y,z
+         * Small angle limit
+         */
+        return new BasicHep3Matrix(0,1,0,-1,0,0,0,0,0);
+    }
+    
+    
+    
+    public BasicMatrix calculateJacobian(Hep3Vector x_vec, Hep3Matrix T) {
+        /*
+         * Calculate jacobian da/db
+         * Arguments:
+         * Hep3Matrix T is the 3x3 rotation matrix from the global/tracking to local frame
+         * Hep3Vector x_vec is the position of the track on the sensor
+         */
+        
+
+        //Derivatives of the rotation matrix deltaR' w.r.t. rotations a,b,c around axis x,y,z
+        Hep3Matrix ddeltaRprime_da = rotationDer_da();
+        Hep3Matrix ddeltaRprime_db = rotationDer_db();
+        Hep3Matrix ddeltaRprime_dc = rotationDer_dc();
+
+        if(_debug>1) {
+            System.out.printf("%s: Rotation matrx from tracking/global to local frame T:\n %s\n",this.getClass().getSimpleName(),T.toString());
+            System.out.printf("%s: Derivatives of the rotation matrix deltaR' w.r.t. rotation a,b,c around x,y,z axis:\n",this.getClass().getSimpleName());
+            System.out.printf("%s: ddeltaRprime_da:\n %s\n",this.getClass().getSimpleName(),ddeltaRprime_da.toString());
+            System.out.printf("%s: ddeltaRprime_db:\n %s\n",this.getClass().getSimpleName(),ddeltaRprime_db.toString());
+            System.out.printf("%s: ddeltaRprime_dc:\n %s\n",this.getClass().getSimpleName(),ddeltaRprime_dc.toString());
+        }
+        
+        
+        
+        
+        // Upper left 3x3
+        Hep3Vector deltaX_gl =  new BasicHep3Vector(1,0,0);    
+        Hep3Vector deltaY_gl =  new BasicHep3Vector(0,1,0);    
+        Hep3Vector deltaZ_gl =  new BasicHep3Vector(0,0,1);    
+        Hep3Vector dq_dx = VecOp.mult(T, deltaX_gl);
+        Hep3Vector dq_dy = VecOp.mult(T, deltaY_gl);
+        Hep3Vector dq_dz = VecOp.mult(T, deltaZ_gl);
+        
+        if(_debug>1) {
+            System.out.printf("%s: - Upper left 3x3 of Jacobian da/db: dq_dx,dq_dy,dq_dz\n",this.getClass().getSimpleName());
+            System.out.printf("%s: dq_dx: %s\n",this.getClass().getSimpleName(),dq_dx.toString());
+            System.out.printf("%s: dq_dy: %s\n",this.getClass().getSimpleName(),dq_dy.toString());
+            System.out.printf("%s: dq_dz: %s\n",this.getClass().getSimpleName(),dq_dz.toString());
+        }
+        
+       
+        
+        if(_debug>1) {
+            System.out.printf("%s: - Upper right 3x3 of Jacobian da/db: dq_dx,dq_dy,dq_dz\n",this.getClass().getSimpleName());
+        }
+        
+        
+        // Upper right 3x3
+        
+        Hep3Vector x_vec_tmp = VecOp.mult(ddeltaRprime_da, x_vec); // derivative of the position
+        Hep3Vector x_vec_tmp2 = VecOp.sub(x_vec_tmp, x_vec); // subtract position
+        Hep3Vector dq_da = VecOp.mult(T,x_vec_tmp2); //rotated into local frame
+        
+        if(_debug>1) {
+            System.out.printf("%s: position   %s rotation derivative w.r.t. a ddeltaR'/da %s\n",this.getClass().getSimpleName(),x_vec.toString(),x_vec_tmp.toString());
+            System.out.printf("%s: subtracted %s and rotated to local %s \n",this.getClass().getSimpleName(),x_vec_tmp2.toString(),dq_da.toString());
+        }
+        
+        
+        x_vec_tmp = VecOp.mult(ddeltaRprime_db, x_vec);
+        x_vec_tmp2 = VecOp.sub(x_vec_tmp, x_vec); 
+        Hep3Vector dq_db = VecOp.mult(T,x_vec_tmp2);
+        
+        if(_debug>1) {
+            System.out.printf("%s: position   %s rotation derivative w.r.t. a ddeltaR'/db %s\n",this.getClass().getSimpleName(),x_vec.toString(),x_vec_tmp.toString());
+            System.out.printf("%s: subtracted %s and rotated to local %s \n",this.getClass().getSimpleName(),x_vec_tmp2.toString(),dq_db.toString());
+        }
+        
+        x_vec_tmp = VecOp.mult(ddeltaRprime_dc, x_vec);
+        x_vec_tmp2 = VecOp.sub(x_vec_tmp, x_vec); 
+        Hep3Vector dq_dc = VecOp.mult(T,x_vec_tmp2);
+
+        if(_debug>1) {
+            System.out.printf("%s: position   %s rotation derivative w.r.t. a ddeltaR'/dc %s\n",this.getClass().getSimpleName(),x_vec.toString(),x_vec_tmp.toString());
+            System.out.printf("%s: subtracted %s and rotated to local %s \n",this.getClass().getSimpleName(),x_vec_tmp2.toString(),dq_dc.toString());
+        }
+        
+    
+        if(_debug>1) {
+            System.out.printf("%s: Summary:\n",this.getClass().getSimpleName());
+            System.out.printf("%s: dq_da: %s\n",this.getClass().getSimpleName(),dq_da.toString());
+            System.out.printf("%s: dq_db: %s\n",this.getClass().getSimpleName(),dq_db.toString());
+            System.out.printf("%s: dq_dc: %s\n",this.getClass().getSimpleName(),dq_dc.toString());
+        }
+        
+        
+       
+        
+        // Lower left 3x3
+        //deltaR = (alpha,beta,gamma) the rotation alignment parameters in the local frame
+        Hep3Vector ddeltaR_dx = new BasicHep3Vector(0,0,0);
+        Hep3Vector ddeltaR_dy = new BasicHep3Vector(0,0,0);
+        Hep3Vector ddeltaR_dz = new BasicHep3Vector(0,0,0);
+
+        
+        if(_debug>1) {
+            System.out.printf("%s: - Lower left 3x3 of Jacobian ddeltaR/d(x,y,z): dDeltaR_dx,dDeltaR_dy,dDeltaR_dz\n",this.getClass().getSimpleName());
+            System.out.printf("%s: ddeltaR_dx: %s\n",this.getClass().getSimpleName(),ddeltaR_dx.toString());
+            System.out.printf("%s: ddeltaR_dy: %s\n",this.getClass().getSimpleName(),ddeltaR_dy.toString());
+            System.out.printf("%s: ddeltaR_dz: %s\n",this.getClass().getSimpleName(),ddeltaR_dz.toString());
+        }
+        
+        
+     
+        
+        // Lower right 3x3
+/*
+        //deltaR = (alpha,beta,gamma) the rotation alignment parameters in the local frame
+        //Expressing T in Euler angles i,j,k
+        double i = 0;
+        double j = 0;
+        double k = 0;
+        double dalpha_da = Math.cos(k)*Math.sin(i)*Math.sin(j) + Math.cos(i)*Math.sin(k);
+        double dbeta_da = Math.cos(i)*Math.cos(k) - Math.sin(i)*Math.sin(j)*Math.sin(k);
+        double dgamma_da = -Math.cos(j)*Math.sin(i);
+        double dalpha_db = -Math.cos(i)*Math.cos(k)*Math.sin(j) + Math.sin(i)*Math.sin(k);
+        double dbeta_db = Math.cos(k)*Math.sin(i) + Math.cos(i)*Math.sin(j)*Math.sin(k);
+        double dgamma_db = Math.cos(i)*Math.cos(j);
+        double dalpha_dc = -Math.cos(i)*Math.cos(k)*Math.sin(j) + Math.sin(i)*Math.sin(k);
+        double dbeta_dc = Math.cos(k)*Math.sin(i) + Math.cos(i)*Math.sin(j)*Math.sin(k);
+        double dgamma_dc = Math.sin(i)*Math.sin(j);
+        
+        Hep3Vector ddeltaR_da = new BasicHep3Vector(dalpha_da,dbeta_da,dgamma_da);
+        Hep3Vector ddeltaR_db = new BasicHep3Vector(dalpha_db,dbeta_db,dgamma_db);
+        Hep3Vector ddeltaR_dc = new BasicHep3Vector(dalpha_dc,dbeta_dc,dgamma_dc);
+*/
+        
+        if(_debug>1) {
+            System.out.printf("%s: - Lower right 3x3 of Jacobian ddeltaR/d(a,b,c): \n",this.getClass().getSimpleName());
+            System.out.printf("%s: T: %s\n",this.getClass().getSimpleName(),T.toString());
+        }
+
+        
+        
+        //Now fill the Jacobian 6x6 matrix
+        BasicMatrix da_db = new BasicMatrix(6,6);
+        //upper left 3x3
+        da_db.setElement(0,0,dq_dx.x());
+        da_db.setElement(1,0,dq_dx.y());
+        da_db.setElement(2,0,dq_dx.z());
+        da_db.setElement(0,1,dq_dy.x());
+        da_db.setElement(1,1,dq_dy.y());
+        da_db.setElement(2,1,dq_dy.z());
+        da_db.setElement(0,2,dq_dz.x());
+        da_db.setElement(1,2,dq_dz.y());
+        da_db.setElement(2,2,dq_dz.z());
+        //upper right 3x3
+        da_db.setElement(0,3,dq_da.x());
+        da_db.setElement(1,3,dq_da.y());
+        da_db.setElement(2,3,dq_da.z());
+        da_db.setElement(0,4,dq_db.x());
+        da_db.setElement(1,4,dq_db.y());
+        da_db.setElement(2,4,dq_db.z());
+        da_db.setElement(0,5,dq_dc.x());
+        da_db.setElement(1,5,dq_dc.y());
+        da_db.setElement(2,5,dq_dc.z());
+        //lower right 3x3
+        da_db.setElement(3,3,T.e(0, 0));
+        da_db.setElement(4,3,T.e(1, 0));
+        da_db.setElement(5,3,T.e(2, 0));
+        da_db.setElement(3,4,T.e(0, 1));
+        da_db.setElement(4,4,T.e(1, 1));
+        da_db.setElement(5,4,T.e(2, 1));
+        da_db.setElement(3,5,T.e(0, 2));
+        da_db.setElement(4,5,T.e(1, 2));
+        da_db.setElement(5,5,T.e(2, 2));
+//        da_db.setElement(4,3,ddeltaR_da.y());
+//        da_db.setElement(5,3,ddeltaR_da.z());
+//        da_db.setElement(3,4,ddeltaR_db.x());
+//        da_db.setElement(4,4,ddeltaR_db.y());
+//        da_db.setElement(5,4,ddeltaR_db.z());
+//        da_db.setElement(3,5,ddeltaR_dc.x());
+//        da_db.setElement(4,5,ddeltaR_dc.y());
+//        da_db.setElement(5,5,ddeltaR_dc.z());
+        //lower left 3x3
+        da_db.setElement(3,0,ddeltaR_dx.x());
+        da_db.setElement(4,0,ddeltaR_dx.y());
+        da_db.setElement(5,0,ddeltaR_dx.z());
+        da_db.setElement(3,1,ddeltaR_dy.x());
+        da_db.setElement(4,1,ddeltaR_dy.y());
+        da_db.setElement(5,1,ddeltaR_dy.z());
+        da_db.setElement(3,2,ddeltaR_dz.x());
+        da_db.setElement(4,2,ddeltaR_dz.y());
+        da_db.setElement(5,2,ddeltaR_dz.z());
+        
+        if(_debug>1) {
+            System.out.printf("%s: da_db:\n%s \n",this.getClass().getSimpleName(),da_db.toString());
+            System.out.printf("%s: det(da_db) = %.3f \n",this.getClass().getSimpleName(),da_db.det());
+        }
+        
+        return da_db;
+        
+    }
+    
+    
+    
+    public void printJacobianInfo(BasicMatrix da_db) {
+    
+        System.out.printf("%s: Jacobian info ---\nda_db:\n%s \n",this.getClass().getSimpleName(),da_db.toString());
+        System.out.printf("du_dx = %8.3f du_dy = %8.3f du_dz = %8.3f\n",da_db.e(0,0),da_db.e(0,1),da_db.e(0,2));
+        System.out.printf("dv_dx = %8.3f dv_dy = %8.3f dv_dz = %8.3f\n",da_db.e(1,0),da_db.e(1,1),da_db.e(1,2));
+        System.out.printf("dw_dx = %8.3f dw_dy = %8.3f dw_dz = %8.3f\n",da_db.e(2,0),da_db.e(2,1),da_db.e(2,2));
+        System.out.printf("du_da = %8.3f du_db = %8.3f du_dc = %8.3f\n",da_db.e(0,3),da_db.e(0,4),da_db.e(0,5));
+        System.out.printf("dv_da = %8.3f dv_db = %8.3f dv_dc = %8.3f\n",da_db.e(1,3),da_db.e(1,4),da_db.e(1,5));
+        System.out.printf("dw_da = %8.3f dw_db = %8.3f dw_dc = %8.3f\n",da_db.e(2,3),da_db.e(2,4),da_db.e(2,5));
+        System.out.printf("dalpha_dx = %8.3f dalpha_dy = %8.3f dalpha_dz = %8.3f\n",da_db.e(3,0),da_db.e(3,1),da_db.e(3,2));
+        System.out.printf("dbeta_dx  = %8.3f dbeta_dy  = %8.3f dbeta_dz  = %8.3f\n",da_db.e(4,0),da_db.e(4,1),da_db.e(4,2));
+        System.out.printf("dgamma_dx = %8.3f dgamma_dy = %8.3f dgamma_dz = %8.3f\n",da_db.e(5,0),da_db.e(5,1),da_db.e(5,2));
+        System.out.printf("dalpha_da = %8.3f dalpha_db = %8.3f dalpha_dc = %8.3f\n",da_db.e(3,3),da_db.e(3,4),da_db.e(3,5));
+        System.out.printf("dbeta_da  = %8.3f dbeta_db  = %8.3f dbeta_dc  = %8.3f\n",da_db.e(4,3),da_db.e(4,4),da_db.e(4,5));
+        System.out.printf("dgamma_da = %8.3f dgamma_db = %8.3f dgamma_dc = %8.3f\n",da_db.e(5,3),da_db.e(5,4),da_db.e(5,5));
+        
+    }
+    
+
+
+
+    public BasicMatrix calculateGlobalHitPositionDers(Hep3Vector x_vec) {
+
+        
+        //****************************************************************************
+        // Calculate the global derivatives in the global/tracking frame dq_a^gl/db
+        //  q_a^gl is the alignment corrected hit position in the global/tracking frame
+        // b = (dx,dy,dz,a,b,c) 
+        
+         
+        //Derivatives of the rotation matrix deltaR' w.r.t. rotations a,b,c around axis x,y,z
+        Hep3Matrix ddeltaRprime_da = rotationDer_da();
+        Hep3Matrix ddeltaRprime_db = rotationDer_db();
+        Hep3Matrix ddeltaRprime_dc = rotationDer_dc();
+
+        if(_debug>1) {
+            System.out.printf("%s: Derivatives of the rotation matrix deltaR' w.r.t. rotation a,b,c around x,y,z axis:\n",this.getClass().getSimpleName());
+            System.out.printf("%s: ddeltaRprime_da:\n %s\n",this.getClass().getSimpleName(),ddeltaRprime_da.toString());
+            System.out.printf("%s: ddeltaRprime_db:\n %s\n",this.getClass().getSimpleName(),ddeltaRprime_db.toString());
+            System.out.printf("%s: ddeltaRprime_dc:\n %s\n",this.getClass().getSimpleName(),ddeltaRprime_dc.toString());
+        }
+        
+        
+        
+        BasicMatrix dq_agl_db = new BasicMatrix(3,6);
+        //Translations
+        Hep3Vector dq_agl_dx = new BasicHep3Vector(1,0,0);
+        Hep3Vector dq_agl_dy = new BasicHep3Vector(0,1,0);
+        Hep3Vector dq_agl_dz = new BasicHep3Vector(0,0,1);
+        //Rotations
+        // Derivative of the rotations w.r.t. rotations a,b,c was already calculated above:
+        // but they need to be avaluated at the hit positon
+        Hep3Vector dq_agl_dalpha = VecOp.mult(ddeltaRprime_da,x_vec);
+        Hep3Vector dq_agl_dbeta = VecOp.mult(ddeltaRprime_db,x_vec);
+        Hep3Vector dq_agl_dgamma = VecOp.mult(ddeltaRprime_dc,x_vec);
+        
+        //put them all in one big matrix
+        
+        dq_agl_db.setElement(0, 0, dq_agl_dx.x());
+        dq_agl_db.setElement(1, 0, dq_agl_dx.y());
+        dq_agl_db.setElement(2, 0, dq_agl_dx.z());
+
+        dq_agl_db.setElement(0, 1, dq_agl_dy.x());
+        dq_agl_db.setElement(1, 1, dq_agl_dy.y());
+        dq_agl_db.setElement(2, 1, dq_agl_dy.z());
+
+        dq_agl_db.setElement(0, 2, dq_agl_dz.x());
+        dq_agl_db.setElement(1, 2, dq_agl_dz.y());
+        dq_agl_db.setElement(2, 2, dq_agl_dz.z());
+
+        dq_agl_db.setElement(0, 3, dq_agl_dalpha.x());
+        dq_agl_db.setElement(1, 3, dq_agl_dalpha.y());
+        dq_agl_db.setElement(2, 3, dq_agl_dalpha.z());
+
+        dq_agl_db.setElement(0, 4, dq_agl_dbeta.x());
+        dq_agl_db.setElement(1, 4, dq_agl_dbeta.y());
+        dq_agl_db.setElement(2, 4, dq_agl_dbeta.z());
+
+        dq_agl_db.setElement(0, 5, dq_agl_dgamma.x());
+        dq_agl_db.setElement(1, 5, dq_agl_dgamma.y());
+        dq_agl_db.setElement(2, 5, dq_agl_dgamma.z());
+
+        
+        
+        if(_debug>1) {
+            System.out.printf("%s: Translation derivative of the alignment corrected hit:\n",this.getClass().getSimpleName());
+            System.out.printf("dq_agl_dx=%s \ndq_agl_dy=%s \ndq_agl_dz=%s\n",dq_agl_dx.toString(),dq_agl_dy.toString(),dq_agl_dz.toString());
+            System.out.printf("%s: Rotation derivative of the alignment corrected hit evaluated at trkpos(or x_vec)=%s:\n",this.getClass().getSimpleName(),x_vec.toString());
+            System.out.printf("dq_agl_dalpha=%s \ndq_agl_dbeta=%s \ndq_agl_dgamma=%s\n",dq_agl_dalpha.toString(),dq_agl_dbeta.toString(),dq_agl_dgamma.toString());
+            System.out.printf("%s: Putting it together\ndq_agl_db:\n%s\n",this.getClass().getSimpleName(),dq_agl_db.toString());
+            
+            //cross-check using manual calculation from note
+            BasicMatrix dq_agl_db_tmp = new BasicMatrix(3,6);
+            dq_agl_db_tmp.setElement(0, 0, 1);
+            dq_agl_db_tmp.setElement(1, 0, 0);
+            dq_agl_db_tmp.setElement(2, 0, 0);
+
+            dq_agl_db_tmp.setElement(0, 1, 0);
+            dq_agl_db_tmp.setElement(1, 1, 1);
+            dq_agl_db_tmp.setElement(2, 1, 0);
+
+            dq_agl_db_tmp.setElement(0, 2, 0);
+            dq_agl_db_tmp.setElement(1, 2, 0);
+            dq_agl_db_tmp.setElement(2, 2, 1);
+
+            dq_agl_db_tmp.setElement(0, 3, 0);
+            dq_agl_db_tmp.setElement(1, 3, x_vec.z());
+            dq_agl_db_tmp.setElement(2, 3, -x_vec.y());
+
+            dq_agl_db_tmp.setElement(0, 4, -x_vec.z());
+            dq_agl_db_tmp.setElement(1, 4, 0);
+            dq_agl_db_tmp.setElement(2, 4, x_vec.x());
+
+            dq_agl_db_tmp.setElement(0, 5, x_vec.y());
+            dq_agl_db_tmp.setElement(1, 5, -x_vec.x());
+            dq_agl_db_tmp.setElement(2, 5, 0);
+            
+            System.out.printf("%s: Cross-check with this manual calculated matrix\ndq_agl_db_tmp:\n%s\n",this.getClass().getSimpleName(),dq_agl_db_tmp.toString());
+            
+        }
+
+        return dq_agl_db;
+         
+    }
+    
+    
+    public void printGlobalHitPositionDers(BasicMatrix dq_db) {
+    
+        System.out.printf("%s: Derivatives of the hit position w.r.t. to the global alignment parameters b: dq_agl_db---\n%s \n",this.getClass().getSimpleName(),dq_db.toString());
+        System.out.printf("dx_dx = %8.3f dx_dy = %8.3f dx_dz = %8.3f\n",dq_db.e(0,0),dq_db.e(0,1),dq_db.e(0,2));
+        System.out.printf("dy_dx = %8.3f dy_dy = %8.3f dy_dz = %8.3f\n",dq_db.e(1,0),dq_db.e(1,1),dq_db.e(1,2));
+        System.out.printf("dz_dx = %8.3f dz_dy = %8.3f dz_dz = %8.3f\n",dq_db.e(2,0),dq_db.e(2,1),dq_db.e(2,2));        
+        System.out.printf("dx_da = %8.3f dx_db = %8.3f dx_dc = %8.3f\n",dq_db.e(0,3),dq_db.e(0,4),dq_db.e(0,5));
+        System.out.printf("dy_dx = %8.3f dy_dy = %8.3f dy_dz = %8.3f\n",dq_db.e(1,3),dq_db.e(1,4),dq_db.e(1,5));
+        System.out.printf("dz_dx = %8.3f dz_dy = %8.3f dz_dz = %8.3f\n",dq_db.e(2,3),dq_db.e(2,4),dq_db.e(2,5));
+        
+    
+    }
+    
+    public void printGlobalPredictedHitPositionDers(BasicMatrix dq_db) {
+    
+        System.out.printf("%s: Derivatives of the predicted hit position w.r.t. to the global alignment parameters b: dq_pgl_db---\n%s \n",this.getClass().getSimpleName(),dq_db.toString());
+        System.out.printf("dx_dx = %8.3f dx_dy = %8.3f dx_dz = %8.3f\n",dq_db.e(0,0),dq_db.e(0,1),dq_db.e(0,2));
+        System.out.printf("dy_dx = %8.3f dy_dy = %8.3f dy_dz = %8.3f\n",dq_db.e(1,0),dq_db.e(1,1),dq_db.e(1,2));
+        System.out.printf("dz_dx = %8.3f dz_dy = %8.3f dz_dz = %8.3f\n",dq_db.e(2,0),dq_db.e(2,1),dq_db.e(2,2));        
+        System.out.printf("dx_da = %8.3f dx_db = %8.3f dx_dc = %8.3f\n",dq_db.e(0,3),dq_db.e(0,4),dq_db.e(0,5));
+        System.out.printf("dy_dx = %8.3f dy_dy = %8.3f dy_dz = %8.3f\n",dq_db.e(1,3),dq_db.e(1,4),dq_db.e(1,5));
+        System.out.printf("dz_dx = %8.3f dz_dy = %8.3f dz_dz = %8.3f\n",dq_db.e(2,3),dq_db.e(2,4),dq_db.e(2,5));
+        
+    
+    }
+    
+    
+    public void printGlobalResidualDers(BasicMatrix dz_db) {
+    
+        System.out.printf("%s: Derivatives of the residual z=q_a - q_p w.r.t. to the global alignment parameters b: dz_db---\n%s \n",this.getClass().getSimpleName(),dz_db.toString());
+        System.out.printf("dx_dx = %8.3f dx_dy = %8.3f dx_dz = %8.3f\n",dz_db.e(0,0),dz_db.e(0,1),dz_db.e(0,2));
+        System.out.printf("dy_dx = %8.3f dy_dy = %8.3f dy_dz = %8.3f\n",dz_db.e(1,0),dz_db.e(1,1),dz_db.e(1,2));
+        System.out.printf("dz_dx = %8.3f dz_dy = %8.3f dz_dz = %8.3f\n",dz_db.e(2,0),dz_db.e(2,1),dz_db.e(2,2));        
+        System.out.printf("dx_da = %8.3f dx_db = %8.3f dx_dc = %8.3f\n",dz_db.e(0,3),dz_db.e(0,4),dz_db.e(0,5));
+        System.out.printf("dy_da = %8.3f dy_db = %8.3f dy_dc = %8.3f\n",dz_db.e(1,3),dz_db.e(1,4),dz_db.e(1,5));
+        System.out.printf("dz_da = %8.3f dz_db = %8.3f dz_dc = %8.3f\n",dz_db.e(2,3),dz_db.e(2,4),dz_db.e(2,5));
+        
+    
+    }
+    
+    public void printLocalResidualDers(BasicMatrix dz_da) {
+    
+        System.out.printf("%s: Derivatives of the residual z=q_a - q_p w.r.t. to the local alignment parameters a: dz_da---\n%s \n",this.getClass().getSimpleName(),dz_da.toString());
+        System.out.printf("du_du =     %8.3f du_dv =    %8.3f du_dw =     %8.3f\n",dz_da.e(0,0),dz_da.e(0,1),dz_da.e(0,2));
+        System.out.printf("dv_du =     %8.3f dv_dv =    %8.3f dv_dw =     %8.3f\n",dz_da.e(1,0),dz_da.e(1,1),dz_da.e(1,2));
+        System.out.printf("dw_du =     %8.3f dw_dv =    %8.3f dw_dw =     %8.3f\n",dz_da.e(2,0),dz_da.e(2,1),dz_da.e(2,2));        
+        System.out.printf("du_dalpha = %8.3f du_dbeta = %8.3f du_dgamma = %8.3f\n",dz_da.e(0,3),dz_da.e(0,4),dz_da.e(0,5));
+        System.out.printf("dv_dalpha = %8.3f dv_dbeta = %8.3f dv_dgamma = %8.3f\n",dz_da.e(1,3),dz_da.e(1,4),dz_da.e(1,5));
+        System.out.printf("dw_dalpha = %8.3f dw_dbeta = %8.3f dw_dgamma = %8.3f\n",dz_da.e(2,3),dz_da.e(2,4),dz_da.e(2,5));
+        
+    
+    }
+    
+    
+    
+    public BasicMatrix calculateGlobalPredictedHitPositionDers(HelicalTrackFit trk, Hep3Vector x_vec) {
+            
+        double d0 = trk.dca();
+        double phi0 = trk.phi0();
+        double R = trk.R();
+        double s = HelixUtils.PathToXPlane(trk, x_vec.x(), 0, 0).get(0);
+        double phi = -s/R + phi0;
+        double slope = trk.slope();
+        double xr = 0.0; 
+        double yr = 0.0;
+        
+        
+        //Derivatives of the predicted hit position qp for a translation of in x,y,z
+            
+        BasicMatrix dq_pgl_dx = new BasicMatrix(3,1);
+        dq_pgl_dx.setElement(0, 0, dx_dx()); 
+        dq_pgl_dx.setElement(1, 0, dy_dx(x_vec.x(), d0, phi0, R, phi)); 
+        dq_pgl_dx.setElement(2, 0, dz_dx(x_vec.x(), xr, yr, d0, phi0, slope, R));
+
+        BasicMatrix dq_pgl_dy = new BasicMatrix(3,1);
+        dq_pgl_dy.setElement(0, 0, dx_dy(x_vec.y(), d0, phi0, R, phi));
+        dq_pgl_dy.setElement(1, 0, dy_dy());
+        dq_pgl_dy.setElement(2, 0, dz_dy(x_vec.y(), d0, phi0, slope, R, phi));
+        
+        BasicMatrix dq_pgl_dz = new BasicMatrix(3,1);
+        dq_pgl_dz.setElement(0, 0, dx_dz(slope, R, phi));
+        dq_pgl_dz.setElement(1, 0, dy_dz(slope, R, phi));
+        dq_pgl_dz.setElement(2, 0, dz_dz());
+
+        
+        
+        /*
+         * Derivatives of the predicted hit position qp for a rotation of a,b,c around x,y,z
+         * 
+         * Note that since these rotations are not around the center of the sensor 
+         * a rotation also leads to a translation, this is nto taken into account here
+         * Since the lever arm might be substantial this might be non-negligible?
+         * 
+        */
+
+        // THIS MIGHT NOT SINCE THE ROTATION IS NOT AROUND THE CENTER OF THE SENSOR!?
+        
+        Hep3Matrix ddeltaRprime_da = rotationDer_da();
+        Hep3Matrix ddeltaRprime_db = rotationDer_db();
+        Hep3Matrix ddeltaRprime_dc = rotationDer_dc();
+        
+        Hep3Vector dq_pgl_drota = VecOp.mult(ddeltaRprime_da, x_vec);
+        Hep3Vector dq_pgl_drotb = VecOp.mult(ddeltaRprime_db, x_vec);
+        Hep3Vector dq_pgl_drotc = VecOp.mult(ddeltaRprime_dc, x_vec);
+
+        
+        //put them all in one big matrix
+        
+        BasicMatrix dq_pgl_db = new BasicMatrix(3,6);
+        
+        dq_pgl_db.setElement(0, 0, dq_pgl_dx.e(0,0));
+        dq_pgl_db.setElement(1, 0, dq_pgl_dx.e(1,0));
+        dq_pgl_db.setElement(2, 0, dq_pgl_dx.e(2,0));
+
+        dq_pgl_db.setElement(0, 1, dq_pgl_dy.e(0,0));
+        dq_pgl_db.setElement(1, 1, dq_pgl_dy.e(1,0));
+        dq_pgl_db.setElement(2, 1, dq_pgl_dy.e(2,0));
+
+        dq_pgl_db.setElement(0, 2, dq_pgl_dz.e(0,0));
+        dq_pgl_db.setElement(1, 2, dq_pgl_dz.e(1,0));
+        dq_pgl_db.setElement(2, 2, dq_pgl_dz.e(2,0));
+
+        dq_pgl_db.setElement(0, 3, dq_pgl_drota.x());
+        dq_pgl_db.setElement(1, 3, dq_pgl_drota.y());
+        dq_pgl_db.setElement(2, 3, dq_pgl_drota.z());
+
+        dq_pgl_db.setElement(0, 4, dq_pgl_drotb.x());
+        dq_pgl_db.setElement(1, 4, dq_pgl_drotb.y());
+        dq_pgl_db.setElement(2, 4, dq_pgl_drotb.z());
+
+        dq_pgl_db.setElement(0, 5, dq_pgl_drotc.x());
+        dq_pgl_db.setElement(1, 5, dq_pgl_drotc.y());
+        dq_pgl_db.setElement(2, 5, dq_pgl_drotc.z());
+        
+        
+        
+         if(_debug>1) {
+            System.out.printf("%s: Translation derivative of the predicted hit position:\n",this.getClass().getSimpleName());
+            System.out.printf("dq_pgl_dx=\n%s \ndq_pgl_dy=\n%s \ndq_pgl_dz=\n%s\n",dq_pgl_dx.toString(),dq_pgl_dy.toString(),dq_pgl_dz.toString());
+            System.out.printf("%s: Rotation derivative of the predicted hit position:\n",this.getClass().getSimpleName());
+            System.out.printf("dq_pgl_dalpha=\n%s \ndq_pgl_dbeta=\n%s \ndq_pgl_dgamma=\n%s\n",dq_pgl_drota.toString(),dq_pgl_drotb.toString(),dq_pgl_drotc.toString());
+            System.out.printf("%s: Putting it together\ndq_pgl_db:\n%s\n",this.getClass().getSimpleName(),dq_pgl_db.toString());
+         }
+                 
+        
+         return dq_pgl_db;
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    //-------------------------------------------
+    //Helper functions
+
+    
+    
+    
+    public double get_dphi(double x, double xr, double yr, double d0, double phi0, double R, double phi) {
+        //Takes into account that phi=[-pi,pi] by checking where the points (x0,y0) and (x,y) are        
+        double dphi = tmpdphi(x,xr,yr,d0,phi0,R,phi);        
+        dphi = dphi > Math.PI ? dphi - 2*Math.PI :  dphi < -Math.PI ? dphi + 2*Math.PI : dphi;
+        return dphi;
+    }
+
+    public double dsign_dR(double R) {
+        return 0.0;
+    }
+    
+    
+    //Generic point y on circle/helix
+    public double y(double x, double xr, double yr, double d0, double phi0, double R,double phi) {
+        //double phi_angle = phi(x, xr, yr, d0, phi0, R);
+        double value = yc(yr,d0,phi0,R) + R*Math.cos(phi);
+        //double value = yolddangerous(x, xr, yr, d0, phi0, R);
+        /*
+        double ydanger = yolddangerous(x, xr, yr, d0, phi0, R);
+        if(value!=ydanger) {
+            System.out.println("ERROR ydanger " + ydanger + " is different than good y " + value +" !!");
+            System.out.println("xint " + x + "  d0 " + d0 + " phi0 " + phi0 + " R " + R);
+            System.out.println("R*Math.cos(phi0)=" + R*Math.cos(phi0) + " sign(R)*Math.sqrt( R*R - Math.pow(x - xc(xr,d0,phi0,R),2) )=" + sign(R)*Math.sqrt( R*R - Math.pow(x - xc(xr,d0,phi0,R),2) ) );
+            System.out.println("Math.pow(x - xc(xr,d0,phi0,R),2)=" + Math.pow(x - xc(xr,d0,phi0,R),2) + "  ");
+            System.exit(1);
+        }
+        
+        */
+        return value;
+    }
+
+    //Generic point y on circle/helix
+    public double yolddangerous(double x, double xr, double yr, double d0, double phi0, double R) {
+        return yc(yr,d0,phi0,R) + sign(R)*deltaxc(x,xr,d0,phi0,R);
+    }
+
+    //x-coordiante of center of circle/helix
+    double xc(double xr,double d0, double phi0, double R) {
+        return xr + (R-d0)*Math.sin(phi0);
+    }
+
+    //y-coordiante of center of circle/helix
+    double yc(double yr,double d0, double phi0, double R) {
+        return yr - (R-d0)*Math.cos(phi0);
+    }
+    
+    // x-coordinate of point of closest approach
+    double x0(double xr, double d0, double phi0) {
+        return xr - d0*Math.sin(phi0);
+    }
+    
+    // y-coordinate of point of closest approach
+    double y0(double yr, double d0, double phi0) {
+        return yr + d0*Math.cos(phi0);
+    }
+    
+    
+    // distance between generic point y and center of circle/helix => y-yc 
+    // FIX THE NAME SO THAT THIS IS deltayc ->MAKES MORE SENSE
+    public double deltaxc(double x, double xr, double d0,double phi0, double R) {
+        return Math.sqrt( R*R - Math.pow(x - xc(xr,d0,phi0,R),2) );
+    }
+ 
+    // distance between generic point x and center of circle/helix => x-xc
+    // FIX THE NAME SO THAT THIS IS deltaxc ->MAKES MORE SENSE
+    public double deltayc(double x, double xr, double yr, double d0,double phi0, double R,double phi) {
+        return Math.sqrt( R*R - Math.pow(y(x,xr,yr,d0,phi0,R,phi) - yc(yr,d0,phi0,R),2) );
+    }
+
+    // derivate of deltayc
+    public double ddeltayc_dd0(double x, double xr, double d0,double phi0, double R) {
+        //double num = sign(R)*sign(R) * Math.sin(phi0) * (x-xr-(-d0+R)*Math.sin(phi0));
+        //double den = Math.sqrt( R*R - sign(R)*sign(R) * (R*R - Math.pow( x-xr-(-d0+R)*Math.sin(phi0), 2)));
+        
+        //Use xc to simplify
+        double num = sign(R)*sign(R) * Math.sin(phi0) * (x-xc(xr,d0,phi0,R));
+        double den = Math.sqrt( R*R - sign(R)*sign(R) * (R*R - Math.pow( x-xc(xr,d0,phi0,R), 2)));
+        
+        return num/den;
+    }
+    
+    // derivate of deltayc
+    public double ddeltayc_dphi0(double x, double xr, double yr, double d0, double phi0, double R) {
+        //double num = (-d0+R)*Math.cos(phi0)*sign(R)*sign(R)*(x-xr-(-d0+R)*Math.sin(phi0));
+        //double den = Math.sqrt( R*R - sign(R)*sign(R)*( R*R - Math.pow(x-xr-(-d0+R)*Math.sin(phi0), 2)  )     );
+        //return -1.0*num/den;
+        
+        //Use yc and xc to simplify
+        double num = ( yc(yr,d0,phi0,R)-yr)*sign(R)*sign(R)*(x-xc(xr,d0,phi0,R));
+        double den = Math.sqrt( R*R - sign(R)*sign(R)*( R*R - Math.pow(x-xc(xr,d0,phi0,R), 2)  )   );
+        return num/den;
+        
+    }
+    
+    // derivate of deltayc
+    public double ddeltayc_dR(double x, double xr, double d0, double phi0, double R) {
+        //simplifying using xc
+        double num = ( 2*R - sign(R)*sign(R)*( 2*R + 2*Math.sin(phi0)*( x - xc(xr,d0,phi0,R)) )  -  2*sign(R)*( R*R - Math.pow(x-xc(xr,d0,phi0,R), 2))*dsign_dR(R)  );
+        double den = 2*Math.sqrt( R*R - sign(R)*sign(R)*( R*R - Math.pow(x-xc(xr,d0,phi0,R), 2) )   );        
+        return num/den;
+    }
+    
+    // Azimuthal angle for PCA - used in dphi calculation
+    public double phi1(double xr, double yr, double d0, double phi0, double R) {
+        return Math.atan2( x0(xr,d0,phi0) - xc(xr,d0,phi0,R)  , y0(yr,d0,phi0) - yc(yr,d0,phi0,R) );
+    }
+
+    // Azimuthal angle for generic point - used in dphi calculation
+    public double phi2(double x, double xr, double yr, double d0, double phi0, double R, double phi) {
+        return Math.atan2( x - xc(xr,d0,phi0,R)  , y(x, xr, yr, d0, phi0, R, phi) - yc(yr,d0,phi0,R) );
+    }
+
+    
+    // delta phi between point on helix (x,y) and point of closest approach (x0,y0)
+    public double tmpdphi(double x, double xr, double yr, double d0, double phi0, double R, double phi) {
+        return phi2(x,xr,yr,d0,phi0,R,phi) - phi1(xr,yr,d0,phi0,R);
+    }
+    
+    // derivative of delta phi between point on helix (x,y) and point of closest approach (x0,y0)
+    public double baddtmpdphi_dR(double x, double xr, double yr, double d0, double phi0, double R, double phi) {
+        // this calculation has been large "simplified" from the original by using x, x0, xc, y, y0, yc
+        double term1 = ((yc(yr,d0,phi0,R) - y0(yr,d0,phi0))*Math.sin(phi0) - (x0(xr,d0,phi0) - xc(xr,d0,phi0,R))*Math.cos(phi0) ) / (R*R);
+        
+        double num = Math.sin(phi0)*Math.pow(y(x, xr, yr, d0, phi0, R, phi) - y0(yr,d0,phi0),2) + ( x - xc(xr,d0,phi0,R))*( R + Math.sin(phi0)*(x-xc(xr,d0,phi0,R)) + Math.pow(y(x, xr, yr, d0, phi0, R, phi)-y0(yr,d0,phi0),2) );
+        
+        double den = (y(x, xr, yr, d0, phi0, R, phi) - yc(yr,d0,phi0,R))*Math.pow(x-xc(xr,d0,phi0,R),2) + sign(R)*sign(R)*Math.pow(y(x, xr, yr, d0, phi0, R, phi) - yc(yr,d0,phi0,R),3);
+        
+        double term2 = sign(R) * num/den;
+        
+        return term1 + term2;
+    }
+
+   
+     //public double phi(double xint,double xr, double yr, double d0, double phi0, double R) {
+        
+         //s = -dphi/C=-R*dphi=-R*(phi-phi0)
+         //phi = -s/R+phi0
+         //=>(z-z0)/slope = -R*(phi-phi0)
+         //=>phi = (z-z0)/(slope*-R)+phi0
+         //double z_pos = 0.0;
+         //double p = z_pos
+         
+        //double arg1 = Math.sin(phi0) - (xint-x0(xr,d0,phi0))/R;
+        //double arg2 = Math.cos(phi0) + (y(xint,xr,yr,d0,phi0,R)-y0(yr,d0,phi0))/R;
+        //double p = Math.atan2( arg1,arg2);
+        
+//        double arg1_2 = R*Math.sin(phi0) + (x0(xr,d0,phi0)-xint);
+//        double arg2_2 = R*Math.cos(phi0) + (y(xint,xr,yr,d0,phi0,R)-y0(yr,d0,phi0));
+//        double p_2 = Math.atan2( arg1,arg2);
+//        
+//        double arg1test = -sign(R )*Math.sin(phi0)+(x0(xr,d0,phi0)-xint)/R;
+//        double arg2test = sign(R )*Math.cos(phi0)+(y(xint,xr,yr,d0,phi0,R)-y0(yr,d0,phi0))/R;
+//        double phitest=Math.atan2(arg1test, arg2test);
+
+//        if(p!=p_2) {
+//            System.out.println("ERROR phi " + p + " != p_2" + p_2 + "!!");
+//            System.out.printf("arg1    =%f     arg2=%f\n",arg1,arg2);
+//            System.out.printf("arg1_2=%f arg_2=%f\n",arg1_2,arg2_2);            
+//            System.exit(1);
+//        }
+
+        /*
+        if(p!=phitest) {
+            System.out.println("ERROR phi " + p + " != phitest " + phitest + "!!");
+            System.out.printf("arg1    =%f     arg2=%f\n",arg1,arg2);
+            System.out.printf("arg1test=%f arg2test=%f\n",arg1test,arg2test);
+            System.out.println("arg1: phi0=" + phi0 + " sin(phi0)=" + Math.sin(phi0) + " -(xint-x0(xr,d0,phi0))/R="+ - (xint-x0(xr,d0,phi0))/R);
+            System.out.println("arg2: phi0=" + phi0 + " os(phi0)=" + Math.cos(phi0) + " + (y(xint,xr,yr,d0,phi0,R)-y0(yr,d0,phi0))/R = " + (y(xint,xr,yr,d0,phi0,R)-y0(yr,d0,phi0))/R);
+            System.out.println("argtest1: -sign(R )*Math.sin(phi0) = " +-sign(R )*Math.sin(phi0)+ " + (x0(xr,d0,phi0)-xint)/R = " + (x0(xr,d0,phi0)-xint)/R );
+            System.out.println("argtest2: sign(R )*Math.cos(phi0) = " + sign(R )*Math.cos(phi0) + " + (y(xint,xr,yr,d0,phi0,R)-y0(yr,d0,phi0))/R = " + (y(xint,xr,yr,d0,phi0,R)-y0(yr,d0,phi0))/R);
+            
+            
+            System.out.println(" phi " + p + " != p_2" + p_2 + "!!");
+            System.out.printf("arg1    =%f     arg2=%f\n",arg1,arg2);
+            System.out.printf("arg1_2=%f arg_2=%f\n",arg1_2,arg2_2);            
+            
+            
+            System.exit(1);
+        }
[truncated at 1000 lines; 651 more skipped]

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
BeamCurrentData.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/BeamCurrentData.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/BeamCurrentData.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,49 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+/**
+ *
+ * @author phansson
+ */
+public class BeamCurrentData {
+    
+    private double _int_current;
+    private int _start_time;
+    private int _stop_time;
+    private int _run_nr;
+    
+    public BeamCurrentData(int run,int start,int stop,double int_cur) {
+        _run_nr = run;
+        _start_time = start;
+        _stop_time = stop;
+        _int_current = int_cur;
+        
+    }
+    
+    public int getRun() {
+        return this._run_nr;
+    }
+    public int getStartTime() {
+        return this._start_time;
+    }
+    public int getStopTime() {
+        return this._stop_time;
+    }
+    public double getIntCurrent() {
+        return this._int_current;
+    }
+    public double getIntCurrentError() {
+        return this._int_current*0.0; //0.05;
+    }
+    
+    public String toString() {
+         String str = String.format("%10s\t%8d\t%8d\t%8.2f+-%.2f",getRun(),getStartTime(),getStopTime(),getIntCurrent(),getIntCurrentError());
+         return str;
+    }
+    
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
CmpGenToFittedTracksDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/CmpGenToFittedTracksDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/CmpGenToFittedTracksDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,192 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.ICloud1D;
+import hep.aida.ICloud2D;
+import hep.aida.IPlotter;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author mgraham
+ */
+public class CmpGenToFittedTracksDriver extends Driver {
+
+    private AIDA aida = AIDA.defaultInstance();
+    int totalTracks=0;
+    int totalTracksProcessed=0;
+    private String outputPlotFileName="";
+    private boolean hideFrame = false;
+    private boolean _debug = false;
+    
+    private AIDAFrame plotterFrame;
+    ICloud1D _h_chi2;
+    ICloud1D _h_ntracksdiff;
+    ICloud1D _h_d0_diff;
+    ICloud2D _h_d0xy_diff;
+    ICloud1D _h_z0_diff;
+    ICloud1D _h_phi0_diff;
+    ICloud1D _h_R_diff;
+    ICloud1D _h_slope_diff;
+    IPlotter _plotter_trackparamdiff;
+    IPlotter _plotter_others;
+     
+       
+    
+    
+    public void setDebug(boolean v) {
+        this._debug = v;
+    }
+    
+    public void setOutputPlotFileName(String filename) {
+        outputPlotFileName = filename;
+    }
+    
+    public void setHideFrame(boolean hide) {
+        hideFrame = hide;
+    }
+    
+    public CmpGenToFittedTracksDriver() {
+    
+    }
+    
+
+    
+    @Override
+    public void detectorChanged(Detector detector) {
+        
+        Hep3Vector IP = new BasicHep3Vector(0., 0., 1.);
+        Hep3Vector _bfield = new BasicHep3Vector(0,0,detector.getFieldMap().getField(IP).y());
+
+        makePlots();
+       
+        
+    }
+    
+    
+    
+    @Override
+    public void process(EventHeader event) {
+
+        List<HelicalTrackFit> tracklistgen = new ArrayList<HelicalTrackFit>();
+        if(event.hasCollection(HelicalTrackFit.class,"MCParticle_HelicalTrackFit")) {        
+            tracklistgen = event.get(HelicalTrackFit.class, "MCParticle_HelicalTrackFit");
+             if(_debug) {
+                System.out.println(this.getClass().getSimpleName() + ": Number of generated Tracks = " + tracklistgen.size());
+             }
+        }
+        
+        List<Track> tracklist = new ArrayList<Track>();
+        if(event.hasCollection(Track.class,"MatchedTracks")) {        
+            tracklist = event.get(Track.class, "MatchedTracks");
+             if(_debug) {
+                System.out.println(this.getClass().getSimpleName() + ": Number of Tracks = " + tracklist.size());
+             }
+        }
+        
+        _h_ntracksdiff.fill(tracklistgen.size()-tracklist.size());
+       
+        if(tracklistgen.size()!=tracklist.size()) {
+            if(this._debug) System.out.println(this.getClass().getSimpleName() + ": tracklistgen.size() = " + tracklistgen.size() + " tracklist.size()=" + tracklist.size());
+            return;
+        }
+        for (HelicalTrackFit trkgen : tracklistgen) {
+            for (Track track : tracklist) {
+                SeedTrack st = (SeedTrack) track;              
+                SeedCandidate seed = st.getSeedCandidate();
+                HelicalTrackFit trk = seed.getHelix();
+                List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+                //if(Math.signum(trkgen.R())!=Math.signum(trk.R())) continue;
+                this._h_d0_diff.fill(trkgen.dca()-trk.dca());
+                this._h_d0xy_diff.fill(trkgen.dca(),trk.dca());
+                this._h_R_diff.fill(trkgen.R()-trk.R());
+                this._h_phi0_diff.fill(trkgen.phi0()-trk.phi0());
+                this._h_z0_diff.fill(trkgen.z0()-trk.z0());
+                this._h_slope_diff.fill(trkgen.slope()-trk.slope());
+                this._h_chi2.fill(trk.chisqtot());
+            }
+            totalTracks++;
+            totalTracksProcessed++;
+            
+        }
+
+        
+        
+        
+    }
+
+    public void endOfData() {
+        //try {
+            System.out.println(this.getClass().getSimpleName() + ": Total Number of Tracks Found = "+totalTracks);
+            System.out.println(this.getClass().getSimpleName() + ": Total Number of Tracks Processed = "+totalTracksProcessed);
+//        } catch (IOException ex) {
+//            Logger.getLogger(CmpGenToFittedTracksDriver.class.getName()).log(Level.SEVERE, null, ex);
+//        }
+        if (!"".equals(outputPlotFileName))
+        try {
+            aida.saveAs(outputPlotFileName);
+        } catch (IOException ex) {
+            Logger.getLogger(TrigRateDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+        }
+        
+    }
+    
+   
+    private void makePlots() {
+        
+         
+        _h_chi2 = aida.cloud1D("chi2");
+        _h_ntracksdiff = aida.cloud1D("ntracksdiff");
+        _h_R_diff = aida.cloud1D("R_diff");
+        _h_d0_diff = aida.cloud1D("d0_diff");
+        _h_d0xy_diff = aida.cloud2D("d0xy_diff");
+        _h_phi0_diff = aida.cloud1D("phi0_diff");
+        _h_slope_diff = aida.cloud1D("slope_diff");
+        _h_z0_diff = aida.cloud1D("z0_diff");
+        _plotter_trackparamdiff = aida.analysisFactory().createPlotterFactory().create();
+        _plotter_trackparamdiff.setTitle("Params diff");
+        _plotter_trackparamdiff.createRegions(2,3);
+        _plotter_trackparamdiff.region(0).plot(_h_R_diff);
+        _plotter_trackparamdiff.region(1).plot(_h_d0_diff);
+        _plotter_trackparamdiff.region(2).plot(_h_phi0_diff);
+        _plotter_trackparamdiff.region(3).plot(_h_z0_diff);
+        _plotter_trackparamdiff.region(4).plot(_h_slope_diff);
+        _plotter_trackparamdiff.region(5).plot(_h_d0xy_diff);
+        
+        this._plotter_others = aida.analysisFactory().createPlotterFactory().create();
+        this._plotter_others.setTitle("Other");
+        this._plotter_others.createRegions(1,2);
+        this._plotter_others.region(0).plot(this._h_ntracksdiff);
+        this._plotter_others.region(1).plot(this._h_chi2);
+        
+        
+        
+        
+        
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("Compare Generated and Fitted Tracks");
+        plotterFrame.addPlotter(_plotter_trackparamdiff);
+        plotterFrame.addPlotter(_plotter_others);
+        plotterFrame.pack();
+        plotterFrame.setVisible(!hideFrame);
+        
+    }
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
Count.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/Count.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/Count.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,47 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+/**
+ *
+ * @author phansson
+ */
+public class Count {
+    
+    private String run;
+    private String name;
+    private double n;
+    private double en;
+    
+    Count(String n, String r, double N, double err) {
+        this.name = n;
+        this.run = r;
+        this.n = N;
+        this.en = err;
+    }
+    
+    public String name() {
+        return this.name;
+    }
+
+    public String run() {
+        return this.run;
+    }
+
+    public double n() {
+        return this.n;
+    }
+
+    public double en() {
+        return this.en;
+    }
+    public void addSimple(double N,double eN) {
+        //Assume these are just counts so simply add up
+        this.n = this.n + N;
+        this.en = this.en + eN;
+    }
+
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
DAQDeadTimeData.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/DAQDeadTimeData.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/DAQDeadTimeData.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,41 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+/**
+ *
+ * @author phansson
+ */
+public class DAQDeadTimeData {
+    
+    private double _daq_rate;
+    private double _trigger_rate;
+    private int _run_nr;
+    
+    public DAQDeadTimeData(int run,double trig, double daq) {
+        _run_nr = run;
+        _trigger_rate = trig;
+        _daq_rate = daq;
+        
+    }
+    
+    public int getRun() {
+        return this._run_nr;
+    }
+    public double getDAQLiveTimeFraction() {
+        return this._daq_rate/this._trigger_rate;
+    }
+    public double getDAQLiveTimeFractionError() {
+        return this._daq_rate/this._trigger_rate*0.0;//0.05;
+    }
+    
+    public String toString() {
+        String str = String.format("%10s\tDAQ rate %8.1f Hz\tTrigger rate%8.2f Hz -> livetime %8.2f +- %.2f",getRun(),_daq_rate,_trigger_rate,this.getDAQLiveTimeFraction(),this.getDAQLiveTimeFractionError());
+         return str;
+    }
+    
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
DumpAIDATextFiles.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/DumpAIDATextFiles.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/DumpAIDATextFiles.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,162 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IManagedObject;
+import hep.aida.ITree;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.commons.cli.*;
+
+/**
+ *
+ * @author phansson Dumps all histograms in AIDA files to a standard text format
+ * @version $Id: DumpAIDATextFiles.java,v 1.3 2013/11/01 19:23:53 meeg Exp $
+ */
+public class DumpAIDATextFiles {
+
+    private static Options createCommandLineOptions() {
+
+        Options options = new Options();
+        //options.addOption(new Option("p", true, "The pattern to match. [NOT IMPLEMENTED YET]"));
+        options.addOption(new Option("f", true, "The file to use."));
+        options.addOption(new Option("d", true, "The directory with files."));
+        return options;
+
+    }
+
+    /**
+     * @param args the command line arguments
+     */
+    public static class TextFileUtil {
+
+        public TextFileUtil() {
+        }
+
+        public void createTextFile(String fileName, ITree tree) {
+            //System.out.println("-----\nCreating text file "+fileName+" from tree with " + tree.listObjectNames().length + " objects");
+            FileWriter fWriter;
+            PrintWriter pWriter;
+            try {
+                fWriter = new FileWriter(fileName);
+                pWriter = new PrintWriter(fWriter);
+
+                for (String name : tree.listObjectNames()) {
+                    //System.out.println(str);
+                    IManagedObject obj = tree.find(name);
+                    if (obj instanceof IHistogram1D) {
+                        //System.out.println(name + " is a histogram");
+                        IHistogram1D h = (IHistogram1D) obj;
+                        String htxt = convertHist1D(h);
+                        pWriter.println(htxt);
+                    }
+                    if (obj instanceof IHistogram2D) {
+                        //System.out.println(name + " is a histogram");
+                        IHistogram2D h = (IHistogram2D) obj;
+                        String htxt = convertHist2D(h);
+                        pWriter.println(htxt);
+                    }
+                }
+
+                fWriter.close();
+                pWriter.close();
+            } catch (IOException ex) {
+                Logger.getLogger(DumpAIDATextFiles.class.getName()).log(Level.SEVERE, null, ex);
+            }
+            //System.out.println("-----");
+
+
+        }
+
+        public String convertHist1D(IHistogram1D h) {
+            //Type title bincontent
+            String htxt = "IHistogram1D \"" + h.title() + "\" " + h.axis().bins() + " " + h.axis().lowerEdge() + " " + h.axis().upperEdge();
+            for (int ibin = 0; ibin < h.axis().bins(); ++ibin) {
+                htxt += " " + h.binEntries(ibin);
+                htxt += " " + h.binHeight(ibin);
+            }
+            return htxt;
+        }
+
+        public String convertHist2D(IHistogram2D h) {
+            //Type title bincontent
+            String htxt = "IHistogram2D \"" + h.title() + "\" " + h.xAxis().bins() + " " + h.xAxis().lowerEdge() + " " + h.xAxis().upperEdge() + " " + h.yAxis().bins() + " " + h.yAxis().lowerEdge() + " " + h.yAxis().upperEdge();
+            for (int xbin = 0; xbin < h.xAxis().bins(); ++xbin) {
+                for (int ybin = 0; ybin < h.yAxis().bins(); ++ybin) {
+                    htxt += " " + h.binEntries(xbin, ybin);
+                    htxt += " " + h.binHeight(xbin, ybin);
+                }
+            }
+            return htxt;
+        }
+    }
+
+    public static void main(String[] args) {
+        // TODO code application logic here
+
+        Options options = createCommandLineOptions();
+        if (args.length == 0) {
+            System.out.println("TestRunEvioToLcio [options] [evioFiles]");
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", options);
+            System.exit(1);
+        }
+        CommandLineParser parser = new PosixParser();
+        CommandLine cl = null;
+        try {
+            cl = parser.parse(options, args);
+        } catch (ParseException e) {
+            throw new RuntimeException("Problem parsing command line options.", e);
+        }
+        List<String> fileList = new ArrayList<String>();
+        if (cl.hasOption("f")) {
+            fileList.add(cl.getOptionValue("f"));
+        } else if (cl.hasOption("d")) {
+            //check if pattern is to be used or simply use run all aida files
+            String dirName = cl.getOptionValue("d");
+            if (cl.hasOption("p")) {
+                System.out.println("The pattern option is not implemented. Please do it!");
+                System.exit(1);
+            } else {
+                File dir = new File(dirName);
+                for (File f : dir.listFiles()) {
+                    if (f.isFile() && f.getName().contains(".aida")) {
+                        fileList.add(f.getAbsolutePath());
+                    }
+                }
+            }
+        }
+        IAnalysisFactory af = IAnalysisFactory.create();
+        TextFileUtil util = new TextFileUtil();
+        for (String file : fileList) {
+            System.out.println("Converting file " + file);
+            if (!file.contains(".aida")) {
+                System.out.println("This is not an AIDA file?!");
+                continue;
+            }
+            ITree tree = null;
+            try {
+                tree = af.createTreeFactory().create(file);
+            } catch (IllegalArgumentException ex) {
+                Logger.getLogger(DumpAIDATextFiles.class.getName()).log(Level.SEVERE, null, ex);
+            } catch (IOException ex) {
+                Logger.getLogger(DumpAIDATextFiles.class.getName()).log(Level.SEVERE, null, ex);
+            }
+            if (tree == null) {
+                System.out.println("Couldn't create \"tree\" for file: " + file);
+                continue;
+            }
+            String txtFileName = file.replaceAll(".aida", ".histtxt");
+            util.createTextFile(txtFileName, tree);
+
+        }
+
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
ECalGainDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ECalGainDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ECalGainDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,521 @@
+package org.lcsim.hps.users.phansson;
+
+import org.lcsim.hps.recon.ecal.*;
+
+import hep.aida.*;
+import hep.aida.ref.plotter.PlotterRegion;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.*;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.event.base.BaseTrack;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.monitoring.deprecated.Redrawable;
+import org.lcsim.hps.monitoring.deprecated.Resettable;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.hps.recon.tracking.EcalTrackMatch;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson+
+ */
+public class ECalGainDriver extends Driver implements Resettable, ActionListener, Redrawable {
+
+    private int nevents = 0;
+    private boolean debug = true;
+    private String trackCollectionName = "MatchedTracks";
+    private String ecalClusterCollectionName = "EcalClusters";
+    private String outputPlotFileName = "test.aida";
+    private String ecalGainFileName = "clusterList.txt";
+    private String triggerClusterCollection = "EcalTriggerClusters";
+    private double triggerThreshold = 10.0;
+    private boolean simTrigger = false;
+    //Print out cluster and track to file
+    private PrintWriter gainWriter = null;
+    private boolean hideFrame = false;
+    private int refreshRate = 100;
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    private AIDAFrame pePlotterFrame;
+    private IPlotter plotter;
+    private JComboBox xCombo;
+    private JLabel xLabel;
+    private JComboBox yCombo;
+    private JLabel yLabel;
+    private Integer xList[];
+    private Integer yList[];
+    private JButton blankButton;
+    private IHistogram1D pePlots[][][] = new IHistogram1D[47][11][5];
+    private IHistogram2D mpePlot;
+    private IHistogram2D spePlot;
+    private IHistogram2D hitmap;
+    private IHistogram1D[] h_PE_t = new IHistogram1D[5];
+    private IHistogram1D[] h_PE_b = new IHistogram1D[5];
+    private IHistogram2D weightPlot;
+    private IHistogram2D sumPlot;
+    int clTop = 0;
+    int clBot = 0;
+    int trTop = 0;
+    int trBot = 0;
+    int trigTop = 0;
+    int trigBot = 0;
+    int matchTop = 0;
+    int matchBot = 0;
+
+    @Override
+    public void detectorChanged(Detector detector) {
+        try {
+            gainWriter = new PrintWriter(ecalGainFileName);
+        } catch (FileNotFoundException ex) {
+            Logger.getLogger(ECalGainDriver.class.getName()).log(Level.SEVERE, null, ex);
+        }
+
+        pePlotterFrame = new AIDAFrame();
+        pePlotterFrame.setTitle("Gain Frame");
+
+        IPlotterStyle style;
+
+        IPlotter plotter_hitmap_gr = af.createPlotterFactory().create();
+        plotter_hitmap_gr.createRegions(1, 3, 0);
+        plotter_hitmap_gr.setTitle("Cluster hit map");
+        plotter_hitmap_gr.style().statisticsBoxStyle().setVisible(false);
+        pePlotterFrame.addPlotter(plotter_hitmap_gr);
+
+        hitmap = aida.histogram2D("Cluster hit map", 46, -23, 23, 11, -5.5, 5.5);
+        plotter_hitmap_gr.region(0).plot(hitmap);
+
+        style = plotter_hitmap_gr.region(0).style();
+        style.setParameter("hist2DStyle", "colorMap");
+        style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        ((PlotterRegion) plotter_hitmap_gr.region(0)).getPlot().setAllowUserInteraction(true);
+        ((PlotterRegion) plotter_hitmap_gr.region(0)).getPlot().setAllowPopupMenus(true);
+
+        IPlotter[] plotter_PoverE = new IPlotter[5];
+
+
+        for (int iE = 0; iE <= 4; ++iE) {
+
+            String str = iE == 0 ? "" : (" iE=" + iE);
+
+            h_PE_t[iE] = aida.histogram1D("E over p top" + str, 50, 0, 2);
+            h_PE_b[iE] = aida.histogram1D("E over p bottom" + str, 50, 0, 2);
+
+            plotter_PoverE[iE] = af.createPlotterFactory().create();
+            plotter_PoverE[iE].createRegions(1, 2, 0);
+            plotter_PoverE[iE].setTitle("E over P" + str);
+            plotter_PoverE[iE].style().statisticsBoxStyle().setVisible(true);
+            pePlotterFrame.addPlotter(plotter_PoverE[iE]);
+
+            plotter_PoverE[iE].region(0).plot(h_PE_t[iE]);
+            plotter_PoverE[iE].region(1).plot(h_PE_b[iE]);
+        }
+
+        plotter = af.createPlotterFactory().create();
+        plotter.createRegions(1, 3, 0);
+        plotter.setTitle("Gain Plots");
+
+        pePlotterFrame.addPlotter(plotter);
+
+        mpePlot = aida.histogram2D("<E over p>", 46, -23, 23, 11, -5.5, 5.5);
+        plotter.region(0).plot(mpePlot);
+        spePlot = aida.histogram2D("RMS(E over p)", 46, -23, 23, 11, -5.5, 5.5);
+        plotter.region(1).plot(spePlot);
+        plotter.region(0).style().statisticsBoxStyle().setVisible(false);
+        plotter.region(0).style().setParameter("hist2DStyle", "colorMap");
+        plotter.region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter.region(1).style().statisticsBoxStyle().setVisible(false);
+        plotter.region(1).style().setParameter("hist2DStyle", "colorMap");
+        plotter.region(1).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+
+        weightPlot = aida.histogram2D("Weights for correction factor", 46, -23, 23, 11, -5.5, 5.5);
+        sumPlot = aida.histogram2D("Sum for correction factor", 46, -23, 23, 11, -5.5, 5.5);
+
+        for (int iE = 0; iE <= 4; ++iE) {
+            for (int irow = -5; irow <= 5; ++irow) {
+                for (int icol = -23; icol <= 23; ++icol) {
+                    if (iE == 0) {
+                        pePlots[icol + 23][irow + 5][iE] = aida.histogram1D("E over p x=" + icol + " y=" + irow, 50, 0, 2);
+                    } else {
+                        pePlots[icol + 23][irow + 5][iE] = aida.histogram1D("E over p x=" + icol + " y=" + irow + " iE=" + iE, 50, 0, 2);
+                    }
+                }
+            }
+        }
+
+        xList = new Integer[46];
+        yList = new Integer[10];
+        int in = 0;
+        for (int i = -5; i <= 5; ++i) {
+            if (i != 0) {
+                yList[in] = i;
+                ++in;
+            }
+        }
+        in = 0;
+        for (int i = -23; i <= 23; ++i) {
+            if (i != 0) {
+                xList[in] = i;
+                ++in;
+            }
+        }
+
+        xCombo = new JComboBox(xList);
+        xCombo.addActionListener(this);
+        xLabel = new JLabel("x");
+        xLabel.setLabelFor(xCombo);
+        pePlotterFrame.getControlsPanel().add(xLabel);
+        pePlotterFrame.getControlsPanel().add(xCombo);
+        yCombo = new JComboBox(yList);
+        yCombo.addActionListener(this);
+        yLabel = new JLabel("y");
+        yLabel.setLabelFor(xCombo);
+        pePlotterFrame.getControlsPanel().add(yLabel);
+        pePlotterFrame.getControlsPanel().add(yCombo);
+
+        plotter.region(2).plot(pePlots[-5 + 23][2 + 5 - 1][0]);
+        xCombo.setSelectedIndex(-5 + 23);
+        yCombo.setSelectedIndex(2 + 5 - 1);
+
+        blankButton = new JButton("Hide histogram");
+        pePlotterFrame.getControlsPanel().add(blankButton);
+        blankButton.addActionListener(this);
+
+        if (!hideFrame) {
+            pePlotterFrame.pack();
+            pePlotterFrame.setVisible(true);
+        }
+    }
+
+    public ECalGainDriver() {
+    }
+
+    public void setDebug(boolean flag) {
+        this.debug = flag;
+    }
+
+    public void setSimTrigger(boolean simTrigger) {
+        this.simTrigger = simTrigger;
+    }
+
+    public void setOutputPlotFileName(String name) {
+        this.outputPlotFileName = name;
+    }
+
+    public void setEcalGainFileName(String name) {
+        this.ecalGainFileName = name;
+    }
+
+    public void setHideFrame(boolean val) {
+        this.hideFrame = val;
+    }
+
+    @Override
+    public void process(EventHeader event) {
+        List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, ecalClusterCollectionName);
+
+        List<Track> tracks;
+        if (event.hasCollection(Track.class, trackCollectionName)) {
+            tracks = event.get(Track.class, trackCollectionName);
+        } else {
+            return;
+        }
+
+        if (simTrigger) {
+            boolean trigger = false;
+            if (event.hasCollection(HPSEcalCluster.class, triggerClusterCollection)) {
+                List<HPSEcalCluster> triggerClusters = event.get(HPSEcalCluster.class, triggerClusterCollection);
+                if (debug) {
+                    System.out.println("Found " + triggerClusters.size() + " trigger clusters and " + clusters.size() + " readout clusters");
+                }
+                for (HPSEcalCluster cluster : triggerClusters) {
+                    if (cluster.getEnergy() > triggerThreshold) {
+                        trigger = true;
+                        int[] pos = getCrystalPair(cluster);
+                        int side = pos[1] > 0 ? 0 : 1; //top or bottom
+                        if (side == 0) {
+                            trigTop++;
+                        } else {
+                            trigBot++;
+                        }
+                    }
+                }
+            }
+            if (!trigger) {
+                return;
+            }
+            if (debug) {
+                System.out.println("Triggered");
+            }
+        }
+
+        ++nevents;
+        if (debug) {
+            System.out.println("Processing event " + nevents);
+        }
+
+        if (refreshRate > 0 && nevents % refreshRate == 0) {
+            redraw();
+        }
+
+        for (Track track : tracks) {
+            BaseTrack trk = (BaseTrack) track;
+            trk.setTrackParameters(trk.getTrackStates().get(0).getParameters(), -0.491);
+            if (debug) {
+                if (TrackUtils.getTrackPositionAtEcal(trk).y() > 0) {
+                    trTop++;
+                } else {
+                    trBot++;
+                }
+            }
+        }
+
+        if (debug) {
+            System.out.println(clusters.size() + " clusters in this event");
+            for (HPSEcalCluster cl : clusters) {
+                int[] pos = getCrystalPair(cl);
+                int side = pos[1] > 0 ? 0 : 1; //top or bottom
+                if (side == 0) {
+                    clTop++;
+                } else {
+                    clBot++;
+                }
+                System.out.format("[%f\t%f\t%f], ix = %d, iy = %d\n", cl.getPosition()[2], cl.getPosition()[0], cl.getPosition()[1], pos[0], pos[1]);
+            }
+
+            System.out.println(tracks.size() + " tracks in this event");
+            for (Track track : tracks) {
+                System.out.println(TrackUtils.getTrackPositionAtEcal(track));
+            }
+        }
+
+
+        while (!tracks.isEmpty() && !clusters.isEmpty()) {
+            HPSEcalCluster bestCl = null;
+            Track bestTrk = null;
+            double minDist = Double.POSITIVE_INFINITY;
+
+            for (HPSEcalCluster cl : clusters) {
+                EcalTrackMatch trkMatchTool = new EcalTrackMatch(debug);
+                int[] pos = getCrystalPair(cl);
+                if (debug) {
+                    System.out.println("Looking at cluster at ix=" + pos[0] + " iy=" + pos[1]);
+                }
+
+                trkMatchTool.setCluster(cl);
+                trkMatchTool.match(tracks);
+//            double dist = trkMatchTool.getDistanceToTrackInY();
+                double dist = trkMatchTool.getDistanceToTrack();
+                if (dist < minDist) {
+                    minDist = dist;
+                    bestCl = cl;
+                    bestTrk = trkMatchTool.getMatchedTrack();
+                }
+            }
+            tracks.remove(bestTrk);
+            clusters.remove(bestCl);
+
+            if (bestCl != null & bestTrk != null && minDist < 80.0) {
+                if (debug) {
+                    int[] pos = getCrystalPair(bestCl);
+                    System.out.format("Matched cluster: [%f\t%f\t%f], ix = %d, iy = %d\n", bestCl.getPosition()[2], bestCl.getPosition()[0], bestCl.getPosition()[1], pos[0], pos[1]);
+                    System.out.println("Matched track: " + TrackUtils.getTrackPositionAtEcal(bestTrk));
+                    System.out.println("Distance: " + minDist);
+                }
+                processMatchedPair(event, bestCl, bestTrk);
+            } else {
+                if (debug) {
+                    System.out.println("Couldn't find a good match");
+                }
+            }
+        }
+    }
+
+    private void processMatchedPair(EventHeader event, HPSEcalCluster bestCl, Track bestTrk) {
+
+        int[] pos = getCrystalPair(bestCl);
+        int side = pos[1] > 0 ? 0 : 1; //top or bottom
+//            if (!trkMatchTool.isMatchedY(50)) {
+//                if (debug) {
+//                    System.out.println("Cluster not matched to a track");
+//                }
+//                if (!tracks.isEmpty()) {
+//                    System.out.format("Unmatched cluster: ");
+//                } else {
+//                    System.out.format("No tracks to match to this cluster: ");
+//                }
+//                System.out.format("[%f\t%f\t%f], ix = %d, iy = %d\n", bestCl.getPosition()[2], bestCl.getPosition()[0], bestCl.getPosition()[1], pos[0], pos[1]);
+//                    ExtendTrack extender = new ExtendTrack();
+//                    extender.setTrack(bestTrk);
+//                    System.out.println(extender.positionAtEcal());
+//                return;
+//            }
+
+//            if (debug) {
+//                System.out.println("Cluster matched to track at distance Y " + trkMatchTool.getDistanceToTrackInY() + " and X " + trkMatchTool.getDistanceToTrackInX());
+//            }
+        if (debug && side == 0) {
+            matchTop++;
+        } else {
+            matchBot++;
+        }
+
+        double P = bestTrk.getTrackStates().get(0).getMomentum()[0] * 1000.0;
+        double E = bestCl.getEnergy() * 1000.0;
+        double Eoverp = E / P;
+        double PoverE = P / E;
+
+        for (CalorimeterHit hit : bestCl.getCalorimeterHits()) {
+            double weight = hit.getRawEnergy() / bestCl.getEnergy();
+            int ix = hit.getIdentifierFieldValue("ix");
+            int iy = hit.getIdentifierFieldValue("iy");
+            weightPlot.fill(ix - 0.5 * Math.signum(ix), iy, weight);
+            sumPlot.fill(ix - 0.5 * Math.signum(ix), iy, weight * PoverE);
+        }
+
+        if (debug) {
+            System.out.println("P " + P + " E " + E);
+        }
+
+//            double Eseed = cl.getSeedHit().getRawEnergy();
+//            double ErawSum = 0;
+//            for(CalorimeterHit hit : cl.getCalorimeterHits()) {
+//                ErawSum += hit.getRawEnergy();
+//            }
+//            
+//            if(Eseed/ErawSum<0.6) continue;
+//            
+        int ebin;
+        if (P > 500 && P <= 700) {
+            ebin = 1;
+        } else if (P > 700 && P <= 900) {
+            ebin = 2;
+        } else if (P > 900 && P <= 1100) {
+            ebin = 3;
+        } else {
+            ebin = 4;
+        }
+
+        if (side == 0) {
+            h_PE_t[0].fill(Eoverp);
+            h_PE_t[ebin].fill(Eoverp);
+
+        } else {
+            h_PE_b[0].fill(Eoverp);
+            h_PE_b[ebin].fill(Eoverp);
+        }
+
+        hitmap.fill(pos[0] - 0.5 * Math.signum(pos[0]), pos[1]);
+
+        pePlots[pos[0] + 23][pos[1] + 5][0].fill(Eoverp);
+
+        pePlots[pos[0] + 23][pos[1] + 5][ebin].fill(Eoverp);
+
+        gainWriter.print(event.getEventNumber() + " " + P + " " + E + " " + pos[0] + " " + pos[1]);
+        for (CalorimeterHit hit : bestCl.getCalorimeterHits()) {
+            gainWriter.print(" " + hit.getIdentifierFieldValue("ix") + " " + hit.getIdentifierFieldValue("iy") + " " + hit.getRawEnergy() * 1000.0 + " " + EcalConditions.physicalToGain(hit.getCellID()));
+        }
+        gainWriter.println("");
+    }
+
+    private int[] getCrystalPair(HPSEcalCluster cluster) {
+        int[] pos = new int[2];
+        pos[0] = cluster.getSeedHit().getIdentifierFieldValue("ix");
+        pos[1] = cluster.getSeedHit().getIdentifierFieldValue("iy");
+
+        //System.out.println("cluster ix,iy " + pos[0] + "," + pos[1] + "    from pos  " + cluster.getSeedHit().getPositionVec().toString());
+        return pos;
+        //getCrystalPair(cluster.getPosition());
+    }
+
+    @Override
+    public void endOfData() {
+        redraw();
+
+        if (!"".equals(outputPlotFileName)) {
+            try {
+                aida.saveAs(outputPlotFileName);
+            } catch (IOException ex) {
+                Logger.getLogger(ECalGainDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+            }
+        }
+        //displayFastTrackingPlots();
+        for (int x = -23; x <= 23; x++) { // slot
+            for (int y = -5; y <= 5; y++) { // crate  
+                if (EcalConditions.physicalToGain(EcalConditions.makePhysicalID(x, y)) != null) {
+                    System.out.printf("%d\t%d\t%d\t%f\t%f\n", x, y, pePlots[x + 23][y + 5][0].allEntries(), pePlots[x + 23][y + 5][0].mean(), pePlots[x + 23][y + 5][0].rms());
+                }
+            }
+        }
+
+        gainWriter.close();
+        if (debug) {
+            System.out.format("trigTop %d trigBot %d trTop %d trBot %d clTop %d clBot %d matchTop %d matchBot %d\n", trigTop, trigBot, trTop, trBot, clTop, clBot, matchTop, matchBot);
+        }
+    }
+
+    @Override
+    public void reset() {
+        if (plotter != null) {
+            plotter.hide();
+            plotter.destroyRegions();
+            for (int x = -23; x <= 23; x++) { // slot
+                for (int y = -5; y <= 5; y++) { // crate  
+                    for (int iE = 0; iE <= 4; ++iE) {
+                        pePlots[x + 23][y + 5][iE].reset();
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent ae) {
+        if (ae.getSource() == blankButton) {
+            plotter.region(2).clear();
+        } else {
+            //get the col and row to display
+            Integer x = (Integer) xCombo.getSelectedItem();
+            Integer y = (Integer) yCombo.getSelectedItem();
+            plotter.region(2).clear();
+            plotter.region(2).plot(pePlots[x + 23][y + 5][0]);
+        }
+    }
+
+    @Override
+    public void redraw() {
+
+        //do something if needed
+        mpePlot.reset();
+        spePlot.reset();
+
+        for (int irow = -5; irow <= 5; ++irow) {
+            for (int icol = -23; icol <= 23; ++icol) {
+                //System.out.println(" redraw irow " + irow + " icol " + icol + " entries " + pePlots[icol+23][irow+5].entries());
+                if (pePlots[icol + 23][irow + 5][0].entries() > 10) {
+                    mpePlot.fill(icol - 0.5 * Math.signum(icol), irow, pePlots[icol + 23][irow + 5][0].mean());
+                    spePlot.fill(icol - 0.5 * Math.signum(icol), irow, pePlots[icol + 23][irow + 5][0].rms());
+                }
+            }
+        }
+    }
+
+    @Override
+    public void setEventRefreshRate(int eventRefreshRate) {
+        refreshRate = eventRefreshRate;
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
ECalHitMapPlots.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ECalHitMapPlots.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ECalHitMapPlots.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,320 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import hep.aida.IHistogram2D;
+import hep.aida.IPlotter;
+import hep.aida.ITree;
+import hep.aida.ref.plotter.PlotterRegion;
+import java.io.IOException;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson
+ */
+public class ECalHitMapPlots {
+    
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    IHistogramFactory hf = aida.histogramFactory();
+//    ITree tree = aida.tree();//(ITreeFactory) af.createTreeFactory().create();
+
+    private boolean hide = false;
+    
+    
+    public ECalHitMapPlots() {
+        
+    }
+    
+    public ECalHitMapPlots(boolean h) {
+        this.hide = h;
+        //System.out.println("Constructor ECalHitMapPlots");
+        
+    }
+    
+    public void hidePlots(boolean h) {
+        this.hide = h;
+    }
+    
+    public void default2DStyle(IPlotterStyle s) {
+        s.statisticsBoxStyle().setVisible(false);
+        s.setParameter("hist2DStyle","colorMap");
+        s.dataStyle().fillStyle().setParameter("colorMapScheme","rainbow");
+        
+    }
+
+    public void plotBasic2DMap(IHistogram2D h, String title, String xTitle, String yTitle,boolean writeToFile) {
+        plotBasic2D(h, title, xTitle, yTitle, 1500, 300,writeToFile);
+        
+    }
+    public void plotBasic2D(IHistogram2D h, String title, String xTitle, String yTitle, int width, int height,boolean writeToFile) {
+        IPlotter plotter_hm = af.createPlotterFactory().create();
+        plotter_hm.setTitle(title);
+        h.setTitle(title);
+        plotter_hm.setParameter("plotterWidth","1500");
+        plotter_hm.setParameter("plotterHeight","300");
+        
+        //plotter_hm.createRegion(10.0,20.0, 460.0,100.0);
+        //plotter_hm.createRegion(d, d1, d2, d3)
+        //plotter_hm.createRegions(1,1);//.plot(hm);
+        plotter_hm.region(0).plot(h);
+        //default2DStyle(plotter_hm.region(0).style());
+        plotter_hm.style().statisticsBoxStyle().setVisible(false);
+        plotter_hm.style().setParameter("hist2DStyle","colorMap");
+        plotter_hm.style().dataStyle().fillStyle().setParameter("colorMapScheme","rainbow");
+        ((PlotterRegion) plotter_hm.region(0)).getPlot().getXAxis().setLabel(xTitle);
+        ((PlotterRegion) plotter_hm.region(0)).getPlot().getYAxis().setLabel(yTitle);          
+        if (!hide) plotter_hm.show();
+        if(writeToFile) {
+        try {
+            plotter_hm.writeToFile(title+".png", "png");
+        } catch(IOException e) {
+            throw new RuntimeException(e);
+        }
+        }
+    }
+    
+     public void plotBasic1D(IHistogram1D h, String title, String xTitle, String yTitle, String fillColor,boolean writeToFile) {
+        IPlotter plotter_hm = af.createPlotterFactory().create();
+        plotter_hm.setTitle(title);
+        if("".equals(fillColor)) fillColor="yellow";
+        //plotter_hm.createRegion(10.0,20.0, 460.0,100.0);
+        //plotter_hm.createRegion(d, d1, d2, d3)
+        plotter_hm.createRegions(1,1);//.plot(hm);
+        plotter_hm.region(0).plot(h);
+        plotter_hm.style().statisticsBoxStyle().setVisible(true);
+        plotter_hm.style().dataStyle().fillStyle().setColor(fillColor);
+        ((PlotterRegion) plotter_hm.region(0)).getPlot().getXAxis().setLabel(xTitle);
+        ((PlotterRegion) plotter_hm.region(0)).getPlot().getYAxis().setLabel(yTitle);          
+        if(!hide) plotter_hm.show();
+        if(writeToFile) {
+        try {
+            plotter_hm.writeToFile(title+".png", "png");
+        } catch(IOException e) {
+            throw new RuntimeException(e);
+        }
+        }
+        
+    }
+
+     
+     
+    public void plotBasic1D(IHistogram1D h, IHistogram1D h2, String title, String xTitle, String yTitle, String leg1,String leg2,boolean writeToFile) {
+        //IPlotter plotter_hm1 = af.createPlotterFactory().create();
+        //IPlotter plotter_hm2 = af.createPlotterFactory().create();
+        IPlotter plotter_hm = af.createPlotterFactory().create();
+        //if(!"".equals(title)) {
+        //    plotter_hm.setTitle(title);
+        //    h.setTitle(title);
+        //}
+        
+        //if(fillColor=="") fillColor="yellow";
+        //plotter_hm.createRegion(10.0,20.0, 460.0,100.0);
+        //plotter_hm.createRegion(d, d1, d2, d3)
+        plotter_hm.createRegions(1,1);//.plot(hm);
+        //plotter_hm1.createRegions(1,1);
+        //plotter_hm2.createRegions(1,1);
+        plotter_hm.region(0).style().dataStyle().fillStyle().setVisible(false);
+        plotter_hm.region(0).style().statisticsBoxStyle().setVisible(false);
+        //plotter_hm.region(0).style().dataStyle().lineStyle().setColor("green");
+        plotter_hm.style().xAxisStyle().setLabel(xTitle);
+        plotter_hm.style().yAxisStyle().setLabel(yTitle);
+//        plotter_hm1.region(1).style().dataStyle().fillStyle().setVisible(false);
+//        plotter_hm1.region(1).style().statisticsBoxStyle().setVisible(false);
+//        plotter_hm1.region(1).style().dataStyle().lineStyle().setColor("green");
+//        plotter_hm1.style().xAxisStyle().setLabel(xTitle);
+//        plotter_hm1.style().yAxisStyle().setLabel(yTitle);
+//        plotter_hm2.region(1).style().dataStyle().fillStyle().setVisible(false);
+//        plotter_hm2.region(1).style().statisticsBoxStyle().setVisible(false);
+//        plotter_hm2.region(1).style().dataStyle().lineStyle().setColor("green");
+//        plotter_hm2.style().xAxisStyle().setLabel(xTitle);
+//        plotter_hm2.style().yAxisStyle().setLabel(yTitle);
+//        
+        //IPlotterStyle dataStyle = plotter_hm.region(0).style();
+        //dataStyle.dataStyle().lineStyle().setColor("green");
+        plotter_hm.region(0).plot(h);
+        //IPlotterStyle dataStyle2 = plotter_hm.region(0).style().;
+        //dataStyle2.dataStyle().lineStyle().setColor("blue");
+        //plotter_hm.region(1).plot(h2,dataStyle);
+        //plotter_hm.region(2).plot(h);
+        plotter_hm.region(0).plot(h2,"mode=overlay");
+        
+        //System.out.println("av Params: " + plotter_hm.style().dataStyle().fillStyle().availableParameters().toString());
+        //for(String str : plotter_hm.style().dataStyle().fillStyle().availableParameters()) {
+        //    System.out.println(str);
+        //}
+        
+        if(!"".equals(xTitle)) ((PlotterRegion) plotter_hm.region(0)).getPlot().getXAxis().setLabel(xTitle);
+        if(!"".equals(yTitle)) ((PlotterRegion) plotter_hm.region(0)).getPlot().getYAxis().setLabel(yTitle);          
+        if(!hide) plotter_hm.show();
+        if(writeToFile) {
+            try {
+                plotter_hm.writeToFile(title+".png", "png");
+            } catch(IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        
+    }
+
+
+    
+    
+    public void plotMultScatAna(ITree tree) {
+
+        boolean save =true;
+        
+        IHistogram2D hm = (IHistogram2D)tree.find("Cluster hit map all");        
+        plotBasic2DMap(hm,"Cluster Hit Map", "Horizontal Crystal Index","Vertical Crystal Index",save);
+        
+        IHistogram1D hAmp = (IHistogram1D)tree.find("Cluster size all");
+        plotBasic1D(hAmp,"Cluster Size", "Cluster Size","Arbitrary Units","green",save);
+
+        IHistogram1D hAmp2 = (IHistogram1D)tree.find("Cluster energy all");
+        plotBasic1D(hAmp2,"Cluster Energy", "Cluster Energy","Arbitrary Units","green",save);
+
+        IHistogram1D hAmp3 = (IHistogram1D)tree.find("toptrig_cl_ecal_e_bottom");
+        plotBasic1D(hAmp3,"Cluster Energy Bottom Unbiased", "Cluster Energy","Arbitrary Units","green",save);
+
+        IHistogram2D hcrhm = (IHistogram2D)tree.find("Crystal hit map all");        
+        plotBasic2DMap(hcrhm,"Crystal Hit Map", "Horizontal Crystal Index","Vertical Crystal Index",save);
+
+        IHistogram1D hEP_t = (IHistogram1D)tree.find("allcl_clEoverP_top");
+        plotBasic1D(hEP_t,"E over P Top", "E over P","Arbitrary Units","green",save);
+
+        IHistogram1D hdx_t = (IHistogram1D)tree.find("allcl_cltrkdx_all");
+        plotBasic1D(hdx_t,"Track Matching", "Cluster X - Track X [mm]","Arbitrary Units","blue",save);
+
+        IHistogram1D hdy_t = (IHistogram1D)tree.find("allcl_cltrkdy_all");
+        plotBasic1D(hdy_t,"Track Matching", "Cluster Y - Track Y [mm]","Arbitrary Units","green",save);
+
+        
+        
+
+
+    
+        
+    }
+    
+    
+    
+    public void plotEcalFilter(ITree tree) {
+
+        boolean save = true;
+       
+        IHistogram2D hAmpMap = (IHistogram2D)tree.find("HPS-TestRun-v2 : EcalCalHits : Mean (Amplitude)");        
+        plotBasic2DMap(hAmpMap,"Average Crystal Amplitude", "Horizontal Crystal Index","Vertical Crystal Index",save);
+
+        
+        IHistogram1D hAmp = (IHistogram1D)tree.find("HPS-TestRun-v2 : EcalCalHits : <Mean> (Amplitude) Filter");        
+        plotBasic1D(hAmp,"Average Crystal Amplitude", "Average Crystal Amplitude","Arbitrary Units","",save);
+
+        IHistogram1D hAmp2 = (IHistogram1D)tree.find("/HPS-TestRun-v2 : EcalCalHits : <Mean> (Amplitude) Bottom Trig Filter");
+        plotBasic1D(hAmp2,"Average Crystal Amplitude unbiased", "Average Crystal Amplitude","Arbitrary Units","",save);
+
+        
+        IHistogram1D hAmpSingle = (IHistogram1D)tree.find("ECAL Amplitudes: x=21; y=-1");        
+        plotBasic1D(hAmpSingle,"Single Crystal Amplitude (21,-1)", "Single Crystal Amplitude","Arbitrary Units","",save);
+        
+        IHistogram1D hAmpSingle2 = (IHistogram1D)tree.find("Top ECAL Amplitudes: x=21; y=-1");        
+        plotBasic1D(hAmpSingle2,"Single Crystal Amplitude unbiased (21,-1)", "Single Crystal Amplitude","Arbitrary Units","",save);
+        
+        
+    }
+
+   
+    
+    public void overLayUpStrBkg(ITree tree_empty, ITree tree) {
+        
+        boolean save = true;
+        
+        IHistogram1D hYp_t = (IHistogram1D)tree.find("Top track q>0 Y @ -67cm");        
+        IHistogram1D hYn_t = (IHistogram1D)tree.find("Top track q<0 Y @ -67cm");                
+        IHistogram1D heYp_t = (IHistogram1D)tree_empty.find("Top track q>0 Y @ -67cm");
+        IHistogram1D heYn_t = (IHistogram1D)tree_empty.find("Top track q<0 Y @ -67cm");        
+
+        IHistogram1D hYp_b = (IHistogram1D)tree.find("Bottom track q>0 Y @ -67cm");        
+        IHistogram1D hYn_b = (IHistogram1D)tree.find("Bottom track q<0 Y @ -67cm");                
+        IHistogram1D heYp_b = (IHistogram1D)tree_empty.find("Bottom track q>0 Y @ -67cm");        
+        IHistogram1D heYn_b = (IHistogram1D)tree_empty.find("Bottom track q<0 Y @ -67cm");        
+
+        
+        double r_t = 1933.479;
+        double r_b = 1933.479;
+        double re_t = 309.785;
+        double re_b = 309.785;
+        
+        double c_t = re_t/r_t;
+        double c_b = re_b/r_b;
+
+        //plotBasic1D(hYp_t,"Top track q>0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","blue");
+        //plotBasic1D(heYp_t,"Top track q>0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","red");
+        //plotBasic1D(hYp_t,heYp_t,"Top track q>0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","blue");
+        //plotBasic1D(hYn_t,heYn_t,"Top track q<0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","blue");
+
+        //plotBasic1D(hYp_b,heYp_b,"Bottom track q>0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","blue");
+        //plotBasic1D(hYn_b,heYn_b,"Bottom track q<0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","blue");
+
+        
+        heYp_t.scale(hYp_t.entries()/heYp_t.entries()*c_t);
+        heYn_t.scale(hYn_t.entries()/heYn_t.entries()*c_t);
+
+        heYp_b.scale(hYp_b.entries()/heYp_b.entries()*c_b);
+        heYn_b.scale(hYn_b.entries()/heYn_b.entries()*c_b);
+
+        plotBasic1D(hYp_t,heYp_t,"(norm) Top track q>0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","","",save);
+        plotBasic1D(hYn_t,heYn_t,"(norm) Top track q<0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","","",save);
+
+        plotBasic1D(hYp_b,heYp_b,"(norm) Bottom track q>0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","","",save);
+        plotBasic1D(hYn_b,heYn_b,"(norm) Bottom track q<0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","","",save);
+
+        
+        IHistogram1D hsYn_t = hf.subtract("(subtr) Top track q<0 Y @ -67cm", hYn_t, heYn_t);
+        IHistogram1D hsYp_t = hf.subtract("(subtr) Top track q>0 Y @ -67cm", hYp_t, heYp_t);
+
+        IHistogram1D hsYn_b = hf.subtract("(subtr) Bottom track q<0 Y @ -67cm", hYn_b, heYn_b);
+        IHistogram1D hsYp_b = hf.subtract("(subtr) Bottom track q>0 Y @ -67cm", hYp_b, heYp_b);
+
+        plotBasic1D(hsYp_t,"(subtr) Top track q>0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","blue",save);
+        plotBasic1D(hsYn_t,"(subtr) Top track q<0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","blue",save);
+        plotBasic1D(hsYp_b,"(subtr) Bottom track q>0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","blue",save);
+        plotBasic1D(hsYn_b,"(subtr) Bottom track q<0 Y @ -67cm", "Track Y @ -67cm [mm]","Arbitrary Units","blue",save);
+        
+        
+        
+        
+    }
+    
+    
+
+/*    
+    public void plotAveAmpMap(ITree tree) {
+
+        System.out.println("plotAveAmp with tree " + tree.name());
+
+        IHistogram2D hm = (IHistogram2D)tree.find("Cluster hit map all");
+        
+        
+        IPlotter plotter_hm = af.createPlotterFactory().create();
+        plotter_hm.setTitle("Cluster Hit Map");
+        plotter_hm.createRegion().plot(hm);
+        plotter_hm.show();
+        default2DStyle(plotter_hm.region(0).style());
+        plotter_hm.style().statisticsBoxStyle().setVisible(false);
+        plotter_hm.style().setParameter("hist2DStyle","colorMap");
+        plotter_hm.style().dataStyle().fillStyle().setParameter("colorMapScheme","rainbow");
+              //((PlotterRegion) plotter_trig_other.region(i)).getPlot().setAllowPopupMenus(true);
+        
+        
+        
+        
+    }
+
+    */
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
FastTrack.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/FastTrack.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/FastTrack.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,142 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import java.util.List;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.tracker.silicon.*;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+
+/**
+ *
+ * @author phansson
+ */
+public class FastTrack {
+
+    private Hep3Vector _startVec;
+    private Hep3Vector _endVec;
+    private boolean _debug;
+    private double _slope;
+    private double _const;
+    double _beamGapCorr;
+   
+    
+    public FastTrack(boolean debug) {
+        _debug = debug; 
+        _beamGapCorr = 0.0;
+    }
+    
+    
+    
+    public FastTrack(Hep3Vector startPos, Hep3Vector endPos, double corr, boolean debug) {
+        //create the track using a straight line in the non-bending plane
+        //The non-bending plane is y-z:
+        //    z is beam direction
+        //    x is parallel to axial strips
+        //    y is measurement direction/orthogonal to strip direction 
+        _debug = debug;
+        _beamGapCorr = corr;    
+        setTrack(startPos,endPos);
+        
+    }
+    
+     public FastTrack(Hep3Vector startPos, double[] endPos, double corr, boolean debug) {
+        //create the track using a straight line in the non-bending plane
+        //The non-bending plane is y-z:
+        //    z is beam direction
+        //    x is parallel to axial strips
+        //    y is measurement direction/orthogonal to strip direction 
+        _debug = debug;
+        _beamGapCorr = corr;    
+        setTrack(startPos,endPos);
+        
+    }
+
+     
+    public void setTrack(Hep3Vector startPos, double[] endPos) {
+        //create the track using a straight line in the non-bending plane
+        //The non-bending plane is y-z:
+        //    z is beam direction
+        //    x is parallel to axial strips
+        //    y is measurement direction/orthogonal to strip direction 
+        Hep3Vector endPos_vec = new BasicHep3Vector(endPos[0],endPos[1],endPos[2]);
+        setTrack(startPos,endPos_vec);
+        
+    }
+     
+    
+    public double getCorrY(double y) {
+        double ynew = y;
+        if (y>0) ynew += _beamGapCorr;
+        else ynew -= _beamGapCorr;
+        return ynew;
+    }
+      
+    public void setTrack(Hep3Vector startPos, Hep3Vector endPos) {
+        //create the track using a straight line in the non-bending plane
+        //The non-bending plane is y-z:
+        //    z is beam direction
+        //    x is parallel to axial strips
+        //    y is measurement direction/orthogonal to strip direction 
+        _startVec = startPos;
+        //Correct for a possible beamgap difference in the geometry of the ecal
+        double y = getCorrY(endPos.y());
+        Hep3Vector endPos_corr = new BasicHep3Vector(endPos.x(),y,endPos.z());
+        _endVec = endPos_corr;
+        _slope = getSlope();
+        _const = getConst();
+        
+        
+    }
+     
+     
+    private double getSlope() {
+        double z1 = _startVec.z();  
+        double z2 = _endVec.z();  
+        double y1 = _startVec.y();  
+        double y2 = _endVec.y();  
+        return (y2-y1)/(z2-z1);
+    }
+
+    private double getConst() {
+        return -1.0*(_slope*_startVec.z());  
+    }
+
+    
+    public double eval(double x) {
+        // non-bend plane is y-z
+        return _slope*x+_const;
+    }
+    
+    public double getFastTrackResidual(SiTrackerHitStrip1D stripCluster) {
+        Hep3Vector posVec = stripCluster.getPositionAsVector();
+        double res = posVec.y() - this.eval(posVec.z());
+        
+        if(_debug) {
+            System.out.println("Hit pos " + posVec.toString());
+            System.out.println("FastTrack position " + this.eval(posVec.z()) + " and z " + posVec.z() + " --> res " + res);
+        }
+        return res;        
+    }
+            
+    public void setEcalBeamgapCorr(double offset) {
+        this._beamGapCorr = offset;    
+    }
+    
+    public String toString() {
+        String s = "FastTrack info: ";
+        s += " startPos: " + _startVec.toString() + "\n";
+        s += " endPos: " + _endVec.toString() + "\n";
+        s += " ECalOffsetY: " + _beamGapCorr + "\n";
+        s += "slope: " + _slope;
+        s += "const: " + _const;
+        return s;
+    }
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
FastTrackResidualDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/FastTrackResidualDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/FastTrackResidualDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,817 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import hep.aida.ref.plotter.PlotterRegion;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.detector.tracker.silicon.*;
+import org.lcsim.event.*;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson+
+ */
+public class FastTrackResidualDriver extends Driver {
+    
+    int nevents = 0;
+    boolean debug = false;
+    boolean saveFile = false;
+    protected IDDecoder dec = null;
+    protected Subdetector ecal;
+    private String ecalName = "Ecal";
+    String sides[] = {"up","down"};
+    double crystalX;
+    double crystalY;
+    double beamGap;
+    double EcalZPosition;
+    double conversionZ;
+    private static int crystalCols;
+    private static int crystalRows;
+    double ecalBeamgapCorr;
+    int ecalClusterSel;
+
+    private String outputPlotFileName = "";
+    
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    private List< List<IHistogram1D> > resy_org = new ArrayList<List<IHistogram1D> >();
+    private List< List<IHistogram1D> > resy_org_layallhit = new ArrayList<List<IHistogram1D> >();
+    private List< List<IHistogram1D> > resy_org_layallsinglehit = new ArrayList<List<IHistogram1D> >();
+    private List< List<IHistogram1D> > resy_org_lay1hit = new ArrayList<List<IHistogram1D> >();
+    private List< IHistogram1D > nhits_tracker = new ArrayList<IHistogram1D>();
+    private List< List<IHistogram1D> > nhits_tracker_layer = new ArrayList<List<IHistogram1D> >();
+    private List< IHistogram1D > ncl_ecal = new ArrayList<IHistogram1D>();
+    private List< IHistogram1D > selcl_ecal_e = new ArrayList<IHistogram1D>(); 
+    private List< IHistogram1D > cl_ecal_e = new ArrayList<IHistogram1D>();
+    private List< IHistogram2D > ncl_ecal_map = new ArrayList<IHistogram2D>(); 
+    private List< IHistogram2D > nselcl_ecal_map = new ArrayList<IHistogram2D>(); 
+    private List< IHistogram2D> resy_2d_org_layallhit = new ArrayList<IHistogram2D>();
+    private List< IHistogram2D> resy_2d_org_layallsinglehit = new ArrayList<IHistogram2D>();
+    
+    
+    public void startOfData() {
+    }
+    
+    public void detectorChanged(Detector detector) {
+	// Get the Subdetector.
+	ecal = detector.getSubdetector(ecalName);
+
+	// Cache ref to decoder.
+	dec = ecal.getIDDecoder();
+        
+        //Ecal geometry
+        crystalX = (13.3 + 16.0) / 2;
+        crystalY = (13.3 + 16.0) / 2;
+        beamGap = 20.0;
+        EcalZPosition = 1370.0;
+        crystalCols = 46;
+        crystalRows = 5;
+        
+        ecalBeamgapCorr = 0.0;
+        
+        // Position of the conversion
+        conversionZ = -1500.0; 
+        
+        ecalClusterSel = 0;
+        
+        IHistogramFactory hf = aida.histogramFactory();
+        String side;
+        for (int iSide=0;iSide<2;++iSide) {
+            if(iSide==0) side="up";
+            else side="down";
+            
+            ncl_ecal.add(hf.createHistogram1D("FT_ncl_ecal_" + side , 20, 0, 20));
+            selcl_ecal_e.add(hf.createHistogram1D("FT_selcl_ecal_e" + side , 100, 0, 4000));
+            cl_ecal_e.add(hf.createHistogram1D("FT_cl_ecal_e" + side , 100, 0, 4000));
+           
+
+            nhits_tracker.add(hf.createHistogram1D("FT_nhits_tracker_" + side , 15, 0, 15));
+
+            List<IHistogram1D> nhl_list  = new ArrayList<IHistogram1D>();
+            nhits_tracker_layer.add(nhl_list);
+            for (int i=0;i<5;++i) {
+                nhl_list.add(hf.createHistogram1D("FT_nhits_tracker_" + side + "_layer" + i , 15, 0, 15));
+            }
+
+                        
+            double res_axis[] = {-40,40};
+
+            
+            resy_2d_org_layallhit.add(hf.createHistogram2D("FT_resy_2d_org_layallhit_" + side, 5, 0.5, 5.5, 60, res_axis[0], res_axis[1]));
+            resy_2d_org_layallsinglehit.add(hf.createHistogram2D("FT_resy_2d_org_layallsinglehit_" + side, 5, 0.5, 5.5, 60, res_axis[0], res_axis[1]));
+            
+                   
+            List<IHistogram1D> list  = new ArrayList<IHistogram1D>();
+            resy_org.add(list);
+            List<IHistogram1D> listLayAllHit  = new ArrayList<IHistogram1D>();
+            resy_org_layallhit.add(listLayAllHit);
+            List<IHistogram1D> listLay1Hit  = new ArrayList<IHistogram1D>();
+            resy_org_lay1hit.add(listLay1Hit);  
+            List<IHistogram1D> listLayAllSingleHit  = new ArrayList<IHistogram1D>();
+            resy_org_layallsinglehit.add(listLayAllSingleHit);
+
+                
+            //Setup the ecal 2D plot
+                        
+            if (side == "up") {
+                ncl_ecal_map.add(hf.createHistogram2D("FT_ecal_hitmap_" + side, 92, -46.0, 46.0, 5, 0.0, 5.0));
+                nselcl_ecal_map.add(hf.createHistogram2D("FT_sel_ecal_hitmap_" + side, 92, -46.0, 46.0, 5, 0.0, 5.0));
+            } else {
+                ncl_ecal_map.add(hf.createHistogram2D("FT_ecal_hitmap_" + side, 92, -46.0, 46.0, 5, -5.0, 0.0));
+                nselcl_ecal_map.add(hf.createHistogram2D("FT_sel_ecal_hitmap_" + side, 92, -46.0, 46.0, 5, -5.0, 0.0));
+            }
+
+            for (int iLayer=1;iLayer<6;++iLayer) {
+                
+                IHistogram1D h = hf.createHistogram1D("FT_res_" + side + "_l"+iLayer, 50, res_axis[0], res_axis[1]);
+                list.add(h);
+
+                IHistogram1D hAll = hf.createHistogram1D("FT_res_LayAllHit_" + side + "_l"+iLayer, 50,res_axis[0], res_axis[1]);
+                listLayAllHit.add(hAll);
+                
+                IHistogram1D hLay1 = hf.createHistogram1D("FT_res_Lay1Hit_" + side + "_l"+iLayer, 50,res_axis[0], res_axis[1]);
+                listLay1Hit.add(hLay1);
+                
+                IHistogram1D hAllSingle = hf.createHistogram1D("FT_res_LayAllSingleHit_" + side + "_l"+iLayer, 50,res_axis[0], res_axis[1]);
+                listLayAllSingleHit.add(hAllSingle);
+                
+            }
+        }
+        
+        
+        displayFastTrackingPlots();
+        
+        
+        
+    }
+    
+    public FastTrackResidualDriver() {}
+    
+
+    public void setConversionZ(double z) {
+        this.conversionZ = z;
+    }
+    
+    public void setecalBeamgapCorr(double val) {
+        this.ecalBeamgapCorr = val;
+        System.out.println("beamgap corr set: "  + ecalBeamgapCorr);
+    }
+
+    public void setDebug(boolean flag) {
+        this.debug = flag;
+    }
+    
+    public void setOutputPlotFileName( String name ) {
+        this.outputPlotFileName = name;
+    }
+
+    public void setEcalZPosition(double val) {
+        this.EcalZPosition = val;
+        System.out.println("EcalZPosition set: "  + EcalZPosition);
+    }
+    
+    public void setEcalClusterSel(int id) {
+        this.ecalClusterSel = id;
+        System.out.println("ecalClusterSel set: "  + ecalClusterSel);
+    }
+    
+    
+    public void process(EventHeader event) {
+        ++nevents;
+        if( debug ) {
+            System.out.println("Processing event " + nevents);    
+        }
+        
+        fastTracking(event);
+        
+    }
+        
+    public void fastTracking(EventHeader event) {
+        
+        if ( debug) {
+            System.out.println("Running fast tracking on this event");
+        }
+        
+        
+        
+        //Get list of all Hits in the event
+        List<SiTrackerHitStrip1D> trackerHits = getAllHitsInEvent(event);
+        
+        
+        
+        //Get the calorimeter cluster object used to construct the track
+        List<HPSEcalCluster> ecal_all_clusters = getAllEcalClustersForFastTracking(event);
+        //Exit if no clusters found
+        if (ecal_all_clusters.size()==0) return;
+
+        //if ( 1==1 ) return;
+        
+        
+        int nhits;
+        int nhitsInTracker;
+        int nhitsInLayer1;
+        Hep3Vector origin_pos;
+        List<Integer> ecal_cls;
+        FastTrack fastTrack = new FastTrack(debug);
+        fastTrack.setEcalBeamgapCorr(ecalBeamgapCorr); //Correct for geometry
+
+        //List<SiTrackerHitStrip1D> stripList;
+        boolean isaxial;
+        String name;
+        SiSensor siSensor;
+        int layer;
+        String si_side;
+        double res;
+        int selclids[];
+        int sel_ecal_idx;
+        int layerIndex = -1;
+        for (int iSide=0;iSide<2;++iSide) {
+            
+        
+            //if ( 1==1 ) return;
+            
+            ecal_cls = getEcalClustersForFastTracking(ecal_all_clusters, sides[iSide]);
+            
+            if (debug) {
+                    System.out.println("Found  " + ecal_cls.size() +" Ecal clusters on the " + sides[iSide] + ": " + ecal_cls.toString());
+            }
+            
+            
+            //if ( 1==1 ) return;
+            
+            ncl_ecal.get(iSide).fill(ecal_cls.size());
+            
+            if( ecal_cls.size() ==0 ) {
+                if(debug) System.out.println("No clusters on this side...");
+                continue;
+            }
+            
+            
+            //Fill map of Ecal hits
+            for( int icl=0; icl<ecal_cls.size(); ++icl) {
+                if(debug) System.out.println("icl " + icl);
+                int clid = ecal_cls.get(icl); 
+                if(debug) System.out.println("clid " + clid + " all clusters size " + ecal_all_clusters.size());
+                int clpos[] = getCrystalPair(ecal_all_clusters.get(clid));
+                if(debug) System.out.println("clpos " + clpos[0] + "," + clpos[1]);
+                ncl_ecal_map.get(iSide).fill(clpos[0], clpos[1]);
+                if(debug) System.out.println("clpos " + clpos[0] + "," + clpos[1]);
+                cl_ecal_e.get(iSide).fill(ecal_all_clusters.get(icl).getEnergy());
+            }
+            
+            sel_ecal_idx = selectCluster(ecal_cls,ecal_all_clusters); 
+            
+            
+            if (sel_ecal_idx < 0) {
+                if (debug) System.out.println("No selected cluster!");
+                continue;
+            }
+            
+            if (debug) System.out.println("Selected clid " + sel_ecal_idx + " is cluster " + ecal_all_clusters.get(sel_ecal_idx).toString() + " and will be used as pointer of fast track ");
+            
+            
+             
+            selclids = getCrystalPair(ecal_all_clusters.get(sel_ecal_idx));
+            nselcl_ecal_map.get(iSide).fill(selclids[0], selclids[1]);
+            
+            selcl_ecal_e.get(iSide).fill(ecal_all_clusters.get(sel_ecal_idx).getEnergy());
+             
+            //Get "target" position i.e. the origin of the radiation
+            origin_pos = getFastTrackOrigin(event);
+            
+            if (debug) System.out.println("Conversion started at " + origin_pos.toString());
+            
+            //Create the fast track 
+            fastTrack.setTrack(origin_pos,ecal_all_clusters.get(sel_ecal_idx).getPosition());
+            
+
+            if ( debug ) System.out.println(fastTrack.toString());
+           
+            
+        
+            nhits = 0;
+            nhitsInTracker = getNAxialHits(trackerHits,sides[iSide]);
+            
+            if( debug ) System.out.println("There are " + nhitsInTracker + " hits on this side of the tracker");
+            
+            //most upstream layer nr is different for top and bottom
+//            int firstLayer = 1;
+//            if (sides[iSide] == "down") firstLayer=2;
+//            nhitsInLayer1 = getNAxialHitsInLayers(trackerHits,sides[iSide],firstLayer);
+
+            int nhitsInLayers[] = getNAxialHitsPerLayer(trackerHits,sides[iSide]);
+
+            boolean allLayersHasHits = true;
+            boolean allLayersHasSingleHit = true;
+            for (int i=0;i<5;++i){
+                if(nhitsInLayers[i]==0) allLayersHasHits = false;
+                if(nhitsInLayers[i]!=1) allLayersHasSingleHit = false;
+            }
+            
+            if( debug ) {
+                System.out.println("Number of hits per layer:");
+                for (int i=0;i<5;++i){
+                    System.out.println("Layer " + (i+1) + " has " + nhitsInLayers[i] + " axial hits");                    
+                }
+            }
+            
+            nhits_tracker.get(iSide).fill(nhitsInTracker);
+            for (int i=0;i<5;++i){
+                nhits_tracker_layer.get(iSide).get(i).fill(nhitsInLayers[i]);
+            }
+            //stripList = new ArrayList<SiTrackerHitStrip1D>();
+            for ( SiTrackerHitStrip1D stripCluster : trackerHits ) {
+                System.out.println("cluster at " + stripCluster.getPositionAsVector().toString() + " " + stripCluster.getSensor().toString());
+                
+                isaxial = isAxialHit(stripCluster);
+                
+                if( isaxial == false) continue;
+                
+                siSensor = stripCluster.getSensor();
+                name = siSensor.getName();
+                
+                if ( name.length() < 14) {
+                    System.err.println("This name is too short!!");
+                    throw new RuntimeException("SiSensor name " + name + " is invalid?");
+                }
+                
+                
+                layer = getLayerFromSiCluster(stripCluster);
+                
+                si_side = getSideFromSiCluster(stripCluster);
+                
+                if ( debug ) {
+                    System.out.println("hit " + nhits + " in layer " + layer + " on " + si_side + " side of detector");
+                }
+
+                
+                if( sides[iSide] != si_side) {
+                     if (debug) System.out.println("This hit is opposite side side as Ecal cluster side -> skip!");
+                     continue;
+                } 
+               
+                if (debug) System.out.println("Hit and cluster both on " + sides[iSide] + " side -> use it!");
+               
+                
+                res = fastTrack.getFastTrackResidual(stripCluster);
+            
+                if (debug) System.out.println("-->res " + res);
+                
+//                1 2 3 4 5 6 7 8 9 10
+//                0   1   2   3   4
+//                  0   1   2   3   4
+               
+                // Fix the layer for the list index -> ugly
+                layerIndex = layer;
+                if ( layer % 2 == 0 ) layerIndex=layer/2-1; 
+                else layerIndex = (layer-1)/2;
+                resy_org.get(iSide).get(layerIndex).fill(res);
+                
+               
+                
+                if (allLayersHasHits) {
+                    resy_org_layallhit.get(iSide).get(layerIndex).fill(res);
+                    resy_2d_org_layallhit.get(iSide).fill((double)layerIndex+1, res, 1);
+                }
+                if (allLayersHasSingleHit) {
+                    resy_org_layallsinglehit.get(iSide).get(layerIndex).fill(res);
+                    resy_2d_org_layallsinglehit.get(iSide).fill((double)layerIndex+1, res, 1);
+                }
+                
+                if (nhitsInLayers[0]>0) {
+                    resy_org_lay1hit.get(iSide).get(layerIndex).fill(res);
+                }
+            
+                ++nhits;
+            }
+        
+            if ( debug ) System.out.println("Processed " + nhits + " for this side");
+        }
+       return;
+    }
+    
+    
+    
+    List<SiTrackerHitStrip1D> getAllHits(EventHeader event) {
+        List<SiTrackerHitStrip1D> stripHits = event.get(SiTrackerHitStrip1D.class, "StripClusterer_SiTrackerHitStrip1D");
+        if(debug) System.out.println("Got " + stripHits.size() + " SiTrackerHitStrip1D in this event");
+        return stripHits;
+    }
+    
+    
+    List<SiTrackerHitStrip1D> getAllHitsInEvent(EventHeader event) {
+        //First a workaround - use hits from track.. 
+        //List<TrackerHit> hits = getAllHitsFromTracks(event);
+        List<SiTrackerHitStrip1D> hits = getAllHits(event);
+        return hits;
+    }
+    
+    private Hep3Vector getFastTrackOrigin(EventHeader event) {
+        double tx = 0.0;
+        double ty = 0.0;
+        Hep3Vector pos = new BasicHep3Vector(tx,ty,conversionZ);
+                
+        return pos;
+    }
+        
+    
+    
+    
+//    private List<HPSEcalCluster> getAllEcalClusters(EventHeader event) {
+//        
+//        List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, "EcalReadoutHits"); 
+//        //List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, "EcalClusters"); 
+//
+//        if ( debug) {
+//            System.out.println("Found " + clusters.size() + " clusters");
+//        }
+//        return clusters;
+//    }
+
+ 
+    public int[] getCrystalPair(HPSEcalCluster cluster) {
+        int[] pos = new int[2];
+        pos[0] = cluster.getSeedHit().getIdentifierFieldValue("ix");
+        pos[1] = cluster.getSeedHit().getIdentifierFieldValue("iy");
+        
+        //System.out.println("cluster ix,iy " + pos[0] + "," + pos[1] + "    from pos  " + cluster.getSeedHit().getPositionVec().toString());
+        return pos;
+        //getCrystalPair(cluster.getPosition());
+    }
+    
+    
+    private List<Integer> getEcalClustersForFastTracking(List<HPSEcalCluster> clusters, String side) {
+        if(side!="up" && side!="down") {
+            throw new RuntimeException("This ecal side" + side + " do not exist!!");
+        }
+        List<Integer> cls = new ArrayList<Integer>();
+        boolean save;
+        int [] pos;
+        
+        for (int i=0;i<clusters.size();++i) {
+            save=false;
+            
+            pos = getCrystalPair(clusters.get(i));
+            
+            if(pos[1]>=0 && side=="up") {
+                save=true;
+            } 
+            if(pos[1]<0 && side=="down") {
+                save=true;
+            } 
+            if(save) {
+                //cls.add(new BasicHep3Vector(pos[0],pos[1],EcalZPosition));
+                cls.add(i);
+                //new BasicHep3Vector(pos[0],pos[1],pos[2]));
+            }
+            
+        }
+        return cls;
+    }
+     
+    private int selectCluster(List<Integer> ids, List<HPSEcalCluster> clusters) {
+        //need to decide which cluster to take
+
+        
+        if (clusters.size()==0) {
+            throw new RuntimeException("No clusters to select from!!!");
+        }
+
+        if (ids.size()==0) {
+            throw new RuntimeException("No idx to clusters to select from!!!");
+        }
+        
+        if(debug) {
+            System.out.println("Select among " + clusters.size() + " clusters restricted to indexes" + ids.toString());
+        }
+        
+        int sel_id = -1;
+        
+        switch (ecalClusterSel) {
+            case 1: 
+                //Require at least 1000MeV cluster
+                double E = -1.0;
+                for (int i=0;i<ids.size();++i) {
+                    if (clusters.get(ids.get(i)).getEnergy()>1000.0 && clusters.get(ids.get(i)).getEnergy()>E ) {
+                        sel_id = ids.get(i);
+                        E = clusters.get(ids.get(i)).getEnergy();
+                    }
+                }
+                break;
+            default:
+                //Use the first in list
+                if (ids.size()>0 && ids.get(0)<clusters.size()) {
+                    sel_id = ids.get(0);
+                }
+                break;
+        }
+        if (debug) System.out.println("Selected ecal cluster id  " + sel_id);
+        
+        return sel_id;        
+           
+    }
+
+    private List<HPSEcalCluster> getAllEcalClustersForFastTracking(EventHeader event) {
+        
+        //List<HPSEcalCluster> clusters = new ArrayList<HPSEcalCluster>();
+        List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, "EcalClusters"); 
+        //List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, "EcalReadoutHits"); 
+        //List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, "EcalCalHits"); 
+        if ( debug) {
+            System.out.println("Found " + clusters.size() + " EcalClusters");
+        }
+        
+     
+        return clusters;
+    }
+
+
+     
+    private boolean isAxialHit(SiTrackerHitStrip1D strip) {
+        String side = this.getSideFromSiCluster(strip);
+        int layer = this.getLayerFromSiCluster(strip);
+        return layer%2==0 ? false : true;
+        
+        //int ref_l = ref_helper.getValue(ref_id, "layer"); // 1-10; axial layers are odd layers; stereo layers are even
+        //int ref_s = ref_helper.getValue(ref_id, "module"); // 0-1; module number is top or bottom
+//        boolean axial = false;
+//        Hep3Vector m = strip.getMeasuredCoordinate();
+//        //System.out.println("y " + m.y() + " -> abs(y) " + Math.abs(m.y()) );
+//        if ( Math.abs((Math.abs(m.y())-1.0))<0.0000000001 ) {
+//            axial = true;
+//            //System.out.println( " ===> " + axial );
+//        }
+//        return axial;
+    }
+        
+    private int getNAxialHits(List<SiTrackerHitStrip1D> trackerHits, String side) {
+        int nhits=0;
+        for ( SiTrackerHitStrip1D stripCluster : trackerHits ) {
+            if(isAxialHit(stripCluster)) {
+                String si_side = getSideFromSiCluster(stripCluster);
+                
+                if( side == si_side) {
+                    ++nhits;
+                }
+            }
+        }
+                          
+        return nhits;
+    }   
+    
+     private int getNAxialHitsInLayers(List<SiTrackerHitStrip1D> trackerHits, String side, int layer) {
+        int nhits=0;
+        String si_side;
+        SiSensor siSensor;
+        String name;
+        int l;
+        for ( SiTrackerHitStrip1D stripCluster : trackerHits ) {
+            
+            if(isAxialHit(stripCluster)==false) continue;
+            
+            si_side = getSideFromSiCluster(stripCluster);
+
+            if( side == si_side) {
+                
+                siSensor = stripCluster.getSensor();
+                name = siSensor.getName();
+                if ( name.length() < 14) {
+                    System.err.println("This name is too short!!");
+                    throw new RuntimeException("SiSensor name " + name + " is invalid?");
+                }
+            
+                l = this.getLayerFromSiCluster(stripCluster);
+                if ( l == layer) ++nhits;
+            
+            } 
+        }
+                          
+        return nhits;
+    }   
+     
+      public int[] getNAxialHitsPerLayer(List<SiTrackerHitStrip1D> trackerHits, String side) {
+        int nhits=0;
+        String si_side;
+        SiSensor siSensor;
+        String name;
+        int l;
+        int i;
+        int n[] = {0,0,0,0,0};
+        for ( SiTrackerHitStrip1D stripCluster : trackerHits ) {
+            
+            if(isAxialHit(stripCluster)==false) continue;
+           
+            si_side = getSideFromSiCluster(stripCluster);
+
+            if( side == si_side) {
+                
+                siSensor = stripCluster.getSensor();
+                name = siSensor.getName();
+                if ( name.length() < 14) {
+                    System.err.println("This name is too short!!");
+                    throw new RuntimeException("SiSensor name " + name + " is invalid?");
+                }
+                l = this.getLayerFromSiCluster(stripCluster);
+                
+                
+                //Turn this into the layer scheme I use
+                    i = ((l+1)/2) - 1;
+                    n[i] = n[i] + 1;                    
+//                if(side=="down") {
+//                    i = ((l+1)/2) - 1;
+//                    n[i] = n[i] + 1;                    
+//                } else {
+//                    //even numbers are used
+//                    i = (l/2) - 1;
+//                    n[i] = n[i] + 1;
+//                }
+            
+            } 
+
+        }
+                          
+        return n;
+    }   
+    
+     private String getSideFromSiCluster(SiTrackerHitStrip1D stripCluster) {       
+         IIdentifierHelper ref_helper = stripCluster.getIdentifierHelper();
+         IIdentifier ref_id = stripCluster.getSensor().getIdentifier();
+                int ref_l = ref_helper.getValue(ref_id, "layer"); // 1-10; axial layers are odd layers; stereo layers are even
+                int ref_s = ref_helper.getValue(ref_id, "module"); // 0-1; module number is top or bottom
+                return ref_s==0 ? "up" : "down";
+////        Hep3Vector posVec = stripCluster.getPositionAsVector();
+////        double yHit = posVec.y();
+////        String side;
+////        if (yHit>=0.0) side = "up";
+////        else side = "down";
+////        return side;
+    }
+
+     private int getLayerFromSiCluster(SiTrackerHitStrip1D stripCluster) {       
+         IIdentifierHelper ref_helper = stripCluster.getIdentifierHelper();
+         IIdentifier ref_id = stripCluster.getSensor().getIdentifier();
+                int ref_l = ref_helper.getValue(ref_id, "layer"); // 1-10; axial layers are odd layers; stereo layers are even
+                int ref_s = ref_helper.getValue(ref_id, "module"); // 0-1; module number is top or bottom
+                return ref_l;
+////        Hep3Vector posVec = stripCluster.getPositionAsVector();
+////        double yHit = posVec.y();
+////        String side;
+////        if (yHit>=0.0) side = "up";
+////        else side = "down";
+////        return side;
+    }
+    
+    private int getLayerFromSensorName(String name) {
+            int ilayer = -1;// = Integer.parseInt(layer.substring(layer.length()-1));
+            if (name.contains("layer")) {
+                
+                //String str_l = name.substring(13);
+            String str_l = name.substring(name.indexOf("layer")+5, name.indexOf("_module"));
+            ilayer = Integer.parseInt(str_l);
+               
+                if ( ilayer < 1 || ilayer > 10 ) {
+                    System.out.println("This layer doesn't exist?");
+                    throw new RuntimeException("SiSensor name " + name + " is invalid?");
+                }
+                
+            } else {
+                throw new RuntimeException("This sensor name do not have a layer!");
+            }
+            System.out.println("Name " + name + " -> layer " + ilayer);
+            return ilayer;
+    }
+    
+   
+    
+
+   
+    
+   public void displayFastTrackingPlots() {
+        //IPlotter plotter = af.createPlotterFactory(af.createTreeFactory().create());
+        IPlotter plotter_org = af.createPlotterFactory().create("HPS SVT Fast Track Residuals (All tracks)");
+        plotter_org.createRegions(5,2,0);
+        IPlotter plotter_org_LayAllHit = af.createPlotterFactory().create("HPS SVT Fast Track Residuals (All layers has hits)");
+        plotter_org_LayAllHit.createRegions(6,2,0);
+        IPlotter plotter_org_LayAllSingleHit = af.createPlotterFactory().create("HPS SVT Fast Track Residuals (All layers has single hit)");
+        plotter_org_LayAllSingleHit.createRegions(6,2,0);
+        IPlotter plotter_org_Lay1Hit = af.createPlotterFactory().create("HPS SVT Fast Track Residuals (1st layer has hits)");
+        plotter_org_Lay1Hit.createRegions(5,2,0);
+        
+        for ( int iSide=0;iSide<2;++iSide) {
+            int nLayers = resy_org.get(iSide).size();
+            for (int iLayer=0;iLayer<nLayers;++iLayer) {
+                int idx = 2*iLayer+iSide;
+                
+                //0 1 2 3 4
+                //1 3 5 7 9
+                
+                plotter_org.region(idx).plot(resy_org.get(iSide).get(iLayer));
+                plotter_org_LayAllHit.region(idx).plot(resy_org_layallhit.get(iSide).get(iLayer));
+                plotter_org_LayAllSingleHit.region(idx).plot(resy_org_layallsinglehit.get(iSide).get(iLayer));
+                plotter_org_Lay1Hit.region(idx).plot(resy_org_lay1hit.get(iSide).get(iLayer));
+
+
+            }
+            //IPlotterStyle style = plotter_org_LayAllHit.style();
+            //style.regionBoxStyle().
+                    
+            plotter_org_LayAllHit.region(10+iSide).style().setParameter("hist2DStyle", "colorMap");
+            plotter_org_LayAllHit.region(10+iSide).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+            plotter_org_LayAllHit.region(10+iSide).plot(resy_2d_org_layallhit.get(iSide));
+            plotter_org_LayAllSingleHit.region(10+iSide).style().setParameter("hist2DStyle", "colorMap");
+            plotter_org_LayAllSingleHit.region(10+iSide).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+            plotter_org_LayAllSingleHit.region(10+iSide).plot(resy_2d_org_layallsinglehit.get(iSide));
+        }
+        plotter_org.show();
+        plotter_org_LayAllHit.show();
+        plotter_org_LayAllSingleHit.show();
+        plotter_org_Lay1Hit.show();
+        
+        
+        
+        //Hit multiplicity
+        IPlotter plotter_hitmult = af.createPlotterFactory().create();
+        plotter_hitmult.createRegions(1,2,0);
+        plotter_hitmult.region(0).plot(nhits_tracker.get(0));
+        plotter_hitmult.region(1).plot(nhits_tracker.get(1));
+        plotter_hitmult.show();
+        
+        IPlotter plotter_hitmult_layer = af.createPlotterFactory().create();
+        plotter_hitmult_layer.createRegions(5,2,0);
+        for ( int iSide=0;iSide<2;++iSide) {
+            int nLayers = resy_org.get(iSide).size();
+            for (int iLayer=0;iLayer<nLayers;++iLayer) {
+                int idx = 2*iLayer+iSide;
+                
+                //0 1 2 3 4
+                //1 3 5 7 9
+                plotter_hitmult_layer.region(idx).plot(nhits_tracker_layer.get(iSide).get(iLayer));
+              
+            }
+        }
+        plotter_hitmult_layer.show();
+        
+        
+        //ECal plots
+        IPlotter plotter_ecalhitmult = af.createPlotterFactory().create();
+        plotter_ecalhitmult.createRegions(5,2,0);
+        plotter_ecalhitmult.region(0).plot(ncl_ecal.get(0));
+        plotter_ecalhitmult.region(1).plot(ncl_ecal.get(1));
+        plotter_ecalhitmult.region(2).plot(ncl_ecal_map.get(0));
+        plotter_ecalhitmult.region(3).plot(ncl_ecal_map.get(1));
+        plotter_ecalhitmult.region(4).plot(nselcl_ecal_map.get(0));
+        plotter_ecalhitmult.region(5).plot(nselcl_ecal_map.get(1));
+        plotter_ecalhitmult.region(6).plot(cl_ecal_e.get(0));
+        plotter_ecalhitmult.region(7).plot(cl_ecal_e.get(1));
+        plotter_ecalhitmult.region(8).plot(selcl_ecal_e.get(0));
+        plotter_ecalhitmult.region(9).plot(selcl_ecal_e.get(1));
+        plotter_ecalhitmult.show();
+        
+        
+          for (int idx=2;idx<6;++idx) {
+                IPlotterStyle style = plotter_ecalhitmult.region(idx).style();
+                style.setParameter("hist2DStyle", "colorMap");
+                style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+                ((PlotterRegion) plotter_ecalhitmult.region(idx)).getPlot().setAllowUserInteraction(false);
+		((PlotterRegion) plotter_ecalhitmult.region(idx)).getPlot().setAllowPopupMenus(false);
+          }
+               
+        
+        
+    }
+    
+    
+    
+    
+    public void endOfData() {
+        
+        if (outputPlotFileName != "")
+        try {
+            aida.saveAs(outputPlotFileName);
+        } catch (IOException ex) {
+            Logger.getLogger(FastTrackResidualDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+        }
+        displayFastTrackingPlots();
+        
+    }
+
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
GlobalParameter.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/GlobalParameter.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/GlobalParameter.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,116 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.vec.Hep3Matrix;
+import hep.physics.vec.Hep3Vector;
+
+/**
+ *
+ * @author phansson
+ */
+public class GlobalParameter {
+    
+    private String _name;
+    private int _side;
+    private int _layer;
+    private int _type;
+    private int _direction;
+    
+    private boolean _active;
+    private BasicMatrix _dfdp = null;
+    
+   
+    
+    public GlobalParameter(String name,int side,int layer,int type,int direction,boolean active) {
+        _name = name;
+        _side = side;
+        _layer = layer;
+        _type = type;
+        _direction = direction;
+        _active = active;
+    
+    }
+
+    public void setParameters(String name,int side,int layer,int type,int direction,boolean active) {
+        clear();
+        _name = name;
+        _side = side;
+        _layer = layer;
+        _type = type;
+        _direction = direction;
+        _active = active;
+    }
+
+    public void clear() {
+        _name = "";
+        _side = -1;
+        _layer = -1;
+        _type = -1;
+        _direction = -1;
+        _active = false;
+        _dfdp=null;
+    }
+    
+    public void setDfDp(BasicMatrix mat) {
+        _dfdp = mat;
+    }
+
+    public void setDfDp(Hep3Vector v) {
+        _dfdp = new BasicMatrix(3,1);
+        _dfdp.setElement(0, 0, v.x());
+        _dfdp.setElement(1, 0, v.y());
+        _dfdp.setElement(2, 0, v.z());
+    }
+
+    public boolean active() {
+        return _active;
+    }
+    
+    public BasicMatrix getDfDp(BasicMatrix mat) {
+        return _dfdp;
+    }
+    
+    public double dfdp(int dim) {
+        return _dfdp.e(dim,0);
+    }
+    
+    public int getLabel() {
+        int label = _side + _type + _direction + _layer;  
+        return label;
+    }
+    
+    public int getSide() {
+        return _side;
+    }
+    
+    public int getLayer() {
+        return _layer;
+    }
+    
+    public int getType() {
+        return _type;
+    }
+    
+    public int getDirection() {
+        return _direction;
+    }
+
+    public String getName() {
+        return _name;
+    }
+    
+    public void print() {
+        System.out.println("GP: " + _name + " " + " side " + _side + " layer " + _layer + " type " + _type + " dir " + _direction + " label " + getLabel() + " Active: " + _active);
+        if(_dfdp==null) {
+            System.out.println("dfdp not evaluated yet");
+        } else {
+            System.out.println("dfdp: " + _dfdp.e(0,0) + " , " + _dfdp.e(1,0) + " , " + _dfdp.e(2, 0));
+        }
+    }
+
+
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
GlobalParameters.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/GlobalParameters.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/GlobalParameters.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,77 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author phansson
+ */
+
+
+public class GlobalParameters {
+
+    //private List<GlobalParameter> _gps;
+    
+    public static final int NGL = 10;
+    private List<GlobalParameter> _gps = new ArrayList<GlobalParameter>(); 
+    public static final int[] _types = {1000,2000};
+    public static final int[] _sides = {10000,20000};
+    public static final int[] _dirs = {100,200,300};
+    
+    public GlobalParameters() {
+        //initialize the parameters
+        //Naming scheme:
+        //[Top]:
+        // 10000 = top
+        // 20000 = bottom
+        //[Type]: 
+        // 1000 - translation
+        // 2000 - rotation
+        //[Direction] (tracker coord. frame)
+        // 100 - x (beamline direction)
+        // 200 - y (non-measurement plane / bend plane)
+        // 300 - z (measurement direction)
+        // [Layer]
+        // 1-10
+              
+        boolean ON;
+        for(int iside=0;iside<2;++iside) {
+            for(int ilayer=1;ilayer<11;++ilayer) {
+                for (int itype=0;itype<2;++itype) {
+                    for (int idir=0;idir<3;++idir) {
+                        //if(_sides[iside]==10000 && ilayer==3 && _types[itype]==1000 && _dirs[idir]==300) ON=true;
+                        //if(ilayer==3 && _types[itype]==1000 && _dirs[idir]==300) ON=true;
+                        ON =true;
+                        //if(_types[itype]==1000 && _dirs[idir]==300) ON=true;
+                        //else ON=false;
+                        GlobalParameter gp = new GlobalParameter("test",_sides[iside],ilayer,_types[itype],_dirs[idir],ON);
+                        _gps.add(gp);
+                    }
+                }
+            }
+        }
+    }
+        
+        
+    
+
+    
+
+    public List<GlobalParameter> getList() {
+        return _gps;
+    }
+    
+    public void print() {
+        System.out.println("---- Global parameters ("+ _gps.size() + ")");
+        for(GlobalParameter p : _gps) {
+            p.print();
+        }
+        System.out.println("----");
+    }
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
MPAlignmentInputCalculator.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/MPAlignmentInputCalculator.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/MPAlignmentInputCalculator.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,133 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.IAnalysisFactory;
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.event.Track;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.hps.recon.tracking.TrackerHitUtils;
+import org.lcsim.hps.users.mgraham.alignment.RunAlignment;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson
+ */
+public abstract class MPAlignmentInputCalculator {
+    protected final int _nTrackParameters = 5;  //the five track parameters
+    protected boolean _DEBUG = false;
+    private String _outfile;
+    protected List<GlobalParameter> _glp;
+    protected BasicMatrix _dfdq;
+    protected HelicalTrackFit _trk;
+    protected String _type = "LOCAL";
+    protected Hep3Vector _bfield;
+    protected ResLimit _resLimits;
+    protected AlignmentUtils _alignUtils;
+    protected AlignmentUtils.OldAlignmentUtils _oldAlignUtils;
+    protected AlignmentUtils.NumDerivatives _numDerivatives;
+    protected TrackerHitUtils trackerHitUtil;
+    protected boolean hideFrame = false;
+    protected AIDA aida = AIDA.defaultInstance();
+    protected IAnalysisFactory af = aida.analysisFactory();
+    
+    protected boolean _includeMS = true;
+    public abstract void PrintResidualsAndDerivatives(Track track, int itrack);
+    protected abstract void makeAlignmentPlots();
+    public abstract void updatePlots();
+    private FileWriter fWriter;
+    private PrintWriter pWriter;
+    
+    public MPAlignmentInputCalculator(String outfile,String type) {
+        _glp = new ArrayList<GlobalParameter>();
+        _resLimits = new ResLimit();
+        _alignUtils = new AlignmentUtils(_DEBUG);
+        _oldAlignUtils = new AlignmentUtils(_DEBUG).new OldAlignmentUtils();
+        _numDerivatives = new AlignmentUtils(_DEBUG).new NumDerivatives();
+        trackerHitUtil = new TrackerHitUtils(_DEBUG);
+        _bfield = new BasicHep3Vector(0., 0., 1.);
+        _type = type;
+        _outfile = outfile;
+        openFile();
+    }
+
+    
+
+    public void setResLimits(int l,int d, double low,double high) {
+        _resLimits.add(0,l,d, low,high); //top
+        _resLimits.add(1,l,d, low,high); //bottom
+    }
+
+
+    public void setResLimits(int s, int l,int d, double low,double high) {
+        _resLimits.add(s,l,d, low,high);
+    }
+
+     
+    public boolean isAllowedResidual(int side,int layer,int d,double res) {
+    
+        if(res <_resLimits.getMin(side,layer,d)) return false;
+        if(res >_resLimits.getMax(side,layer,d)) return false;
+        return true;
+        
+    }
+    
+    
+    public void closeFile() {
+        try {
+            pWriter.close();
+            fWriter.close();
+        } catch(IOException ex) {
+             Logger.getLogger(RunAlignment.class.getName()).log(Level.SEVERE, null, ex);
+        }
+    }
+
+    private void openFile() {
+         try {
+            fWriter = new FileWriter(_outfile);
+            pWriter = new PrintWriter(fWriter);
+        } catch (IOException ex) {
+            Logger.getLogger(RunAlignment.class.getName()).log(Level.SEVERE, null, ex);
+        }
+    }
+    
+    public void addMilleInputLine(String line) {
+        this.pWriter.print(line);
+    }
+
+    public void setDebug(boolean debug) {
+        this._DEBUG = debug;
+        _alignUtils.setDebug(debug);
+        _numDerivatives.setDebug(debug);
+    }
+
+    public void setHideFrame(boolean hide) {
+        this.hideFrame = hide;
+    }
+
+    public void setIncludeMS(boolean include) {
+        this._includeMS = include;
+    }
+
+   
+    public void setUniformZFieldStrength(double bfield) {
+        _bfield = new BasicHep3Vector(0.0, 0.0, bfield);
+    }
+
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
ModuleMPAlignmentInput.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ModuleMPAlignmentInput.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ModuleMPAlignmentInput.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,710 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import hep.aida.ref.plotter.PlotterRegion;
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.matrix.MatrixOp;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.*;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.tracking.SvtUtils;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+
+/**
+ * Class to calculate and print the residuals and derivatives
+ * of the alignment parameters...used as input for MillePede
+ * Notation follows the MillePede manual:
+ * http://www.desy.de/~blobel/Mptwo.pdf
+ *
+ * the track is measured in the HelicalTrackFit frame
+ * and residuals are in the tracking frame (x,y,z)
+ *
+ * ordering of track parameters is
+ *    double d0 = _trk.dca();
+ *    double z0 = _trk.z0();
+ *    double slope = _trk.slope();
+ *    double phi0 = _trk.phi0();
+ *    double R = _trk.R();
+ *
+ * @author mgraham
+ */
+public final class ModuleMPAlignmentInput extends MPAlignmentInputCalculator {
+
+    private double[] _resid = new double[3];
+    private double[] _error = new double[3];
+    
+    
+    private AIDAFrame plotterFrame;
+    private AIDAFrame plotterFrameSummary;
+    private IDataPointSet dps_t;
+    private IDataPointSet dps_b;
+    private IDataPointSet dps_pull_t;
+    private IDataPointSet dps_pull_b;
+    private IPlotter plotter_resuydiff_t;
+    private IPlotter plotter_resuydiff_b;
+    
+    
+    
+   
+    
+    
+    
+    public ModuleMPAlignmentInput(String outfile,String type) {
+        super(outfile,type);
+        
+        makeAlignmentPlots();
+
+    }
+
+ 
+    
+    @Override
+    public void PrintResidualsAndDerivatives(Track track, int itrack) {
+        
+        SeedTrack st = (SeedTrack) track;
+        SeedCandidate seed = st.getSeedCandidate();
+        Map<HelicalTrackHit, MultipleScatter> msmap = seed.getMSMap();
+        _trk = seed.getHelix();
+        List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+        String half = hitsOnTrack.get(0).getPosition()[2]>0 ? "top" : "bottom";
+        this.addMilleInputLine(String.format("TRACK %s (%d)\n",half,itrack));
+        aida.cloud1D("Track Chi2 "+ half).fill(track.getChi2());
+        aida.cloud1D("Track Chi2ndf "+ half).fill(track.getChi2()/track.getNDF());
+        if(_DEBUG) System.out.printf("%s: track %d (chi2=%.2f ndf=%d) has %d hits\n",this.getClass().getSimpleName(),itrack,track.getChi2(),track.getNDF(),hitsOnTrack.size());
+        for (TrackerHit hit : hitsOnTrack) {
+            
+            HelicalTrackHit htc = (HelicalTrackHit) hit;
+            
+            if(!(htc instanceof HelicalTrackCross)) {
+                if(_DEBUG) System.out.println(this.getClass().getSimpleName() + ": this hit is not a cross");
+                continue;
+            }
+            
+            // Update the hit position to be sure it's the latest
+            HelicalTrackCross cross = (HelicalTrackCross) htc;
+            cross.setTrackDirection(_trk);
+            
+
+            CalculateResidual(htc);
+            CalculateLocalDerivatives(htc);
+            CalculateGlobalDerivatives(htc);
+            PrintHitResiduals(htc);
+
+            
+        }
+        
+        if(itrack%50==0) this.updatePlots();
+    }
+
+    
+   
+    
+    private void CalculateLocalDerivatives(HelicalTrackHit hit) {
+        double xint = hit.x();
+        BasicMatrix dfdqGlobalOld = _oldAlignUtils.calculateLocalHelixDerivatives(_trk, xint);
+        BasicMatrix dfdqGlobal = _alignUtils.calculateLocalHelixDerivatives(_trk, xint);
+        BasicMatrix dfdqGlobalNum = this._numDerivatives.calculateLocalHelixDerivatives(_trk, xint);
+        _dfdq = dfdqGlobal;
+        
+        if (_DEBUG) {
+            
+            //get track parameters.
+            double d0 = _trk.dca();
+            double z0 = _trk.z0();
+            double slope = _trk.slope();
+            double phi0 = _trk.phi0();
+            double R = _trk.R();
+            double s = HelixUtils.PathToXPlane(_trk, xint, 0, 0).get(0);
+            double phi = -s/R + phi0;
+            double[] trackpars = {d0, z0, slope, phi0, R, s, xint};
+            System.out.printf("%s: --- CalculateLocalDerivatives HelicalTrackHit Result --- \n",this.getClass().getSimpleName());
+            System.out.printf("%s: Hit position: %s \n",this.getClass().getSimpleName(),hit.getCorrectedPosition().toString());
+            System.out.printf("%s: %10s%10s%10s%10s%10s%10s%10s\n",this.getClass().getSimpleName(),"d0","z0","slope","phi0","R", "xint", "s");
+            System.out.printf("%s: %10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f\n",this.getClass().getSimpleName(), d0, z0, slope, phi0, R,xint,s);
+            System.out.printf("%s: Local derivatives:\n",this.getClass().getSimpleName());
+            System.out.printf("%s\n",dfdqGlobal.toString());
+            System.out.printf("%s: Numerical Local derivatives:\n",this.getClass().getSimpleName());
+            System.out.printf("%s\n",dfdqGlobalNum.toString());
+            System.out.printf("%s: OLD Local derivatives:\n",this.getClass().getSimpleName());
+            System.out.printf("%s\n",dfdqGlobalOld.toString());
+        }
+    
+    }
+    
+    
+   
+    
+    
+    private void CalculateGlobalDerivatives(HelicalTrackHit hit) {
+        
+        /*
+         * Residual in tracking frame is defined as r = m_a-p
+         * with m_a as the alignment corrected position (u_a,v_a,w_a) 
+         * and p is the predicted hit position in the tracking frame
+         * 
+         * Calcualte the derivative of dr/da where
+         * a=(delta_u,delta_v,delta_w,alpha,beta,gamma) 
+         * are the alingment paramerers in the tracking frame
+         * 
+         * Factorize: dr/da=dr/dm_a*dm_a/da
+         * 
+         * Start with dr/dma
+         */
+        
+        //Find the unit vector of the track direction
+        TrackDirection trkdir = HelixUtils.CalculateTrackDirection(_trk, _trk.PathMap().get(hit));
+        Hep3Vector t = trkdir.Direction();
+        //Find the unit vector of the plane where the hit happened
+        if(!(hit instanceof HelicalTrackCross) ) {
+            throw new RuntimeException("Error: gl ders for HTH only works if they are crosses!");
+        }
+        
+        
+        HelicalTrackCross cross = (HelicalTrackCross) hit;
+        HelicalTrackStrip strip = cross.getStrips().get(0);
+        Hep3Vector n = strip.w();
+        
+        
+       
+        /*
+         * use the measured hit position 
+         */
+        double umeas,vmeas,wmeas;
+        umeas = hit.x();
+        vmeas = hit.y(); //the un-measured (along the strip) is set to zero
+        wmeas = hit.z(); // the hit is on the surface of the plane
+        
+        /*
+         * Calculate the dma_da 
+         */
+        
+        BasicMatrix dma_da = new BasicMatrix(3,6);
+        //dma_ddeltau
+        dma_da.setElement(0, 0, 1);
+        dma_da.setElement(1, 0, 0);
+        dma_da.setElement(2, 0, 0);
+        //dma_ddeltav
+        dma_da.setElement(0, 1, 0);
+        dma_da.setElement(1, 1, 1);
+        dma_da.setElement(2, 1, 0);
+        //dma_ddeltau
+        dma_da.setElement(0, 2, 0);
+        dma_da.setElement(1, 2, 0);
+        dma_da.setElement(2, 2, 1);
+        //dma_dalpha
+        dma_da.setElement(0, 3, 0);
+        dma_da.setElement(1, 3, wmeas);
+        dma_da.setElement(2, 3, -vmeas);
+        //dma_dbeta
+        dma_da.setElement(0, 4, -wmeas);
+        dma_da.setElement(1, 4, 0);
+        dma_da.setElement(2, 4, umeas);
+        //dma_dgamma
+        dma_da.setElement(0, 5, vmeas);
+        dma_da.setElement(1, 5, -umeas);
+        dma_da.setElement(2, 5, 0);
+        
+        
+        
+         /*
+         * Calculate the dr_dma 
+         * e_ij = delta(i,j) - t_i*t_j/(t*n)
+         */
+        BasicMatrix dr_dma = new BasicMatrix(3,3);
+        double tn = VecOp.dot(t, n);
+        double[] t_arr = t.v();
+        double[] n_arr = n.v();
+        for(int i=0;i<3;++i) {
+            for(int j=0;j<3;++j) {
+                double delta_ij = i==j ? 1 : 0;
+                double elem = delta_ij - t_arr[i]*n_arr[j]/tn;
+                dr_dma.setElement(i, j, elem);
+            }
+        }
+        
+        
+        
+        /*
+         * Calculate the dr/da=dr/dma*dma/da
+         */
+        
+        BasicMatrix dr_da = (BasicMatrix) MatrixOp.mult(dr_dma, dma_da);
+        
+   
+        int layer = hit.Layer();
+        int side = SvtUtils.getInstance().isTopLayer((SiSensor) ((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement()) ? 10000 : 20000;
+
+        
+        if(_DEBUG) {
+            double phi = -_trk.PathMap().get(hit)/_trk.R()+_trk.phi0();
+            System.out.printf("%s: --- Calculate SIMPLE global derivatives for helical track hit ---\n",this.getClass().getSimpleName());
+            System.out.printf("%s: Side %d, layer %d, hit position %s\n",this.getClass().getSimpleName(),side,layer,hit.getCorrectedPosition().toString());
+            System.out.printf("%s: %10s%10s%10s%10s%10s%10s%10s%10s\n",this.getClass().getSimpleName(),"d0","z0","slope","phi0","R","phi","xint","s");
+            System.out.printf("%s: %10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f\n",this.getClass().getSimpleName(), _trk.dca(), _trk.z0(), _trk.slope(), _trk.phi0(), _trk.R(),phi,hit.x(),_trk.PathMap().get(hit));
+            System.out.printf("%s: Track direction t = %s\n",this.getClass().getSimpleName(),t.toString());
+            System.out.printf("%s: Plane normal    n = %s\n",this.getClass().getSimpleName(),n.toString());
+            System.out.printf("%s: m=(umeas,vmeas,wmeas)=(%.3f,%.3f,%.3f)\n",this.getClass().getSimpleName(),umeas,vmeas,wmeas);
+            System.out.printf("dma_da=\n%s\ndr_dma=\n%s\ndr_da=\n%s\n",dma_da.toString(),dr_dma.toString(),dr_da.toString());
+            
+        }
+   
+        
+        
+        
+        /*
+         * Prepare the derivatives for output
+         */
+        
+        
+        
+        _glp.clear();
+        
+        GlobalParameter gp_tu = new GlobalParameter("Translation in x",side,layer,1000,100,true);
+        Hep3Vector mat = new BasicHep3Vector(dr_da.e(0, 0),dr_da.e(1, 0),dr_da.e(2, 0));
+        gp_tu.setDfDp(mat);
+        _glp.add(gp_tu);
+        if (_DEBUG) {
+            gp_tu.print();
+        }
+
+        GlobalParameter gp_tv = new GlobalParameter("Translation in y",side,layer,1000,200,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 1),dr_da.e(1, 1),dr_da.e(2, 1));
+        gp_tv.setDfDp(mat);
+        _glp.add(gp_tv);
+        if (_DEBUG) {
+            gp_tv.print();
+        }
+
+        
+        GlobalParameter gp_tw = new GlobalParameter("Translation in z",side,layer,1000,300,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 2),dr_da.e(1, 2),dr_da.e(2, 2));
+        gp_tw.setDfDp(mat);
+        _glp.add(gp_tw);
+        if (_DEBUG) {
+            gp_tw.print();
+        }
+        
+        GlobalParameter gp_ta = new GlobalParameter("Rotation alpha",side,layer,2000,100,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 3),dr_da.e(1, 3),dr_da.e(2, 3));
+        gp_ta.setDfDp(mat);
+        _glp.add(gp_ta);
+        if (_DEBUG) {
+            gp_ta.print();
+        }
+
+        GlobalParameter gp_tb = new GlobalParameter("Rotation beta",side,layer,2000,200,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 4),dr_da.e(1, 4),dr_da.e(2, 4));
+        gp_tb.setDfDp(mat);
+        _glp.add(gp_tb);
+        if (_DEBUG) {
+            gp_tb.print();
+        }
+        
+        GlobalParameter gp_tg = new GlobalParameter("Rotation gamma",side,layer,2000,300,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 5),dr_da.e(1, 5),dr_da.e(2, 5));
+        gp_tg.setDfDp(mat);
+        _glp.add(gp_tg);
+        if (_DEBUG) {
+            gp_tg.print();
+        }
+
+        
+
+        
+        
+    }
+
+    
+    
+    
+    
+   
+    
+    
+     private void CalculateResidual(HelicalTrackHit hit) {
+        if(_DEBUG) System.out.printf("%s: --- Calculate Residual for HelicalTrackhit ---\n",this.getClass().getSimpleName());
+
+         Map<String,Double> res_map = TrackUtils.calculateTrackHitResidual(hit, _trk, _includeMS);
+         _resid[0] = 0.;
+         _error[0] = 0.320/Math.sqrt(12);
+         _resid[1] = res_map.get("resy");
+         _error[1] = res_map.get("erry");
+         _resid[2] = res_map.get("resz");
+         _error[2] = res_map.get("errz");
+
+
+
+        //Fill residuals vs distrance from center of plane in the v directions
+        //aida.profile1D("res_u_vs_ydiff_layer_" + strip.layer() + "_" + side).fill(vdiffTrk.y(),_resid[0]);
+        
+        if (_DEBUG) {
+            System.out.printf("%s: CalculateResidual HelicalTrackHit Result ----\n",this.getClass().getSimpleName());
+            System.out.printf("%s: Hit positon: %s\n",this.getClass().getSimpleName(),hit.getCorrectedPosition().toString());
+            Hep3Vector trkpos = HelixUtils.PointOnHelix(_trk, HelixUtils.PathToXPlane(_trk, hit.x(), 0, 0).get(0));
+            System.out.printf("%s: Predicted position: %s\n",this.getClass().getSimpleName(),trkpos.toString());
+            System.out.printf("%s: drphi=%,4f dz=%.4f MS: drdphi=%.4f, dz=%.4f\n",this.getClass().getSimpleName(),hit.drphi(),hit.dr()*Math.abs(_trk.slope()),_trk.ScatterMap().get(hit).drphi(),_trk.ScatterMap().get(hit).dz());
+            System.out.printf("%s: %12s %12s %12s\n","resx","resy","resz");
+            System.out.printf("%s: %5.5f+-%5.5f %5.5f+-%5.5f %5.5f+-%5.5f\n",_resid[0],_error[0],_resid[1],_error[1],_resid[2],_error[2]);
+        }
+
+    }
+     
+    
+    
+    
+  
+
+   
+
+     private void PrintHitResiduals(HelicalTrackHit hit) {
+         HelicalTrackStrip strip = ((HelicalTrackCross) hit).getStrips().get(0);
+         String side = SvtUtils.getInstance().isTopLayer((SiSensor) ((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement()) ? "top" : "bottom";        
+        if (_DEBUG) {
+            System.out.printf("%s: --- Alignment Results for this helical track hit ---\n",this.getClass().getSimpleName());
+            
+            String sensor_type = SvtUtils.getInstance().isAxial((SiSensor) ((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement()) ? "axial" : "stereo";
+            System.out.printf("%s: Layer %d in %s at position %s\n",this.getClass().getSimpleName(), hit.Layer(),side, hit.getCorrectedPosition().toString());
+            System.out.printf("%s: Residuals (x,y,z) : %5.5e %5.5e %5.5e\n",this.getClass().getSimpleName(), _resid[0], _resid[1], _resid[2]);
+            System.out.printf("%s: Errors (x,y,z)    : %5.5e %5.5e %5.5e\n",this.getClass().getSimpleName(), _error[0], _error[1], _error[2]);
+            String[] q = {"d0", "z0", "slope", "phi0", "R"};
+            System.out.printf("%s: track parameter derivatives:\n",this.getClass().getSimpleName());
+            for (int i = 0; i < _nTrackParameters; i++) {
+                System.out.printf("%s: %s     %5.5e %5.5e %5.5e\n",this.getClass().getSimpleName(), q[i], _dfdq.e(0, i), _dfdq.e(1, i), _dfdq.e(2, i));
+            }
+            //String[] p = {"u-displacement"};
+            System.out.printf("%s: Global parameter derivatives\n",this.getClass().getSimpleName());
+            for (GlobalParameter gl : _glp) {
+                System.out.printf("%s: %s  %8.3e %5.8e %8.3e   %5d  \"%10s\"\n",this.getClass().getSimpleName(), "", gl.dfdp(0), gl.dfdp(1), gl.dfdp(2), gl.getLabel(),gl.getName());
+            }
+            System.out.printf("%s: --- END Alignment Results for this helical track hit ---\n",this.getClass().getSimpleName());
+        }
+        this.addMilleInputLine(String.format("%d\n", hit.Layer()));
+        // Loop over the three directions u,v,w and print residuals and derivatives
+        
+        List<String> direction = new ArrayList<String>(Arrays.asList("x","y","z"));
+        
+        int s = "bottom".equals(side) ? 1 : 0;
+        for(int j=0;j<direction.size();++j){
+           
+            
+            
+            //if(!isAllowedResidual(s,strip.layer(),j,_resid[j])) {
+            //    if(_DEBUG) System.out.println("Layer " + strip.layer() + " in " + d[j] + " res " + _resid[j] + " +- " + _error[j] + " was outside allowed range");
+            //    continue;
+            //}
+////            if(Math.abs(_resid[j]/_error[j])>3) {
+////                if(_DEBUG) System.out.println("Layer " + strip.layer() + " in " + d[j] + " res " + _resid[j] + " +- " + _error[j] + " had too high pull");
+////                continue;
+////            }
+            //This should really be x,y,z but the downstream parser likes u,v,w -> FIX THIS!
+            String d = direction.get(j).equals("x") ? "u" : direction.get(j).equals("y") ? "v" : "w";
+            this.addMilleInputLine(String.format("res_%s %5.5e %5.5e \n", d, _resid[j], _error[j])); 
+            for (int i = 0; i < _nTrackParameters; i++) {
+                this.addMilleInputLine(String.format("lc_%s %5.5e \n", d, _dfdq.e(j, i)));
+            }
+            for (GlobalParameter gl: _glp) {
+                if(gl.active()){
+                    this.addMilleInputLine(String.format("gl_%s %5.5e %5d\n", d, gl.dfdp(j), gl.getLabel()));
+                    
+                    //Cross check that side is correct
+                    int lbl = gl.getLabel();
+                    Double df = Math.floor(lbl/10000);
+                    int iside = (df.intValue() % 10) - 1;
+                    //System.out.println("track is on " + s + " gl param is " + lbl + "(" + df + ","+iside+")"  );
+                    if(iside!=s) {
+                        System.out.println("WARNING track is on " + s + " while gl param is " + lbl + "(" + df + ")"  );
+                        System.exit(1);
+                    }
+                    
+                }
+            }
+            if( _resid[j] < 9999999 ) {
+                if (_DEBUG) System.out.println(this.getClass().getSimpleName() + ": filling ures with " + _resid[j]);
+                aida.histogram1D("res_"+direction.get(j)+"_layer" + strip.layer() + "_" + side).fill(_resid[j]);    
+                aida.histogram1D("reserr_"+direction.get(j)+"_layer" + strip.layer() + "_" + side).fill(_error[j]);    
+                aida.histogram1D("respull_"+direction.get(j)+"_layer" + strip.layer() + "_" + side).fill(_resid[j]/_error[j]);    
+            
+            
+                aida.histogram2D("respull_slope_"+direction.get(j)+"_layer" + strip.layer() + "_" + side).fill(_trk.slope(),_resid[j]/_error[j]);    
+            }
+            
+        }
+    }
+ 
+
+    
+
+    
+    @Override
+    public void makeAlignmentPlots() {
+    
+        
+        
+        aida.tree().cd("/");
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("Residuals");
+        plotterFrameSummary = new AIDAFrame();
+        plotterFrameSummary.setTitle("Summary");
+              
+        List<String> sides = new ArrayList<String>(Arrays.asList("top","bottom"));
+
+        IPlotter plotter_chi2 = af.createPlotterFactory().create();
+        plotter_chi2.createRegions(2,2);
+        plotter_chi2.setTitle("Track Chi2");
+        plotterFrame.addPlotter(plotter_chi2);
+        ICloud1D hchi2_top = aida.cloud1D("Track Chi2 top");
+        ICloud1D hchi2_bot = aida.cloud1D("Track Chi2 bottom");
+        ICloud1D hchi2ndf_top = aida.cloud1D("Track Chi2ndf top");
+        ICloud1D hchi2ndf_bot = aida.cloud1D("Track Chi2ndf bottom");
+        plotter_chi2.region(0).plot(hchi2_top);
+        plotter_chi2.region(1).plot(hchi2_bot);
+        plotter_chi2.region(2).plot(hchi2ndf_top);
+        plotter_chi2.region(3).plot(hchi2ndf_bot);
+        
+        
+        List<String> direction = new ArrayList<String>(Arrays.asList("x","y","z"));
+        
+        
+        
+        double xbins_u_res[][] = {
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01}
+                {-0.15,0.15},
+                {-0.4,0.4},
+                {-0.7,0.7},
+                {-0.5,0.5},
+                {-0.5,0.5},
+                {-0.5,0.5},
+                {-2,2},
+                {-2,2},
+                {-2,2},
+                {-2,2}            
+        };
+        double xbins_u_reserr[][] = {
+                {0,0.04},
+                {0,0.04},
+                {0,0.5},
+                {0,0.5},
+                {0,0.7},
+                {0,0.7},
+                {0,1.2},
+                {0,1.2},
+                {0,1.5},
+                {0,1.5}
+        };
+        double xbins_u_respull[][] = {
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5}
+        };
+        
+        for (int d=0;d<direction.size();++d) { 
+
+            for (int s=0;s<2;++s) { 
+        //    if(iSide==1) continue;
+                IPlotter plotter_res = af.createPlotterFactory().create();
+                plotter_res.createRegions(5,2,0);
+                plotter_res.setTitle("res_" + direction.get(d) + " " + sides.get(s));
+                IPlotter plotter_reserr = af.createPlotterFactory().create();
+                plotter_reserr.createRegions(5,2,0);
+                plotter_reserr.setTitle("reserr_" + direction.get(d) + " " + sides.get(s));
+                IPlotter plotter_respull = af.createPlotterFactory().create();
+                plotter_respull.createRegions(5,2,0);
+                plotter_respull.setTitle("respull_" + direction.get(d) + " " + sides.get(s));
+                IPlotter plotter_respull_slope = af.createPlotterFactory().create();
+                plotter_respull_slope.createRegions(5,2,0);
+                plotter_respull_slope.setTitle("respull_slope_" + direction.get(d) + " " + sides.get(s));
+
+                for (int iLayer=1;iLayer<11;++iLayer) {
+                    
+                    IHistogram h = aida.histogram1D("res_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) , 50, xbins_u_res[iLayer-1][0], xbins_u_res[iLayer-1][1]);                        
+                    IHistogram h1 = aida.histogram1D("reserr_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) , 50, xbins_u_reserr[iLayer-1][0], xbins_u_reserr[iLayer-1][1]);            
+                    IHistogram h2 = aida.histogram1D("respull_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) , 50, xbins_u_respull[iLayer-1][0], xbins_u_respull[iLayer-1][1]);                        
+
+                    IHistogram hslope;
+                    if(sides.get(s)=="top") hslope = aida.histogram2D("respull_slope_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) ,50, 0 , 0.1, 50, xbins_u_respull[iLayer-1][0], xbins_u_respull[iLayer-1][1]);                        
+                    else hslope = aida.histogram2D("respull_slope_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) ,50, -0.1 , 0, 50, xbins_u_respull[iLayer-1][0], xbins_u_respull[iLayer-1][1]);                        
+                    
+                        
+                    int region = (iLayer-1);//*2+iSide;
+
+                    plotter_res.region(region).plot(h);
+                    plotter_reserr.region(region).plot(h1);
+                    plotter_respull.region(region).plot(h2);
+                    plotter_respull_slope.region(region).plot(hslope);
+
+                    ((PlotterRegion) plotter_res.region(region)).getPlot().setAllowUserInteraction(true);
+                    ((PlotterRegion) plotter_res.region(region)).getPlot().setAllowPopupMenus(true);
+                    ((PlotterRegion) plotter_reserr.region(region)).getPlot().setAllowUserInteraction(true);
+                    ((PlotterRegion) plotter_reserr.region(region)).getPlot().setAllowPopupMenus(true);
+                    ((PlotterRegion) plotter_respull.region(region)).getPlot().setAllowUserInteraction(true);
+                    ((PlotterRegion) plotter_respull.region(region)).getPlot().setAllowPopupMenus(true);
+                    ((PlotterRegion) plotter_respull_slope.region(region)).getPlot().setAllowUserInteraction(true);
+                    ((PlotterRegion) plotter_respull_slope.region(region)).getPlot().setAllowPopupMenus(true);
+                    plotter_respull_slope.style().dataStyle().fillStyle().setParameter("colorMapScheme","rainbow");
+                    ((PlotterRegion) plotter_respull_slope.region(region)).getPlot().setAllowPopupMenus(true);
+
+                   
+                } 
+
+                //plotter_res.show();
+                plotterFrame.addPlotter(plotter_res);
+                plotterFrame.addPlotter(plotter_reserr);
+                plotterFrame.addPlotter(plotter_respull);
+                plotterFrame.addPlotter(plotter_respull_slope);
+            }
+        
+            
+        
+           
+        }
+        
+        
+         
+         
+        IPlotter plotter_prf = af.createPlotterFactory().create();
+        plotter_prf.createRegions(1,2,0);
+        plotter_prf.setTitle("<Residuals>");
+        IDataPointSetFactory dpsf = aida.analysisFactory().createDataPointSetFactory(null);
+        dps_t = dpsf.create("dps_t", "Mean of u residuals top",2);
+        plotter_prf.region(0).plot(dps_t);
+        dps_b = dpsf.create("dps_b", "Mean of u residuals bottom",2);
+        plotter_prf.region(0).plot(dps_b);
+        
+        dps_pull_t = dpsf.create("dps_pull_t", "Mean of u pulls top",2);
+        plotter_prf.region(1).plot(dps_pull_t);
+        dps_pull_b = dpsf.create("dps_pull_b", "Mean of u pulls bottom",2);
+        plotter_prf.region(1).plot(dps_pull_b);
+
+        for(int region=0;region<2;++region) {
+            ((PlotterRegion) plotter_prf.region(region)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) plotter_prf.region(region)).getPlot().setAllowPopupMenus(true);
+        }
+        
+        plotterFrameSummary.addPlotter(plotter_prf);
+        
+        
+        plotter_resuydiff_t = af.createPlotterFactory().create();
+        plotter_resuydiff_t.createRegions(5,2,0);
+        plotter_resuydiff_t.setTitle("res u vs ydiff top");      
+        plotter_resuydiff_b = af.createPlotterFactory().create();
+        plotter_resuydiff_b.createRegions(5,2,0);
+        plotter_resuydiff_b.setTitle("res u vs ydiff bot");      
+        //plotter_resuydiff_t_b.createRegions(5,2,0);
+        //plotter_resuydiff_b.setTitle("distr: res u vs ydiff");      
+        for(int iLayer=1;iLayer<11;++iLayer) {
+            IProfile1D prf_t = aida.profile1D("res_u_vs_ydiff_layer_"+iLayer+"_top",10,-50,50);
+            IProfile1D prf_b = aida.profile1D("res_u_vs_ydiff_layer_"+iLayer+"_bottom",10,-50,50);          
+            plotter_resuydiff_t.region(iLayer-1).plot(prf_t);
+            plotter_resuydiff_b.region(iLayer-1).plot(prf_b);
+            ((PlotterRegion) plotter_resuydiff_t.region(iLayer-1)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) plotter_resuydiff_t.region(iLayer-1)).getPlot().setAllowPopupMenus(true);
+            ((PlotterRegion) plotter_resuydiff_b.region(iLayer-1)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) plotter_resuydiff_b.region(iLayer-1)).getPlot().setAllowPopupMenus(true);
+        }
+        
+        plotterFrameSummary.addPlotter(plotter_resuydiff_t);
+        plotterFrameSummary.addPlotter(plotter_resuydiff_b);
+        
+        
+        plotterFrame.pack();
+        plotterFrame.setVisible(!hideFrame);
+        plotterFrameSummary.pack();
+        plotterFrameSummary.setVisible(!hideFrame);
+        
+    
+    }
+    
+    
+    @Override
+    public void updatePlots() {
+        dps_t.clear();
+        dps_b.clear();
+        dps_pull_t.clear();
+        dps_pull_b.clear();
+        
+        final int nLayers = 10;
+        final List<String> direction = new ArrayList<String>(Arrays.asList("x","y","z"));
+        for(int i=1;i<nLayers+1;++i) {
+            
+            for(String d : direction) {
+
+                double mean = aida.histogram1D("res_"+d+"_layer"+i+"_top").mean();
+                double stddev = aida.histogram1D("res_"+d+"_layer"+i+"_top").rms();
+                double N =  aida.histogram1D("res_"+d+"_layer"+i+"_top").entries();
+                double error = N >0 ? stddev/Math.sqrt(N) : 0; 
+                dps_t.addPoint();
+                dps_t.point(i-1).coordinate(1).setValue(mean);
+                dps_t.point(i-1).coordinate(1).setErrorPlus(error);
+                dps_t.point(i-1).coordinate(0).setValue(i);
+                dps_t.point(i-1).coordinate(0).setErrorPlus(0);
+
+                mean = aida.histogram1D("res_"+d+"_layer"+i+"_bottom").mean();
+                stddev = aida.histogram1D("res_"+d+"_layer"+i+"_bottom").rms();
+                N =  aida.histogram1D("res_"+d+"_layer"+i+"_bottom").entries();
+                error = N >0 ? stddev/Math.sqrt(N) : 0; 
+                dps_b.addPoint();
+                dps_b.point(i-1).coordinate(1).setValue(mean);
+                dps_b.point(i-1).coordinate(1).setErrorPlus(error);
+                dps_b.point(i-1).coordinate(0).setValue(i);
+                dps_b.point(i-1).coordinate(0).setErrorPlus(0);
+
+                mean = aida.histogram1D("respull_"+d+"_layer"+i+"_top").mean();
+                stddev = aida.histogram1D("respull_"+d+"_layer"+i+"_top").rms();
+                N =  aida.histogram1D("respull_"+d+"_layer"+i+"_top").entries();
+                error = N >0 ? stddev/Math.sqrt(N) : 0; 
+                dps_pull_t.addPoint();
+                dps_pull_t.point(i-1).coordinate(1).setValue(mean);
+                dps_pull_t.point(i-1).coordinate(1).setErrorPlus(error);
+                dps_pull_t.point(i-1).coordinate(0).setValue(i);
+                dps_pull_t.point(i-1).coordinate(0).setErrorPlus(0);
+
+                mean = aida.histogram1D("respull_"+d+"_layer"+i+"_bottom").mean();
+                stddev = aida.histogram1D("respull_"+d+"_layer"+i+"_bottom").rms();
+                N =  aida.histogram1D("respull_"+d+"_layer"+i+"_bottom").entries();
+                error = N >0 ? stddev/Math.sqrt(N) : 0; 
+                dps_pull_b.addPoint();
+                dps_pull_b.point(i-1).coordinate(1).setValue(mean);
+                dps_pull_b.point(i-1).coordinate(1).setErrorPlus(error);
+                dps_pull_b.point(i-1).coordinate(0).setValue(i);
+                dps_pull_b.point(i-1).coordinate(0).setErrorPlus(0);
+                
+            }
+        }
+        
+         
+         
+    }
+
+    
+    
+    
+
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
MultScatAnalysis.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/MultScatAnalysis.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/MultScatAnalysis.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,2441 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import hep.aida.ref.plotter.PlotterRegion;
+import hep.physics.vec.BasicHepLorentzVector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.HepLorentzVector;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.detector.identifier.*;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.hps.evio.TriggerData;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.hps.recon.ecal.EcalConditions;
+import org.lcsim.hps.recon.tracking.EcalTrackMatch;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+import org.lcsim.event.base.BaseCluster;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+
+/**
+ *
+ * @author phansson+
+ */
+public class MultScatAnalysis extends Driver {
+    
+    int nevents = 0;
+    boolean debug = false;
+    boolean saveFile = false;
+    protected IDDecoder dec = null;
+    protected Subdetector ecal;
+    private String ecalName = "Ecal";
+    String sides[] = {"top","bottom","all"};
+    double crystalX;
+    double crystalY;
+    double beamGap;
+    double EcalZPosition;
+    public static final double TARGETZ = -67.4; //mm
+    private static int crystalCols;
+    private static int crystalRows;
+    int ecalClusterSel;
+    boolean hide = false;
+    
+    private String outputPlotFileName = "test.aida";
+    private String trackCollectionName = "MatchedTracks";
+    private String ecalClusterCollectionName = "EcalClusters";
+    private String inputEcalHitCollection = "EcalCalHits";
+    private boolean doTriggerPart = false;
+    private boolean doTrackingPart = false;
+    
+
+    
+    EcalTrackMatch trkMatchTool;
+    
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    IHistogramFactory hf = aida.histogramFactory();
+    private AIDAFrame plotterFrame;
+    private AIDAFrame plotterFrameTrig;
+    
+    IPlotter plotter_trig_tag;
+    IPlotter plotter_cltrkmatchE;
+    IHistogram1D clusterEnergy[][] = new IHistogram1D[47][11];
+            
+    private int trigger[] = {0,0};
+    
+    
+    private int refreshRate = 1000;
+    
+    
+    
+    public void startOfData() {
+    }
+    
+    public void detectorChanged(Detector detector) {
+	// Get the Subdetector.
+	ecal = detector.getSubdetector(ecalName);
+
+	// Cache ref to decoder.
+	dec = ecal.getIDDecoder();
+        
+        //Ecal geometry
+        crystalX = (13.3 + 16.0) / 2;
+        crystalY = (13.3 + 16.0) / 2;
+        beamGap = 37.0;//20.0;
+        crystalCols = 46;
+        crystalRows = 5;
+        
+        ecalClusterSel = 1;
+        
+        
+        if(doTriggerPart) {
+
+            plotterFrameTrig = new AIDAFrame();
+            plotterFrameTrig.setTitle("Trigger");
+
+            IPlotter plotter_trig_other = af.createPlotterFactory().create();
+            plotter_trig_other.createRegions(3,1,0);
+            plotter_trig_other.setTitle("Other");
+            plotterFrameTrig.addPlotter(plotter_trig_other);
+
+
+            IHistogram ht1 = aida.histogram1D("trigger_count" , 7, 0, 7); 
+            IHistogram ht2 = aida.histogram1D("trigger_bank" , 2, 0, 2); 
+            IHistogram ht3 = aida.histogram1D("trigger_list" , 2, 0, 2);         
+            plotter_trig_other.region(0).plot(ht1);
+            plotter_trig_other.region(1).plot(ht2);
+            plotter_trig_other.region(2).plot(ht3);
+            for(int i=0;i<3;++i) {
+                IPlotterStyle style = plotter_trig_other.region(i).style();
+                //style.setParameter("hist2DStyle", "colorMap");
+                //style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+                ((PlotterRegion) plotter_trig_other.region(i)).getPlot().setAllowUserInteraction(true);
+                ((PlotterRegion) plotter_trig_other.region(i)).getPlot().setAllowPopupMenus(true);
+            }
+
+
+
+
+            plotter_trig_tag = af.createPlotterFactory().create();
+            plotter_trig_tag.createRegions(3,3,0);
+            plotter_trig_tag.setTitle("Tag&Probe Top");
+            plotterFrameTrig.addPlotter(plotter_trig_tag);
+            IHistogram htag1 = aida.histogram1D("toptrig_cl_ecal_n_top" , 7, 0, 7); 
+            IHistogram htag2 = aida.histogram1D("toptrig_cl_ecal_e_top" , 100, 0, 1500); 
+            IHistogram htag3 = aida.histogram1D("toptrig_cl_ecal_emax_top" , 100, 0, 1500); 
+            IHistogram htag4 = aida.histogram1D("toptrig_cl_ecal_e_bottom" , 100, 0, 1500); 
+            IHistogram htag5 = aida.histogram1D("toptrig_cl_ecal_e_bottom_trig" , 100, 0, 1500); 
+            IHistogram htag6 = aida.histogram1D("toptrigtag_cl_ecal_e_bottom" , 100, 0, 1500); 
+            IHistogram htag7 = aida.histogram1D("toptrigtag_cl_ecal_e_bottom_trig" , 100, 0, 1500); 
+            IHistogram htag8 = aida.histogram1D("toptrig_cl_ecal_e_bottom_trigeff" , 100, 0, 1500); 
+            IHistogram htag9 = aida.histogram1D("toptrigtag_cl_ecal_e_bottom_trigeff" , 100, 0, 1500); 
+
+            plotter_trig_tag.region(0).plot(htag1);
+            plotter_trig_tag.region(3).plot(htag2);
+            plotter_trig_tag.region(6).plot(htag3);
+            plotter_trig_tag.region(1).plot(htag4);
+            plotter_trig_tag.region(2).plot(htag6);
+            plotter_trig_tag.region(4).plot(htag5);
+            plotter_trig_tag.region(5).plot(htag7);
+            plotter_trig_tag.region(7).plot(htag9);
+            plotter_trig_tag.region(8).plot(htag9);
+
+            for(int i=0;i<9;++i) {
+                IPlotterStyle style = plotter_trig_tag.region(i).style();
+                //style.setParameter("hist2DStyle", "colorMap");
+                //style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+                ((PlotterRegion) plotter_trig_tag.region(i)).getPlot().setAllowUserInteraction(true);
+                ((PlotterRegion) plotter_trig_tag.region(i)).getPlot().setAllowPopupMenus(true);
+            }
+
+
+            IPlotter plotter_trig_tag2 = af.createPlotterFactory().create();
+            plotter_trig_tag2.setTitle("Tag&Probe Top Counts");
+            plotterFrameTrig.addPlotter(plotter_trig_tag2);
+            IHistogram htag10 = aida.histogram1D("toptrig_cl_ecal_n_bottom" , 7, 0, 7); 
+            plotter_trig_tag2.createRegion().plot(htag10);
+
+            if(!hide) {
+                plotterFrameTrig.pack();
+                plotterFrameTrig.setVisible(true);
+            }
+
+        }
+
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("General");
+        
+        
+        
+        IPlotter plotter_ecal_pos = af.createPlotterFactory().create();
+        IPlotter plotter_ecal_e = af.createPlotterFactory().create();
+        IPlotter plotter_ecal_hitmap = af.createPlotterFactory().create();
+        IPlotter plotter_ecal_crhitmap = af.createPlotterFactory().create();
+        IPlotter plotter_ecal_cramp = af.createPlotterFactory().create();
+        IPlotter plotter_ecal_cls = af.createPlotterFactory().create();
+        
+        plotter_ecal_e.createRegions(2,3,0);
+        plotter_ecal_e.setTitle("Ecal Cluster Energy");
+        plotter_ecal_cramp.createRegions(2,3,0);
+        plotter_ecal_cramp.setTitle("Ecal Crystal Hit Map");
+        //plotter_ecal_crhitmap.style().statisticsBoxStyle().setVisible(false);
+        plotter_ecal_crhitmap.createRegions(2,3,0);
+        plotter_ecal_crhitmap.setTitle("Ecal Crystal Hit Map");
+        plotter_ecal_crhitmap.style().statisticsBoxStyle().setVisible(false);
+        plotter_ecal_hitmap.createRegions(2,3,0);
+        plotter_ecal_hitmap.setTitle("Ecal Cluster Hit Map");
+        plotter_ecal_hitmap.style().statisticsBoxStyle().setVisible(false);
+        plotter_ecal_pos.createRegions(2,3,0);
+        plotter_ecal_pos.setTitle("Ecal Cluster Position");
+        plotter_ecal_pos.style().statisticsBoxStyle().setVisible(false);
+        plotter_ecal_cls.createRegions(2,3,0);
+        plotter_ecal_cls.setTitle("Ecal Cluster size");
+
+        plotterFrame.addPlotter(plotter_ecal_e);
+        plotterFrame.addPlotter(plotter_ecal_crhitmap);
+        plotterFrame.addPlotter(plotter_ecal_cramp);
+        plotterFrame.addPlotter(plotter_ecal_hitmap);
+        plotterFrame.addPlotter(plotter_ecal_pos);
+        plotterFrame.addPlotter(plotter_ecal_cls);
+        
+        
+
+            IPlotter plotter_track_mom_pos = af.createPlotterFactory().create();
+            plotter_track_mom_pos.createRegions(3,3,0);
+            plotter_track_mom_pos.setTitle("Track Momentum vs Position");
+            plotter_track_mom_pos.style().statisticsBoxStyle().setVisible(false);
+            plotterFrame.addPlotter(plotter_track_mom_pos);
+            IHistogram hPzVsX_t = aida.histogram2D("Top track Pz vs X" , 25, -500,500, 50, 0, 3500);
+            IHistogram hPzVsX_b = aida.histogram2D("Bottom track Pz vs X" , 25, -500,500, 50, 0, 3500);
+            IHistogram hPzVsX_a = aida.histogram2D("Track Pz vs X" , 25, -500,500, 50, 0, 3500);
+            IHistogram hPzVsXqp_t = aida.histogram2D("Top track q>0 Pz vs X" , 25, -500,500, 50, 0, 3500);
+            IHistogram hPzVsXqp_b = aida.histogram2D("Bottom track q>0 Pz vs X" , 25, -500,500, 50, 0, 3500);
+            IHistogram hPzVsXqp_a = aida.histogram2D("Track q>0 Pz vs X" , 25, -500,500, 50, 0, 3500);
+            IHistogram hPzVsXqm_t = aida.histogram2D("Top track q<0 Pz vs X" , 25, -500,500, 50, 0, 3500);
+            IHistogram hPzVsXqm_b = aida.histogram2D("Bottom track q<0 Pz vs X" , 25, -500,500, 50, 0, 3500);
+            IHistogram hPzVsXqm_a = aida.histogram2D("Track q<0 Pz vs X" , 25, -500,500, 50, 0, 3500);
+            plotter_track_mom_pos.region(0).plot(hPzVsX_t);
+            plotter_track_mom_pos.region(1).plot(hPzVsX_b);
+            plotter_track_mom_pos.region(2).plot(hPzVsX_a);
+            plotter_track_mom_pos.region(3).plot(hPzVsXqp_t);
+            plotter_track_mom_pos.region(4).plot(hPzVsXqp_b);
+            plotter_track_mom_pos.region(5).plot(hPzVsXqp_a);
+            plotter_track_mom_pos.region(6).plot(hPzVsXqm_t);
+            plotter_track_mom_pos.region(7).plot(hPzVsXqm_b);
+            plotter_track_mom_pos.region(8).plot(hPzVsXqm_a);
+            for(int i=0;i<9;++i) {
+                plotter_track_mom_pos.region(i).style().setParameter("hist2DStyle", "colorMap");
+                plotter_track_mom_pos.region(i).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+                ((PlotterRegion) plotter_track_mom_pos.region(i)).getPlot().setAllowUserInteraction(true);
+                ((PlotterRegion) plotter_track_mom_pos.region(i)).getPlot().setAllowPopupMenus(true);
+
+            }
+
+
+            IPlotter plotter_track_mom = af.createPlotterFactory().create();
+            plotter_track_mom.createRegions(3,3,0);
+            plotter_track_mom.setTitle("Track Momentum");
+            plotterFrame.addPlotter(plotter_track_mom);
+            IHistogram hPz_t = aida.histogram1D("Top track Pz" , 50, 0, 3500);
+            IHistogram hPz_b = aida.histogram1D("Bottom track Pz" , 50, 0, 3500);
+            IHistogram hPz_a = aida.histogram1D("Track Pz" , 50, 0, 3500);
+            IHistogram hmPz_t = aida.histogram1D("Matched top track Pz" , 50, 0, 3500);
+            IHistogram hmPz_b = aida.histogram1D("Matched bottom track Pz" , 50, 0, 3500);
+            IHistogram hmPz_a = aida.histogram1D("Matched track Pz" , 50, 0, 3500);
+            IHistogram hmsPz_t = aida.histogram1D("Matched sel top track Pz" , 50, 0, 3500);
+            IHistogram hmsPz_b = aida.histogram1D("Matched sel bottom track Pz" , 50, 0, 3500);
+            IHistogram hmsPz_a = aida.histogram1D("Matched sel track Pz" , 50, 0, 3500);
+
+
+            plotter_track_mom.region(0).plot(hPz_t);
+            plotter_track_mom.region(1).plot(hPz_b);
+            plotter_track_mom.region(2).plot(hPz_a);
+            plotter_track_mom.region(3).plot(hmPz_t);
+            plotter_track_mom.region(4).plot(hmPz_b);
+            plotter_track_mom.region(5).plot(hmPz_a);
+            plotter_track_mom.region(6).plot(hmsPz_t);
+            plotter_track_mom.region(7).plot(hmsPz_b);
+            plotter_track_mom.region(8).plot(hmsPz_a);
+
+            IPlotter plotter_track_mom2 = af.createPlotterFactory().create();
+            plotter_track_mom2.createRegions(3,3,0);
+            plotter_track_mom2.setTitle("Track Momentum Target Outliers X");
+            plotterFrame.addPlotter(plotter_track_mom2);
+            IHistogram hPzTX_t = aida.histogram1D("Top track !target in X Pz" , 50, 0, 3500);
+            IHistogram hPzTX_b = aida.histogram1D("Bottom track !target in X Pz" , 50, 0, 3500);
+            IHistogram hPzTX_a = aida.histogram1D("Track !target in X Pz" , 50, 0, 3500);
+            IHistogram hmPzTX_t = aida.histogram1D("Matched top track !target in X Pz" , 50, 0, 3500);
+            IHistogram hmPzTX_b = aida.histogram1D("Matched bottom track !target in X Pz" , 50, 0, 3500);
+            IHistogram hmPzTX_a = aida.histogram1D("Matched track !target in X Pz" , 50, 0, 3500);
+            IHistogram hmsPzTX_t = aida.histogram1D("Matched sel top track !target in X Pz" , 50, 0, 3500);
+            IHistogram hmsPzTX_b = aida.histogram1D("Matched sel bottom track !target in X Pz" , 50, 0, 3500);
+            IHistogram hmsPzTX_a = aida.histogram1D("Matched sel track !target in X Pz" , 50, 0, 3500);
+
+
+            plotter_track_mom2.region(0).plot(hPzTX_t);
+            plotter_track_mom2.region(1).plot(hPzTX_b);
+            plotter_track_mom2.region(2).plot(hPzTX_a);
+            plotter_track_mom2.region(3).plot(hmPzTX_t);
+            plotter_track_mom2.region(4).plot(hmPzTX_b);
+            plotter_track_mom2.region(5).plot(hmPzTX_a);
+            plotter_track_mom2.region(6).plot(hmsPzTX_t);
+            plotter_track_mom2.region(7).plot(hmsPzTX_b);
+            plotter_track_mom2.region(8).plot(hmsPzTX_a);
+
+
+            IPlotter plotter_track_ext = af.createPlotterFactory().create();
+            plotter_track_ext.createRegions(2,3,0);
+            plotter_track_ext.setTitle("Track @ Target");
+            plotterFrame.addPlotter(plotter_track_ext);
+            IHistogram hTrkXAtConv_t = aida.histogram1D("Top track X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkYAtConv_t = aida.histogram1D("Top track Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkXAtConv_b = aida.histogram1D("Bottom track X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkYAtConv_b = aida.histogram1D("Bottom track Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkXAtConv_a = aida.histogram1D("Track X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkYAtConv_a = aida.histogram1D("Track Y @ -67cm" , 50, -20, 20);
+            plotter_track_ext.region(0).plot(hTrkXAtConv_t);
+            plotter_track_ext.region(1).plot(hTrkXAtConv_b);
+            plotter_track_ext.region(2).plot(hTrkXAtConv_a);
+            plotter_track_ext.region(3).plot(hTrkYAtConv_t);
+            plotter_track_ext.region(4).plot(hTrkYAtConv_b);
+            plotter_track_ext.region(5).plot(hTrkYAtConv_a);
+
+            IHistogram hTrkHMXAtConv_t = aida.histogram1D("Top track Pz>1GeV X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtConv_t = aida.histogram1D("Top track Pz>1GeV Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkHMXAtConv_b = aida.histogram1D("Bottom track Pz>1GeV X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtConv_b = aida.histogram1D("Bottom track Pz>1GeV Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkHMXAtConv_a = aida.histogram1D("Track Pz>1GeV X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtConv_a = aida.histogram1D("Track Pz>1GeV Y @ -67cm" , 50, -20, 20);
+            plotter_track_ext.region(0).plot(hTrkHMXAtConv_t,"mode=overlay");
+            plotter_track_ext.region(1).plot(hTrkHMXAtConv_b,"mode=overlay");
+            plotter_track_ext.region(2).plot(hTrkHMXAtConv_a,"mode=overlay");
+            plotter_track_ext.region(3).plot(hTrkHMYAtConv_t,"mode=overlay");
+            plotter_track_ext.region(4).plot(hTrkHMYAtConv_b,"mode=overlay");
+            plotter_track_ext.region(5).plot(hTrkHMYAtConv_a,"mode=overlay");
+
+            IPlotter plotter_track_ext_entr = af.createPlotterFactory().create();
+            plotter_track_ext_entr.createRegions(2,3,0);
+            plotter_track_ext_entr.setTitle("Track @ 0cm"); 
+            plotterFrame.addPlotter(plotter_track_ext_entr);
+            IHistogram hTrkXAtEntr_t = aida.histogram1D("Top track X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkYAtEntr_t = aida.histogram1D("Top track Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkXAtEntr_b = aida.histogram1D("Bottom track X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkYAtEntr_b = aida.histogram1D("Bottom track Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkXAtEntr_a = aida.histogram1D("Track X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkYAtEntr_a = aida.histogram1D("Track Y @ 0cm" , 50, -40, 40);
+            plotter_track_ext_entr.region(0).plot(hTrkXAtEntr_t);
+            plotter_track_ext_entr.region(1).plot(hTrkXAtEntr_b);
+            plotter_track_ext_entr.region(2).plot(hTrkXAtEntr_a);
+            plotter_track_ext_entr.region(3).plot(hTrkYAtEntr_t);
+            plotter_track_ext_entr.region(4).plot(hTrkYAtEntr_b);
+            plotter_track_ext_entr.region(5).plot(hTrkYAtEntr_a);
+
+
+            IHistogram hTrkHMXAtEntr_t = aida.histogram1D("Top track Pz>1GeV X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtEntr_t = aida.histogram1D("Top track Pz>1GeV Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkHMXAtEntr_b = aida.histogram1D("Bottom track Pz>1GeV X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtEntr_b = aida.histogram1D("Bottom track Pz>1GeV Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkHMXAtEntr_a = aida.histogram1D("Track Pz>1GeV X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtEntr_a = aida.histogram1D("Track Pz>1GeV Y @ 0cm" , 50, -40, 40);
+            plotter_track_ext_entr.region(0).plot(hTrkHMXAtEntr_t,"mode=overlay");
+            plotter_track_ext_entr.region(1).plot(hTrkHMXAtEntr_b,"mode=overlay");
+            plotter_track_ext_entr.region(2).plot(hTrkHMXAtEntr_a,"mode=overlay");
+            plotter_track_ext_entr.region(3).plot(hTrkHMYAtEntr_t,"mode=overlay");
+            plotter_track_ext_entr.region(4).plot(hTrkHMYAtEntr_b,"mode=overlay");
+            plotter_track_ext_entr.region(5).plot(hTrkHMYAtEntr_a,"mode=overlay");
+
+
+            IPlotter plotter_track_ext_coll = af.createPlotterFactory().create();
+            plotter_track_ext_coll.createRegions(2,3,0);
+            plotter_track_ext_coll.setTitle("Track @ -150cm"); 
+            plotterFrame.addPlotter(plotter_track_ext_coll);
+            IHistogram hTrkXAtColl_t = aida.histogram1D("Top track X @ -150cm" , 50, -100, 100);
+            IHistogram hTrkYAtColl_t = aida.histogram1D("Top track Y @ -150cm" , 50, -40, 40);
+            IHistogram hTrkXAtColl_b = aida.histogram1D("Bottom track X @ -150cm" , 50, -100, 100);
+            IHistogram hTrkYAtColl_b = aida.histogram1D("Bottom track Y @ -150cm" , 50, -40, 40);
+            IHistogram hTrkXAtColl_a = aida.histogram1D("Track X @ -150cm" , 50, -100, 100);
+            IHistogram hTrkYAtColl_a = aida.histogram1D("Track Y @ -150cm" , 50, -40, 40);
+            plotter_track_ext_coll.region(0).plot(hTrkXAtColl_t);
+            plotter_track_ext_coll.region(1).plot(hTrkXAtColl_b);
+            plotter_track_ext_coll.region(2).plot(hTrkXAtColl_a);
+            plotter_track_ext_coll.region(3).plot(hTrkYAtColl_t);
+            plotter_track_ext_coll.region(4).plot(hTrkYAtColl_b);
+            plotter_track_ext_coll.region(5).plot(hTrkYAtColl_a);
+
+
+            IHistogram hTrkHMXAtColl_t = aida.histogram1D("Top track Pz>1GeV X @ -150cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtColl_t = aida.histogram1D("Top track Pz>1GeV Y @ -150cm" , 50, -40, 40);
+            IHistogram hTrkHMXAtColl_b = aida.histogram1D("Bottom track Pz>1GeV X @ -150cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtColl_b = aida.histogram1D("Bottom track Pz>1GeV Y @ -150cm" , 50, -40, 40);
+            IHistogram hTrkHMXAtColl_a = aida.histogram1D("Track Pz>1GeV X @ -150cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtColl_a = aida.histogram1D("Track Pz>1GeV Y @ -150cm" , 50, -40, 40);
+            plotter_track_ext_coll.region(0).plot(hTrkHMXAtColl_t,"mode=overlay");
+            plotter_track_ext_coll.region(1).plot(hTrkHMXAtColl_b,"mode=overlay");
+            plotter_track_ext_coll.region(2).plot(hTrkHMXAtColl_a,"mode=overlay");
+            plotter_track_ext_coll.region(3).plot(hTrkHMYAtColl_t,"mode=overlay");
+            plotter_track_ext_coll.region(4).plot(hTrkHMYAtColl_b,"mode=overlay");
+            plotter_track_ext_coll.region(5).plot(hTrkHMYAtColl_a,"mode=overlay");
+
+
+
+
+
+            IPlotter plotter_track_ext2 = af.createPlotterFactory().create();
+            plotter_track_ext2.createRegions(2,3,0);
+            plotter_track_ext2.setTitle("Matched track @ Target ");
+            plotterFrame.addPlotter(plotter_track_ext2);
+            IHistogram hmTrkXAtConv_t = aida.histogram1D("Top matched track X @ -67cm" , 50, -100, 100);
+            IHistogram hmTrkYAtConv_t = aida.histogram1D("Top matched track Y @ -67cm" , 50, -20, 20);
+            IHistogram hmTrkXAtConv_b = aida.histogram1D("Bottom matched track X @ -67cm" , 50, -100, 100);
+            IHistogram hmTrkYAtConv_b = aida.histogram1D("Bottom matched track Y @ -67cm" , 50, -20, 20);
+            IHistogram hmTrkXAtConv_a = aida.histogram1D("Matched track X @ -67cm" , 50, -100, 100);
+            IHistogram hmTrkYAtConv_a = aida.histogram1D("Matched track Y @ -67cm" , 50, -20, 20);
+            plotter_track_ext2.region(0).plot(hmTrkXAtConv_t);
+            plotter_track_ext2.region(1).plot(hmTrkXAtConv_b);
+            plotter_track_ext2.region(2).plot(hmTrkXAtConv_a);
+            plotter_track_ext2.region(3).plot(hmTrkYAtConv_t);
+            plotter_track_ext2.region(4).plot(hmTrkYAtConv_b);
+            plotter_track_ext2.region(5).plot(hmTrkYAtConv_a);
+
+
+
+
+
+
+            IPlotter plotter_track_ext3 = af.createPlotterFactory().create();
+            plotter_track_ext3.createRegions(2,3,0);
+            plotter_track_ext3.setTitle("Matched sel track @ Target");
+            plotterFrame.addPlotter(plotter_track_ext3);
+            IHistogram hmsTrkXAtConv_t = aida.histogram1D("Top sel matched track X @ -67cm" , 50, -100, 100);
+            IHistogram hmsTrkYAtConv_t = aida.histogram1D("Top sel matched track Y @ -67cm" , 50, -100, 100);
+            IHistogram hmsTrkXAtConv_b = aida.histogram1D("Bottom sel matched track X @ -67cm" , 50, -100, 100);
+            IHistogram hmsTrkYAtConv_b = aida.histogram1D("Bottom sel matched track Y @ -67cm" , 50, -100, 100);
+            IHistogram hmsTrkXAtConv_a = aida.histogram1D("Matched sel track X @ -67cm" , 50, -100, 100);
+            IHistogram hmsTrkYAtConv_a = aida.histogram1D("Matched sel track Y @ -67cm" , 50, -100, 100);
+            plotter_track_ext3.region(0).plot(hmsTrkXAtConv_t);
+            plotter_track_ext3.region(1).plot(hmsTrkXAtConv_b);
+            plotter_track_ext3.region(2).plot(hmsTrkXAtConv_a);
+            plotter_track_ext3.region(3).plot(hmsTrkYAtConv_t);
+            plotter_track_ext3.region(4).plot(hmsTrkYAtConv_b);
+            plotter_track_ext3.region(5).plot(hmsTrkYAtConv_a);
+
+
+
+
+            IPlotter plotter_track_ext4 = af.createPlotterFactory().create();
+            plotter_track_ext4.createRegions(2,3,0);
+            plotter_track_ext4.setTitle("Track @ Target Pos. Charge");
+            plotterFrame.addPlotter(plotter_track_ext4);
+            IHistogram hTrkXAtConvqp_t = aida.histogram1D("Top track q>0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkYAtConvqp_t = aida.histogram1D("Top track q>0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkXAtConvqp_b = aida.histogram1D("Bottom track q>0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkYAtConvqp_b = aida.histogram1D("Bottom track q>0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkXAtConvqp_a = aida.histogram1D("Track q>0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkYAtConvqp_a = aida.histogram1D("Track q>0 Y @ -67cm" , 50, -20, 20);
+            plotter_track_ext4.region(0).plot(hTrkXAtConvqp_t);
+            plotter_track_ext4.region(1).plot(hTrkXAtConvqp_b);
+            plotter_track_ext4.region(2).plot(hTrkXAtConvqp_a);
+            plotter_track_ext4.region(3).plot(hTrkYAtConvqp_t);
+            plotter_track_ext4.region(4).plot(hTrkYAtConvqp_b);
+            plotter_track_ext4.region(5).plot(hTrkYAtConvqp_a);
+
+
+            IHistogram hTrkHMXAtConvqp_t = aida.histogram1D("Top track Pz>1GeV q>0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtConvqp_t = aida.histogram1D("Top track Pz>1GeV q>0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkHMXAtConvqp_b = aida.histogram1D("Bottom track Pz>1GeV q>0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtConvqp_b = aida.histogram1D("Bottom track Pz>1GeV q>0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkHMXAtConvqp_a = aida.histogram1D("Track Pz>1GeV q>0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtConvqp_a = aida.histogram1D("Track Pz>1GeV q>0 Y @ -67cm" , 50, -20, 20);
+            plotter_track_ext4.region(0).plot(hTrkHMXAtConvqp_t,"mode=overlay");
+            plotter_track_ext4.region(1).plot(hTrkHMXAtConvqp_b,"mode=overlay");
+            plotter_track_ext4.region(2).plot(hTrkHMXAtConvqp_a,"mode=overlay");
+            plotter_track_ext4.region(3).plot(hTrkHMYAtConvqp_t,"mode=overlay");
+            plotter_track_ext4.region(4).plot(hTrkHMYAtConvqp_b,"mode=overlay");
+            plotter_track_ext4.region(5).plot(hTrkHMYAtConvqp_a,"mode=overlay");
+
+
+
+            IPlotter plotter_track_ext4_entr = af.createPlotterFactory().create();
+            plotter_track_ext4_entr.createRegions(2,3,0);
+            plotter_track_ext4_entr.setTitle("Track @ 0cm Pos. Charge");
+            plotterFrame.addPlotter(plotter_track_ext4_entr);
+            IHistogram hTrkXAtEntrqp_t = aida.histogram1D("Top track q>0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkYAtEntrqp_t = aida.histogram1D("Top track q>0 Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkXAtEntrqp_b = aida.histogram1D("Bottom track q>0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkYAtEntrqp_b = aida.histogram1D("Bottom track q>0 Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkXAtEntrqp_a = aida.histogram1D("Track q>0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkYAtEntrqp_a = aida.histogram1D("Track q>0 Y @ 0cm" , 50, -40, 40);
+            plotter_track_ext4_entr.region(0).plot(hTrkXAtEntrqp_t);
+            plotter_track_ext4_entr.region(1).plot(hTrkXAtEntrqp_b);
+            plotter_track_ext4_entr.region(2).plot(hTrkXAtEntrqp_a);
+            plotter_track_ext4_entr.region(3).plot(hTrkYAtEntrqp_t);
+            plotter_track_ext4_entr.region(4).plot(hTrkYAtEntrqp_b);
+            plotter_track_ext4_entr.region(5).plot(hTrkYAtEntrqp_a);
+
+
+            IHistogram hTrkHMXAtEntrqp_t = aida.histogram1D("Top track Pz>1GeV q>0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtEntrqp_t = aida.histogram1D("Top track Pz>1GeV q>0 Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkHMXAtEntrqp_b = aida.histogram1D("Bottom track Pz>1GeV q>0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtEntrqp_b = aida.histogram1D("Bottom track Pz>1GeV q>0 Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkHMXAtEntrqp_a = aida.histogram1D("Track Pz>1GeV q>0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtEntrqp_a = aida.histogram1D("Track Pz>1GeV q>0 Y @ 0cm" , 50, -40, 40);
+            plotter_track_ext4_entr.region(0).plot(hTrkHMXAtEntrqp_t,"mode=overlay");
+            plotter_track_ext4_entr.region(1).plot(hTrkHMXAtEntrqp_b,"mode=overlay");
+            plotter_track_ext4_entr.region(2).plot(hTrkHMXAtEntrqp_a,"mode=overlay");
+            plotter_track_ext4_entr.region(3).plot(hTrkHMYAtEntrqp_t,"mode=overlay");
+            plotter_track_ext4_entr.region(4).plot(hTrkHMYAtEntrqp_b,"mode=overlay");
+            plotter_track_ext4_entr.region(5).plot(hTrkHMYAtEntrqp_a,"mode=overlay"); 
+
+
+
+            IPlotter plotter_track_ext5 = af.createPlotterFactory().create();
+            plotter_track_ext5.createRegions(2,3,0);
+            plotter_track_ext5.setTitle("Track @ Target Neg. Charge");
+            plotterFrame.addPlotter(plotter_track_ext5);
+            IHistogram hTrkXAtConvqm_t = aida.histogram1D("Top track q<0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkYAtConvqm_t = aida.histogram1D("Top track q<0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkXAtConvqm_b = aida.histogram1D("Bottom track q<0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkYAtConvqm_b = aida.histogram1D("Bottom track q<0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkXAtConvqm_a = aida.histogram1D("Track q<0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkYAtConvqm_a = aida.histogram1D("Track q<0 Y @ -67cm" , 50, -20, 20);
+            plotter_track_ext5.region(0).plot(hTrkXAtConvqm_t);
+            plotter_track_ext5.region(1).plot(hTrkXAtConvqm_b);
+            plotter_track_ext5.region(2).plot(hTrkXAtConvqm_a);
+            plotter_track_ext5.region(3).plot(hTrkYAtConvqm_t);
+            plotter_track_ext5.region(4).plot(hTrkYAtConvqm_b);
+            plotter_track_ext5.region(5).plot(hTrkYAtConvqm_a);
+
+            IHistogram hTrkHMXAtConvqm_t = aida.histogram1D("Top track Pz>1GeV q<0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtConvqm_t = aida.histogram1D("Top track Pz>1GeV q<0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkHMXAtConvqm_b = aida.histogram1D("Bottom track Pz>1GeV q<0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtConvqm_b = aida.histogram1D("Bottom track Pz>1GeV q<0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hTrkHMXAtConvqm_a = aida.histogram1D("Track Pz>1GeV q<0 X @ -67cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtConvqm_a = aida.histogram1D("Track Pz>1GeV q<0 Y @ -67cm" , 50, -20, 20);
+            plotter_track_ext5.region(0).plot(hTrkHMXAtConvqm_t,"mode=overlay");
+            plotter_track_ext5.region(1).plot(hTrkHMXAtConvqm_b,"mode=overlay");
+            plotter_track_ext5.region(2).plot(hTrkHMXAtConvqm_a,"mode=overlay");
+            plotter_track_ext5.region(3).plot(hTrkHMYAtConvqm_t,"mode=overlay");
+            plotter_track_ext5.region(4).plot(hTrkHMYAtConvqm_b,"mode=overlay");
+            plotter_track_ext5.region(5).plot(hTrkHMYAtConvqm_a,"mode=overlay");
+
+
+            IPlotter plotter_track_ext5_entr = af.createPlotterFactory().create();
+            plotter_track_ext5_entr.createRegions(2,3,0);
+            plotter_track_ext5_entr.setTitle("Track @ 0cm Neg. Charge");
+            plotterFrame.addPlotter(plotter_track_ext5_entr);
+            IHistogram hTrkXAtEntrqm_t = aida.histogram1D("Top track q<0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkYAtEntrqm_t = aida.histogram1D("Top track q<0 Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkXAtEntrqm_b = aida.histogram1D("Bottom track q<0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkYAtEntrqm_b = aida.histogram1D("Bottom track q<0 Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkXAtEntrqm_a = aida.histogram1D("Track q<0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkYAtEntrqm_a = aida.histogram1D("Track q<0 Y @ 0cm" , 50, -40, 40);
+            plotter_track_ext5_entr.region(0).plot(hTrkXAtEntrqm_t);
+            plotter_track_ext5_entr.region(1).plot(hTrkXAtEntrqm_b);
+            plotter_track_ext5_entr.region(2).plot(hTrkXAtEntrqm_a);
+            plotter_track_ext5_entr.region(3).plot(hTrkYAtEntrqm_t);
+            plotter_track_ext5_entr.region(4).plot(hTrkYAtEntrqm_b);
+            plotter_track_ext5_entr.region(5).plot(hTrkYAtEntrqm_a);
+
+
+
+
+            IHistogram hTrkHMXAtEntrqm_t = aida.histogram1D("Top track Pz>1GeV q<0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtEntrqm_t = aida.histogram1D("Top track Pz>1GeV q<0 Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkHMXAtEntrqm_b = aida.histogram1D("Bottom track Pz>1GeV q<0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtEntrqm_b = aida.histogram1D("Bottom track Pz>1GeV q<0 Y @ 0cm" , 50, -40, 40);
+            IHistogram hTrkHMXAtEntrqm_a = aida.histogram1D("Track Pz>1GeV q<0 X @ 0cm" , 50, -100, 100);
+            IHistogram hTrkHMYAtEntrqm_a = aida.histogram1D("Track Pz>1GeV q<0 Y @ 0cm" , 50, -40, 40);
+            plotter_track_ext5_entr.region(0).plot(hTrkHMXAtEntrqm_t,"mode=overlay");
+            plotter_track_ext5_entr.region(1).plot(hTrkHMXAtEntrqm_b,"mode=overlay");
+            plotter_track_ext5_entr.region(2).plot(hTrkHMXAtEntrqm_a,"mode=overlay");
+            plotter_track_ext5_entr.region(3).plot(hTrkHMYAtEntrqm_t,"mode=overlay");
+            plotter_track_ext5_entr.region(4).plot(hTrkHMYAtEntrqm_b,"mode=overlay");
+            plotter_track_ext5_entr.region(5).plot(hTrkHMYAtEntrqm_a,"mode=overlay");
+
+
+
+
+
+
+            IPlotter plotter_track_ext6 = af.createPlotterFactory().create();
+            plotter_track_ext6.createRegions(2,3,0);
+            plotter_track_ext6.setTitle("Matched Track @ Target Pos. Charge");
+            plotterFrame.addPlotter(plotter_track_ext6);
+            IHistogram hmTrkXAtConvqp_t = aida.histogram1D("Top matched track q>0 X @ -67cm" , 50, -100, 100);
+            IHistogram hmTrkYAtConvqp_t = aida.histogram1D("Top matched track q>0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hmTrkXAtConvqp_b = aida.histogram1D("Bottom matched track q>0 X @ -67cm" , 50, -100, 100);
+            IHistogram hmTrkYAtConvqp_b = aida.histogram1D("Bottom matched track q>0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hmTrkXAtConvqp_a = aida.histogram1D("Matched track q>0 X @ -67cm" , 50, -100, 100);
+            IHistogram hmTrkYAtConvqp_a = aida.histogram1D("Matched track q>0 Y @ -67cm" , 50, -20, 20);
+            plotter_track_ext6.region(0).plot(hmTrkXAtConvqp_t);
+            plotter_track_ext6.region(1).plot(hmTrkXAtConvqp_b);
+            plotter_track_ext6.region(2).plot(hmTrkXAtConvqp_a);
+            plotter_track_ext6.region(3).plot(hmTrkYAtConvqp_t);
+            plotter_track_ext6.region(4).plot(hmTrkYAtConvqp_b);
+            plotter_track_ext6.region(5).plot(hmTrkYAtConvqp_a);
+
+            IPlotter plotter_track_ext7 = af.createPlotterFactory().create();
+            plotter_track_ext7.createRegions(2,3,0);
+            plotter_track_ext7.setTitle("Matched Track @ Target Neg. Charge");
+            plotterFrame.addPlotter(plotter_track_ext7);
+            IHistogram hmTrkXAtConvqm_t = aida.histogram1D("Top matched track q<0 X @ -67cm" , 50, -100, 100);
+            IHistogram hmTrkYAtConvqm_t = aida.histogram1D("Top matched track q<0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hmTrkXAtConvqm_b = aida.histogram1D("Bottom matched track q<0 X @ -67cm" , 50, -100, 100);
+            IHistogram hmTrkYAtConvqm_b = aida.histogram1D("Bottom matched track q<0 Y @ -67cm" , 50, -20, 20);
+            IHistogram hmTrkXAtConvqm_a = aida.histogram1D("Matched track q<0 X @ -67cm" , 50, -100, 100);
+            IHistogram hmTrkYAtConvqm_a = aida.histogram1D("Matched track q<0 Y @ -67cm" , 50, -20, 20);
+            plotter_track_ext7.region(0).plot(hmTrkXAtConvqm_t);
+            plotter_track_ext7.region(1).plot(hmTrkXAtConvqm_b);
+            plotter_track_ext7.region(2).plot(hmTrkXAtConvqm_a);
+            plotter_track_ext7.region(3).plot(hmTrkYAtConvqm_t);
+            plotter_track_ext7.region(4).plot(hmTrkYAtConvqm_b);
+            plotter_track_ext7.region(5).plot(hmTrkYAtConvqm_a);
+
+
+
+
+
+            IPlotter plotter_track_chi2 = af.createPlotterFactory().create();
+            plotter_track_chi2.createRegions(3,3,0);
+            plotter_track_chi2.setTitle("Track Chi2");
+            plotterFrame.addPlotter(plotter_track_chi2);
+            IHistogram hChi2_t = aida.histogram1D("Top track Chi2" , 50, 0, 15);
+            IHistogram hChi2_b = aida.histogram1D("Bottom track Chi2" , 50, 0, 15);
+            IHistogram hChi2_a = aida.histogram1D("Track Chi2" , 50, 0, 15);
+            IHistogram hmChi2_t = aida.histogram1D("Matched top track Chi2" , 50, 0, 15);
+            IHistogram hmChi2_b = aida.histogram1D("Matched bottom track Chi2" , 50, 0, 15);
+            IHistogram hmChi2_a = aida.histogram1D("Matched track Chi2" , 50, 0, 15);
+            IHistogram hmsChi2_t = aida.histogram1D("Matched sel top track Chi2" , 50, 0, 15);
+            IHistogram hmsChi2_b = aida.histogram1D("Matched sel bottom track Chi2" , 50, 0, 15);
+            IHistogram hmsChi2_a = aida.histogram1D("Matched sel track Chi2" , 50, 0, 15);
+
+            plotter_track_chi2.region(0).plot(hChi2_t);
+            plotter_track_chi2.region(1).plot(hChi2_b);
+            plotter_track_chi2.region(2).plot(hChi2_a);    
+            plotter_track_chi2.region(3).plot(hmChi2_t);
+            plotter_track_chi2.region(4).plot(hmChi2_b);
+            plotter_track_chi2.region(5).plot(hmChi2_a);    
+            plotter_track_chi2.region(6).plot(hmsChi2_t);
+            plotter_track_chi2.region(7).plot(hmsChi2_b);
+            plotter_track_chi2.region(8).plot(hmsChi2_a);    
+
+
+
+            IPlotter plotter_track_chi2_2 = af.createPlotterFactory().create();
+            plotter_track_chi2_2.createRegions(3,3,0);
+            plotter_track_chi2_2.setTitle("Track Chi2 Target Outliers X");
+            plotterFrame.addPlotter(plotter_track_chi2_2);
+            IHistogram hChi2TX_t = aida.histogram1D("Top track !target in X Chi2" , 50, 0, 15);
+            IHistogram hChi2TX_b = aida.histogram1D("Bottom track !target in X Chi2" , 50, 0, 15);
+            IHistogram hChi2TX_a = aida.histogram1D("Track !target in X Chi2" , 50, 0, 15);
+            IHistogram hmChi2TX_t = aida.histogram1D("Matched top track !target in X Chi2" , 50, 0, 15);
+            IHistogram hmChi2TX_b = aida.histogram1D("Matched bottom track !target in X Chi2" , 50, 0, 15);
+            IHistogram hmChi2TX_a = aida.histogram1D("Matched track !target in X Chi2" , 50, 0, 15);
+            IHistogram hmsChi2TX_t = aida.histogram1D("Matched sel top track !target in X Chi2" , 50, 0, 15);
+            IHistogram hmsChi2TX_b = aida.histogram1D("Matched sel bottom track !target in X Chi2" , 50, 0, 15);
+            IHistogram hmsChi2TX_a = aida.histogram1D("Matched sel track !target in X Chi2" , 50, 0, 15);
+
+            plotter_track_chi2_2.region(0).plot(hChi2TX_t);
+            plotter_track_chi2_2.region(1).plot(hChi2TX_b);
+            plotter_track_chi2_2.region(2).plot(hChi2TX_a);    
+            plotter_track_chi2_2.region(3).plot(hmChi2TX_t);
+            plotter_track_chi2_2.region(4).plot(hmChi2TX_b);
+            plotter_track_chi2_2.region(5).plot(hmChi2TX_a);    
+            plotter_track_chi2_2.region(6).plot(hmsChi2TX_t);
+            plotter_track_chi2_2.region(7).plot(hmsChi2TX_b);
+            plotter_track_chi2_2.region(8).plot(hmsChi2TX_a);    
+
+
+
+            
+            
+            IHistogram hmcls_t = aida.histogram1D("Cluster size matched top", 6, 0.0, 6.0);
+            IHistogram hmcls_b = aida.histogram1D("Cluster size matched bottom", 6, 0.0, 6.0);
+            IHistogram hmcls_a = aida.histogram1D("Cluster size matched", 6, 0.0, 6.0);
+            IHistogram hmscls_t = aida.histogram1D("Cluster size matched sel top", 6, 0.0, 6.0);
+            IHistogram hmscls_b = aida.histogram1D("Cluster size matched sel bottom", 6, 0.0, 6.0);
+            IHistogram hmscls_a = aida.histogram1D("Cluster size matched sel", 6, 0.0, 6.0);
+        
+        
+            
+            
+            
+
+            IPlotter plotter_ecal_clsxm = af.createPlotterFactory().create();
+            plotter_ecal_clsxm.createRegions(2,3,0);
+            plotter_ecal_clsxm.setTitle("Ecal Cluster size matched");
+            plotterFrame.addPlotter(plotter_ecal_clsxm);
+
+            plotter_ecal_clsxm.region(0).plot(hmcls_t);
+            plotter_ecal_clsxm.region(1).plot(hmcls_b);
+            plotter_ecal_clsxm.region(2).plot(hmcls_a);
+            plotter_ecal_clsxm.region(3).plot(hmscls_t);
+            plotter_ecal_clsxm.region(4).plot(hmscls_b);
+            plotter_ecal_clsxm.region(5).plot(hmscls_a);
+            
+
+
+
+
+            IHistogram hmHMcls_t = aida.histogram1D("Cluster size matched trk Pz>600MeV top", 6, 0.0, 6.0);
+            IHistogram hmHMcls_b = aida.histogram1D("Cluster size matched trk Pz>600MeV bottom", 6, 0.0, 6.0);
+            IHistogram hmHMcls_a = aida.histogram1D("Cluster size matched trk Pz>600MeV", 6, 0.0, 6.0);
+            IHistogram hmHM2cls_t = aida.histogram1D("Cluster size matched trk Pz>1000MeV top", 6, 0.0, 6.0);
+            IHistogram hmHM2cls_b = aida.histogram1D("Cluster size matched trk Pz>1000MeV bottom", 6, 0.0, 6.0);
+            IHistogram hmHM2cls_a = aida.histogram1D("Cluster size matched trk Pz>1000MeV", 6, 0.0, 6.0);
+
+
+
+
+            IPlotter plotter_ecal_clsxm2 = af.createPlotterFactory().create();
+            plotter_ecal_clsxm2.createRegions(2,3,0);
+            plotter_ecal_clsxm2.setTitle("Ecal Cluster size matched Trk Pz");
+            plotterFrame.addPlotter(plotter_ecal_clsxm2);
+
+            plotter_ecal_clsxm2.region(0).plot(hmHMcls_t);
+            plotter_ecal_clsxm2.region(1).plot(hmHMcls_b);
+            plotter_ecal_clsxm2.region(2).plot(hmHMcls_a);
+            plotter_ecal_clsxm2.region(3).plot(hmHM2cls_t);
+            plotter_ecal_clsxm2.region(4).plot(hmHM2cls_b);
+            plotter_ecal_clsxm2.region(5).plot(hmHM2cls_a);
+
+
+
+
+
+            IHistogram hnclmatch_a = aida.histogram1D("Nr of track matched clusters dR<20.0",3,-0.5,2.5);
+            IHistogram hnclmatch_t = aida.histogram1D("Nr of track matched top clusters dR<20.0" ,3,-0.5,2.5);
+            IHistogram hnclmatch_b = aida.histogram1D("Nr of track matched bottom clusters dR<20.0" ,3,-0.5,2.5);
+            IHistogram hnsclmatch_a = aida.histogram1D("Nr of sel track matched clusters dR<20.0",3,-0.5,2.5);
+            IHistogram hnsclmatch_t = aida.histogram1D("Nr of sel track matched top clusters dR<20.0" ,3,-0.5,2.5);
+            IHistogram hnsclmatch_b = aida.histogram1D("Nr of sel track matched bottom clusters dR<20.0" ,3,-0.5,2.5);
+
+
+
+            IPlotter plotter_nclmatch = af.createPlotterFactory().create();
+            plotter_nclmatch.createRegions(2,3,0);
+            plotter_nclmatch.setTitle("Ecal track match # dR<20.0");
+            plotterFrame.addPlotter(plotter_nclmatch);
+            plotter_nclmatch.region(0).plot(hnclmatch_t);
+            plotter_nclmatch.region(1).plot(hnclmatch_b);
+            plotter_nclmatch.region(2).plot(hnclmatch_a);
+            plotter_nclmatch.region(3).plot(hnsclmatch_t);
+            plotter_nclmatch.region(4).plot(hnsclmatch_b);
+            plotter_nclmatch.region(5).plot(hnsclmatch_a);
+
+
+
+            IHistogram hnclmatchY_a = aida.histogram1D("Nr of track matched clusters dY<20.0",3,-0.5,2.5);
+            IHistogram hnclmatchY_t = aida.histogram1D("Nr of track matched top clusters dY<20.0" ,3,-0.5,2.5);
+            IHistogram hnclmatchY_b = aida.histogram1D("Nr of track matched bottom clusters dY<20.0" ,3,-0.5,2.5);
+            IHistogram hnsclmatchY_a = aida.histogram1D("Nr of sel track matched clusters dY<20.0",3,-0.5,2.5);
+            IHistogram hnsclmatchY_t = aida.histogram1D("Nr of sel track matched top clusters dY<20.0" ,3,-0.5,2.5);
+            IHistogram hnsclmatchY_b = aida.histogram1D("Nr of sel track matched bottom clusters dY<20.0" ,3,-0.5,2.5);
+
+            IPlotter plotter_nclmatchY = af.createPlotterFactory().create();
+            plotter_nclmatchY.createRegions(2,3,0);
+            plotter_nclmatchY.setTitle("Ecal track match # dY<20.0");
+            plotterFrame.addPlotter(plotter_nclmatchY);
+            plotter_nclmatchY.region(0).plot(hnclmatchY_t);
+            plotter_nclmatchY.region(1).plot(hnclmatchY_b);
+            plotter_nclmatchY.region(2).plot(hnclmatchY_a);
+            plotter_nclmatchY.region(3).plot(hnsclmatchY_t);
+            plotter_nclmatchY.region(4).plot(hnsclmatchY_b);
+            plotter_nclmatchY.region(5).plot(hnsclmatchY_a);
+
+
+
+            IPlotter plotter_clmatchpos = af.createPlotterFactory().create();
+            plotter_clmatchpos.createRegions(2,3,0);
+            plotter_clmatchpos.setTitle("Cluster track match pos");
+            plotter_clmatchpos.style().statisticsBoxStyle().setVisible(false);
+            plotterFrame.addPlotter(plotter_clmatchpos);
+
+            IHistogram hclmatchpos_a = aida.histogram2D("Track matched cluster pos",51,-25.5,25.5,11,-5.5,5.5);
+            IHistogram hclmatchpos_t = aida.histogram2D("Track matched top cluster pos",51,-25.5,25.5,6,-0.5,5.5);
+            IHistogram hclmatchpos_b = aida.histogram2D("Track matched bottom cluster pos",51,-25.5,25.5,6,-5.5,0.5);
+            IHistogram hsclmatchpos_a = aida.histogram2D("Track matched sel cluster pos",51,-25.5,25.5,11,-5.5,5.5);
+            IHistogram hsclmatchpos_t = aida.histogram2D("Track matched sel top cluster pos",51,-25.5,25.5,6,-0.5,5.5);
+            IHistogram hsclmatchpos_b = aida.histogram2D("Track matched sel bottom cluster pos",51,-25.5,25.5,6,-5.5,0.5);
+
+
+
+            plotter_clmatchpos.region(0).plot(hclmatchpos_t);
+            plotter_clmatchpos.region(1).plot(hclmatchpos_b);
+            plotter_clmatchpos.region(2).plot(hclmatchpos_a);
+            plotter_clmatchpos.region(3).plot(hsclmatchpos_t);
+            plotter_clmatchpos.region(4).plot(hsclmatchpos_b);
+            plotter_clmatchpos.region(5).plot(hsclmatchpos_a);
+
+            for(int i=0;i<6;++i) {
+                plotter_clmatchpos.region(i).style().setParameter("hist2DStyle", "colorMap");
+                plotter_clmatchpos.region(i).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+                ((PlotterRegion) plotter_clmatchpos.region(i)).getPlot().setAllowUserInteraction(true);
+                ((PlotterRegion) plotter_clmatchpos.region(i)).getPlot().setAllowPopupMenus(true);
+            }
+
+            IPlotter plotter_clunmatchpos = af.createPlotterFactory().create();
+            plotter_clunmatchpos.createRegions(2,3,0);
+            plotter_clunmatchpos.setTitle("Cluster track unmatched pos");
+            plotterFrame.addPlotter(plotter_clunmatchpos);
+
+            IHistogram hsclunmatchpos_a = aida.histogram2D("Track unmatched sel cluster pos",50,-500,500,50,-100,100);
+            IHistogram hsclunmatchpos_t = aida.histogram2D("Track unmatched sel top cluster pos",50,-500,500,50,-100,100);
+            IHistogram hsclunmatchpos_b = aida.histogram2D("Track unmatched sel bottom cluster pos",50,-500,500,50,-100,100);
+            plotter_clunmatchpos.region(0).plot(hsclunmatchpos_t);
+            plotter_clunmatchpos.region(1).plot(hsclunmatchpos_b);
+            plotter_clunmatchpos.region(2).plot(hsclunmatchpos_a);
+
+
+
+
+
+
+
+
+
+        
+        
+        
+        
+        
+        
+        
+        IPlotter plotter_cln = af.createPlotterFactory().create();
+        plotter_cln.createRegions(2,3,0);
+        plotter_cln.setTitle("Cluster multiplicity");
+        plotterFrame.addPlotter(plotter_cln);
+        
+        IHistogram hsCln_a = aida.histogram1D("Cluster sel multiplicity",5,0,5);
+        IHistogram hsCln_t = aida.histogram1D("Top cluster sel multiplicity",5,0,5);
+        IHistogram hsCln_b = aida.histogram1D("Bottom cluster sel multiplicity",5,0,5);
+        IHistogram hCln_a = aida.histogram1D("Cluster multiplicity",5,0,5);
+        IHistogram hCln_t = aida.histogram1D("Top cluster multiplicity",5,0,5);
+        IHistogram hCln_b = aida.histogram1D("Bottom cluster multiplicity",5,0,5);
+        
+        plotter_cln.region(2).plot(hCln_a);
+        plotter_cln.region(0).plot(hCln_t);//,"mode=overlay");
+        plotter_cln.region(1).plot(hCln_b);//,"mode=overlay");
+        
+        plotter_cln.region(5).plot(hsCln_a);
+        plotter_cln.region(3).plot(hsCln_t);//,"mode=overlay");
+        plotter_cln.region(4).plot(hsCln_b);//,"mode=overlay");
+        
+        
+        
+        
+        
+      
+        
+        
+        
+        
+        IPlotter plotter_ecal_clsx = af.createPlotterFactory().create();
+        plotter_ecal_clsx.createRegions(2,3,0);
+        plotter_ecal_clsx.setTitle("Ecal Cluster size");
+        plotterFrame.addPlotter(plotter_ecal_clsx);
+        
+        
+         
+        IHistogram hcls_t = aida.histogram1D("Cluster size top", 6, 0.0, 6.0);
+        IHistogram hcls_b = aida.histogram1D("Cluster size bottom", 6, 0.0, 6.0);
+        IHistogram hcls_a = aida.histogram1D("Cluster size", 6, 0.0, 6.0);
+        IHistogram hscls_t = aida.histogram1D("Cluster size sel top", 6, 0.0, 6.0);
+        IHistogram hscls_b = aida.histogram1D("Cluster size sel bottom", 6, 0.0, 6.0);
+        IHistogram hscls_a = aida.histogram1D("Cluster size sel", 6, 0.0, 6.0);
+        
+        plotter_ecal_clsx.region(0).plot(hcls_t);
+        plotter_ecal_clsx.region(1).plot(hcls_b);
+        plotter_ecal_clsx.region(2).plot(hcls_a);
+        plotter_ecal_clsx.region(3).plot(hcls_t);
+        plotter_ecal_clsx.region(4).plot(hcls_b);
+        plotter_ecal_clsx.region(5).plot(hcls_a);
+        
+        
+        
+        
+        
+        
+        
+      
+        
+        
+        IHistogram hth = aida.histogram1D("Cluster theta", 100, 0.02, 0.07);
+        IHistogram hth_t = aida.histogram1D("Top cluster theta", 100, 0.02, 0.07);
+        IHistogram hth_b = aida.histogram1D("Bottom cluster theta", 100, 0.02, 0.07);
+        IHistogram hth_ecl = aida.histogram1D("Cluster theta sel", 100, 0.02, 0.07);
+        IHistogram hth_ecl_t = aida.histogram1D("Top cluster theta sel", 100, 0.02, 0.07);
+        IHistogram hth_ecl_b = aida.histogram1D("Bottom cluster theta sel", 100, 0.02, 0.07);
+        IHistogram hth_m = aida.histogram1D("Cluster theta matched trk", 100, 0.02, 0.07);
+        IHistogram hth_m_t = aida.histogram1D("Top cluster theta matched trk", 100, 0.02, 0.07);
+        IHistogram hth_m_b = aida.histogram1D("Bottom cluster theta matched trk", 100, 0.02, 0.07);
+        IHistogram hth_eclm = aida.histogram1D("Cluster sel theta matched trk", 100, 0.02, 0.07);
+        IHistogram hth_eclm_t = aida.histogram1D("Top cluster sel theta matched trk", 100, 0.02, 0.07);
+        IHistogram hth_eclm_b = aida.histogram1D("Bottom cluster sel theta matched trk", 100, 0.02, 0.07);
+        IHistogram hth_mp = aida.histogram1D("Cluster theta matched trk Pz>1000MeV", 100, 0.02, 0.07);
+        IHistogram hth_mp_t = aida.histogram1D("Top cluster theta matched trk Pz>1000MeV", 100, 0.02, 0.07);
+        IHistogram hth_mp_b = aida.histogram1D("Bottom cluster theta matched trk Pz>1000MeV", 100, 0.02, 0.07);
+        
+        
+        IPlotter plotter_ecal_cltheta = af.createPlotterFactory().create();
+        plotter_ecal_cltheta.createRegions(5,3,0);
+        plotter_ecal_cltheta.setTitle("Ecal cl theta");
+        plotterFrame.addPlotter(plotter_ecal_cltheta);
+        
+        plotter_ecal_cltheta.region(0).plot(hth);
+        plotter_ecal_cltheta.region(1).plot(hth_t);
+        plotter_ecal_cltheta.region(2).plot(hth_b);
+        plotter_ecal_cltheta.region(3).plot(hth_ecl);
+        plotter_ecal_cltheta.region(4).plot(hth_ecl_t);
+        plotter_ecal_cltheta.region(5).plot(hth_ecl_b);
+        plotter_ecal_cltheta.region(6).plot(hth_m);
+        plotter_ecal_cltheta.region(7).plot(hth_m_t);
+        plotter_ecal_cltheta.region(8).plot(hth_m_b);
+        plotter_ecal_cltheta.region(9).plot(hth_eclm);
+        plotter_ecal_cltheta.region(10).plot(hth_eclm_t);
+        plotter_ecal_cltheta.region(11).plot(hth_eclm_b);
+        plotter_ecal_cltheta.region(12).plot(hth_mp);
+        plotter_ecal_cltheta.region(13).plot(hth_mp_t);
+        plotter_ecal_cltheta.region(14).plot(hth_mp_b);
+
+
+        
+        IHistogram hEoverPX_t = aida.histogram2D("EoverP vs cl X top",51,-25.5,25.5,50,0,2);
+        IHistogram hEoverPX_b = aida.histogram2D("EoverP vs cl X bottom",51,-25.5,25.5,50,0,2);
+        
+        IHistogram hsEoverPX_t = aida.histogram2D("EoverP vs cl X sel top",51,-25.5,25.5,50,0,2);
+        IHistogram hsEoverPX_b = aida.histogram2D("EoverP vs cl X sel bottom",51,-25.5,25.5,50,0,2);
+
+        IHistogram htsEoverPX_t = aida.histogram2D("EoverP vs cl X Pz>1GeV top",51,-25.5,25.5,50,0,2);
+        IHistogram htsEoverPX_b = aida.histogram2D("EoverP vs cl X Pz>1GeV bottom",51,-25.5,25.5,50,0,2);
+
+        
+        IPlotter plotter_ep_x = af.createPlotterFactory().create();
+        plotter_ep_x.createRegions(3,2,0);
+        plotter_ep_x.setTitle("E over P vs X ");
+        plotter_ep_x.style().statisticsBoxStyle().setVisible(false);
+        plotterFrame.addPlotter(plotter_ep_x);
+
+        plotter_ep_x.region(0).plot(hEoverPX_t);
+        plotter_ep_x.region(1).plot(hEoverPX_b);
+        plotter_ep_x.region(2).plot(hsEoverPX_t);
+        plotter_ep_x.region(3).plot(hsEoverPX_b);
+        plotter_ep_x.region(4).plot(htsEoverPX_t);
+        plotter_ep_x.region(5).plot(htsEoverPX_b);
+        
+        for(int i=0;i<6;++i) {
+            plotter_ep_x.region(i).style().setParameter("hist2DStyle", "colorMap");
+            plotter_ep_x.region(i).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        }
+        
+        
+        
+
+        IHistogram hnEoverP_t = aida.histogram1D("EoverP cl X<0 Pz>0.6GeV top",50,0,2);
+        IHistogram hnEoverP_b = aida.histogram1D("EoverP cl X<0 Pz>0.6GeV bottom",50,0,2);
+        IHistogram hnEoverPX_t = aida.histogram2D("EoverP vs cl X Pz>0.6GeV top",51,-25.5,25.5,50,0,2);
+        IHistogram hnEoverPX_b = aida.histogram2D("EoverP vs cl X Pz>0.6GeV bottom",51,-25.5,25.5,50,0,2);
+
+        
+        IPlotter plotter_ep_x2 = af.createPlotterFactory().create();
+        plotter_ep_x2.createRegions(2,2,0);
+        plotter_ep_x2.setTitle("E over P other");
+        plotter_ep_x2.style().statisticsBoxStyle().setVisible(false);
+        plotterFrame.addPlotter(plotter_ep_x2);
+
+        plotter_ep_x2.region(0).plot(hnEoverP_t);
+        plotter_ep_x2.region(1).plot(hnEoverP_b);
+        plotter_ep_x2.region(2).plot(hnEoverPX_t);
+        plotter_ep_x2.region(3).plot(hnEoverPX_b);
+        
+        for(int i=2;i<4;++i) {
+            plotter_ep_x2.region(i).style().setParameter("hist2DStyle", "colorMap");
+            plotter_ep_x2.region(i).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        }
+        
+        
+        
+        IHistogram hnEoverP2_t = aida.histogram1D("EoverP cl X<0 Pz>0.6GeV Y>1 top",50,0,2);
+        IHistogram hnEoverP2_b = aida.histogram1D("EoverP cl X<0 Pz>0.6GeV Y<-1 bottom",50,0,2);
+        IHistogram hnEoverPX2_t = aida.histogram2D("EoverP cl X<0 vs cl X Pz>0.6GeV Y>1 top",26,-25.5,0.5,50,0,2);
+        IHistogram hnEoverPX2_b = aida.histogram2D("EoverP cl X<0 vs cl X Pz>0.6GeV Y<-1 bottom",26,-25.5,0.5,50,0,2);
+
+        
+        IPlotter plotter_ep_xn = af.createPlotterFactory().create();
+        plotter_ep_xn.createRegions(2,2,0);
+        plotter_ep_xn.setTitle("E over P other 2");
+        plotter_ep_xn.style().statisticsBoxStyle().setVisible(false);
+        plotterFrame.addPlotter(plotter_ep_xn);
+
+        plotter_ep_xn.region(0).plot(hnEoverP2_t);
+        plotter_ep_xn.region(1).plot(hnEoverP2_b);
+        plotter_ep_xn.region(2).plot(hnEoverPX2_t);
+        plotter_ep_xn.region(3).plot(hnEoverPX2_b);
+        
+        for(int i=2;i<4;++i) {
+            plotter_ep_xn.region(i).style().setParameter("hist2DStyle", "colorMap");
+            plotter_ep_xn.region(i).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        }
+
+        
+        
[truncated at 1000 lines; 1444 more skipped]

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
ParticleHelixProducer.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ParticleHelixProducer.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ParticleHelixProducer.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,317 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.ICloud1D;
+import hep.aida.IPlotter;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Matrix;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.lcsim.constants.Constants;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.base.ParticleTypeClassifier;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelixParamCalculator;
+import org.lcsim.fit.helicaltrack.MultipleScatter;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.analysis.ecal.HPSMCParticlePlotsDriver;
+import org.lcsim.hps.recon.tracking.HPSTrack;
+import org.lcsim.hps.recon.tracking.TrackerHitUtils;
+import org.lcsim.recon.tracking.digitization.sisim.TrackerHitType;
+import org.lcsim.recon.tracking.digitization.sisim.TrackerHitType.CoordinateSystem;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson
+ * @version $Id: ParticleHelixProducer.java,v 1.8 2012/11/19 22:20:07 omoreno
+ * Exp $
+ */
+public class ParticleHelixProducer extends Driver {
+
+    private boolean debug = false;
+    private boolean hideFrame = true;
+    private boolean saveSingleTrack = false;
+    private boolean noTopTracks = true;
+    private boolean noBottomTracks = false;
+    private int _totalTracks = 0;
+    TrackerHitUtils trackerhitutils = new TrackerHitUtils();
+    Hep3Matrix detToTrk;
+    Hep3Vector _bfield;
+    TrackerHitType trackerType = new TrackerHitType(TrackerHitType.CoordinateSystem.GLOBAL, TrackerHitType.MeasurementType.STRIP_1D);
+    CoordinateSystem coordinate_system = trackerType.getCoordinateSystem();
+    // Name of StripHit1D output collection.
+    private String trackOutputCollectionName = "MCParticle_HelicalTrackFit";
+    private AIDA aida = AIDA.defaultInstance();
+    IPlotter plotter_trkparams;
+    ICloud1D h_pt;
+    ICloud1D h_phi0;
+    ICloud1D h_d0;
+    ICloud1D h_R;
+    ICloud1D h_slope;
+    ICloud1D h_z0;
+
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    public void setHideFrame(boolean hide) {
+        this.hideFrame = hide;
+    }
+
+    public void setNoTopTracks(boolean doTop) {
+        this.noTopTracks = doTop;
+    }
+
+    public void setNoBottomTracks(boolean doBot) {
+        this.noBottomTracks = doBot;
+    }
+
+    public void setSaveSingleTrack(boolean single) {
+        this.saveSingleTrack = single;
+    }
+
+    public void setTrackOutputCollectionName(String trackOutputCollectionName) {
+        this.trackOutputCollectionName = trackOutputCollectionName;
+    }
+
+    /**
+     * Creates a new instance of TrackerHitDriver.
+     */
+    public ParticleHelixProducer() {
+    }
+
+    /**
+     * Do initialization once we get a Detector.
+     */
+    @Override
+    public void detectorChanged(Detector detector) {
+
+        // Call sub-Driver's detectorChanged methods.
+        super.detectorChanged(detector);
+
+        if (this.noTopTracks && this.noBottomTracks) {
+            System.out.println(this.getClass().getSimpleName() + ": ERROR you need to produce top or bottom tracks!");
+            System.exit(1);
+        }
+
+        Hep3Vector IP = new BasicHep3Vector(0., 0., 1.);
+        _bfield = new BasicHep3Vector(0, 0, detector.getFieldMap().getField(IP).y());
+        detToTrk = trackerhitutils.detToTrackRotationMatrix();
+
+
+        plotter_trkparams = aida.analysisFactory().createPlotterFactory().create();
+        plotter_trkparams.createRegions(3, 2);
+        h_pt = aida.cloud1D("Track pT");
+        h_R = aida.cloud1D("Track R");
+        h_phi0 = aida.cloud1D("Track phi0");
+        h_d0 = aida.cloud1D("Track d0");
+        h_slope = aida.cloud1D("Track slope");
+        h_z0 = aida.cloud1D("Track z0");
+        plotter_trkparams.region(0).plot(h_pt);
+        plotter_trkparams.region(1).plot(h_R);
+        plotter_trkparams.region(2).plot(h_phi0);
+        plotter_trkparams.region(3).plot(h_d0);
+        plotter_trkparams.region(4).plot(h_slope);
+        plotter_trkparams.region(5).plot(h_z0);
+        if (!this.hideFrame) {
+            plotter_trkparams.show();
+        }
+
+
+    }
+
+    /**
+     * Perform the digitization.
+     */
+    @Override
+    public void process(EventHeader event) {
+
+
+        //Make new tracks based on the MC particles
+        //List<HelicalTrackFit> tracks = new ArrayList<HelicalTrackFit>();
+        List<HPSTrack> tracks = new ArrayList<HPSTrack>();
+
+        if (event.hasCollection(MCParticle.class)) {
+            List<MCParticle> mcparticles = event.get(MCParticle.class).get(0);
+            List<MCParticle> fsParticles = HPSMCParticlePlotsDriver.makeGenFSParticleList(mcparticles);
+
+            //-----> DEBUG
+            if (debug) {
+                String particleList = "[ ";
+                for (MCParticle mcParticle : mcparticles) {
+                    particleList += mcParticle.getPDGID() + ", ";
+                }
+                particleList += "]";
+                this.printDebug("MC Particles: " + particleList);
+            }
+            if (debug) {
+                String particleList = "[ ";
+                for (MCParticle fsParticle : fsParticles) {
+                    particleList += fsParticle.getPDGID() + ", ";
+                }
+                particleList += "]";
+                this.printDebug("Final State MC Particles: " + particleList);
+            }
+            //------> DEBUG
+
+            double bfield = Math.abs(_bfield.z()); //remove sign from B-field, assumed to be along z-direction
+            if (debug) {
+                System.out.println(this.getClass().getSimpleName() + ": bfield " + bfield);
+            }
+
+            for (MCParticle part : fsParticles) {
+                if (Math.random() > 0.5) {
+                    this.printDebug("Random value below threshold. Skipping the final state MC particle " + part.getPDGID());
+                    continue;
+                }
+                if (ParticleTypeClassifier.isElectron(part.getPDGID()) || ParticleTypeClassifier.isPositron(part.getPDGID())) {
+
+
+                    Hep3Vector p = part.getMomentum();
+                    Hep3Vector org = part.getOrigin();
+                    double q = -1 * part.getCharge(); //since I flipped the B-field I need to flip the charge
+
+
+                    if (p.magnitude() < 0.3) {
+                        if (debug) {
+                            System.out.println(this.getClass().getSimpleName() + ": this MC particle had too small momentum p=" + p.toString());
+                        }
+                        continue;
+                    }
+
+                    double thetay = Math.atan(p.y() / p.z());
+
+                    if (Math.abs(thetay) < 0.01) {
+                        if (debug) {
+                            System.out.println(this.getClass().getSimpleName() + ": this MC particle had too small thetay =" + Math.abs(Math.atan(p.y() / p.z())));
+                        }
+                        continue;
+                    }
+
+                    if (this.noTopTracks && thetay > 0.0) {
+                        if (debug) {
+                            System.out.println(this.getClass().getSimpleName() + ": this MC particle had negative thetay (" + thetay + ") and we only want top tracks");
+                        }
+                        continue;
+                    }
+                    if (this.noBottomTracks && thetay < 0.0) {
+                        if (debug) {
+                            System.out.println(this.getClass().getSimpleName() + ": this MC particle had positive thetay (" + thetay + ") and we only want bottom tracks");
+                        }
+                        continue;
+                    }
+
+
+                    //propagate to start of field region if needed
+                    double dz = 0 - org.z();
+                    if (dz > 0) {
+                        System.out.print(this.getClass().getSimpleName() + ": Propagate MC particle to field region from org=" + org.toString());
+                        double tanPxPz = p.x() / p.z();
+                        double tanPyPz = p.y() / p.z();
+                        double dx = dz * tanPxPz;
+                        double dy = dz * tanPyPz;
+
+                        org = new BasicHep3Vector(org.x() + dx, org.y() + dy, org.z() + dz);
+
+                        System.out.println(" to   org=" + org.toString() + " (p=" + p.toString() + ")");
+
+                    }
+
+                    //if(debug) System.out.println(this.getClass().getSimpleName() + ": MC particle p=" + p.toString() +" org=" + org.toString() +" q = " + q);
+                    p = VecOp.mult(detToTrk, p);
+                    org = VecOp.mult(detToTrk, org);
+                    if (debug) {
+                        System.out.println(this.getClass().getSimpleName() + ": MC particle p=" + p.toString() + " org=" + org.toString() + " q = " + q + " (rotated)");
+                    }
+
+                    if (debug) {
+                        double pt = Math.sqrt(p.x() * p.x() + p.y() * p.y());
+                        double Rman = q * pt / (Constants.fieldConversion * bfield);
+                        double phi = Math.atan2(p.y(), p.x());
+                        double xc = org.x() + Rman * Math.sin(phi);
+                        double yc = org.y() - Rman * Math.cos(phi);
+                        double Rc = Math.sqrt(xc * xc + yc * yc);
+                        double dca = q > 0 ? (Rman - Rc) : (Rman + Rc);
+                        System.out.println(this.getClass().getSimpleName() + ": manual calcualtion gives pt " + pt + " R " + Rman + " phi " + phi + " xc " + xc + " yc " + yc + " Rc " + Rc + " DCA " + dca);
+                    }
+                    //HelixParamCalculator hpc = new HelixParamCalculator(part,bfield);
+                    HelixParamCalculator hpc = new HelixParamCalculator(p, org, (int) q, bfield); //remove sign from b-field
+                    double[] pars = new double[5];
+                    pars[0] = hpc.getDCA();
+                    pars[1] = hpc.getPhi0();
+                    pars[2] = 1 / hpc.getRadius();
+                    pars[3] = hpc.getZ0();
+                    pars[4] = hpc.getSlopeSZPlane();
+                    //HelicalTrackFit htf = this.trackUtils.makeHelicalTrackFit(pars);
+                    HPSTrack htf = this.makeHPSTrack(pars, part);
+                    tracks.add(htf);
+                    if (debug) {
+                        System.out.println(this.getClass().getSimpleName() + ": MC particle created HelicalTrackFit " + htf.toString());
+
+                    }
+
+                    h_pt.fill(htf.pT(bfield));
+                    h_R.fill(htf.R());
+                    h_d0.fill(htf.dca());
+                    h_phi0.fill(htf.phi0());
+                    h_slope.fill(htf.slope());
+                    h_z0.fill(htf.z0());
+
+
+                    if (saveSingleTrack && tracks.size() == 1) {
+                        break;
+                    }
+
+                }
+            }
+        }
+
+        // If there were not HpsHelicalTrackFits created, skip the event
+        if (tracks.isEmpty()) {
+            this.printDebug("No tracks were created. Skipping the event ...");
+            return;
+        }
+
+        this.printDebug("created " + tracks.size() + " MC particle helix tracks");
+        event.put(this.trackOutputCollectionName, tracks, HPSTrack.class, 0);
+        _totalTracks += tracks.size();
+    }
+
+    /**
+     * Create an HpsHelicalTrackFit
+     *
+     * @param helixParameters : an array of helix parameters
+     * @param mcParticle : MC particle associated to this HelicalTrackFit
+     * @return HpsHelicalTrackFit :
+     */
+    public HPSTrack makeHPSTrack(double[] helixParameters, MCParticle mcParticle) {
+        return new HPSTrack(helixParameters, new SymmetricMatrix(5), new double[2], new int[2],
+                new HashMap<HelicalTrackHit, Double>(), new HashMap<HelicalTrackHit, MultipleScatter>(), mcParticle);
+    }
+
+    /**
+     * print debug statement
+     *
+     * @param debugStatement : debug statement
+     */
+    public void printDebug(String debugStatement) {
+        if (!debug) {
+            return;
+        }
+        System.out.println(this.getClass().getSimpleName() + ": " + debugStatement);
+    }
+
+    @Override
+    public void endOfData() {
+
+        System.out.println(this.getClass().getSimpleName() + ": produced " + _totalTracks);
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
PolarCount.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/PolarCount.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/PolarCount.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,69 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+
+import hep.aida.IHistogram1D;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author phansson
+ */
+public class PolarCount {
+    
+    private String run;
+    private String name;
+    private double val;
+    private Count count;
+    
+    
+    PolarCount(String n, String r, double v, Count c) {
+        this.name = n;
+        this.run = r;
+        this.val = v;
+        this.count = c;
+    }
+    
+    PolarCount(PolarCount c) {
+        this.name = c.name();
+        this.run = c.run();
+        this.val = c.val;
+        this.count = c.count();
+    }
+        
+    
+    public String name() {
+        return this.name;
+    }
+
+    public void setName(String str) {
+        this.name = str;
+    }
+
+    public void setCount(Count c) {
+        this.count = c;
+    }
+    
+    public String run() {
+        return this.run;
+    }
+
+    public double val() {
+        return this.val;
+    }
+
+    public void addSimple(PolarCount l) {
+        this.count.addSimple(l.count().n(), l.count().en());
+    }
+    
+    public Count count() {
+        return this.count;
+    }
+    
+
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
ResLimit.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ResLimit.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ResLimit.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,101 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import java.util.*;
+
+
+
+/**Map< Integer, Map<Integer
+ *
+ * @author phansson
+ */
+public class ResLimit {
+    
+    Map< Integer, Map<Integer,Double[]> >  map_top = new HashMap< Integer, Map<Integer,Double[]> >();
+    Map< Integer, Map<Integer,Double[]> >  map_bottom = new HashMap< Integer, Map<Integer,Double[]> >();
+    
+    
+    public void ResLimit() {
+            
+    }
+    
+    
+    public void add(int side, int layer,int dir,double xmin,double xmax) {
+        Map< Integer, Map<Integer,Double[]> >  map;
+        if(side==0) {
+            map = map_top;
+        } else {
+            map = map_bottom;
+        }
+        if(map.containsKey(layer)) {
+            Double v[] = {xmin,xmax};        
+            map.get(layer).put(dir,v);
+        } else {
+            map.put(layer,new HashMap<Integer,Double[]>());
+            add(side,layer,dir,xmin,xmax);
+        }
+        
+        
+    }
+    
+    public double getMin(int side,int l,int d) {
+        return getLim(side,l,d)[0];
+        
+    }
+
+    public double getMax(int side,int l,int d) {
+        return getLim(side,l,d)[1];
+        
+    }
+
+    public Double[] getLim(int side,int l,int d) {
+        Map< Integer, Map<Integer,Double[]> >  map;
+        if(side==0) {
+            map = map_top;
+        } else {
+            map = map_bottom;
+        }
+        if(!map.containsKey(l)) {
+            System.out.println("ERROR this layer " + l + " doesn't exist in ResLimit!");
+            System.exit(1);
+        }
+        if(!map.get(l).containsKey(d)) {
+            System.out.println("ERROR this layer " + l + " doesn't have direction " + d + " in ResLimit!");
+            System.exit(1);
+        }
+        return map.get(l).get(d);
+    }
+    
+    public void print() {
+        System.out.print("---Residual limits:");
+        for(int side=0;side<2;++side) {
+            System.out.print("Side: " + side);
+            Map< Integer, Map<Integer,Double[]> >  map;
+            if(side==0) {
+                map = map_top;
+            } else {
+                map = map_bottom;
+            }
+            Iterator it = map.keySet().iterator();
+            System.out.printf("%5s %5.1d %5.1d \n","Layer","Dir","Min","Max");
+        
+        while(it.hasNext()) {
+            Integer l = (Integer)it.next();
+            Map<Integer,Double[]> m = map.get(l);
+            Iterator itt = m.keySet().iterator();
+            while(itt.hasNext()) {
+                Integer dir = (Integer)itt.next();
+                Double[] lim = m.get(dir);
+                System.out.printf("%5d %5d %5.1f %5.1f \n",l,dir,lim[0],lim[1]);
+                
+            }
+        }
+        }
+    }
+    
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
RunMPAlignment.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/RunMPAlignment.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/RunMPAlignment.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,231 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.event.*;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.geometry.Detector;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHit;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author mgraham
+ */
+public class RunMPAlignment extends Driver {
+
+    private AIDA aida = AIDA.defaultInstance();
+    String[] detNames = {"Tracker"};
+    int nevt = 0;
+    double[] beamsize = {0.001, 0.02, 0.02};
+    String _config = "";
+    StripMPAlignmentInput ap;
+    int totalTracks=0;
+    int totalTracksProcessed=0;
+    private String _resLimitFileName="";
+    private String outputPlotFileName="";
+    private boolean hideFrame = false;
+// flipSign is a kludge...
+//  HelicalTrackFitter doesn't deal with B-fields in -ive Z correctly
+//  so we set the B-field in +iveZ and flip signs of fitted tracks
+//  note:  this should be -1 for Test configurations and +1 for Full (v3.X and lower) configurations
+//  this is set by the _config variable (detType in HeavyPhotonDriver)
+    int flipSign = 1;
+    private boolean _debug = false;
+    private String _type = "LOCAL"; //GLOBAL OR LOCAL RESIDUALS
+     
+    private String simTrackerHitCollectionName = "TrackerHits";
+    private String milleFile = "alignMP.txt";
+    
+    public void setDebug(boolean v) {
+        this._debug = v;
+    }
+    public void setType(String type) {
+        this._type = type;
+    }
+    public void setMilleFile(String filename) {
+        milleFile = filename;
+    }
+    public void setOutputPlotFileName(String filename) {
+        outputPlotFileName = filename;
+    }
+    
+    public void setHideFrame(boolean hide) {
+        hideFrame = hide;
+    }
+    
+    public void setResidualLimitFileName(String fileName) {
+        this._resLimitFileName = fileName;
+    }
+
+    
+    public RunMPAlignment() {
+    }
+
+    
+    @Override
+    public void detectorChanged(Detector detector) {
+        
+        ap = new StripMPAlignmentInput(milleFile,_type);
+        ap.setDebug(_debug);
+        ap.setHideFrame(hideFrame);
+        double bfield = detector.getFieldMap().getField(new BasicHep3Vector(0., 0., 1.)).y();
+        System.out.printf("%s: B-field in z %.3f\n",this.getClass().getSimpleName(),bfield);
+        ap.setUniformZFieldStrength(bfield);
+        loadResidualLimits();
+        
+    }
+    
+    
+    
+    @Override
+    public void process(EventHeader event) {
+
+        
+        List<Track> tracklist = null;
+        if(event.hasCollection(Track.class,"MatchedTracks")) {        
+            tracklist = event.get(Track.class, "MatchedTracks");
+             if(_debug) {
+                System.out.println(this.getClass().getSimpleName() + ": Number of Tracks = " + tracklist.size());
+             }
+        }
+        
+        for (Track trk : tracklist) {
+            
+            //if(trk.getCharge()>0) continue;
+            //if(trk.getTrackStates().get(0).getMomentum()[0]>0.8) continue;
+            
+            totalTracks++;
+            
+            if(hitsOnBothSides(trk)) continue;
+            
+            double Px =  trk.getTrackStates().get(0).getMomentum()[0];
+            if(Px < 0.2) {
+                System.out.printf("%s: Trk p = [%.3f,%.3f,%.3f] is low skip!?\n",this.getClass().getSimpleName(),
+                        trk.getTrackStates().get(0).getMomentum()[0],trk.getTrackStates().get(0).getMomentum()[1],trk.getTrackStates().get(0).getMomentum()[2]);
+                continue;
+            }
+            
+            totalTracksProcessed++;
+            
+            ap.PrintResidualsAndDerivatives(trk, totalTracks);
+            
+            
+            
+
+        }
+        
+        
+        
+        
+    }
+
+    @Override
+    public void endOfData() {
+        ap.updatePlots();
+        ap.closeFile();
+        if (!"".equals(outputPlotFileName)) {
+            try {
+                aida.saveAs(outputPlotFileName);
+            } catch (IOException ex) {
+                Logger.getLogger(TrigRateDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+            }
+        }
+        System.out.println(this.getClass().getSimpleName() + ": Total Number of Tracks Found = "+totalTracks);
+        System.out.println(this.getClass().getSimpleName() + ": Total Number of Tracks Processed = "+totalTracksProcessed);
+        
+        
+    }
+    
+    
+    public boolean hitsOnBothSides(Track track) {
+        List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+        int ihalf = hitsOnTrack.get(0).getPosition()[2]>0 ? 1 : 0;
+        boolean hitsOnWrongSide = false;
+        for (TrackerHit hit : hitsOnTrack) {
+            double[] pos = hit.getPosition();
+            if((ihalf==0 && pos[2]>0) || (ihalf==1 && pos[2]<0)) {
+                hitsOnWrongSide = true;
+                break;
+            }
+        }   
+        if(hitsOnWrongSide) {
+            System.out.println(this.getClass().getSimpleName() + ": TRACK w/ both halves hit (: chi2 "+track.getChi2()+", pX "+track.getPX()+", pY "+track.getPY()+", pZ "+track.getPZ()+")");
+            System.out.printf(this.getClass().getSimpleName() + ": Hits: ");
+            for (TrackerHit hit : hitsOnTrack) {
+                double[] pos = hit.getPosition();
+                System.out.printf(this.getClass().getSimpleName() + ": (%.2f,%.2f,%.2f)", pos[0],pos[1],pos[2]);
+            }   
+            System.out.println("");
+        }
+        return hitsOnWrongSide;
+    }
+    
+    private void loadResidualLimits() {
+        
+        //Initialize the res limits
+        for(int i=1;i<=10;++i) {
+            for(int j=0;j<3;++j) {
+                double xmin = -50;
+                double xmax = 50;
+                for(int side=0;side<2;++side) {
+                   ap.setResLimits(side,i,j, xmin, xmax);        
+                }
+            }
+        }
+        
+        if(!"".equals(this._resLimitFileName)) {
+            FileReader fReader;
+            BufferedReader bReader;
+            try {
+                fReader = new FileReader(this._resLimitFileName);
+                bReader = new BufferedReader(fReader);
+
+                String line;
+                while( (line = bReader.readLine()) != null) {
+                    if (line.contains("#")) continue;
+                    String[] vec = line.split("\\s+");
+                    if(vec.length!=5) {
+                        System.out.println(this.getClass().getSimpleName() + ": Error: residual limits line has wrong format -> " + line);
+                        System.exit(1);
+                    }
+                    try {
+                        int side = Integer.parseInt(vec[0]);
+                        int layer = Integer.parseInt(vec[1]);
+                        int direction = Integer.parseInt(vec[2]);
+                        double min = Double.parseDouble(vec[3]);
+                        double max = Double.parseDouble(vec[4]);
+                        ap.setResLimits(side, layer, direction, min, max);
+                    } catch(NumberFormatException e) {
+                        Logger.getLogger(RunMPAlignment.class.getName()).log(Level.SEVERE,null,e);
+                    }
+                }
+                bReader.close();
+                fReader.close();
+            }
+            catch (FileNotFoundException ex) {
+                Logger.getLogger(TrigRateAna.class.getName()).log(Level.SEVERE, null, ex);
+            } catch (IOException e) {
+                Logger.getLogger(TrigRateAna.class.getName()).log(Level.SEVERE,null,e);
+            } 
+        }
+    
+        
+
+    }
+    
+    
+    
+    
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
SimpleHPSConditions.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/SimpleHPSConditions.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/SimpleHPSConditions.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,133 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author phansson
+ */
+public class SimpleHPSConditions {
+    
+    private class SimpleHPSCondition {
+        public double _thickness;
+        public double _rate;
+        public double _rate_rec;
+        public double _int_current;
+        public int _start_time;
+        public int _stop_time;
+        public int _run_nr;
+
+        public SimpleHPSCondition() {}
+        
+        @Override
+        public String toString() {
+           return String.format("%d %.1f nC %.2f r.l. %.2f %.2f Hz \n",_run_nr,_int_current,_thickness,_rate,_rate_rec);
+        }
+    
+    }
+    
+    public List<SimpleHPSCondition> _conditionsList = new ArrayList<SimpleHPSCondition>();
+    
+    public SimpleHPSConditions() {
+     
+        this.loadCond();
+        
+    }
+    
+    public void loadCond() {
+//        System.out.println("Reading beam currents from " + pathToFile);
+        InputStreamReader fReader;
+        BufferedReader bufReader;
+        try {
+            InputStream stream = this.getClass().getResourceAsStream("/org/lcsim/hps/steering/runConditions.txt");
+            fReader = new InputStreamReader(stream);
+            bufReader = new BufferedReader(fReader);
+
+            String line;
+            while( (line = bufReader.readLine()) != null) {
+                //System.out.println("Line: " + line);
+                if(line.contains("run") || line.contains("#")) continue;
+                
+                String[] vec_line = line.split("\\s+");
+                //for(int i=0;i<5;++i) System.out.println(vec_line[i] +" ," );
+                String s = vec_line[0];
+                //System.out.println("s \"" + s + "\"");
+                Integer run = Integer.parseInt(s);
+                //System.out.println(run);
+                int start = Integer.parseInt(vec_line[1]);
+                int stop = Integer.parseInt(vec_line[2]);
+                double cur = Double.parseDouble(vec_line[4]);
+                double t = Double.parseDouble(vec_line[5]);
+                double rate = Double.parseDouble(vec_line[6]);
+                double rate_rec = Double.parseDouble(vec_line[7]);
+
+                SimpleHPSCondition c = new SimpleHPSCondition();
+                c._run_nr = run;
+                c._int_current = cur;
+                c._start_time = start;
+                c._stop_time = stop;
+                c._rate = rate;
+                c._rate_rec = rate_rec;
+                c._thickness = t;
+                this._conditionsList.add(c);
+                System.out.println("Add conditions for run " + c.toString());
+                
+            }
+            bufReader.close();
+            fReader.close();
+        } catch (FileNotFoundException ex) {
+            Logger.getLogger(TrigRateAna.class.getName()).log(Level.SEVERE, null, ex);
+        } catch (IOException e) {
+            Logger.getLogger(TrigRateAna.class.getName()).log(Level.SEVERE,null,e);
+        } 
+        
+    }
+    
+    private SimpleHPSCondition getCond(int run) {
+        for(SimpleHPSCondition c: this._conditionsList) {
+            if(c._run_nr==run) {
+                return c;
+            }
+        }
+        return null;
+    }
+    public int getStartTime(int run) {
+        return this.getCond(run)._start_time;
+    }
+    public int getStopTime(int run) {
+        return this.getCond(run)._stop_time;
+    }
+    public double getIntCurrent(int run) {
+        return this.getCond(run)._int_current;
+    }
+    public double getRate(int run) {
+        return this.getCond(run)._rate;
+    }
+    public double getRecRate(int run) {
+        return this.getCond(run)._rate_rec;
+    }
+    public double getThickness(int run) {
+        return this.getCond(run)._thickness;
+    }
+    
+    public String toString() {
+         //String str = String.format("%10s\t%8d\t%8d\t%8.2f+-%.2f",getRun(),getStartTime(),getStopTime(),getIntCurrent(),getIntCurrentError());
+         String str = " yeah need to add something";
+         return str;
+    }
+    
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
SimpleResiduals.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/SimpleResiduals.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/SimpleResiduals.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,749 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogramFactory;
+import hep.aida.IPlotter;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.tracker.silicon.*;
+import org.lcsim.event.*;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHit;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson
+ */
+public class SimpleResiduals extends Driver {
+    
+    int nevents = 0;
+    private boolean debug = false;
+    private boolean doFastTracking = false;
+    private boolean doDefaultResiduals = false;
+    protected IDDecoder dec = null;
+    protected Subdetector ecal;
+    private String ecalName = "Ecal";
+    double crystalX = (13.3 + 16.0) / 2;
+    double crystalY = (13.3 + 16.0) / 2;
+    double beamGap = 20.0;
+    private double EcalZPosition = 1370.0;
+    
+    
+    
+    private String outputPlotFileName;
+    
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    private IHistogram1D phi0;
+    private IHistogram1D z0;
+    private IHistogram1D slope;
+    private IHistogram1D theta;
+    private IHistogram1D resx_simple_TrackHit;
+    private IHistogram1D resx_simple_Strip0;
+    private IHistogram1D resx_simple_Strip1;
+    private IHistogram1D resy_simple_TrackHit;
+    private IHistogram1D resy_simple_Strip0;
+    private IHistogram1D resy_simple_Strip1;
+    private IHistogram1D resz_simple_TrackHit;
+    private IHistogram1D resz_simple_Strip0;
+    private IHistogram1D resz_simple_Strip1;
+    
+    //FastTrack residuals
+    private List< List<IHistogram1D> > resy_org = new ArrayList<List<IHistogram1D> >();
+    private List< List<IHistogram1D> > resy_org_layallhit = new ArrayList<List<IHistogram1D> >();
+    private List< List<IHistogram1D> > resy_org_lay1hit = new ArrayList<List<IHistogram1D> >();
+    
+    private List< IHistogram1D> nhits_tracker = new ArrayList<IHistogram1D>();
+    
+    
+    public void startOfData() {
+        System.out.println("startOfData called");
+        if( debug ) 
+            System.out.println("Debug ON");
+        else 
+            System.err.println("Debug OFF");
+    }
+    
+    public void detectorChanged(Detector detector) {
+	// Get the Subdetector.
+	ecal = detector.getSubdetector(ecalName);
+
+	// Cache ref to decoder.
+	dec = ecal.getIDDecoder();
+    }
+    
+    public SimpleResiduals() {
+        System.out.println("Empty HPSRunAlignment constructor called");
+        IHistogramFactory hf = aida.histogramFactory();
+        //Histograms
+        phi0 = hf.createHistogram1D("phi0", 50, 0, 2*Math.PI);
+        z0 = hf.createHistogram1D("z0", 50, -10, 10);
+        slope = hf.createHistogram1D("slope", 50, -0.1, 0.1);
+        theta = hf.createHistogram1D("theta", 50, -1*Math.PI, Math.PI);
+        resx_simple_TrackHit = hf.createHistogram1D("resx_simple_TrackHit", 50, -10, 10);
+        resy_simple_TrackHit = hf.createHistogram1D("resy_simple_TrackHit", 50, -20, 20);
+        resz_simple_TrackHit = hf.createHistogram1D("resz_simple_TrackHit", 50, -10, 10);
+        
+        resx_simple_Strip0 = hf.createHistogram1D("resx_simple_Strip0", 50, -10, 10);
+        resy_simple_Strip0 = hf.createHistogram1D("resy_simple_Strip0", 50, -100, 100);
+        resz_simple_Strip0 = hf.createHistogram1D("resz_simple_Strip0", 50, -10, 10);
+
+        resx_simple_Strip1 = hf.createHistogram1D("resx_simple_Strip1", 50, -10, 10);
+        resy_simple_Strip1 = hf.createHistogram1D("resy_simple_Strip1", 50, -100, 100);
+        resz_simple_Strip1 = hf.createHistogram1D("resz_simple_Strip1", 50, -10, 10);
+        
+        System.out.println("Creating resy histos");
+        for (int iSide=0;iSide<2;++iSide) {
+            String side;
+            if(iSide==0) side="up";
+            else side="down";
+            System.out.println("Creating resy histos for side  " + side + "(size: " + resy_org.size() + ")");
+            List<IHistogram1D> list  = new ArrayList<IHistogram1D>();
+            resy_org.add(list);
+            List<IHistogram1D> listLayAllHit  = new ArrayList<IHistogram1D>();
+            resy_org_layallhit.add(listLayAllHit);
+            List<IHistogram1D> listLay1Hit  = new ArrayList<IHistogram1D>();
+            resy_org_lay1hit.add(listLay1Hit);
+            
+            nhits_tracker.add(hf.createHistogram1D("FT_nhits_tracker_" + side , 20, 0, 20));
+            
+            System.out.println("Creating resy histos for side " + iSide + "(size: " + resy_org.size() + ")");
+            for (int iLayer=1;iLayer<6;++iLayer) {
+                System.out.println("add iSide " + iSide + " iLayer " + iLayer);
+                
+                IHistogram1D h = hf.createHistogram1D("FT_resy_org_" + side + "_l"+iLayer, 50, -25, 25);
+                list.add(h);
+
+                IHistogram1D hAll = hf.createHistogram1D("FT_resy_org_LayAllHit_" + side + "_l"+iLayer, 50, -25, 25);
+                listLayAllHit.add(hAll);
+                
+                IHistogram1D hLay1 = hf.createHistogram1D("FT_resy_org_lay1hit_" + side + "_l"+iLayer, 50, -25, 25);
+                listLay1Hit.add(hLay1);
+                
+            }
+        }
+    
+        
+    }
+    
+    List<SiTrackerHitStrip1D> getAllHits(EventHeader event) {
+        List<SiTrackerHitStrip1D> stripHits = event.get(SiTrackerHitStrip1D.class, "StripClusterer_SiTrackerHitStrip1D");
+        if(debug) System.out.println("Got " + stripHits.size() + " SiTrackerHitStrip1D in this event");
+        return stripHits;
+    }
+    
+    
+    List<TrackerHit> getAllHitsFromTracks(EventHeader event) {
+        List<Track> trackList = event.get(Track.class, "MatchedTracks");
+        
+        if( debug )
+            System.out.println("There are " +  trackList.size() + " tracks in \"MatchedTrack\"");
+        
+        
+        //Loop over all tracks and find the hits
+        List<TrackerHit> hits = new ArrayList<TrackerHit>();
+        int ntracks = 0;
+        for ( Track track : trackList ) {
+            List<TrackerHit> trackerHits = track.getTrackerHits();
+            for ( TrackerHit h : trackerHits ) {
+                
+                hits.add(h);
+            }
+            if ( debug ) { 
+                System.out.println("Track " + ntracks + " has " + trackerHits.size() + " hits -> added " + hits.size() + " so far.");
+            }
+        }
+        return hits;
+    }
+    
+    List<SiTrackerHitStrip1D> getAllHitsInEvent(EventHeader event) {
+        //First a workaround - use hits from track.. 
+        //List<TrackerHit> hits = getAllHitsFromTracks(event);
+        List<SiTrackerHitStrip1D> hits = getAllHits(event);
+        if( debug ) {
+            System.err.println("Found " + hits.size() + " hits");
+        }
+        return hits;
+    }
+    
+    private Hep3Vector getFastTrackOrigin(EventHeader event) {
+        double tx = 0.0;
+        double ty = 0.0;
+        double tz = 0.0;
+        Hep3Vector pos = new BasicHep3Vector(tx,ty,tz);
+                
+        return pos;
+    }
+        
+    private List<HPSEcalCluster> getAllEcalClusters(EventHeader event) {
+        
+        List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, "EcalClusters"); 
+        if ( debug) {
+            System.out.println("Found " + clusters.size() + " clusters");
+        }
+        return clusters;
+    }
+
+    private double[] getClusterPosition(HPSEcalCluster cluster) {
+        CalorimeterHit hit = cluster.getSeedHit();
+
+        //IDDecoder dec = dec.getSubdetector("Ecal").getIDDecoder();
+        dec.setID(hit.getCellID());
+        int ix = dec.getValue("ix");
+        int iy = dec.getValue("iy");
+        double position[] = new double[2];
+        position[0] = crystalX * ix;
+        position[1] = crystalY * iy + beamGap * Math.signum(iy);
+        return position; 
+    }
+
+    
+    private List<Hep3Vector> getEcalClustersForFastTracking(List<HPSEcalCluster> clusters, String side) {
+        if(!side.equalsIgnoreCase("up") && !side.equalsIgnoreCase("down")) {
+            throw new RuntimeException("This ecal side" + side + " do not exist!!");
+        }
+        List<Hep3Vector> cls = new ArrayList<Hep3Vector>();
+        boolean save;
+        double [] pos_xy;
+        for ( HPSEcalCluster cl : clusters) {
+            save=false;
+            pos_xy = getClusterPosition(cl);
+            if(pos_xy[1]>=0 && side.equalsIgnoreCase("up")) {
+                save=true;
+            } else if(pos_xy[1]<0 && side.equalsIgnoreCase("down")) {
+                save=true;
+            } 
+            if(save) cls.add(new BasicHep3Vector(pos_xy[0],pos_xy[1],EcalZPosition));
+        }
+        return cls;
+    }
+     
+    private Hep3Vector selectCluster(List<Hep3Vector> clusters) {
+        //need to decide which cluster to take
+        if (clusters.size()>0) {
+            Hep3Vector pos = clusters.get(0);
+            return pos;
+        } else {
+            throw new RuntimeException("No cluser positions to choose from!");
+        }
+        
+    }
+
+    private List<HPSEcalCluster> getAllEcalClustersForFastTracking(EventHeader event) {
+        
+        List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, "EcalClusters"); 
+        if ( debug) {
+            System.out.println("Found " + clusters.size() + " clusters");
+        }
+        
+     
+        return clusters;
+    }
+
+    
+    public void fastTracking(EventHeader event) {
+        
+        if ( debug) {
+            System.out.println("Running fast tracking on this event");
+        }
+        
+        //Get list of all Hits in the event
+        List<SiTrackerHitStrip1D> trackerHits = getAllHitsInEvent(event);
+        
+        //Get the calorimeter cluster object used to construct the track
+        List<HPSEcalCluster> ecal_all_clusters = getAllEcalClustersForFastTracking(event);
+        //Exit if no clusters found
+        if (ecal_all_clusters.size()==0) return;
+
+        String sides[] = {"up","down"};
+        int nhits;
+        int nhitsInTracker;
+        int nhitsInLayer1;
+        Hep3Vector ecal_cl;
+        Hep3Vector origin_pos;
+        List<Hep3Vector> ecal_cls;
+        FastTrack fastTrack = new FastTrack(debug);
+        List<SiTrackerHitStrip1D> stripList;
+        boolean isaxial;
+        String name;
+        SiSensor siSensor;
+        int layer;
+        String si_side;
+        double res;
+        for (int iSide=0;iSide<2;++iSide) {
+            
+            if(debug) System.out.println("Side: " + sides[iSide]);
+            
+            ecal_cls = getEcalClustersForFastTracking(ecal_all_clusters, sides[iSide]);
+            if (debug) System.out.println("This side has " + ecal_cls.size() + " clusters");
+            if( ecal_cls.size() ==0 ) {
+                System.out.println("No clusters...");
+                continue;
+            }
+            ecal_cl = selectCluster(ecal_cls);  
+                        
+            //Get "target" position i.e. the origin of the radiation
+            origin_pos = getFastTrackOrigin(event);
+            
+            //Create the fast track 
+            fastTrack.setTrack(origin_pos, ecal_cl);
+            
+            if ( debug ) System.out.println(fastTrack.toString());
+           
+        
+            nhits = 0;
+            nhitsInTracker = getNLayersWithAxialHit(trackerHits,sides[iSide]);
+            //most upstream layer nr is different for top and bottom
+            int firstLayer = 1;
+            if (sides[iSide] == "down") firstLayer=2;
+            nhitsInLayer1 = getNAxialHitsInLayers(trackerHits,sides[iSide],firstLayer);
+            
+            nhits_tracker.get(iSide).fill(nhitsInTracker);
+            
+            stripList = new ArrayList<SiTrackerHitStrip1D>();
+            for ( SiTrackerHitStrip1D stripCluster : trackerHits ) {
+                
+                isaxial = isAxialHit(stripCluster);
+                
+                if( isaxial == false) continue;
+                
+                siSensor = stripCluster.getSensor();
+                name = siSensor.getName();
+                if ( name.length() < 14) {
+                    System.err.println("This name is too short!!");
+                    throw new RuntimeException("SiSensor name " + name + " is invalid?");
+                }
+                
+                
+                layer = getLayerFromSensorName(name);
+                
+                si_side = getSideFromSiCluster(stripCluster);
+                
+                if ( debug ) {
+                    System.out.println("hit " + nhits + " on " + si_side + " side of detector");
+                    System.out.println("SiSensor layer " + layer + "(" + name + ")");
+                    System.out.println("isAxial? " + isaxial);
+                }
+
+                
+                if( sides[iSide] == si_side) {
+                    System.out.println("This hit is same side as Ecal cluster side");
+                } else {
+                     System.out.println("This hit is opposite side side as Ecal cluster side -> skip!");
+                     continue;
+                } 
+                
+                res = fastTrack.getFastTrackResidual(stripCluster);
+            
+//                1 2 3 4 5 6 7 8 9 10
+//                0   1   2   3   4
+//                  0   1   2   3   4
+               
+                // Fix the layer for the list index
+                int layerIndex = layer;
+                if ( layer % 2 ==0 ) layerIndex=layer/2-1; 
+                else layerIndex = (layer-1)/2;
+                resy_org.get(iSide).get(layerIndex).fill(res);
+                
+                if (nhitsInTracker==5) {
+                    resy_org_layallhit.get(iSide).get(layerIndex).fill(res);
+                }
+                
+                if (nhitsInLayer1>0) {
+                    resy_org_lay1hit.get(iSide).get(layerIndex).fill(res);
+                }
+            
+                ++nhits;
+            }
+        
+            if ( debug ) System.out.println("Processed " + nhits + " for this side");
+        }
+       return;
+    }
+    
+     
+    private boolean isAxialHit(SiTrackerHitStrip1D strip) {
+        boolean axial = false;
+        Hep3Vector m = strip.getMeasuredCoordinate();
+        System.out.println("y " + m.y() + " -> abs(y) " + Math.abs(m.y()) );
+        if ( Math.abs((Math.abs(m.y())-1.0))<0.0000000001 ) {
+            axial = true;
+            System.out.println( " ===> " + axial );
+        }
+        return axial;
+    }
+        
+    private int getNLayersWithAxialHit(List<SiTrackerHitStrip1D> trackerHits, String side) {
+        int nhits=0;
+        for ( SiTrackerHitStrip1D stripCluster : trackerHits ) {
+            
+            if(isAxialHit(stripCluster)) {
+                String si_side = getSideFromSiCluster(stripCluster);
+                
+                if( side == si_side) {
+                    ++nhits;
+                }
+            }
+        }
+                          
+        return nhits;
+    }   
+    
+     private int getNAxialHitsInLayers(List<SiTrackerHitStrip1D> trackerHits, String side, int layer) {
+        int nhits=0;
+        String si_side;
+        SiSensor siSensor;
+        String name;
+        int l;
+        for ( SiTrackerHitStrip1D stripCluster : trackerHits ) {
+            
+            if(isAxialHit(stripCluster)==false) continue;
+           
+            si_side = getSideFromSiCluster(stripCluster);
+
+            if( side == si_side) {
+                
+                siSensor = stripCluster.getSensor();
+                name = siSensor.getName();
+                if ( name.length() < 14) {
+                    System.err.println("This name is too short!!");
+                    throw new RuntimeException("SiSensor name " + name + " is invalid?");
+                }
+            
+                l = getLayerFromSensorName(name);
+                if ( l == layer) ++nhits;
+            
+            } 
+        }
+                          
+        return nhits;
+    }   
+    
+     private String getSideFromSiCluster(SiTrackerHitStrip1D stripCluster) {       
+        Hep3Vector posVec = stripCluster.getPositionAsVector();
+        double yHit = posVec.y();
+        String side;
+        if (yHit>=0.0) side = "up";
+        else side = "down";
+        return side;
+    }
+
+    
+    private int getLayerFromSensorName(String name) {
+            int ilayer = -1;// = Integer.parseInt(layer.substring(layer.length()-1));
+            if (name.contains("layer")) {
+                
+                String l = name.substring(13);
+                l = l.substring(0, l.indexOf("_"));
+                System.out.println("layer: " + l + " (length: " + l.length() + ")");
+                //String ll = l.subs
+                //System.out.println("ll: " + ll);
+                ilayer = Integer.parseInt(l);
+                System.out.println("il: " + ilayer);
+                if ( ilayer < 1 || ilayer > 10 ) {
+                    System.err.println("This layer doesn't exist?");
+                    throw new RuntimeException("SiSensor name " + name + " is invalid?");
+                }
+                
+            } else {
+                throw new RuntimeException("This sensor name do not have a layer!");
+            }
+            
+            
+            return ilayer;
+    }
+    
+    public void process(EventHeader event) {
+        ++nevents;
+        if( debug ) {
+            System.out.println("Processing event " + nevents);
+            
+        }
+        
+        if ( doFastTracking ) {
+            System.out.println("doFastTracking ");
+            fastTracking(event);
+        } 
+        
+        //if ( doDefaultResiduals ) {
+        if ( 1==0 ) {
+            if( debug )     
+                System.out.println("Do normal residuals");
+            
+            //Get list of tracks
+            List<Track> trackList = event.get(Track.class, "MatchedTracks");
+            
+            if( debug )
+                System.out.println(trackList.size() + " tracks in \"MatchedTrack\"");
+        
+            //Loop over all tracks and calculate Millipede input
+            int ntracks = 0;
+            for ( Track track : trackList ) {
+                if ( debug ) { 
+                    System.out.println("Track " + ntracks);
+                    printTrackBasicInfo(track);
+                }
+                
+                fillTrackInfo(track);
+                //Calculate residuals
+                calcResiduals(track);
+            
+            
+                ++ntracks;
+            }
+        
+            if ( debug )
+                System.out.println("Processed " + ntracks + " in this event");
+        }
+    }
+    
+    
+    public void getHitInfo( SiTrackerHitStrip1D stripCluster) {
+        SiSensor sensor = stripCluster.getSensor();
+        SiTrackerIdentifierHelper sid_helper = stripCluster.getIdentifierHelper();
+        List<RawTrackerHit> raw_hits = stripCluster.getRawHits();
+        if (debug) {
+            System.out.println("This stripCluster has " + raw_hits.size() + ":");
+            System.out.println(raw_hits.toString());
+            System.out.println("Loop and print info on all raw hits");
+        }
+        for (RawTrackerHit raw_hit : raw_hits) {
+            SiSensorElectrodes electrodes = sensor.getReadoutElectrodes(ChargeCarrier.HOLE);
+            IIdentifier id = raw_hit.getIdentifier();
+            Integer strip_id = sid_helper.getElectrodeValue(id);
+            Hep3Vector local_pos = ((SiStrips) electrodes).getStripCenter(strip_id);
+            electrodes.getParentToLocal().inverse().transform(local_pos);
+            Hep3Vector global_pos = ((SiSensor) electrodes.getDetectorElement()).getGeometry().getLocalToGlobal().transformed(local_pos);
+            double ypos = global_pos.y();
+            double zpos = global_pos.z();
+            System.out.println("id  " + id + " strip_id " + strip_id + " local_pos " + local_pos.toString() + " global_pos " + global_pos.toString() + " ypos " + ypos + " zpos " + zpos);
+        }
+    }
+    
+    
+    public void fillTrackInfo( Track track) {
+        aida.histogram1D("phi0").fill(track.getTrackParameter(HelicalTrackFit.phi0Index));    
+        aida.histogram1D("z0").fill(track.getTrackParameter(HelicalTrackFit.z0Index));
+        aida.histogram1D("slope").fill(track.getTrackParameter(HelicalTrackFit.slopeIndex));
+        double theta = Math.atan(1.0/track.getTrackParameter(HelicalTrackFit.slopeIndex));
+        aida.histogram1D("theta").fill(theta);
+    }
+    
+    public void displayTrackPlots() {
+        IPlotter plotter = af.createPlotterFactory().create();
+        //IPlotter plotter = af.createPlotterFactory(af.createTreeFactory().create());
+
+        plotter.createRegions(2,2,0);
+        plotter.region(0).plot(phi0);
+        plotter.region(1).plot(z0);
+        plotter.region(2).plot(slope);
+        plotter.region(3).plot(theta);
+        plotter.show();
+    }
+    
+    public void calcResiduals(Track track) {
+        //Calculates residuals of the hits on the fitted track
+        List<TrackerHit> trackerHits = track.getTrackerHits();
+        int nhits = 0;
+        for ( TrackerHit hit : trackerHits ) {
+            //Get the strips
+            HelicalTrackHit helicalTrackHit = (HelicalTrackHit) hit;
+            HelicalTrackCross helicalTrackCross = (HelicalTrackCross) helicalTrackHit;
+            List<HelicalTrackStrip> helicalStrips = helicalTrackCross.getStrips();
+            HelicalTrackStrip s0 = helicalStrips.get(0);
+            HelicalTrackStrip s1 = helicalStrips.get(1);
+            //Get the position
+            Hep3Vector pos = helicalTrackHit.getCorrectedPosition();
+            Hep3Vector pos0 = getStripGlobalPos(s0);
+            Hep3Vector pos1 = getStripGlobalPos(s1);
+            
+            if ( debug ) {
+                System.out.println("hit " + nhits);
+                System.out.println("HelicalTrackHit corr pos:\n" + pos.toString());
+                System.out.println("Strip 0 global pos:" + pos0.toString());
+                System.out.println("Strip s0:");
+                System.out.println(s0.toString());
+               
+                System.out.println("Strip 1 global pos:" + pos1.toString());
+                System.out.println("Strip s1:");
+                System.out.println(s1.toString());
+            }
+            
+            //Simple residual calculation
+            fillSimpleResiduals(track,pos,"TrackHit");
+            fillSimpleResiduals(track,pos0,"Strip0");
+            fillSimpleResiduals(track,pos1,"Strip1");
+            
+            ++nhits;
+        }
+    }
+    
+    Hep3Vector getTrackPosAtHit(Track track, Hep3Vector hit) {
+        //Find the position of the track at the hit
+        double x_origin = hit.x();
+        double smax = 1e3; //not used
+        int mxint = 5; // not used (five track parameters )
+        SeedTrack st = (SeedTrack) track;
+        SeedCandidate seed = st.getSeedCandidate();
+        HelicalTrackFit hel_track = seed.getHelix();
+        List<Double> pathlength_xyplane = HelixUtils.PathToXPlane(hel_track, x_origin,smax, mxint);
+        Hep3Vector track_pos = HelixUtils.PointOnHelix(hel_track, pathlength_xyplane.get(0));
+        return track_pos;
+    }
+    
+    public void fillSimpleResiduals(Track track, Hep3Vector hit, String name) {
+        Hep3Vector trackPosAtHit = getTrackPosAtHit(track,hit);
+        double res[] = new double[3];
+        res[0]=trackPosAtHit.x()-hit.x();
+        res[1]=trackPosAtHit.y()-hit.y();
+        res[2]=trackPosAtHit.z()-hit.z();
+        if (name == "TrackHit") { 
+            aida.histogram1D("resx_simple_TrackHit").fill(res[0]);
+            aida.histogram1D("resy_simple_TrackHit").fill(res[1]);
+            aida.histogram1D("resz_simple_TrackHit").fill(res[2]);
+        } else if(name == "Strip0") {
+            aida.histogram1D("resx_simple_Strip0").fill(res[0]);
+            aida.histogram1D("resy_simple_Strip0").fill(res[1]);
+            aida.histogram1D("resz_simple_Strip0").fill(res[2]);
+        } else if(name == "Strip1") {
+            aida.histogram1D("resx_simple_Strip1").fill(res[0]);
+            aida.histogram1D("resy_simple_Strip1").fill(res[1]);
+            aida.histogram1D("resz_simple_Strip1").fill(res[2]);
+        } else {
+            System.out.println("Histograms not defined: " + name);
+        }
+   
+    }
+        
+    public void displaySimpleResPlots() {
+        IPlotter plotter = af.createPlotterFactory().create();
+        //IPlotter plotter = af.createPlotterFactory(af.createTreeFactory().create());
+        plotter.createRegions(3,3,0);
+        plotter.region(0).plot(resx_simple_TrackHit);
+        plotter.region(1).plot(resy_simple_TrackHit);
+        plotter.region(2).plot(resz_simple_TrackHit);
+        plotter.region(3).plot(resx_simple_Strip0);
+        plotter.region(4).plot(resy_simple_Strip0);
+        plotter.region(5).plot(resz_simple_Strip0);
+        plotter.region(6).plot(resx_simple_Strip1);
+        plotter.region(7).plot(resy_simple_Strip1);
+        plotter.region(8).plot(resz_simple_Strip1);
+        plotter.show();
+    }
+    
+   public void displayFastTrackingPlots() {
+        //IPlotter plotter = af.createPlotterFactory(af.createTreeFactory().create());
+        IPlotter plotter_org = af.createPlotterFactory().create();
+        plotter_org.createRegions(5,2,0);
+        IPlotter plotter_org_LayAllHit = af.createPlotterFactory().create();
+        plotter_org_LayAllHit.createRegions(5,2,0);
+        IPlotter plotter_org_Lay1Hit = af.createPlotterFactory().create();
+        plotter_org_Lay1Hit.createRegions(5,2,0);
+        
+        for ( int iSide=0;iSide<2;++iSide) {
+            int nLayers = resy_org.get(iSide).size();
+            for (int iLayer=0;iLayer<nLayers;++iLayer) {
+                int idx = 2*iLayer+iSide;
+                
+                //0 1 2 3 4
+                //1 3 5 7 9
+                
+                plotter_org.region(idx).plot(resy_org.get(iSide).get(iLayer));
+                plotter_org_LayAllHit.region(idx).plot(resy_org_layallhit.get(iSide).get(iLayer));
+                plotter_org_Lay1Hit.region(idx).plot(resy_org_lay1hit.get(iSide).get(iLayer));
+            }
+        }
+        plotter_org.show();
+        plotter_org_LayAllHit.show();
+        plotter_org_Lay1Hit.show();
+        
+        IPlotter plotter_hitmult = af.createPlotterFactory().create();
+        plotter_hitmult.createRegions(2,1,0);
+        plotter_hitmult.region(0).plot(nhits_tracker.get(0));
+        plotter_hitmult.region(1).plot(nhits_tracker.get(1));
+        plotter_hitmult.show();
+        
+        
+    }
+    
+    
+    
+    Hep3Vector getStripGlobalPos(HelicalTrackStrip strip) {
+        Hep3Vector origin0 = strip.origin();       
+        Hep3Vector u = strip.u();
+        Hep3Vector v = strip.v();
+        double umeas = strip.umeas();    
+        Hep3Vector pos = new BasicHep3Vector(origin0.x()+u.x()*umeas+v.x(),origin0.y()+u.y()*umeas+v.y(),origin0.z()+u.z()*umeas+v.z());
+        //pos = origin + umeas * uhat + v * vhat
+        return pos;
+    }
+    
+    public void printTrackBasicInfo(Track track) {
+        System.out.println("--Basic track info--");
+        System.out.println(track.toString());
+    }
+    
+    public void endOfData() {
+        System.out.println("endOfData called");
+        try {
+            aida.saveAs(outputPlotFileName);
+        } catch (IOException ex) {
+            Logger.getLogger(FastTrackResidualDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+        }
+        if (doFastTracking) {
+            displayFastTrackingPlots();
+        }
+        if (0==1) {
+        //if (doDefaultResiduals) {
+            displayTrackPlots();
+            displaySimpleResPlots();
+        }
+    }
+
+    public void setDebug(boolean debug) {
+        this.debug = true;
+    }
+
+    public void setdoFastTracking(boolean debug) {
+        this.doFastTracking = true;
+    }
+    
+    public void setdoDefaultResiduals(boolean debug) {
+        this.doDefaultResiduals = true;
+    }
+    public void setOutputPlotFileName( String name ) {
+        this.outputPlotFileName = name;
+    }
+
+    public void setEcalZPosition(double val) {
+        this.EcalZPosition = val;
+    }
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
StripMPAlignmentInput.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/StripMPAlignmentInput.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/StripMPAlignmentInput.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,1127 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import hep.aida.ref.plotter.PlotterRegion;
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.matrix.MatrixOp;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Matrix;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.*;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.tracking.SvtUtils;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+
+/**
+ * Class to calculate and print the residuals and derivatives
+ * of the alignment parameters...used as input for MillePede
+ * Notation follows the MillePede manual:
+ * http://www.desy.de/~blobel/Mptwo.pdf
+ *
+ * the track is measured in the HelicalTrackFit frame
+ * and residuals are in the sensor frame (u,v,w)
+ *
+ * ordering of track parameters is
+ *    double d0 = _trk.dca();
+ *    double z0 = _trk.z0();
+ *    double slope = _trk.slope();
+ *    double phi0 = _trk.phi0();
+ *    double R = _trk.R();
+ *
+ * @author mgraham
+ */
+public class StripMPAlignmentInput extends MPAlignmentInputCalculator {
+
+    private double[] _resid = new double[3];
+    private double[] _error = new double[3];
+    
+    
+    private AIDAFrame plotterFrame;
+    private AIDAFrame plotterFrameSummary;
+    private IDataPointSet dps_t;
+    private IDataPointSet dps_b;
+    private IDataPointSet dps_pull_t;
+    private IDataPointSet dps_pull_b;
+    private IPlotter plotter_resuydiff_t;
+    private IPlotter plotter_resuydiff_b;
+    
+    
+    
+   
+    
+    
+    
+    public StripMPAlignmentInput(String outfile,String type) {
+        super(outfile,type);
+        
+        makeAlignmentPlots();
+
+    }
+
+    @Override
+    public void setResLimits(int l,int d, double low,double high) {
+       
+    }
+
+    public void setResLimits(int s, int l,int d, double low,double high) {
+       
+    }
+
+    
+    
+    public void PrintResidualsAndDerivatives(Track track, int itrack) {
+        
+        SeedTrack st = (SeedTrack) track;
+        SeedCandidate seed = st.getSeedCandidate();
+        Map<HelicalTrackHit, MultipleScatter> msmap = seed.getMSMap();
+        _trk = seed.getHelix();
+        List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+        String half = hitsOnTrack.get(0).getPosition()[2]>0 ? "top" : "bottom";
+        this.addMilleInputLine(String.format("TRACK %s (%d)\n",half,itrack));
+        aida.cloud1D("Track Chi2 "+ half).fill(track.getChi2());
+        aida.cloud1D("Track Chi2ndf "+ half).fill(track.getChi2()/track.getNDF());
+        if(_DEBUG) System.out.printf("%s: track %d (chi2=%.2f ndf=%d) has %d hits\n",this.getClass().getSimpleName(),itrack,track.getChi2(),track.getNDF(),hitsOnTrack.size());
+        for (TrackerHit hit : hitsOnTrack) {
+            
+            HelicalTrackHit htc = (HelicalTrackHit) hit;
+            
+            if(!(htc instanceof HelicalTrackCross)) {
+                if(_DEBUG) System.out.println(this.getClass().getSimpleName() + ": this hit is not a cross");
+                continue;
+            }
+            
+            // Update the hit position to be sure it's the latest
+            HelicalTrackCross cross = (HelicalTrackCross) htc;
+            cross.setTrackDirection(_trk);
+
+            // Get the MS errors
+            double msdrphi = msmap.get(htc).drphi();
+            double msdz = msmap.get(htc).dz();
+            // Find the strip clusters for this 3D hit 
+            List<HelicalTrackStrip> clusterlist = cross.getStrips();
+
+            if(_DEBUG) {
+                System.out.printf("%s: This hit has %d clusters msdrphi=%.4f msdz=%.4f\n",this.getClass().getSimpleName(),clusterlist.size(),msdrphi,msdz);
+            }
+            for (HelicalTrackStrip cl : clusterlist) {
+                    CalculateResidual(cl, msdrphi, msdz);
+                    CalculateLocalDerivatives(cl);
+                    CalculateGlobalDerivatives(cl);
+                    PrintStripResiduals(cl);
+
+            }
+
+        }
+        
+        if(itrack%50==0) this.updatePlots();
+    }
+
+    
+    private void CalculateLocalDerivatives(HelicalTrackStrip strip) {
+        double xint = strip.origin().x();
+        BasicMatrix dfdqGlobalOld = _oldAlignUtils.calculateLocalHelixDerivatives(_trk, xint);
+        BasicMatrix dfdqGlobal = _alignUtils.calculateLocalHelixDerivatives(_trk, xint);
+        BasicMatrix dfdqGlobalNum = this._numDerivatives.calculateLocalHelixDerivatives(_trk, xint);
+        Hep3Matrix trkToStrip = trackerHitUtil.getTrackToStripRotation(strip);
+        _dfdq = (BasicMatrix) MatrixOp.mult(trkToStrip, dfdqGlobal);
+        
+        if (_DEBUG) {
+            
+            //get track parameters.
+            double d0 = _trk.dca();
+            double z0 = _trk.z0();
+            double slope = _trk.slope();
+            double phi0 = _trk.phi0();
+            double R = _trk.R();
+            double s = HelixUtils.PathToXPlane(_trk, xint, 0, 0).get(0);
+            double phi = -s/R + phi0;
+            double[] trackpars = {d0, z0, slope, phi0, R, s, xint};
+            System.out.printf("%s: --- CalculateLocalDerivatives Result --- \n",this.getClass().getSimpleName());
+            System.out.printf("%s: Strip Origin %s \n",this.getClass().getSimpleName(),strip.origin().toString());
+            System.out.printf("%s: %10s%10s%10s%10s%10s%10s%10s\n",this.getClass().getSimpleName(),"d0","z0","slope","phi0","R", "xint", "s");
+            System.out.printf("%s: %10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f\n",this.getClass().getSimpleName(), d0, z0, slope, phi0, R,xint,s);
+            System.out.printf("%s: Local derivatives:\n",this.getClass().getSimpleName());
+            System.out.printf("%s\n",dfdqGlobal.toString());
+            System.out.printf("%s: Numerical Local derivatives:\n",this.getClass().getSimpleName());
+            System.out.printf("%s\n",dfdqGlobalNum.toString());
+            System.out.printf("%s: OLD Local derivatives:\n",this.getClass().getSimpleName());
+            System.out.printf("%s\n",dfdqGlobalOld.toString());
+        }
+    
+    }
+    
+   
+    
+    private void CalculateGlobalDerivatives(HelicalTrackStrip strip) {
+        
+        /*
+         * Residual in local sensor frame is defined as r = m_a-p
+         * with m_a as the alignment corrected position (u_a,v_a,w_a) 
+         * and p is the predicted hit position in the local sensor frame
+         * 
+         * Calcualte the derivative of dr/da where
+         * a=(delta_u,delta_v,delta_w,alpha,beta,gamma) 
+         * are the alingment paramerers in the local sensor frame
+         * 
+         * Factorize: dr/da=dr/dm_a*dm_a/da
+         * 
+         * Start with dr/dma
+         */
+        
+        //Find interception with the plane the hit belongs to i.e. the predicted hit position 
+        Hep3Vector p = TrackUtils.getHelixPlaneIntercept(_trk, strip, Math.abs(this._bfield.z()));
+        double pathLengthToInterception = HelixUtils.PathToXPlane(_trk, p.x(),0,0).get(0);
+        //Find the unit vector of the track direction
+        TrackDirection trkdir = HelixUtils.CalculateTrackDirection(_trk, pathLengthToInterception);
+        Hep3Vector t_TRACK = trkdir.Direction();
+        Hep3Vector n_TRACK = strip.w();
+        Hep3Matrix T = trackerHitUtil.getTrackToStripRotation(strip);
+        Hep3Vector t = VecOp.mult(T, t_TRACK);
+        Hep3Vector n = VecOp.mult(T, n_TRACK);
+        
+       
+        /*
+         * Measured position, either
+         * 1. use the measured hit position on the plane w.r.t. an origin that is centered on the sensor plane.
+         * 2. use the predicted hit position in order to get a better measure of the unmeasured directions
+         */
+        double umeas,vmeas,wmeas;
+        boolean useMeasuredHitPosition = false;
+        if(useMeasuredHitPosition) {
+            if(_DEBUG) System.out.printf("%s: using measured hit position as \"m\"\n",this.getClass().getSimpleName());
+            umeas = strip.umeas();
+            vmeas = 0.; //the un-measured (along the strip) is set to zero
+            wmeas = 0.; // the hit is on the surface of the plane
+        } else {
+            if(_DEBUG) System.out.printf("%s: using predicted hit position at %s  as \"m\"\n",this.getClass().getSimpleName(),p.toString());
+            Hep3Vector p_local = VecOp.sub(p,strip.origin()); //subtract the center of the sensor in tracking frame
+            if(_DEBUG) System.out.printf("%s: vector between origin of sensor and predicted position in tracking frame: %s \n",this.getClass().getSimpleName(),p_local.toString());
+            p_local = VecOp.mult(T, p_local); //rotate to local frame
+            if(_DEBUG) System.out.printf("%s: predicted position in local frame: %s \n",this.getClass().getSimpleName(),p_local.toString());
+            umeas = p_local.x();
+            vmeas = p_local.y(); 
+            wmeas = p_local.z();
+            Hep3Vector res_tmp = new BasicHep3Vector(strip.umeas()-p_local.x(),0.-p_local.y(),0.-p_local.z());
+            if(_DEBUG) System.out.printf("%s: cross check residuals %s\n",this.getClass().getSimpleName(),res_tmp.toString());
+            
+        }
+        
+        /*
+         * Calculate the dma_da 
+         */
+        
+        BasicMatrix dma_da = new BasicMatrix(3,6);
+        //dma_ddeltau
+        dma_da.setElement(0, 0, 1);
+        dma_da.setElement(1, 0, 0);
+        dma_da.setElement(2, 0, 0);
+        //dma_ddeltav
+        dma_da.setElement(0, 1, 0);
+        dma_da.setElement(1, 1, 1);
+        dma_da.setElement(2, 1, 0);
+        //dma_ddeltau
+        dma_da.setElement(0, 2, 0);
+        dma_da.setElement(1, 2, 0);
+        dma_da.setElement(2, 2, 1);
+        //dma_dalpha
+        dma_da.setElement(0, 3, 0);
+        dma_da.setElement(1, 3, wmeas);
+        dma_da.setElement(2, 3, -vmeas);
+        //dma_dbeta
+        dma_da.setElement(0, 4, -wmeas);
+        dma_da.setElement(1, 4, 0);
+        dma_da.setElement(2, 4, umeas);
+        //dma_dgamma
+        dma_da.setElement(0, 5, vmeas);
+        dma_da.setElement(1, 5, -umeas);
+        dma_da.setElement(2, 5, 0);
+        
+        
+        
+         /*
+         * Calculate the dr_dma 
+         * e_ij = delta(i,j) - t_i*t_j/(t*n)
+         */
+        BasicMatrix dr_dma = new BasicMatrix(3,3);
+        double tn = VecOp.dot(t, n);
+        double[] t_arr = t.v();
+        double[] n_arr = n.v();
+        for(int i=0;i<3;++i) {
+            for(int j=0;j<3;++j) {
+                double delta_ij = i==j ? 1 : 0;
+                double elem = delta_ij - t_arr[i]*n_arr[j]/tn;
+                dr_dma.setElement(i, j, elem);
+            }
+        }
+        
+        
+        
+        /*
+         * Calculate the dr/da=dr/dma*dma/da
+         */
+        
+        BasicMatrix dr_da = (BasicMatrix) MatrixOp.mult(dr_dma, dma_da);
+        
+   
+        int layer = strip.layer();
+        int side = SvtUtils.getInstance().isTopLayer((SiSensor) ((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement()) ? 10000 : 20000;
+
+        
+        if(_DEBUG) {
+            double phi = -pathLengthToInterception/_trk.R()+_trk.phi0();
+            System.out.printf("%s: --- Calculate SIMPLE global derivatives ---\n",this.getClass().getSimpleName());
+            System.out.printf("%s: Side %d, layer %d, strip origin %s\n",this.getClass().getSimpleName(),side,layer,strip.origin().toString());
+            System.out.printf("%s: %10s%10s%10s%10s%10s%10s%10s%10s%10s\n",this.getClass().getSimpleName(),"d0","z0","slope","phi0","R","xint","phi", "xint","s");
+            System.out.printf("%s: %10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f\n",this.getClass().getSimpleName(), _trk.dca(), _trk.z0(), _trk.slope(), _trk.phi0(), _trk.R(),p.x(),phi,p.x(),pathLengthToInterception);
+            System.out.printf("%s: Track direction t = %s\n",this.getClass().getSimpleName(),t.toString());
+            System.out.printf("%s: Plane normal    n = %s\n",this.getClass().getSimpleName(),n.toString());
+            System.out.printf("%s: m=(umeas,vmeas,wmeas)=(%.3f,%.3f,%.3f)\n",this.getClass().getSimpleName(),umeas,vmeas,wmeas);
+            System.out.printf("dma_da=\n%s\ndr_dma=\n%s\ndr_da=\n%s\n",dma_da.toString(),dr_dma.toString(),dr_da.toString());
+            
+        }
+   
+        
+        
+        
+        /*
+         * Prepare the derivatives for output
+         */
+        
+        
+        
+        _glp.clear();
+        
+        GlobalParameter gp_tu = new GlobalParameter("Translation in u",side,layer,1000,100,true);
+        Hep3Vector mat = new BasicHep3Vector(dr_da.e(0, 0),dr_da.e(1, 0),dr_da.e(2, 0));
+        gp_tu.setDfDp(mat);
+        _glp.add(gp_tu);
+        if (_DEBUG) {
+            gp_tu.print();
+        }
+
+        GlobalParameter gp_tv = new GlobalParameter("Translation in v",side,layer,1000,200,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 1),dr_da.e(1, 1),dr_da.e(2, 1));
+        gp_tv.setDfDp(mat);
+        _glp.add(gp_tv);
+        if (_DEBUG) {
+            gp_tv.print();
+        }
+
+        
+        GlobalParameter gp_tw = new GlobalParameter("Translation in w",side,layer,1000,300,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 2),dr_da.e(1, 2),dr_da.e(2, 2));
+        gp_tw.setDfDp(mat);
+        _glp.add(gp_tw);
+        if (_DEBUG) {
+            gp_tw.print();
+        }
+        
+        GlobalParameter gp_ta = new GlobalParameter("Rotation alpha",side,layer,2000,100,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 3),dr_da.e(1, 3),dr_da.e(2, 3));
+        gp_ta.setDfDp(mat);
+        _glp.add(gp_ta);
+        if (_DEBUG) {
+            gp_ta.print();
+        }
+
+        GlobalParameter gp_tb = new GlobalParameter("Rotation beta",side,layer,2000,200,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 4),dr_da.e(1, 4),dr_da.e(2, 4));
+        gp_tb.setDfDp(mat);
+        _glp.add(gp_tb);
+        if (_DEBUG) {
+            gp_tb.print();
+        }
+        
+        GlobalParameter gp_tg = new GlobalParameter("Rotation gamma",side,layer,2000,300,true);
+        mat = new BasicHep3Vector(dr_da.e(0, 5),dr_da.e(1, 5),dr_da.e(2, 5));
+        gp_tg.setDfDp(mat);
+        _glp.add(gp_tg);
+        if (_DEBUG) {
+            gp_tg.print();
+        }
+
+        
+
+        
+        
+    }
+
+    
+   
+    
+    
+    
+    private void CalculateResidual(HelicalTrackStrip strip, double msdrdphi, double msdz) {
+        if(_DEBUG) System.out.printf("%s: --- CalculateResidual ---\n",this.getClass().getSimpleName());
+        
+        double bfield = Math.abs(this._bfield.z());
+
+        Map<String,Double> res_local = TrackUtils.calculateLocalTrackHitResiduals(_trk, strip, msdrdphi, msdz, bfield);
+        
+        _resid[0] = res_local.get("ures");
+        _resid[1] = res_local.get("vres");
+        _resid[2] = res_local.get("wres");
+        _error[0] = res_local.get("ureserr");
+        _error[1] = res_local.get("vreserr");
+        _error[2] = res_local.get("wreserr");
+        
+        double vdiffy = res_local.get("vdiffTrky");
+        String side = SvtUtils.getInstance().isTopLayer((SiSensor)((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement()) ? "top" : "bottom";
+        //Fill residuals vs distrance from center of plane in the v directions
+        aida.profile1D("res_u_vs_ydiff_layer_" + strip.layer() + "_" + side).fill(vdiffy,_resid[0]);
+
+        
+        /*
+        Hep3Vector u = strip.u();
+        Hep3Vector v = strip.v();
+        Hep3Vector w = strip.w();
+        Hep3Vector eta = VecOp.cross(u,v);
+        Hep3Vector corigin = strip.origin();
+        String side = SvtUtils.getInstance().isTopLayer((SiSensor)((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement()) ? "top" : "bottom";
+
+        
+//        if(_DEBUG) {
+//            System.out.printf("%s: Finding interception point for residual calculation (B=%s)\n",this.getClass().getSimpleName(),this._bfield.toString());
+//            Hep3Vector trkpos_wrong= TrackUtils.helixPositionAtPlaneApprox(_trk, strip); 
+//            System.out.printf("%s: using wrong method xint_wrong=%.3f s_wrong=%.3f -> trkpos_wrong=%s\n",this.getClass().getSimpleName(),trkpos_wrong.toString());
+//        }
+        //Find interception with plane that the strips belongs to
+        Hep3Vector trkpos = TrackUtils.getHelixPlaneIntercept(_trk, strip, bfield);
+        
+        if(_DEBUG) {
+            System.out.printf("%s: found interception point at %s \n",this.getClass().getSimpleName(),trkpos.toString());
+        }
+        
+
+        if(Double.isNaN(trkpos.x()) || Double.isNaN(trkpos.y()) || Double.isNaN(trkpos.z())) {
+            System.out.printf("%s: failed to get interception point (%s) \n",this.getClass().getSimpleName(),trkpos.toString());
+            System.out.printf("%s: track params\n%s\n",this.getClass().getSimpleName(),_trk.toString());
+            System.out.printf("%s: track pT=%.3f chi2=[%.3f][%.3f] \n",this.getClass().getSimpleName(),_trk.pT(bfield),_trk.chisq()[0],_trk.chisq()[1]);
+            trkpos = TrackUtils.getHelixPlaneIntercept(_trk, strip, bfield);
+            System.exit(1);
+        }
+        
+        
+        
+        double xint = trkpos.x();
+        double phi0 = _trk.phi0();
+        double R = _trk.R();
+        double s = HelixUtils.PathToXPlane(_trk, xint, 0, 0).get(0);
+        double phi = -s/R + phi0;
+        
+        
+        
+        Hep3Vector mserr = new BasicHep3Vector(msdrdphi * Math.sin(phi), msdrdphi * Math.sin(phi), msdz);
+        Hep3Vector vdiffTrk = VecOp.sub(trkpos, corigin);
+        Hep3Matrix trkToStrip = this.trackerHitUtil.getTrackToStripRotation(strip);
+        Hep3Vector vdiff = VecOp.mult(trkToStrip, vdiffTrk);
+        
+        
+        
+        double umc = vdiff.x();
+        double vmc = vdiff.y();
+        double wmc = vdiff.z();
+        double umeas = strip.umeas();
+        double uError = strip.du();
+        double msuError = VecOp.dot(mserr, u);
+        double vmeas = 0;
+        double vError = (strip.vmax() - strip.vmin()) / Math.sqrt(12);
+        double wmeas = 0;
+        double wError = 10.0/Math.sqrt(12); //0.001;
+        _resid[0] = umeas - umc;
+        _error[0] = _includeMS ? Math.sqrt(uError * uError + msuError * msuError) : uError;
+        _resid[1] = vmeas - vmc;
+        _error[1] = vError;
+        _resid[2] = wmeas - wmc;
+        _error[2] = wError;
+
+        if(res_local.get("ures")!=_resid[0] || res_local.get("vres")!=_resid[1] || res_local.get("wres")!=_resid[2] || 
+                res_local.get("ureserr")!=_error[0] || res_local.get("vreserr")!=_error[1] || res_local.get("wreserr")!=_error[2] ) {
+            System.out.printf("%s: resu is different? %f vs %f \n",res_local.get("ures"),_resid[0]);
+            System.out.printf("%s: resv is different? %f vs %f \n",res_local.get("vres"),_resid[1]);
+            System.out.printf("%s: resw is different? %f vs %f \n",res_local.get("wres"),_resid[2]);
+            System.exit(1);
+        }
+        if (_DEBUG) {
+            System.out.printf("%s: CalculateResidual Result ----\n",this.getClass().getSimpleName());
+            System.out.printf("%s: Strip layer %d Origin: %s\n",this.getClass().getSimpleName(),strip.layer(),corigin.toString());
+            System.out.printf("%s: Position on the track (tracking coordinates) at the strip: %s\n",this.getClass().getSimpleName(),trkpos.toString());
+            System.out.printf("%s: vdiffTrk %s\n",this.getClass().getSimpleName(),vdiffTrk.toString());
+            System.out.printf("%s: vdiff %s\n",this.getClass().getSimpleName(),vdiff.toString());
+            System.out.printf("%s: u %s\n",this.getClass().getSimpleName(),u.toString());
+            System.out.printf("%s: umeas = %.4f  umc = %.4f\n",this.getClass().getSimpleName(),umeas,umc);
+            System.out.printf("%s: udiff = %.4f +/- %.4f  ( uError=%.4f , msuError=%.4f\n",this.getClass().getSimpleName(),_resid[0],_error[0],uError,msuError);
+            System.out.printf("%s: MS: drdphi=%.4f, dz=%.4f\n",this.getClass().getSimpleName(),msdrdphi,msdz);
+            System.out.printf("%s: MS: phi=%.4f => msvec=%s\n",this.getClass().getSimpleName(),phi,mserr.toString());
+            System.out.printf("%s: MS: msuError = %.4f (msvec*u = %s * %s\n",this.getClass().getSimpleName(),msuError,mserr.toString(),u.toString());          
+        }
+        */
+
+        
+
+    }
+    
+    
+  
+    
+    
+   
+    
+    
+
+    private void PrintStripResiduals(HelicalTrackStrip strip) {
+        
+        String side = SvtUtils.getInstance().isTopLayer((SiSensor) ((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement()) ? "top" : "bottom";        
+        
+        if (_DEBUG) {
+            System.out.printf("%s: --- Alignment Results for this Strip ---\n",this.getClass().getSimpleName());            
+            String sensor_type = SvtUtils.getInstance().isAxial((SiSensor) ((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement()) ? "axial" : "stereo";
+            System.out.printf("%s: Strip layer %4d is %s in %s  at origin %s\n",this.getClass().getSimpleName(), strip.layer(),sensor_type, side, strip.origin().toString());
+            System.out.printf("%s: u=%s v=%s w=%s\n",this.getClass().getSimpleName(), strip.u().toString(),strip.v().toString(),strip.w().toString());
+            System.out.printf("%s: Residuals (u,v,w) : %5.5e %5.5e %5.5e\n",this.getClass().getSimpleName(), _resid[0], _resid[1], _resid[2]);
+            System.out.printf("%s: Errors (u,v,w)    : %5.5e %5.5e %5.5e\n",this.getClass().getSimpleName(), _error[0], _error[1], _error[2]);
+            String[] q = {"d0", "z0", "slope", "phi0", "R"};
+            System.out.printf("%s: track parameter derivatives:\n",this.getClass().getSimpleName());
+            for (int i = 0; i < _nTrackParameters; i++)
+                System.out.printf("%s: %s     %5.5e %5.5e %5.5e\n",this.getClass().getSimpleName(), q[i], _dfdq.e(0, i), _dfdq.e(1, i), _dfdq.e(2, i));
+            System.out.printf("%s: Global parameter derivatives\n",this.getClass().getSimpleName());
+            for (GlobalParameter gl : _glp) System.out.printf("%s: %s  %8.3e %5.8e %8.3e   %5d  \"%10s\"\n",this.getClass().getSimpleName(), "", gl.dfdp(0), gl.dfdp(1), gl.dfdp(2), gl.getLabel(),gl.getName());
+            System.out.printf("%s: --- END Alignment Results for this Strip ---\n",this.getClass().getSimpleName());
+        }
+        
+        
+        
+        this.addMilleInputLine(String.format("%d\n", strip.layer()));
+        
+        
+        List<String> direction = new ArrayList<String>(Arrays.asList("u")); //use only u direction!
+        
+        int s;
+        for(int d=0;d<direction.size();++d){
+            side = "bottom";
+            s = 1;
+            if( strip.origin().z()>0) {
+                side = "top";
+                s = 0;
+            }   
+            
+            
+            //if(!isAllowedResidual(s,strip.layer(),j,_residirection.get(d))) {
+            //    if(_DEBUG) System.out.println("Layer " + strip.layer() + " in " + direction.get(d) + " res " + _residirection.get(d) + " +- " + _error[d] + " was outside allowed range");
+            //    continue;
+            //}
+
+            this.addMilleInputLine(String.format("res_%s %5.5e %5.5e \n", direction.get(d), _resid[d], _error[d])); 
+            for (int i = 0; i < _nTrackParameters; i++) {
+                this.addMilleInputLine(String.format("lc_%s %5.5e \n", direction.get(d), _dfdq.e(d, i)));
+            }
+            for (GlobalParameter gl: _glp) {
+                if(gl.active()){
+                    this.addMilleInputLine(String.format("gl_%s %5.5e %5d\n", direction.get(d), gl.dfdp(d), gl.getLabel()));
+                    //x-check that side is correct
+                    int lbl = gl.getLabel();
+                    Double df = Math.floor(lbl/10000);
+                    int iside = (df.intValue() % 10) - 1;
+                    //System.out.println("track is on " + s + " gl param is " + lbl + "(" + df + ","+iside+")"  );
+                    if(iside!=s) {
+                        System.out.println("WARNING track is on " + s + " while gl param is " + lbl + "(" + df + ")"  );
+                        System.exit(1);
+                    }
+                    
+                }
+            }
+            if (_DEBUG) System.out.println(this.getClass().getSimpleName() + ": filling ures with " + _resid[d]);
+            aida.histogram1D("res_"+direction.get(d)+"_layer" + strip.layer() + "_" + side).fill(_resid[d]);    
+            aida.histogram1D("reserr_"+direction.get(d)+"_layer" + strip.layer() + "_" + side).fill(_error[d]);    
+            aida.histogram1D("respull_"+direction.get(d)+"_layer" + strip.layer() + "_" + side).fill(_resid[d]/_error[d]);    
+            aida.histogram2D("respull_slope_"+direction.get(d)+"_layer" + strip.layer() + "_" + side).fill(_trk.slope(),_resid[d]/_error[d]);    
+
+        }
+    }
+
+    
+
+   
+
+    
+    @Override
+    protected void makeAlignmentPlots() {
+    
+        
+        
+        aida.tree().cd("/");
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("Residuals");
+        plotterFrameSummary = new AIDAFrame();
+        plotterFrameSummary.setTitle("Summary");
+              
+        List<String> sides = new ArrayList<String>(Arrays.asList("top","bottom"));
+
+        IPlotter plotter_chi2 = af.createPlotterFactory().create();
+        plotter_chi2.createRegions(2,2);
+        plotter_chi2.setTitle("Track Chi2");
+        plotterFrame.addPlotter(plotter_chi2);
+        ICloud1D hchi2_top = aida.cloud1D("Track Chi2 top");
+        ICloud1D hchi2_bot = aida.cloud1D("Track Chi2 bottom");
+        ICloud1D hchi2ndf_top = aida.cloud1D("Track Chi2ndf top");
+        ICloud1D hchi2ndf_bot = aida.cloud1D("Track Chi2ndf bottom");
+        plotter_chi2.region(0).plot(hchi2_top);
+        plotter_chi2.region(1).plot(hchi2_bot);
+        plotter_chi2.region(2).plot(hchi2ndf_top);
+        plotter_chi2.region(3).plot(hchi2ndf_bot);
+        
+        
+        List<String> direction = "MODULE".equals(this._type) ? new ArrayList<String>(Arrays.asList("x","y","z")) : new ArrayList<String>(Arrays.asList("u"));
+        
+        
+        
+        double xbins_u_res[][] = {
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01},
+//            {-0.01,0.01}
+                {-0.15,0.15},
+                {-0.4,0.4},
+                {-0.7,0.7},
+                {-0.5,0.5},
+                {-0.5,0.5},
+                {-0.5,0.5},
+                {-2,2},
+                {-2,2},
+                {-2,2},
+                {-2,2}            
+        };
+        double xbins_u_reserr[][] = {
+                {0,0.04},
+                {0,0.04},
+                {0,0.5},
+                {0,0.5},
+                {0,0.7},
+                {0,0.7},
+                {0,1.2},
+                {0,1.2},
+                {0,1.5},
+                {0,1.5}
+        };
+        double xbins_u_respull[][] = {
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5},
+                {-5,5}
+        };
+        
+        for (int d=0;d<direction.size();++d) { 
+
+            for (int s=0;s<2;++s) { 
+        //    if(iSide==1) continue;
+                IPlotter plotter_res = af.createPlotterFactory().create();
+                plotter_res.createRegions(5,2,0);
+                plotter_res.setTitle("res_" + direction.get(d) + " " + sides.get(s));
+                IPlotter plotter_reserr = af.createPlotterFactory().create();
+                plotter_reserr.createRegions(5,2,0);
+                plotter_reserr.setTitle("reserr_" + direction.get(d) + " " + sides.get(s));
+                IPlotter plotter_respull = af.createPlotterFactory().create();
+                plotter_respull.createRegions(5,2,0);
+                plotter_respull.setTitle("respull_" + direction.get(d) + " " + sides.get(s));
+                IPlotter plotter_respull_slope = af.createPlotterFactory().create();
+                plotter_respull_slope.createRegions(5,2,0);
+                plotter_respull_slope.setTitle("respull_slope_" + direction.get(d) + " " + sides.get(s));
+
+                for (int iLayer=1;iLayer<11;++iLayer) {
+                    
+                    IHistogram h = aida.histogram1D("res_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) , 50, xbins_u_res[iLayer-1][0], xbins_u_res[iLayer-1][1]);                        
+                    IHistogram h1 = aida.histogram1D("reserr_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) , 50, xbins_u_reserr[iLayer-1][0], xbins_u_reserr[iLayer-1][1]);            
+                    IHistogram h2 = aida.histogram1D("respull_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) , 50, xbins_u_respull[iLayer-1][0], xbins_u_respull[iLayer-1][1]);                        
+
+                    IHistogram hslope;
+                    if(sides.get(s)=="top") hslope = aida.histogram2D("respull_slope_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) ,50, 0 , 0.1, 50, xbins_u_respull[iLayer-1][0], xbins_u_respull[iLayer-1][1]);                        
+                    else hslope = aida.histogram2D("respull_slope_"+direction.get(d)+"_layer" + (iLayer) + "_" + sides.get(s) ,50, -0.1 , 0, 50, xbins_u_respull[iLayer-1][0], xbins_u_respull[iLayer-1][1]);                        
+                    
+                        
+                    int region = (iLayer-1);//*2+iSide;
+
+                    plotter_res.region(region).plot(h);
+                    plotter_reserr.region(region).plot(h1);
+                    plotter_respull.region(region).plot(h2);
+                    plotter_respull_slope.region(region).plot(hslope);
+
+                    ((PlotterRegion) plotter_res.region(region)).getPlot().setAllowUserInteraction(true);
+                    ((PlotterRegion) plotter_res.region(region)).getPlot().setAllowPopupMenus(true);
+                    ((PlotterRegion) plotter_reserr.region(region)).getPlot().setAllowUserInteraction(true);
+                    ((PlotterRegion) plotter_reserr.region(region)).getPlot().setAllowPopupMenus(true);
+                    ((PlotterRegion) plotter_respull.region(region)).getPlot().setAllowUserInteraction(true);
+                    ((PlotterRegion) plotter_respull.region(region)).getPlot().setAllowPopupMenus(true);
+                    ((PlotterRegion) plotter_respull_slope.region(region)).getPlot().setAllowUserInteraction(true);
+                    ((PlotterRegion) plotter_respull_slope.region(region)).getPlot().setAllowPopupMenus(true);
+                    plotter_respull_slope.style().dataStyle().fillStyle().setParameter("colorMapScheme","rainbow");
+                    ((PlotterRegion) plotter_respull_slope.region(region)).getPlot().setAllowPopupMenus(true);
+
+                   
+                } 
+
+                //plotter_res.show();
+                plotterFrame.addPlotter(plotter_res);
+                plotterFrame.addPlotter(plotter_reserr);
+                plotterFrame.addPlotter(plotter_respull);
+                plotterFrame.addPlotter(plotter_respull_slope);
+            }
+        
+            
+        
+           
+        }
+        
+        
+         
+         
+        IPlotter plotter_prf = af.createPlotterFactory().create();
+        plotter_prf.createRegions(1,2,0);
+        plotter_prf.setTitle("<Residuals>");
+        IDataPointSetFactory dpsf = aida.analysisFactory().createDataPointSetFactory(null);
+        dps_t = dpsf.create("dps_t", "Mean of u residuals top",2);
+        plotter_prf.region(0).plot(dps_t);
+        dps_b = dpsf.create("dps_b", "Mean of u residuals bottom",2);
+        plotter_prf.region(0).plot(dps_b);
+        
+        dps_pull_t = dpsf.create("dps_pull_t", "Mean of u pulls top",2);
+        plotter_prf.region(1).plot(dps_pull_t);
+        dps_pull_b = dpsf.create("dps_pull_b", "Mean of u pulls bottom",2);
+        plotter_prf.region(1).plot(dps_pull_b);
+
+        for(int region=0;region<2;++region) {
+            ((PlotterRegion) plotter_prf.region(region)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) plotter_prf.region(region)).getPlot().setAllowPopupMenus(true);
+        }
+        
+        plotterFrameSummary.addPlotter(plotter_prf);
+        
+        
+        plotter_resuydiff_t = af.createPlotterFactory().create();
+        plotter_resuydiff_t.createRegions(5,2,0);
+        plotter_resuydiff_t.setTitle("res u vs ydiff top");      
+        plotter_resuydiff_b = af.createPlotterFactory().create();
+        plotter_resuydiff_b.createRegions(5,2,0);
+        plotter_resuydiff_b.setTitle("res u vs ydiff bot");      
+        //plotter_resuydiff_t_b.createRegions(5,2,0);
+        //plotter_resuydiff_b.setTitle("distr: res u vs ydiff");      
+        for(int iLayer=1;iLayer<11;++iLayer) {
+            IProfile1D prf_t = aida.profile1D("res_u_vs_ydiff_layer_"+iLayer+"_top",10,-50,50);
+            IProfile1D prf_b = aida.profile1D("res_u_vs_ydiff_layer_"+iLayer+"_bottom",10,-50,50);          
+            plotter_resuydiff_t.region(iLayer-1).plot(prf_t);
+            plotter_resuydiff_b.region(iLayer-1).plot(prf_b);
+            ((PlotterRegion) plotter_resuydiff_t.region(iLayer-1)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) plotter_resuydiff_t.region(iLayer-1)).getPlot().setAllowPopupMenus(true);
+            ((PlotterRegion) plotter_resuydiff_b.region(iLayer-1)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) plotter_resuydiff_b.region(iLayer-1)).getPlot().setAllowPopupMenus(true);
+        }
+        
+        plotterFrameSummary.addPlotter(plotter_resuydiff_t);
+        plotterFrameSummary.addPlotter(plotter_resuydiff_b);
+        
+        
+        plotterFrame.pack();
+        plotterFrame.setVisible(!hideFrame);
+        plotterFrameSummary.pack();
+        plotterFrameSummary.setVisible(!hideFrame);
+        
+    
+    }
+    
+    
+    @Override
+    public void updatePlots() {
+        dps_t.clear();
+        dps_b.clear();
+        dps_pull_t.clear();
+        dps_pull_b.clear();
+        
+        final int nLayers = 10;
+        final List<String> direction = this._type.equals("MODULE") ? new ArrayList<String>(Arrays.asList("x","y","z")) : new ArrayList<String>(Arrays.asList("u"));
+        for(int i=1;i<nLayers+1;++i) {
+            
+            for(String d : direction) {
+
+                double mean = aida.histogram1D("res_"+d+"_layer"+i+"_top").mean();
+                double stddev = aida.histogram1D("res_"+d+"_layer"+i+"_top").rms();
+                double N =  aida.histogram1D("res_"+d+"_layer"+i+"_top").entries();
+                double error = N >0 ? stddev/Math.sqrt(N) : 0; 
+                dps_t.addPoint();
+                dps_t.point(i-1).coordinate(1).setValue(mean);
+                dps_t.point(i-1).coordinate(1).setErrorPlus(error);
+                dps_t.point(i-1).coordinate(0).setValue(i);
+                dps_t.point(i-1).coordinate(0).setErrorPlus(0);
+
+                mean = aida.histogram1D("res_"+d+"_layer"+i+"_bottom").mean();
+                stddev = aida.histogram1D("res_"+d+"_layer"+i+"_bottom").rms();
+                N =  aida.histogram1D("res_"+d+"_layer"+i+"_bottom").entries();
+                error = N >0 ? stddev/Math.sqrt(N) : 0; 
+                dps_b.addPoint();
+                dps_b.point(i-1).coordinate(1).setValue(mean);
+                dps_b.point(i-1).coordinate(1).setErrorPlus(error);
+                dps_b.point(i-1).coordinate(0).setValue(i);
+                dps_b.point(i-1).coordinate(0).setErrorPlus(0);
+
+                mean = aida.histogram1D("respull_"+d+"_layer"+i+"_top").mean();
+                stddev = aida.histogram1D("respull_"+d+"_layer"+i+"_top").rms();
+                N =  aida.histogram1D("respull_"+d+"_layer"+i+"_top").entries();
+                error = N >0 ? stddev/Math.sqrt(N) : 0; 
+                dps_pull_t.addPoint();
+                dps_pull_t.point(i-1).coordinate(1).setValue(mean);
+                dps_pull_t.point(i-1).coordinate(1).setErrorPlus(error);
+                dps_pull_t.point(i-1).coordinate(0).setValue(i);
+                dps_pull_t.point(i-1).coordinate(0).setErrorPlus(0);
+
+                mean = aida.histogram1D("respull_"+d+"_layer"+i+"_bottom").mean();
+                stddev = aida.histogram1D("respull_"+d+"_layer"+i+"_bottom").rms();
+                N =  aida.histogram1D("respull_"+d+"_layer"+i+"_bottom").entries();
+                error = N >0 ? stddev/Math.sqrt(N) : 0; 
+                dps_pull_b.addPoint();
+                dps_pull_b.point(i-1).coordinate(1).setValue(mean);
+                dps_pull_b.point(i-1).coordinate(1).setErrorPlus(error);
+                dps_pull_b.point(i-1).coordinate(0).setValue(i);
+                dps_pull_b.point(i-1).coordinate(0).setErrorPlus(0);
+                
+            }
+        }
+        
+         
+         
+    }
+
+    
+    
+    
+    
+    private void CalculateGlobalDerivativesWRONG(HelicalTrackStrip strip) {
+       
+        //Find interception with plane that the strips belongs to
+        Hep3Vector x_vec = TrackUtils.getHelixPlaneIntercept(_trk, strip, Math.abs(this._bfield.z()));
+        
+        if(Double.isNaN(x_vec.x())) {
+            System.out.printf("%s: error this trkpos is wrong %s\n",this.getClass().getSimpleName(),x_vec.toString());
+            System.out.printf("%s: origin %s trk \n%s\n",this.getClass().getSimpleName(),strip.origin(),_trk.toString());
+            x_vec = TrackUtils.getHelixPlaneIntercept(_trk, strip, Math.abs(this._bfield.z()));
+            System.exit(1);
+        }
+        double slope = _trk.slope();
+        double xr = 0.0;
+        double yr = 0.0;
+        double d0 = _trk.dca();
+        double phi0 = _trk.phi0();
+        double R = _trk.R();
+        double z0 = _trk.z0();
+        double s = HelixUtils.PathToXPlane(_trk, x_vec.x(), 0, 0).get(0);
+        double phi = -s/R + phi0;
+        double umeas = strip.umeas();
+        Hep3Vector corigin = strip.origin();
+        double vmeas = corigin.y(); //THis is wrong
+        int layer = strip.layer();
+        int side = SvtUtils.getInstance().isTopLayer((SiSensor) ((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement()) ? 10000 : 20000;
+
+        if(_DEBUG) {
+            System.out.printf("%s: --- Calculate global derivatives ---\n",this.getClass().getSimpleName());
+            System.out.printf("%s: Side %d, layer %d, strip origin %s\n",this.getClass().getSimpleName(),side,layer,corigin.toString());
+            System.out.printf("%s: %10s%10s%10s%10s%10s%10s%10s%10s%10s\n",this.getClass().getSimpleName(),"d0","z0","slope","phi0","R","xint","phi", "xint","s");
+            System.out.printf("%s: %10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f\n",this.getClass().getSimpleName(), d0, z0, slope, phi0, R,x_vec.x(),phi,x_vec.x(),s);
+        }
+        
+        //1st index = alignment parameter (only u so far)
+        //2nd index = residual coordinate (on du so far)
+        //Naming scheme:
+        //[Top]:
+        // 10000 = top
+        // 20000 = bottom
+        //[Type]: 
+        // 1000 - translation
+        // 2000 - rotation
+        //[Direction] (tracker coord. frame)
+        // 100 - x (beamline direction)
+        // 200 - y (bend plane)
+        // 300 - z (non-bend direction)
+        // [Layer]
+        // 1-10
+        
+             
+       //Rotation matrix from the tracking fram to the sensor/strip frame
+        Hep3Matrix T = trackerHitUtil.getTrackToStripRotation(strip);
+        
+      
+        
+        /*
+         * Calculate jacobian da/db
+         */
+        
+        BasicMatrix da_db = this._alignUtils.calculateJacobian(x_vec,T);
+      
+        
+        if(_DEBUG) {
+            this._alignUtils.printJacobianInfo(da_db);
+        }
+        
+        
+        
+        /*
+         * Invert the Jacobian
+         */
+        
+        
+        BasicMatrix db_da = (BasicMatrix) MatrixOp.inverse(da_db);
+        
+
+        
+        if(_DEBUG) {
+            System.out.printf("%s: Invert the Jacobian. We get da_db^-1=db_da: \n%s \n",this.getClass().getSimpleName(),db_da.toString());
+            BasicMatrix prod = (BasicMatrix) MatrixOp.mult(db_da,da_db);
+            System.out.printf("%s: Check the inversion i.e. db_da*da_db: \n%s \n",this.getClass().getSimpleName(),prod.toString());
+        }
+
+
+        /*
+         * Calculate global derivative of the residual dz/db = dq_a^gl/db-dq_p^gl/db
+         * dq_a^gl is the alignment corrected position in the global tracking frame
+         * dq_p^gl_db is the predicted hit position (from the track model) in the global/tracking frame
+         * 
+         */
+
+       
+
+         //****************************************************************************
+        // First term in dz/db 
+
+        //3x6 matrix
+        BasicMatrix dq_agl_db = _alignUtils.calculateGlobalHitPositionDers(x_vec);
+       
+        
+        if(_DEBUG) {
+            _alignUtils.printGlobalHitPositionDers(dq_agl_db);
+        }
+        
+        
+        
+        /*
+         * Second term in dz/db  
+         * dq_p^gl_db is the predicted hit position (from the track model) in the global/tracking frame
+         * 
+         */
+
+        //3x6 matrix
+        BasicMatrix dq_pgl_db = _alignUtils.calculateGlobalPredictedHitPositionDers(_trk,x_vec);
+
+        if(_DEBUG) {
+            _alignUtils.printGlobalPredictedHitPositionDers(dq_pgl_db);
+        
+            System.out.printf("%s: Cross-check using numerical derivatives for dq_pgl/db (numder)\n",this.getClass().getSimpleName());
+        
+            BasicMatrix dq_pgl_db_numder = this._numDerivatives.calculateGlobalPredictedHitPositionDers(_trk,x_vec);
+            _alignUtils.printGlobalPredictedHitPositionDers(dq_pgl_db_numder);
+        
+        }
+
+        /*
+         * Note that a shift in the position of the hit (q_agl) in in the 
+         * y/z plane is equivalent of the shift of the position of the prediction hit q_pgl
+         * in the same plane. Thus we set these terms of the derivative to zero
+         * 
+         */
+
+        dq_pgl_db.setElement(0, 0, 0);
+        dq_pgl_db.setElement(1, 1, 0);
+        dq_pgl_db.setElement(2, 2, 0);
+        
+        
+        /*
+         * For the rotations in this global frame the rotation leads to a shift of the position 
+         * of the predicted hit. Since angles are small this rotation is the same as the 
+         * rotation of the hit position
+         */
+        
+        dq_pgl_db.setElement(0, 3, 0);
+        dq_pgl_db.setElement(1, 3, 0);
+        dq_pgl_db.setElement(2, 3, 0);
+        dq_pgl_db.setElement(0, 4, 0);
+        dq_pgl_db.setElement(1, 4, 0);
+        dq_pgl_db.setElement(2, 4, 0);
+        dq_pgl_db.setElement(0, 5, 0);
+        dq_pgl_db.setElement(1, 5, 0);
+        dq_pgl_db.setElement(2, 5, 0);
+        
+        
+         if(_DEBUG) {
+            System.out.printf("%s: Fixing the predicted derivatives that are equivalent to the hit position derivatives. The result is below.\n",this.getClass().getSimpleName());
+            _alignUtils.printGlobalPredictedHitPositionDers(dq_pgl_db);
+        }
+        
+        /*
+         * Putting them together i.e. subtract the predicted from the hit position derivative 
+         */
+               
+        //3x6 matrix    
+        BasicMatrix dz_db = (BasicMatrix) MatrixOp.sub(dq_agl_db, dq_pgl_db);
+
+            
+        if(_DEBUG) {
+            _alignUtils.printGlobalResidualDers(dz_db);
+        }
+        
+        /*
+         * Convert the to the local frame using the Jacobian
+         */
+       
+        //3x6 = 3x6*6x6 matrix
+        BasicMatrix dz_da = (BasicMatrix) MatrixOp.mult(dz_db, db_da);
+        
+        if(_DEBUG) {   
+            _alignUtils.printLocalResidualDers(dz_da);
[truncated at 1000 lines; 130 more skipped]

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
TestSort.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TestSort.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TestSort.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,79 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author phansson
+ */
+public class TestSort {
+
+    public static class CmpClass implements Comparable<CmpClass> {
+        private int _val;
+        public CmpClass(int i) {
+            _val = i;
+        }
+        public void set(int i) {
+            _val = i;
+        }
+        public int get() {
+            return _val;
+        }
+
+        @Override
+        public int compareTo(CmpClass o) {
+            return o._val-_val;
+        }        
+    
+    }
+    
+    
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) {
+        
+        List<CmpClass> list = new ArrayList<CmpClass>();
+        list.add(new CmpClass(1));
+        list.add(new CmpClass(2));
+        list.add(new CmpClass(3));
+
+        System.out.printf("list:\n");
+        
+        for (CmpClass c : list) {
+            System.out.printf("%d\n",c._val);
+        }
+
+        Collections.sort(list);
+
+        System.out.printf("after sort:\n");
+        
+        for (CmpClass c : list) {
+            System.out.printf("%d\n",c._val);
+        }
+
+        list.get(1).set(4);
+
+        System.out.printf("list:\n");
+       
+        for (CmpClass c : list) {
+            System.out.printf("%d\n",c._val);
+        }
+
+        Collections.sort(list);
+
+        System.out.printf("after sort:\n");
+        
+        for (CmpClass c : list) {
+            System.out.printf("%d\n",c._val);
+        }
+
+    
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
TrigRateAna.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TrigRateAna.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TrigRateAna.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,1275 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import hep.aida.ref.plotter.PlotterRegion;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.util.aida.AIDA;
+
+
+
+/**
+ *
+ * @author phansson
+ */
+
+
+
+
+
+public class TrigRateAna {
+    
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    IHistogramFactory hf = aida.histogramFactory();
+//    ITree tree = aida.tree();//(ITreeFactory) af.createTreeFactory().create();
+    
+    private int _bkgRunNr1 = -1;
+    private int _bkgRunNr2 = -1;
+    
+    private boolean _saveFiles = false;
+    private boolean _hide = false;
+    private String _addOn = "";
+    
+    double _C_ep = 1;
+    
+    ECalHitMapPlots util = new ECalHitMapPlots();
+    
+    List<Count> _countList = new ArrayList<Count>();
+
+    HashMap<String,Integer> _counts = new HashMap<String,Integer>();
+    HashMap<String,Integer> _counts_merged = new HashMap<String,Integer>();
+    HashMap<String,Double> _counts_merged_norm = new HashMap<String,Double>();
+    HashMap<String,Double> _counts_merged_norm_subtr = new HashMap<String,Double>();
+    HashMap<String,Double> _counts_merged_norm_subtr_qscaled = new HashMap<String,Double>();
+    HashMap<String,Double> _counts_merged_norm_subtr_qscaled_daqscaled = new HashMap<String,Double>();
+    
+    HashMap<String,Double> _ratio = new HashMap<String,Double>();
+
+    List<PolarCount> _polarCountList = new ArrayList<PolarCount>();
+    
+    List<BeamCurrentData> _beamCurrent = new ArrayList<BeamCurrentData>();
+    List<DAQDeadTimeData> _deadTime = new ArrayList<DAQDeadTimeData>();
+    HashMap<Integer,Double> _thicknessMap = new HashMap<Integer,Double>();
+
+  
+    double _chargeScale = 1.0;
+    
+    
+    public void saveFiles(boolean v) {
+        _saveFiles = v;
+    }
+    
+    public void addOn(String s) {
+        _addOn = s;
+    }
+    
+    public void hidePlots(boolean h) {
+        this._hide = h;
+        this.util.hidePlots(this._hide);
+    }
+    
+    public TrigRateAna() {
+        
+        //System.out.println("Constructor ECalHitMapPlots");
+        
+    }
+    
+    public void setChargeNormalization(double q) {
+        _chargeScale = q;
+    }
+   
+    public void setBackgroundRunNrs(int nr1, int nr2) {
+        _bkgRunNr1 = nr1;
+        _bkgRunNr2 = nr2;
+        
+    }
+    
+    
+    public void getGainCalibration(ITree tree,String side) {
+        
+        IHistogram1D h = (IHistogram1D)tree.find("Cluster E>600GeV Eoverp good region " + side);
+        
+        util.plotBasic1D(h,"Eoverp good region E>600MeV", "E/p","Arbitrary Units","green",_saveFiles);
+        
+        double max = -1;
+        int bin_max = -1;
+        for(int bin=1;bin<h.axis().bins();++bin) {
+            if(h.binEntries(bin)>max) {
+                max=h.binEntries(bin);
+                bin_max = bin;
+            }
+        }
+        
+        System.out.println("Maximum E/p: " + h.axis().binCenter(bin_max));
+        _C_ep = h.axis().binCenter(bin_max);
+        System.out.println("Gain calibration: " + _C_ep);
+        
+        return;
+        
+//        IHistogram2D hm = (IHistogram2D)tree.find("Cluster hit map all");        
+//        plotBasic2D(hm,"Cluster Hit Map", "Horizontal Crystal Index","Vertical Crystal Index");
+//        
+//        IHistogram1D hAmp = (IHistogram1D)tree.find("Cluster size all");
+//        plotBasic1D(hAmp,"Cluster Size", "Cluster Size","Arbitrary Units","green");
+
+        
+        
+
+
+    
+        
+    }
+    
+    
+    private int findCount(List<Count> list, String r,String n) {
+        //System.out.println("Looking for run " + r + " for type " + n + " among " + list.size() + "count objects");
+        for(int i=0;i<list.size();++i) {
+            System.out.println(i +": " + list.get(i).run() + " " + list.get(i).name());
+            if(list.get(i).name().equals(n)) {
+                if(list.get(i).run().equals(r)) {
+                    //System.out.println("Found it! " + i);
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+    
+    private int findPolarCount(List<PolarCount> list, String r, double v, String n) {
+        //System.out.println("Looking for run " + r + " for type " + n + " and val " + v + " among " + list.size() + " polar count objects");
+        for(int i=0;i<list.size();++i) {
+            //System.out.println(i +": " + list.get(i).run() + " " + list.get(i).name() + " " + list.get(i).val());
+            if(list.get(i).name().equals(n)) {
+                if(list.get(i).run().equals(r)) {
+                    if(Double.compare(list.get(i).val(),v)==0) {
+                        //System.out.println("Found it! " + i);
+                        return i;
+                    }
+                }
+            }
+        }
+        return -1;
+    }
+    
+    private List<Count> findCount(String name) {
+        List<Count> list = new ArrayList<Count>();
+        for(Count c :_countList) {
+            if(c.name().equals(name)) list.add(c);
+        }
+        return list;
+    }
+
+    private List<PolarCount> findPolarCount(String name) {
+        List<PolarCount> list = new ArrayList<PolarCount>();
+        for(PolarCount c :_polarCountList) {
+            if(c.name().equals(name)) list.add(c);
+        }
+        return list;
+    }
+
+    
+    public void mergeCounts() {
+//        HashMap<String,Integer> m = _counts_merged;
+//        for (Map.Entry<String, Integer> e : _counts.entrySet()) {
+//            String k = e.getKey();
+//            Integer n = e.getValue();
+//            if(k.contains("_")) {
+//                int idx = k.indexOf("_");
+//                String str = k.substring(0, idx);
+//                k = str;
+//            }
+//            if(m.containsKey(k)) {
+//                n += m.get(k);
+//            }
+//            m.put(k, n);
+//        }
+//        
+        List<Count> list = new ArrayList<Count>();
+        
+        for(Count c : _countList) {
+            String run = c.run();
+            String name = "merged"; //c.name();
+            if(run.contains("_")) {
+                int idx = run.indexOf("_");
+                String str = run.substring(0, idx);
+                run = str;
+            }
+            int idx = findCount(list,run,name);
+            if(idx<0) {
+                Count c_new = new Count(name,run,c.n(),c.en());
+                list.add(c_new);
+            } else {
+                list.get(idx).addSimple(c.n(),c.en());
+            }
+            
+        }
+        _countList.addAll(list);
+        
+        
+        
+        
+        List<PolarCount> list2 = new ArrayList<PolarCount>();
+        
+        for(PolarCount c : _polarCountList) {
+            String run = c.run();
+            String name = "merged"; //c.name();
+            if(run.contains("_")) {
+                int idx = run.indexOf("_");
+                String str = run.substring(0, idx);
+                run = str;
+            }
+            int idx = findPolarCount(list2,run,c.val(),name);
+            if(idx<0) {
+                PolarCount c_new = new PolarCount(name,run,c.val(),c.count());
+                
+                list2.add(c_new);
+            } else {
+                list2.get(idx).addSimple(c);
+            }
+            
+        }
+        _polarCountList.addAll(list2);
+        
+        
+        
+        
+    }
+    
+    public boolean isBackgroundRun(int nr) {
+        if(_bkgRunNr1==nr) return true;
+        if(_bkgRunNr2==nr) return true;
+        return false;
+        
+    }
+    
+    
+    public BeamCurrentData getBCD(String run_str) {
+        for(BeamCurrentData b : _beamCurrent) {
+            if(b.getRun()==Integer.parseInt(run_str)) return b;
+        }
+        return null;
+    }
+    
+    
+    
+    public void normalize() {
+        
+//        HashMap<String,Double> m = _counts_merged_norm;
+//        
+//        for (Map.Entry<String, Integer> e : _counts_merged.entrySet()) {
+//            String k = e.getKey();
+//            Integer n = e.getValue();
+//            //get the integrated beam current
+//            BeamCurrentData bcd = getBCD(k);
+//            if(bcd==null) {
+//                System.out.println("Error run " + k + " is not in beam current list!");
+//                System.exit(1);
+//            }
+//            
+//            double current = bcd.getIntCurrent();
+//            double n_norm = n/current; // unit is [/nC]
+//            m.put(k, n_norm);
+//            
+//        }
+//        
+        
+        List<Count> list = new ArrayList<Count>();
+        for(Count c : _countList) {
+            if(c.name()!="merged") continue;
+            String run = c.run();
+            String name = "normalized"; //c.name();
+            BeamCurrentData bcd = getBCD(run);
+            if(bcd==null) {
+                System.out.println("Error run " + run + " is not in beam current list!");
+                System.exit(1);
+            }
+            double current = bcd.getIntCurrent();
+            double ecurrent = bcd.getIntCurrentError();
+            double n = c.n();
+            double en = c.en();
+            double n_norm = n/current;
+            double en_norm = Math.sqrt((en/current)*(en/current) + (n/(current*current)*ecurrent)*(n/(current*current)*ecurrent));
+            
+            Count c_new = new Count(name,run,n_norm,en_norm);
+            list.add(c_new);
+            
+        }
+        _countList.addAll(list);
+        
+        
+        List<PolarCount> polarlist = new ArrayList<PolarCount>();
+        for(PolarCount c : _polarCountList) {
+            if(c.name()!="merged") continue;
+            String run = c.run();
+            String name = "normalized"; //c.name();
+            BeamCurrentData bcd = getBCD(run);
+            if(bcd==null) {
+                System.out.println("Error run " + run + " is not in beam current list!");
+                System.exit(1);
+            }
+            double current = bcd.getIntCurrent();
+            double ecurrent = bcd.getIntCurrentError();
+            double n = c.count().n();
+            double en = c.count().en();
+            double n_norm = n/current;
+            double en_norm = Math.sqrt((en/current)*(en/current) + (n/(current*current)*ecurrent)*(n/(current*current)*ecurrent));
+            
+            PolarCount c_new = new PolarCount(name,run,c.val(),new Count(name,run,n_norm,en_norm));
+            polarlist.add(c_new);
+            
+        }
+        _polarCountList.addAll(polarlist);
+        
+        
+        
+        
+    }
+    
+    
+      
+    public void subtractBackground() {
+       
+//        double bkg1 = _counts_merged_norm.get(String.valueOf(this._bkgRunNr1));
+//        double bkg2 = _counts_merged_norm.get(String.valueOf(this._bkgRunNr2));
+//        for (Map.Entry<String, Double> e : _counts_merged_norm.entrySet()) {
+//            String k = e.getKey();
+//            double n = e.getValue();
+//            int k_int = Integer.parseInt(k);
+//            if(k_int == this._bkgRunNr1) continue;
+//            if(k_int == this._bkgRunNr2) continue;
+//            
+//            double ns = k_int<1360 ? (n-bkg1) : (n-bkg2);
+//                
+//            _counts_merged_norm_subtr.put(k, ns);
+//        }
+//        
+        
+        int idx_bkg1 = findCount(this._countList,String.valueOf(this._bkgRunNr1),"normalized");
+        int idx_bkg2 = findCount(this._countList,String.valueOf(this._bkgRunNr2),"normalized");
+        
+        double bkg1 = _countList.get(idx_bkg1).n();
+        double bkg2 = _countList.get(idx_bkg2).n();
+        
+        System.out.println("bkg1 " + bkg1 + " bkg2 " + bkg2);
+        
+        double ebkg1 = _countList.get(idx_bkg1).en();
+        double ebkg2 = _countList.get(idx_bkg2).en();
+        
+        List<Count> list = new ArrayList<Count>();
+        for(Count c: _countList) {
+            if(!c.name().equals("normalized")) continue;
+            String name = "bkgsubtr";
+            String run = c.run();
+            int run_int = Integer.parseInt(run);
+            if(this.isBackgroundRun(run_int)) continue;
+            double b = run_int<1360 ? bkg1 : bkg2;
+            double eb = run_int<1360 ? ebkg1 : ebkg2;
+            double n = c.n()-b;
+            double en = Math.sqrt(c.en()*c.en() + eb*eb);
+            
+            Count c_new = new Count(name,run,n,en);
+            list.add(c_new);
+        }
+        _countList.addAll(list);
+        
+        
+        
+        List<PolarCount> polarList = new ArrayList<PolarCount>();
+        for(PolarCount c: _polarCountList) {
+            if(!c.name().equals("normalized")) continue;
+            String name = "bkgsubtr";
+            String run = c.run();
+            int run_int = Integer.parseInt(run);
+            if(this.isBackgroundRun(run_int)) continue;
+            
+            idx_bkg1 = findPolarCount(this._polarCountList,String.valueOf(this._bkgRunNr1),c.val(),"normalized");
+            idx_bkg2 = findPolarCount(this._polarCountList,String.valueOf(this._bkgRunNr2),c.val(),"normalized");
+            bkg1 = _polarCountList.get(idx_bkg1).count().n();
+            bkg2 = _polarCountList.get(idx_bkg2).count().n();
+        
+            System.out.println("polar " + c.val() + " bkg1 " + bkg1 + " bkg2 " + bkg2);
+        
+            ebkg1 = _polarCountList.get(idx_bkg1).count().en();
+            ebkg2 = _polarCountList.get(idx_bkg2).count().en();
+            
+            double b = run_int<1360 ? bkg1 : bkg2;
+            double eb = run_int<1360 ? ebkg1 : ebkg2;
+            double n = c.count().n()-b;
+            double en = Math.sqrt(c.count().en()*c.count().en() + eb*eb);
+            
+            PolarCount c_new = new PolarCount(name,run,c.val(),new Count(name,run,n,en));
+            polarList.add(c_new);
+        }
+        _polarCountList.addAll(polarList);
+        
+        
+    }
+    
+    
+    
+        
+    public void scaleToRndCharge() {
+
+        System.out.println("Scaling to " + _chargeScale + " nC  from nC");
+        
+        
+//        for (Map.Entry<String, Double> e : this._counts_merged_norm_subtr.entrySet()) {
+//            String k = e.getKey();
+//            double n = e.getValue();
+//            int k_int = Integer.parseInt(k);
+//            
+//            double ns = n*_chargeScale;
+//            
+//            _counts_merged_norm_subtr_qscaled.put(k, ns);
+//        }
+        
+        List<Count> list = new ArrayList<Count>();
+        for(Count c : _countList) {
+            if(!c.name().equals("bkgsubtr")) continue;
+            String name = "q-scaled";
+            String run  = c.run();
+            double ns = c.n()*_chargeScale;
+            double ens = c.en()*_chargeScale;
+            Count c_new = new Count(name,run,ns,ens);
+            list.add(c_new);
+            
+        }
+        _countList.addAll(list);
+        
+        
+        List<PolarCount> polarList = new ArrayList<PolarCount>();
+        for(PolarCount c : _polarCountList) {
+            if(!c.name().equals("bkgsubtr")) continue;
+            String name = "q-scaled";
+            String run  = c.run();
+            double ns = c.count().n()*_chargeScale;
+            double ens = c.count().en()*_chargeScale;
+            PolarCount c_new = new PolarCount(name,run,c.val(),new Count(name,run,ns,ens));
+            polarList.add(c_new);
+            
+        }
+        _polarCountList.addAll(polarList);
+        
+        
+        
+        
+    }
+    
+    
+     public DAQDeadTimeData getDTD(String run_str) {
+        for(DAQDeadTimeData b : _deadTime) {
+            if(b.getRun()==Integer.parseInt(run_str)) return b;
+        }
+        return null;
+    }
+    
+     public void scaleDAQDeadTime() {
+
+        System.out.println("Scaling DAQ dead time");
+        
+        
+//        for (Map.Entry<String, Double> e : this._counts_merged_norm_subtr_qscaled.entrySet()) {
+//            String k = e.getKey();
+//            double n = e.getValue();
+//            DAQDeadTimeData dtd = getDTD(k);
+//            if(dtd==null) {
+//                System.out.println("Error run " + k + " is not in daq dead time map");
+//                System.exit(1);
+//            }
+//            
+//            double ns = n/dtd.getDAQLiveTimeFraction();
+//            
+//            _counts_merged_norm_subtr_qscaled_daqscaled.put(k, ns);
+//        }
+        
+        
+        List<Count> list = new ArrayList<Count>();
+        for(Count c : _countList) {
+            if(!c.name().equals("q-scaled")) continue;
+            String name = "daq-scaled";
+            String run  = c.run();
+            DAQDeadTimeData dtd = getDTD(run);
+            if(dtd==null) {
+                System.out.println("Error run " + run + " is not in daq dead time map");
+                System.exit(1);
+            }
+            double a = c.n();
+            double b = dtd.getDAQLiveTimeFraction();
+            double ea = c.en();
+            double eb = dtd.getDAQLiveTimeFractionError();
+            double ns = a/b;
+            double ens = Math.sqrt((ea/b)*(ea/b) + (eb*a/(b*b))*(eb*a/(b*b)));
+            Count c_new = new Count(name,run,ns,ens);
+            list.add(c_new);
+            
+        }
+        
+        _countList.addAll(list);
+        
+        
+         List<PolarCount> polarList = new ArrayList<PolarCount>();
+        for(PolarCount c : _polarCountList) {
+            if(!c.name().equals("q-scaled")) continue;
+            String name = "daq-scaled";
+            String run  = c.run();
+            DAQDeadTimeData dtd = getDTD(run);
+            if(dtd==null) {
+                System.out.println("Error run " + run + " is not in daq dead time map");
+                System.exit(1);
+            }
+            double a = c.count().n();
+            double b = dtd.getDAQLiveTimeFraction();
+            double ea = c.count().en();
+            double eb = dtd.getDAQLiveTimeFractionError();
+            double ns = a/b;
+            double ens = Math.sqrt((ea/b)*(ea/b) + (eb*a/(b*b))*(eb*a/(b*b)));
+            PolarCount c_new = new PolarCount(name,run,c.val(),new Count(name,run,ns,ens));
+            polarList.add(c_new);
+            
+        }
+        
+        _polarCountList.addAll(polarList);
+        
+        
+    }
+    
+    
+     public double thickness(String run) {
+         if(run.contains("_")) {
+             run = run.split("_")[0];
+         }
+         int run_int = Integer.parseInt(run);
+         if(!_thicknessMap.containsKey(run_int)) {
+             System.out.println("thickness map do not contain " + run_int);
+             System.exit(1);
+         }
+         return _thicknessMap.get(run_int);
+         
+     }
+     
+     
+    public void prettyPrintCount() {
+        System.out.println("== Raw counts ==");
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        
+        for (Map.Entry<String, Integer> e : _counts.entrySet()) {
+            System.out.printf("%10s\t%17.2f\t%10d\n", e.getKey(),thickness(e.getKey()),e.getValue());
+        }
+        
+        System.out.println("== Merged ==");
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Map.Entry<String, Integer> e : _counts_merged.entrySet()) {
+            System.out.printf("%10s\t%17.2f\t%10d\n", e.getKey(),thickness(e.getKey()),e.getValue());
+        }
+        System.out.println("== Merged and normalized ==");
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Map.Entry<String, Double> e : _counts_merged_norm.entrySet()) {
+            System.out.printf("%10s\t%17.2f\t%10.2f [/nC]\n", e.getKey(),thickness(e.getKey()),e.getValue());
+        }
+        System.out.println("== Merged, normalized and subtracted ==");
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Map.Entry<String, Double> e : _counts_merged_norm_subtr.entrySet()) {
+            System.out.printf("%10s\t%17.2f\t%10.2f [/nC]\n", e.getKey(),thickness(e.getKey()),e.getValue());
+        }
+        System.out.println("== Merged, normalized, subtracted ==");
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Map.Entry<String, Double> e : _counts_merged_norm_subtr_qscaled.entrySet()) {
+            System.out.printf("%10s\t%17.2f\t%10.2f [/%.1fnC]\n", e.getKey(),thickness(e.getKey()),e.getValue(),_chargeScale);
+        }
+        System.out.println("== Merged, normalized, subtracted and corrected for DAQ dead time ==");
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Map.Entry<String, Double> e : _counts_merged_norm_subtr_qscaled_daqscaled.entrySet()) {
+            System.out.printf("%10s\t%17.2f\t%10.2f [/%.1fnC]\n", e.getKey(),thickness(e.getKey()),e.getValue(),_chargeScale);
+        }
+
+        System.out.println("== Ratio w.r.t. 0.18% thickness ==");
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","N[thickness]/N[0.18%]");
+        for (Map.Entry<String, Double> e : _ratio.entrySet()) {
+            System.out.printf("%10s\t%17.2f\t%10.2f\n", e.getKey(),thickness(e.getKey()),e.getValue());
+        }
+
+        
+        
+        System.out.println("\n\n== Integrated beam currents ==");
+        System.out.printf("%10s\t%8s\t%8s\t%8s\n","run","start","stop","Int. I [nC]\n");
+        for(BeamCurrentData b: _beamCurrent) {
+            System.out.printf("%s\n",b.toString());
+        }
+        
+        System.out.println("\n\n== DAQ Dead Time ==");
+        for(DAQDeadTimeData b: _deadTime) {
+            System.out.printf("%s\n",b.toString());
+        }
+        
+        
+        
+        
+        
+    }
+    
+    
+    
+    
+    public void prettyPrintCountList() {
+        System.out.println("== Raw counts ==");
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        List<Count> list = findCount("raw");
+        for (Count e : list) {
+            System.out.printf("%10s\t%17.2f\t%10.2f+-%.3f\n", e.run(),thickness(e.run()),e.n(),e.en());
+        }
+        System.out.println("== Merged ==");
+        list = findCount("merged");        
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Count e : list) {
+            System.out.printf("%10s\t%17.2f\t%10.2f+-%.3f\n", e.run(),thickness(e.run()),e.n(),e.en());
+        }
+
+        System.out.println("== Merged and normalized ==");
+        list = findCount("normalized");        
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Count e : list) {
+            System.out.printf("%10s\t%17.2f\t%10.2f+-%.3f\n", e.run(),thickness(e.run()),e.n(),e.en());
+        }
+
+        System.out.println("== Merged, normalized and subtracted ==");
+        list = findCount("bkgsubtr");        
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Count e : list) {
+            System.out.printf("%10s\t%17.2f\t%10.2f+-%.3f\n", e.run(),thickness(e.run()),e.n(),e.en());
+        }
+       
+        System.out.println("== Merged, normalized, subtracted, q-scaled ==");
+        list = findCount("q-scaled");        
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Count e : list) {
+            System.out.printf("%10s\t%17.2f\t%10.2f+-%.3f [/%.1fnC]\n", e.run(),thickness(e.run()),e.n(),e.en(),_chargeScale);
+        }
+        
+        System.out.println("== Merged, normalized, subtracted and corrected for DAQ dead time ==");
+        list = findCount("daq-scaled");        
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","Counts");
+        for (Count e : list) {
+            System.out.printf("%10s\t%17.2f\t%10.2f+-%.3f [/%.1fnC]\n", e.run(),thickness(e.run()),e.n(),e.en(),_chargeScale);
+        }
+
+        System.out.println("== Ratio w.r.t. 0.18% thickness ==");
+        System.out.printf("%10s\t%17s\t%10s\n","run","Target thickn. [% r.l.]","N[thickness]/N[0.18%]");
+        list = findCount("ratio0.18");        
+        for (Count e : list) {
+            System.out.printf("%10s\t%17.2f\t%10.2f+-%.3f [/%.1fnC]\n", e.run(),thickness(e.run()),e.n(),e.en(),_chargeScale);
+        }
+
+        
+       
+        System.out.println("== Polar: Merged, normalized, subtracted and corrected for DAQ dead time ==");
+        List<PolarCount> polarList = findPolarCount("daq-scaled");        
+        List<String> listRun = new ArrayList<String>();
+        for(PolarCount c : polarList) {
+            if(listRun.contains(c.run())) continue;
+            listRun.add(c.run());
+        }
+        System.out.printf("%10s\t%17s\t%10s\t%10s\n","run","Target thickn. [% r.l.]","Polar \"Y\"","Counts");
+        for(String r : listRun) {
+            for (PolarCount e : polarList) {
+                if(!e.run().equals(r)) continue;
+                System.out.printf("%10s\t%17.2f\t%10.1f\t%10.2f+-%.3f [/%.1fnC]\n", e.run(),thickness(e.run()),e.val(),e.count().n(),e.count().en(),_chargeScale);
+            }
+        }
+        
+        
+        
+        
+        
+        
+        
+        System.out.println("\n\n== Integrated beam currents ==");
+        System.out.printf("%10s\t%8s\t%8s\t%8s\n","run","start","stop","Int. I [nC]\n");
+        for(BeamCurrentData b: _beamCurrent) {
+            System.out.printf("%s\n",b.toString());
+        }
+        
+        System.out.println("\n\n== DAQ Dead Time ==");
+        for(DAQDeadTimeData b: _deadTime) {
+            System.out.printf("%s\n",b.toString());
+        }
+        
+        
+        
+        
+        
+    }
+    
+    
+    
+    
+    
+    public void plotCount() {
+        plotCount("raw");
+        plotCount("merged");
+        plotCount("normalized");
+        plotCount("bkgsubtr");
+        plotCount("q-scaled");
+        plotCount("daq-scaled");
+        
+        plotPolarCount("raw");
+        plotPolarCount("merged");
+        plotPolarCount("normalized");
+        plotPolarCount("bkgsubtr");
+        plotPolarCount("q-scaled");
+        plotPolarCount("daq-scaled");
+
+/*
+        plotCount(this._counts,"Counts raw");
+        plotCount(this._counts_merged,"Counts merged");
+        plotCountD(this._counts_merged_norm,"Counts merged normalized");
+        plotCountD(this._counts_merged_norm,"Counts merged background subtracted");
+        plotCountD(this._counts_merged_norm_subtr_qscaled,"Counts merged normalized q-norm");
+        plotCountD(this._counts_merged_norm_subtr_qscaled_daqscaled,"Counts merged normalized q-norm");
+        */
+    }
+
+//    public void plotCount(Map<String,Integer> map, String name) {
+//        HashMap<String,Double> m = new HashMap<String,Double>();
+//        for(Map.Entry<String,Integer> e : map.entrySet()) {
+//            m.put(e.getKey(), e.getValue().doubleValue());
+//        }
+//        plotCountD(m,name);
+//    }
+//    
+    public void plotCount(String name) {
+
+      //IDataPointSetFactory dpsf = af.createDataPointSetFactory();
+      
+      // Create a one dimensional IDataPointSet.
+      IDataPointSet dps = af.createDataPointSetFactory(af.createTreeFactory().createTree()).create("dps1D",name,2);
+      String xtitle = "Target thickness [% rad. len.]";
+      for (Count e : _countList) {
+          if(!e.name().equals(name)) continue;
+            dps.addPoint();
+            dps.point(dps.size()-1).coordinate(0).setValue(this.thickness(e.run()));
+            dps.point(dps.size()-1).coordinate(0).setErrorPlus(0);
+            dps.point(dps.size()-1).coordinate(1).setValue(e.n());
+            dps.point(dps.size()-1).coordinate(1).setErrorPlus(e.en());
+            //xtitle += " " + e.getKey();
+            
+      }
+      IPlotter plotter_hm = af.createPlotterFactory().create();
+      plotter_hm.setTitle("Counts");
+      plotter_hm.currentRegion().plot(dps);
+        
+      ((PlotterRegion) plotter_hm.region(0)).getPlot().getXAxis().setLabel(xtitle);
+        
+        
+        //if(fillColor=="") fillColor="yellow";
+        //plotter_hm.createRegion(10.0,20.0, 460.0,100.0);
+        //plotter_hm.createRegion(d, d1, d2, d3)
+//        plotter_hm.createRegions(1,1);//.plot(hm);
+//        plotter_hm.region(0).plot(h);
+//        plotter_hm.region(1).plot(h2);
+//        plotter_hm.region(2).plot(h);
+//        plotter_hm.region(2).plot(h2,"mode=overlay");
+        plotter_hm.style().statisticsBoxStyle().setVisible(false);
+        //plotter_hm.style().dataStyle().fillStyle().setColor(fillColor);
+        //((PlotterRegion) plotter_hm.region(0)).getPlot().getXAxis().setLabel(xTitle);
+        //((PlotterRegion) plotter_hm.region(0)).getPlot().getYAxis().setLabel(yTitle);          
+        if(!this._hide) plotter_hm.show();
+        
+        
+        if(_saveFiles) {
+            try {
+                plotter_hm.writeToFile(name + "_" + _addOn +".png", "png");
+            } catch(IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        
+        
+        
+    }
+    
+    public void plotPolarCount(String name) {
+
+      IPlotter plotter_hm = af.createPlotterFactory().create();
+      plotter_hm.setTitle("Polar Angle Counts");
+      
+      int nregions;
+      List<String> runs = new ArrayList<String>();
+      for (PolarCount e : _polarCountList) {
+          if(!e.name().equals(name)) continue;
+          if(runs.contains(e.run())) continue;
+          runs.add(e.run());
+      }
+      
+      System.out.println("Found " + runs.size() + " runs for " + name);
+      boolean first = true;
+      for(String run : runs) {
+        //IDataPointSetFactory dpsf = af.createDataPointSetFactory();
+      
+        // Create a one dimensional IDataPointSet.
+        IDataPointSet dps = af.createDataPointSetFactory(af.createTreeFactory().createTree()).create("dps1D",name,2);
+        String xtitle = "Polar Hit Count";//Target thickness [% rad. len.]";
+        for (PolarCount e : _polarCountList) {
+            if(!e.name().equals(name)) continue;
+            if(!e.run().equals(run)) continue;
+                dps.addPoint();
+//                dps.point(dps.size()-1).coordinate(0).setValue(this.thickness(e.run()));
+                dps.point(dps.size()-1).coordinate(0).setValue(e.val());
+                dps.point(dps.size()-1).coordinate(0).setErrorPlus(0);
+                dps.point(dps.size()-1).coordinate(1).setValue(e.count().n());
+                dps.point(dps.size()-1).coordinate(1).setErrorPlus(e.count().en());
+                //xtitle += " " + e.getKey();
+                
+        }
+      
+        if(first) plotter_hm.currentRegion().plot(dps);
+        else {
+           plotter_hm.currentRegion().plot(dps,"mode=overlay"); 
+        }
+        
+        ((PlotterRegion) plotter_hm.region(0)).getPlot().getXAxis().setLabel(xtitle);
+      }
+        
+        //if(fillColor=="") fillColor="yellow";
+        //plotter_hm.createRegion(10.0,20.0, 460.0,100.0);
+        //plotter_hm.createRegion(d, d1, d2, d3)
+//        plotter_hm.createRegions(1,1);//.plot(hm);
+//        plotter_hm.region(0).plot(h);
+//        plotter_hm.region(1).plot(h2);
+//        plotter_hm.region(2).plot(h);
+//        plotter_hm.region(2).plot(h2,"mode=overlay");
+        plotter_hm.style().statisticsBoxStyle().setVisible(false);
+        //plotter_hm.style().dataStyle().fillStyle().setColor(fillColor);
+        //((PlotterRegion) plotter_hm.region(0)).getPlot().getXAxis().setLabel(xTitle);
+        //((PlotterRegion) plotter_hm.region(0)).getPlot().getYAxis().setLabel(yTitle);          
+        if(!this._hide) plotter_hm.show();
+        
+        
+        if(_saveFiles) {
+            try {
+                plotter_hm.writeToFile(name + "_" + _addOn +".png", "png");
+            } catch(IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        
+        
+        
+    }
+
+    
+      public void makeRatio(double denominator_name, String name) {
+
+           //Find the denominator
+          double den = -1;
+          double eden = 0;
+//          for (Map.Entry<String, Double> e : this._counts_merged_norm_subtr.entrySet()) {
+//              if(isBackgroundRun(Integer.parseInt(e.getKey()))) continue;
+//              double t = this.thickness(e.getKey());
+//              if(t == denominator_name) {
+//                  den = e.getValue();
+//                  break;
+//              }
+//          }
+//          
+//          System.out.println("Den " + den + " (" + denominator_name + ")");
+//          if(den<0) {
+//              System.exit(1);
+//          }
+//          
+//        
+//        for (Map.Entry<String, Double> e : this._counts_merged_norm_subtr.entrySet()) {
+//        
+//          double n =  e.getValue();
+//          double ratio = n/den;
+//          double t = this.thickness(e.getKey());
+//          _ratio.put(e.getKey(), ratio);
+//          //System.out.println(e.getKey() + " t " + t + " n " + n + " ratio " + ratio);
+//
+//            
+//        }
+//        
+        
+        
+        for(Count c : _countList) {
+            if(c.name()!="bkgsubtr") continue;
+            if(isBackgroundRun(Integer.parseInt(c.run()))) continue;
+            double t = this.thickness(c.run());
+              if(t == denominator_name) {
+                  den = c.n();
+                  eden = c.en();
+                  break;
+              }
+        }
+        List<Count> list = new ArrayList<Count>();
+        for(Count c : _countList) {
+            if(c.name()!="bkgsubtr") continue;
+            String name_new = "ratio0.18";
+            double a = c.n();
+            double ea = c.en();
+            double b = den;
+            double eb = eden;
+            double r = a/b;
+            double er = Math.sqrt((ea/b)*(ea/b) + (eb*a/(b*b))*(eb*a/(b*b)));
+            Count c_new = new Count(name_new,c.run(),r,er);
+            list.add(c_new);
+            
+            
+        }
+        _countList.addAll(list);
+        
+        
+        
+        
+      }
+    
+    
+    
+    
+     public void plotRatio(String name) {
+     
+     
+         
+          
+      // Create a one dimensional IDataPointSet.
+      IDataPointSet dps = af.createDataPointSetFactory(af.createTreeFactory().createTree()).create("dps2D",name,2);
+      String xtitle = " Converter thickness (% r.l.)";
+      //for (Map.Entry<String, Double> e : this._ratio.entrySet()) {
+      for (Count e : this._countList) {
+          if(!e.name().equals("ratio0.18")) continue;
+          dps.addPoint();
+          double t = this.thickness(e.run());
+          dps.point(dps.size()-1).coordinate(0).setValue(t);
+          dps.point(dps.size()-1).coordinate(0).setErrorPlus(0);
+          dps.point(dps.size()-1).coordinate(1).setValue(e.n());
+          dps.point(dps.size()-1).coordinate(1).setErrorPlus(e.en());
+          //xtitle += " " + e.getKey();
+          
+            
+      }
+      
+        IPlotter plotter_hm = af.createPlotterFactory().create();
+        plotter_hm.style().dataStyle().lineStyle().setVisible(false);
+        plotter_hm.setTitle("Ratio " + name);
+        plotter_hm.currentRegion().plot(dps);
+        ((PlotterRegion) plotter_hm.region(0)).getPlot().getXAxis().setLabel(xtitle);
+        
+        
+        //if(fillColor=="") fillColor="yellow";
+        //plotter_hm.createRegion(10.0,20.0, 460.0,100.0);
+        //plotter_hm.createRegion(d, d1, d2, d3)
+//        plotter_hm.createRegions(1,1);//.plot(hm);
+//        plotter_hm.region(0).plot(h);
+//        plotter_hm.region(1).plot(h2);
+//        plotter_hm.region(2).plot(h);
+//        plotter_hm.region(2).plot(h2,"mode=overlay");
+        plotter_hm.style().statisticsBoxStyle().setVisible(false);
+        //plotter_hm.style().dataStyle().fillStyle().setColor(fillColor);
+        //((PlotterRegion) plotter_hm.region(0)).getPlot().getXAxis().setLabel(xTitle);
+        //((PlotterRegion) plotter_hm.region(0)).getPlot().getYAxis().setLabel(yTitle);          
+        if(!this._hide) plotter_hm.show();
+        if(_saveFiles) {
+            try {
+                plotter_hm.writeToFile(name + "_" + _addOn + ".png", "png");
+            } catch(IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        
+        
+        
+    }
+    
+    
+    public void addCount(ITree tree,String hname, String name) {
+        
[truncated at 1000 lines; 278 more skipped]

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
TrigRateDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TrigRateDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TrigRateDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,476 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import hep.aida.ref.plotter.PlotterRegion;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.Subdetector;
+import org.lcsim.hps.event.BeamlineConstants;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.hps.recon.ecal.EcalConditions;
+import org.lcsim.hps.recon.tracking.EcalTrackMatch;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson+
+ */
+public class TrigRateDriver extends Driver {
+    
+    int nevents = 0;
+    boolean debug = true;
+    protected IDDecoder dec = null;
+    protected Subdetector ecal;
+    private String ecalName = "Ecal";
+    
+    
+    private boolean hideFrame = true;
+    private boolean simTrigger = false;
+    
+    private String outputPlotFileName = "trigRate.aida";
+    private String trackCollectionName = "MatchedTracks";
+    private String ecalClusterCollectionName = "EcalClusters";
+    private String triggerClusterCollectionName = "EcalTriggerClusters";
+    private double triggerThreshold = 10.0;
+    
+    EcalTrackMatch trkMatchTool;
+    
+    private boolean doTracking = false;
+    
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    IHistogramFactory hf = aida.histogramFactory();
+    private AIDAFrame plotterFrame;
+    private AIDAFrame plotterFrameTrig;
+
+    private static int nThr = 3;
+    private int eThr[] = {0,600,800};
+    
+
+    IPlotter plotter_trig_tag;
+    IHistogram1D clusterEnergy[][] = new IHistogram1D[47][11];
+    IHistogram2D meanClusterEnergy;
+    IHistogram1D hityCol[][] = new IHistogram1D[nThr][47];
+
+    
+    private int trigger[] = {0,0};
+
+    
+    private int refreshRate = 1000;
+    
+    // Cluster energy correction
+    //double C_ep = 1.0; //1.0/0.3;
+
+    
+    
+    public void startOfData() {
+    }
+    
+    public void detectorChanged(Detector detector) {
+	// Get the Subdetector.
+	ecal = detector.getSubdetector(ecalName);
+
+	// Cache ref to decoder.
+	dec = ecal.getIDDecoder();
+        
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("TrigRateFrame");
+        
+        IPlotterStyle style;
+        
+        IPlotter plotter_hitmap_gr = af.createPlotterFactory().create();
+        plotter_hitmap_gr.createRegions(2,nThr+1,0);
+        plotter_hitmap_gr.setTitle("Cluster hit map");
+        plotter_hitmap_gr.style().statisticsBoxStyle().setVisible(false);
+        plotterFrame.addPlotter(plotter_hitmap_gr);
+
+        IPlotter plotter_hitmap_1 = af.createPlotterFactory().create();
+        plotter_hitmap_1.createRegions(1);
+        plotter_hitmap_1.setTitle("Cluster hit map");
+        plotter_hitmap_1.style().statisticsBoxStyle().setVisible(false);
+        plotterFrame.addPlotter(plotter_hitmap_1);
+
+        IPlotter plotter_hitY_gr = af.createPlotterFactory().create();
+        plotter_hitY_gr.createRegions(2,nThr+1,0);
+        plotter_hitY_gr.setTitle("Cluster hit Y");
+        plotter_hitY_gr.style().statisticsBoxStyle().setVisible(false);
+        plotterFrame.addPlotter(plotter_hitY_gr);
+
+        IPlotter plotter_hitTheta_gr = af.createPlotterFactory().create();
+        plotter_hitTheta_gr.createRegions(2,nThr+1,0);
+        plotter_hitTheta_gr.setTitle("Cluster hit theta");
+        plotter_hitTheta_gr.style().statisticsBoxStyle().setVisible(false);
+        plotterFrame.addPlotter(plotter_hitTheta_gr);
+
+        
+        IPlotter plotter_ep_gr = af.createPlotterFactory().create();
+        plotter_ep_gr.createRegions(2,nThr+1,0);
+        plotter_ep_gr.setTitle("Cluster E over p");
+        plotter_ep_gr.style().statisticsBoxStyle().setVisible(false);
+        plotterFrame.addPlotter(plotter_ep_gr);
+
+        
+        IHistogram hm = aida.histogram2D("Cluster hit map", 52, -25.5, 25.5, 6, -5.5, 5.5);
+        plotter_hitmap_1.region(0).plot(hm);            
+        style = plotter_hitmap_1.region(0).style();
+        style.setParameter("hist2DStyle", "colorMap");
+        style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        ((PlotterRegion) plotter_hitmap_1.region(0)).getPlot().setAllowUserInteraction(true);
+        ((PlotterRegion) plotter_hitmap_1.region(0)).getPlot().setAllowPopupMenus(true);
+        
+        
+        for(int iside=0;iside<2;++iside) {
+            String side = iside==0 ? "top" : "bottom";
+            double ymin = iside == 0 ? -0.5 : -5.5;
+            double ymax = iside == 0 ? 5.5 : 0.5;
+            
+            IHistogram h = aida.histogram2D("Hit map " + side, 26, -25.5, 0.5, 6, ymin, ymax);
+            plotter_hitmap_gr.region((nThr+1)*iside).plot(h);
+
+            
+            IHistogram hy = aida.histogram1D("Hit Y " + side, 7, -0.5, 6.5);
+            plotter_hitY_gr.region((nThr+1)*iside).plot(hy);
+            
+            IHistogram hth = aida.histogram1D("Hit theta " + side, 10, 0, 80);
+            plotter_hitTheta_gr.region((nThr+1)*iside).plot(hth);
+            
+            IHistogram hep = aida.histogram1D("Cluster Eoverp " + side, 50, 0, 2);
+            plotter_ep_gr.region((nThr+1)*iside).plot(hep);
+            
+            
+            for(int i=0;i<nThr;++i) {            
+                int reg = ((nThr+1)*iside)+(i+1);
+                if(debug) System.out.println("reg " + reg);
+                h = aida.histogram2D("Hit map E>" + eThr[i] + "MeV "  + side, 26, -25.5, 0.5, 6, ymin, ymax);
+                plotter_hitmap_gr.region(reg).plot(h);
+                
+                hy = aida.histogram1D("Hit Y E>" + eThr[i] + "MeV " + side, 7, -0.5,6.5);
+                plotter_hitY_gr.region(reg).plot(hy);
+
+                hth = aida.histogram1D("Hit theta E>" + eThr[i] + "MeV " + side, 20, 0,80);
+                plotter_hitTheta_gr.region(reg).plot(hth);
+
+                
+                for(int icol=-23;icol<=23;++icol) {
+                    hityCol[i][icol+23] = aida.histogram1D("Hit Y E>" + eThr[i] + "MeV " + side + " col"+icol, 7, -0.5,6.5);
+                }
+                
+                hep = aida.histogram1D("Eoverp E>" + eThr[i] + "MeV " + side, 50, 0,2);
+                plotter_ep_gr.region(reg).plot(hep);
+                
+            
+            }
+        }
+        
+
+        for(int i=0;i<2*(nThr+1);++i) {
+                            
+            if(debug) System.out.println("i " + i);
+
+            style = plotter_hitmap_gr.region(i).style();
+            style.setParameter("hist2DStyle", "colorMap");
+            style.dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+            ((PlotterRegion) plotter_hitmap_gr.region(i)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) plotter_hitmap_gr.region(i)).getPlot().setAllowPopupMenus(true);
+        }
+
+        
+        
+        for(int irow=-5;irow<=5;++irow) {
+            for(int icol=-23;icol<=23;++icol) {
+                clusterEnergy[icol+23][irow+5] = aida.histogram1D("Cluster energy x=" + icol + " y=" + irow, 50, 0,6000);  
+            }
+        }
+        
+        meanClusterEnergy = aida.histogram2D("Mean cluster energy", 47, -23, 23, 11, -5, 5);
+        
+        IPlotter plotter_clE = af.createPlotterFactory().create();
+        //plotter_clE.createRegions(2,6,0);
+        plotter_clE.setTitle("Cluster Energy");
+        plotter_clE.style().statisticsBoxStyle().setVisible(false);
+        plotter_clE.style().setParameter("hist2DStyle", "colorMap");
+        plotter_clE.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter_clE.currentRegion().plot(meanClusterEnergy);
+        
+        plotterFrame.addPlotter(plotter_clE);
+        
+        
+            
+        if(!hideFrame) {
+
+            plotterFrame.pack();
+            plotterFrame.setVisible(true);
+        }
+               
+        
+        
+      
+        
+        
+        
+    }
+    
+    public TrigRateDriver() {
+    
+        trkMatchTool = new EcalTrackMatch(false);
+    
+    }
+    
+
+    
+
+    public void setDebug(boolean flag) {
+        this.debug = flag;
+    }
+    
+    public void setOutputPlotFileName( String name ) {
+        this.outputPlotFileName = name;
+    }
+    
+    public void setHideFrame( boolean val ) {
+        this.hideFrame = val;
+    }
+    
+    public void setSimTrigger(boolean simTrigger) {
+        this.simTrigger = simTrigger;
+    }
+    
+    
+    public void process(EventHeader event) {
+        ++nevents;
+        if( debug ) {
+            System.out.println("Processing event " + nevents);    
+        }
+        
+        if( refreshRate > 0 && nevents % refreshRate == 0 ) {
+            redraw();
+        }
+        
+        
+        if(simTrigger) {
+            boolean trigger = false;
+            if(event.hasCollection(HPSEcalCluster.class, triggerClusterCollectionName)) {
+                for(HPSEcalCluster cluster : event.get(HPSEcalCluster.class, triggerClusterCollectionName)) {
+                    if(cluster.getEnergy() > triggerThreshold) {
+                        trigger = true;
+                    }
+                }
+            }
+            if(!trigger) {
+                if(debug) {
+                    System.out.println("event " + nevents + " did NOT trigger using simTrigger");
+                }
+                return;
+            }
+            if(debug) {
+                System.out.println("event " + nevents + " triggered using simTrigger");
+            }
+        }
+        
+        
+        //fastTracking(event);
+        
+        List<HPSEcalCluster> clusters = event.get(HPSEcalCluster.class, ecalClusterCollectionName); 
+        
+        
+        if(debug) System.out.println( clusters.size() + " ECal clusters in the event");
+        
+        //plotClusterDistr(clusters,"");
+        
+        
+        List<Track> tracks = null;
+        if(doTracking) {
+            if(event.hasCollection(Track.class, trackCollectionName)) {
+                tracks = event.get(Track.class, trackCollectionName);
+            } else {
+                tracks = new ArrayList<Track>();
+            }
+            if(debug) System.out.println( tracks.size() + " tracks in this event");
+        }
+        
+        
+        for(HPSEcalCluster cl : clusters) {
+            
+            int[] clusterPosIdx = new int[2];
+            clusterPosIdx[0] = cl.getSeedHit().getIdentifierFieldValue("ix");
+            clusterPosIdx[1] = cl.getSeedHit().getIdentifierFieldValue("iy");
+            //Uses shower max position -> update ix,iy above? --> FIX THIS!
+            double clusterPosY = cl.getPosition()[1];
+            double clusterPosZ = cl.getPosition()[2];         
+            String side = clusterPosIdx[1]>0 ? "top" : "bottom";
+            int iside = clusterPosIdx[1]>0 ? 0 : 1;
+            
+            int hitY = clusterPosIdx[1]>0 ? clusterPosIdx[1] : (-1*clusterPosIdx[1]);
+            double hitTheta = Math.atan(clusterPosY/(clusterPosZ-BeamlineConstants.HARP_POSITION_TESTRUN));
+            //x-check
+            if(hitTheta<0) {
+                if(!"bottom".equals(side)) {
+                    throw new RuntimeException("Hit theta was inconsistent with side!");
+                }
+                hitTheta *= -1;
+            }
+            
+            clusterEnergy[clusterPosIdx[0]+23][clusterPosIdx[1]+5].fill(cl.getEnergy());
+            aida.histogram2D("Cluster hit map").fill(clusterPosIdx[0], clusterPosIdx[1]);
+            aida.histogram2D("Hit map " + side).fill(clusterPosIdx[0], clusterPosIdx[1]);
+            aida.histogram1D("Hit Y " + side).fill(hitY);
+            aida.histogram1D("Hit theta " + side).fill(hitTheta*1000.0); //mrad
+                    
+            double eoverp = -1;
+            if(doTracking) {
+                trkMatchTool.setCluster(cl);
+                trkMatchTool.match(tracks);
+                if(trkMatchTool.isMatchedY(20)) {
+                    eoverp = cl.getEnergy()/(trkMatchTool.getMatchedTrack().getPX()*1000);
+                }   
+            }
+            if(eoverp>0) aida.histogram1D("Eoverp " + side).fill(eoverp);
+
+            if(debug) System.out.println("Ep = " + eoverp + " doTracking " + doTracking);
+
+            for(int i=0;i<nThr;++i){
+                if(cl.getEnergy()>eThr[i]) {
+                    aida.histogram2D("Hit map E>" + eThr[i] + "MeV " + side).fill(clusterPosIdx[0], clusterPosIdx[1]);
+                    aida.histogram1D("Hit Y E>" + eThr[i] + "MeV " + side).fill(hitY);
+                    aida.histogram1D("Hit theta E>" + eThr[i] + "MeV " + side).fill(hitTheta*1000.0); //mrad
+                    if(eoverp>0) aida.histogram1D("Eoverp E>" + eThr[i] + "MeV " + side).fill(eoverp);
+                    hityCol[i][clusterPosIdx[0]+23].fill(clusterPosIdx[1]);
+                }
+
+            }
+
+
+        }
+        
+
+    
+    
+    
+    
+    }
+       
+    
+    
+    
+  
+    
+    
+ 
+      
+    
+    
+     
+    private boolean hasBadNeighbours(HPSEcalCluster cluster) {
+        //check if this cluster has a neighbour that is dead or bad
+        if(!EcalConditions.badChannelsLoaded()) return false;
+        List<CalorimeterHit> hits = cluster.getCalorimeterHits();
+        IIdentifierHelper helper = EcalConditions.getHelper();
+        IExpandedIdentifier expId = new ExpandedIdentifier(helper.getIdentifierDictionary().getNumberOfFields());
+        expId.setValue(helper.getFieldIndex("system"), ecal.getSystemID());
+        
+        boolean bad = false;
+        
+        System.out.println("Checking cluster with " + cluster.getSize() + " hits for bad neighbours");
+        
+        for(CalorimeterHit hit : hits) {
+            IIdentifier compactId = hit.getIdentifier();   
+            //x-check
+            if(EcalConditions.isBadChannel(hit.getCellID())) {
+                System.out.println("This cluster has a bad channel hit included!? ");
+                int x = helper.getValue(compactId, "ix");
+                int y = helper.getValue(compactId, "iy");
+                System.out.println(x + "," + y + " id " + hit.getCellID());
+                System.exit(1);
+            }
+            //Find crystal pair
+            
+              
+                        
+            int x = helper.getValue(compactId, "ix");
+            int y = helper.getValue(compactId, "iy");
+            System.out.println("Hit at " + x + "," + y);
+            for(int ix=x-1;ix!=x+2;++ix) {
+                for(int iy=y-1;iy!=y+2;++iy) {
+                    expId.setValue(helper.getFieldIndex("ix"), ix);
+                    expId.setValue(helper.getFieldIndex("iy"), iy);
+                    IIdentifier compactId_t = helper.pack(expId);
+                    System.out.println("Check" + ix + "," + iy + " id " + compactId_t.getValue());
+                    if(EcalConditions.isBadChannel(compactId_t.getValue())) {
+                        System.out.println("This cell was BAD!");
+                        return true;
+                    }
+                }    
+            }
+            
+            
+        }
+        return false;
+        
+    }
+     
+    
+    
+    
+ 
+   
+
+    
+    private void redraw() {
+         //System.out.println("redraw");
+         if(meanClusterEnergy.entries()>0) {
+         meanClusterEnergy.reset();
+         //System.out.println("redraw cluster energy");
+         for(int irow=-5;irow<=5;++irow) {
+            for(int icol=-23;icol<=23;++icol) {
+                //System.out.println(irow+" "+icol);
+                if(clusterEnergy[icol+23][irow+5].entries()>5) {
+                    meanClusterEnergy.fill(icol,irow,clusterEnergy[icol+23][irow+5].mean());
+                }
+            }
+        }
+         }
+    }
+        
+    
+    
+    public void endOfData() {
+        if(nevents>0){
+            redraw();
+        }
+        
+        
+        
+        
+        
+        if (outputPlotFileName != "")
+        try {
+            aida.saveAs(outputPlotFileName);
+        } catch (IOException ex) {
+            Logger.getLogger(TrigRateDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+        }
+        //displayFastTrackingPlots();
+        
+    }
+
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
TriggerTurnOnAnalysis.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TriggerTurnOnAnalysis.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TriggerTurnOnAnalysis.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,392 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import hep.physics.vec.Hep3Vector;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.base.ParticleTypeClassifier;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.analysis.ecal.HPSMCParticlePlotsDriver;
+import org.lcsim.hps.evio.TriggerData;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson
+ */
+public class TriggerTurnOnAnalysis extends Driver {
+    private boolean _DEBUG = false;
+    private String ecalClusterCollectionName = "EcalTriggerClusters";
+    private String triggerDataCollectionName = "TriggerStatus";
+    
+    private int totalEvents = 0;
+    
+    private List<MCParticle> electrons = null;
+    private List<MCParticle> positrons = null;
+    
+    private IHistogram1D hCountTrig;
+    private IHistogram1D hThetay;
+    private IHistogram1D hThetayAll;
+    private IHistogram2D hThetayvsEAll;
+    private IHistogram1D hThetaySmallest;
+    private IHistogram1D hThetaySmallestEcut;
+    private IHistogram1D hTrigThetaySmallestEcut;
+    private IHistogram1D hThetayLargest;
+    private IHistogram1D hThetayLargestEcut;
+    private IHistogram1D hTrigThetayLargestEcut;
+    private IHistogram2D hThetaySmallestvsE;
+    private IHistogram2D hTrigThetaySmallestvsE;
+    private IHistogram2D hThetayLargestvsE;
+    private IHistogram2D hTrigThetayLargestvsE;
+    private IHistogram2D hThetayvsThetay;
+    private IHistogram2D hTrigThetayvsThetay;
+    private IHistogram2D hele1vsele2;
+    
+    private boolean _hideFrame = false;
+    private String _aidaFileName = "trigturnonanalysis.aida";
+    private AIDA aida = AIDA.defaultInstance();
+    private IAnalysisFactory af = aida.analysisFactory();
+    IHistogramFactory hf = aida.histogramFactory();
+    IPlotter plotter_count;
+    IPlotter plotter_count_1;
+    IPlotter plotter_count_2;
+    IPlotter plotter_count_3;
+    IPlotter plotter_count_4;
+    IPlotter plotter_count_11;
+    IPlotter plotter_count_22;
+    
+    
+    public void setHideFrame(boolean hide) {
+        this._hideFrame = hide;
+    }
+    
+    public void setAidaFileName(String filename) {
+        this._aidaFileName = filename;
+    }
+    
+    @Override
+    public void detectorChanged(Detector detector) {
+        
+        
+        makePlots();
+        
+        
+
+    }
+    
+    @Override
+    public void process(EventHeader event) {
+
+        if(_DEBUG) System.out.println(this.getClass().getSimpleName() + ": Process event " + event.getEventNumber());
+
+        List<MCParticle> mcparticles = null;
+        if(event.hasCollection(MCParticle.class)) {
+            mcparticles = event.get(MCParticle.class).get(0);
+            if(_DEBUG) System.out.println(this.getClass().getSimpleName() + ": Number of MC particles = " + mcparticles.size());
+
+            List<MCParticle> fsParticles = HPSMCParticlePlotsDriver.makeGenFSParticleList(mcparticles);
+            if(_DEBUG) System.out.println(this.getClass().getSimpleName()+": Number of FS MC particles = " + fsParticles.size());
+            electrons = this.getTriggerCandidates(11, -1, -1, fsParticles);
+            positrons = this.getTriggerCandidates(-11, -1, -1, fsParticles);
+            if(_DEBUG) {
+                System.out.println(this.getClass().getSimpleName()+": " + electrons.size() + " electrons");
+                System.out.println(this.getClass().getSimpleName()+": " + positrons.size() + " electrons");
+            }
+            
+            
+        }
+        else {
+            System.out.println(this.getClass().getSimpleName() + ": no MC particles in this event");
+        }
+        
+        
+
+        
+        List<TriggerData> trigger_data = null;
+        
+        if(event.hasCollection(TriggerData.class, triggerDataCollectionName)) {
+            trigger_data = event.get(TriggerData.class, triggerDataCollectionName);
+            if(_DEBUG) System.out.println(this.getClass().getSimpleName() + ": event " + event.getRunNumber() + " has trigger data");
+        }
+        else {
+            if(_DEBUG) System.out.println(this.getClass().getSimpleName() + ": event " + event.getRunNumber() + " has no trigger data");
+        }
+        
+        List<HPSEcalCluster> clusters = null;
+        if( event.hasCollection(HPSEcalCluster.class, ecalClusterCollectionName) ) {
+            clusters = event.get(HPSEcalCluster.class, ecalClusterCollectionName);
+            if(_DEBUG) System.out.println(this.getClass().getSimpleName() + ": event " + event.getRunNumber() + " has " + clusters.size() + " ecal clusters");
+        }
+        else {
+            if(_DEBUG) System.out.println(this.getClass().getSimpleName() + ": event " + event.getRunNumber() + " has no ecal clusters");
+        }
+        
+        //fill counting histogram
+        hCountTrig.fill( trigger_data == null ? 0 : 1);
+        
+        //find smallest angle of the proposed pair that fired the trigger
+        
+        // Use electron/positron with highest E
+        MCParticle electron = null;
+        for(MCParticle e : electrons) {
+            hThetayAll.fill( Math.abs(Math.atan(e.getMomentum().y()/e.getMomentum().z())) );
+            hThetayvsEAll.fill( Math.abs(Math.atan(e.getMomentum().y()/e.getMomentum().z())) , e.getEnergy() );
+            
+            if (electron==null) {
+                electron = e;
+            } else {
+                if(e.getEnergy() > electron.getEnergy()) {
+                    electron = e;
+                }
+            }
+        }
+        if(electrons.size()>=2) {
+            hele1vsele2.fill(electrons.get(0).getEnergy(),electrons.get(1).getEnergy());
+        }
+        MCParticle positron = null;
+        for(MCParticle e : positrons) {
+            hThetayAll.fill( Math.abs(Math.atan(e.getMomentum().y()/e.getMomentum().z())) );
+            hThetayvsEAll.fill( Math.abs(Math.atan(e.getMomentum().y()/e.getMomentum().z())) , e.getEnergy() );
+            if (positron==null) {
+                positron = e;
+            } else {
+                if(e.getEnergy() > positron.getEnergy()) {
+                    positron = e;
+                }
+            }
+        }
+
+            
+        if(electron!=null && positron!=null) {
+            double electron_thetay = Math.abs(Math.atan(electron.getMomentum().y()/electron.getMomentum().z()));               
+            double positron_thetay = Math.abs(Math.atan(positron.getMomentum().y()/positron.getMomentum().z()));
+            double electron_E = electron.getEnergy();
+            double positron_E = positron.getEnergy();
+            double thetay_smallest = electron_thetay < positron_thetay ? electron_thetay : positron_thetay;
+            double E_thetay_smallest = electron_thetay < positron_thetay ? electron.getEnergy() : positron.getEnergy();
+            double thetay_largest = electron_thetay < positron_thetay ? positron_thetay : electron_thetay;
+            double E_thetay_largest = electron_thetay < positron_thetay ? positron.getEnergy() : electron.getEnergy();
+      
+            double highest_E = -1;//electron.getEnergy() > positron.getEnergy() ? electron.getEnergy() : positron.getEnergy();
+            double highest_E_thetay = -1;//electron.getEnergy() > positron.getEnergy() ? electron_thetay : positron_thetay;
+
+            if(electron_thetay > positron_thetay && electron_E > positron_E) {
+                highest_E_thetay = electron_thetay;
+                highest_E = electron_E;
+            } else if(electron_thetay < positron_thetay && electron_E < positron_E) {
+                highest_E_thetay = positron_thetay;
+                highest_E = positron_E;
+            }
+            
+            
+            hThetay.fill( electron_thetay );
+            hThetay.fill( positron_thetay );
+            hThetaySmallest.fill( thetay_smallest );
+            if(highest_E>0) hThetayLargest.fill( highest_E_thetay );
+            hThetaySmallestvsE.fill(thetay_smallest, E_thetay_smallest);
+            if(highest_E>0) hThetayLargestvsE.fill(highest_E_thetay, highest_E);
+            hThetayvsThetay.fill(thetay_smallest, thetay_largest );
+            if(E_thetay_smallest>0.0) {
+                hThetaySmallestEcut.fill( thetay_smallest );
+                hThetayLargestEcut.fill( highest_E_thetay );
+                if(trigger_data!=null) {
+                    hTrigThetaySmallestvsE.fill(thetay_smallest, E_thetay_smallest);
+                    if(highest_E>0) hTrigThetayLargestvsE.fill(highest_E_thetay, highest_E);
+                    hTrigThetayvsThetay.fill(thetay_smallest, thetay_largest );
+                    hTrigThetaySmallestEcut.fill( thetay_smallest );
+                    if(highest_E>0) hTrigThetayLargestEcut.fill( highest_E_thetay );
+                } 
+            }
+            
+            
+        }
+        if(totalEvents % 500 == 0 && !this._hideFrame) updatePlots(); //plots are updated at end of data anyway
+        totalEvents++;
+        
+    }
+    
+    MCParticle ele_cand = null;
+    MCParticle pos_cand = null;
+    
+    List<MCParticle> getTriggerCandidates(int pdgid, double E_cut, double thetay_cut, List<MCParticle> fsParticles) {
+        List<MCParticle> particles  = new ArrayList<MCParticle>();
+        for(MCParticle particle : fsParticles) {
+            int pdgID = particle.getPDGID();
+            if(pdgid!=pdgID) continue;
+            if(E_cut>0 && particle.getEnergy()<E_cut) continue;
+            Hep3Vector p = particle.getMomentum();
+            double thetay = Math.abs(Math.atan(p.y()/p.z()));
+            if(thetay_cut>0 && thetay<thetay_cut) continue;
+            particles.add(particle);
+        }
+        return particles;
+   }
+    
+    @Override
+   public void endOfData() {
+        updatePlots();
+        if (!"".equals(this._aidaFileName))
+        try {
+            aida.saveAs(this._aidaFileName);
+        } catch (IOException ex) {
+            Logger.getLogger(TrigRateDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + this._aidaFileName, ex);
+        }
+        
+        if(this._hideFrame) {
+            plotter_count.hide();
+            plotter_count_1.hide();
+            plotter_count_11.hide();
+            plotter_count_2.hide();
+            plotter_count_22.hide();
+            plotter_count_3.hide();
+            plotter_count_4.hide();
+        }
+        
+   }
+    
+    
+   private void makePlots() {
+        hCountTrig = aida.histogram1D("hCountTrig",2,0,2);
+        hThetay = aida.histogram1D("Theta_y",50,0,0.1);
+        hThetayAll = aida.histogram1D("Theta_y all",50,0,0.1);
+        
+        hThetayvsEAll = aida.histogram2D("Theta_y vs E all",25,0,0.1,20,0,2.);
+        hThetaySmallest = aida.histogram1D("Theta_y smallest",50,0,0.05);
+        hThetaySmallestEcut = aida.histogram1D("Theta_y smallest Ecut",50,0,0.05);
+        hTrigThetaySmallestEcut = aida.histogram1D("Triggered Theta_y smallest Ecut",50,0,0.05);
+        hTrigThetaySmallestEcut.annotation().addItem("xAxisLabel", "Theta_y [rad]");
+        hThetayLargest = aida.histogram1D("Theta_y largest",50,0,0.05);
+        hThetayLargestEcut = aida.histogram1D("Theta_y largest Ecut",50,0,0.05);
+        hTrigThetayLargestEcut = aida.histogram1D("Triggered Theta_y largest Ecut",50,0,0.05);
+        hTrigThetayLargestEcut.annotation().addItem("xAxisLabel", "Theta_y [rad]");
+        hThetaySmallestvsE = aida.histogram2D("Theta_y smallest vs E",25,0,0.1,20,0,2.);
+        hTrigThetaySmallestvsE = aida.histogram2D("Triggered Theta_y smallest vs E",25,0,0.1,20,0,2.);
+        hThetayLargestvsE = aida.histogram2D("Theta_y largest vs E",25,0,0.1,20,0,2.);
+        hTrigThetayLargestvsE = aida.histogram2D("Triggered Theta_y largest vs E",25,0,0.1,20,0,2.);
+        hThetayvsThetay = aida.histogram2D("Theta_y for e+e- pair",50,0,0.1,50,0,0.2);
+        hTrigThetayvsThetay = aida.histogram2D("Triggered Theta_y for e+e- pair",50,0,0.1,50,0,0.2);
+        
+        hele1vsele2 = aida.histogram2D("hele1vsele2", 50,0,2,50,0,2);
+        
+        plotter_count = af.createPlotterFactory().create();
+        plotter_count.createRegions(2,2);
+        plotter_count.setTitle("Trigger Count");
+        plotter_count.style().setParameter("hist2DStyle", "colorMap");
+        plotter_count.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter_count.region(0).plot(hCountTrig);
+        plotter_count.region(1).plot(hThetayvsEAll);
+        plotter_count.region(2).plot(hThetay);
+        plotter_count.region(3).plot(hThetayAll);
+        
+        plotter_count_1 = af.createPlotterFactory().create();
+        plotter_count_1.createRegions(2,2);
+        plotter_count_1.setTitle("Acceptance vs Thetay");
+        plotter_count_1.region(0).plot(hThetaySmallest);
+        plotter_count_1.region(1).plot(hThetaySmallestEcut);
+        plotter_count_1.region(2).plot(hTrigThetaySmallestEcut);
+        plotter_count_1.region(3).style().statisticsBoxStyle().setVisible(false);
+        
+        plotter_count_11 = af.createPlotterFactory().create();
+        plotter_count_11.createRegions(2,2);
+        plotter_count_11.setTitle("Acceptance vs Thetay largest");
+        //plotter_count.style().statisticsBoxStyle().setVisible(true);
+        plotter_count_11.region(0).plot(hThetayLargest);
+        plotter_count_11.region(1).plot(hThetayLargestEcut);
+        plotter_count_11.region(2).plot(hTrigThetayLargestEcut);
+        plotter_count_11.region(3).style().statisticsBoxStyle().setVisible(false);
+        
+        plotter_count_2 = af.createPlotterFactory().create();
+        plotter_count_2.createRegions(2,2);
+        plotter_count_2.setTitle("Trigger Count");
+        //plotter_count.style().statisticsBoxStyle().setVisible(true);
+        plotter_count_2.style().setParameter("hist2DStyle", "colorMap");
+        plotter_count_2.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter_count_2.region(0).plot(hThetaySmallestvsE);
+        plotter_count_2.region(1).plot(hTrigThetaySmallestvsE);
+        plotter_count_2.region(2).style().statisticsBoxStyle().setVisible(false);
+        
+        plotter_count_22 = af.createPlotterFactory().create();
+        plotter_count_22.createRegions(2,2);
+        plotter_count_22.setTitle("Trigger Count");
+        //plotter_count.style().statisticsBoxStyle().setVisible(true);
+        plotter_count_22.style().setParameter("hist2DStyle", "colorMap");
+        plotter_count_22.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter_count_22.region(0).plot(hThetayLargestvsE);
+        plotter_count_22.region(1).plot(hTrigThetayLargestvsE);
+        plotter_count_22.region(2).style().statisticsBoxStyle().setVisible(false);
+        
+        plotter_count_3 = af.createPlotterFactory().create();
+        plotter_count_3.createRegions(1,2);
+        plotter_count_3.setTitle("Trigger Count");
+        //plotter_count.style().statisticsBoxStyle().setVisible(true);
+        plotter_count_3.style().setParameter("hist2DStyle", "colorMap");
+        plotter_count_3.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter_count_3.region(0).plot(hThetayvsThetay);
+        plotter_count_3.region(1).plot(hTrigThetayvsThetay);
+        
+        
+        plotter_count_4 = af.createPlotterFactory().create();
+        plotter_count_4.createRegions(1,1);
+        plotter_count_4.setTitle("e- vs e-");
+        //plotter_count.style().statisticsBoxStyle().setVisible(true);
+        plotter_count_4.style().setParameter("hist2DStyle", "colorMap");
+        plotter_count_4.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+        plotter_count_4.region(0).style().statisticsBoxStyle().setVisible(false);
+        plotter_count_4.region(0).plot(hele1vsele2);
+        
+        if(!this._hideFrame) {
+            plotter_count.show();
+            plotter_count_1.show();
+            plotter_count_11.show();
+            plotter_count_2.show();
+            plotter_count_22.show();
+            plotter_count_3.show();
+            plotter_count_4.show();
+        }
+        
+        
+   }
+    
+   private void updatePlots() {
+       
+       //hTrigEffThetaySmallest = aida.histogram1D("hTrigEffThetaySmallest",50,0,0.1);
+       IHistogram1D hTrigEffThetaySmallest = hf.divide("Trigger efficiency vs Theta_y smallest", hTrigThetaySmallestEcut, hThetaySmallestEcut);
+       hTrigEffThetaySmallest.annotation().addItem("xAxisLabel", "Theta_y [rad]");
+       hTrigEffThetaySmallest.annotation().addItem("yAxisLabel", "Trigger Efficiency");
+       plotter_count_1.region(3).clear();
+       plotter_count_1.region(3).style().statisticsBoxStyle().setVisible(false);
+       plotter_count_1.region(3).plot(hTrigEffThetaySmallest);
+       IHistogram2D hTrigEffThetaySmallestvsE = hf.divide("Trigger efficiency Theta_y vs E smallest", hTrigThetaySmallestvsE,hThetaySmallestvsE);
+       hTrigEffThetaySmallestvsE.annotation().addItem("xAxisLabel", "Theta_y [rad]");
+       hTrigEffThetaySmallestvsE.annotation().addItem("yAxisLabel", "Energy [GeV]");
+       plotter_count_2.region(2).clear();
+       plotter_count_2.region(2).style().statisticsBoxStyle().setVisible(false);
+       plotter_count_2.region(2).plot(hTrigEffThetaySmallestvsE);
+       
+       IHistogram1D hTrigEffThetayLargest = hf.divide("Trigger efficiency vs Theta_y largest", hTrigThetayLargestEcut, hThetayLargestEcut);
+       hTrigEffThetayLargest.annotation().addItem("xAxisLabel", "Theta_y [rad]");
+       hTrigEffThetayLargest.annotation().addItem("yAxisLabel", "Trigger Efficiency");
+       plotter_count_11.region(3).clear();
+       plotter_count_11.region(3).style().statisticsBoxStyle().setVisible(false);
+       plotter_count_11.region(3).plot(hTrigEffThetayLargest);   
+       IHistogram2D hTrigEffThetayLargestvsE = hf.divide("Trigger efficiency Theta_y vs E largest", hTrigThetayLargestvsE,hThetayLargestvsE);
+       hTrigEffThetayLargestvsE.annotation().addItem("xAxisLabel", "Theta_y [rad]");
+       hTrigEffThetayLargestvsE.annotation().addItem("yAxisLabel", "Energy [GeV]");
+       plotter_count_22.region(2).clear();
+       plotter_count_22.region(2).style().statisticsBoxStyle().setVisible(false);
+       plotter_count_22.region(2).plot(hTrigEffThetayLargestvsE);
+       
+   }
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
TruthMomentumResolutionDriver.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TruthMomentumResolutionDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TruthMomentumResolutionDriver.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,417 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import java.io.IOException;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.Track;
+import org.lcsim.event.base.ParticleTypeClassifier;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.analysis.ecal.HPSMCParticlePlotsDriver;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author mgraham
+ */
+public class TruthMomentumResolutionDriver extends Driver {
+
+   
+    private String outputPlotFileName="";
+    private boolean hideFrame = false;
+    int totalTracks = 0;
+    private boolean _debug = false;
+    private AIDA aida = AIDA.defaultInstance();
+    private AIDAFrame pFrame;
+    IAnalysisFactory af = aida.analysisFactory();
+    IPlotter pPlotter;
+    IPlotter pPlotter2;
+    IPlotter pPlotter22;
+    IPlotter pPlotter3;    
+    IHistogram1D hElectronP;
+    IHistogram1D hPositronP;
+    IHistogram1D hTrackP;
+    IHistogram1D hPosTrackP;
+    IHistogram1D hTruthMatchedPosTrackP;
+    IHistogram1D hTruthMatchedPosTrackPdiff;
+    IHistogram1D[] hTruthMatchedPosTrackPdiffvsP = new IHistogram1D[5];
+    IDataPointSet hTruthMatchedPosTrackPres;
+    IHistogram1D hNegTrackP;
+    IHistogram1D hTruthMatchedNegTrackP;
+    IHistogram1D hTruthMatchedNegTrackPdiff;
+    IHistogram1D[] hTruthMatchedNegTrackPdiffvsP = new IHistogram1D[5];
+    IDataPointSet hTruthMatchedNegTrackPres;
+    ICloud1D hTruthMatchedPosTrackPdiffPrev[] = new ICloud1D[5];
+    ICloud1D hTruthMatchedNegTrackPdiffPrev[] = new ICloud1D[5];
+    ICloud1D hNTracks;
+    IHistogram1D trkCountVsEventPlot;
+
+    ICloud1D hNPosTracks;
+    ICloud1D hNNegTracks;
+    ICloud1D hNPositronsForTrack;
+    ICloud1D hNElectronsForTrack;
+    ICloud1D hNPositronsForTrackInv;
+    ICloud1D hNElectronsForTrackInv;
+    
+    HashMap<Integer,MCParticle> mc_ele_prev = new HashMap<Integer, MCParticle>();
+    HashMap<Integer,MCParticle> mc_pos_prev = new HashMap<Integer, MCParticle>();
+    
+    
+    
+    public void setDebug(boolean v) {
+        this._debug = v;
+    }
+    
+    public void setOutputPlotFileName(String filename) {
+        outputPlotFileName = filename;
+    }
+    
+    public void setHideFrame(boolean hide) {
+        hideFrame = hide;
+    }
+    
+    public TruthMomentumResolutionDriver() {
+     
+    
+    }
+    
+
+    
+    public void detectorChanged(Detector detector) {
+        
+     
+      
+        pFrame = new AIDAFrame();
+        pFrame.setTitle("Truth p Plots");
+        makePlots();
+       
+   
+        
+        pFrame.pack();
+        pFrame.setVisible(!hideFrame);
+
+       
+    }
+    
+    public double getMomentum(Track track) {
+        double[] p_vec = track.getTrackStates().get(0).getMomentum();
+        return Math.sqrt(p_vec[0]*p_vec[0] + p_vec[1]*p_vec[1] +p_vec[2]*p_vec[2]);
+    }
+    
+    
+    public void process(EventHeader event) {
+
+
+        //  Create a map between tracks and the associated MCParticle
+        List<Track> tracklist = event.get(Track.class, "MatchedTracks");
+        if(_debug) System.out.println("Number of Tracks = " + tracklist.size());
+        List<MCParticle> mcparticles = event.get(MCParticle.class).get(0);
+        if(_debug) System.out.println("Number of MC particles = " + mcparticles.size());
+        List<MCParticle> fsParticles = HPSMCParticlePlotsDriver.makeGenFSParticleList(mcparticles);
+        if(_debug) System.out.println("Number of FS MC particles = " + fsParticles.size());
+        
+        
+        
+        MCParticle electron=null;
+        MCParticle positron=null;
+        
+        int nele = 0;
+        int nposi = 0;
+        for(MCParticle fs : fsParticles) {
+            if(ParticleTypeClassifier.isElectron(fs.getPDGID())) {
+                ++nele;
+                if(electron==null) electron = fs;
+                else {
+                    if(fs.getEnergy()>electron.getEnergy()) {
+                        electron = fs;
+                    } 
+                } 
+            } else if(ParticleTypeClassifier.isPositron(fs.getPDGID())) {
+                ++nposi;
+                if(positron==null) positron = fs;
+                else {
+                    if(fs.getEnergy()>positron.getEnergy()) {
+                        positron = fs;
+                    } 
+                } 
+            }
+        }
+    
+        if(electron!=null) this.hElectronP.fill(electron.getMomentum().magnitude());
+        if(positron!=null) this.hPositronP.fill(positron.getMomentum().magnitude());
+        int[] ntrks = {0,0,0};
+
+        for (Track trk : tracklist) {
+            double p = this.getMomentum(trk);
+            this.hTrackP.fill(p);
+            if(this.isElectronTrack(trk)) {
+                this.hNegTrackP.fill(p);
+                if(electron!=null) {
+                    this.hTruthMatchedNegTrackP.fill(p);
+                    this.hTruthMatchedNegTrackPdiff.fill(p - electron.getMomentum().magnitude());
+                    hTruthMatchedNegTrackPdiffvsP[this.getMomentumBin(electron.getMomentum().magnitude())].fill(p - electron.getMomentum().magnitude());   
+                    if(_debug) System.out.println("Filling ele for " + mc_ele_prev.size() + " prev ");
+                    for(Map.Entry<Integer,MCParticle> prev : mc_ele_prev.entrySet()) {
+                        if(_debug) System.out.println("prev " + prev.getKey());
+                        this.hTruthMatchedNegTrackPdiffPrev[prev.getKey()].fill(p - prev.getValue().getMomentum().magnitude());
+                    }
+                }
+                ++ntrks[2];
+            }
+            else {
+                this.hPosTrackP.fill(p);
+                if(positron!=null) {
+                    this.hTruthMatchedPosTrackP.fill(p);
+                    this.hTruthMatchedPosTrackPdiff.fill(p - positron.getMomentum().magnitude());
+                    hTruthMatchedPosTrackPdiffvsP[this.getMomentumBin(positron.getMomentum().magnitude())].fill(p - positron.getMomentum().magnitude());   
+                    if(_debug) System.out.println("Filling pos for " + mc_pos_prev.size() + " prev ");
+                    for(Map.Entry<Integer,MCParticle> prev : mc_pos_prev.entrySet()) {
+                        if(_debug) System.out.println("prev " + prev.getKey());
+                        this.hTruthMatchedPosTrackPdiffPrev[prev.getKey()].fill(p - prev.getValue().getMomentum().magnitude());
+                    }
+                }
+                ++ntrks[1];
+            }
+            
+            ++totalTracks;
+            ++ntrks[0];
+            //int q = trk.getCharge();
+        }
+        this.hNTracks.fill(ntrks[0]);
+        this.hNPosTracks.fill(ntrks[1]);
+        this.hNNegTracks.fill(ntrks[2]);
+            
+        if(ntrks[1]>0) hNPositronsForTrack.fill(nposi);
+        if(ntrks[2]>0) hNElectronsForTrack.fill(nele);
+        if(ntrks[2]>0) hNPositronsForTrackInv.fill(nposi);
+        if(ntrks[1]>0) hNElectronsForTrackInv.fill(nele);
+        
+        for(int i=0;i<tracklist.size();++i) trkCountVsEventPlot.fill(event.getEventNumber());
+        
+        //Save to list of previous truth particles
+        if(electron!=null) {
+            mc_ele_prev = this.updatePrevMap(mc_ele_prev);
+            mc_ele_prev.put(0, electron);
+        }
+        if(positron!=null) {
+            mc_pos_prev = this.updatePrevMap(mc_pos_prev);
+            mc_pos_prev.put(0, positron);
+        }   
+
+         if(totalTracks%50==0) this.updatePlots();
+        
+    }
+
+    private int getMomentumBin(double p) {
+        int p_bin = -1;
+        for(int i=0;i<5;++i) {
+            double plow = i/2.0;
+            double phigh = (i)/2.0+0.5;
+            if(p>=plow && p<phigh) {
+                p_bin = i;
+                break;
+            }
+        }
+        if(p_bin==-1) p_bin = 4;
+        return p_bin;
+    }
+    
+    private boolean isElectronTrack(Track track) {
+        //fix confusing sign flip in magnetic field!!
+        return track.getCharge()>0 ? true : false;
+    }
+    
+    private HashMap<Integer,MCParticle> updatePrevMap(HashMap<Integer,MCParticle> map) {
+        HashMap<Integer,MCParticle> newmap = new HashMap<Integer,MCParticle>();
+        for (Map.Entry<Integer, MCParticle> entry : map.entrySet()) {
+            if(entry.getKey()<4) {
+                if(_debug) System.out.println("Key e = " + entry.getKey() + ", Value = " + entry.getValue());
+                newmap.put(entry.getKey()+1, entry.getValue());
+            }
+        }
+        return newmap;
+    }
+    
+    
+
+    private MCParticle getHighestEnergyParticle(int pdgId, List<MCParticle> fsParticles) {
+        MCParticle particle = null;
+        for(MCParticle fs : fsParticles) {
+            int fsPdg = fs.getPDGID();
+            if(fsPdg==pdgId) {
+                if(particle==null) {
+                    particle = fs;
+                }
+                else {
+                    if(fs.getEnergy()>particle.getEnergy()) {
+                        particle = fs;
+                    } 
+                } 
+            }
+        }
+        return particle;
+    }
+
+
+    public void endOfData() {
+        this.updatePlots();
+        System.out.println("Total Number of Tracks Found = "+totalTracks);
+          
+        if (outputPlotFileName != "")
+        try {
+            aida.saveAs(outputPlotFileName);
+        } catch (IOException ex) {
+            Logger.getLogger(TrigRateDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+        }
+        
+    }
+    
+    private void makePlots() {
+    
+    
+        pPlotter = af.createPlotterFactory().create("Truth p Plots");
+        pPlotter.setTitle("Truth p Plots");
+        pFrame.addPlotter(pPlotter);
+        IPlotterStyle style0 = pPlotter.style();
+        //style0.dataStyle().fillStyle().setColor("yellow");
+        //style0.dataStyle().errorBarStyle().setVisible(false);
+        pPlotter.createRegions(2, 6);       
+        hTrackP = aida.histogram1D("Track p", 50, 0,4);
+        hPosTrackP = aida.histogram1D("Track p q>0", 50, 0,4);
+        hNegTrackP = aida.histogram1D("Track p q<0", 50, 0,4);
+        hTruthMatchedPosTrackP = aida.histogram1D("Track p q>0 e+ match", 50, 0,4);
+        hTruthMatchedNegTrackP = aida.histogram1D("Track p q<0 e- match", 50, 0,4);
+        hTruthMatchedPosTrackPdiff = aida.histogram1D("Track p - p(e+) q>0", 100, -0.2,0.2);
+        hTruthMatchedNegTrackPdiff = aida.histogram1D("Track p - p(e-) q<0", 100, -0.2,0.2);
+        for(int i=0;i<5;++i) {
+              double plow = i/2.0+0.5;
+              double phigh = (i+1)/2.0+0.5;
+              hTruthMatchedPosTrackPdiffvsP[i] = aida.histogram1D("Track p - p(e+) q>0 p["+plow+","+phigh+"]", 100, -0.2,0.2);
+              hTruthMatchedNegTrackPdiffvsP[i] = aida.histogram1D("Track p - p(e-) q<0 p["+plow+","+phigh+"]", 100, -0.2,0.2);
+     
+        }
+        IDataPointSetFactory dpsf = aida.analysisFactory().createDataPointSetFactory(aida.tree());
+        hTruthMatchedPosTrackPres = dpsf.create("hTruthMatchedPosTrackPres", "RMS(Track p - p(e+)) q>0 vs P",2);
+        hTruthMatchedNegTrackPres = dpsf.create("hTruthMatchedNegTrackPres", "RMS(Track p - p(e-)) q<0 vs P",2);
+        hNTracks = aida.cloud1D("Ntrks");
+        trkCountVsEventPlot = aida.histogram1D("Number of Tracks vs Event Nr", 501, -0.5, 500.5);
+	trkCountVsEventPlot.annotation().addItem("xAxisLabel", "Event Number");
+        hNPosTracks = aida.cloud1D("Ntrks q>0");
+        hNNegTracks = aida.cloud1D("Ntrks q<0");    
+        hElectronP = aida.histogram1D("Electron Momentum", 50, 0,4);
+        hPositronP = aida.histogram1D("Positron Momentum", 50, 0,4);      
+        hNPositronsForTrack = aida.cloud1D("N positrons given track with q>0");
+        hNElectronsForTrack = aida.cloud1D("N electrons given track with q<0");
+        hNPositronsForTrackInv = aida.cloud1D("N positrons given track with q<0");
+        hNElectronsForTrackInv = aida.cloud1D("N electrons given track with q>0");
+
+        
+        pPlotter.region(0).plot(hTrackP);
+        pPlotter.region(0).plot(hPosTrackP);
+        pPlotter.region(0).plot(hNegTrackP);
+        pPlotter.region(6).plot(hNTracks);
+        pPlotter.region(6).plot(hNPosTracks);
+        pPlotter.region(6).plot(hNNegTracks);     
+        pPlotter.region(1).plot(hElectronP);
+        pPlotter.region(7).plot(hPositronP);
+        pPlotter.region(2).plot(this.hTruthMatchedPosTrackP);
+        pPlotter.region(3).plot(trkCountVsEventPlot);
+        pPlotter.region(8).plot(this.hTruthMatchedNegTrackP);
+        pPlotter.region(4).plot(this.hNPositronsForTrack);
+        pPlotter.region(10).plot(this.hNElectronsForTrack);
+        pPlotter.region(5).plot(this.hNPositronsForTrackInv);
+        pPlotter.region(11).plot(this.hNElectronsForTrackInv);
+
+        
+        
+        pPlotter2 = af.createPlotterFactory().create("Resolution");
+        pPlotter2.setTitle("Resolution");
+        pFrame.addPlotter(pPlotter2);
+        style0 = pPlotter2.style();
+        //style0.dataStyle().fillStyle().setColor("yellow");
+        //style0.dataStyle().errorBarStyle().setVisible(false);
+        pPlotter2.createRegions(2, 2);
+        pPlotter2.region(0).plot(this.hTruthMatchedPosTrackPdiff);
+        pPlotter2.region(2).plot(this.hTruthMatchedNegTrackPdiff);
+        pPlotter2.region(1).plot(this.hTruthMatchedPosTrackPres);
+        pPlotter2.region(3).plot(this.hTruthMatchedNegTrackPres);
+        
+        
+        
+        pPlotter22 = af.createPlotterFactory().create("Resolutions");
+        pPlotter22.setTitle("Resolutions");
+        pFrame.addPlotter(pPlotter22);
+        style0 = pPlotter22.style();
+        //style0.dataStyle().fillStyle().setColor("yellow");
+        //style0.dataStyle().errorBarStyle().setVisible(false);
+        pPlotter22.createRegions(2, 5);
+        for(int i=0;i<5;++i) {   
+            pPlotter22.region(i).plot(this.hTruthMatchedPosTrackPdiffvsP[i]);
+            pPlotter22.region(5+i).plot(this.hTruthMatchedNegTrackPdiffvsP[i]);
+        }
+        
+       
+        pPlotter3 = af.createPlotterFactory().create("Truth p Plots");
+        pPlotter3.setTitle("Prev BS's");
+        pFrame.addPlotter(pPlotter3);
+        pPlotter3.createRegions(2, 5);
+        
+        for(int i=0;i<5;++i) {
+            hTruthMatchedPosTrackPdiffPrev[i] = aida.cloud1D("Track p - p(e+) q>0 BC=-" + i);
+            hTruthMatchedNegTrackPdiffPrev[i] = aida.cloud1D("Track p - p(e-) q<0 BC=-" + i);
+            pPlotter3.region(i).plot(hTruthMatchedPosTrackPdiffPrev[i]);
+            pPlotter3.region(5+i).plot(hTruthMatchedNegTrackPdiffPrev[i]);
+        }
+    
+    }
+   
+    
+    
+    
+    
+    
+ 
+
+
+ void updatePlots() {
+     this.hTruthMatchedNegTrackPres.clear();
+     this.hTruthMatchedPosTrackPres.clear();
+        
+     for(int i=0;i<5;++i) {
+                       
+        double plow = i/2.0+0.5;
+        double phigh = (i+1)/2.0+0.5;
+        double p = (phigh-plow)/2+plow;
+        double rms = hTruthMatchedPosTrackPdiffvsP[i].rms();
+        double n = hTruthMatchedPosTrackPdiffvsP[i].entries();
+        //aproximation
+        double rms_error = n==0? 0 :  Math.sqrt(Math.pow(hTruthMatchedPosTrackPdiffvsP[i].rms(),2)/(2*hTruthMatchedPosTrackPdiffvsP[i].entries()));
+        
+        this.hTruthMatchedPosTrackPres.addPoint();
+        this.hTruthMatchedPosTrackPres.point(i).coordinate(1).setValue(rms/p);
+        this.hTruthMatchedPosTrackPres.point(i).coordinate(1).setErrorPlus(rms_error);
+        this.hTruthMatchedPosTrackPres.point(i).coordinate(0).setValue(p);
+        this.hTruthMatchedPosTrackPres.point(i).coordinate(0).setErrorPlus((phigh-plow)/2);
+        
+       
+        rms = hTruthMatchedPosTrackPdiffvsP[i].rms();
+        n = hTruthMatchedPosTrackPdiffvsP[i].entries();
+        //aproximation
+        rms_error = n==0? 0 :  Math.sqrt(Math.pow(hTruthMatchedPosTrackPdiffvsP[i].rms(),2)/(2*hTruthMatchedPosTrackPdiffvsP[i].entries()));
+        
+        this.hTruthMatchedNegTrackPres.addPoint();
+        this.hTruthMatchedNegTrackPres.point(i).coordinate(1).setValue(rms/p);
+        this.hTruthMatchedNegTrackPres.point(i).coordinate(1).setErrorPlus(rms_error);
+        this.hTruthMatchedNegTrackPres.point(i).coordinate(0).setValue((phigh-plow)/2+plow);
+        this.hTruthMatchedNegTrackPres.point(i).coordinate(0).setErrorPlus((phigh-plow)/2);
+        
+        
+    }
+ }
+}
\ No newline at end of file

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
TwoTrackAnlysis.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TwoTrackAnlysis.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/TwoTrackAnlysis.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,1061 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IPlotter;
+import hep.aida.ref.plotter.PlotterRegion;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.tracker.silicon.DopedSilicon;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.fit.helicaltrack.HitIdentifier;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.analysis.ecal.HPSMCParticlePlotsDriver;
+import org.lcsim.hps.event.BeamlineConstants;
+import org.lcsim.hps.evio.TriggerData;
+import org.lcsim.hps.recon.ecal.HPSEcalCluster;
+import org.lcsim.hps.recon.tracking.EventQuality;
+import org.lcsim.hps.recon.tracking.HPSTrack;
+import org.lcsim.hps.recon.tracking.SvtUtils;
+import org.lcsim.hps.recon.tracking.TrackUtils;
+import org.lcsim.hps.recon.vertexing.StraightLineTrack;
+import org.lcsim.hps.recon.vertexing.TwoParticleVertexer;
+import org.lcsim.hps.recon.vertexing.TwoTrackFringeVertexer;
+import org.lcsim.hps.recon.vertexing.TwoTrackVertexer;
+import org.lcsim.event.Vertex;
+import org.lcsim.event.base.ParticleTypeClassifier;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ * Analysis class which makes a text file compatible with ROOT Tree.
+ * @author phansson <[log in to unmask]>
+ * @version $id: $
+ */
+public class TwoTrackAnlysis extends Driver {
+
+    private FileWriter fileWriter = null;
+    private PrintWriter printWriter = null;
+    private String outputNameTextTuple = "twotrackAnlysisTuple.txt";
+    private String trackCollectionName = "MatchedTracks";
+    private boolean doPrintBranchInfoLine = true; //firs tline in text file
+    private AIDA aida = AIDA.defaultInstance();
+    private int totalEvents=0;
+    private int totalTwoTrackEvents=0;
+    private int totalMCEvents=0;
+    private int totalTwoTrackMCEvents=0;
+    private boolean hideFrame = false;
+    private String outputPlotFileName;
+    private String ecalClusterCollectionName = "EcalClusters";
+    private String stereoHitCollectionName = "RotatedHelicalTrackHits";
+    private String triggerDecisionCollectionName = "TriggerBank";
+    private String MCParticleCollectionName = "MCParticle";
+    private String _stripClusterCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+    private double targetPosition = BeamlineConstants.HARP_POSITION_TESTRUN;
+    private boolean _debug;
+    private HitIdentifier _ID = new HitIdentifier();
+    private TwoTrackVertexer vertexer = new TwoTrackVertexer();
+    private TwoTrackFringeVertexer fringeVertexer = new TwoTrackFringeVertexer();
+    private TwoParticleVertexer particleVertexer = new TwoParticleVertexer();
+	private boolean _keepAllTracks = true;
+    private EventQuality.Quality trk_quality_def = EventQuality.Quality.MEDIUM;
+    private IPlotter _plotterParticleVertex;
+    private IPlotter _plotterTrackVertex;
+    private IPlotter _plotterTrackVertexFr;
+    private IPlotter _plotterTrackVertexNonBend;
+    private IPlotter _plotterTrackMult;
+    private IPlotter _plotterTrackAtConv;
+    private IHistogram1D _vtxpos_x;
+    private IHistogram1D _vtxpos_y;
+    private IHistogram1D _vtxpos_z;
+    private IHistogram1D _vtxposfr_x;
+    private IHistogram1D _vtxposfr_y;
+    private IHistogram1D _vtxposfr_z;
+    private IHistogram1D _vtxposnonb_x;
+    private IHistogram1D _vtxposnonb_y;
+    private IHistogram1D _vtxposnonb_dy;
+    private IHistogram1D _vtxposnonb_z;
+    private IHistogram1D _partvtxpos_x;
+    private IHistogram1D _partvtxpos_y;
+    private IHistogram1D _partvtxpos_z;
+    private IHistogram1D _vtxposnonb_xAtZ0;
+    private IHistogram1D _vtxposnonb_zAtTarget;
+    private IHistogram1D _vtxposnonb_angle1;
+    private IHistogram1D _vtxposnonb_angle2;
+    private IHistogram2D _ntrks_px;
+    private IHistogram1D _trk_y_at_conv_top_pos;
+    private IHistogram1D _trk_z_at_conv_top_pos;
+    private IHistogram1D _trk_y_at_conv_top_pos_fr;
+    private IHistogram1D _trk_z_at_conv_top_pos_fr;
+    private IHistogram1D _trk_y_at_conv_bot_pos;
+    private IHistogram1D _trk_z_at_conv_bot_pos;
+    private IHistogram1D _trk_y_at_conv_bot_pos_fr;
+    private IHistogram1D _trk_z_at_conv_bot_pos_fr;
+    private IHistogram1D _trk_y_at_conv_top_neg;
+    private IHistogram1D _trk_z_at_conv_top_neg;
+    private IHistogram1D _trk_y_at_conv_top_neg_fr;
+    private IHistogram1D _trk_z_at_conv_top_neg_fr;
+    private IHistogram1D _trk_y_at_conv_bot_neg;
+    private IHistogram1D _trk_z_at_conv_bot_neg;
+    private IHistogram1D _trk_y_at_conv_bot_neg_fr;
+    private IHistogram1D _trk_z_at_conv_bot_neg_fr;
+	    
+    private class CmpTrack implements Comparable<CmpTrack> {
+        private Track _track;
+        public CmpTrack(Track track) {
+            _track = track;
+        }
+        @Override
+        public int compareTo(CmpTrack t) {
+                int v = ((Double)(t._track.getTrackStates().get(0).getMomentum()[0]*100000 - _track.getTrackStates().get(0).getMomentum()[0]*100000)).intValue();
+                //System.out.printf("%s: _track = %f _t = %f  => %d \n",this.getClass().getSimpleName(),_track.getTrackStates().get(0).getMomentum()[0],t._track.getTrackStates().get(0).getMomentum()[0],v);
+                return v;
+        }
+    }
+    
+    
+    public void setDebug(boolean v) {
+        this._debug = v;
+    }
+    public void setOutputPlotFileName(String filename) {
+        outputPlotFileName = filename;
+    }
+    public void setOutputNameTextTuple(String filename) {
+        this.outputNameTextTuple = filename;
+    }
+    
+    public void setHideFrame(boolean hide) {
+        hideFrame = hide;
+    }
+    
+    public void setTrackCollectionName(String name) {
+        trackCollectionName = name;
+    }
+    
+    public void setTargetPosition(double pos) {
+        targetPosition = pos;
+    }
+    
+
+    
+    public TwoTrackAnlysis() {
+    }
+
+    
+    @Override
+    public void detectorChanged(Detector detector) {
+
+        createWriter();
+
+        if(printWriter==null)
+            System.out.println("printWriter is null");
+            
+        fillTextTupleBranches();
+
+        makePlots();
+       
+        
+    }
+    
+    
+    
+    @Override
+    public void process(EventHeader event) {
+
+        if(this._debug) 
+            System.out.println(this.getClass().getSimpleName() + ": processing event " + totalEvents + " which has event nr " + event.getEventNumber());
+            
+        
+        
+        totalEvents++;
+        
+        this.vertexer.clear();
+        this.fringeVertexer.clear();
+        this.particleVertexer.clear();
+        
+        
+        List<Track> tracklist = null;
+        if(event.hasCollection(Track.class,trackCollectionName)) {        
+            tracklist = event.get(Track.class, trackCollectionName);
+            if(_debug) System.out.println(this.getClass().getSimpleName() + ": Number of Tracks = " + tracklist.size() + " in event " + event.getEventNumber());
+        } else {
+             if(_debug)  System.out.println(this.getClass().getSimpleName() + ": No track collection in event " + event.getEventNumber());
+             return;
+        }
+        
+        
+        //if(tracklist.size()<2) {
+            //if(_debug) 
+        //        System.out.printf("%s: event %d has only %d tracks \n",this.getClass().getSimpleName(),event.getEventNumber(),tracklist.size());  
+        //    System.exit(1);
+        //    return;
+        //}
+        
+        ArrayList<CmpTrack> tracks = new ArrayList<CmpTrack>();
+        for(int i=0;i<tracklist.size();++i) {
+            Track trk = tracklist.get(i);
+			if( _keepAllTracks) {
+                tracks.add(new CmpTrack(trk));
+			}
+            else if(TrackUtils.isGoodTrack(trk, tracklist, trk_quality_def)) {
+                //System.out.printf("%s: trk momentum (%.3f,%.3f,%.3f) chi2=%.3f\n",this.getClass().getSimpleName(),trk.getTrackStates().get(0).getMomentum()[0],trk.getTrackStates().get(0).getMomentum()[1],trk.getTrackStates().get(0).getMomentum()[2],trk.getChi2());
+                if(_debug) {
+                    int cuts = TrackUtils.passTrackSelections(trk, tracklist, trk_quality_def);
+                    System.out.printf("%s: track cuts: \n%s\n",this.getClass().getSimpleName(),EventQuality.instance().print(cuts));
+                    System.out.printf("%s: trk momentum (%.3f,%.3f,%.3f) chi2=%.3f\n",this.getClass().getSimpleName(),trk.getTrackStates().get(0).getMomentum()[0],trk.getTrackStates().get(0).getMomentum()[1],trk.getTrackStates().get(0).getMomentum()[2],trk.getChi2());
+                }
+                if(trk.getChi2()>10. && _debug) {
+                    System.out.printf("%s: trk momentum (%.3f,%.3f,%.3f) chi2=%.3f\n",this.getClass().getSimpleName(),trk.getTrackStates().get(0).getMomentum()[0],trk.getTrackStates().get(0).getMomentum()[1],trk.getTrackStates().get(0).getMomentum()[2],trk.getChi2());
+                    int cuts = TrackUtils.passTrackSelections(trk, tracklist, trk_quality_def);
+                    System.out.printf("%s: track cuts: \n%s\n",this.getClass().getSimpleName(),EventQuality.instance().print(cuts));
+                    //System.exit(0);
+                }
+                tracks.add(new CmpTrack(trk));            
+			} else {
+               if(_debug) System.out.println(this.getClass().getSimpleName() + ": trk failed track selections (event nr " + event.getEventNumber() + ")\n" + trk.toString());
+            }
+        }
+        
+        Collections.sort(tracks);
+        
+        Hep3Vector vtxPos = null;
+        Hep3Vector vtxPosFringe = null;
+        Hep3Vector vtxPosNonBend = null;
+        
+        if(tracks.size()>1) {
+            Track trk1 = tracks.get(0)._track;
+            Track trk2 = tracks.get(1)._track;
+            
+            vertexer.setTracks(trk1, trk2);
+            vertexer.fitVertex();            
+			Vertex vtx = vertexer.getFittedVertex();
+			if (vtx != null) {
+				vtxPos = vertexer.getFittedVertex().getPosition();
+				fringeVertexer.setTracks(trk1, trk2);
+				fringeVertexer.fitVertex();
+				vtxPosFringe = fringeVertexer.getFittedVertex().getPosition();
+				
+				if(this._debug) {
+					System.out.printf("%s: vtxPos=%s\n", this.getClass().getSimpleName(),vtxPos.toString());
+					System.out.printf("%s: vtxPosFringe=%s\n", this.getClass().getSimpleName(),vtxPosFringe.toString());
+				}
+				
+				if(vtxPos.x() != vtxPos.x()) {
+					System.out.printf("%s: vtxPos is NaN -> Skip\n",this.getClass().getSimpleName());
+					vtxPos = null;
+				}
+				if(vtxPosFringe.x() != vtxPosFringe.x()) {
+					System.out.printf("%s: vtxPosFringe is NaN -> Skip\n",this.getClass().getSimpleName());
+					vtxPos = null;
+				}
+				
+				this._vtxpos_x.fill(vtxPos.x());
+				this._vtxpos_y.fill(vtxPos.y());
+				this._vtxpos_z.fill(vtxPos.z());            
+				
+				if(vtxPosFringe!=null) {
+					this._vtxposfr_x.fill(vtxPosFringe.x());
+					this._vtxposfr_y.fill(vtxPosFringe.y());
+					this._vtxposfr_z.fill(vtxPosFringe.z());            
+				}
+			}				
+            
+            boolean useFringe = false;
+            StraightLineTrack[] slts = this.getSLTs(trk1, trk2, useFringe);
+            double zAtCross = this.getCrossingS(trk1, trk2);
+            double[] xyAtZ1 = slts[0].calculateXYAtZ(zAtCross);
+            double[] xyAtZ2 = slts[1].calculateXYAtZ(zAtCross);
+
+            Hep3Vector[] vtxNonBend = {new BasicHep3Vector(xyAtZ1[0],xyAtZ1[1],zAtCross),new BasicHep3Vector(xyAtZ2[0],xyAtZ2[1],zAtCross)};
+            //System.out.printf("%s: vtxNonBend=%s\n", this.getClass().getSimpleName(),vtxNonBend.toString());
+            
+            this._vtxposnonb_x.fill(vtxNonBend[0].x());
+            this._vtxposnonb_y.fill(vtxNonBend[0].y());
+            this._vtxposnonb_y.fill(vtxNonBend[1].y());
+            this._vtxposnonb_dy.fill(vtxNonBend[0].y()-vtxNonBend[1].y());
+            this._vtxposnonb_z.fill(vtxNonBend[0].z());
+
+            this._vtxposnonb_xAtZ0.fill(slts[0].calculateXYAtZ(0.)[0]);
+            this._vtxposnonb_zAtTarget.fill(slts[0].getYZAtX(this.targetPosition)[1]);
+            this._vtxposnonb_angle1.fill(Math.atan(slts[0].dzdx()));
+            this._vtxposnonb_angle2.fill(Math.atan(slts[1].dzdx()));
+            
+            vtxPosNonBend = vtxNonBend[0];
+
+        }
+        
+        
+        List<HPSEcalCluster> clusters = new ArrayList<HPSEcalCluster>();
+
+        if(!event.hasCollection(HPSEcalCluster.class, ecalClusterCollectionName)) {
+            if(_debug) {
+                System.out.println(this.getClass().getSimpleName() + ": event doesn't have a ecal cluster collection ");
+            }
+        } else {
+            clusters = event.get(HPSEcalCluster.class, ecalClusterCollectionName); 
+        
+            if(_debug) {
+                System.out.println(this.getClass().getSimpleName() + ": found " + clusters.size() + " ecal clusters " + event.getEventNumber());
+            }
+        }
+        
+        Hep3Vector vtxPosMC = null;
+        MCParticle electron=null;
+        MCParticle positron=null;
+        if(event.hasCollection(MCParticle.class,this.MCParticleCollectionName)) {
+            totalMCEvents++;
+            List<MCParticle> mcparticles = event.get(MCParticle.class,this.MCParticleCollectionName);
+            List<MCParticle> fsParticles = HPSMCParticlePlotsDriver.makeGenFSParticleList(mcparticles);
+                 
+            for(MCParticle part : fsParticles) {
+                if(ParticleTypeClassifier.isElectron(part.getPDGID())) {
+                    if(electron==null) {
+                        electron = part;
+                    } else {
+                        if(part.getEnergy()>electron.getEnergy()) {
+                            electron = part;
+                        }
+                    }
+                }
+                if(ParticleTypeClassifier.isPositron(part.getPDGID())) {
+                    if(positron==null) {
+                        positron = part;
+                    } else {
+                        if(part.getEnergy()>positron.getEnergy()) {
+                            positron = part;
+                        }
+                    }
+                }
+            }
+
+            if(electron!=null && positron!=null) {
+                particleVertexer.setParticle(electron, positron);
+                particleVertexer.fitVertex();
+                vtxPosMC = particleVertexer.getFittedVertex().getPosition();
+                if(this._debug) System.out.printf("%s: vtxPosMC=%s org1 %s org2 %s\n", this.getClass().getSimpleName(),vtxPosMC.toString(),electron.getOrigin().toString(),positron.getOrigin().toString());
+                this._partvtxpos_x.fill(vtxPosMC.x());
+                this._partvtxpos_y.fill(vtxPosMC.y());
+                this._partvtxpos_z.fill(vtxPosMC.z());
+                totalTwoTrackMCEvents++;
+            }
+        }
+        
+
+        
+        totalTwoTrackEvents++;
+        try {
+            this.fillTextTuple(electron, positron, tracks, vtxPosMC, vtxPos, vtxPosFringe, vtxPosNonBend, clusters, event);
+        } catch (IOException ex) {
+            Logger.getLogger(TwoTrackAnlysis.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        
+        if(this._debug) System.out.println(this.getClass().getSimpleName() + ": # two track events so far = "+totalTwoTrackEvents);
+        //System.exit(0);
+        
+    }
+
+    
+    
+    @Override
+    public void endOfData() {
+        
+        System.out.println(this.getClass().getSimpleName() + ": Total Number of Events = "+this.totalEvents);
+        System.out.println(this.getClass().getSimpleName() + ": Total Number of Two-Track events Processed = "+this.totalTwoTrackEvents);
+        System.out.println(this.getClass().getSimpleName() + ": Total Number of MCEvents = "+this.totalMCEvents);
+        System.out.println(this.getClass().getSimpleName() + ": Total Number of Two-Track MC events Processed = "+this.totalTwoTrackMCEvents);
+        
+        if (!"".equals(outputPlotFileName)) {
+            try {
+                aida.saveAs(outputPlotFileName);
+            } catch (IOException ex) {
+                Logger.getLogger(TrigRateDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+            }
+        }
+        
+        if(printWriter==null) {
+            //Fill branches to text file (this is because detectorChanged() is called only if there are events to process
+            createWriter();
+            fillTextTupleBranches();
+        }
+            
+        
+        System.out.printf("%s: printWriter close \n",this.getClass().getSimpleName());
+        printWriter.close();
+        try {
+            fileWriter.close();
+        } catch (IOException ex) {
+            Logger.getLogger(TwoTrackAnlysis.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        
+                
+    }
+    
+    
+  
+    
+    private boolean isFileEmpty(String fileName) {
+        File f = new File(fileName);
+        return f.length() == 0; //return zero also in case file doesn't exist
+    }
+    
+    
+    private void fillTextTupleBranches() {
+        
+        if(!doPrintBranchInfoLine) {
+            throw new RuntimeException("Trying to fill tuple branches with flag being set to false?!");
+        }
+        
+        String br_line = "";                 
+        br_line+="evtnr/I:";
+        br_line+="ntrks_top/I:ntrks_bot/I:ntrks100_top/I:ntrks100_bot/I:ntrks200_top/I:ntrks200_bot/I:ntrks300_top/I:ntrks300_bot/I:ntrks400_top/I:ntrks400_bot/I:ntrks500_top/I:ntrks500_bot/I:";
+        br_line+="e_px/F:e_py/F:e_pz/F:p_px/F:p_py/F:p_pz/F:";
+        
+        for(int itrk=1;itrk<=4;++itrk) {
+            String trk_str = String.format("trk%d", itrk);
+
+            br_line+=""+trk_str+"_d0/F:"+trk_str+"_phi0/F:"+trk_str+"_R/F:"+trk_str+"_z0/F:"+trk_str+"_slope/F:";
+            br_line+=""+trk_str+"_q/I:"+trk_str+"_chi2/F:"+trk_str+"_px/F:"+trk_str+"_py/F:"+trk_str+"_pz/F:"+trk_str+"_nhits/I:";
+            for(int iLayer=1;iLayer<=5;++iLayer) br_line+=""+trk_str+"_hit"+iLayer+"_x/F:"+""+trk_str+"_hit"+iLayer+"_y/F:"+""+trk_str+"_hit"+iLayer+"_z/F:";
+            for(int iLayer=1;iLayer<=5;++iLayer) {
+                br_line+=""+trk_str+"_res"+iLayer+"_y/F:"+""+trk_str+"_res"+iLayer+"_z/F:";
+                br_line+=""+trk_str+"_eres"+iLayer+"_y/F:"+""+trk_str+"_eres"+iLayer+"_z/F:";
+                br_line+=""+trk_str+"_drdphi"+iLayer+"/F:"+""+trk_str+"_msdrphi"+iLayer+"/F:";
+                br_line+=""+trk_str+"_dz"+iLayer+"/F:"+""+trk_str+"_msdz"+iLayer+"/F:";
+                //br_line+=""+trk_str+"_ures"+iLayer+"/F:"+""+trk_str+"_ureserr"+iLayer+"/F:";
+            }
+            for(int iLayer=1;iLayer<=10;++iLayer) br_line+=""+trk_str+"_strip"+iLayer+"_u/F:"+""+trk_str+"_strip"+iLayer+"_time/F:"+""+trk_str+"_strip"+iLayer+"_E/F:";
+            
+            br_line+=""+trk_str+"_conv_y/F:"+trk_str+"_conv_z/F:";
+            br_line+=""+trk_str+"_fr_conv_x/F:"+trk_str+"_fr_conv_y/F:"+trk_str+"_fr_conv_z/F:";
+            br_line+=""+trk_str+"_target_y/F:"+trk_str+"_target_z/F:";
+            br_line+=""+trk_str+"_fr_target_x/F:"+trk_str+"_fr_target_y/F:"+trk_str+"_fr_target_z/F:";
+            //br_line+=""+trk_str+"_ecal_y/F:"+trk_str+"_ecal_z/F:";
+            br_line+=""+trk_str+"_ecal_y/F:"+trk_str+"_ecal_z/F:"+trk_str+"_fr_ecal_x/F:"+trk_str+"_fr_ecal_y/F:"+trk_str+"_fr_ecal_z/F:";
+            //br_line+=""+trk_str+"_fr_ecal_x/F:"+trk_str+"_fr_ecal_y/F:"+trk_str+"_fr_ecal_z/F:";
+            //br_line+=""+trk_str+"_fr_ecal_x/F:";
+            
+        }
+        //
+        for(int iLayer=1;iLayer<=10;++iLayer) br_line+="top_strip"+iLayer+"_n/F:";
+        for(int iLayer=1;iLayer<=10;++iLayer) br_line+="bot_strip"+iLayer+"_n/F:";
+        for(int iLayer=1;iLayer<=10;iLayer+=2) br_line+="top_stereo"+iLayer+"_n/F:";
+        for(int iLayer=1;iLayer<=10;iLayer+=2) br_line+="bot_stereo"+iLayer+"_n/F:";
+        br_line+="vtx_truth_x/F:vtx_truth_y/F:vtx_truth_z/F:";
+        br_line+="vtx_x/F:vtx_y/F:vtx_z/F:";
+        br_line+="vtx_fr_x/F:vtx_fr_y/F:vtx_fr_z/F:";
+        br_line+="vtx_nonbend_x/F:vtx_nonbend_y/F:vtx_nonbend_z/F:";
+        br_line+="cl1_E/F:cl1_ix/I:cl1_iy/I:cl1_x/F:cl1_y/F:cl1_n/I:";
+        br_line+="cl2_E/F:cl2_ix/I:cl2_iy/I:cl2_x/F:cl2_y/F:cl2_n/I:";
+        br_line+="cl3_E/F:cl3_ix/I:cl3_iy/I:cl3_x/F:cl3_y/F:cl3_n/I:";
+        br_line+="ncl_top/I:ncl_bot/I:";
+        br_line+="trig_top/I:trig_bot/I";
+        
+        if(printWriter==null) {
+            System.out.println("hmm 1");
+        }
+        printWriter.println(br_line);
+
+        doPrintBranchInfoLine = false;
+
+    }
+    
+    
+    
+    
+    private void fillTextTuple(MCParticle e, MCParticle p, List<CmpTrack> tracks, Hep3Vector vtxPosParticle, Hep3Vector vtxPos, Hep3Vector vtxPosFr, Hep3Vector vtxPosNonBend, List<HPSEcalCluster> clusters, EventHeader event) throws IOException {
+        if(doPrintBranchInfoLine) {
+            throw new RuntimeException("Need to fill tuple branches first!?");
+        }
+        
+        //Event info
+        printWriter.format("%5d ",event.getEventNumber());
+        if(tracks.size()>0) {
+        for(int icut=0;icut<=5;++icut) {
+            int ntrks[] = getNtracks(tracks,icut*0.1);
+            printWriter.format("%5d %5d ",ntrks[0],ntrks[1]);
+            this._ntrks_px.fill(0.1*icut, ntrks[0]+ntrks[1]);
+        }
+        } else {
+            printWriter.format("%5d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d ", -9999999, -9999999, -9999999, -9999999, -9999999, -9999999, -9999999, -9999999, -9999999, -9999999, -9999999, -9999999 );
+        }
+        
+        //Truth
+        if(e!=null && p!=null) printWriter.format("%5.5f %5.5f %5.5f %5.5f %5.5f %5.5f ", e.getPX(),e.getPY(),e.getPZ(), p.getPX(),p.getPY(),p.getPZ() );
+        else printWriter.format("%5.5f %5.5f %5.5f %5.5f %5.5f %5.5f ", -9999999., -9999999., -9999999., -9999999., -9999999., -9999999. );
+        
+        
+        for (int itrk=0;itrk<4;itrk++) {
+            Track trk1 = null;
+            if(tracks.size()>itrk) trk1 = tracks.get(itrk)._track;
+        
+            if(trk1!=null) {
+                SeedTrack st1 = (SeedTrack) trk1;
+                HelicalTrackFit helix1 = st1.getSeedCandidate().getHelix();     
+                List<TrackerHit> hitsOnTrack1 = trk1.getTrackerHits();
+                HashMap<Integer,HelicalTrackHit> hits1 = getHitMap(hitsOnTrack1,helix1);
+
+                printWriter.format("%5.5f %5.5f %5.5f %5.5f %5.5f ",helix1.dca(),helix1.phi0(),helix1.R(),helix1.z0(),helix1.slope());
+                printWriter.format("%5d %5.5f %5.5f %5.5f %5.5f %5d ",trk1.getCharge(),trk1.getChi2(), trk1.getTrackStates().get(0).getMomentum()[0],trk1.getTrackStates().get(0).getMomentum()[1],trk1.getTrackStates().get(0).getMomentum()[2],hitsOnTrack1.size());
+                // stupid but I want to keep one line per event so default in case there is not hits in all layers
+                for(int iLayer=0;iLayer<5;++iLayer) {
+                    HelicalTrackHit hitOnLayer = hits1.get(iLayer*2+1);// = this.getHitOnLayer(iLayer, hitsOnTrack);
+                    if (hitOnLayer != null) printWriter.format("%5.5f %5.5f %5.5f ", hitOnLayer.getPosition()[0],hitOnLayer.getPosition()[1],hitOnLayer.getPosition()[2]);
+                    else printWriter.format("%5.5f %5.5f %5.5f ", -9999999.9, -9999999.9, -9999999.9);
+                }
+
+                //Get the helix for residual calculation
+                for(int iLayer=0;iLayer<5;++iLayer) {
+                    HelicalTrackHit hitOnLayer = hits1.get(iLayer*2+1);// = this.getHitOnLayer(iLayer, hitsOnTrack);
+                    if (hitOnLayer != null) {
+                        //printWriter.format("\n%s\n","X11");
+                        Map<String,Double> res = TrackUtils.calculateTrackHitResidual(hitOnLayer, helix1, true);
+                        if( !res.isEmpty() ) {
+                        	printWriter.format("%5.5f %5.5f ",res.get("resy"),res.get("resz"));
+                        	printWriter.format("%5.5f %5.5f ",res.get("erry"),res.get("errz"));
+                        	printWriter.format("%5.5f %5.5f ", res.get("drphi"),res.get("msdrphi"));
+                        	printWriter.format("%5.5f %5.5f ", res.get("dz_res"),res.get("msdz"));
+                        } else {
+                            printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                            printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                            printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                            printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);                        	
+                        }
+                    }
+                    else {
+                        printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                        printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                        printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                        printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                    }
+                }
+                
+                HashMap<Integer,List<HelicalTrackStrip>> striphits1 = this.getStripHitsMap(hitsOnTrack1);        
+                for(int iLayer=1;iLayer<=10;++iLayer) {
+                    HelicalTrackStrip strip=null;
+                    if(striphits1.containsKey(iLayer)) strip = striphits1.get(iLayer).get(0);
+                    if(strip!=null) {
+                        printWriter.format("%5.5f %5.5f %5.5f ", strip.umeas(),strip.time(),strip.dEdx()/DopedSilicon.ENERGY_EHPAIR);
+                    }
+                    else {
+                        printWriter.format("%5.5f %5.5f %5.5f ", -99999999.9, -99999999.9, -99999999.9);
+                    }
+                }
+
+                //Track at converter
+                Hep3Vector posAtConverter = TrackUtils.extrapolateTrack(trk1,BeamlineConstants.HARP_POSITION_TESTRUN);
+                if(beamlinePosOk(posAtConverter))  printWriter.format("%5.5f %5.5f ", posAtConverter.x(),posAtConverter.y()); //note rotation from JLab->tracking
+                else printWriter.format("%5.5f %5.5f ", -9999999.9,-9999999.9);
+                HPSTrack hpstrk1 = new HPSTrack(helix1);
+                Hep3Vector posAtConverterFringe1 = hpstrk1.getPositionAtZMap(100., BeamlineConstants.HARP_POSITION_TESTRUN, 5.0)[0];
+                if (beamlinePosOk(posAtConverterFringe1)) printWriter.format("%5.5f %5.5f %5.5f ", posAtConverterFringe1.z(),posAtConverterFringe1.x(),posAtConverterFringe1.y()); //note rotation from JLab->tracking
+                else printWriter.format("%5.5f %5.5f %5.5f ", -9999999.9,-9999999.9,-9999999.9);
+                
+                Hep3Vector posAtNomTarget1 = TrackUtils.extrapolateTrack(trk1,0);
+                if(beamlinePosOk(posAtNomTarget1)) printWriter.format("%5.5f %5.5f ", posAtNomTarget1.x(),posAtNomTarget1.y()); //note rotation from JLab->tracking
+                else printWriter.format("%5.5f %5.5f ", -9999999.9,-9999999.9);
+
+                Hep3Vector posAtNomTargetFringe1 = hpstrk1.getPositionAtZMap(100., 0.0, 5.0)[0];
+                if (beamlinePosOk(posAtNomTargetFringe1)) printWriter.format("%5.5f %5.5f %5.5f ", posAtNomTargetFringe1.z(),posAtNomTargetFringe1.x(),posAtNomTargetFringe1.y()); //note rotation from JLab->tracking
+                else printWriter.format("%5.5f %5.5f %5.5f ", -9999999.9,-9999999.9,-9999999.9);
+
+                Hep3Vector posAtECal = TrackUtils.extrapolateTrack(trk1,BeamlineConstants.ECAL_FACE_TESTRUN);  
+                Hep3Vector posAtECalFringe1 = hpstrk1.getPositionAtZMap(BeamlineConstants.DIPOLE_EDGE_TESTRUN - 100, BeamlineConstants.ECAL_FACE_TESTRUN, 5.0, false)[0];
+                if(beamlinePosOk(posAtECal)) {
+                	//printWriter.format("%5.5f %5.5f ",posAtECal.x(),posAtECal.y()); //note rotation from JLab->tracking
+                	printWriter.format("%5.5f %5.5f %5.5f %5.5f %5.5f ",posAtECal.x(),posAtECal.y(),posAtECalFringe1.z(),posAtECalFringe1.x(),posAtECalFringe1.y()); //note rotation from JLab->tracking
+                } 
+                else printWriter.format("%5.5f %5.5f %5.5f %5.5f %5.5f ",-9999999.9,-9999999.9,-9999999.9,-9999999.9,-9999999.9);
+                //else printWriter.format("%5.5f %5.5f ",-9999999.9,-9999999.9);
+
+                //Hep3Vector posAtECalFringe1 = hpstrk1.getPositionAtZMap(BeamlineConstants.DIPOLE_EDGE_TESTRUN - 100, BeamlineConstants.ECAL_FACE_TESTRUN, 5.0, false)[0];
+                //if (posAtECalFringe1!=null) printWriter.format("%5.5f %5.5f %5.5f ", posAtECalFringe1.z(),posAtECalFringe1.x(),posAtECalFringe1.y()); //note rotation from JLab->tracking
+                //printWriter.format("%5.5f %5.5f %5.5f ", -9999999.9,-9999999.9,-9999999.9);
+                //if (posAtECalFringe1!=null) printWriter.format("%5.5f ", posAtECalFringe1.z()); //note rotation from JLab->tracking
+                //printWriter.format("%5.5f ", -9999999.9);
+
+                
+                if(beamlinePosOk(posAtConverter)) {
+                    if(TrackUtils.isTopTrack(trk1, 4)) {
+                        if(trk1.getCharge()>0) {
+                            this._trk_y_at_conv_top_pos.fill(posAtConverter.x());
+                            this._trk_z_at_conv_top_pos.fill(posAtConverter.y());
+                        } else {
+                            this._trk_y_at_conv_top_neg.fill(posAtConverter.x());
+                            this._trk_z_at_conv_top_neg.fill(posAtConverter.y());
+                        }
+                    } else {
+                        if(trk1.getCharge()>0) {
+                            this._trk_y_at_conv_bot_pos.fill(posAtConverter.x());
+                            this._trk_z_at_conv_bot_pos.fill(posAtConverter.y());
+                        } else {
+                            this._trk_y_at_conv_bot_neg.fill(posAtConverter.x());
+                            this._trk_z_at_conv_bot_neg.fill(posAtConverter.y());
+                        }
+                    }
+                }
+                if(beamlinePosOk(posAtConverterFringe1)) {
+                    if(TrackUtils.isTopTrack(trk1, 4)) {
+                        if(trk1.getCharge()>0) {
+                            this._trk_y_at_conv_top_pos_fr.fill(posAtConverterFringe1.x());
+                            this._trk_z_at_conv_top_pos_fr.fill(posAtConverterFringe1.y());
+                        } else {
+                            this._trk_y_at_conv_top_neg_fr.fill(posAtConverterFringe1.x());
+                            this._trk_z_at_conv_top_neg_fr.fill(posAtConverterFringe1.y());
+                        }
+                    } else {
+                        if(trk1.getCharge()>0) {
+                            this._trk_y_at_conv_bot_pos_fr.fill(posAtConverterFringe1.x());
+                            this._trk_z_at_conv_bot_pos_fr.fill(posAtConverterFringe1.y());
+                        } else {
+                            this._trk_y_at_conv_bot_neg_fr.fill(posAtConverterFringe1.x());
+                            this._trk_z_at_conv_bot_neg_fr.fill(posAtConverterFringe1.y());
+                        }
+                    }
+                }
+                
+                
+                
+            }
+            else {
+
+                printWriter.format("%5.5f %5.5f %5.5f %5.5f %5.5f ",-9999999.9,-9999999.9,-9999999.9,-9999999.9,-9999999.9);
+                printWriter.format("%5d %5.5f %5.5f %5.5f %5.5f %5d ",-9999999,-9999999.9, -9999999.9,-9999999.9,-9999999.9,-9999999);
+                for(int iLayer=0;iLayer<5;++iLayer) {
+                    printWriter.format("%5.5f %5.5f %5.5f ", -9999999.9, -9999999.9, -9999999.9);
+                }
+                for(int iLayer=0;iLayer<5;++iLayer) {
+                        printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                        printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                        printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                        printWriter.format("%5.5f %5.5f ", -9999999.9, -9999999.9);
+                }
+                for(int iLayer=1;iLayer<=10;++iLayer) {
+                    printWriter.format("%5.5f %5.5f %5.5f ", -99999999.9, -99999999.9, -99999999.9);
+                }
+                
+                printWriter.format("%5.5f %5.5f ",-9999999.9,-9999999.9); //note rotation from JLab->tracking
+                printWriter.format("%5.5f %5.5f %5.5f ",-9999999.9,-9999999.9,-9999999.9); //note rotation from JLab->tracking
+                printWriter.format("%5.5f %5.5f ",-9999999.9,-9999999.9); //note rotation from JLab->tracking
+                printWriter.format("%5.5f %5.5f %5.5f ",-9999999.9,-9999999.9,-9999999.9); //note rotation from JLab->tracking
+                printWriter.format("%5.5f %5.5f %5.5f %5.5f %5.5f ",-9999999.9,-9999999.9,-9999999.9,-9999999.9,-9999999.9); //note rotation from JLab->tracking
+                //printWriter.format("%5.5f %5.5f %5.5f ",-9999999.9,5555.5,-9999999.9); //note rotation from JLab->tracking
+                //printWriter.format("%5.5f ",-9999999.9); //note rotation from JLab->tracking
+                
+            }
+        }
+        //printWriter.format("\n%s\n","X1");
+
+
+
+        //printWriter.format("\n%s\n","X2");
+
+
+        
+
+        HashMap<Integer,List<SiTrackerHitStrip1D>> allstriphits = this.getAllStripHitsMap(event,true);
+        //System.out.printf("%s: %d strip hits in event\n",this.getClass().getSimpleName(),allstriphits.size());
+        for(int iLayer=1;iLayer<=10;++iLayer) {
+            if(allstriphits.containsKey(iLayer)) {
+                printWriter.format("%5d ", allstriphits.get(iLayer).size());
+                //System.out.printf("%s: layer %d has %d strip hits\n",this.getClass().getSimpleName(),iLayer,allstriphits.get(iLayer).size());
+            }
+            else {
+                printWriter.format("%5d ", -99999999);
+                //System.out.printf("%s: layer %d has 0 strip hits\n",this.getClass().getSimpleName(),iLayer);
+            }
+        }
+        allstriphits = this.getAllStripHitsMap(event,false);
+        for(int iLayer=1;iLayer<=10;++iLayer) {
+            if(allstriphits.containsKey(iLayer)) printWriter.format("%5d ", allstriphits.get(iLayer).size());
+            else printWriter.format("%5d ", -99999999);
+        }
+
+        List<HelicalTrackHit> stereoHits = new ArrayList<HelicalTrackHit>();
+        if(event.hasCollection(HelicalTrackHit.class, stereoHitCollectionName)) {
+            stereoHits = event.get(HelicalTrackHit.class, stereoHitCollectionName);
+        } 
+
+       
+        HashMap<Integer,List<HelicalTrackHit>> allstereohits = getAllStereoHitsMap(stereoHits,true);
+        for(int iLayer=1;iLayer<=10;iLayer+=2) {
+            if(allstereohits.containsKey(iLayer)) printWriter.format("%5d ", allstereohits.get(iLayer).size());
+            else printWriter.format("%5d ", -99999999);
+        }
+        allstereohits = getAllStereoHitsMap(stereoHits,false);
+        for(int iLayer=1;iLayer<=10;iLayer+=2) {
+            if(allstereohits.containsKey(iLayer)) printWriter.format("%5d ", allstereohits.get(iLayer).size());
+            else printWriter.format("%5d ", -99999999);
+        }
+        //printWriter.format("\n%s\n","X4");
+        
+        //Particle vtx
+        if(vtxPosParticle!=null) printWriter.format("%5.5f %5.5f %5.5f ", vtxPosParticle.x(),vtxPosParticle.y(),vtxPosParticle.z() );
+        else printWriter.format("%5.5f %5.5f %5.5f ", -9999999., -9999999., -9999999. );
+        //Track vtx
+        if(vtxPos!=null) printWriter.format("%5.5f %5.5f %5.5f ", vtxPos.x(),vtxPos.y(),vtxPos.z() );
+        else printWriter.format("%5.5f %5.5f %5.5f ", -9999999., -9999999., -9999999. );
+        if(vtxPosFr!=null) printWriter.format("%5.5f %5.5f %5.5f ", vtxPosFr.x(),vtxPosFr.y(),vtxPosFr.z() );
+        else printWriter.format("%5.5f %5.5f %5.5f ", -9999999., -9999999., -9999999. );
+        if(vtxPosNonBend!=null) printWriter.format("%5.5f %5.5f %5.5f ", vtxPosNonBend.x(),vtxPosNonBend.y(),vtxPosNonBend.z() );
+        else printWriter.format("%5.5f %5.5f %5.5f ", -9999999., -9999999., -9999999. );
+        int ncl_t=0; int ncl_b=0;
+        for(int i=0;i<3;++i) {
+            if(clusters==null) {
+                printWriter.format("%5.5f %5d %5d %5.5f %5.5f %5d ",-999999.9,-999999,-999999,-999999.,-999999.,-999999);
+            }
+            else if(clusters.size()<=i) {
+                printWriter.format("%5.5f %5d %5d %5.5f %5.5f %5d ",-999999.9,-999999,-999999,-999999.,-999999.,-999999);
+            } else {
+                //for(HPSEcalCluster cl : clusters) {
+                int iy = clusters.get(i).getSeedHit().getIdentifierFieldValue("iy");
+                int ix = clusters.get(i).getSeedHit().getIdentifierFieldValue("ix");
+                double pos[] = clusters.get(i).getPosition();
+                double E = clusters.get(i).getEnergy();
+                int clsize = clusters.get(i).getSize();
+                printWriter.format("%5.5f %5d %5d %5.5f %5.5f %5d ",E,ix,iy,pos[0],pos[1],clsize);
+                if( iy > 0) ncl_t++;
+                else ncl_b++;
+            }
+        }
+        printWriter.format("%5d %5d ",ncl_t,ncl_b);
+        TriggerData trigger = getTriggerInfo(event);
+        if(trigger==null) printWriter.format("%5d %5d",0,0);
+        else printWriter.format("%5d %5d",trigger.getTopTrig()>0?1:0,trigger.getBotTrig()>0?1:0);
+        printWriter.println();
+        
+    }
+    
+    
+    /**
+     * Check that object is not null or undefined
+     * @param pos to check
+     * @return
+     */
+    private boolean beamlinePosOk(Hep3Vector pos) {
+		if( pos == null) {
+			return false;
+		} else if ( Double.isNaN(pos.x()) || Double.isNaN(pos.y()) || Double.isNaN(pos.z()) ) {
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+    private TriggerData getTriggerInfo(EventHeader event) {
+        if(!event.hasCollection(TriggerData.class, triggerDecisionCollectionName)) {
+            if(_debug) 
+                System.out.printf( "%s: Event %d has NO trigger bank\n",this.getClass().getSimpleName(),event.getEventNumber());
+            return null;
+        } else {
+            List<TriggerData> triggerDataList = event.get(TriggerData.class, "TriggerBank");
+            if(triggerDataList.isEmpty()) {
+                if(_debug) 
+                    System.out.println( "Event has trigger bank exists but is empty");
+                return null;
+            } else {
+                if(_debug) 
+                    System.out.println( "Event has trigger bank");
+                return triggerDataList.get(0);
+            }
+        }
+    }
+                
+
+    private HashMap<Integer,HelicalTrackHit> getHitMap(List<TrackerHit> hits,HelicalTrackFit helix) {
+        HashMap<Integer,HelicalTrackHit> map = new HashMap<Integer,HelicalTrackHit>();
+        for(TrackerHit hit : hits) {
+            HelicalTrackHit hth = (HelicalTrackHit) hit;
+            map.put(hth.Layer(), hth);
+        }
+        return map;
+    }
+    
+
+    private HashMap<Integer,List<HelicalTrackStrip>> getStripHitsMap(List<TrackerHit> hits) {
+        HashMap<Integer,List<HelicalTrackStrip>> map = new HashMap<Integer,List<HelicalTrackStrip>>();
+        for(TrackerHit hit : hits) {
+            HelicalTrackHit hth = (HelicalTrackHit) hit;
+            HelicalTrackCross htc = (HelicalTrackCross) hth;
+            HelicalTrackStrip s1 = htc.getStrips().get(0);
+            HelicalTrackStrip s2 = htc.getStrips().get(1);
+            if(!map.containsKey(s1.layer())) map.put(s1.layer(), new ArrayList<HelicalTrackStrip>());
+            if(!map.containsKey(s2.layer())) map.put(s2.layer(), new ArrayList<HelicalTrackStrip>());
+            map.get(s1.layer()).add(s1);
+            map.get(s2.layer()).add(s2);
+        }
+        return map;
+    }
+    
+    private HashMap<Integer,List<SiTrackerHitStrip1D>> getAllStripHitsMap(EventHeader event, boolean top) {
+        HashMap<Integer,List<SiTrackerHitStrip1D>> map = new HashMap<Integer,List<SiTrackerHitStrip1D>>();
+        if(!event.hasCollection(SiTrackerHitStrip1D.class, this._stripClusterCollectionName)) {
+            return map;
+        }
+        List<SiTrackerHitStrip1D> strips = event.get(SiTrackerHitStrip1D.class, this._stripClusterCollectionName);
+        if(this._debug) System.out.printf("%s: found %d strips in clollection, asking strips in the %s\n", this.getClass().getSimpleName(),strips.size(),(top?"top":"bottom"));
+        for(SiTrackerHitStrip1D strip : strips) {
+            IDetectorElement de = strip.getSensor();
+            SiSensor sensor = (SiSensor) de;
+            int lyr = _ID.getLayer(de);
+            if(!top && SvtUtils.getInstance().isTopLayer(sensor)) continue;
+            else if (top && !SvtUtils.getInstance().isTopLayer(sensor)) continue;
+            if(this._debug) System.out.printf("%s: strip \"%s\" at %s is selected\n", this.getClass().getSimpleName(),_ID.getName(de),strip.getPositionAsVector().toString());
+            if(!map.containsKey(lyr)) {
+                map.put(lyr, new ArrayList<SiTrackerHitStrip1D>());
+            }
+            map.get(lyr).add(strip);
+        }
+        
+        return map;
+    }
+    
+    private HashMap<Integer,List<HelicalTrackHit>> getAllStereoHitsMap(List<HelicalTrackHit> stereoHits, boolean top) {
+        HashMap<Integer,List<HelicalTrackHit>> map = new HashMap<Integer,List<HelicalTrackHit>>();
+        if(stereoHits==null) {
+            return map;
+        }
+        if(this._debug) System.out.printf("%s: asking for stereo hits in the %s\n", this.getClass().getSimpleName(),(top?"top":"bottom"));
+        for(HelicalTrackHit hit : stereoHits) {
+            if(top && hit.z()<0) continue;
+            if(!top && hit.z()>0) continue;
+            if(this._debug) System.out.printf("%s: hit at xyz=%.3f,%.3f,%.3f is selected\n", this.getClass().getSimpleName(),hit.x(),hit.y(),hit.z());
+            if(!map.containsKey(hit.Layer())) {
+                map.put(hit.Layer(), new ArrayList<HelicalTrackHit>());
+            }
+            map.get(hit.Layer()).add(hit);
+        }
+        return map;
+    }
+    
+    private int[] getNtracks(List<CmpTrack> tracks, double min_px) {
+        //System.out.printf("%s: getNtracks for %d tracks with min_px=%.3f \n",this.getClass().getSimpleName(),tracks.size(),min_px);
+        int n[] = {0,0};
+        for(CmpTrack track : tracks) {
+            if(track._track.getTrackStates().get(0).getMomentum()[0]<min_px) {
+                continue;
+            }
+            //System.out.printf("%s: track had enough px=%f\n",this.getClass().getSimpleName(),track._track.getTrackStates().get(0).getMomentum()[0]);
+            
+            List<TrackerHit> hitsOnTrack = track._track.getTrackerHits();
+            for(TrackerHit hit : hitsOnTrack) {
+                double y = hit.getPosition()[1];
+                if(y>0) {
+                    //System.out.printf("%s: this track (chi2=%f) is a top track\n",this.getClass().getSimpleName(),track._track.getChi2());
+                    n[0]++;
+                    break;
+                } else if(y<0) {
+                    //System.out.printf("%s: this track (chi2=%f) is a bot track\n",this.getClass().getSimpleName(),track._track.getChi2());
+                    n[1]++;
+                    break;
+                }
+            }
+        }
+        //System.out.printf("%s: found %d top and %d bot tracks\n",this.getClass().getSimpleName(),n[0],n[1]);
+
+        return n;
+    }
+
+    
+    
+      private void makePlots() {
+        _vtxpos_x = aida.histogram1D("Vertex position X", 100, -800, -500);
+        _vtxpos_y = aida.histogram1D("Vertex position Y", 100, 0, 40);
+        _vtxpos_z = aida.histogram1D("Vertex position Z", 100, -4, 4);
+        _vtxposfr_x = aida.histogram1D("Vertex fr position X", 100, -800, -500);
+        _vtxposfr_y = aida.histogram1D("Vertex fr position Y", 100, 0, 40);
+        _vtxposfr_z = aida.histogram1D("Vertex fr position Z", 100, -4, 4);
+        _vtxposnonb_x = aida.histogram1D("Vertex position non-bend X", 100, -800, -500);
+        _vtxposnonb_y = aida.histogram1D("Vertex position non-bend Y", 100, 0, 40);
+        _vtxposnonb_dy = aida.histogram1D("Vertex position non-bend Ytrk1-Ytrk2", 100, -20, 20);
+        _vtxposnonb_z = aida.histogram1D("Vertex position non-bend Z", 100, -4, 4);
+        _partvtxpos_x = aida.histogram1D("Particle Vertex position X", 100, -1000, 0);
+        _partvtxpos_y = aida.histogram1D("Particle Vertex position Y", 100, -20, 60);
+        _partvtxpos_z = aida.histogram1D("Particle Vertex position Z", 100, -5, 5);
+        _vtxposnonb_xAtZ0 = aida.histogram1D("SLT position non-bend X at Z=0", 100, -1000, 0);
+        _vtxposnonb_zAtTarget = aida.histogram1D("SLT position non-bend Z at target", 100, -5, 5);
+        _vtxposnonb_angle1 = aida.histogram1D("SLT thetay non-bend (trk1)", 100, -0.05, 0.05);
+        _vtxposnonb_angle2 = aida.histogram1D("SLT thetay non-bend (trk2)", 100, -0.05, 0.05);
+
+        _ntrks_px = aida.histogram2D("Track multiplicity vs px cut", 6, 0, 0.6,8,0,8);
+        
+        _trk_y_at_conv_top_pos = aida.histogram1D("Track y @ converter top +", 100, -30,60);
+        _trk_z_at_conv_top_pos = aida.histogram1D("Track z @ converter top +", 100, -20,20);
+        _trk_y_at_conv_top_pos_fr = aida.histogram1D("Track y @ converter top + (fr)", 100, -30, 60);
+        _trk_z_at_conv_top_pos_fr = aida.histogram1D("Track z @ converter top + (fr)", 100, -20, 20);
+        _trk_y_at_conv_bot_pos = aida.histogram1D("Track y @ converter bot +", 100, -30,60);
+        _trk_z_at_conv_bot_pos = aida.histogram1D("Track z @ converter bot +", 100, -20,20);
+        _trk_y_at_conv_bot_pos_fr = aida.histogram1D("Track y @ converter bot + (fr)", 100, -30, 60);
+        _trk_z_at_conv_bot_pos_fr = aida.histogram1D("Track z @ converter bot + (fr)", 100, -20, 20);
+
+        _trk_y_at_conv_top_neg = aida.histogram1D("Track y @ converter top -", 100, -30,60);
+        _trk_z_at_conv_top_neg = aida.histogram1D("Track z @ converter top -", 100, -20,20);
+        _trk_y_at_conv_top_neg_fr = aida.histogram1D("Track y @ converter top - (fr)", 100, -30, 60);
+        _trk_z_at_conv_top_neg_fr = aida.histogram1D("Track z @ converter top - (fr)", 100, -20, 20);
+        _trk_y_at_conv_bot_neg = aida.histogram1D("Track y @ converter bot -", 100, -30,60);
+        _trk_z_at_conv_bot_neg = aida.histogram1D("Track z @ converter bot -", 100, -20,20);
+        _trk_y_at_conv_bot_neg_fr = aida.histogram1D("Track y @ converter bot - (fr)", 100, -30, 60);
+        _trk_z_at_conv_bot_neg_fr = aida.histogram1D("Track z @ converter bot - (fr)", 100, -20, 20);
+
+        
+        
+        _plotterTrackVertex = aida.analysisFactory().createPlotterFactory().create();
+        _plotterTrackVertex.createRegions(2,2);
+        _plotterTrackVertex.region(0).plot(_vtxpos_x);
+        _plotterTrackVertex.region(1).plot(_vtxpos_y);
+        _plotterTrackVertex.region(2).plot(_vtxpos_z);
+        _plotterTrackVertexFr = aida.analysisFactory().createPlotterFactory().create();
+        _plotterTrackVertexFr.createRegions(2,2);
+        _plotterTrackVertexFr.region(0).plot(_vtxposfr_x);
+        _plotterTrackVertexFr.region(1).plot(_vtxposfr_y);
+        _plotterTrackVertexFr.region(2).plot(_vtxposfr_z);
+        _plotterTrackVertexNonBend = aida.analysisFactory().createPlotterFactory().create();
+        _plotterTrackVertexNonBend.createRegions(2,4);
+        _plotterTrackVertexNonBend.region(0).plot(_vtxposnonb_x);
+        _plotterTrackVertexNonBend.region(1).plot(_vtxposnonb_y);
+        _plotterTrackVertexNonBend.region(2).plot(_vtxposnonb_z);
+        _plotterTrackVertexNonBend.region(3).plot(_vtxposnonb_dy);
+        _plotterTrackVertexNonBend.region(4).plot(_vtxposnonb_xAtZ0);
+        _plotterTrackVertexNonBend.region(5).plot(_vtxposnonb_zAtTarget);
+        _plotterTrackVertexNonBend.region(6).plot(_vtxposnonb_angle1);
+        _plotterTrackVertexNonBend.region(7).plot(_vtxposnonb_angle2);
+        _plotterParticleVertex = aida.analysisFactory().createPlotterFactory().create();
+        _plotterParticleVertex.createRegions(2,2);
+        _plotterParticleVertex.region(0).plot(_partvtxpos_x);
+        _plotterParticleVertex.region(1).plot(_partvtxpos_y);
+        _plotterParticleVertex.region(2).plot(_partvtxpos_z);
+        _plotterTrackMult = aida.analysisFactory().createPlotterFactory().create();
+        _plotterTrackMult.createRegions(1,1);
+        _plotterTrackMult.region(0).plot(_ntrks_px);
+        _plotterTrackAtConv = aida.analysisFactory().createPlotterFactory().create();
+        _plotterTrackAtConv.createRegions(4,4);
+        _plotterTrackAtConv.region(0).plot(_trk_y_at_conv_top_pos);
+        _plotterTrackAtConv.region(4).plot(_trk_z_at_conv_top_pos);
+        _plotterTrackAtConv.region(8).plot(_trk_y_at_conv_top_pos_fr);
+        _plotterTrackAtConv.region(12).plot(_trk_z_at_conv_top_pos_fr);
+        _plotterTrackAtConv.region(2).plot(_trk_y_at_conv_bot_pos);
+        _plotterTrackAtConv.region(6).plot(_trk_z_at_conv_bot_pos);
+        _plotterTrackAtConv.region(10).plot(_trk_y_at_conv_bot_pos_fr);
+        _plotterTrackAtConv.region(14).plot(_trk_z_at_conv_bot_pos_fr);
+
+        _plotterTrackAtConv.region(1).plot(_trk_y_at_conv_top_neg);
+        _plotterTrackAtConv.region(5).plot(_trk_z_at_conv_top_neg);
+        _plotterTrackAtConv.region(9).plot(_trk_y_at_conv_top_neg_fr);
+        _plotterTrackAtConv.region(13).plot(_trk_z_at_conv_top_neg_fr);
+        _plotterTrackAtConv.region(3).plot(_trk_y_at_conv_bot_neg);
+        _plotterTrackAtConv.region(7).plot(_trk_z_at_conv_bot_neg);
+        _plotterTrackAtConv.region(11).plot(_trk_y_at_conv_bot_neg_fr);
+        _plotterTrackAtConv.region(15).plot(_trk_z_at_conv_bot_neg_fr);
+        
+        _plotterParticleVertex.setTitle("MC particle Vertex");
+        _plotterTrackVertex.setTitle("Two Track Vertex");
+        _plotterTrackVertexNonBend.setTitle("Two Track Vertex Non Bend");
+        _plotterTrackMult.setTitle("Track multiplicity");
+        _plotterTrackAtConv.setTitle("Track @ converter");
+        
+        for(int i=0;i<3;++i) {
+            ((PlotterRegion) _plotterParticleVertex.region(i)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) _plotterParticleVertex.region(i)).getPlot().setAllowPopupMenus(true);
+            ((PlotterRegion) _plotterTrackVertex.region(i)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) _plotterTrackVertex.region(i)).getPlot().setAllowPopupMenus(true);
+            ((PlotterRegion) _plotterTrackVertexNonBend.region(i)).getPlot().setAllowUserInteraction(true);
+            ((PlotterRegion) _plotterTrackVertexNonBend.region(i)).getPlot().setAllowPopupMenus(true);
+            if(i==0) {
+                ((PlotterRegion) _plotterTrackMult.region(i)).getPlot().setAllowUserInteraction(true);
+                ((PlotterRegion) _plotterTrackMult.region(i)).getPlot().setAllowPopupMenus(true);
+            }
+        }
+        
+        if(!this.hideFrame) {
+            this._plotterParticleVertex.show();
+            this._plotterTrackVertex.show();
+            this._plotterTrackVertexFr.show();
+            this._plotterTrackVertexNonBend.show();
+            //this._plotterTrackMult.show();
[truncated at 1000 lines; 64 more skipped]

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
WTrack.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/WTrack.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/WTrack.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,339 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+import java.util.ArrayList;
+import java.util.List;
+import org.lcsim.constants.Constants;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+
+/**
+ *
+ * @author phansson
+ */
+public class WTrack {
+
+    private boolean _debug = false;
+    public enum PARAM{TEST;}
+    private double[] _parameters = new double[7];
+    public HelicalTrackFit _htf = null;
+    private double _bfield;
+    private double _a;
+    
+    static int max_iterations_intercept = 10;
+    static double epsilon_intercept = 1e-4;
+    
+    public WTrack(WTrack trk) {
+        _bfield = trk._bfield;
+        _a = trk._a;
+        _parameters = trk._parameters;
+        _htf = trk._htf;
+        _debug = trk._debug;
+    }
+    
+    public WTrack(HelicalTrackFit track, double bfield) {
+        initWithTrack(track, bfield, false);
+    }
+    
+    public WTrack(HelicalTrackFit track, double bfield, boolean flip) {
+        initWithTrack(track, bfield, flip);
+    }
+    public void initWithTrack(HelicalTrackFit track, double bfield, boolean flip) {
+        _htf = track;
+        _bfield = flip ? -1.0*bfield : bfield; // flip if needed
+        _a = -1*Constants.fieldConversion*_bfield*Math.signum(track.R());
+        double p = track.p(Math.abs(_bfield));
+        double theta = Math.PI/2.0 - Math.atan(track.slope());
+        double phi = track.phi0();
+        _parameters[0] = p*Math.cos(phi)*Math.sin(theta);
+        _parameters[1] = p*Math.sin(phi)*Math.sin(theta);
+        _parameters[2] = p*Math.cos(theta); 
+        _parameters[3] = Math.sqrt(_parameters[0]*_parameters[0]+_parameters[1]*_parameters[1]+_parameters[2]*_parameters[2]);
+        _parameters[4] = -1*track.dca()*Math.sin(phi); //x0
+        _parameters[5] = track.dca()*Math.cos(phi); //y0
+        _parameters[6] = track.z0(); //z0
+        if(_debug) {
+            System.out.printf("%s: WTrack initialized (p=%f,bfield=%f,theta=%f,phi=%f) from HelicalTrackFit:\n%s:%s\n",this.getClass().getSimpleName(),
+                    p,_bfield,theta,phi,
+                    this.getClass().getSimpleName(),this.toString());
+        }
+    }
+    public void setTrackParameters(double [] params) {
+        _parameters = params;
+    }
+    
+    public double[] getParameters() {
+        return _parameters;
+    }
+    
+    private boolean goingForward() {
+        // assuming the track should go in the x-direction --> not very general -> FIX THIS!?
+        return getP0().x()>0 ? true : false;
+    }
+    
+    
+    public double a() {
+        return _a;
+
+    }
+    
+    private int getCharge() {
+        return (int) Math.signum(_htf.R());
+    }
+    
+    public Hep3Vector getP0() {
+        return ( new BasicHep3Vector(_parameters[0],_parameters[1],_parameters[2]));
+    }
+    
+    public Hep3Vector getX0() {
+        return ( new BasicHep3Vector(_parameters[4],_parameters[5],_parameters[6]));
+    }
+        
+    public String paramsToString() {
+        String str = "";
+        for(int i=0;i<7;++i) str += _parameters[i] + ", ";
+        return str;
+    }
+    public String toString() {
+        
+        String str = "WTrack params [" + paramsToString() + "]";
+        if(this._htf!=null) {
+            str += "\n with corresponding HelicalTrackFit:\n";
+            str += this._htf.toString(); 
+        }
+       return str;
+    }
+    
+    
+    
+    
+    
+    
+     private Hep3Vector getMomentumOnHelix(double s) {
+        WTrack track = this;
+        double a = track.a();
+        Hep3Vector p0 = track.getP0();
+        double rho = a / p0.magnitude();
+        double px = p0.x()*Math.cos(rho*s) - p0.y()*Math.sin(rho*s);
+        double py = p0.y()*Math.cos(rho*s) + p0.x()*Math.sin(rho*s);
+        double pz = p0.z(); 
+        return (new BasicHep3Vector(px,py,pz));
+    }
+    
+    private Hep3Vector getPointOnHelix(double s) {
+        WTrack track = this;
+        double a = track.a();
+        Hep3Vector p0 = track.getP0();
+        Hep3Vector x0 = track.getX0();
+        double rho = a / p0.magnitude();
+        double x = x0.x() + p0.x()/a*Math.sin(rho*s) - p0.y()/a*(1-Math.cos(rho*s));
+        double y = x0.y() + p0.y()/a*Math.sin(rho*s) + p0.x()/a*(1-Math.cos(rho*s));
+        double z = x0.z() + p0.z()/p0.magnitude()*s;
+        return (new BasicHep3Vector(x,y,z));
+    }
+    
+    private double getPathLengthToPlaneApprox(Hep3Vector xp, Hep3Vector eta, Hep3Vector h) {
+        /*
+         * Find the approximate path length to the point xp 
+         * in arbitrary oriented, constant magnetic field with unit vector h
+         */
+        WTrack track = this;
+        double a = track.a();
+        Hep3Vector p0 = track.getP0();
+        Hep3Vector x0 = track.getX0();
+        double p = p0.magnitude();
+        double rho = a / p;
+        double A = VecOp.dot(eta,VecOp.cross(p0, h))/p*0.5*rho;
+        double B = VecOp.dot(p0,eta)/p;
+        double C = VecOp.dot(VecOp.sub(x0,xp),eta);
+        double t = B*B-4*A*C;
+        if(t<0) {
+            System.out.println(" getPathLengthToPlaneApprox ERROR t is negative (" + t + ")!" );
+            System.out.println(" p " + p + " rho " + rho + " a " + a + " A " + A + " B " + B + " C " + C);
+            System.out.println(" track params: " + track.paramsToString());
+            System.out.println(" xp " + xp.toString());
+            System.out.println(" eta " + eta.toString());
+            System.out.println(" h " + h.toString());
+            System.exit(1);
+        }
+        double root1 = (-B + Math.sqrt(t)) /(2*A);
+        double root2 = (-B - Math.sqrt(t)) /(2*A);
+
+        // choose the smallest positive solution
+        // if both negative choose the smallest negative ???
+        //if(root1==0 || root2==0) root=0;
+        double root = Math.abs(root1) <= Math.abs(root2) ? root1 : root2;
+//        else if(Math.signum(root1)>0 && Math.signum(root2)<0) root = root1;
+//        else if(Math.signum(root2)>0 && Math.signum(root1)<0) root = root2;
+//        else if(Math.signum(root1)>0 && Math.signum(root2)>0) root =  root1 > root2 ? root2 : root1;
+//        else if(Math.signum(root1)<0 && Math.signum(root2)<0) root =  root1 < root2 ? root2 : root1;
+//        else {
+//            System.out.println(" I should never get here! (root1=" + root1 + " root2=" + root2+")");
+//            System.exit(1);
+//        }
+        if(_debug) {
+                System.out.println(" getPathLengthToPlaneApprox ");
+                System.out.println(" " + track.paramsToString());
+                System.out.println(" xp " + xp.toString());
+                System.out.println(" eta " + eta.toString());
+                System.out.println(" h " + h.toString());
+                System.out.println(" p " + p + " rho " + rho + " t " + t + " A " + A + " B " + B + " C " + C);
+                System.out.println(" root1 " + root1 + " root2 " + root2 + " -> root " + root);
+        }
+        return root;
+    
+    }
+    
+    
+    private Hep3Vector getPointOnHelix(double s, Hep3Vector h) {
+        /*
+         * Get point on helix at path lenght s 
+         * in arbitrary oriented, constant magnetic field with unit vector h
+         */
+        WTrack track = this;
+        double a = track.a();
+        Hep3Vector p0 = track.getP0();
+        double p = p0.magnitude();
+        Hep3Vector x0 = track.getX0();
+        double rho = a / p0.magnitude();
+        double srho = s*rho;
+        Hep3Vector a1 = VecOp.mult(1/a*Math.sin(srho), p0);
+        Hep3Vector a2 = VecOp.mult(1/a*(1-Math.cos(srho)),VecOp.cross(p0,h));
+        Hep3Vector a3 = VecOp.mult(VecOp.dot(p0, h)/p,h);
+        Hep3Vector a4 = VecOp.mult(s-Math.sin(srho)/rho, a3);
+        Hep3Vector x = VecOp.add(x0,a1);
+        x = VecOp.sub(x,a2);
+        x = VecOp.add(x,a4);
+        return x;
+    }
+    
+    private Hep3Vector getMomentumOnHelix(double s, Hep3Vector h) {
+        /*
+         * Get point on helix at path lenght s 
+         * in arbitrary oriented, constant magnetic field with unit vector h
+         */
+        WTrack track = this;
+        double a = track.a();
+        Hep3Vector p0 = track.getP0();
+        double rho = a / p0.magnitude();
+        double srho = s*rho;
+        Hep3Vector a1 = VecOp.mult(Math.cos(srho), p0);
+        Hep3Vector a2 = VecOp.cross(p0, VecOp.mult(Math.sin(srho),h));
+        Hep3Vector a3 = VecOp.mult(VecOp.dot(p0,h),VecOp.mult(1-Math.cos(srho),h));
+        Hep3Vector p  = VecOp.sub(a1,a2);
+        p = VecOp.add(p,a3);
+        return p;
+    }
+    
+    
+    private double[] getHelixParametersAtPathLength(double s, Hep3Vector h) {
+        /*
+         * Calculate the exact position of the new helix parameters at path length s
+         * in an arbitrarily oriented, constant magnetic field
+         * 
+         * point xp is the point 
+         * h is a unit vector in the direction of the magnetic field
+         */
+        
+        // Find track parameters at that path length
+        Hep3Vector p = getMomentumOnHelix(s, h);
+        Hep3Vector x = getPointOnHelix(s, h);
+        
+        Hep3Vector p_tmp = getMomentumOnHelix(s);
+        Hep3Vector x_tmp = getPointOnHelix(s);
+        
+        if(_debug) {
+            System.out.println(" point on helix at s");
+            System.out.println(" p  " + p.toString() + "   p_tmp " + p_tmp.toString());
+            System.out.println(" x  " + x.toString() + "   x_tmp " + x_tmp.toString());
+        }
+        
+        
+        //Create the new parameter array
+        double [] pars = new double[7];
+        pars[0] = p.x();
+        pars[1] = p.y();
+        pars[2] = p.z();
+        pars[3] = getParameters()[3]; //E is unchanged
+        pars[4] = x.x();
+        pars[5] = x.y();
+        pars[6] = x.z();
+        return pars;
+    }
+    
+    
+    public Hep3Vector getHelixAndPlaneIntercept(Hep3Vector xp, Hep3Vector eta, Hep3Vector h) {
+    
+        /*
+         * Find the interception point between the helix and plane
+         * xp: point on the plane
+         * eta: unit vector of the plane
+         * h: unit vector of magnetic field
+         */
+        
+        
+        int iteration = 1;
+        double s_total = 0.;
+        double step = 9999999.9;
+        //List<WTrack> tracks = new ArrayList<WTrack>();
+        WTrack trk = this;
+        while(iteration<=max_iterations_intercept && Math.abs(step)>epsilon_intercept) {
+            
+            if(_debug) {
+                System.out.printf("%s: Iteration %d\n", this.getClass().getSimpleName(),iteration);
+                System.out.printf("%s: s_total %f prev_step %.3f current trk params: %s \n",
+                                        this.getClass().getSimpleName(),s_total,step,trk.paramsToString());
+            }
+            
+            // check that the track is not looping
+            
+            if(trk.goingForward()) {
+                
+
+                // Start by approximating the path length to the point
+                step = getPathLengthToPlaneApprox(xp, eta, h);
+
+                if(_debug) System.out.printf("%s: path length step s=%.3f\n",this.getClass().getSimpleName(),step);
+
+                // Find the track parameters at this point
+                double[] params = getHelixParametersAtPathLength(step, h);
+
+                // update the track parameters           
+                trk.setTrackParameters(params);
+
+                if(_debug) System.out.printf("%s: updated track params: [%s]\n",this.getClass().getSimpleName(),trk.paramsToString());
+
+                //tracks.add(trk);
+                iteration++;
+                s_total += step;
+
+                //Save distance between point and estimate
+                //Hep3Vector dpoint = VecOp.sub(xp, trk.getX0());
+            
+            } else {
+                //if(_debug) 
+                    System.out.printf("%s: this track started to go backwards?! params [%s]\n",this.getClass().getSimpleName(),trk.toString());
+                return null;
+            }
+            
+            
+        }
+        
+        if(_debug) System.out.printf("%s: final total_s=%f with final step %f after %d iterations gave track params: %s\n",
+                                        this.getClass().getSimpleName(),s_total,step,iteration,trk.paramsToString());
+        
+        return trk.getX0();
+    
+    }
+    
+   
+    
+  
+    
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
dataMCPlots.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/dataMCPlots.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/dataMCPlots.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,373 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import hep.aida.ref.plotter.Plotter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.commons.cli.*;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson
+ */
+public class dataMCPlots {
+
+    
+//    private AIDA aida = AIDA.defaultInstance();
+//    private IAnalysisFactory af = aida.analysisFactory();
+//    IHistogramFactory hf = aida.histogramFactory();
+//    ITree tree = aida.tree();//(ITreeFactory) af.createTreeFactory().create();
+
+    
+    private static void printObjectsInTree(ITree tree) {
+        System.out.println("-----\nObject names in tree " + tree.name() + ":");
+        for( String str : tree.listObjectNames()) {
+            System.out.println(str);
+        }
+        System.out.println("-----");
+    }
+    
+    
+    private static Options createCommandLineOptions() {
+        Options option = new Options();
+        option.addOption("s", false, "Save to file");
+        option.addOption("t", true, "Select the type of analysis to run");
+        option.addOption("n", true, "Name added to plots");
+        return option;
+    }
+    
+    
+    public static class DataCont {
+        public double n_data;
+        public double en_data;
+        public double n_pred;
+        public double en_pred;
+        public DataCont(double data,double edata,double pred,double epred) {
+            n_data=data;
+            en_data=edata;
+            n_pred=pred;
+            en_pred=epred;
+        }
+    }
+    
+    
+    /**
+     * @param args the command line arguments
+     */
+
+    public static void main(String[] args) {
+        // TODO code application logic here
+        
+
+        IAnalysisFactory af = IAnalysisFactory.create();
+        ECalHitMapPlots ecalhtplots = new ECalHitMapPlots();
+            
+        
+        
+        Options opts = createCommandLineOptions();
+        if (args.length == 0) {
+            System.out.println("dataMCPlots [options]");
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", opts);
+            System.exit(1);
+        }
+        CommandLineParser parser = new PosixParser();
+        CommandLine cmd=null;
+        try {
+            cmd = parser.parse(opts, args);
+        } catch (ParseException ex) {
+            Logger.getLogger(dataMCPlots.class.getName()).log(Level.SEVERE, null, ex);
+        }
+
+        
+        
+        int type=0;
+        String strType = cmd.getOptionValue("t");
+        if(strType==null) {
+            System.out.println("using default analysis " + type);
+        } else {
+            type = Integer.parseInt(strType);
+        }
+        boolean savePlots = false;
+        if(cmd.hasOption("s")) {
+            savePlots = true;
+        }
+        String outName = "dataMC";
+        if(cmd.hasOption("n")) {
+            outName = cmd.getOptionValue("n");
+        }
+        
+        
+        if(type==1) {
+             HashMap<Integer,DataCont> map_dc = new HashMap<Integer,DataCont>();
+             String path = "plots/20120723_ecal_dataMC/";
+             Integer runs[] = {1351,1354,1353};
+             Integer runsBkg[] = {1358,1358,1358};
+             String mc[] = {path+"trigratefile_egs5_merged_5000mb_90na_0x016.aida",
+                            path+"trigratefile_egs5_merged_20bb_90na_0x0045.aida",
+                            path+"trigratefile_egs5_merged_50bb_90na_0x0018.aida"
+                            };
+             String mcG4[] = {path+"trigratefile_g4_merged_5000mb_90na_0x016.aida",
+                            path+"trigratefile_g4_merged_20bb_90na_0x0045.aida",
+                            path+"trigratefile_g4_merged_50bb_90na_0x0018.aida"
+                            };
+             
+             double Q_normalization = 90.0; //nC i.e. 90nC is 1s of beam at 90nA
+             
+        
+            SimpleHPSConditions cond = new SimpleHPSConditions();
+
+            AIDA aida = AIDA.defaultInstance();
+            //IAnalysisFactory af = aida.analysisFactory();
+            IHistogramFactory hf = aida.histogramFactory();
+            IDataPointSetFactory dpsf = af.createDataPointSetFactory(null);
+    //    ITree tree = aida.tree();//(ITreeFactory) af.createTreeFactory().create();
+            IDataPointSet dpsObs = dpsf.create("dpsObs","Data",2);
+            IDataPointSet dpsPred = dpsf.create("dpsPred","EGS",2);
+            IDataPointSet dpsPredG4 = dpsf.create("dpsPredG4","G4",2);
+            //IHistogram1D hdata = aida.histogram1D("Observed",runs.length , 0, runs.length);
+            for(int irun=0;irun<runs.length;++irun) {
+
+                    DataCont dc = getDataMC(path+"trigratefile_run"+runs[irun]+".aida",mc[irun], path+"trigratefile_run"+runsBkg[irun]+".aida",outName+"_egs5_"+runs[irun],savePlots,Q_normalization);
+                    dpsObs.addPoint();
+                    dpsObs.point(irun).coordinate(1).setValue(dc.n_data);
+                    dpsObs.point(irun).coordinate(1).setErrorMinus(dc.en_data/2.0);
+                    dpsObs.point(irun).coordinate(1).setErrorPlus(dc.en_data/2.0);
+                    dpsObs.point(irun).coordinate(0).setValue(cond.getThickness(runs[irun]));
+                    dpsObs.point(irun).coordinate(0).setErrorMinus(0.);
+                    dpsObs.point(irun).coordinate(0).setErrorPlus(0.);
+                    
+                    dpsPred.addPoint();
+                    dpsPred.point(irun).coordinate(1).setValue(dc.n_pred);
+                    dpsPred.point(irun).coordinate(1).setErrorMinus(dc.en_pred/2.0);
+                    dpsPred.point(irun).coordinate(1).setErrorPlus(dc.en_pred/2.0);
+                    dpsPred.point(irun).coordinate(0).setValue(cond.getThickness(runs[irun]));
+                    dpsPred.point(irun).coordinate(0).setErrorMinus(0.5);
+                    dpsPred.point(irun).coordinate(0).setErrorPlus(0.5);
+                    
+                    DataCont dcG4 = getDataMC(path+"trigratefile_run"+runs[irun]+".aida",mcG4[irun], path+"trigratefile_run"+runsBkg[irun]+".aida",outName+"_g4_"+runs[irun],savePlots,Q_normalization);
+                    
+                    dpsPredG4.addPoint();
+                    dpsPredG4.point(irun).coordinate(1).setValue(dcG4.n_pred);
+                    dpsPredG4.point(irun).coordinate(1).setErrorMinus(dcG4.en_pred/2.0);
+                    dpsPredG4.point(irun).coordinate(1).setErrorPlus(dcG4.en_pred/2.0);
+                    dpsPredG4.point(irun).coordinate(0).setValue(cond.getThickness(runs[irun]));
+                    dpsPredG4.point(irun).coordinate(0).setErrorMinus(0.5);
+                    dpsPredG4.point(irun).coordinate(0).setErrorPlus(0.5);
+                    
+
+            }
+            
+
+            IPlotter pl_datamc1 = af.createPlotterFactory().create();
+            pl_datamc1.setTitle("Data vs MC");
+            
+            pl_datamc1.style().statisticsBoxStyle().setVisible(false);
+            pl_datamc1.createRegions(1,1);
+            pl_datamc1.region(0).style().dataStyle().lineStyle().setVisible(false);
+            
+            IPlotterStyle dataStyle = pl_datamc1.region(0).style();
+            dataStyle.dataStyle().lineStyle().setColor("blue");
+            
+            //pl_datamc1.region(0).style().dataStyle().markerStyle().setShape(strType)
+            pl_datamc1.region(0).style().xAxisStyle().setLabel("Target thickness (%r.l.)");
+            pl_datamc1.region(0).style().yAxisStyle().setLabel("Counts /"+Q_normalization+"nC");
+            pl_datamc1.region(0).plot(dpsObs, dataStyle);
+            pl_datamc1.region(0).plot(dpsPred,"mode=overlay");
+            pl_datamc1.region(0).plot(dpsPredG4,"mode=overlay");
+            pl_datamc1.show();
+            if(savePlots) {
+                try {
+                    pl_datamc1.writeToFile(outName+".png","png");
+                } catch (IOException ex) {
+                    Logger.getLogger(dataMCPlots.class.getName()).log(Level.SEVERE, null, ex);
+                }
+            }
+    
+        }
+        
+    }
+
+    
+    
+    public static DataCont getDataMC(String file_data,String file_mc, String file_bkg,String name,boolean savePlots,double Qnorm) {
+        
+           try {
+                String path = "";//plots/20120710_ecal_dataMC/../../";
+                
+                //String file_mc = "egs_5.5gev_0.016x0_500mb_90na_01_HPS-TestRun-v2_filtered250_multscat.aida";
+                //String file_mc = "trigratefile_egs5_merged_5000mb_90na_0x016.aida";
+                //String file_mc = "trigratefile_egs5_500mb_90na_01.aida";//trigratefile_egs5_160rl.aida";
+                //String file_data = "trigratefile_run1351.aida";
+                //String file_bkg = "trigratefile_run1358.aida";
+                
+                IAnalysisFactory af = IAnalysisFactory.create();
+                ITree tree_data = af.createTreeFactory().create(path+ file_data);
+                ITree tree_mc = af.createTreeFactory().create(path+ file_mc);
+                ITree tree_bkg = af.createTreeFactory().create(path+ file_bkg);
+                
+                ECalHitMapPlots ecalhtplots = new ECalHitMapPlots();
+                
+                //String name = "dataMC_clusterE_tophalf_norm";
+
+                
+                
+                SimpleHPSConditions cond = new SimpleHPSConditions();
+                
+                int idx = file_data.indexOf("run");
+                int run_data = Integer.parseInt(file_data.substring(idx+3,idx+7));
+                idx = file_bkg.indexOf("run");
+                int run_bkg = Integer.parseInt(file_bkg.substring(idx+3,idx+7));
+
+                //normalize to integrated current of data
+                double int_current_mc = getCurrentFromFileName(file_mc);// 90.0; //nC i.e. 1s of beam at 90nA
+                double n_bunches_mc = getBunchesFromFileName(file_mc);// e.g. 500mb
+                int_current_mc = int_current_mc*n_bunches_mc/500.0;
+                
+                double k_Q_data = Qnorm/cond.getIntCurrent(run_data);
+                
+                double k_Q = k_Q_data*cond.getIntCurrent(run_data)/int_current_mc;
+                System.out.printf("Run %d: intCurrent %.1fnC intCurrent(MC) %.1fnC Qnorm %.1fnC \n",run_data,cond.getIntCurrent(run_data),int_current_mc,Qnorm);
+                System.out.printf("=> k_Q_mc %.1f\n",k_Q );
+                System.out.printf("=> k_Q_data %.1f\n",k_Q_data );
+
+                double k_norm_bkg = cond.getIntCurrent(run_data)/cond.getIntCurrent(run_bkg);
+                System.out.printf("Run %d: intCurrent %.1fnC \n",run_bkg,cond.getIntCurrent(run_bkg));
+                System.out.printf("=> k_norm_bkg %.1f\n",k_norm_bkg );
+
+                double k_rec_data = cond.getRecRate(run_data)/cond.getRate(run_data);
+                System.out.printf("Run %d: rate %.1fHz rec rate %.1fHz\n",run_data,cond.getRate(run_data),cond.getRecRate(run_data));
+                System.out.printf("=> k_rec_data %.2f\n",k_rec_data );
+                
+                double k_rec_bkg = cond.getRecRate(run_bkg)/cond.getRate(run_bkg);
+                System.out.printf("Run %d: rate %.1fHz rec rate %.1fHz\n",run_data,cond.getRate(run_bkg),cond.getRecRate(run_bkg));
+                System.out.printf("=> k_rate_bkg %.2f\n",k_rec_bkg );
+                
+                
+                //Overlay a few histograms
+                List<String> histNames = new ArrayList<String>();
+                for(int ix=-23;ix<=23;++ix) {
+                    for(int iy=-5;iy<=5;++iy) {
+                        
+                        if(ix<=0) continue;
+                        if(iy<=0) continue;
+                        
+                        histNames.add("Cluster energy x="+ix+" y="+iy);
+                        
+                    }    
+                }
+                //System.out.println("Histogram names: "+histNames.toString());
+                
+                int iadded=0;
+                IHistogram1D h_obs=null;
+                IHistogram1D h_bkg=null;
+                IHistogram1D h_mc=null;
+                 
+                
+                boolean dataToMCNorm = false;
+                for(String hname : histNames) {
+                    IHistogram1D h_obs_tmp = (IHistogram1D)tree_data.find(hname);
+                    IHistogram1D h_bkg_tmp = (IHistogram1D)tree_bkg.find(hname);
+                    IHistogram1D h_mc_tmp;
+//                    if(file_mc.contains("merged")) {
+//                        h_mc_tmp = (IHistogram1D)tree_mc.find(hname+" merged");
+//                        System.out.println("adding merged hist \'"+h_mc_tmp.title()+"\'with " + h_mc_tmp.entries());
+//                    } else {
+                    h_mc_tmp = (IHistogram1D)tree_mc.find(hname);
+                    
+                    if(iadded==0) {
+                        h_obs = ecalhtplots.hf.createCopy(h_obs_tmp.title()+ " sum", h_obs_tmp);
+                        h_bkg = ecalhtplots.hf.createCopy(h_bkg_tmp.title()+ " sum", h_bkg_tmp);
+                        h_mc = ecalhtplots.hf.createCopy(h_mc_tmp.title()+ " sum", h_mc_tmp);
+                    } else {
+                    
+                        h_obs.add(h_obs_tmp);
+                        h_bkg.add(h_bkg_tmp);
+                        h_mc.add(h_mc_tmp);
+                    }
+                    ++iadded;
+                    
+                }
+                
+                System.out.println("Added " + iadded + " histograms");
+                
+                //scale data by dead time efficiency
+                h_bkg.scale(1/k_rec_bkg);
+                h_obs.scale(1/k_rec_data);
+                
+                //subtract normalized background from data
+                h_bkg.scale(k_norm_bkg);
+                IHistogram1D h_data = ecalhtplots.hf.subtract(h_obs.title() + " bkgsubtr", h_obs, h_bkg);
+                
+                //Normalize data
+                h_data.scale(k_Q_data);
+                
+                if(dataToMCNorm) { //normalize by setting histogram integrals equal
+                    h_mc.scale(h_data.sumBinHeights()/h_mc.sumBinHeights());
+                } else { //absolute normalization to beam current
+                    h_mc.scale(k_Q);
+                }
+                //System.out.println("mc " + h_mc.entries() + "(" + h_mc.allEntries() + ")" + " obs " + h_obs.entries()+ "(" + h_obs.allEntries() + ")" + " bkg " + h_bkg.entries()+ "(" + h_bkg.allEntries() + ")" + " obs " + h_data.entries()+ "(" + h_data.allEntries() + ")");
+                //System.out.println("mc " + h_mc.sumBinHeights() + " obs " + h_obs.sumBinHeights() + " bkg " + h_bkg.sumBinHeights() + " obs " + h_data.sumBinHeights());
+                System.out.printf("Run %d: obs %.1f bkg %.1f\t=>\tdata %.1f MC %.1f\t->\tdata/MC=%.2f\n",run_data,h_obs.sumBinHeights(),h_bkg.sumBinHeights(),h_data.sumBinHeights(),h_mc.sumBinHeights(),h_data.sumBinHeights()/h_mc.sumBinHeights());
+                h_data.setTitle("Data");
+                h_mc.setTitle("MC");
+                
+                ecalhtplots.plotBasic1D(h_data,h_mc,name, "Cluster energy (MeV)","Counts /"+Qnorm+"nC","data","MC",savePlots);
+                
+                DataCont dc = new DataCont(h_data.sumBinHeights(),Math.sqrt(h_data.sumBinHeights()),h_mc.sumBinHeights(),Math.sqrt(h_mc.entries())*k_Q);
+                
+                return dc;
+                    
+                
+            } catch(IOException e) {
+                throw new RuntimeException(e);
+            }
+         }
+
+    
+    
+    
+    public static double getBunchesFromFileName(String filename) {
+        //trigratefile_egs5_merged_500mb_90na_0x016.aida
+        String[] parts = filename.split("_");
+        for(String part : parts) {
+            int idx = part.indexOf("mb");
+            if(idx!=-1) {
+                return Double.valueOf(part.substring(0, idx));
+            }
+            idx = part.indexOf("bb");
+            if(idx!=-1) {
+                return 1000.0*Double.valueOf(part.substring(0, idx));
+            }
+            
+        }
+        return -1.0;
+        
+    }
+
+    public static double getCurrentFromFileName(String filename) {
+        //trigratefile_egs5_merged_500mb_90na_0x016.aida
+        String[] parts = filename.split("_");
+        for(String part : parts) {
+            int idx = part.indexOf("na");
+            if(idx==-1) {
+                continue;
+            }
+            return Double.valueOf(part.substring(0, idx));
+        }
+        return -1.0;
+        
+    }
+
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
ecalGainAna.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ecalGainAna.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ecalGainAna.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,455 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.commons.cli.*;
+import org.lcsim.geometry.util.DetectorLocator;
+import org.lcsim.hps.recon.ecal.ECalUtils;
+import org.lcsim.hps.recon.ecal.EcalConditions;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson
+ */
+public class ecalGainAna {
+
+//    private AIDA aida = AIDA.defaultInstance();
+//    private IAnalysisFactory af = aida.analysisFactory();
+//    IHistogramFactory hf = aida.histogramFactory();
+//    ITree tree = aida.tree();//(ITreeFactory) af.createTreeFactory().create();
+    private static void printObjectsInTree(ITree tree) {
+        System.out.println("-----\nObject names in tree " + tree.name() + ":");
+        for (String str : tree.listObjectNames()) {
+            System.out.println(str);
+        }
+        System.out.println("-----");
+    }
+
+    private static Options createCommandLineOptions() {
+        Options option = new Options();
+        option.addOption("f", true, "Input file for Pelle's analysis");
+        option.addOption("s", false, "Save to file (Pelle)");
+        option.addOption("n", true, "Name added to plots");
+        option.addOption("m", true, "Minimum weight for calibration");
+        option.addOption("d", true, "Detector used for calibration");
+        option.addOption("g", false, "Use HV groups in calibration");
+        return option;
+    }
+
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) {
+        // TODO code application logic here
+
+
+        IAnalysisFactory af = IAnalysisFactory.create();
+
+
+        Options opts = createCommandLineOptions();
+        if (args.length == 0) {
+            System.out.println("ecalGainAna [options]");
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", opts);
+            System.exit(1);
+        }
+        CommandLineParser parser = new PosixParser();
+        CommandLine cmd = null;
+        try {
+            cmd = parser.parse(opts, args);
+        } catch (ParseException ex) {
+            Logger.getLogger(ecalGainAna.class.getName()).log(Level.SEVERE, null, ex);
+        }
+
+        String outName = "ecalgainplots";
+        if (cmd.hasOption("n")) {
+            outName = cmd.getOptionValue("n");
+        }
+
+        if (cmd.hasOption("f")) {
+            boolean savePlots = false;
+            if (cmd.hasOption("s")) {
+                savePlots = true;
+            }
+
+            String fileName = "";
+            fileName = cmd.getOptionValue("f");
+            System.out.println("File: " + fileName);
+            doPelleAnalysis(af, savePlots, fileName, outName);
+        }
+
+        if (cmd.getArgs().length != 2) {
+            System.err.println("Expected two arguments: ecalGainAna gaindriver_sim.aida gaindriver.aida");
+            System.exit(1);
+        }
+
+        double minCount = 20.0;
+        if (cmd.hasOption("m")) {
+            minCount = Double.valueOf(cmd.getOptionValue("m"));
+        }
+
+        boolean useHVGroups = cmd.hasOption("g");
+
+        ITree sim = null;
+        ITree real = null;
+        ITree outTree = null;
+        try {
+            sim = af.createTreeFactory().create(cmd.getArgs()[0]);
+            real = af.createTreeFactory().create(cmd.getArgs()[1]);
+            outTree = af.createTreeFactory().createTree(outName + ".aida", null, ITreeFactory.RECREATE);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        IHistogram1D pePlotsSim[][][] = new IHistogram1D[47][11][5];
+        IHistogram1D pePlotsReal[][][] = new IHistogram1D[47][11][5];
+
+        for (int iE = 0; iE <= 4; ++iE) {
+            for (int irow = -5; irow <= 5; ++irow) {
+                for (int icol = -23; icol <= 23; ++icol) {
+                    if (iE == 0) {
+                        pePlotsSim[icol + 23][irow + 5][iE] = (IHistogram1D) sim.find("E over p x=" + icol + " y=" + irow);
+                        pePlotsReal[icol + 23][irow + 5][iE] = (IHistogram1D) real.find("E over p x=" + icol + " y=" + irow);
+                    } else {
+                        pePlotsSim[icol + 23][irow + 5][iE] = (IHistogram1D) sim.find("E over p x=" + icol + " y=" + irow + " iE=" + iE);
+                        pePlotsReal[icol + 23][irow + 5][iE] = (IHistogram1D) real.find("E over p x=" + icol + " y=" + irow + " iE=" + iE);
+                    }
+                }
+            }
+        }
+
+        IHistogram2D weightPlotSim = (IHistogram2D) sim.find("Weights for correction factor");
+        IHistogram2D sumPlotSim = (IHistogram2D) sim.find("Sum for correction factor");
+        IHistogram2D weightPlotReal = (IHistogram2D) real.find("Weights for correction factor");
+        IHistogram2D sumPlotReal = (IHistogram2D) real.find("Sum for correction factor");
+
+//        IHistogram2D mpePlotSim = (IHistogram2D) sim.find("<E over p>");
+//        IHistogram2D spePlotSim = (IHistogram2D) sim.find("RMS(E over p)");
+//        IHistogram2D mpePlotReal = (IHistogram2D) real.find("<E over p>");
+//        IHistogram2D spePlotReal = (IHistogram2D) real.find("RMS(E over p)");
+
+        String detectorName = "HPS-TestRun-v3";
+        if (cmd.hasOption("d")) {
+            detectorName = cmd.getOptionValue("d");
+        }
+
+        EcalConditions.detectorChanged(DetectorLocator.findDetector(detectorName), "Ecal");
+        EcalConditions.loadCalibration();
+
+        IHistogramFactory hf = af.createHistogramFactory(outTree);
+
+        IHistogram2D corrPlotSim = hf.createHistogram2D("Weighted E over p - simulation", 46, -23, 23, 11, -5.5, 5.5);
+        IHistogram2D corrPlotReal = hf.createHistogram2D("Weighted E over p - data", 46, -23, 23, 11, -5.5, 5.5);
+
+        for (int x = -23; x <= 23; x++) {
+            int ix = x > 0 ? x + 22 : x + 23;
+            for (int y = -5; y <= 5; y++) {
+                double ep;
+                if (weightPlotSim.binHeight(ix, y + 5) > minCount / 4.0) {
+                    ep = weightPlotSim.binHeight(ix, y + 5) / sumPlotSim.binHeight(ix, y + 5);
+                    if (ep > 1.0) {
+                        ep = 1.0;
+                    }
+                    corrPlotSim.fill(x - 0.5 * Math.signum(x), y, ep);
+                }
+                if (weightPlotReal.binHeight(ix, y + 5) > minCount / 4.0) {
+                    ep = weightPlotReal.binHeight(ix, y + 5) / sumPlotReal.binHeight(ix, y + 5);
+                    if (ep > 1.0) {
+                        ep = 1.0;
+                    }
+                    corrPlotReal.fill(x - 0.5 * Math.signum(x), y, ep);
+                }
+            }
+        }
+
+
+        IPlotter plotter = af.createPlotterFactory().create();
+        plotter.setParameter("plotterWidth", "600");
+        plotter.setParameter("plotterHeight", "400");
+        plotter.createRegion();
+        plotter.region(0).style().statisticsBoxStyle().setVisible(false);
+        plotter.region(0).style().setParameter("hist2DStyle", "colorMap");
+        plotter.region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+
+
+        plotter.region(0).plot(weightPlotSim);
+        plotter.region(0).setTitle(weightPlotSim.title() + " - simulation");
+        try {
+            plotter.writeToFile(outName + "_weights_sim.png", "png");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        plotter.region(0).remove(weightPlotSim);
+        plotter.region(0).plot(weightPlotReal);
+        plotter.region(0).setTitle(weightPlotReal.title() + " - data");
+        plotter.region(0).refresh();
+        try {
+            plotter.writeToFile(outName + "_weights_data.png", "png");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        plotter.region(0).remove(weightPlotReal);
+
+//        plotter.region(0).style().zAxisStyle().setParameter("scale", "log");
+        plotter.region(0).plot(corrPlotSim);
+//        plotter.region(0).setZLimits(0, 10.0);
+        plotter.region(0).style().zAxisStyle().setParameter("upperLimit", "10.0");
+        plotter.region(0).setTitle(corrPlotSim.title());
+        plotter.region(0).refresh();
+        plotter.region(0).style().zAxisStyle().setParameter("upperLimit", "10.0");
+        try {
+            plotter.writeToFile(outName + "_corr_sim.png", "png");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        plotter.region(0).remove(corrPlotSim);
+        plotter.region(0).plot(corrPlotReal);
+//        plotter.region(0).setZLimits(0, 10.0);
+//for (String opt :plotter.region(0).style().zAxisStyle().availableParameters()) {
+//            System.out.println(opt);
+//        }
+        plotter.region(0).setTitle(corrPlotReal.title());
+        plotter.region(0).refresh();
+        try {
+            plotter.writeToFile(outName + "_corr_data.png", "png");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        plotter.region(0).remove(corrPlotReal);
+//        plotter.region(0).style().zAxisStyle().setParameter("scale", "lin");
+//        plotter.region(0).setZLimits();
+
+
+
+        IHistogram2D ecalPlot = hf.createHistogram2D("ECal map", 46, -23, 23, 11, -5.5, 5.5);
+        plotter.region(0).plot(ecalPlot);
+
+
+        IHistogram1D pePlotsHVSim[][] = new IHistogram1D[4][12];
+        IHistogram1D pePlotsHVReal[][] = new IHistogram1D[4][12];
+        double[][] weightsHVSim = new double[4][12];
+        double[][] sumsHVSim = new double[4][12];
+        double[][] weightsHVReal = new double[4][12];
+        double[][] sumsHVReal = new double[4][12];
+
+
+        double allWeightsReal = 0;
+        double allWeightsSim = 0;
+
+        for (int quad = 1; quad <= 4; ++quad) {
+            for (int module = 1; module <= 12; ++module) {
+                pePlotsHVSim[quad - 1][module - 1] = hf.createHistogram1D("E over p quadrant=" + quad + " HV group=" + module, 50, 0, 2);
+                pePlotsHVReal[quad - 1][module - 1] = hf.createHistogram1D("E over p quadrant=" + quad + " HV group=" + module, 50, 0, 2);
+            }
+        }
+        for (int x = -23; x <= 23; x++) {
+            for (int y = -5; y <= 5; y++) {
+                pePlotsHVSim[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1].add(pePlotsSim[x + 23][y + 5][0]);
+                pePlotsHVReal[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1].add(pePlotsReal[x + 23][y + 5][0]);
+                weightsHVSim[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1] += weightPlotSim.binHeight(x + 23, y + 5);
+                sumsHVSim[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1] += sumPlotSim.binHeight(x + 23, y + 5);
+                weightsHVReal[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1] += weightPlotReal.binHeight(x + 23, y + 5);
+                sumsHVReal[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1] += sumPlotReal.binHeight(x + 23, y + 5);
+                allWeightsReal += weightPlotReal.binHeight(x + 23, y + 5);
+                allWeightsSim += weightPlotSim.binHeight(x + 23, y + 5);
+            }
+        }
+
+        for (int x = -23; x <= 23; x++) {
+            for (int y = -5; y <= 5; y++) {
+                Double gain = EcalConditions.physicalToGain(EcalConditions.makePhysicalID(x, y));
+                if (gain != null) {
+                    ecalPlot.fill(x - 0.5 * Math.signum(x), y, gain);
+//                    gainsPlot.fill(x, y, HPSECalUtils.getHVGroup(x, y));
+                }
+            }
+        }
+
+        plotter.region(0).setTitle("Crystal gains before iterating");
+        plotter.region(0).refresh();
+        try {
+            plotter.writeToFile(outName + "_gains_initial.png", "png");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        ecalPlot.reset();
+
+        for (int x = -23; x <= 23; x++) {
+            for (int y = -5; y <= 5; y++) {
+                ecalPlot.fill(x - 0.5 * Math.signum(x), y, pePlotsSim[x + 23][y + 5][0].allEntries());
+            }
+        }
+
+        plotter.region(0).setTitle("Matched cluster counts in simulation");
+        plotter.region(0).refresh();
+        try {
+            plotter.writeToFile(outName + "_counts_sim.png", "png");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        ecalPlot.reset();
+
+        for (int x = -23; x <= 23; x++) {
+            for (int y = -5; y <= 5; y++) {
+                ecalPlot.fill(x - 0.5 * Math.signum(x), y, pePlotsReal[x + 23][y + 5][0].allEntries());
+            }
+        }
+
+        plotter.region(0).setTitle("Matched cluster counts in data");
+        plotter.region(0).refresh();
+        try {
+            plotter.writeToFile(outName + "_counts_data.png", "png");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        ecalPlot.reset();
+
+        PrintStream gainStream;
+        try {
+            gainStream = new PrintStream(outName + ".gain");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+
+        gainStream.format("#x\ty\tgain\n");
+        for (int side = 0; side < 2; side++) {
+            for (int x = -23; x <= 23; x++) {
+                for (int iy = 1; iy <= 5; iy++) {
+                    int y = side == 0 ? iy : -iy;
+                    Double gain = EcalConditions.physicalToGain(EcalConditions.makePhysicalID(x, y));
+                    IHistogram1D peSim = pePlotsSim[x + 23][y + 5][0];
+                    IHistogram1D peReal = pePlotsReal[x + 23][y + 5][0];
+                    IHistogram1D peHVSim = pePlotsHVSim[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1];
+                    IHistogram1D peHVReal = pePlotsHVReal[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1];
+                    double weightHVReal = weightsHVReal[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1];
+                    double sumHVReal = sumsHVReal[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1];
+                    double weightHVSim = weightsHVSim[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1];
+                    double sumHVSim = sumsHVSim[ECalUtils.getQuadrant(x, y) - 1][ECalUtils.getHVGroup(x, y) - 1];
+                    if (gain != null) {
+                        if (weightPlotSim.binHeight(x + 23, y + 5) > minCount && weightPlotReal.binHeight(x + 23, y + 5) > minCount) {
+                            gain *= (corrPlotSim.binHeight(x + 23, y + 5) / corrPlotReal.binHeight(x + 23, y + 5));
+                        } else if (useHVGroups && weightHVReal > 4 * minCount && weightHVSim > 4 * minCount) {
+                            gain *= (weightHVSim / sumHVSim) / (weightHVReal / sumHVReal);
+//                        } else if (weightHVReal / allWeightsReal > 4 * weightHVSim / allWeightsSim) {
+//                            gain /= 1.5;
+//                        } else if (weightHVSim / allWeightsSim > 4 * weightHVReal / allWeightsReal) {
+//                            gain *= 1.5;
+                        }
+//                    if (peSim.allEntries() >= minCount && peReal.allEntries() >= minCount) {
+//                        gain *= (peSim.mean() / peReal.mean());
+//                    } else if (peHVSim.allEntries() >= minCount && peHVReal.allEntries() >= minCount) {
+////                        gain *= (peHVSim.mean() / peHVReal.mean());
+//                    }
+                        gainStream.format("%d\t%d\t%f\n", x, y, gain);
+                        ecalPlot.fill(x - 0.5 * Math.signum(x), y, gain);
+//                    System.out.printf("%d\t%d\t%d\t%f\t%f\n", x, y, pePlotsSim[x + 23][y + 5][0].allEntries(), pePlotsSim[x + 23][y + 5][0].mean(), pePlotsSim[x + 23][y + 5][0].rms());
+                    }
+                }
+            }
+        }
+        gainStream.close();
+
+        plotter.region(0).setTitle("Crystal gains after iterating");
+        plotter.region(0).refresh();
+        try {
+            plotter.writeToFile(outName + "_gains_final.png", "png");
+            outTree.commit();
+            outTree.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static void doPelleAnalysis(IAnalysisFactory af, boolean savePlots, String fileName, String outName) {
+        ITree tree = null;
+        try {
+            tree = af.createTreeFactory().create(fileName);
+        } catch (IllegalArgumentException ex) {
+            Logger.getLogger(ecalGainAna.class.getName()).log(Level.SEVERE, null, ex);
+        } catch (IOException ex) {
+            Logger.getLogger(ecalGainAna.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        //printObjectsInTree(tree);
+
+        IDataPointSetFactory dpsf = af.createDataPointSetFactory(null);
+        IDataPointSet[] dpsEp = new IDataPointSet[2];
+        dpsEp[0] = dpsf.create("dpsEp_t", "E/p vs p top", 2);
+        dpsEp[1] = dpsf.create("dpsEp_b", "E/p vs p bot", 2);
+        double[] ebins = {100, 600, 800, 1000, 1300};
+        for (int iE = 0; iE <= 4; ++iE) {
+            String str = iE == 0 ? "" : (" iE=" + iE);
+            IPlotter pl = af.createPlotterFactory().create();
+            pl.createRegions(1, 2, 0);
+            pl.setTitle("E over p" + str);
+            pl.style().statisticsBoxStyle().setVisible(true);
+            pl.show();
+            for (int iside = 0; iside <= 1; ++iside) {
+                String side = iside == 0 ? "top" : "bottom";
+
+                //String name = "E over p x="+icol+" y="+irow+str;
+                String name = "E over p " + side + str;
+                IHistogram1D h = (IHistogram1D) tree.find(name);
+
+                pl.region(iside).plot(h);
+                pl.region(iside).style().xAxisStyle().setLabel("E over p " + side);
+                pl.region(iside).style().yAxisStyle().setLabel("Events");
+
+                dpsEp[iside].addPoint();
+                dpsEp[iside].point(iE).coordinate(0).setValue(ebins[iE]);
+                dpsEp[iside].point(iE).coordinate(1).setValue(h.mean());
+                double err = 0.;//(h.entries()>5||h.rms()>0.0)?h.rms()/Math.sqrt(h.entries()):0;
+                System.out.println("N " + h.entries() + " rms " + h.rms() + " err " + h.rms() / Math.sqrt(h.entries()));
+                dpsEp[iside].point(iE).coordinate(1).setErrorMinus(err / 2);
+                dpsEp[iside].point(iE).coordinate(1).setErrorPlus(err / 2);
+
+
+//            for(int irow=-5;irow<=5;++irow) {
+//                for(int icol=-23;icol<=23;++icol) {
+//                    String name;
+//                    if(iE==0) name = "E over p x="+icol+" y="+irow;
+//                    else      name = "E over p x="+icol+" y="+irow+" iE="+iE;
+//                    
+//                    IHistogram1D h = (IHistogram1D) tree.find(name);
+//                    int N = h.entries();
+//                    double m = h.mean();
+//                    double c 
+//                }
+//            }
+            }
+
+            if (savePlots) {
+                try {
+                    pl.writeToFile(outName + "iE" + iE + ".png", "png");
+                } catch (IOException ex) {
+                    Logger.getLogger(ecalGainAna.class.getName()).log(Level.SEVERE, null, ex);
+                }
+            }
+
+        }
+
+        IPlotter plM = af.createPlotterFactory().create();
+        plM.createRegions(1, 1, 0);
+        plM.setTitle("<E over p>");
+        plM.style().statisticsBoxStyle().setVisible(false);
+        plM.region(0).style().xAxisStyle().setLabel("Track momentum bins");
+        plM.region(0).style().yAxisStyle().setLabel("Mean E/p");
+        plM.show();
+        plM.region(0).plot(dpsEp[0]);
+        plM.region(0).plot(dpsEp[1], "mode=overlay");
+
+        if (savePlots) {
+            try {
+                plM.writeToFile(outName + "_mean_vs_p.png", "png");
+            } catch (IOException ex) {
+                Logger.getLogger(ecalGainAna.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+
+
+    }
+}
\ No newline at end of file

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
ecalPlots.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ecalPlots.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/ecalPlots.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,336 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.commons.cli.*;
+
+/**
+ *
+ * @author phansson
+ */
+public class ecalPlots {
+
+    
+//    private AIDA aida = AIDA.defaultInstance();
+//    private IAnalysisFactory af = aida.analysisFactory();
+//    IHistogramFactory hf = aida.histogramFactory();
+//    ITree tree = aida.tree();//(ITreeFactory) af.createTreeFactory().create();
+
+    
+    private static void printObjectsInTree(ITree tree) {
+        System.out.println("-----\nObject names in tree " + tree.name() + ":");
+        for( String str : tree.listObjectNames()) {
+            System.out.println(str);
+        }
+        System.out.println("-----");
+    }
+    
+    
+    private static Options createCommandLineOptions() {
+        Options option = new Options();
+        option.addOption("s", false, "Save to file");
+        option.addOption("t", true, "Select the type of analysis to run");
+        return option;
+    }
+    
+    
+    
+    /**
+     * @param args the command line arguments
+     */
+
+    public static void main(String[] args) {
+        // TODO code application logic here
+        
+
+        IAnalysisFactory af = IAnalysisFactory.create();
+        ECalHitMapPlots ecalhtplots = new ECalHitMapPlots();
+            
+        
+        
+        Options opts = createCommandLineOptions();
+        if (args.length == 0) {
+            System.out.println("ecalPlots [options]");
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", opts);
+            System.exit(1);
+        }
+        CommandLineParser parser = new PosixParser();
+        CommandLine cmd=null;
+        try {
+            cmd = parser.parse(opts, args);
+        } catch (ParseException ex) {
+            Logger.getLogger(ecalPlots.class.getName()).log(Level.SEVERE, null, ex);
+        }
+
+        
+        
+        int type=0;
+        String strType = cmd.getOptionValue("t");
+        if(strType==null) {
+            System.out.println("using default analysis " + type);
+        } else {
+            type = Integer.parseInt(strType);
+        }
+        boolean savePlots = false;
+        if(cmd.hasOption("s")) {
+            savePlots = true;
+        }
+        
+ 
+               
+        if(type==999) {
+        
+            ITree tree=null;
+            try {
+                String[] list = cmd.getArgs();
+                String file  = list[0];
+                tree = af.createTreeFactory().create(file);
+                printObjectsInTree(tree);
+                IHistogram1D h = (IHistogram1D)tree.find(list[1]);
+                ecalhtplots.plotBasic1D(h,list[1],"","","",false);
+                
+            } catch (IllegalArgumentException ex) {
+                Logger.getLogger(ecalPlots.class.getName()).log(Level.SEVERE, null, ex);
+            } catch (IOException ex) {
+                Logger.getLogger(ecalPlots.class.getName()).log(Level.SEVERE, null, ex);
+            }
+            
+            return;
+        }
+        
+        if(type==0) {
+            
+            try {
+                String path = "plots/20120710_ecal_dataMC/";
+                String file_mc = "../../multscatana.aida";
+                //String file_mc = "multscatana_egs5_500empty.aida";
+                String file_data = "multscatana_run1351.aida";
+                String file_bkg = "multscatana_run1358.aida";
+                
+                //ITree tree_mc = af.createTreeFactory().create(path+"multscatana_egs5_ecalbadchapplied.aida");
+            //if(1==1) return;
+            ITree tree_mc = af.createTreeFactory().create(path+ file_mc);
+            printObjectsInTree(tree_mc);
+            if(1==1) return;
+            
+            ITree tree_data = af.createTreeFactory().create(path+file_data);
+            ITree tree_bkg = af.createTreeFactory().create(path+file_bkg);
+            String name = "dataMC_500empty_run1351_egs5_currentNorm";
+            
+            //Overlay a few histograms
+            List<String> histNames = new ArrayList<String>();
+            
+            histNames.add("Cluster energy all");
+            histNames.add("Cluster energy bottom");
+            histNames.add("Cluster energy top");
+            histNames.add("Cluster size");
+            histNames.add("Cluster size bottom");
+            histNames.add("Cluster size top");
+            histNames.add("Crystal amplitude all");
+            histNames.add("Crystal amplitude bottom");
+            histNames.add("Crystal amplitude top");
+            for(int icol=-5;icol<=5;++icol) {
+                for(int irow=-23;irow<=23;++irow) {
+                    if(Math.abs(irow)==1) {
+                        histNames.add("Cluster energy x=" + icol + " y=" + irow);
+                    }
+                }
+            }
+
+
+            SimpleHPSConditions cond = new SimpleHPSConditions();
+            
+            int idx = file_data.indexOf("run");
+            
+            int run_data = Integer.parseInt(file_data.substring(idx+3,idx+7));
+            idx = file_bkg.indexOf("run");
+            int run_bkg = Integer.parseInt(file_bkg.substring(idx+3,idx+7));
+            
+            //normalize to integrated current of data
+            double int_current_mc = 90.0; //nC i.e. 1s of beam at 90nA
+            double k_Q = cond.getIntCurrent(run_data)/int_current_mc;
+            System.out.printf("Run %d: intCurrent %.1fnC MC<->%.1fnC  => k_current %.1f\n",run_data,cond.getIntCurrent(run_data),int_current_mc,k_Q );
+            double k_rec = cond.getRecRate(run_data)/cond.getRate(run_data);
+            System.out.printf("Run %d: rate %.1fHz rec rate %.1fHz  => k_rate %.1f\n",run_data,cond.getRate(run_data),cond.getRecRate(run_data),k_rec );
+            
+                boolean normDataToMC = true;
+                for(String hname : histNames) {
+                    IHistogram1D h_mc = (IHistogram1D)tree_mc.find(hname);
+                    IHistogram1D h_obs = (IHistogram1D)tree_data.find(hname);
+                    IHistogram1D h_bkg = (IHistogram1D)tree_bkg.find(hname);
+                    double rate_obs = cond.getRecRate(run_data);//1933.479;
+                    double rate_bkg = cond.getRecRate(run_bkg);//309.785;
+                    double c_rate = rate_bkg/rate_obs;
+                    h_bkg.scale((h_obs.entries()/h_bkg.entries())*c_rate);
+                    IHistogram1D h_data = ecalhtplots.hf.subtract(hname + " bkgsubtr", h_obs, h_bkg);
+                    if(normDataToMC) {
+                        h_mc.scale(h_data.sumBinHeights()/h_mc.sumBinHeights());
+                    } else {
+                        h_mc.scale(k_Q*k_rec);
+                    }
+                    //System.out.println("mc " + h_mc.entries() + " obs " + h_obs.entries() + " bkg " + h_bkg.entries() + " obs " + h_data.entries());
+                    //System.out.println("mc " + h_mc.sumBinHeights() + " obs " + h_obs.sumBinHeights() + " bkg " + h_bkg.sumBinHeights() + " obs " + h_data.sumBinHeights());
+                    System.out.printf("Run %d: obs %.1f bkg %.1f\t=>\tdata %.1f MC %.1f\t->\tdata/MC=%.2f\n",run_data,h_obs.sumBinHeights(),h_bkg.sumBinHeights(),h_data.sumBinHeights(),h_mc.sumBinHeights(),h_data.sumBinHeights()/h_mc.sumBinHeights());
+
+                    ecalhtplots.plotBasic1D(h_data,h_mc,name+"_"+hname, "","","Data","MC",savePlots);
+
+                }
+            } catch(IOException e) {
+                throw new RuntimeException(e);
+            }
+            
+        }
+        
+        
+        
+        
+        
+         if(type==2) {
+            
+            try {
+                String path = "";//plots/20120710_ecal_dataMC/../../";
+                String file_dead = "multscatana_egs5_160rl.aida";//multscatana_egs5_500empty_nodeadchannelfilter.aida";
+                String file = "multscatana_egs5_160rl.aida";//"multscatana_egs5_500empty.aida";
+                 ITree tree_dead = af.createTreeFactory().create(path+ file_dead);
+                 ITree tree = af.createTreeFactory().create(path+ file);
+                String name = "deadChEffect_egs5";
+
+                //Overlay a few histograms
+                List<String> histNames = new ArrayList<String>();
+                
+                histNames.add("Cluster energy x=4 y=1");
+                histNames.add("Cluster energy x=5 y=1");
+                
+                
+                for(String hname : histNames) {
+                    IHistogram1D h = (IHistogram1D)tree.find(hname);
+                    IHistogram1D h_dead = (IHistogram1D)tree_dead.find(hname);
+                    
+                    //h_bkg.scale((h.entries()/h_dead.entries())*c_rate);
+                    //IHistogram1D h_data = ecalhtplots.hf.subtract(hname + " bkgsubtr", h_obs, h_bkg);
+                    //h_mc.scale(h_data.sumBinHeights()/h_mc.sumBinHeights());
+                    
+                    //System.out.println("mc " + h_mc.entries() + " obs " + h_obs.entries() + " bkg " + h_bkg.entries() + " obs " + h_data.entries());
+                    //System.out.println("mc " + h_mc.sumBinHeights() + " obs " + h_obs.sumBinHeights() + " bkg " + h_bkg.sumBinHeights() + " obs " + h_data.sumBinHeights());
+                    //System.out.printf("Run %d: obs %.1f bkg %.1f\t=>\tdata %.1f MC %.1f\t->\tdata/MC=%.2f\n",run_data,h_obs.sumBinHeights(),h_bkg.sumBinHeights(),h_data.sumBinHeights(),h_mc.sumBinHeights(),h_data.sumBinHeights(),h_mc.sumBinHeights());
+
+                    ecalhtplots.plotBasic1D(h,h_dead,name+"_"+hname, "","","Fixed","Bad Ch. incl.",savePlots);
+
+                }
+                
+                
+
+            } catch(IOException e) {
+                throw new RuntimeException(e);
+            }
+         }
+        
+        
+        
+          
+        
+         
+        
+        /*
+        ITree tree_multscatana = null;
+        try {
+            tree_multscatana = analysisFactory.createTreeFactory().create("plots/PAC/20120610/noEcalChFilter_1351/multscatana_1351_noEcalChFilter.aida");
+            //tree_multscatana = analysisFactory.createTreeFactory().create("plots/PAC/20120610/EcalChFilter_1351/multscatana_1351_EcalChFilter.aida");
+            
+            
+
+            printObjectsInTree(tree_multscatana);
+            
+            //ecalhtplots.plotMultScatAna(tree_multscatana);
+            
+            
+            
+            
+            
+            //tree_multscatana = analysisFactory.createTreeFactory().create("multscatana_1351.aida");
+        } catch(IOException e) {
+            throw new RuntimeException(e);
+        }
+        
+        
+        ITree tree_filter = null;
+        try {
+            tree_filter = analysisFactory.createTreeFactory().create("plots/PAC/20120610/noEcalChFilter_1351/ecalCrystalFilter_1351_noEcalChFilter.aida");
+            //tree_filter = analysisFactory.createTreeFactory().create("plots/PAC/20120610/EcalChFilter_1351/ecalCrystalFilter_1351_EcalChFilter.aida");
+        
+            printObjectsInTree(tree_filter);
+        
+            //ecalhtplots.plotEcalFilter(tree_filter);
+            
+        
+        } catch(IOException e) {
+            throw new RuntimeException(e);
+        }
+        
+        */
+        
+        if(type==1) {
+            ITree tree_empty_multscatana = null;
+            ITree tree_1351_multscatana = null;
+            try {
+                tree_empty_multscatana = af.createTreeFactory().create("multscatana_1358_EcalChFilter_100k.aida");
+                tree_1351_multscatana = af.createTreeFactory().create("multscatana_1351_EcalChFilter.aida");
+                //tree_1351_multscatana = analysisFactory.createTreeFactory().create("plots/PAC/20120610/EcalChFilter_1351/multscatana_1351_EcalChFilter.aida");
+
+
+                ecalhtplots.overLayUpStrBkg(tree_empty_multscatana, tree_1351_multscatana);
+
+
+
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+
+        }
+        
+        
+    }
+
+    public static double getBunchesFromFileName(String filename) {
+        //trigratefile_egs5_merged_500mb_90na_0x016.aida
+        String[] parts = filename.split("_");
+        for(String part : parts) {
+            int idx = part.indexOf("mb");
+            if(idx!=-1) {
+                return Double.valueOf(part.substring(0, idx));
+            }
+            idx = part.indexOf("bb");
+            if(idx!=-1) {
+                return 1000.0*Double.valueOf(part.substring(0, idx));
+            }
+            
+        }
+        return -1.0;
+        
+    }
+
+    public static double getCurrentFromFileName(String filename) {
+        //trigratefile_egs5_merged_500mb_90na_0x016.aida
+        String[] parts = filename.split("_");
+        for(String part : parts) {
+            int idx = part.indexOf("na");
+            if(idx==-1) {
+                continue;
+            }
+            return Double.valueOf(part.substring(0, idx));
+        }
+        return -1.0;
+        
+    }
+
+    
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
mergeSimpleAIDA.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/mergeSimpleAIDA.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/mergeSimpleAIDA.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,199 @@
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+import org.apache.commons.cli.*;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson
+ * @version $Id: mergeSimpleAIDA.java,v 1.4 2012/12/11 23:50:48 meeg Exp $
+ */
+public class mergeSimpleAIDA {
+
+    /**
+     * @param args the command line arguments
+     */
+    private static Options createCommandLineOptions() {
+        Options option = new Options();
+        option.addOption("r", true, "Regular expression to match files");
+        option.addOption("d", true, "File directory");
+        option.addOption("o", true, "Merged file name");
+        option.addOption("t", false, "Print files to be merged only");
+        option.addOption("a", false, "Average histograms across files instead of just summing them");
+        return option;
+    }
+
+    public static void main(String[] args) {
+        // TODO code application logic here
+
+        Options opts = createCommandLineOptions();
+        if (args.length == 0) {
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", opts);
+            System.exit(1);
+        }
+        CommandLineParser parser = new PosixParser();
+        CommandLine cmd = null;
+        try {
+            cmd = parser.parse(opts, args);
+        } catch (ParseException ex) {
+            Logger.getLogger(mergeSimpleAIDA.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        String regexp = ".*aida$";
+        if (cmd.hasOption("r")) {
+            regexp = cmd.getOptionValue("r");
+        }
+
+        String path = ".";
+        if (cmd.hasOption("d")) {
+            path = cmd.getOptionValue("d");
+        }
+        String outfile = "merged";
+        if (cmd.hasOption("o")) {
+            outfile = cmd.getOptionValue("o");
+        }
+        boolean testOnly = cmd.hasOption("t");
+
+        boolean doAverage = cmd.hasOption("a");
+
+        File[] files = listFilesMatching(path, regexp);
+
+        if (files == null || files.length == 0) {
+            System.out.println("No files matched " + regexp + " in " + path);
+            System.exit(1);
+        }
+
+        System.out.println("Found " + files.length + " matching files");
+
+        if (testOnly) {
+            for (File f : files) {
+                System.out.println(f.getName());
+            }
+        } else {
+            mergeFiles(files, outfile, doAverage);
+        }
+    }
+
+    public static void mergeFiles(File[] files, String outFileName, boolean doAverage) {
+
+        System.out.println("Merging " + files.length + " into " + outFileName);
+        AIDA aida = AIDA.defaultInstance();
+        IAnalysisFactory af = aida.analysisFactory();
+        IHistogramFactory hf = aida.histogramFactory();
+        int count = 0;
+
+        for (File f : files) {
+
+            System.out.println("Processing file f " + f.toString());
+            ITree tree = null;
+            try {
+                tree = af.createTreeFactory().create(f.toString());
+            } catch (IllegalArgumentException ex) {
+                Logger.getLogger(mergeSimpleAIDA.class.getName()).log(Level.SEVERE, null, ex);
+            } catch (IOException ex) {
+                Logger.getLogger(mergeSimpleAIDA.class.getName()).log(Level.SEVERE, null, ex);
+            }
+            for (String str : tree.listObjectNames()) {
+                //if(!str.contains("Cluster energy x")) continue;
+                IManagedObject obj = tree.find(str);
+                if (IHistogram1D.class.isInstance(obj)) {
+                    IHistogram1D h = (IHistogram1D) obj;
+                    if (h == null) {
+                        System.out.println("Error " + str + " had problems to be cast to 1D?");
+                        continue;
+                    }
+                    String name = h.title();// + " merged";
+                    IHistogram1D hc = null;// = aida.histogram1D(name);
+                    try {
+                        hc = (IHistogram1D) aida.tree().find(name);
+                    } catch (IllegalArgumentException ex) {
+                        System.out.println(" creating " + name);
+                    }
+                    if (hc == null) {
+
+                        hc = hf.createCopy(name, h);
+                    } else {
+                        hc = hf.add(hc.title(), hc, h);
+                    }
+                    if (name.contains("x=1 y=1")) {
+                        System.out.println("Now " + hc.entries() + " entries (<m>=" + hc.mean() + " RMS=" + h.rms() + ")");
+                    }
+                }
+                if (IHistogram2D.class.isInstance(obj)) {
+                    IHistogram2D h = (IHistogram2D) obj;
+                    if (h == null) {
+                        System.out.println("Error " + str + " had problems to be cast to 1D?");
+                        continue;
+                    }
+                    String name = h.title();// + " merged";
+                    IHistogram2D hc = null;// = aida.histogram1D(name);
+                    try {
+                        hc = (IHistogram2D) aida.tree().find(name);
+                    } catch (IllegalArgumentException ex) {
+                        System.out.println(" creating " + name);
+                    }
+                    if (hc == null) {
+
+                        hc = hf.createCopy(name, h);
+                    } else {
+                        hc = hf.add(hc.title(), hc, h);
+                    }
+                }
+            }
+            ++count;
+        }
+
+        // divide all histograms by the count to get the average
+        if (doAverage) {
+            for (String str : aida.tree().listObjectNames()) {
+                //if(!str.contains("Cluster energy x")) continue;
+                IManagedObject obj = aida.tree().find(str);
+                if (IHistogram.class.isInstance(obj)) {
+                    IHistogram h = (IHistogram) obj;
+                    if (h == null) {
+                        System.out.println("Error " + str + " had problems to be cast to 1D?");
+                        continue;
+                    }
+                    h.scale(1.0 / count);
+                }
+            }
+        }
+
+        try {
+            aida.saveAs(outFileName);
+        } catch (IOException ex) {
+            Logger.getLogger(mergeSimpleAIDA.class.getName()).log(Level.SEVERE, null, ex);
+        }
+
+    }
+
+    public static File[] listFilesMatching(String path, String regexp) {
+        //Find files matching the reg exp
+        System.out.println("Find files in " + path + " matching the reg exp " + regexp);
+        File dir = new File(path);
+        if (!dir.isDirectory()) {
+            throw new IllegalArgumentException(path + " is no directory.");
+
+            //System.out.println(path+" is not a dir?!");
+        }
+        final Pattern p = Pattern.compile(regexp);
+        System.out.println("pattern " + p.toString());
+
+        return dir.listFiles(new FilenameFilter() {
+
+            @Override
+            public boolean accept(File file, String name) {
+                boolean match = p.matcher(name).matches();
+                //System.out.println("accepting file " + name + ": " + match);
+                return match;
+            }
+        });
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/phansson
trigRate.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/trigRate.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/phansson/trigRate.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,292 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.lcsim.hps.users.phansson;
+
+import hep.aida.*;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.cli.*;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author phansson
+ */
+public class trigRate {
+
+    
+//    private AIDA aida = AIDA.defaultInstance();
+//    private IAnalysisFactory af = aida.analysisFactory();
+//    IHistogramFactory hf = aida.histogramFactory();
+//    ITree tree = aida.tree();//(ITreeFactory) af.createTreeFactory().create();
+
+    
+    private static void printObjectsInTree(ITree tree) {
+        System.out.println("-----\nObject names in tree " + tree.name() + ":");
+        for( String str : tree.listObjectNames()) {
+            System.out.println(str);
+        }
+        System.out.println("-----");
+    }
+
+    
+    private static Options createCommandLineOptions() {
+        Options options = new Options();
+        
+        options.addOption(new Option("d",false, "DAQ dead time file"));
+        options.addOption(new Option("f",false, "Beam current file"));
+        options.addOption(new Option("w",false, "Save all plots to files"));
+        options.addOption(new Option("n",false, "Name that will be added to all plots"));
+        options.addOption(new Option("e",true, "Cluster energy cut"));
+        options.addOption(new Option("s",true, "Top or bottom half"));
+        options.addOption(new Option("h",true, "Hide plots"));
+        
+        return options;
+    }
+    
+    
+    /**
+     * @param args the command line arguments
+     */
+
+    public static void main(String[] args) {
+        // TODO code application logic here
+        
+        IAnalysisFactory analysisFactory = IAnalysisFactory.create();
+        TrigRateAna ana = new TrigRateAna();
+
+        Options options = createCommandLineOptions();
+        if (args.length == 0) {
+            System.out.println("trigRate [options]");
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", options);
+            System.exit(1);
+        }
+        CommandLineParser parser = new PosixParser();
+        
+        CommandLine cl = null;
+        try {
+            cl = parser.parse(options, args);
+        } catch (ParseException e) {
+            throw new RuntimeException("Problem parsing command line options.", e);
+        }
+        
+        boolean save = false;
+        String curFile = "/Users/phansson/work/HPS/software/reco/run/beamCurrents.txt";
+        String deadFile = "/Users/phansson/work/HPS/software/reco/run/deadFile.txt";
+        String ttFile = "/Users/phansson/work/HPS/software/reco/run/targetThickness.txt";
+        
+        
+        if(cl.hasOption("f")) {
+            curFile = cl.getOptionValue("f");
+        }
+
+        if(cl.hasOption("d")) {
+            deadFile = cl.getOptionValue("d");
+        }
+        
+        int clEnergy = -1;
+        if(cl.hasOption("e")) {
+            clEnergy = Integer.parseInt(cl.getOptionValue("e"));
+        } else {
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", options);
+            System.exit(1);
+        }
+
+        System.out.println("Cluster energy " + clEnergy);
+
+        if(clEnergy<0) {
+            System.out.println("Error Cluster energy " + clEnergy);
+            System.exit(1);
+        }
+        
+        
+        String side = "";
+        if(cl.hasOption("s")) {
+            side = cl.getOptionValue("s");
+        } else {
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", options);
+            System.exit(1);
+        }
+
+        System.out.println("Side " + side);
+
+        if(side=="") {
+            System.out.println("Error side " + side );
+            System.exit(1);
+        }
+        
+        if(cl.hasOption("w")) {
+            save = Boolean.parseBoolean(cl.getOptionValue("w"));
+            
+        } 
+        boolean hide = false;
+        if(cl.hasOption("h")) {
+            hide = Boolean.parseBoolean(cl.getOptionValue("h"));
+            
+        } 
+
+
+        
+        String name = "";
+        if(cl.hasOption("n")) {
+            name = cl.getOptionValue("s");
+        } else {
+            HelpFormatter help = new HelpFormatter();
+            help.printHelp(" ", options);
+            System.exit(1);
+        }
+
+        System.out.println("Name " + name);
+
+        if(name=="") {
+            System.out.println("Error name " + name );
+            System.exit(1);
+        }
+
+        
+        
+        
+         
+        
+        ana.addOn(name);
+        ana.saveFiles(save);
+        ana.hidePlots(hide);
+        ana.loadBeamCurrent(curFile);
+        ana.loadDAQDeadTime(deadFile);
+        ana.setChargeNormalization(90.0);
+        ana.setBackgroundRunNrs(1358, 1359);
+        ana.loadTargetThickness(ttFile);
+        
+        
+        
+        
+        
+         
+        try {
+            ITree tree = analysisFactory.createTreeFactory().create("plots/20120618_trig_rate_gainfix_noFirstRow/trigratedriver_hps_001351_withtracking.evio.0.aida");
+            //printObjectsInTree(tree);
+            //ana.getGainCalibration(tree,side);
+            
+            
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        
+        
+        
+        
+        
+        
+       
+            
+        
+       
+        
+       
+        
+        
+        try {
+
+            //String path = "plots/20120615_trig_rate/";
+            //String path = "plots/20120615_trig_rate_gainfix/";
+            //String path = "plots/20120618_trig_rate_gainfix_noFirstRow/";
+            String path = "plots/20120618_trig_rate_gainfix/";
+            path = "";
+            
+            List<String> trees = new ArrayList<String>();
+            trees.add(path + "trigratefile_001351.aida");//driver_hps_001351.evio.0.aida");  
+            //trees.add(path + "trigratedriver_hps_001354.evio.0.aida");  
+            //trees.add(path + "trigratedriver_hps_001359.evio.0.aida");  
+            //trees.add(path + "trigratedriver_hps_001362.evio.0.aida");
+            //trees.add(path + "trigratedriver_hps_001353.evio.0.aida");  
+            //trees.add(path + "trigratedriver_hps_001354.evio.1.aida");  
+            //trees.add(path + "trigratedriver_hps_001360.evio.0.aida");  
+            //trees.add(path + "trigratedriver_hps_001362.evio.1.aida");
+            //trees.add(path + "trigratedriver_hps_001353.evio.1.aida");  
+            trees.add(path + "trigratefile_001358.aida");
+            //trees.add(path + "trigratedriver_hps_001358.evio.0.aida");  
+            //trees.add(path + "trigratedriver_hps_001360.evio.1.aida");  
+            //trees.add(path + "trigratedriver_hps_001362.evio.2.aida");
+            
+
+/*
+            trees.add(path + "trigratedriver_1351.aida");
+            trees.add(path + "trigratedriver_1353_0.aida");
+            trees.add(path + "trigratedriver_1353_1.aida");
+            trees.add(path + "trigratedriver_1354_0.aida");
+            trees.add(path + "trigratedriver_1354_1.aida");
+            trees.add(path + "trigratedriver_1358.aida");
+            trees.add(path + "trigratedriver_1359.aida");
+            trees.add(path + "trigratedriver_1360_0.aida");
+            trees.add(path + "trigratedriver_1360_1.aida");
+            trees.add(path + "trigratedriver_1362_0.aida");
+            trees.add(path + "trigratedriver_1362_1.aida");
+            trees.add(path + "trigratedriver_1362_2.aida");
+*/
+
+            
+            String hNameHitMap = "Cluster E>" + clEnergy + "GeV hit map good region " + side;
+            String hNameHitY = "Cluster E>" + clEnergy + "GeV hit Y good region " + side;
+            
+            
+            
+            
+            
+            
+            
+            for(String t : trees) {
+                ITree tree = analysisFactory.createTreeFactory().create(t);
+                //printObjectsInTree(tree);
+            
+                System.out.println("\"" + t+ "\":");
+                //ana.prettyPrintCount(tree);
+                int idx = t.lastIndexOf("13");
+                int idxE = t.lastIndexOf(".evio.");
+                String str = t.substring(idx, idxE);
+                str += "_" + t.substring(idxE+6, idxE+7);
+                ana.addCount(tree,hNameHitMap,str);
+                ana.addPolarHist(tree,hNameHitY,str);
+                
+                
+                //ana.plotEp(tree,str);
+                
+                              
+            }
+            ana.mergeCounts();
+            ana.normalize();
+            ana.subtractBackground();
+            ana.scaleToRndCharge();
+            ana.scaleDAQDeadTime();
+            ana.plotCount();
+            ana.makeRatio(0.18, "ratio_w_018");
+            ana.plotRatio("ratio_w_018");
+            //ana.prettyPrintCount();
+            ana.prettyPrintCountList();
+            
+//            /Cluster E>0.6GeV hit map good region
+//            /Cluster E>1GeV hit map good region
+//            /Cluster E_corr>0.6GeV hit map good region
+//            /Cluster E_corr>1GeV hit map good region
+
+            
+            //ana.getGainCalibration(tree);
+            
+            
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        
+        
+        
+        
+        
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/sarah
ExamplePlotter.java added at 52
--- java/trunk/users/src/main/java/org/lcsim/hps/users/sarah/ExamplePlotter.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/sarah/ExamplePlotter.java	2013-12-03 16:59:02 UTC (rev 52)
@@ -0,0 +1,71 @@
+package org.lcsim.hps.users.sarah;
+
+import org.lcsim.hps.users.mgraham.*;
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogram1D;
+import hep.aida.IPlotter;
+import hep.aida.IPlotterStyle;
+import java.util.List;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.monitoring.deprecated.AIDAFrame;
+import org.lcsim.hps.monitoring.deprecated.Resettable;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+
+ @author mgraham
+ */
+public class ExamplePlotter extends Driver implements Resettable {
+
+    private AIDAFrame plotterFrame;
+    private AIDA aida = AIDA.defaultInstance();
+    IPlotter plotter;
+    IAnalysisFactory fac = aida.analysisFactory();
+    private String trackCollectionName = "MatchedTracks";
+
+    protected void detectorChanged(Detector detector) {
+        aida.tree().cd("/");
+        plotterFrame = new AIDAFrame();
+        plotterFrame.setTitle("HPS Tracking Plots");
+
+        plotter = fac.createPlotterFactory().create("HPS Tracking Plots");
+        plotter.setTitle("Momentum");
+        IPlotterStyle style = plotter.style();
+        style.dataStyle().fillStyle().setColor("yellow");
+        style.dataStyle().errorBarStyle().setVisible(false);
+        plotter.createRegions(2, 2);
+        plotterFrame.addPlotter(plotter);
+
+        IHistogram1D trkPx = aida.histogram1D("Track Momentum (Px)", 25, -0.25, 0.25);
+        IHistogram1D trkPy = aida.histogram1D("Track Momentum (Py)", 25, -0.1, 0.1);
+        IHistogram1D trkPz = aida.histogram1D("Track Momentum (Pz)", 25, 0, 3.5);
+        IHistogram1D trkChi2 = aida.histogram1D("Track Chi2", 25, 0, 25.0);
+
+        plotter.region(0).plot(trkPx);
+        plotter.region(1).plot(trkPy);
+        plotter.region(2).plot(trkPz);
+        plotter.region(3).plot(trkChi2);
+
+        plotterFrame.pack();
+        plotterFrame.setVisible(true);
+    }
+
+    public void process(EventHeader event) {
+        aida.tree().cd("/");
+        List<Track> tracks = event.get(Track.class, trackCollectionName);
+        for (Track trk : tracks) {
+            aida.histogram1D("Track Momentum (Px)").fill(trk.getPY());
+            aida.histogram1D("Track Momentum (Py)").fill(trk.getPZ());
+            aida.histogram1D("Track Momentum (Pz)").fill(trk.getPX());
+            aida.histogram1D("Track Chi2").fill(trk.getChi2());
+        }
+    }
+
+    @Override
+    public void reset() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+}
SVNspam 0.1