62 added files
java/sandbox/tracking
--- java/sandbox/tracking/pom.xml (rev 0)
+++ java/sandbox/tracking/pom.xml 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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-tracking</artifactId>
+ <name>hps-tracking</name>
+ <description>HPS tracking reconstruction module</description>
+
+ <parent>
+ <groupId>org.hps</groupId>
+ <artifactId>hps-parent</artifactId>
+ <relativePath>../parent/pom.xml</relativePath>
+ <version>3.0.2-SNAPSHOT</version>
+ </parent>
+
+ <scm>
+ <url>http://java.freehep.org/svn/repos/hps/list/java/trunk/tracking/</url>
+ <connection>scm:svn:svn://svn.freehep.org/hps/java/trunk/tracking/</connection>
+ <developerConnection>scm:svn:svn://svn.freehep.org/hps/java/trunk/tracking/</developerConnection>
+ </scm>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>org/lcsim/hps/recon/tracking/TruthResidualTest.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.lcsim</groupId>
+ <artifactId>lcsim-distribution</artifactId>
+ <version>${lcsimVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hps</groupId>
+ <artifactId>hps-conditions</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hps</groupId>
+ <artifactId>hps-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hps</groupId>
+ <artifactId>hps-ecal-readout-sim</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-math3</artifactId>
+ <version>3.2</version>
+ </dependency>
+ </dependencies>
+
+</project>
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/AlignmentParameters.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/AlignmentParameters.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,560 @@
+package org.hps.recon.tracking;
+
+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.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/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/AxialTrackReconDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/AxialTrackReconDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,436 @@
+package org.hps.recon.tracking;
+
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrack2DHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.MultipleScatter;
+import org.lcsim.fit.line.SlopeInterceptLineFit;
+import org.lcsim.fit.line.SlopeInterceptLineFitter;
+import org.lcsim.geometry.Detector;
+import org.lcsim.lcio.LCIOConstants;
+import org.lcsim.recon.tracking.digitization.sisim.config.ReadoutCleanupDriver;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.recon.tracking.seedtracker.StrategyXMLUtils;
+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 AxialTrackReconDriver extends Driver {
+
+ // Debug flag.
+ //private final static boolean DEBUG = false;
+ 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;
+ // Name of the SVT subdetector.
+ private String subdetectorName = "Tracker";
+ // SimTrackerHit input collection for readout cleanup.
+ private String simTrackerHitCollectionName = "TrackerHits";
+ // Tracking strategies resource path.
+ private String strategyResource = "HPS-Test-1pt3.xml";
+ // Output track collection.
+ private String trackCollectionName = "MatchedTracks";
+ // HelicalTrackHit input collection.
+ private String stInputCollectionName = "RotatedHelicalTrackHits";
+ // Output hit collection for HelicalTrackHits.
+ private String hthOutputCollectionName = "HelicalTrackHits";
+ // Input strip hits collection from digi.
+ private String stripHitsCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+ // Hit relations output collection.
+ private String helicalTrackHitRelationsCollectionName = "HelicalTrackHitRelations";
+ // Track to MC relations output collection.
+ private String helicalTrackMCRelationsCollectionName = "HelicalTrackMCRelations";
+ // Max strip separation when making HelicalTrackHits.
+ private double stripMaxSeparation = 10.01;
+ // Tolerance factor when making HelicalTrackHits.
+ private double stripTolerance = 0.01;
+ private List<SeedStrategy> sFinallist;
+
+ public AxialTrackReconDriver() {
+ }
+
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
+ public void setSubdetectorName(String subdetectorName) {
+ this.subdetectorName = subdetectorName;
+ }
+
+ /**
+ * 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 setHelicalTrackHitRelationsCollectionName(String helicalTrackHitRelationsCollectionName) {
+ this.helicalTrackHitRelationsCollectionName = helicalTrackHitRelationsCollectionName;
+ }
+
+ public void setHelicalTrackMCRelationsCollectionName(String helicalTrackMCRelationsCollectionName) {
+ this.helicalTrackMCRelationsCollectionName = helicalTrackMCRelationsCollectionName;
+ }
+
+ public void setInputHitCollectionName(String inputHitCollectionName) {
+ this.stInputCollectionName = inputHitCollectionName;
+ }
+
+ public void setOutputHitCollectionName(String outputHitCollectionName) {
+ this.hthOutputCollectionName = outputHitCollectionName;
+ }
+
+ public void setStripHitsCollectionName(String stripHitsCollectionName) {
+ this.stripHitsCollectionName = stripHitsCollectionName;
+ }
+
+ public void setTrackCollectionName(String trackCollectionName) {
+ this.trackCollectionName = trackCollectionName;
+ }
+
+ public void setStripMaxSeparation(double stripMaxSeparation) {
+ this.stripMaxSeparation = stripMaxSeparation;
+ }
+
+ public void setStripTolerance(double stripTolerance) {
+ this.stripTolerance = stripTolerance;
+ }
+
+ /**
+ * Set the SimTrackerHit collection to be used for tracking.
+ *
+ * @param simTrackerHitCollectionName The name of the SimTrackerHit
+ * collection in the event.
+ */
+ public void setSimTrackerHitCollectionName(String simTrackerHitCollectionName) {
+ this.simTrackerHitCollectionName = simTrackerHitCollectionName;
+ }
+
+ /**
+ * This is used to setup the Drivers after XML config.
+ */
+ 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.println("Set B-field to " + this.bfield);
+ }
+
+ initialize();
+
+ super.detectorChanged(detector);
+ }
+
+ /**
+ * Setup all the child Drivers necessary for track reconstruction.
+ */
+ private void initialize() {
+ //
+ // 1) Driver to create HelicalTrackHits expected by Seedtracker.
+ //
+ // TODO Make this step its own separate Driver??? (Matt)
+
+ // Setup default stereo pairings, which should work for even number of
+ // modules.
+ List<SiTrackerModule> modules = detector.getSubdetector(subdetectorName).getDetectorElement().findDescendants(SiTrackerModule.class);
+ if (modules.size() == 0) {
+ throw new RuntimeException("No SiTrackerModules found in detector.");
+ }
+
+
+ // Create the Driver.
+ HelicalTrackHitDriver hthdriver = new HelicalTrackHitDriver();
+ hthdriver.addCollection(stripHitsCollectionName);
+ hthdriver.setOutputCollectionName(hthOutputCollectionName);
+// hthdriver.setHitRelationName(helicalTrackHitRelationsCollectionName);
+// hthdriver.setMCRelationName(helicalTrackMCRelationsCollectionName);
+
+ // hthdriver.setStripMaxSeparation(stripMaxSeparation);
+ // hthdriver.setStripTolerance(stripTolerance); // user parameter?
+ hthdriver.setTransformToTracking(true);
+ hthdriver.setDebug(true);
+ add(hthdriver);
+
+ //
+ // 2) Driver to run Seed Tracker.
+ //
+ sFinallist = StrategyXMLUtils.getStrategyListFromInputStream(this.getClass().getResourceAsStream(strategyResource));
+ // 3) Cleanup the readouts for next event.
+ //
+ List<String> readoutCleanup = new ArrayList<String>();
+ readoutCleanup.add(this.simTrackerHitCollectionName);
+ add(new ReadoutCleanupDriver(readoutCleanup));
+
+ }
+
+ /**
+ * Call super for child processing at start of data.
+ */
+ public void startOfData() {
+ super.startOfData();
+ }
+
+ /**
+ * This method is used to run the reconstruction and print debug
+ * information.
+ */
+ public void process(EventHeader event) {
+ // This call runs the track reconstruction using the sub-Drivers.
+ super.process(event);
+ double maxChi2 = 250;
+ List<HelicalTrackHit> hth = event.get(HelicalTrackHit.class, stInputCollectionName);
+
+
+ System.out.println("The HelicalTrackHit collection " + hthOutputCollectionName + " has " + hth.size() + " hits.");
+ List<HelicalTrackHit> hitsLayer1 = getLayerHits(hth, 1);
+ List<HelicalTrackHit> hitsLayer3 = getLayerHits(hth, 3);
+ List<HelicalTrackHit> hitsLayer5 = getLayerHits(hth, 5);
+ List<HelicalTrackHit> hitsLayer7 = getLayerHits(hth, 7);
+ List<HelicalTrackHit> hitsLayer9 = getLayerHits(hth, 9);
+
+ List<SeedCandidate> seedtracks = new ArrayList<SeedCandidate>();
+ for (HelicalTrackHit h1 : hitsLayer1) {
+ for (HelicalTrackHit h3 : hitsLayer3) {
+ for (HelicalTrackHit h5 : hitsLayer5) {
+ for (HelicalTrackHit h7 : hitsLayer7) {
+// for (HelicalTrackHit h9 : hitsLayer9) {
+
+ SeedCandidate seed = new SeedCandidate(sFinallist.get(0), bfield);
+ seed.addHit(h1);
+ seed.addHit(h3);
+ seed.addHit(h5);
+ seed.addHit(h7);
+// seed.addHit(h9);
+
+ HelicalTrackFit fitRes = fit(seed);
+ if (fitRes != null) {
+ seed.setHelix(fitRes);
+ if (fitRes.chisq()[1] > maxChi2)
+ continue;
+
+ seedtracks.add(seed);
+// System.out.println(fitRes.toString());
+ }
+// }
+ }
+ }
+ }
+ }
+
+ addTracksToEvent(event, seedtracks, bfield);
+ // Debug printouts.
+ if (debug) {
+ // Check for HelicalTrackHits.
+
+ // Check for Tracks.
+ List<Track> tracks = event.get(Track.class, trackCollectionName);
+ System.out.println("The Track collection " + trackCollectionName + " has " + tracks.size() + " tracks.");
+
+ // Print out track info.
+ for (Track track : tracks) {
+ System.out.println(track.toString());
+ System.out.println("chi2 = " + track.getChi2());
+ }
+ }
+
+ // Increment number of events.
+ ++nevents;
+
+ // Add to tracks found.
+ ntracks += event.get(Track.class, trackCollectionName).size();
+ }
+
+ public HelicalTrackFit fit(SeedCandidate seed) {
+ List<HelicalTrackHit> hitcol = seed.getHits();
+ Map<HelicalTrackHit, MultipleScatter> msmap = new HashMap<HelicalTrackHit, MultipleScatter>();
+ SlopeInterceptLineFitter _lfitter = new SlopeInterceptLineFitter();
+ SlopeInterceptLineFit _lfit;
+ boolean success = false;
+ // Check if we have enough pixel hits to do a straight-line fit of s vs z
+ int npix = hitcol.size();
+ // Calculate the arc lengths from the DCA to each hit and check for backwards hits
+ Map<HelicalTrackHit, Double> smap = getPathLengths(hitcol);
+ // Create the objects that will hold the fit output
+ double[] chisq = new double[2];
+ int[] ndof = new int[2];
+ ndof[0] = 0;
+ chisq[0] = 0;
+ double[] par = new double[5];
+ SymmetricMatrix cov = new SymmetricMatrix(5);
+
+
+ // Setup for the line fit
+ double[] s = new double[npix];
+ double[] z = new double[npix];
+ double[] dz = new double[npix];
+
+ // Store the coordinates and errors for the line fit
+ for (int i = 0; i < npix; i++) {
+ HelicalTrackHit hit = hitcol.get(i);
+ z[i] = hit.z();
+ System.out.println(hit.getCorrectedCovMatrix().toString());
+ dz[i] = Math.sqrt(hit.getCorrectedCovMatrix().e(2, 2));
+ s[i] = smap.get(hit);
+ System.out.println(z[i] + " " + dz[i] + " " + s[i]);
+ }
+
+ // Call the line fitter and check for success
+ success = _lfitter.fit(s, z, dz, npix);
+ if (!success) {
+ return null;
+ }
+
+ // Save the line fit, chi^2, and DOF
+ _lfit = _lfitter.getFit();
+ chisq[1] = _lfit.chisquared();
+ ndof[1] = npix - 2;
+
+ // Save the line fit parameters
+ par[HelicalTrackFit.z0Index] = _lfit.intercept();
+ par[HelicalTrackFit.slopeIndex] = _lfit.slope();
+ par[HelicalTrackFit.curvatureIndex] = 0.0001;
+ par[HelicalTrackFit.dcaIndex] = 0.0001;
+ par[HelicalTrackFit.phi0Index] = 0.000;
+
+
+ // Save the line fit covariance matrix elements
+ cov.setElement(HelicalTrackFit.z0Index, HelicalTrackFit.z0Index, Math.pow(_lfit.interceptUncertainty(), 2));
+ cov.setElement(HelicalTrackFit.z0Index, HelicalTrackFit.slopeIndex, _lfit.covariance());
+ cov.setElement(HelicalTrackFit.slopeIndex, HelicalTrackFit.slopeIndex, Math.pow(_lfit.slopeUncertainty(), 2));
+ cov.setElement(HelicalTrackFit.curvatureIndex, HelicalTrackFit.curvatureIndex, 0);
+ cov.setElement(HelicalTrackFit.curvatureIndex, HelicalTrackFit.phi0Index, 0);
+ cov.setElement(HelicalTrackFit.phi0Index, HelicalTrackFit.phi0Index, 0);
+ cov.setElement(HelicalTrackFit.curvatureIndex, HelicalTrackFit.dcaIndex, 0); // fix d0 sign convention
+ cov.setElement(HelicalTrackFit.phi0Index, HelicalTrackFit.dcaIndex, 0); // fix d0 sign convention
+ cov.setElement(HelicalTrackFit.dcaIndex, HelicalTrackFit.dcaIndex, 0);
+
+
+ // Create the HelicalTrackFit for this helix
+ return new HelicalTrackFit(par, cov, chisq, ndof, smap, msmap);
+
+ }
+
+ private Map<HelicalTrackHit, Double> getPathLengths(List<HelicalTrackHit> hits) {
+
+ // Create a map to store the arc lengths
+ Map<HelicalTrackHit, Double> smap = new HashMap<HelicalTrackHit, Double>();
+
+ // Initialize looper tracking and iterate over ordered list of hits
+ double slast = 0.;
+ int ilast = -1;
+ double s;
+ for (int i = 0; i < hits.size(); i++) {
+
+ // Retrieve the next hit ordered by z coordinate and check hit type
+ HelicalTrackHit hit = hits.get(i);
+ if (hit instanceof HelicalTrack2DHit) {
+
+ // Axial hit - measure from the DCA (can't handle loopers)
+// s = HelixUtils.PathLength(_cfit, hit);
+ s = hit.getPosition()[0];
+ // Save the arc length for this hit
+ smap.put(hit, s);
+ }
+ }
+ return smap;
+ }
+
+ private List<HelicalTrackHit> getLayerHits(List<HelicalTrackHit> hth, int layer) {
+ List<HelicalTrackHit> layerHits = new ArrayList<HelicalTrackHit>();
+
+ for (HelicalTrackHit hit : hth) {
+ if (hit.Layer() == layer)
+ layerHits.add(hit);
+ }
+ return layerHits;
+ }
+
+ 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.");
+ }
+ }
+
+ private void addTracksToEvent(EventHeader event, List<SeedCandidate> seedlist, double bfield) {
+ // Create a the track list
+ List<Track> tracks = new ArrayList<Track>();
+
+ // Initialize the reference point to the origin
+ double[] ref = new double[3];
+ ref[0] = 0.;
+ ref[1] = 0.;
+ ref[2] = 0.;
+ // Loop over the SeedCandidates that have survived
+ for (SeedCandidate trackseed : seedlist) {
+
+ // Create a new SeedTrack (SeedTrack extends BaseTrack)
+ SeedTrack trk = new SeedTrack();
+
+ // Add the hits to the track
+ for (HelicalTrackHit hit : trackseed.getHits()) {
+ trk.addHit((TrackerHit) hit);
+ }
+
+ // Retrieve the helix and save the relevant bits of helix info
+ HelicalTrackFit helix = trackseed.getHelix();
+ trk.setTrackParameters(helix.parameters(), bfield);
+ trk.setCovarianceMatrix(helix.covariance());
+ trk.setChisq(helix.chisqtot());
+ trk.setNDF(helix.ndf()[0] + helix.ndf()[1]);
+
+ // Flag that the fit was successful and set the reference point
+ trk.setFitSuccess(true);
+ trk.setReferencePoint(ref);
+ trk.setRefPointIsDCA(true);
+
+ // Set the strategy used to find this track
+ trk.setStratetgy(trackseed.getSeedStrategy());
+
+ // Set the SeedCandidate this track is based on
+ trk.setSeedCandidate(trackseed);
+
+
+ // Add the track to the list of tracks
+ tracks.add((Track) trk);
+ }
+
+ // Put the tracks back into the event and exit
+ int flag = 1 << LCIOConstants.TRBIT_HITS;
+ event.put(trackCollectionName, tracks, Track.class, flag);
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/DataTrackerFakeHitDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/DataTrackerFakeHitDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,1030 @@
+package org.hps.recon.tracking;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogram1D;
+import hep.aida.IPlotter;
+import hep.aida.IProfile1D;
+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.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.hps.conditions.deprecated.SvtUtils;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.ITranslation3D;
+import org.lcsim.detector.Transform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.solids.Inside;
+import org.lcsim.detector.solids.Polygon3D;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.DopedSilicon;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
+import org.lcsim.detector.tracker.silicon.SiStrips;
+import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseRawTrackerHit;
+import org.lcsim.event.base.BaseSimTrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.fit.helicaltrack.HitIdentifier;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHit;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+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
+ */
+public class DataTrackerFakeHitDriver extends Driver {
+
+ private boolean debug = false;
+ TrackerHitUtils trackerhitutils = new TrackerHitUtils();
+ Hep3Matrix detToTrk;
+ Hep3Vector _bfield;
+ TrackerHitType trackerType = new TrackerHitType(TrackerHitType.CoordinateSystem.GLOBAL, TrackerHitType.MeasurementType.STRIP_1D);
+ CoordinateSystem coordinate_system = trackerType.getCoordinateSystem();
+ private HitIdentifier _ID = new HitIdentifier();
+ private EventHeader.LCMetaData metaData = null;
+ private boolean _doHth = false;
+ boolean createSimTrackerHits = false;
+ // Collections
+ List<SimTrackerHit> simHits = null;
+ List<SiTrackerHit> stripHits1D = null;
+ List<HelicalTrackHit> hths = null;
+ String trackCollectionName = "MCParticle_HelicalTrackFit";
+ String stripHitOutputCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+ String hthOutputCollectionName = "RotatedHelicalTrackHits";
+ String simTrackerHitCollectionName = "FakeTrackerHits";
+ // Subdetector name.
+ private String subdetectorName = "Tracker";
+ // Various data lists required by digitization.
+ private List<String> processPaths = new ArrayList<String>();
+ private List<IDetectorElement> processDEs = new ArrayList<IDetectorElement>();
+ private Set<SiSensor> processSensors = new HashSet<SiSensor>();
+ //Visualization
+ private boolean hideFrame = false;
+ private AIDA aida = AIDA.defaultInstance();
+ private HashMap<SiSensor, IProfile1D> _delta_histos;
+ private HashMap<SiSensor, IHistogram1D> _delta_itercount = new HashMap<SiSensor, IHistogram1D>();
+ IProfile1D _prf_final_deltas;
+ IProfile1D _prf_all_deltas;
+ IHistogram1D _h_nstriphits_top;
+ IHistogram1D _h_nstriphits_bottom;
+ IAnalysisFactory af = aida.analysisFactory();
+ IPlotter plotter_iter;
+ IPlotter plotter_itercount;
+ IPlotter plotter_iter_final;
+ IPlotter plotter_iter_all;
+ IPlotter plotter_nstripclusters;
+ IPlotter plotter_trackposodd;
+ int[][] counts = new int[2][10];
+
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
+ public void setHideFrame(boolean hide) {
+ this.hideFrame = hide;
+ }
+
+ public void setDoHth(boolean debug) {
+ this._doHth = debug;
+ }
+
+ /**
+ * Enable/disable the creation of SimTrackerHits
+ */
+ public void setCreateSimTrackerHits(boolean createSimTrackerHits) {
+ this.createSimTrackerHits = createSimTrackerHits;
+ }
+
+// public void setReadoutCollectionName(String readoutCollectionName) {
+// this.readoutCollectionName = readoutCollectionName;
+// }
+ public void setSubdetectorName(String subdetectorName) {
+ this.subdetectorName = subdetectorName;
+ }
+
+ public void setStripHitOutputCollectionName(String stripHitOutputCollectionName) {
+ this.stripHitOutputCollectionName = stripHitOutputCollectionName;
+ }
+
+ public void setHthOutputCollectionName(String hthOutputCollectionName) {
+ this.hthOutputCollectionName = hthOutputCollectionName;
+ }
+
+ public void setTrackCollectionName(String trackCollectionName) {
+ this.trackCollectionName = trackCollectionName;
+ }
+
+ /**
+ * Creates a new instance of TrackerHitDriver.
+ */
+ public DataTrackerFakeHitDriver() {
+ this._delta_histos = new HashMap<SiSensor, IProfile1D>();
+ }
+
+ /**
+ * Do initialization once we get a Detector.
+ */
+ @Override
+ public void detectorChanged(Detector detector) {
+
+ // Call sub-Driver's detectorChanged methods.
+ super.detectorChanged(detector);
+
+
+ Hep3Vector IP = new BasicHep3Vector(0., 0., 1.);
+ _bfield = new BasicHep3Vector(0, 0, detector.getFieldMap().getField(IP).y());
+ detToTrk = trackerhitutils.detToTrackRotationMatrix();
+
+
+ // Process detectors specified by path, otherwise process entire
+ // detector
+ IDetectorElement deDetector = detector.getDetectorElement();
+
+ for (String path : processPaths) {
+ processDEs.add(deDetector.findDetectorElement(path));
+ }
+
+ if (processDEs.isEmpty()) {
+ processDEs.add(deDetector);
+ }
+
+ for (IDetectorElement detectorElement : processDEs) {
+ processSensors.addAll(detectorElement.findDescendants(SiSensor.class));
+ }
+
+ // Set the detector to process.
+ processPaths.add(subdetectorName);
+
+ this.makePlots();
+
+ }
+
+ /**
+ * Perform the digitization.
+ */
+ @Override
+ public void process(EventHeader event) {
+
+
+ // Obtain the tracks from the event
+ if (!event.hasCollection(HPSTrack.class, trackCollectionName)) {
+ this.printDebug("No HPSTracks were found, skipping event");
+ simHits = null;
+ return;
+ }
+ List<HPSTrack> tracks = event.get(HPSTrack.class, trackCollectionName);
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": found " + tracks.size() + " tracks (" + this.trackCollectionName + ")");
+ }
+
+ // Instantiate the list of interest
+ if (this._doHth) {
+ this.printDebug("Creating HelicalTrackHits...");
+ hths = new ArrayList<HelicalTrackHit>();
+ } else if (createSimTrackerHits) {
+ this.printDebug("Creating SimTrackerHits...");
+ simHits = new ArrayList<SimTrackerHit>();
+ metaData = event.getMetaData(event.get(SimTrackerHit.class, "TrackerHits"));
+ } else {
+ // Create StripHit1Ds by default
+ this.printDebug("Creating StripHit1D...");
+ stripHits1D = new ArrayList<SiTrackerHit>();
+ }
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": Add hits for " + tracks.size() + " tracks (" + this.trackCollectionName + ")");
+ }
+
+ for (HPSTrack helix : tracks) {
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": trying to add hits for this track");
+ }
+
+ // Get the MC Particle associated with this track
+ MCParticle mcParticle = helix.getMCParticle();
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + helix.toString());
+ System.out.println(this.getClass().getSimpleName() + ": htf x0 " + helix.x0() + " y0 " + helix.y0());
+
+ System.out.println(this.getClass().getSimpleName() + ": create a WTrack object");
+ }
+
+ WTrack wtrack = new WTrack(helix, Math.abs(_bfield.z()), true); //remove sign from B-field (assumed to go along z-direction)
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": " + wtrack.toString());
+
+ }
+
+
+
+ int n_hits_top = 0;
+ int n_hits_bot = 0;
+ boolean isTopTrack = false;
+ boolean isBotTrack = false;
+
+ // Make hits if the helix passed through the sensor
+ for (SiSensor sensor : processSensors) {
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": add hits to sensor " + sensor.getName() + " at position " + sensor.getGeometry().getPosition().toString());
+ }
+
+ // When creating stereo hits, skip the even sensors
+ if (this._doHth && _ID.getLayer(sensor) % 2 == 0) {
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": this was an even sensor -> skip for HTH production");
+ }
+ continue;
+ }
+
+ // Get the position where the sensor and track intercept (Maybe this should go
+ // inside the method makeSimTrackerHit since it's the only method that uses it
+ Hep3Vector trackPosAtSensor = this.getHelixPlaneIntercept(sensor, wtrack);
+ this.printDebug("The track/plane intercept at " + trackPosAtSensor.toString());
+
+ // Check if the track lies within the sensor
+ boolean isHit = TrackUtils.sensorContainsTrack(trackPosAtSensor, sensor);
+
+ if (isHit) {
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": make a tracker hit and add to this sensor");
+ }
+ if (SvtUtils.getInstance().isTopLayer(sensor)) {
+ n_hits_top++;
+ isTopTrack = true;
+ } else {
+ n_hits_bot++;
+ isBotTrack = true;
+ }
+ if (this._doHth) {
+ hths.add(this.makeHelicalTrackHit(sensor, wtrack));
+ } else if (createSimTrackerHits) {
+ // Create a SimTrackerHit at the intersect between a track and a sensor
+ simHits.add(this.makeSimTrackerHit(metaData, sensor, trackPosAtSensor, mcParticle, wtrack));
+ } else {
+ stripHits1D.add(this.makeTrackerHit(sensor, wtrack));
+ }
+ } else {
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": this helix didn't pass within the sensor so no hit was added");
+ }
+ }
+
+ }
+
+ if (isTopTrack) {
+ this._h_nstriphits_top.fill(n_hits_top);
+ }
+ if (isBotTrack) {
+ this._h_nstriphits_bottom.fill(n_hits_bot);
+ }
+ if (isTopTrack && isBotTrack) {
+ System.out.println(this.getClass().getSimpleName() + ": tris track is both top and bottom??? \n" + wtrack.toString() + "\nHTF:" + helix.toString());
+ System.exit(1);
+ }
+
+ /*
+ stripHits1D.addAll(stripHits1D_for_track);
+ hths.addAll(hths_for_track);
+ */
+ }
+
+
+
+ if (debug) {
+ if (stripHits1D != null) {
+ System.out.println(this.getClass().getSimpleName() + ": Produced " + stripHits1D.size() + " hits for collection " + this.stripHitOutputCollectionName);
+ }
+ if (hths != null) {
+ System.out.println(this.getClass().getSimpleName() + ": Produced " + hths.size() + " hits for collection " + this.hthOutputCollectionName);
+ }
+ }
+
+
+ //int flag = LCIOUtil.bitSet(0, 31, true); // Turn on 64-bit cell ID.
+ //event.put(this.rawTrackerHitOutputCollectionName, rawHits, RawTrackerHit.class, flag, toString());
+ // Put the collection of interest into the event
+
+ if (_doHth) {
+ event.put(hthOutputCollectionName, hths, HelicalTrackHit.class, 0);
+ } else if (createSimTrackerHits) {
+ event.put(simTrackerHitCollectionName, simHits, SimTrackerHit.class, 0);
+ this.printDebug("SimTrackerHits created: " + simHits.size());
+ } else {
+ event.put(stripHitOutputCollectionName, stripHits1D, SiTrackerHitStrip1D.class, 0, toString());
+ }
+ //event.put("RotatedHelicalTrackHits", rotatedhits, HelicalTrackHit.class, 0);
+
+ /*
+ if (debug) {
+ if(event.hasCollection(HelicalTrackHit.class, "RotatedHelicalTrackHits")) {
+ System.out.println(this.getClass().getSimpleName() + ": has hths:");
+ for(HelicalTrackHit hth : hths) {
+ System.out.println(this.getClass().getSimpleName() + ": " + hth.getPosition().toString());
+ }
+ } else {
+ System.out.println(this.getClass().getSimpleName() + ": has not hths!");
+ }
+ }
+ if (debug) {
+ for (int mod = 0; mod < 2; mod++) {
+ for (int layer = 0; layer < 10; layer++) {
+ counts[mod][layer] += SvtUtils.getInstance().getSensor(mod, layer).getReadout().getHits(SiTrackerHit.class).size();
+ }
+ }
+ }*/
+ }
+
+ private SiTrackerHitStrip1D makeTrackerHit(SiSensor sensor, WTrack wtrack) {
+ //private SiTrackerHitStrip1D makeTrackerHit(List<HPSFittedRawTrackerHit> cluster, SiSensorElectrodes electrodes) {
+ //create fake raw tracker hit
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": makeTrackerHit");
+ }
+
+ List<RawTrackerHit> rth_cluster = this.makeRawTrackerFakeHit(sensor);
+ if (rth_cluster.size() != 1) {
+ System.out.println(this.getClass().getSimpleName() + ": the fake raw tracker hit cluster is different than one!? " + rth_cluster.size());
+ System.exit(1);
+ }
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": created a fake raw tracker hit ");
+ }
+ RawTrackerHit raw_hit = rth_cluster.get(0);
+ IIdentifier id = raw_hit.getIdentifier();
+
+ //Get the electrode objects
+ SiTrackerIdentifierHelper _sid_helper = (SiTrackerIdentifierHelper) sensor.getIdentifierHelper();
+ ChargeCarrier carrier = ChargeCarrier.getCarrier(_sid_helper.getSideValue(id));
+ SiSensorElectrodes electrodes = ((SiSensor) raw_hit.getDetectorElement()).getReadoutElectrodes(carrier);
+
+
+
+
+ ITransform3D local_to_global;
+ if (coordinate_system == TrackerHitType.CoordinateSystem.GLOBAL) {
+ local_to_global = new Transform3D();
+ } else if (coordinate_system == TrackerHitType.CoordinateSystem.SENSOR) {
+ local_to_global = sensor.getGeometry().getLocalToGlobal();
+ } else {
+ throw new RuntimeException(this.getClass().getSimpleName() + " problem with coord system " + coordinate_system.toString());
+ }
+
+
+ ITransform3D electrodes_to_global = electrodes.getLocalToGlobal();
+ ITransform3D global_to_hit = local_to_global.inverse();
+ ITransform3D electrodes_to_hit = Transform3D.multiply(global_to_hit, electrodes_to_global);
+
+ Hep3Vector u = electrodes_to_hit.rotated(electrodes.getMeasuredCoordinate(0));
+ Hep3Vector v = electrodes_to_hit.rotated(electrodes.getUnmeasuredCoordinate(0));
+ Hep3Vector w = VecOp.cross(u, v);
+ Hep3Vector _orgloc = new BasicHep3Vector(0., 0., 0.);
+ electrodes_to_global.transformed(_orgloc);
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": electrodes u " + u.toString());
+ System.out.println(this.getClass().getSimpleName() + ": electrodes v " + v.toString());
+ System.out.println(this.getClass().getSimpleName() + ": electrodes w " + w.toString() + "( " + w.magnitude() + ")");
+ }
+
+ electrodes_to_global.getTranslation().translate(_orgloc);
+ if (debug) {
+ System.out.print(this.getClass().getSimpleName() + ": orgloc " + _orgloc.toString() + " -> ");
+ }
+ _orgloc = VecOp.mult(detToTrk, _orgloc);
+ if (debug) {
+ System.out.println(_orgloc.toString());
+ }
+
+
+
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": Try to find the interception point");
+ }
+
+ //B-field must go along Z direction
+ Hep3Vector h = new BasicHep3Vector(_bfield.x(), _bfield.y(), Math.abs(_bfield.z()));
+ h = VecOp.unit(h);
+ //Rotate into tracking frame
+ Hep3Vector eta = VecOp.mult(detToTrk, w);
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": eta " + eta.toString());
+ }
+
+ Hep3Vector position = wtrack.getHelixAndPlaneIntercept(_orgloc, eta, h);
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": found interception point at position " + position.toString());
+ }
+
+
+ HelicalTrackFit htf = wtrack._htf;
+ List<Double> s = HelixUtils.PathToXPlane(htf, position.x(), 0, 0);
+ Hep3Vector posOnHelix = HelixUtils.PointOnHelix(htf, s.get(0));
+ Hep3Vector posdiff = VecOp.sub(position, posOnHelix);
+ System.out.println(this.getClass().getSimpleName() + ": diffpos " + posdiff.toString() + " L " + position.toString() + " posOnHelix " + posOnHelix.toString() + " R=" + htf.R());
+
+ position = VecOp.mult(VecOp.inverse(detToTrk), position);
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": rotate the hit position to the global frame -> " + position.toString());
+ }
+
+
+
+ // Need to make sure that the position is at the edge of the strip in the global frame
+ // 1. Rotate to the local sensor frame
+ position = ((SiSensor) electrodes.getDetectorElement()).getGeometry().getGlobalToLocal().transformed(position);
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": local (sensor) hit position " + position.toString());
+ }
+
+ // 2. Remove the coordinate of the unmeasured direction
+
+ position = new BasicHep3Vector(position.x(), 0, position.z());
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": fixed local (sensor) hit position " + position.toString());
+ }
+
+ // 3. Transform back to global coordinates
+
+ position = ((SiSensor) electrodes.getDetectorElement()).getGeometry().getLocalToGlobal().transformed(position);
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": fixed global hit position " + position.toString());
+ }
+
+
+
+
+ //Fill dummy versions
+ SymmetricMatrix covariance = this.getCovariance(rth_cluster, electrodes);
+ double time = this.getTime(rth_cluster);
+ double energy = this.getEnergy(rth_cluster);
+
+
+ SiTrackerHitStrip1D hit = new SiTrackerHitStrip1D(position, covariance, energy, time, rth_cluster, trackerType);
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": created SiStrip1D at " + position.toString());
+ }
+
+
+ return hit;
+
+
+ }
+
+ /**
+ *
+ * Find the unit vector of a sensor
+ *
+ * @param sensor
+ * @return unit vector of the plane
+ */
+ private Hep3Vector getPlaneUnitVector(SiSensor sensor) {
+ /*
+ * Weird way of getting the unit vector by creating a fake raw tracker hit...must be simpler way?
+ */
+ RawTrackerHit raw_hit = this.makeRawTrackerFakeHit(sensor).get(0);
+ IIdentifier id = raw_hit.getIdentifier();
+ //Get the electrode objects
+ SiTrackerIdentifierHelper _sid_helper = (SiTrackerIdentifierHelper) sensor.getIdentifierHelper();
+ ChargeCarrier carrier = ChargeCarrier.getCarrier(_sid_helper.getSideValue(id));
+ SiSensorElectrodes electrodes = ((SiSensor) raw_hit.getDetectorElement()).getReadoutElectrodes(carrier);
+ ITransform3D local_to_global;
+ if (coordinate_system == TrackerHitType.CoordinateSystem.GLOBAL) {
+ local_to_global = new Transform3D();
+ } else if (coordinate_system == TrackerHitType.CoordinateSystem.SENSOR) {
+ local_to_global = sensor.getGeometry().getLocalToGlobal();
+ } else {
+ throw new RuntimeException(this.getClass().getSimpleName() + " problem with coord system " + coordinate_system.toString());
+ }
+ ITransform3D electrodes_to_global = electrodes.getLocalToGlobal();
+ ITransform3D global_to_hit = local_to_global.inverse();
+ ITransform3D electrodes_to_hit = Transform3D.multiply(global_to_hit, electrodes_to_global);
+
+ Hep3Vector u = electrodes_to_hit.rotated(electrodes.getMeasuredCoordinate(0));
+ Hep3Vector v = electrodes_to_hit.rotated(electrodes.getUnmeasuredCoordinate(0));
+ Hep3Vector w = VecOp.cross(u, v);
+ Hep3Vector eta = VecOp.mult(detToTrk, w);
+ return eta;
+
+ }
+
+ /**
+ *
+ * Find the origin of the sensor plane
+ *
+ * @param sensor
+ * @return origin position of the plane
+ */
+ private Hep3Vector getOrgLoc(SiSensor sensor) {
+ /*
+ * Weird way of getting the org location by creating a fake raw tracker hit...must be simpler way?
+ */
+ List<RawTrackerHit> rth_cluster = this.makeRawTrackerFakeHit(sensor);
+ if (rth_cluster.size() != 1) {
+ System.out.println(this.getClass().getSimpleName() + ": the fake raw tracker hit cluster is different than one!? " + rth_cluster.size());
+ System.exit(1);
+ }
+ //Get the electrode objects
+ IIdentifier id = rth_cluster.get(0).getIdentifier();
+ SiTrackerIdentifierHelper _sid_helper = (SiTrackerIdentifierHelper) sensor.getIdentifierHelper();
+ ChargeCarrier carrier = ChargeCarrier.getCarrier(_sid_helper.getSideValue(id));
+ SiSensorElectrodes electrodes = ((SiSensor) rth_cluster.get(0).getDetectorElement()).getReadoutElectrodes(carrier);
+ ITransform3D local_to_global;
+ if (coordinate_system == TrackerHitType.CoordinateSystem.GLOBAL) {
+ local_to_global = new Transform3D();
+ } else if (coordinate_system == TrackerHitType.CoordinateSystem.SENSOR) {
+ local_to_global = sensor.getGeometry().getLocalToGlobal();
+ } else {
+ throw new RuntimeException(this.getClass().getSimpleName() + " problem with coord system " + coordinate_system.toString());
+ }
+ ITransform3D electrodes_to_global = electrodes.getLocalToGlobal();
+ Hep3Vector _orgloc = new BasicHep3Vector(0., 0., 0.);
+ electrodes_to_global.transformed(_orgloc);
+ electrodes_to_global.getTranslation().translate(_orgloc);
+ if (debug) {
+ System.out.print(this.getClass().getSimpleName() + ": orgloc " + _orgloc.toString() + " -> ");
+ }
+ _orgloc = VecOp.mult(detToTrk, _orgloc);
+ if (debug) {
+ System.out.println(_orgloc.toString());
+ }
+
+ return _orgloc;
+
+ }
+
+ private Hep3Vector getHelixPlaneIntercept(SiSensor sensor, WTrack wtrack) {
+ Hep3Vector eta = this.getPlaneUnitVector(sensor);
+ Hep3Vector _orgloc = this.getOrgLoc(sensor);
+ Hep3Vector h = new BasicHep3Vector(_bfield.x(), _bfield.y(), Math.abs(_bfield.z()));
+ h = VecOp.unit(h);
+ Hep3Vector position = wtrack.getHelixAndPlaneIntercept(_orgloc, eta, h);
+ if (debug) {
+ HelicalTrackFit htf = wtrack._htf;
+ List<Double> s = HelixUtils.PathToXPlane(htf, position.x(), 0, 0);
+ Hep3Vector posOnHelix = HelixUtils.PointOnHelix(htf, s.get(0));
+ Hep3Vector posdiff = VecOp.sub(position, posOnHelix);
+ System.out.println(this.getClass().getSimpleName() + ": Path length to position " + position.toString() + ": s = " + s.get(0));
+ System.out.println(this.getClass().getSimpleName() + ": Difference between W and helixutils: diffpos " + posdiff.toString() + " ( " + position.toString() + " posOnHelix " + posOnHelix.toString() + " R=" + htf.R());
+ }
+
+
+ return position;
+ }
+
+ private HelicalTrackHit makeHelicalTrackHit(SiSensor sensor, WTrack wtrack) {
+ //private SiTrackerHitStrip1D makeTrackerHit(List<HPSFittedRawTrackerHit> cluster, SiSensorElectrodes electrodes) {
+ //create fake raw tracker hit
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": makeTrackerHit");
+ }
+
+ List<RawTrackerHit> rth_cluster = this.makeRawTrackerFakeHit(sensor);
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": Try to find the interception point");
+ }
+
+ Hep3Vector position = this.getHelixPlaneIntercept(sensor, wtrack);
+
+
+ //Fill dummy covariance matrix with minimal uncertainties
+ //SymmetricMatrix covariance = this.getCovariance(rth_cluster, electrodes);
+ SymmetricMatrix covariance = new SymmetricMatrix(3);
+ double cov_xx = Math.pow(0.00001, 2); //1um error
+ double cov_yy = cov_xx;
+ double cov_zz = cov_xx;
+ covariance.setElement(0, 0, cov_xx);
+ covariance.setElement(1, 1, cov_yy);
+ covariance.setElement(2, 2, cov_zz);
+
+ double time = this.getTime(rth_cluster);
+ double energy = this.getEnergy(rth_cluster);
+
+
+ //IDetectorElement de = sensor;
+ String det = _ID.getName(sensor);
+ int layer = _ID.getLayer(sensor);
+ BarrelEndcapFlag beflag = _ID.getBarrelEndcapFlag(sensor);
+
+ if (layer % 2 == 0) {
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": problem, trying to create a HTH for even layer? " + layer);
+ }
+ System.exit(1);
+ }
+
+ HelicalTrackHit hit = new HelicalTrackHit(position, covariance, 0.0, time, 3, rth_cluster, det, layer, beflag);
+ //SiTrackerHitStrip1D hit = new SiTrackerHitStrip1D(position, covariance, energy, time, rth_cluster, trackerType);
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": created HelicalTrackHit at " + position.toString() + " and layer " + hit.Layer() + "(" + layer + ")");
+ }
+
+
+ return hit;
+
+
+ }
+
+ /**
+ * Create a SimTrackerHit and add it to the corresponding readout
+ *
+ * @param metaData : meta data associated with the SimTrackerHit collection
+ * @param sensor : sensor on which the hit will be created on
+ * @param trkPositionAtSensor : the position of a track at a sensor plane
+ * @param particle : MC particle associated with the track containing the
+ * hit
+ * @return SimTrackerHit
+ */
+ private SimTrackerHit makeSimTrackerHit(EventHeader.LCMetaData metaData, SiSensor sensor, Hep3Vector trkPositionAtSensor, MCParticle particle, WTrack wtrack) {
+
+ // Transform the position of the SimTrackerHit to the detector coordinates
+ // TODO: Fix the extrapolator so that it returns the position in the detector frame
+ //Hep3Vector trkPositionAtSensorDet = VecOp.mult(VecOp.inverse(detToTrk),trkPositionAtSensor);
+ //this.printDebug("The helix and sensor intercept at: " + trkPositionAtSensorDet.toString());
+
+ // Sensor to tracking frame transformation
+ ITransform3D localToGlobal = sensor.getGeometry().getLocalToGlobal();
+ // Tracking frame to sensor transformation
+ ITransform3D globalToSensor = sensor.getGeometry().getGlobalToLocal();
+
+ // Get the sensor position
+ Hep3Vector sensorPosition = sensor.getGeometry().getPosition();
+ this.printDebug("Sensor position: " + sensorPosition.toString());
+ // Transform the sensor position to the tracking frame
+ Hep3Vector transformedSensorPosition = globalToSensor.transformed(sensorPosition);
+ this.printDebug("Transformed sensor position: " + transformedSensorPosition.toString());
+
+ // Get the solid representing a sensor
+ Box sensorSolid = (Box) sensor.getGeometry().getLogicalVolume().getSolid();
+ // Get the solid faces
+ Polygon3D pSide = sensorSolid.getFacesNormalTo(new BasicHep3Vector(0, 0, 1)).get(0);
+ this.printDebug("p Side: " + pSide.toString());
+ Polygon3D nSide = sensorSolid.getFacesNormalTo(new BasicHep3Vector(0, 0, -1)).get(0);
+ this.printDebug("n Side: " + pSide.toString());
+
+ // Translate to the sensor face (p side)
+ ITranslation3D translateToPSide = new Translation3D(VecOp.mult(-pSide.getDistance(), pSide.getNormal()));
+ this.printDebug("pSide Translation vector: " + translateToPSide.getTranslationVector().toString());
+
+ // Translate to the p side of the sensor
+ Hep3Vector pSidePosition = translateToPSide.translated(transformedSensorPosition);
+ this.printDebug("Translated sensor position at p side: " + pSidePosition.toString());
+ // Transform the sensor position to the tracking coordinates
+ localToGlobal.transform(pSidePosition);
+ this.printDebug("Translated sensor position at p side in tracking coordinates: " + pSidePosition.toString());
+ // Check if the point lies inside of the sensor
+ if (sensor.getGeometry().inside(pSidePosition) == Inside.OUTSIDE) {
+ throw new RuntimeException("Position of p side face does not lie within the sensor volume!");
+ } else {
+ this.printDebug("p side position lies within the sensor volume");
+ }
+
+ // Find the interception between the p side face and the track
+ Hep3Vector h = new BasicHep3Vector(_bfield.x(), _bfield.y(), Math.abs(_bfield.z()));
+ h = VecOp.unit(h);
+ // Transform the sensor position to the lcsim coordinates
+ pSidePosition = VecOp.mult(detToTrk, pSidePosition);
+ this.printDebug("p side position in lcsim coordinates: " + pSidePosition.toString());
+ //Hep3Vector pSideInter = wutils.getHelixAndPlaneIntercept(wtrack, pSidePosition, VecOp.unit(pSidePosition), h);
+ Hep3Vector eta = this.getPlaneUnitVector(sensor);
+ Hep3Vector pSideInter = wtrack.getHelixAndPlaneIntercept(pSidePosition, eta, h);
+ this.printDebug("Intersection between track and p side: " + pSideInter.toString());
+ // Transform back to the JLab coordinates
+ pSideInter = VecOp.mult(VecOp.inverse(detToTrk), pSideInter);
+ this.printDebug("Intersection trasnformed to the JLab coordinates: " + pSideInter.toString());
+ if (sensor.getGeometry().inside(pSideInter) == Inside.OUTSIDE) {
+ throw new RuntimeException("Position of p side/track intercept does not lie within the sensor volume!");
+ } else {
+ this.printDebug("p side/track intercept lies within the sensor volume");
+ }
+
+ // Translate to the sensor n side
+ ITranslation3D translateToNSide = new Translation3D(VecOp.mult(-nSide.getDistance(), nSide.getNormal()));
+ this.printDebug("n side Translation vector: " + translateToNSide.getTranslationVector().toString());
+
+ // Translate to the n side of the sensor
+ Hep3Vector nSidePosition = translateToNSide.translated(transformedSensorPosition);
+ this.printDebug("Translated sensor position at n side: " + nSidePosition.toString());
+ // Transform the sensor position to the tracking coordinates
+ localToGlobal.transform(nSidePosition);
+ this.printDebug("Translated sensor position at n side in tracking coordinates: " + nSidePosition.toString());
+ // Check if the point lies inside of the sensor
+ if (sensor.getGeometry().inside(nSidePosition) == Inside.OUTSIDE) {
+ throw new RuntimeException("Position of n side face does not lie within the sensor volume!");
+ } else {
+ this.printDebug("n side position lies within the sensor volume");
+ }
+
+ // Find the interception between the p side face and the track
+ // Transform the sensor position to the lcsim coordinates
+ nSidePosition = VecOp.mult(detToTrk, nSidePosition);
+ this.printDebug("n side position in lcsim coordinates: " + nSidePosition.toString());
+ //Hep3Vector pSideInter = wutils.getHelixAndPlaneIntercept(wtrack, pSidePosition, VecOp.unit(pSidePosition), h);
+ Hep3Vector nSideInter = wtrack.getHelixAndPlaneIntercept(nSidePosition, eta, h);
+ this.printDebug("Intersection between track and n side: " + nSideInter.toString());
+ // Transform back to the JLab coordinates
+ nSideInter = VecOp.mult(VecOp.inverse(detToTrk), nSideInter);
+ this.printDebug("Intersection trasnfored to the JLab coordinates: " + nSideInter.toString());
+ if (sensor.getGeometry().inside(nSideInter) == Inside.OUTSIDE) {
+ throw new RuntimeException("Position of n side/track intercept does not lie within the sensor volume!");
+ } else {
+ this.printDebug("n side/track intercept lies within the sensor volume");
+ }
+
+ // Find the midpoint between a straight line connecting the p side and n side intercepts
+ Hep3Vector trkPositionAtSensorDet = VecOp.add(nSideInter, pSideInter);
+ trkPositionAtSensorDet = VecOp.mult(.5, trkPositionAtSensorDet);
+ this.printDebug("Hit will be placed at position: " + trkPositionAtSensorDet.toString());
+ if (sensor.getGeometry().inside(trkPositionAtSensorDet) == Inside.OUTSIDE) {
+ throw new RuntimeException("Midpoint does not lie within the sensor volume!");
+ } else {
+ this.printDebug("midpoint lies within the sensor volume");
+ }
+
+ // Find the length of the line. For now, this is the path length
+ // Note: The small delta parameter is to avoid ending up outside of the sensor
+ double pathLength = VecOp.sub(nSideInter, pSideInter).magnitude() - .01;
+ this.printDebug("The path length is: " + pathLength);
+
+ /* DEBUG
+ Hep3Vector midpoint = new BasicHep3Vector(trkPositionAtSensorDet.v());
+ Hep3Vector direction = VecOp.unit(new BasicHep3Vector(particle.getMomentum().v()));
+ Hep3Vector half_length = VecOp.mult(pathLength/2.0,direction);
+
+ Hep3Vector endPoint = VecOp.add(midpoint,half_length);
+ this.printDebug("The end point is at position: " + endPoint.toString());
+
+ Hep3Vector startPoint = VecOp.add(midpoint,VecOp.mult(-1.0,half_length));
+ this.printDebug("The start point is at position: " + startPoint.toString());
+
+ if(sensor.getGeometry().inside(endPoint) == Inside.OUTSIDE){
+ throw new RuntimeException("Position of end point does not lie within the sensor volume!");
+ } else {
+ this.printDebug("end point lies within the sensor volume");
+ }
+
+ if(sensor.getGeometry().inside(startPoint) == Inside.OUTSIDE){
+ throw new RuntimeException("Position start point does not lie within the sensor volume!");
+ } else {
+ this.printDebug("Start point lies within the sensor volume");
+ } */
+
+ double dEdx = 24000/* MIP */ * DopedSilicon.ENERGY_EHPAIR;
+ double[] momentum = particle.getMomentum().v();
+ this.printDebug("Particle Momentum: " + particle.getMomentum().toString());
+ double time = 0;
+ int cellID = (int) TrackerHitUtils.makeSimTrackerHitId(sensor).getValue();
+
+ SimTrackerHit simHit = new BaseSimTrackerHit(trkPositionAtSensorDet.v(), dEdx, momentum, pathLength, time, cellID, particle, metaData, sensor);
+ // Add it to the sensor readout
+ // sensor.getReadout().addHit(simHit);
+ return simHit;
+ }
+
+ //private SymmetricMatrix getCovariance() {
+ private SymmetricMatrix getCovariance(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes) {
+ SymmetricMatrix covariance = new SymmetricMatrix(3);
+ covariance.setElement(0, 0, Math.pow(getMeasuredResolution(cluster, electrodes), 2));
+ covariance.setElement(1, 1, Math.pow(getUnmeasuredResolution(cluster, electrodes), 2));
+ covariance.setElement(2, 2, 0.0);
+
+ SymmetricMatrix covariance_global = electrodes.getLocalToGlobal().transformed(covariance);
+
+// System.out.println("Global covariance matrix: \n"+covariance_global);
+
+ return covariance_global;
+
+ }
+
+ private double getMeasuredResolution(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes) // should replace this by a ResolutionModel class that gives expected resolution. This could be a big job.
+ {
+ double measured_resolution;
+
+ double sense_pitch = ((SiSensor) electrodes.getDetectorElement()).getSenseElectrodes(electrodes.getChargeCarrier()).getPitch(0);
+
+// double readout_pitch = electrodes.getPitch(0);
+// double noise = _readout_chip.getChannel(strip_number).computeNoise(electrodes.getCapacitance(strip_number));
+// double signal_expected = (0.000280/DopedSilicon.ENERGY_EHPAIR) *
+// ((SiSensor)electrodes.getDetectorElement()).getThickness(); // ~280 KeV/mm for thick Si sensors
+ double _oneClusterErr = 1 / Math.sqrt(12);
+ double _twoClusterErr = 1 / 5;
+ double _threeClusterErr = 1 / 3;
+ double _fourClusterErr = 1 / 2;
+ double _fiveClusterErr = 1;
+
+ if (cluster.size() == 1) {
+ measured_resolution = sense_pitch * _oneClusterErr;
+ } else if (cluster.size() == 2) {
+ measured_resolution = sense_pitch * _twoClusterErr;
+ } else if (cluster.size() == 3) {
+ measured_resolution = sense_pitch * _threeClusterErr;
+ } else if (cluster.size() == 4) {
+ measured_resolution = sense_pitch * _fourClusterErr;
+ } else {
+ measured_resolution = sense_pitch * _fiveClusterErr;
+ }
+
+ return measured_resolution;
+ }
+
+ private double getUnmeasuredResolution(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes) {
+ // Get length of longest strip in hit
+ double hit_length = 0;
+ for (RawTrackerHit hit : cluster) {
+ hit_length = Math.max(hit_length, ((SiStrips) electrodes).getStripLength(1));
+ }
+ return hit_length / Math.sqrt(12);
+ }
+
+ private double getTime(List<RawTrackerHit> cluster) {
+ return 0;
+ }
+
+ private double getEnergy(List<RawTrackerHit> cluster) {
+ double total_charge = 20000;
+//
+// double total_charge = 0.0;
+// for (RawTrackerHit hit : cluster) {
+// double signal = hit.getAmp();
+// total_charge += signal;
+// }
+ return total_charge * DopedSilicon.ENERGY_EHPAIR;
+ }
+
+ /**
+ * Creates a raw tracker hit at a dummy channel
+ *
+ * @param sensor that will get the hit
+ * @return list of a single raw tracker hit
+ */
+ public List<RawTrackerHit> makeRawTrackerFakeHit(SiSensor sensor) {
+
+ //if(debug) System.out.println(this.getClass().getSimpleName() + ": makeRawTrackerFakeHit for sensor " + sensor.getName());
+ List<RawTrackerHit> raw_hits = new ArrayList<RawTrackerHit>();
+
+ // Get SimTrackerHits
+ //IReadout ro = sensor.getReadout();
+
+
+ // Loop over electrodes and digitize with readout chip
+ for (ChargeCarrier carrier : ChargeCarrier.values()) {
+ if (sensor.hasElectrodesOnSide(carrier)) {
+
+ //if(debug) System.out.println(this.getClass().getSimpleName() + ": creating a dummy hit for sensor " + sensor.getName());
+ //SortedMap<Integer,List<Integer>> digitized_hits = _readout_chip.readout(electrode_data.get(carrier),sensor.getReadoutElectrodes(carrier));
+ //if(debug) System.out.println(this.getClass().getSimpleName() + ": creating a dummy hit for sensor " + sensor.getName());
+
+ int channel = 1;
+ int time = 0;
+ long cell_id = sensor.makeStripId(channel, carrier.charge()).getValue();
+ //List<Integer> readout_data = new ArrayList<Integer>();
+ short[] adc_values = new short[6];
+ for (Integer i = 0; i < 6; ++i) {
+ Integer adc = 50;
+ adc_values[i] = adc.shortValue(); //ADC counts
+ }
+ IDetectorElement detector_element = sensor;
+ RawTrackerHit raw_hit = new BaseRawTrackerHit(time, cell_id, adc_values, new ArrayList<SimTrackerHit>(), detector_element);
+ //ro.addHit(raw_hit);
+ raw_hits.add(raw_hit);
+
+
+ }
+
+ }
+
+ return raw_hits;
+ }
+
+ private void makePlots() {
+
+ for (SiSensor sensor : processSensors) {
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": Making plots for " + sensor.getName());
+ }
+ IProfile1D h = aida.profile1D("deltas " + sensor.getName(), 7, 0, 7);
+ this._delta_histos.put(sensor, h);
+ IHistogram1D h1 = aida.histogram1D("Number of iterations " + sensor.getName(), 7, 0, 7);
+ this._delta_itercount.put(sensor, h1);
+ }
+
+ _prf_all_deltas = aida.profile1D("alldeltas", 10, 0, 10);//,50,-20,20);
+ _prf_final_deltas = aida.profile1D("finaldeltas", 10, 0, 10);//,50,-20,20);
+
+ _h_nstriphits_top = aida.histogram1D("NstripClusters top", 11, -0.5, 10.5);
+ _h_nstriphits_bottom = aida.histogram1D("NstripClusters bottom", 11, -0.5, 10.5);
+
+ //_h_trkposodd_top = aida.histogram1D("_h_trkposodd_top", 50, -0.5, 10.5);
+
+ plotter_iter_final = af.createPlotterFactory().create();
+ plotter_iter_final.createRegions(1, 1);
+ plotter_iter_final.region(0).plot(_prf_final_deltas);
+ plotter_iter_final.region(0).style().xAxisStyle().setLabel("Final iteration");
+ plotter_iter_final.region(0).style().yAxisStyle().setLabel("<Distance to xp>");
+
+ plotter_iter_all = af.createPlotterFactory().create();
+ plotter_iter_all.createRegions(1, 1);
+ plotter_iter_all.region(0).plot(_prf_all_deltas);
+ plotter_iter_all.region(0).style().xAxisStyle().setLabel("Iteration");
+ plotter_iter_all.region(0).style().yAxisStyle().setLabel("<Distance to xp>");
+
+
+ plotter_iter = af.createPlotterFactory().create();
+ plotter_iter.createRegions(6, 4);
+ plotter_iter.style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ plotter_iter.style().statisticsBoxStyle().setVisible(false);
+ plotter_itercount = af.createPlotterFactory().create();
+ plotter_itercount.createRegions(6, 4);
+
+ plotter_nstripclusters = af.createPlotterFactory().create();
+ plotter_nstripclusters.createRegions(2, 2);
+ plotter_nstripclusters.region(0).plot(_h_nstriphits_top);
+ plotter_nstripclusters.region(1).plot(_h_nstriphits_bottom);
+
+ plotter_trackposodd = af.createPlotterFactory().create();
+ plotter_trackposodd.createRegions(2, 2);
+ //plotter_trackposodd.region(0).plot(_h_trkposodd_top);
+
+ int i = 0;
+ for (SiSensor sensor : this.processSensors) {
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": " + i + ": adding plot to plotter for " + sensor.getName());
+ }
+ plotter_iter.region(i).plot(this._delta_histos.get(sensor));
+ plotter_iter.style().setParameter("hist2DStyle", "colorMap");
+ plotter_iter.region(i).style().xAxisStyle().setLabel("Iteration");
+ plotter_iter.region(i).style().yAxisStyle().setLabel("<Distance to xp>");
+
+ plotter_itercount.region(i).plot(this._delta_itercount.get(sensor));
+ plotter_itercount.region(i).style().xAxisStyle().setLabel("# iterations");
+ ++i;
[truncated at 1000 lines; 33 more skipped]
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/DataTrackerHitDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/DataTrackerHitDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,231 @@
+package org.hps.recon.tracking;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.hps.conditions.deprecated.SvtUtils;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.lcio.LCIOUtil;
+import org.lcsim.recon.tracking.digitization.sisim.CDFSiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHit;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author mgraham
+ */
+public class DataTrackerHitDriver extends Driver {
+ // Debug switch for development.
+
+ private boolean debug = false;
+ // Collection name.
+// private String readoutCollectionName = "TrackerHits";
+ // Subdetector name.
+ private String subdetectorName = "Tracker";
+ // Name of RawTrackerHit output collection.
+// private String rawTrackerHitOutputCollectionName = "RawTrackerHitMaker_RawTrackerHits";
+ // Name of StripHit1D output collection.
+ private String stripHitOutputCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+ // Clustering parameters.
+ private double clusterSeedThreshold = 4.0;
+ private double clusterNeighborThreshold = 3.0;
+ private double clusterThreshold = 4.0;
+ private int clusterMaxSize = 10;
+ private int clusterCentralStripAveragingThreshold = 4;
+ // Clustering errors by number of TrackerHits.
+ private static final double clusterErrorMultiplier = 1.0;
+ private double oneClusterErr = clusterErrorMultiplier / Math.sqrt(12.);
+ private double twoClusterErr = clusterErrorMultiplier / 5.0;
+ private double threeClusterErr = clusterErrorMultiplier / 3.0;
+ private double fourClusterErr = clusterErrorMultiplier / 2.0;
+ private double fiveClusterErr = clusterErrorMultiplier / 1.0;
+ // Various data lists required by digitization.
+ private List<String> processPaths = new ArrayList<String>();
+ private List<IDetectorElement> processDEs = new ArrayList<IDetectorElement>();
+ private Set<SiSensor> processSensors = new HashSet<SiSensor>();
+ // Digi class objects.
+// private SiDigitizer stripDigitizer;
+// private HPSFittedRawTrackerHitMaker hitMaker;
+ private HPSStripMaker stripClusterer;
+ // private DumbShaperFit shaperFit;
+ int[][] counts = new int[2][10];
+
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
+// public void setReadoutCollectionName(String readoutCollectionName) {
+// this.readoutCollectionName = readoutCollectionName;
+// }
+ public void setSubdetectorName(String subdetectorName) {
+ this.subdetectorName = subdetectorName;
+ }
+
+ public void setStripHitOutputCollectionName(String stripHitOutputCollectionName) {
+ this.stripHitOutputCollectionName = stripHitOutputCollectionName;
+ }
+
+ public void setClusterSeedThreshold(double clusterSeedThreshold) {
+ this.clusterSeedThreshold = clusterSeedThreshold;
+ }
+
+ public void setClusterNeighborThreshold(double clusterNeighborThreshold) {
+ this.clusterNeighborThreshold = clusterNeighborThreshold;
+ }
+
+ public void setClusterThreshold(double clusterThreshold) {
+ this.clusterThreshold = clusterThreshold;
+ }
+
+ public void setClusterMaxSize(int clusterMaxSize) {
+ this.clusterMaxSize = clusterMaxSize;
+ }
+
+ public void setClusterCentralStripAveragingThreshold(int clusterCentralStripAveragingThreshold) {
+ this.clusterCentralStripAveragingThreshold = clusterCentralStripAveragingThreshold;
+ }
+
+ public void setOneClusterErr(double oneClusterErr) {
+ this.oneClusterErr = oneClusterErr;
+ }
+
+ public void setTwoClusterErr(double twoClusterErr) {
+ this.twoClusterErr = twoClusterErr;
+ }
+
+ public void setThreeClusterErr(double threeClusterErr) {
+ this.threeClusterErr = threeClusterErr;
+ }
+
+ public void setFourClusterErr(double fourClusterErr) {
+ this.fourClusterErr = fourClusterErr;
+ }
+
+ public void setFiveClusterErr(double fiveClusterErr) {
+ this.fiveClusterErr = fiveClusterErr;
+ }
+
+ /**
+ * Creates a new instance of TrackerHitDriver.
+ */
+ public DataTrackerHitDriver() {
+ }
+
+ /**
+ * Do initialization once we get a Detector.
+ */
+ @Override
+ public void detectorChanged(Detector detector) {
+
+ // Call sub-Driver's detectorChanged methods.
+ super.detectorChanged(detector);
+
+ // Process detectors specified by path, otherwise process entire
+ // detector
+ IDetectorElement deDetector = detector.getDetectorElement();
+
+ for (String path : processPaths) {
+ processDEs.add(deDetector.findDetectorElement(path));
+ }
+
+ if (processDEs.isEmpty()) {
+ processDEs.add(deDetector);
+ }
+
+ for (IDetectorElement detectorElement : processDEs) {
+ processSensors.addAll(detectorElement.findDescendants(SiSensor.class));
+ //if (debug)
+ // System.out.println("added " + processSensors.size() + " sensors");
+ }
+
+ // Create the sensor simulation.
+ CDFSiSensorSim stripSim = new CDFSiSensorSim();
+
+
+ // Create Strip clustering algorithm.
+ HPSNearestNeighborRMS stripClusteringAlgo = new HPSNearestNeighborRMS();
+ stripClusteringAlgo.setSeedThreshold(clusterSeedThreshold);
+ stripClusteringAlgo.setNeighborThreshold(clusterNeighborThreshold);
+ stripClusteringAlgo.setClusterThreshold(clusterThreshold);
+
+// hitMaker=new HPSFittedRawTrackerHitMaker(shaperFit);
+ // Create the clusterers and set hit-making parameters.
+ stripClusterer = new HPSStripMaker(stripSim, 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 detector to process.
+ processPaths.add(subdetectorName);
+ }
+
+ /**
+ * Perform the digitization.
+ */
+ @Override
+ public void process(EventHeader event) {
+ // Call sub-Driver processing.
+// super.process(event);
+
+ // Make new lists for output.
+// List<HPSFittedRawTrackerHit> rawHits = new ArrayList<HPSFittedRawTrackerHit>();
+ List<SiTrackerHit> stripHits1D = new ArrayList<SiTrackerHit>();
+
+// // Make HPS hits.
+// for (SiSensor sensor : processSensors) {
+// rawHits.addAll(hitMaker.makeHits(sensor));
+// }
+
+ // Make strip hits.
+ for (SiSensor sensor : processSensors) {
+ stripHits1D.addAll(stripClusterer.makeHits(sensor));
+ }
+
+ // Debug prints.
+ if (debug) {
+// List<SimTrackerHit> simHits = event.get(SimTrackerHit.class, this.readoutCollectionName);
+// System.out.println("SimTrackerHit collection " + this.readoutCollectionName + " has " + simHits.size() + " hits.");
+// System.out.println("RawTrackerHit collection " + this.rawTrackerHitOutputCollectionName + " has " + rawHits.size() + " hits.");
+ System.out.println("TrackerHit collection " + this.stripHitOutputCollectionName + " has " + stripHits1D.size() + " hits.");
+ }
+
+ // Put output hits into collection.
+ int flag = LCIOUtil.bitSet(0, 31, true); // Turn on 64-bit cell ID.
+// event.put(this.rawTrackerHitOutputCollectionName, rawHits, RawTrackerHit.class, flag, toString());
+ event.put(this.stripHitOutputCollectionName, stripHits1D, SiTrackerHitStrip1D.class, 0, toString());
+ if (debug) {
+ for (int mod = 0; mod < 2; mod++) {
+ for (int layer = 0; layer < 10; layer++) {
+ counts[mod][layer] += SvtUtils.getInstance().getSensor(mod, layer).getReadout().getHits(SiTrackerHit.class).size();
+ }
+ }
+ }
+ if (debug) {
+ System.out.println("[ DataTrackerHitDriver ] - " + this.stripHitOutputCollectionName + " has " + stripHits1D.size() + " hits.");
+ }
+ }
+
+ @Override
+ public void endOfData() {
+ if (debug) {
+ for (int mod = 0; mod < 2; mod++) {
+ for (int layer = 0; layer < 10; layer++) {
+ System.out.format("mod %d, layer %d, count %d\n", mod, layer, counts[mod][layer]);
+ }
+ }
+ }
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/DumbShaperFit.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/DumbShaperFit.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,62 @@
+package org.hps.recon.tracking;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants.ChannelConstants;
+import org.lcsim.event.RawTrackerHit;
+
+/**
+ *
+ * @author mgraham
+ */
+public class DumbShaperFit implements HPSShaperFitAlgorithm {
+
+ public DumbShaperFit() {
+ }
+
+ @Override
+ public HPSShapeFitParameters fitShape(RawTrackerHit rth, ChannelConstants constants) {
+ short[] adcVals = rth.getADCValues();
+ return this.fitShape(adcVals, constants);
+ }
+
+ public HPSShapeFitParameters fitShape(short[] adcVals, ChannelConstants constants){
+ HPSShapeFitParameters fitresults = new HPSShapeFitParameters();
+ double[] pedSub={-99.0,-99.0,-99.0,-99.0,-99.0,-99.0};
+ double maxADC=-99999;
+ int iMax=-1;
+ double t0=-999;
+ for(int i=0;i<6;i++){
+ pedSub[i]=adcVals[i]-constants.getPedestal();
+ if(pedSub[i]>maxADC){
+ maxADC=pedSub[i];
+ iMax=i;
+ }
+ }
+ if(iMax>0&&iMax<5){
+ t0 = (pedSub[iMax-1]*24.0*(iMax-1)+pedSub[iMax]*24.0*(iMax)+pedSub[iMax+1]*24.0*(iMax+1))/(pedSub[iMax-1]+pedSub[iMax]+pedSub[iMax+1]);
+ }else if(iMax==0){
+ t0 =(pedSub[iMax]*24.0*(iMax)+pedSub[iMax+1]*24.0*(iMax+1))/(pedSub[iMax]+pedSub[iMax+1]) ;
+ }else if(iMax==5){
+ t0 =(pedSub[iMax]*24.0*(iMax)+pedSub[iMax-1]*24.0*(iMax-1))/(pedSub[iMax-1]+pedSub[iMax]) ;
+ }
+
+ //mg...put in a cut here to make sure pulse shape is reasonable
+ //if not, set t0 to -99 (which will fail the later t0>0 cut
+ if(iMax==0||iMax==5)
+ t0=-99;
+ //make sure it goes up below iMax
+ for(int i=0;i<iMax;i++){
+ if(pedSub[i+1]<pedSub[i])
+ t0=-99;
+ }
+ //...and down below iMax
+ for(int i=iMax;i<5;i++){
+ if(pedSub[i+1]>pedSub[i])
+ t0=-99;
+ }
+
+ fitresults.setAmp(maxADC);
+ fitresults.setT0(t0);
+
+ return fitresults;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/EcalTrackMatch.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/EcalTrackMatch.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,142 @@
+package org.hps.recon.tracking;
+
+import hep.physics.vec.Hep3Vector;
+
+import java.util.List;
+
+import org.lcsim.event.Cluster;
+import org.lcsim.event.Track;
+
+/**
+ *
+ * @author phansson
+ */
+public class EcalTrackMatch {
+
+// public static final double crystalSizeX = (13.3 + 16.0) / 2;
+// public static final double crystalSizeY = (13.3 + 16.0) / 2;
+// private double RADIUS = crystalSizeX;
+// private String trackCollectionName = "MatchedTracks";
+ Cluster cluster;
+ Track matchedTrack;
+ private boolean debug = false;
+
+ public EcalTrackMatch() {
+ cluster = null;
+ matchedTrack = null;
+ }
+
+ public EcalTrackMatch(boolean deb) {
+ cluster = null;
+ matchedTrack = null;
+ debug = deb;
+
+ }
+
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
+ public Track getMatchedTrack() {
+ return matchedTrack;
+ }
+
+ public void setCluster(Cluster cl) {
+ this.cluster = cl;
+ }
+
+ public double dX(Track track) {
+ return dist(track, 0);
+ }
+
+ public double dY(Track track) {
+ return dist(track, 1);
+ }
+
+ public double dist(Track track, int dir) {
+ Hep3Vector trk_pos = TrackUtils.getTrackPositionAtEcal(track);
+ double dx;
+ if (dir == 0) {
+ dx = cluster.getPosition()[0] - trk_pos.x();
+ } else {
+ dx = cluster.getPosition()[1] - trk_pos.y();
+ }
+ if (debug) {
+ System.out.println("dist = " + dx + " from cluster to track in " + (dir == 0 ? "X" : "Y") + " to track at " + trk_pos.x() + "," + trk_pos.y() + "," + trk_pos.z());
+ }
+ return dx;
+ }
+
+ public double dR(Track track) {
+ Hep3Vector trk_pos = TrackUtils.getTrackPositionAtEcal(track);
+ double dx = dX(track);
+ double dy = dY(track);
+ double dr = Math.sqrt(dx * dx + dy * dy);
+ if (debug) {
+ System.out.println("dR = " + dr + " to track at " + trk_pos.toString());
+ }
+ return dr;
+ }
+
+ public void match(List<Track> tracks) {
+ matchedTrack = null;
+ if (debug) {
+ System.out.println("Matching cluster at " + cluster.getPosition()[0] + "," + cluster.getPosition()[1] + "," + cluster.getPosition()[2] + " with " + tracks.size() + " tracks.");
+ }
+ //get the position of the cluster anc compare to tracks at the ecal face
+ double dr;
+// SeedTrack trk;
+// Hep3Vector trk_pos;
+ double drmin = 999999.9;
+ for (Track track : tracks) {
+ dr = dR(track);
+ if (dr < drmin) {
+ drmin = dr;
+ matchedTrack = track;
+ }
+ }
+ if (debug) {
+ if (matchedTrack == null) {
+ System.out.println("No matched track was found");
+ } else {
+ System.out.println("Matched a track with dr " + dR(matchedTrack));
+ }
+ }
+ }
+
+ public boolean match(List<Track> tracks, double drmax) {
+ match(tracks);
+ return isMatched(drmax);
+ }
+
+ public boolean isMatched(double rad_max) {
+ if (matchedTrack == null) {
+ return false;
+ }
+ double dr = dR(matchedTrack);
+ return (dr < rad_max ? true : false);
+ }
+
+ public boolean isMatchedY(double max) {
+ if (matchedTrack == null) {
+ return false;
+ }
+ double dy = dY(matchedTrack);
+ return (Math.abs(dy) < max);
+ }
+
+ public double getDistanceToTrack() {
+ return matchedTrack == null ? -1 : dR(matchedTrack);
+
+ }
+
+ public double getDistanceToTrackInX() {
+ return matchedTrack == null ? -1 : dX(matchedTrack);
+
+ }
+
+ public double getDistanceToTrackInY() {
+ return matchedTrack == null ? -1 : dY(matchedTrack);
+
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/EventQuality.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/EventQuality.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,114 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Singleton class to hold default cut values
+ *
+ * @author Per Hansson Adrian <[log in to unmask]>
+ * @version $id: $
+ */
+public class EventQuality {
+
+
+
+ private static EventQuality _instance = null;
+ public static enum Quality{LOOSE,MEDIUM,TIGHT}
+ public static enum Cut{
+ UNDEFINED(0),PZ(1),CHI2(2),SHAREDHIT(3),NHITS(4),TOPBOTHIT(5);
+ private int value;
+ private Cut(int value) {
+ this.value = value;
+ }
+ public int getValue() {
+ return this.value;
+ }
+ }
+ private List<CutObject> _cut_list = new ArrayList<CutObject>();
+
+ public EventQuality() {
+ addCut(new CutObject(Cut.CHI2,"CHI2",100000.,10.,10.));
+ addCut(new CutObject(Cut.PZ,"PZ",0.000005,0.4,0.4));
+ addCut(new CutObject(Cut.SHAREDHIT,"SHAREDHIT",0,0,0));
+ addCut(new CutObject(Cut.NHITS,"NHITS",4,4,5));
+ addCut(new CutObject(Cut.TOPBOTHIT,"TOPBOTHIT",0,0,0));
+ }
+
+ public static EventQuality instance() {
+ if(_instance==null) {
+ _instance = new EventQuality();
+ }
+ return _instance;
+ }
+
+ private void addCut(CutObject c) {
+ _cut_list.add(c);
+ }
+
+ private CutObject find(Cut cut) {
+ for(CutObject co : _cut_list) {
+ if (co._cut==cut) {
+ return co;
+ }
+ }
+ return null;
+ }
+
+ public double getCutValue(Cut cut,Quality quality) {
+ CutObject co = find(cut);
+ if(co==null) {
+ System.out.printf("Cut \"%d\" didn't exist!?\n",cut);
+ System.exit(0);
+ }
+ return co.get(quality);
+ }
+
+ @Override
+ public String toString() {
+ String s = String.format("EventQuality has %d cuts defined:\n",this._cut_list.size());
+ for (CutObject c: _cut_list) {
+ s += String.format("%s\n",c.toString());
+ }
+ return s;
+ }
+
+ public String print(int cuts) {
+ String s = String.format("cuts=%d:\n",cuts);
+ for (CutObject cut : _cut_list) {
+ int tmp = cuts & (1<<cut._cut.getValue());
+ s += String.format("Cut %s %s\n",cut._name,tmp==0?"PASSED":"FAILED");
+ }
+ return s;
+ }
+
+ private class CutObject {
+ String _name = "UNDEFINED";
+ Cut _cut = Cut.UNDEFINED;
+ Map<Quality,Double> _map = new HashMap<Quality,Double>();
+ public CutObject(Cut c, String name, double val1,double val2,double val3) {
+ _cut = c;
+ _name = name;
+ _map.put(Quality.LOOSE, val1);
+ _map.put(Quality.MEDIUM, val2);
+ _map.put(Quality.TIGHT, val3);
+ }
+ public void set(Quality q, double val) {
+ _map.put(q,val);
+ }
+ public double get(Quality q) {
+ return _map.get(q);
+ }
+ @Override
+ public String toString() {
+ return String.format("Name:%s cut:%d val=[%f,%f,%f]",_name,_cut.getValue(),_map.get(Quality.LOOSE),_map.get(Quality.MEDIUM),_map.get(Quality.TIGHT));
+ }
+ }
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/FindableTrack.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/FindableTrack.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,343 @@
+/*
+ * FindableTrack.java
+ *
+ * Created on October 24, 2008, 9:50 PM
+ *
+ */
+package org.hps.recon.tracking;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.lcsim.detector.DetectorElementStore;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IDetectorElementContainer;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.fit.helicaltrack.HelixParamCalculator;
+import org.lcsim.fit.helicaltrack.HitIdentifier;
+import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
+import org.lcsim.recon.tracking.seedtracker.SeedLayer;
+import org.lcsim.recon.tracking.seedtracker.SeedLayer.SeedType;
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+
+/**
+ *
+ * @author Richard Partridge
+ * @version $Id: FindableTrack.java,v 1.4 2012/11/08 01:22:41 omoreno Exp $
+ */
+public class FindableTrack {
+
+ public enum Ignore {
+ NoPTCut, NoDCACut, NoZ0Cut, NoSeedCheck, NoConfirmCheck, NoMinHitCut
+ };
+
+ private double _bfield;
+ private RelationalTable<SimTrackerHit, MCParticle> _hittomc;
+ private HitIdentifier _ID;
+ private int _nlayersTot=10;
+
+ public FindableTrack(EventHeader event, List<SimTrackerHit> simTrackerHits){
+
+ // Get the magnetic field
+ Hep3Vector IP = new BasicHep3Vector(0., 0., 1.);
+ _bfield = event.getDetector().getFieldMap().getField(IP).y();
+
+ // Instantiate the hit identifier class
+ _ID = new HitIdentifier();
+
+ // Create a relational table that maps SimTrackerHits to MCParticles
+ _hittomc = new BaseRelationalTable<SimTrackerHit, MCParticle>(RelationalTable.Mode.MANY_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+
+ List<List<SimTrackerHit>> simTrackerHitCollections = new ArrayList<List<SimTrackerHit>>();
+
+ // If the collection of SimTrackerHits is not specified get the collection from the event.
+ // Otherwise, add the collection to the list of collections to be processed.
+ if(simTrackerHits == null) simTrackerHitCollections.addAll(event.get(SimTrackerHit.class));
+ else simTrackerHitCollections.add(simTrackerHits);
+
+ // Loop over the SimTrackerHits and fill in the relational table
+ for (List<SimTrackerHit> simlist : simTrackerHitCollections){
+ for (SimTrackerHit simhit : simlist)
+ if (simhit.getMCParticle() != null)
+ _hittomc.add(simhit, simhit.getMCParticle());
+ }
+ }
+
+ public FindableTrack(EventHeader event, List<SimTrackerHit> simTrackerHits, int nLayersTot){
+ this(event, simTrackerHits);
+ this._nlayersTot = nLayersTot;
+ }
+
+ public FindableTrack(EventHeader event){
+ this(event, null);
+ }
+
+ public FindableTrack(EventHeader event, int nLayersTot){
+ this(event, null, nLayersTot);
+ }
+
+ public boolean isFindable(MCParticle mcp, List<SeedStrategy> slist, Ignore ignore) {
+ List<Ignore> ignores = new ArrayList<Ignore>();
+ ignores.add(ignore);
+ return isFindable(mcp, slist, ignores);
+ }
+
+ public boolean isFindable(MCParticle mcp, List<SeedStrategy> slist) {
+ return isFindable(mcp, slist, new ArrayList<Ignore>());
+ }
+
+ public boolean isFindable(MCParticle mcp, List<SeedStrategy> slist, List<Ignore> ignores) {
+
+ // We can't find neutral particles'
+ if (mcp.getCharge() == 0)
+ return false;
+
+ // Find the helix parameters in the L3 convention used by org.lcsim
+ HelixParamCalculator helix = new HelixParamCalculator(mcp, _bfield);
+
+ // We haven't yet determined the track is findable
+ boolean findable = false;
+
+ // Loop over strategies and check if the track is findable
+ for (SeedStrategy strat : slist) {
+
+ // Check the MC Particle's pT
+ if (!CheckPT(helix, ignores, strat))
+ continue;
+
+ // Check the MC Particle's DCA
+ if (!CheckDCA(helix, ignores, strat))
+ continue;
+
+ // Check the MC Particle's Z0
+ if (!CheckZ0(helix, ignores, strat))
+ continue;
+
+ // Check that we have hits on the seed layers
+ if (!CheckSeed(mcp, ignores, strat))
+ continue;
+
+ // Check that we have the required confirmation hits
+ if (!CheckConfirm(mcp, ignores, strat))
+ continue;
+
+ // Check for the minimum number of hits
+ if (!CheckMinHits(mcp, ignores, strat))
+ continue;
+
+ // Passed all the checks - track is findable
+ findable = true;
+ break;
+ }
+
+ return findable;
+ }
+
+ public int LayersHit(MCParticle mcp) {
+
+ // Get the list of hits associated with the MCParticle
+ Set<SimTrackerHit> hitlist = _hittomc.allTo(mcp);
+
+ // Create a set of the identifiers for the hit layers
+ Set<String> idset = new HashSet<String>();
+
+ // Create the set of identifiers
+ for (SimTrackerHit simhit : hitlist) {
+
+ String identifier_old = _ID.Identifier(getDetectorElement(simhit));
+ String identifier = _ID.Identifier(simhit);
+ if (!idset.contains(identifier))
+ idset.add(identifier);
+ }
+
+ return idset.size();
+ }
+
+ public boolean isTrackFindable(MCParticle mcParticle, int nLayers){
+
+ if(nLayers%2 == 1) throw new RuntimeException(this.getClass().getSimpleName() + ": The required number of layers hit must be even");
+
+ // A neutral particle can't be found
+ if(mcParticle.getCharge() == 0) return false;
+
+ // Get the list of SimTrackerHits associated with the MC particle
+ Set<SimTrackerHit> simHits = _hittomc.allTo(mcParticle);
+
+ // Find the layers hit
+ boolean[] layerHit = new boolean[_nlayersTot];
+ for(SimTrackerHit simHit : simHits){
+ layerHit[simHit.getLayer()-1] = true;
+ }
+
+ int nLayersHit = 0;
+ // Check how many pairs of layers were hit
+ for(int index = 0; index < _nlayersTot; index += 2){
+ if(layerHit[index] && layerHit[index+1]) nLayersHit += 2;
+ }
+
+ return nLayersHit >= nLayers;
+ }
+
+ public Set<SimTrackerHit> getSimTrackerHits(MCParticle mcParticle){
+ return _hittomc.allTo(mcParticle);
+ }
+
+ public boolean InnerTrackerIsFindable(MCParticle mcp, int nlayers, boolean printout) {
+ Set<SimTrackerHit> hitlist = _hittomc.allTo(mcp);
+ boolean[] layerHit={false,false,false,false,false,false,false,false,false,false,false,false};
+ for (SimTrackerHit simhit : hitlist) {
+ layerHit[simhit.getLayer()-1]=true;
+ }
+ for(int i=0;i<nlayers;i++){
+ System.out.println(layerHit[i]);
+ if(layerHit[i]==false)return false;
+ }
+ return true;
+ }
+
+ public boolean InnerTrackerIsFindable(MCParticle mcp, int nlayers) {
+ Set<SimTrackerHit> hitlist = _hittomc.allTo(mcp);
+ boolean[] layerHit={false,false,false,false,false,false,false,false,false,false,false,false};
+ for (SimTrackerHit simhit : hitlist) {
+ layerHit[simhit.getLayer()-1]=true;
+ }
+ for(int i=0;i<nlayers;i++){
+ if(layerHit[i]==false)return false;
+ }
+ return true;
+ }
+
+ public boolean OuterTrackerIsFindable(MCParticle mcp, int start) {
+ Set<SimTrackerHit> hitlist = _hittomc.allTo(mcp);
+ boolean[] layerHit={false,false,false,false,false,false,false,false,false,false,false,false};
+ for (SimTrackerHit simhit : hitlist) {
+ layerHit[simhit.getLayer()-1]=true;
+ }
+ for(int i=start;i<_nlayersTot;i++){
+ if(layerHit[i]==false)return false;
+ }
+ return true;
+ }
+
+ private boolean CheckPT(HelixParamCalculator helix, List<Ignore> ignores, SeedStrategy strat) {
+
+ // First see if we are skipping this check
+ if (ignores.contains(Ignore.NoPTCut))
+ return true;
+
+ return helix.getMCTransverseMomentum() >= strat.getMinPT();
+ }
+
+ private boolean CheckDCA(HelixParamCalculator helix, List<Ignore> ignores, SeedStrategy strat) {
+
+ // First see if we are skipping this check
+ if (ignores.contains(Ignore.NoDCACut))
+ return true;
+
+ return Math.abs(helix.getDCA()) <= strat.getMaxDCA();
+ }
+
+ private boolean CheckZ0(HelixParamCalculator helix, List<Ignore> ignores, SeedStrategy strat) {
+
+ // First see if we are skipping this check
+ if (ignores.contains(Ignore.NoZ0Cut))
+ return true;
+
+ return Math.abs(helix.getZ0()) <= strat.getMaxZ0();
+ }
+
+ private boolean CheckSeed(MCParticle mcp, List<Ignore> ignores, SeedStrategy strat) {
+
+ // First see if we are skipping this check
+ if (ignores.contains(Ignore.NoSeedCheck))
+ return true;
+
+ return HitCount(mcp, strat.getLayers(SeedType.Seed)) == 3;
+ }
+
+ private boolean CheckConfirm(MCParticle mcp, List<Ignore> ignores, SeedStrategy strat) {
+
+ // First see if we are skipping this check
+ if (ignores.contains(Ignore.NoConfirmCheck))
+ return true;
+
+ return HitCount(mcp, strat.getLayers(SeedType.Confirm)) >= strat.getMinConfirm();
+ }
+
+ private boolean CheckMinHits(MCParticle mcp, List<Ignore> ignores, SeedStrategy strat) {
+
+ // First see if we are skipping this check
+ if (ignores.contains(Ignore.NoMinHitCut))
+ return true;
+
+ return HitCount(mcp, strat.getLayerList()) >= strat.getMinHits();
+ }
+
+ private int HitCount(MCParticle mcp, List<SeedLayer> lyrlist) {
+
+ // Get the list of hits associated with the MCParticle
+ Set<SimTrackerHit> hitlist = _hittomc.allTo(mcp);
+
+ // Count the number of layers with hits in them
+ int hitcount = 0;
+ for (SeedLayer lyr : lyrlist)
+ // Loop over the hits for this MCParticle
+ for (SimTrackerHit simhit : hitlist) {
+
+ // Get the detector element for this hit
+// IDetectorElement de = getDetectorElement(simhit);
+
+ // Check names
+// String detname_old = _ID.getName(de);
+ String detname_new = simhit.getSubdetector().getName();
+ // if (!detname_old.equals(detname_new)) {
+ // System.out.println("Detector name mismatch - old: "+detname_old+ " new: "+detname_new);
+ // }
+ // int layer_old = _ID.getLayer(de);
+ int layer_new = simhit.getLayer();
+ // if (layer_old != layer_new) {
+ // System.out.println("Layer number mismatch - old: "+layer_old+" new: "+layer_new);
+ // }
+// BarrelEndcapFlag be_old = _ID.getBarrelEndcapFlag(de);
+ BarrelEndcapFlag be_new = simhit.getBarrelEndcapFlag();
+ // if (!be_old.equals(be_new)) {
+ // System.out.println("BarrelEndcapFlag mismatch - old: "+be_old+" new: "+be_new);
+ // }
+
+ // See if this hit is on the layer we are checking
+// if (!lyr.getDetName().equals(_ID.getName(de))) continue;
+// if (lyr.getLayer() != _ID.getLayer(de)) continue;
+// if (!lyr.getBarrelEndcapFlag().equals(_ID.getBarrelEndcapFlag(de)))
+// continue;
+ if (!lyr.getDetName().equals(detname_new))
+ continue;
+ if (lyr.getLayer() != layer_new)
+ continue;
+ if (!lyr.getBarrelEndcapFlag().equals(be_new))
+ continue;
+ hitcount++;
+ break;
+ }
+
+ return hitcount;
+ }
+
+ private IDetectorElement getDetectorElement(SimTrackerHit hit) {
+ IDetectorElementContainer cont = DetectorElementStore.getInstance().find(hit.getIdentifier());
+ IDetectorElement de;
+ if (cont.isEmpty())
+ throw new RuntimeException("Detector Container is empty!");
+ else
+ de = cont.get(0);
+ return de;
+ }
+}
\ No newline at end of file
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/FpgaData.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/FpgaData.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,197 @@
+package org.hps.recon.tracking;
+
+//--- java ---//
+import static org.hps.conditions.deprecated.HPSSVTConstants.ADC_TEMP_COUNT;
+import static org.hps.conditions.deprecated.HPSSVTConstants.BETA;
+import static org.hps.conditions.deprecated.HPSSVTConstants.CONST_A;
+import static org.hps.conditions.deprecated.HPSSVTConstants.MAX_TEMP;
+import static org.hps.conditions.deprecated.HPSSVTConstants.MIN_TEMP;
+import static org.hps.conditions.deprecated.HPSSVTConstants.R_DIV;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TEMP_INC;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TEMP_K0;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TEMP_MASK;
+import static org.hps.conditions.deprecated.HPSSVTConstants.V_MAX;
+import static org.hps.conditions.deprecated.HPSSVTConstants.V_REF;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+//--- org.lcsim ---//
+import org.lcsim.event.GenericObject;
+//-- Constants ---//
+
+/**
+ * Generic object to contain hybrid temperatures and data tail value. Converts
+ * and ADC value to a temperature in celsius
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: FpgaData.java,v 1.3 2012/08/16 01:06:30 meeg Exp $
+ */
+public class FpgaData implements GenericObject {
+
+ int fpgaID;
+ List<Double> temperatures = new ArrayList<Double>();
+ int tail;
+ private static double[] temperatureTable = null;
+
+ /**
+ *
+ * @param temperature : array containing hybrid temperatures
+ * @param tail : word present at the end of a FPGA data set
+ */
+ public FpgaData(int fpgaID, int[] data, int tail) {
+ this.fpgaID = fpgaID;
+
+ int[] temperature = extractTemperature(data);
+
+ // Fill the temperature lookup table
+ fillTemperatureTable();
+
+ this.tail = tail;
+
+ // Fill the temperature list
+ for (int index = 0; index < temperature.length; index++) {
+ temperatures.add(intToTemperature(temperature[index]));
+ }
+ }
+
+ public FpgaData(int fpgaID, double[] temperatures, int tail) {
+ this.fpgaID = fpgaID;
+
+ this.tail = tail;
+
+ this.temperatures.clear();
+ // Fill the temperature list
+ for (int index = 0; index < temperatures.length; index++) {
+ this.temperatures.add(temperatures[index]);
+ }
+ }
+
+ /**
+ * Extract temperatures from the SVT data stream
+ *
+ * @param data : array containing temperature data
+ * @return temperatures
+ *
+ */
+ public static int[] extractTemperature(int[] data) {
+ int[] temperatures = new int[(data.length) * 2];
+
+ int tempIndex = 0;
+ for (int index = 0; index < data.length; index++) {
+ temperatures[tempIndex] = data[index] & TEMP_MASK;
+ temperatures[tempIndex + 1] = (data[index] >>> 16) & TEMP_MASK;
+ tempIndex += 2;
+ }
+ return temperatures;
+ }
+
+ /**
+ * Temperature lookup table. Takes an ADC value and returns a temperature in
+ * Celsius
+ */
+ private static void fillTemperatureTable() {
+
+ if (temperatureTable == null) {
+ temperatureTable = new double[ADC_TEMP_COUNT];
+
+ double tempK, res, volt;
+ int idx;
+ double temp = MIN_TEMP;
+
+ while (temp < MAX_TEMP) {
+
+ tempK = TEMP_K0 + temp;
+ res = CONST_A * Math.exp(BETA / tempK);
+ volt = (res * V_MAX) / (R_DIV + res);
+ idx = (int) ((volt / V_REF) * (double) (ADC_TEMP_COUNT - 1));
+ if (idx < ADC_TEMP_COUNT) {
+ temperatureTable[idx] = temp;
+ }
+ temp += TEMP_INC;
+ }
+ }
+ }
+
+ public static double intToTemperature(int tempIndex) {
+ fillTemperatureTable();
+ return temperatureTable[tempIndex];
+ }
+
+ public static int temperatureToInt(double temperature) {
+ fillTemperatureTable();
+ return Math.abs(Arrays.binarySearch(temperatureTable, temperature));
+ }
+
+ public int[] extractData() {
+ fillTemperatureTable();
+
+ int[] header = new int[(temperatures.size() + 1) / 2];
+ for (int i = 0; i < temperatures.size(); i++) {
+ if (i % 2 == 0) {
+ header[i / 2] = (header[i / 2] &= ~TEMP_MASK) | (temperatureToInt(temperatures.get(i)) & TEMP_MASK);
+ } else {
+ header[i / 2] = (header[i / 2] &= ~(TEMP_MASK << 16)) | ((temperatureToInt(temperatures.get(i)) & TEMP_MASK) << 16);
+ }
+ }
+ return header;
+ }
+
+ public int getFpga() {
+ return fpgaID;
+ }
+
+ public int getTail() {
+ return tail;
+ }
+
+ /**
+ * Get the temperature at a given index
+ */
+ @Override
+ public double getDoubleVal(int index) {
+ return temperatures.get(index);
+ }
+
+ @Override
+ public float getFloatVal(int index) {
+ return 0;
+ }
+
+ /**
+ * Get the tail value
+ */
+ @Override
+ public int getIntVal(int index) {
+ switch (index) {
+ case 0:
+ return getFpga();
+ case 1:
+ return getTail();
+ default:
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ }
+
+ @Override
+ public int getNDouble() {
+ return temperatures.size();
+ }
+
+ @Override
+ public int getNFloat() {
+ return 0;
+ }
+
+ @Override
+ public int getNInt() {
+ return 2;
+ }
+
+ @Override
+ public boolean isFixedSize() {
+ return false;
+ }
+;
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSClusteringAlgorithm.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSClusteringAlgorithm.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,25 @@
+package org.hps.recon.tracking;
+
+import java.util.List;
+
+/**
+ *
+ * @author mgraham
+ */
+
+
+public interface HPSClusteringAlgorithm {
+
+ /**
+ * Finds the clusters given a list of RawTrackerHits on a particular
+ * silicon sensor with electrodes given by SiSensorElectrodes. A list
+ * of clusters is returned, with each cluster being a list of RawTrackerHits
+ * the form the cluster.
+ *
+ * @param hits base hits
+ * @return list of clusters, with each cluster being a list of RawTrackerHits
+ */
+ public List<List<HPSFittedRawTrackerHit>> findClusters(
+ List<HPSFittedRawTrackerHit> hits);
+
+}
\ No newline at end of file
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSFittedRawTrackerHit.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSFittedRawTrackerHit.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,37 @@
+package org.hps.recon.tracking;
+
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.base.BaseLCRelation;
+
+/**
+ *
+ * @author meeg
+ * @version $Id: HPSFittedRawTrackerHit.java,v 1.3 2013/04/16 22:05:43 phansson Exp $
+ */
+public class HPSFittedRawTrackerHit extends BaseLCRelation {
+
+ public HPSFittedRawTrackerHit(RawTrackerHit hit, HPSShapeFitParameters fit) {
+ super(hit, fit);
+ }
+
+ public RawTrackerHit getRawTrackerHit() {
+ return (RawTrackerHit) getFrom();
+ }
+
+ public HPSShapeFitParameters getShapeFitParameters() {
+ return (HPSShapeFitParameters) getTo();
+ }
+
+ public double getT0() {
+ return getShapeFitParameters().getT0();
+ }
+
+ public double getAmp() {
+ return getShapeFitParameters().getAmp();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("HPSFittedRawTrackerHit: hit cell id %d on sensor %s with fit %s\n",this.getRawTrackerHit().getCellID(),getRawTrackerHit().getDetectorElement().getName(),this.getShapeFitParameters().toString());
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSNearestNeighborRMS.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSNearestNeighborRMS.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,258 @@
+package org.hps.recon.tracking;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants;
+import org.hps.conditions.deprecated.HPSSVTConstants;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
+import org.lcsim.event.RawTrackerHit;
+
+/**
+ *
+ * @author mgraham
+ */
+public class HPSNearestNeighborRMS implements HPSClusteringAlgorithm {
+
+ private static String _NAME = "NearestNeighborRMS";
+ private double _seed_threshold;
+ private double _neighbor_threshold;
+ private double _cluster_threshold;
+ private double _meanTime = 24;
+ private double _timeWindow = 48;
+ private double _maxChisq = 20.0;
+
+ /**
+ * Instantiate NearestNeighborRMS with specified thresholds.
+ * Seed threshold is the minimum charge to initiate a cluster. Neighbor
+ * threshold is the minimum charge to add a neighboring cell to a cluster.
+ * Cluster threshold is minimum charge of the entire cluster.
+ * All thresholds are in units of RMS noise of the channel(s).
+ *
+ * @param seed_threshold seed threshold
+ * @param neighbor_threshold neighbor threshold
+ * @param cluster_threshold cluster threshold
+ */
+ public HPSNearestNeighborRMS(double seed_threshold, double neighbor_threshold, double cluster_threshold) {
+ _seed_threshold = seed_threshold;
+ _neighbor_threshold = neighbor_threshold;
+ _cluster_threshold = cluster_threshold;
+ }
+
+ /**
+ * Instantiate NearestNeighborRMS with default thresholds:
+ *
+ * seed_threshold = 4*RMS noise
+ * neighbor_threshold = 3*RMS noise
+ * cluster_threshold = 4*RMS noise
+ */
+ public HPSNearestNeighborRMS() {
+ this(4.0, 3.0, 4.0);
+ }
+
+ /**
+ * Set the seed threshold. Units are RMS noise.
+ *
+ * @param seed_threshold seed threshold
+ */
+ public void setSeedThreshold(double seed_threshold) {
+ _seed_threshold = seed_threshold;
+ }
+
+ /**
+ * Set the neighbor threshold. Units are RMS noise.
+ *
+ * @param neighbor_threshold neighbor threshold
+ */
+ public void setNeighborThreshold(double neighbor_threshold) {
+ _neighbor_threshold = neighbor_threshold;
+ }
+
+ /**
+ * Set the cluster threshold. Units are RMS noise.
+ *
+ * @param cluster_threshold cluster threshold
+ */
+ public void setClusterThreshold(double cluster_threshold) {
+ _cluster_threshold = cluster_threshold;
+ }
+
+ /**
+ * Find clusters using the nearest neighbor algorithm.
+ *
+ * @param base_hits List of RawTrackerHits to be clustered
+ * @return list of clusters, with a cluster being a list of RawTrackerHits
+ */
+ @Override
+ public List<List<HPSFittedRawTrackerHit>> findClusters(List<HPSFittedRawTrackerHit> base_hits) {
+
+ // Check that the seed threshold is at least as large as the neighbor threshold
+ if (_seed_threshold < _neighbor_threshold) {
+ throw new RuntimeException("Tracker hit clustering error: seed threshold below neighbor threshold");
+ }
+
+ // Create maps that show the channel status and relate the channel number to the raw hit and vice versa
+ int mapsize = 2 * base_hits.size();
+ Map<Integer, Boolean> clusterable = new HashMap<Integer, Boolean>(mapsize);
+ Map<HPSFittedRawTrackerHit, Integer> hit_to_channel = new HashMap<HPSFittedRawTrackerHit, Integer>(mapsize);
+ Map<Integer, HPSFittedRawTrackerHit> channel_to_hit = new HashMap<Integer, HPSFittedRawTrackerHit>(mapsize);
+
+ // Create list of channel numbers to be used as cluster seeds
+ List<Integer> cluster_seeds = new ArrayList<Integer>();
+
+ // Loop over the raw hits and construct the maps used to relate cells and hits, initialize the
+ // clustering status map, and create a list of possible cluster seeds
+ for (HPSFittedRawTrackerHit base_hit : base_hits) {
+
+ RawTrackerHit rth = base_hit.getRawTrackerHit();
+ // get the channel number for this hit
+ SiTrackerIdentifierHelper sid_helper = (SiTrackerIdentifierHelper) rth.getIdentifierHelper();
+ IIdentifier id = rth.getIdentifier();
+ int channel_number = sid_helper.getElectrodeValue(id);
+
+ // Check for duplicate RawTrackerHit
+ if (hit_to_channel.containsKey(base_hit)) {
+ throw new RuntimeException("Duplicate hit: " + id.toString());
+ }
+
+ // Check for duplicate RawTrackerHits or channel numbers
+ if (channel_to_hit.containsKey(channel_number)) {
+// throw new RuntimeException("Duplicate channel number: "+channel_number);
+ System.out.println("Duplicate channel number: " + channel_number);
+ }
+
+ // Add this hit to the maps that relate channels and hits
+ hit_to_channel.put(base_hit, channel_number);
+ channel_to_hit.put(channel_number, base_hit);
+
+ // Get the signal from the readout chip
+ double signal = base_hit.getAmp();
+ double noiseRMS = HPSSVTCalibrationConstants.getNoise((SiSensor) rth.getDetectorElement(), channel_number);
+ double time = base_hit.getT0();
+ // Mark this hit as available for clustering if it is above the neighbor threshold
+ clusterable.put(channel_number, signal / noiseRMS >= _neighbor_threshold);
+
+ // Add this hit to the list of seeds if it is above the seed threshold
+ if (signal / noiseRMS >= _seed_threshold && passTimingCut(base_hit) && passChisqCut(base_hit)) {
+ cluster_seeds.add(channel_number);
+ }
+ }
+
+ // Create a list of clusters
+ List<List<HPSFittedRawTrackerHit>> cluster_list = new ArrayList<List<HPSFittedRawTrackerHit>>();
+
+ // Now loop over the cluster seeds to form clusters
+ for (int seed_channel : cluster_seeds) {
+
+ // First check if this hit is still available for clustering
+ if (!clusterable.get(seed_channel)) {
+ continue;
+ }
+
+ // Create a new cluster
+ List<HPSFittedRawTrackerHit> cluster = new ArrayList<HPSFittedRawTrackerHit>();
+ double cluster_signal = 0.;
+ double cluster_noise_squared = 0.;
+
+ // Create a queue to hold channels whose neighbors need to be checked for inclusion
+ LinkedList<Integer> unchecked = new LinkedList<Integer>();
+
+ // Add the seed channel to the unchecked list and mark it as unavailable for clustering
+ unchecked.addLast(seed_channel);
+ clusterable.put(seed_channel, false);
+
+ // Check the neighbors of channels added to the cluster
+ while (unchecked.size() > 0) {
+
+ // Pull the next channel off the queue and add it's hit to the cluster
+ int clustered_cell = unchecked.removeFirst();
+ cluster.add(channel_to_hit.get(clustered_cell));
+ cluster_signal += channel_to_hit.get(clustered_cell).getAmp();
+ cluster_noise_squared += Math.pow(HPSSVTCalibrationConstants.getNoise((SiSensor) (channel_to_hit.get(clustered_cell)).getRawTrackerHit().getDetectorElement(), clustered_cell), 2);
+// cluster_noise_squared +=0; //need to get the noise from the calib. const. class
+ // Get the neigbor channels
+// Set<Integer> neighbor_channels = electrodes.getNearestNeighborCells(clustered_cell);
+ Set<Integer> neighbor_channels = getNearestNeighborCells(clustered_cell);
+
+ // Now loop over the neighbors and see if we can add them to the cluster
+ for (int channel : neighbor_channels) {
+
+ // Get the status of this channel
+ Boolean addhit = clusterable.get(channel);
+
+ // If the map entry is null, there is no raw hit for this channel
+ if (addhit == null) {
+ continue;
+ }
+
+ // Check if this neighbor channel is still available for clustering
+ if (!addhit) {
+ continue;
+ }
+
+ // Add channel to the list of unchecked clustered channels
+ // and mark it unavailable for clustering
+ unchecked.addLast(channel);
+ clusterable.put(channel, false);
+
+ } // end of loop over neighbor cells
+ } // end of loop over unchecked cells
+
+ // Finished with this cluster, check cluster threshold and add it to the list of clusters
+ if (cluster.size() > 0
+ && cluster_signal / Math.sqrt(cluster_noise_squared) > _cluster_threshold) {
+ cluster_list.add(cluster);
+ }
+
+ } // End of loop over seeds
+
+ // Finished finding clusters
+ return cluster_list;
+ }
+
+ private boolean passTimingCut(HPSFittedRawTrackerHit hit) {
+
+ boolean pass = false;
+ double time = hit.getT0();
+ if (Math.abs(time - _meanTime) < _timeWindow) {
+ pass = true;
+ }
+
+ return pass;
+ }
+
+ private boolean passChisqCut(HPSFittedRawTrackerHit hit) {
+ return hit.getShapeFitParameters().getChiSq() < _maxChisq;
+ }
+
+ 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 < HPSSVTConstants.TOTAL_STRIPS_PER_SENSOR);
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSRawTrackerHitFitterDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSRawTrackerHitFitterDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,116 @@
+package org.hps.recon.tracking;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants;
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants.ChannelConstants;
+import org.hps.conditions.deprecated.HPSSVTConstants;
+import org.hps.readout.ecal.ReadoutTimestamp;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.lcio.LCIOConstants;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author mgraham
+ */
+public class HPSRawTrackerHitFitterDriver extends Driver {
+
+ private boolean debug = false;
+ private HPSShaperFitAlgorithm _shaper = new DumbShaperFit();
+ private String rawHitCollectionName = "SVTRawTrackerHits";
+ private String fitCollectionName = "SVTShapeFitParameters";
+ private String fittedHitCollectionName = "SVTFittedRawTrackerHits";
+ private int genericObjectFlags = 1 << LCIOConstants.GOBIT_FIXED;
+ private int relationFlags = 0;
+ private boolean correctT0Shift = false;
+ private boolean useTimestamps = false;
+
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
+ public void setCorrectT0Shift(boolean correctT0Shift) {
+ this.correctT0Shift = correctT0Shift;
+ }
+
+ public void setUseTimestamps(boolean useTimestamps) {
+ this.useTimestamps = useTimestamps;
+ }
+
+ public void setFitAlgorithm(String fitAlgorithm) {
+ if (fitAlgorithm.equals("Analytic")) {
+ _shaper = new HPSShaperAnalyticFitAlgorithm();
+ } else {
+ throw new RuntimeException("Unrecognized fitAlgorithm: " + fitAlgorithm);
+ }
+ }
+
+ public void setFitCollectionName(String fitCollectionName) {
+ this.fitCollectionName = fitCollectionName;
+ }
+
+ public void setFittedHitCollectionName(String fittedHitCollectionName) {
+ this.fittedHitCollectionName = fittedHitCollectionName;
+ }
+
+ public void setRawHitCollectionName(String rawHitCollectionName) {
+ this.rawHitCollectionName = rawHitCollectionName;
+ }
+
+ @Override
+ public void startOfData() {
+ if (rawHitCollectionName == null) {
+ throw new RuntimeException("The parameter ecalCollectionName was not set!");
+ }
+ }
+
+ @Override
+ public void process(EventHeader event) {
+ if (!event.hasCollection(RawTrackerHit.class, rawHitCollectionName)) {
+ //System.out.println(rawHitCollectionName + " does not exist; skipping event");
+ return;
+ }
+
+ List<RawTrackerHit> rawHits = event.get(RawTrackerHit.class, rawHitCollectionName);
+ if (rawHits == null) {
+ throw new RuntimeException("Event is missing SVT hits collection!");
+ }
+ List<HPSFittedRawTrackerHit> hits = new ArrayList<HPSFittedRawTrackerHit>();
+ List<HPSShapeFitParameters> fits = new ArrayList<HPSShapeFitParameters>();
+
+ // Make a fitted hit from this cluster
+ for (RawTrackerHit hit : rawHits) {
+ int strip = hit.getIdentifierFieldValue("strip");
+ ChannelConstants constants = HPSSVTCalibrationConstants.getChannelConstants((SiSensor) hit.getDetectorElement(), strip);
+ HPSShapeFitParameters fit = _shaper.fitShape(hit, constants);
+ if (correctT0Shift) {
+ double corMod = 0;
+ if (useTimestamps) {
+ double t0Svt = ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_TRACKER, event);
+ double t0Trig = ReadoutTimestamp.getTimestamp(ReadoutTimestamp.SYSTEM_TRIGGER, event);
+ corMod += (t0Svt - t0Trig);
+ }
+ corMod -= constants.getT0Shift();
+ fit.setT0(fit.getT0() + corMod);
+// fit.setT0(fit.getT0() - constants.getT0Shift());
+
+ }
+ if (debug) {
+ System.out.println(fit);
+ }
+ fits.add(fit);
+ HPSFittedRawTrackerHit hth = new HPSFittedRawTrackerHit(hit, fit);
+ hits.add(hth);
+ if (strip == HPSSVTConstants.TOTAL_STRIPS_PER_SENSOR) { //drop unbonded channel
+ continue;
+ }
+ hit.getDetectorElement().getReadout().addHit(hth);
+ }
+ event.put(fitCollectionName, fits, HPSShapeFitParameters.class, genericObjectFlags);
+ event.put(fittedHitCollectionName, hits, HPSFittedRawTrackerHit.class, relationFlags);
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSSVTData.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSSVTData.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,307 @@
+package org.hps.recon.tracking;
+
+//--- Constants ---//
+
+import static org.hps.conditions.deprecated.HPSSVTConstants.APV_MASK;
+import static org.hps.conditions.deprecated.HPSSVTConstants.CHANNEL_MASK;
+import static org.hps.conditions.deprecated.HPSSVTConstants.FPGA_MASK;
+import static org.hps.conditions.deprecated.HPSSVTConstants.HYBRID_MASK;
+import static org.hps.conditions.deprecated.HPSSVTConstants.SAMPLE_MASK;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TEMP_MASK;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_APV25_CHANNELS;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_APV25_PER_HYBRID;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_NUMBER_OF_SAMPLES;
+
+/**
+ *
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: HPSSVTData.java,v 1.8 2012/08/16 01:06:30 meeg Exp $
+ */
+public class HPSSVTData {
+
+ // 4x32
+ int[] data = new int[4];
+ // Time of the hit
+ int hitTime = 0;
+
+ /**
+ *
+ * Creates an SVT data packet from
+ *
+ * @param hybridNumber Hybrid number (0-3)
+ * @param apvNumber APV25 chip number (0-4)
+ * @param channelNumber Sensor strip number (0-127)
+ * @param fpgaAddress FPGA address
+ * @param adc ADC samples obtained by sampling the shaper output. Currently,
+ * six samples are obtained per raw hit.
+ */
+ public HPSSVTData(int hybridNumber, int apvNumber,
+ int channelNumber, int fpgaAddress, short[] adc) {
+ this.createSVTDataPacket(hybridNumber, apvNumber,
+ channelNumber, fpgaAddress, adc);
+ }
+
+ /**
+ * Creates and SVT data packet from existing SVT data
+ *
+ * @param data The packed data as int array of size 4
+ */
+ public HPSSVTData(int[] data) {
+ if (data.length != 4) {
+ throw new RuntimeException("Data sample size is not valid!");
+ }
+
+ this.data = data;
+ }
+
+ /**
+ * Get the packed data for this sample
+ *
+ * @return sample The packed data as an int array of size 4.
+ */
+ public int[] getData() {
+ return data;
+ }
+
+ /**
+ * Creates and SVT data packet
+ */
+ private void createSVTDataPacket(int hybridNumber, int apvNumber,
+ int channelNumber, int fpgaAddress, short[] adc) {
+ createSVTDataPacket(hybridNumber, apvNumber, channelNumber, fpgaAddress, adc, data);
+ }
+
+ public static void createSVTDataPacket(int hybridNumber, int apvNumber,
+ int channelNumber, int fpgaAddress, short[] adc, int[] data) {
+ /*
+ * Sample Data consists of the following: Z[xx:xx] = Zeros, O[xx:xx] =
+ * Ones data[0] = O[0], Z[0], Hybrid[1:0], Z[0], ApvChip[2:0], Z[0],
+ * Channel[6:0], FpgaAddress[15:0] data[1] = Z[1:0], Sample1[13:0]],
+ * Z[1:0], Sample0[13:0] data[2] = Z[1:0], Sample3[13:0]], Z[1:0],
+ * Sample2[13:0] data[3] = Z[1:0], Sample5[13:0]], Z[1:0], Sample4[13:0]
+ *
+ */
+
+ //--- data[0] ---//
+ //-----------------//
+
+ // The most significant digit of data[0] is set to 1
+ data[0] |= 0x80000000;
+
+ // Insert the hybrid number
+ data[0] = (data[0] &= ~(HYBRID_MASK << 28)) | ((hybridNumber & HYBRID_MASK) << 28);
+
+ // Insert the APV number
+ data[0] = (data[0] &= ~(APV_MASK << 24)) | ((apvNumber & APV_MASK) << 24);
+
+ // Insert the channel number
+ data[0] = (data[0] &= ~(CHANNEL_MASK << 16)) | ((channelNumber & CHANNEL_MASK) << 16);
+
+ // Insert the FPGA address
+ data[0] = (data[0] &= ~FPGA_MASK) | (fpgaAddress & FPGA_MASK);
+
+
+ //--- data[1] ----//
+ //------------------//
+
+ // Add data 0
+ data[1] = (data[1] &= ~SAMPLE_MASK) | (adc[0] & SAMPLE_MASK);
+
+ // Add data 1
+ data[1] = (data[1] &= ~(SAMPLE_MASK << 16)) | ((adc[1] & SAMPLE_MASK) << 16);
+
+
+
+ //--- data[2] ----//
+ //------------------//
+
+ // Add sample 2
+ data[2] = (data[2] &= ~SAMPLE_MASK) | (adc[2] & SAMPLE_MASK);
+
+
+ // Add sample 3
+ data[2] = (data[2] &= ~(SAMPLE_MASK << 16)) | ((adc[3] & SAMPLE_MASK) << 16);
+
+
+ //--- data[3] ----//
+ //------------------//
+
+ // Add sample 4
+ data[3] = (data[3] &= ~SAMPLE_MASK) | (adc[4] & SAMPLE_MASK);
+
+
+ // Add sample 5
+ data[3] = (data[3] &= ~(SAMPLE_MASK << 16)) | ((adc[5] & SAMPLE_MASK) << 16);
+ }
+
+ /**
+ * Get the hybrid number associated with this SVT data packet
+ *
+ * @return hybrid number (0-3)
+ */
+ public int getHybridNumber() {
+ return getHybridNumber(data);
+ }
+
+ public static int getHybridNumber(int[] data) {
+ return (data[0] >>> 28) & HYBRID_MASK;
+ }
+
+ /**
+ * Get the APV number associated with this SVT data packet
+ *
+ * @return APV number (0-4)
+ */
+ public int getAPVNumber() {
+ return getAPVNumber(data);
+ }
+
+ public static int getAPVNumber(int[] data) {
+ return (data[0] >>> 24) & APV_MASK;
+ }
+
+ /**
+ * Get the channel number associated with this SVT data packet
+ *
+ * @return channel number (0-127)
+ */
+ public int getChannelNumber() {
+ return getChannelNumber(data);
+ }
+
+ public static int getChannelNumber(int[] data) {
+ return (data[0] >>> 16) & CHANNEL_MASK;
+ }
+
+ /**
+ * Get the FPGA address associated with this SVT data packet
+ *
+ * @return FPGA address
+ */
+ public int getFPGAAddress() {
+ return getFPGAAddress(data);
+ }
+
+ public static int getFPGAAddress(int[] data) {
+ return data[0] & FPGA_MASK;
+ }
+
+ /**
+ * Get the nth SVT sample
+ *
+ * @param n The sample number of interest. Valid values are 0 to 5
+ * @throws RuntimeException if the sample number is out of range
+ * @return ADC value of the nth sample
+ *
+ *
+ */
+ public int getSample(int n) {
+ return getSample(n, data);
+ }
+
+ public static int getSample(int n, int[] data) {
+
+ switch (n) {
+ case 0:
+ return data[1] & SAMPLE_MASK;
+ case 1:
+ return (data[1] >>> 16) & SAMPLE_MASK;
+ case 2:
+ return data[2] & SAMPLE_MASK;
+ case 3:
+ return (data[2] >>> 16) & SAMPLE_MASK;
+ case 4:
+ return data[3] & SAMPLE_MASK;
+ case 5:
+ return (data[3] >>> 16) & SAMPLE_MASK;
+ default:
+ throw new RuntimeException("Invalid sample number! Valid range of values for n are from 0 - 5");
+ }
+ }
+
+ /**
+ * Get all SVT samples
+ *
+ * @return An array containing all SVT Shaper signal samples
+ */
+ public short[] getAllSamples() {
+ return getAllSamples(data);
+ }
+
+ public static short[] getAllSamples(int[] data) {
+ short[] samples = new short[TOTAL_NUMBER_OF_SAMPLES];
+ // Get all SVT Samples
+ for (int index = 0; index < TOTAL_NUMBER_OF_SAMPLES; index++) {
+ samples[index] = (short) getSample(index, data);
+ }
+
+ return samples;
+ }
+
+ /**
+ * Get the hit time at which the hit occurred
+ *
+ * @return The time at which the hit occurred with respect to the trigger
+ */
+ public int getHitTime() {
+ return hitTime;
+ }
+
+ /**
+ * Set the hit time at which the hit occurred
+ *
+ * @param hitTime : Time at which the hit occurred
+ */
+ public void setHitTime(int hitTime) {
+ this.hitTime = hitTime;
+ }
+
+ /**
+ *
+ */
+ public static double[] getTemperature(int[] data) {
+ double[] temperatures = new double[(data.length) * 2];
+
+ int tempIndex = 0;
+ for (int index = 0; index < data.length; index++) {
+ temperatures[tempIndex] = data[index] & TEMP_MASK;
+ temperatures[tempIndex + 1] = (data[index] >>> 16) & TEMP_MASK;
+ tempIndex += 2;
+ }
+
+ return temperatures;
+ }
+
+ /**
+ * Get the sensor (a k a physical) channel corresponding to a raw chip channel
+ *
+ * @param apv : APV25 chip number
+ * @param channel : APV25 raw channel number
+ *
+ * @return sensor channel number
+ */
+ public static int getSensorChannel(int apv, int channel) {
+ int sensorChannel = (TOTAL_APV25_PER_HYBRID - apv - 1) * TOTAL_APV25_CHANNELS + channel;
+ if (sensorChannel < 0 || sensorChannel >= TOTAL_APV25_PER_HYBRID * TOTAL_APV25_CHANNELS) {
+ throw new RuntimeException("sensor channel " + sensorChannel + " is outside of valid range! APV " + apv + ", channel " + channel);
+ }
+ return sensorChannel;
+ }
+
+ public static int getAPV(int sensorChannel) {
+ return TOTAL_APV25_PER_HYBRID - (sensorChannel / TOTAL_APV25_CHANNELS) - 1;
+ }
+
+ public static int getAPVChannel(int sensorChannel) {
+ return sensorChannel % TOTAL_APV25_CHANNELS;
+ }
+
+ public static int getSensorChannel(int[] data) {
+ return getSensorChannel(getAPVNumber(data), getChannelNumber(data));
+ }
+
+ public int getSensorChannel() {
+ return getSensorChannel(data);
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSShapeFitParameters.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSShapeFitParameters.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,144 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+import org.lcsim.event.GenericObject;
+
+/**
+ *
+ * @author mgraham
+ */
+public class HPSShapeFitParameters implements GenericObject {
+
+ private double _t0 = Double.NaN;
+ private double _t0Err = Double.NaN;
+ private double _amp = Double.NaN;
+ private double _ampErr = Double.NaN;
+ private double _tp = Double.NaN;
+ private double _tpErr = Double.NaN;
+ private double _chiSq = Double.NaN;
+
+ public HPSShapeFitParameters() {
+ }
+
+ public HPSShapeFitParameters(double t0, double amplitude) {
+ _t0 = t0;
+ _amp = amplitude;
+ }
+
+ public void setT0(double t0) {
+ _t0 = t0;
+ }
+
+ public void setAmp(double amp) {
+ _amp = amp;
+ }
+
+ public void setTp(double tp) {
+ _tp = tp;
+ }
+
+ public void setAmpErr(double _ampErr) {
+ this._ampErr = _ampErr;
+ }
+
+ public void setT0Err(double _t0Err) {
+ this._t0Err = _t0Err;
+ }
+
+ public void setTpErr(double _tpErr) {
+ this._tpErr = _tpErr;
+ }
+
+ public void setChiSq(double _chiSq) {
+ this._chiSq = _chiSq;
+ }
+
+ public double getT0() {
+ return _t0;
+ }
+
+ public double getAmp() {
+ return _amp;
+ }
+
+ public double getTp() {
+ return _tp;
+ }
+
+ public double getT0Err() {
+ return _t0Err;
+ }
+
+ public double getAmpErr() {
+ return _ampErr;
+ }
+
+ public double getTpErr() {
+ return _tpErr;
+ }
+
+ public double getChiSq() {
+ return _chiSq;
+ }
+
+ @Override
+ public int getNInt() {
+ return 0;
+ }
+
+ @Override
+ public int getNFloat() {
+ return 0;
+ }
+
+ @Override
+ public int getNDouble() {
+ return 7;
+ }
+
+ @Override
+ public int getIntVal(int index) {
+ throw new UnsupportedOperationException("No int values in " + this.getClass().getSimpleName());
+ }
+
+ @Override
+ public float getFloatVal(int index) {
+ throw new UnsupportedOperationException("No int values in " + this.getClass().getSimpleName());
+ }
+
+ @Override
+ public double getDoubleVal(int index) {
+ switch (index) {
+ case 0:
+ return _t0;
+ case 1:
+ return _t0Err;
+ case 2:
+ return _amp;
+ case 3:
+ return _ampErr;
+ case 4:
+ return _tp;
+ case 5:
+ return _tpErr;
+ case 6:
+ return _chiSq;
+ default:
+ throw new UnsupportedOperationException("Only 7 double values in " + this.getClass().getSimpleName());
+ }
+
+ }
+
+ @Override
+ public boolean isFixedSize() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("chisq=%f\tA=%f\tAerr=%f\tT0=%f\tT0err=%f", _chiSq, _amp, _ampErr, _t0, _t0Err);
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSShaperAnalyticFitAlgorithm.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSShaperAnalyticFitAlgorithm.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,106 @@
+package org.hps.recon.tracking;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants.ChannelConstants;
+import org.hps.conditions.deprecated.HPSSVTConstants;
+import org.lcsim.event.RawTrackerHit;
+//import org.lcsim.math.chisq.ChisqProb;
+
+/**
+ * Fast fitter; currently only fits single hits. Uses Tp from ChannelConstants;
+ * fits values and errors for T0 and amplitude.
+ *
+ * @author meeg
+ * @version $Id: HPSShaperAnalyticFitAlgorithm.java,v 1.4 2012/04/25 18:01:32
+ * mgraham Exp $
+ */
+public class HPSShaperAnalyticFitAlgorithm implements HPSShaperFitAlgorithm {
+
+ @Override
+ public HPSShapeFitParameters fitShape(RawTrackerHit rth, ChannelConstants constants) {
+ short[] samples = rth.getADCValues();
+ return this.fitShape(samples, constants);
+ }
+
+ public HPSShapeFitParameters fitShape(short[] samples, ChannelConstants constants) {
+ double minChisq = Double.POSITIVE_INFINITY;
+ int bestStart = 0;
+ HPSShapeFitParameters fit = new HPSShapeFitParameters();
+ for (int i = 0; i < samples.length - 2; i++) {
+ double chisq = fitSection(samples, constants, fit, i);
+// System.out.println("i = " + i + ", " + fit);
+ if (chisq < minChisq) {
+ minChisq = chisq;
+ bestStart = i;
+ }
+ }
+ fitSection(samples, constants, fit, bestStart);
+// System.out.format("%f\t%f\t%f\t%f\t%f\t%f\n", samples[0] - constants.getPedestal(), samples[1] - constants.getPedestal(), samples[2] - constants.getPedestal(), samples[3] - constants.getPedestal(), samples[4] - constants.getPedestal(), samples[5] - constants.getPedestal());
+// System.out.println("start = " + bestStart + ", " + fit);
+ return fit;
+ }
+
+ private double fitSection(short[] samples, ChannelConstants constants, HPSShapeFitParameters fit, int start) {
+ int length = samples.length - start;
+ double[] y = new double[length];
+ double[] t = new double[length];
+
+ for (int i = 0; i < length; i++) {
+ y[i] = samples[start + i] - constants.getPedestal();
+ t[i] = HPSSVTConstants.SAMPLING_INTERVAL * i;
+ }
+
+ double[] p = new double[length];
+ double[] a = new double[length];
+ for (int i = 0; i < length; i++) {
+ p[i] = y[i] / constants.getNoise();
+ a[i] = Math.exp(1 - t[i] / constants.getTp()) / (constants.getTp() * constants.getNoise());
+ }
+
+ double pa, aatt, pat, aat, aa;
+ pa = 0;
+ aatt = 0;
+ pat = 0;
+ aat = 0;
+ aa = 0;
+ for (int i = 0; i < length; i++) {
+ pa += p[i] * a[i];
+ aatt += a[i] * a[i] * t[i] * t[i];
+ pat += p[i] * a[i] * t[i];
+ aat += a[i] * a[i] * t[i];
+ aa += a[i] * a[i];
+ }
+
+ double t0 = (pa * aatt - pat * aat) / (pa * aat - aa * pat);
+ double A = pa / ((Math.exp(t0 / constants.getTp()) * (aat - t0 * aa)));
+
+ double time_var = 0;
+ double height_var = 0;
+ for (int i = 0; i < length; i++) {
+ double dt_dp = a[i] * (aatt - t[i] * aat - t0 * (aat - t[i] * aa)) / (pa * aat - aa * pat);
+ double dh_dp = (a[i] * Math.exp(-1.0 * t0 / constants.getTp()) + A * dt_dp * aa) / (aat - t0 * aa) - A * dt_dp / constants.getTp();
+ time_var += dt_dp * dt_dp;
+ height_var += dh_dp * dh_dp;
+ }
+ t0 += HPSSVTConstants.SAMPLING_INTERVAL * start;
+ fit.setAmp(A);
+ fit.setAmpErr(Math.sqrt(height_var));
+ fit.setT0(t0);
+ fit.setT0Err(Math.sqrt(time_var));
+ fit.setTp(constants.getTp());
+
+ double chisq = 0;
+ for (int i = 0; i < samples.length; i++) {
+ double ti = HPSSVTConstants.SAMPLING_INTERVAL * i;
+ double fit_y = A * (Math.max(0, (ti - t0)) / constants.getTp()) * Math.exp(1 - (ti - t0) / constants.getTp()) + constants.getPedestal();
+ chisq += Math.pow((fit_y - samples[i]) / constants.getNoise(), 2);
+ }
+ fit.setChiSq(chisq);
+
+ if (A > 0) {
+// return ChisqProb.gammp(samples.length - 2, chisq);
+ return chisq / (samples.length - 2);
+ } else {
+ return Double.POSITIVE_INFINITY;
+ }
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSShaperFitAlgorithm.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSShaperFitAlgorithm.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,18 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants.ChannelConstants;
+import org.lcsim.event.RawTrackerHit;
+
+/**
+ *
+ * @author mgraham
+ */
+public interface HPSShaperFitAlgorithm {
+
+ public HPSShapeFitParameters fitShape(RawTrackerHit rth, ChannelConstants constants);
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSStripMaker.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSStripMaker.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,353 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+import hep.physics.matrix.SymmetricMatrix;
+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;
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IReadout;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.DopedSilicon;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
+import org.lcsim.detector.tracker.silicon.SiStrips;
+import org.lcsim.detector.tracker.silicon.SiTrackerIdentifierHelper;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.recon.tracking.digitization.sisim.SiSensorSim;
+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 mgraham
+ */
+public class HPSStripMaker {
+
+ private static String _NAME = "HPSStripClusterer";
+ // Clustering algorithm
+ HPSClusteringAlgorithm _clustering;
+ // Number of strips beyond which charge is averaged on center strips
+ int _max_noaverage_nstrips = 4;
+ // Absolute maximum cluster size
+ int _max_cluster_nstrips = 10;
+ // Sensor simulation needed to correct for Lorentz drift
+ SiSensorSim _simulation;
+ // Identifier helper (reset once per sensor)
+ SiTrackerIdentifierHelper _sid_helper;
+ // Temporary map connecting hits to strip numbers for sake of speed (reset once per sensor)
+ Map<HPSFittedRawTrackerHit, Integer> _strip_map = new HashMap<HPSFittedRawTrackerHit, Integer>();
+ double _oneClusterErr = 1 / Math.sqrt(12);
+ double _twoClusterErr = 1 / 5;
+ double _threeClusterErr = 1 / 3;
+ double _fourClusterErr = 1 / 2;
+ double _fiveClusterErr = 1;
+
+ boolean _debug = false;
+
+ public HPSStripMaker(HPSClusteringAlgorithm algo) {
+ _clustering = algo;
+ }
+
+ public HPSStripMaker(SiSensorSim simulation, HPSClusteringAlgorithm algo) {
+ _clustering = algo;
+ _simulation = simulation;
+ }
+
+ public String getName() {
+ return _NAME;
+ }
+
+ // Make hits for all sensors within a DetectorElement
+ public List<SiTrackerHit> makeHits(IDetectorElement detector) {
+ System.out.println("makeHits(IDetectorElement): " + detector.getName());
+ List<SiTrackerHit> hits = new ArrayList<SiTrackerHit>();
+ List<SiSensor> sensors = detector.findDescendants(SiSensor.class);
+
+ // Loop over all sensors
+ for (SiSensor sensor : sensors) {
+ if (sensor.hasStrips()) {
+ hits.addAll(makeHits(sensor));
+ }
+ }
+
+ // Return hit list
+ return hits;
+ }
+
+ // Make hits for a sensor
+ public List<SiTrackerHit> makeHits(SiSensor sensor) {
+
+ //System.out.println("makeHits: " + sensor.getName());
+
+ List<SiTrackerHit> hits = new ArrayList<SiTrackerHit>();
+
+ // Get SiTrackerIdentifierHelper for this sensor and refresh the strip map used to increase speed
+ _sid_helper = (SiTrackerIdentifierHelper) sensor.getIdentifierHelper();
+ _strip_map.clear();
+
+ // Get hits for this sensor
+ IReadout ro = sensor.getReadout();
+ List<HPSFittedRawTrackerHit> hps_hits = ro.getHits(HPSFittedRawTrackerHit.class);
+
+ Map<SiSensorElectrodes, List<HPSFittedRawTrackerHit>> electrode_hits = new HashMap<SiSensorElectrodes, List<HPSFittedRawTrackerHit>>();
+
+ for (HPSFittedRawTrackerHit hps_hit : hps_hits) {
+
+ // get id and create strip map, get electrodes.
+ IIdentifier id = hps_hit.getRawTrackerHit().getIdentifier();
+ _strip_map.put(hps_hit, _sid_helper.getElectrodeValue(id));
+
+ // Get electrodes and check that they are strips
+ //System.out.println("proc raw hit from: " + DetectorElementStore.getInstance().find(raw_hit.getIdentifier()).get(0).getName());
+ ChargeCarrier carrier = ChargeCarrier.getCarrier(_sid_helper.getSideValue(id));
+ SiSensorElectrodes electrodes = ((SiSensor) hps_hit.getRawTrackerHit().getDetectorElement()).getReadoutElectrodes(carrier);
+ if (!(electrodes instanceof SiStrips)) {
+ continue;
+ }
+
+ if (electrode_hits.get(electrodes) == null) {
+ electrode_hits.put(electrodes, new ArrayList<HPSFittedRawTrackerHit>());
+ }
+
+ electrode_hits.get(electrodes).add(hps_hit);
+ }
+
+ for (Map.Entry entry : electrode_hits.entrySet()) {
+ hits.addAll(makeHits(sensor, (SiStrips) entry.getKey(), (List<HPSFittedRawTrackerHit>) entry.getValue()));
+ }
+
+ return hits;
+ }
+
+ public List<SiTrackerHit> makeHits(SiSensor sensor, SiSensorElectrodes electrodes, List<HPSFittedRawTrackerHit> hps_hits) {
+
+
+
+ // Call the clustering algorithm to make clusters
+ List<List<HPSFittedRawTrackerHit>> cluster_list = _clustering.findClusters(hps_hits);
+
+ // Create an empty list for the pixel hits to be formed from clusters
+ List<SiTrackerHit> hits = new ArrayList<SiTrackerHit>();
+
+ // Make a pixel hit from this cluster
+ for (List<HPSFittedRawTrackerHit> cluster : cluster_list) {
+
+ // Make a TrackerHit from the cluster if it meets max cluster size requirement
+ if (cluster.size() <= _max_cluster_nstrips) {
+ SiTrackerHitStrip1D hit = makeTrackerHit(cluster, electrodes);
+ // Add to readout and to list of hits
+// ((SiSensor) electrodes.getDetectorElement()).getReadout().addHit(hit);
+ hits.add(hit);
+ sensor.getReadout().addHit(hit);
+ }
+ }
+
+ return hits;
+ }
+
+ public void SetOneClusterErr(double err) {
+ _oneClusterErr = err;
+ }
+
+ public void SetTwoClusterErr(double err) {
+ _twoClusterErr = err;
+ }
+
+ public void SetThreeClusterErr(double err) {
+ _threeClusterErr = err;
+ }
+
+ public void SetFourClusterErr(double err) {
+ _fourClusterErr = err;
+ }
+
+ public void SetFiveClusterErr(double err) {
+ _fiveClusterErr = err;
+ }
+
+ public void setCentralStripAveragingThreshold(int max_noaverage_nstrips) {
+ _max_noaverage_nstrips = max_noaverage_nstrips;
+ }
+
+ public void setMaxClusterSize(int max_cluster_nstrips) {
+ _max_cluster_nstrips = max_cluster_nstrips;
+ }
+
+ private SiTrackerHitStrip1D makeTrackerHit(List<HPSFittedRawTrackerHit> cluster, SiSensorElectrodes electrodes) {
+ if(_debug) System.out.println(this.getClass().getSimpleName() + " makeTrackerHit ");
+ Hep3Vector position = getPosition(cluster, electrodes);
+ SymmetricMatrix covariance = getCovariance(cluster, electrodes);
+ double time = getTime(cluster);
+ double energy = getEnergy(cluster);
+ TrackerHitType type = new TrackerHitType(TrackerHitType.CoordinateSystem.GLOBAL, TrackerHitType.MeasurementType.STRIP_1D);
+ List<RawTrackerHit> rth_cluster = new ArrayList<RawTrackerHit>();
+ for (HPSFittedRawTrackerHit bth : cluster) {
+ rth_cluster.add(bth.getRawTrackerHit());
+ }
+ SiTrackerHitStrip1D hit = new SiTrackerHitStrip1D(position, covariance, energy, time, rth_cluster, type);
+ if(_debug) System.out.println(this.getClass().getSimpleName() + " SiTrackerHitStrip1D created at " + position + "(" + hit.getPositionAsVector().toString()+")" + " E " + energy + " time " + time);
+ return hit;
+ }
+
+ private Hep3Vector getPosition(List<HPSFittedRawTrackerHit> cluster, SiSensorElectrodes electrodes) {
+ if(_debug) System.out.println(this.getClass().getSimpleName() + " getPosition for cluster size " + cluster.size());
+ List<Double> signals = new ArrayList<Double>();
+ List<Hep3Vector> positions = new ArrayList<Hep3Vector>();
+
+ if(_debug) System.out.println(this.getClass().getSimpleName() + " Loop of " + cluster.size() + " and add signals and positions to vectors");
+
+ for (HPSFittedRawTrackerHit hit : cluster) {
+ signals.add(hit.getAmp());
+ positions.add(((SiStrips) electrodes).getStripCenter(_strip_map.get(hit)));
+ if(_debug) System.out.println(this.getClass().getSimpleName() + " Added hit with signal " + hit.getAmp() + " at strip center posiiton " + (((SiStrips) electrodes).getStripCenter(_strip_map.get(hit))));
+ }
+
+ // Average charge on central strips of longer clusters
+ if (signals.size() > _max_noaverage_nstrips) {
+ int nstrips_center = signals.size() - 2;
+
+ // collect sum of charges on center strips
+ double center_charge_sum = 0.0;
+ for (int istrip = 1; istrip < signals.size() - 1; istrip++) {
+ center_charge_sum += signals.get(istrip);
+ }
+
+ // distribute evenly on center strips
+ double center_charge_strip = center_charge_sum / nstrips_center;
+ for (int istrip = 1; istrip < signals.size() - 1; istrip++) {
+ signals.set(istrip, center_charge_strip);
+ }
+ }
+
+ if(_debug) System.out.println(this.getClass().getSimpleName() + " Calculate charge weighted mean for " + signals.size() + " signals");
+
+ double total_charge = 0;
+ Hep3Vector position = new BasicHep3Vector(0, 0, 0);
+
+ for (int istrip = 0; istrip < signals.size(); istrip++) {
+ double signal = signals.get(istrip);
+
+ total_charge += signal;
+ position = VecOp.add(position, VecOp.mult(signal, positions.get(istrip)));
+ if(_debug) System.out.println(this.getClass().getSimpleName() + "strip " + istrip+": signal " + signal + " position " + positions.get(istrip) + " -> total_position " + position.toString() + " ( total charge " + total_charge + ")");
+
+ }
+ position = VecOp.mult(1 / total_charge, position);
+ if(_debug) System.out.println(this.getClass().getSimpleName() + " charge weighted position "+position.toString() + " (before trans)");
+ electrodes.getParentToLocal().inverse().transform(position);
+ if(_debug) System.out.println(this.getClass().getSimpleName() + " charge weighted position "+position.toString() + " (after trans)");
+
+ // Swim position back through lorentz drift direction to midpoint between bias surfaces
+ if(_simulation!=null) {
+ _simulation.setSensor((SiSensor) electrodes.getDetectorElement());
+ _simulation.lorentzCorrect(position, electrodes.getChargeCarrier());
+ if(_debug) System.out.println(this.getClass().getSimpleName() + ": Position " + position.toString() + " ( after Lorentz)");
+ }
+
+ // return position in global coordinates
+ Hep3Vector newpos = ((SiSensor) electrodes.getDetectorElement()).getGeometry().getLocalToGlobal().transformed(position);
+ if(_debug) System.out.println(this.getClass().getSimpleName() + " final cluster position "+newpos.toString());
+
+ return ((SiSensor) electrodes.getDetectorElement()).getGeometry().getLocalToGlobal().transformed(position);
+// return electrodes.getLocalToGlobal().transformed(position);
+ }
+
+ private double getTime(List<HPSFittedRawTrackerHit> cluster) {
+ int time_sum = 0;
+ int signal_sum = 0;
+
+ for (HPSFittedRawTrackerHit hit : cluster) {
+
+ double signal = hit.getAmp();
+ double time = hit.getT0();
+
+ time_sum += time * signal;
+ signal_sum += signal;
+
+ }
+ return (double) time_sum / (double) signal_sum;
+ }
+
+ private SymmetricMatrix getCovariance(List<HPSFittedRawTrackerHit> cluster, SiSensorElectrodes electrodes) {
+ SymmetricMatrix covariance = new SymmetricMatrix(3);
+ covariance.setElement(0, 0, Math.pow(getMeasuredResolution(cluster, electrodes), 2));
+ covariance.setElement(1, 1, Math.pow(getUnmeasuredResolution(cluster, electrodes), 2));
+ covariance.setElement(2, 2, 0.0);
+
+ SymmetricMatrix covariance_global = electrodes.getLocalToGlobal().transformed(covariance);
+
+// System.out.println("Global covariance matrix: \n"+covariance_global);
+
+ return covariance_global;
+
+// BasicHep3Matrix rotation_matrix = (BasicHep3Matrix)electrodes.getLocalToGlobal().getRotation().getRotationMatrix();
+// BasicHep3Matrix rotation_matrix_transposed = new BasicHep3Matrix(rotation_matrix);
+// rotation_matrix_transposed.transpose();
+//
+//// System.out.println("Rotation matrix: \n"+rotation_matrix);
+//// System.out.println("Rotation matrix transposed: \n"+rotation_matrix_transposed);
+//// System.out.println("Local covariance matrix: \n"+covariance);
+//
+// BasicHep3Matrix covariance_global = (BasicHep3Matrix)VecOp.mult(rotation_matrix,VecOp.mult(covariance,rotation_matrix_transposed));
+//
+//// System.out.println("Global covariance matrix: \n"+covariance_global);
+//
+// return new SymmetricMatrix((Matrix)covariance_global);
+ }
+
+ private double getMeasuredResolution(List<HPSFittedRawTrackerHit> cluster, SiSensorElectrodes electrodes) // should replace this by a ResolutionModel class that gives expected resolution. This could be a big job.
+ {
+ double measured_resolution;
+
+ double sense_pitch = ((SiSensor) electrodes.getDetectorElement()).getSenseElectrodes(electrodes.getChargeCarrier()).getPitch(0);
+
+// double readout_pitch = electrodes.getPitch(0);
+// double noise = _readout_chip.getChannel(strip_number).computeNoise(electrodes.getCapacitance(strip_number));
+// double signal_expected = (0.000280/DopedSilicon.ENERGY_EHPAIR) *
+// ((SiSensor)electrodes.getDetectorElement()).getThickness(); // ~280 KeV/mm for thick Si sensors
+
+ if (cluster.size() == 1) {
+ measured_resolution = sense_pitch * _oneClusterErr;
+ } else if (cluster.size() == 2) {
+ measured_resolution = sense_pitch * _twoClusterErr;
+ } else if (cluster.size() == 3) {
+ measured_resolution = sense_pitch * _threeClusterErr;
+ } else if (cluster.size() == 4) {
+ measured_resolution = sense_pitch * _fourClusterErr;
+ } else {
+ measured_resolution = sense_pitch * _fiveClusterErr;
+ }
+
+ return measured_resolution;
+ }
+
+ private double getUnmeasuredResolution(List<HPSFittedRawTrackerHit> cluster, SiSensorElectrodes electrodes) {
+ // Get length of longest strip in hit
+ double hit_length = 0;
+ for (HPSFittedRawTrackerHit hit : cluster) {
+ hit_length = Math.max(hit_length, ((SiStrips) electrodes).getStripLength(_strip_map.get(hit)));
+ }
+ return hit_length / Math.sqrt(12);
+ }
+
+ private double getEnergy(List<HPSFittedRawTrackerHit> cluster) {
+ double total_charge = 0.0;
+ for (HPSFittedRawTrackerHit hit : cluster) {
+ double signal = hit.getAmp();
+ total_charge += signal;
+ }
+ return total_charge * DopedSilicon.ENERGY_EHPAIR;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSTrack.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSTrack.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,524 @@
+package org.hps.recon.tracking;
+
+import static org.lcsim.constants.Constants.fieldConversion;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.hps.conditions.deprecated.BeamSpot;
+import org.hps.conditions.deprecated.FieldMap;
+import org.lcsim.event.MCParticle;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.fit.helicaltrack.MultipleScatter;
+import org.lcsim.hps.util.Pair;
+import org.lcsim.spacegeom.CartesianVector;
+import org.lcsim.spacegeom.SpacePoint;
+import org.lcsim.spacegeom.SpaceVector;
+import org.lcsim.util.swim.Helix;
+import org.lcsim.util.swim.Line;
+import org.lcsim.util.swim.Trajectory;
+
+/**
+ * Class HPSTrack: extension of HelicalTrackFit to include HPS-specific
+ * variables other useful things.
+ *
+ * @author mgraham created on 6/27/2011
+ */
+public class HPSTrack extends HelicalTrackFit {
+
+ private BeamSpot _beam;
+ //all of the variables defined below are in the jlab (detector) frame
+ //this position & momentum are measured at the DOCA to the Y-axis,
+ //which is where the tracking returns it's parameters by default
+ private Hep3Vector _pDocaY;
+ private Hep3Vector _posDocaY;
+ //the position & momentum of the track at the intersection of the target (z=0)
+ private Hep3Vector _pTarget;
+ private Hep3Vector _posTarget;
+ //the position & momentum of the track at DOCA to the beam axis (z)
+ private Hep3Vector _pDocaZ;
+ private Hep3Vector _posDocaZ;
+ private double bField = 0.491; // make this set-able
+ private boolean _debug = false;
+ private boolean _debugForward = false;
+ private Trajectory _trajectory;
+ Map<Pair<Integer, Integer>, Double> _fieldMap;
+ Map<Pair<Integer, Integer>, Pair<Double, Double>> _fieldBins;
+ private MCParticle mcParticle;
+
+ public HPSTrack(double[] pars, SymmetricMatrix cov, double[] chisq, int[] ndf,
+ Map<HelicalTrackHit, Double> smap, Map<HelicalTrackHit, MultipleScatter> msmap,
+ BeamSpot beam) {
+ super(pars, cov, chisq, ndf, smap, msmap);
+ _beam = beam;
+ calculateParametersAtTarget();
+ calculateParametersAtDocaY();
+ calculateParametersAtDocaZ();
+ }
+
+ public HPSTrack(double[] pars, SymmetricMatrix cov, double[] chisq, int[] ndf,
+ Map<HelicalTrackHit, Double> smap, Map<HelicalTrackHit, MultipleScatter> msmap) {
+ super(pars, cov, chisq, ndf, smap, msmap);
+ calculateParametersAtTarget();
+ calculateParametersAtDocaY();
+ calculateParametersAtDocaZ();
+ }
+
+ public HPSTrack(HelicalTrackFit htf, BeamSpot beam) {
+ super(htf.parameters(), htf.covariance(), htf.chisq(), htf.ndf(), htf.PathMap(), htf.ScatterMap());
+ _beam = beam;
+ calculateParametersAtTarget();
+ calculateParametersAtDocaY();
+ calculateParametersAtDocaZ();
+ }
+
+ public HPSTrack(HelicalTrackFit htf) {
+ super(htf.parameters(), htf.covariance(), htf.chisq(), htf.ndf(), htf.PathMap(), htf.ScatterMap());
+ calculateParametersAtTarget();
+ calculateParametersAtDocaY();
+ calculateParametersAtDocaZ();
+ }
+
+ public HPSTrack(double[] parameters, SymmetricMatrix covariance, double[] chiSquared, int[] ndf,
+ Map<HelicalTrackHit, Double> sMap, Map<HelicalTrackHit, MultipleScatter> msMap, MCParticle mcParticle) {
+ super(parameters, covariance, chiSquared, ndf, sMap, msMap);
+
+ // Set the MC particle associated with this fit
+ this.mcParticle = mcParticle;
+ }
+
+ /**
+ * Get map of the the track trajectory within the uniform bfield
+ */
+ public Map<Integer, Double[]> trackTrajectory(double zStart, double zStop, int nSteps) {
+ Map<Integer, Double[]> traj = new HashMap<Integer, Double[]>();
+ double step = (zStop - zStart) / nSteps;
+ Double zVal = zStart;
+ Integer nstep = 0;
+ while (zVal < zStop) {
+ Double[] xyz = {0.0, 0.0, 0.0};
+ double s = HelixUtils.PathToXPlane(this, zVal, 1000.0, 1).get(0);
+ xyz[0] = HelixUtils.PointOnHelix(this, s).y();
+ xyz[1] = HelixUtils.PointOnHelix(this, s).z();
+ xyz[2] = zVal;
+ traj.put(nstep, xyz);
+ zVal += step;
+ nstep++;
+ }
+ return traj;
+ }
+
+ /**
+ * Get map of the the track direction within the uniform bfield
+ */
+ public Map<Integer, Double[]> trackDirection(double zStart, double zStop, int nSteps) {
+ Map<Integer, Double[]> traj = new HashMap<Integer, Double[]>();
+ double step = (zStop - zStart) / nSteps;
+ Double zVal = zStart;
+
+ Integer nstep = 0;
+ while (zVal < zStop) {
+ Double[] xyz = {0.0, 0.0, 0.0};
+ double s = HelixUtils.PathToXPlane(this, zVal, 1000.0, 1).get(0);
+ xyz[0] = HelixUtils.Direction(this, s).y();
+ xyz[1] = HelixUtils.Direction(this, s).z();
+ xyz[2] = zVal;
+ traj.put(nstep, xyz);
+ zVal += step;
+ nstep++;
+ }
+ return traj;
+ }
+
+ private void calculateParametersAtTarget() {
+ double pTot = this.p(bField);
+ //currently, PathToXPlane only returns a single path (no loopers!)
+ List<Double> paths = HelixUtils.PathToXPlane(this, 0.0, 100.0, 1);
+ Hep3Vector posTargetTrkSystem = HelixUtils.PointOnHelix(this, paths.get(0));
+ Hep3Vector dirTargetTrkSystem = HelixUtils.Direction(this, paths.get(0));
+ _posTarget = HPSTransformations.transformVectorToDetector(posTargetTrkSystem);
+ _pTarget = VecOp.mult(pTot, HPSTransformations.transformVectorToDetector(dirTargetTrkSystem));
+
+ }
+
+ private void calculateParametersAtDocaY() {
+ double pTot = this.p(bField);
+ Hep3Vector posDocaYTrkSystem = HelixUtils.PointOnHelix(this, 0);
+ Hep3Vector dirDocaYTrkSystem = HelixUtils.Direction(this, 0);
+ _posDocaY = HPSTransformations.transformVectorToDetector(posDocaYTrkSystem);
+ _pDocaY = VecOp.mult(pTot, HPSTransformations.transformVectorToDetector(dirDocaYTrkSystem));
+
+ }
+
+ private void calculateParametersAtDocaZ() {
+ double pTot = this.p(bField);
+ double sAtDocaZ = findPathToDocaZ();
+ Hep3Vector posDocaZTrkSystem = HelixUtils.PointOnHelix(this, sAtDocaZ);
+ Hep3Vector dirDocaZTrkSystem = HelixUtils.Direction(this, sAtDocaZ);
+ _posDocaZ = HPSTransformations.transformVectorToDetector(posDocaZTrkSystem);
+ _pDocaZ = VecOp.mult(pTot, HPSTransformations.transformVectorToDetector(dirDocaZTrkSystem));
+ }
+
+// public Hep3Vector getPositionAtZ(double xFinal, double fringeHalfWidth, double step) {
+// double startFringeUpstream = -2 * fringeHalfWidth;
+// double stopFringeUpstream = 0;
+// if (_debug)
+// System.out.println(this.toString());
+//
+//
+// }
+ public Hep3Vector getPositionAtZ(double xFinal, double start, double stop, double step) {
+
+ double startFringe = start;
+ double stopFringe = stop;
+ // _debugForward = false;
+ // if (xFinal > 900)
+ // _debugForward = true;
+ // if looking upstream, we'll be propagating backwards
+ if (xFinal < 0) {
+ step = -step;
+ startFringe = stop;
+ stopFringe = start;
+ }
+ double fringeHalfWidth = Math.abs(stopFringe - startFringe) / 2;
+ double fringeMid = (stopFringe + startFringe) / 2;
+ if (_debugForward) {
+ System.out.println(this.toString());
+ }
+
+ double sStartFringe = HelixUtils.PathToXPlane(this, startFringe, 1000.0, 1).get(0);
+ if (_debugForward) {
+ System.out.println("path to end of fringe = " + sStartFringe + "; xFinal = " + xFinal);
+ }
+ double xtmp = startFringe;
+ double ytmp = HelixUtils.PointOnHelix(this, sStartFringe).y();
+ double ztmp = HelixUtils.PointOnHelix(this, sStartFringe).z();
+ double Rorig = this.R();
+ double xCtmp = this.xc();
+ double yCtmp = this.yc();
+ double q = Math.signum(this.curvature());
+ double phitmp = getPhi(xtmp, ytmp, xCtmp, yCtmp, q);
+ if (_debugForward) {
+ System.out.println("\nOriginal xtmp = " + xtmp
+ + "; ytmp = " + ytmp
+ + "; ztmp = " + ztmp
+ + "; phitmp = " + phitmp);
+
+ System.out.println("nOriginal Rorig = " + Rorig
+ + "; xCtmp = " + xCtmp
+ + "; yCtmp = " + yCtmp);
+ }
+ if (_debugForward) {
+ System.out.println("Original Direction at Fringe: " + HelixUtils.Direction(this, startFringe).toString());
+ }
+ double Rtmp = Rorig;
+ // now start stepping through the fringe field
+ Hep3Vector r0Tmp = HelixUtils.PointOnHelix(this, sStartFringe);
+ SpacePoint r0 = new SpacePoint(r0Tmp);
+ double pTot = this.p(bField);
+ Hep3Vector dirOrig = HelixUtils.Direction(this, sStartFringe);
+ Hep3Vector p0 = VecOp.mult(pTot, dirOrig);
+ Hep3Vector dirTmp = dirOrig;
+ SpacePoint rTmp = r0;
+ Hep3Vector pTmp = p0;
+ double pXOrig = p0.x();
+ double pXTmp = pXOrig;
+ double totalS = sStartFringe;
+ if (_debugForward) {
+ double tmpdX = xFinal - startFringe;
+ Hep3Vector fooExt = extrapolateStraight(dirOrig, tmpdX);
+ Hep3Vector fooFinal = VecOp.add(fooExt, r0Tmp);
+ System.out.println("Extrpolating straight back from startFringe = (" + fooFinal.x() + "," + fooFinal.y() + "," + fooFinal.z() + ")");
+
+ }
+ //follow trajectory while: in fringe field, before end point, and we don't have a looper
+ while (Math.signum(step) * xtmp < Math.signum(step) * stopFringe && Math.signum(step) * xtmp < Math.signum(step) * xFinal && Math.signum(pXOrig * pXTmp) > 0) {
+ if (_debugForward) {
+ System.out.println("New step in Fringe Field");
+ System.out.println("rTmp = " + rTmp.toString());
+ System.out.println("pTmp = " + pTmp.toString());
+ System.out.println("OriginalHelix pos = " + HelixUtils.PointOnHelix(this, totalS));
+ System.out.println("OriginalHelix Momentum = " + VecOp.mult(pTot, HelixUtils.Direction(this, totalS)));
+ }
+
+ double fringeFactor = getFringe(Math.signum(step) * (fringeMid - rTmp.x()), fringeHalfWidth);
+// double myBField=bField * fringeFactor;
+ double myBField = FieldMap.getFieldFromMap(rTmp.x(), rTmp.y());
+ if (_debugForward) {
+ System.out.println("rTmp.x() = " + rTmp.x() + " field = " + myBField);
+ }
+ setTrack(pTmp, rTmp, q, myBField);
+ rTmp = _trajectory.getPointAtDistance(step);
+ pTmp = VecOp.mult(pTot, _trajectory.getUnitTangentAtLength(step));
+ pXTmp = pTmp.x();
+ xtmp = rTmp.x();
+ if (_debugForward) {
+ System.out.println("############## done... #############");
+
+ System.out.println("\n");
+ }
+ totalS += step;
+ }
+ //ok, done with field...extrapolate straight back...
+ Hep3Vector pointInTrking;
+ if (Math.signum(step) * xtmp < Math.signum(step) * xFinal) {
+ //get direction of the track before it hits fringe field
+ double deltaX = xFinal - xtmp;
+ Hep3Vector dir = _trajectory.getUnitTangentAtLength(0);
+// double deltaY = deltaX * dir.y();
+// double deltaZ = deltaX * dir.z();
+ Hep3Vector delta = extrapolateStraight(dir, deltaX);
+// double deltaZ = Math.sqrt(deltaX*deltaX+deltaY*deltaY)* dir.z();
+ pointInTrking = new BasicHep3Vector(xFinal, delta.y() + ytmp, delta.z() + ztmp);
+
+ if (_debugForward) {
+ System.out.println("Pointing straight forward from xtmp = " + xtmp
+ + "; ytmp = " + ytmp
+ + "; ztmp = " + ztmp
+ + "; deltaX= " + deltaX);
+ System.out.println("Directions: " + dir.toString());
+ System.out.println("Position at ECal: x = " + xFinal + "; y = " + pointInTrking.y() + "; z = " + pointInTrking.z());
+
+ }
+ } else { // still in the fringe field...just return the current position
+// pointInTrking = new BasicHep3Vector(xFinal, ytmp, ztmp);
+ pointInTrking = new BasicHep3Vector(rTmp.x(), rTmp.y(), rTmp.z());
+ }
+ return HPSTransformations.transformVectorToDetector(pointInTrking);
+ }
+
+ /**
+ * Get the position and direction on the track using B-field map for
+ * extrapolation
+ *
+ * @param start = starting z-position of extrapolation
+ * @param zFinal = final z-position
+ * @param step = step size
+ * @return position[0] and direction[1] at Z=zfinal
+ */
+ public Hep3Vector[] getPositionAtZMap(double start, double xFinal, double step) {
+ return this.getPositionAtZMap(start, xFinal, step, true);
+ }
+
+ public Hep3Vector[] getPositionAtZMap(double start, double xFinal, double step, boolean debugOk) {
+
+ double startFringe = start;
+
+ _debugForward = false;
+ if (xFinal > 900) {
+ _debugForward = debugOk ? true : false;
+ }
+ // if looking upstream, we'll be propagating backwards
+ if (xFinal < 0) {
+ step = -step;
+ }
+ if (_debugForward) {
+ System.out.println(this.toString());
+ }
+
+ double sStartFringe = HelixUtils.PathToXPlane(this, startFringe, 1000.0, 1).get(0);
+ if (_debugForward) {
+ System.out.println("path to end of fringe = " + sStartFringe + "; xFinal = " + xFinal);
+ }
+ double xtmp = startFringe;
+ double ytmp = HelixUtils.PointOnHelix(this, sStartFringe).y();
+ double ztmp = HelixUtils.PointOnHelix(this, sStartFringe).z();
+ double Rorig = this.R();
+ double xCtmp = this.xc();
+ double yCtmp = this.yc();
+ double q = Math.signum(this.curvature());
+ double phitmp = getPhi(xtmp, ytmp, xCtmp, yCtmp, q);
+ if (_debugForward) {
+ System.out.println("\nOriginal xtmp = " + xtmp
+ + "; ytmp = " + ytmp
+ + "; ztmp = " + ztmp
+ + "; phitmp = " + phitmp);
+
+ System.out.println("nOriginal Rorig = " + Rorig
+ + "; xCtmp = " + xCtmp
+ + "; yCtmp = " + yCtmp);
+ }
+ if (_debugForward) {
+ System.out.println("Original Direction at Fringe: " + HelixUtils.Direction(this, startFringe).toString());
+ }
+ double Rtmp = Rorig;
+ // now start stepping through the fringe field
+ Hep3Vector r0Tmp = HelixUtils.PointOnHelix(this, sStartFringe);
+ SpacePoint r0 = new SpacePoint(r0Tmp);
+ double pTot = this.p(bField);
+ Hep3Vector dirOrig = HelixUtils.Direction(this, sStartFringe);
+ Hep3Vector p0 = VecOp.mult(pTot, dirOrig);
+ Hep3Vector dirTmp = dirOrig;
+ SpacePoint rTmp = r0;
+ Hep3Vector pTmp = p0;
+ double pXOrig = p0.x();
+ double pXTmp = pXOrig;
+ double totalS = sStartFringe;
+ if (_debugForward) {
+ double tmpdX = xFinal - startFringe;
+ Hep3Vector fooExt = extrapolateStraight(dirOrig, tmpdX);
+ Hep3Vector fooFinal = VecOp.add(fooExt, r0Tmp);
+ System.out.println("Extrpolating straight back from startFringe = (" + fooFinal.x() + "," + fooFinal.y() + "," + fooFinal.z() + ")");
+
+ }
+ //follow trajectory while: in fringe field, before end point, and we don't have a looper
+ while (Math.signum(step) * xtmp < Math.signum(step) * xFinal && Math.signum(pXOrig * pXTmp) > 0) {
+ if (_debugForward) {
+ System.out.println("New step in Fringe Field");
+ System.out.println("rTmp = " + rTmp.toString());
+ System.out.println("pTmp = " + pTmp.toString());
+ System.out.println("OriginalHelix pos = " + HelixUtils.PointOnHelix(this, totalS));
+ System.out.println("OriginalHelix Momentum = " + VecOp.mult(pTot, HelixUtils.Direction(this, totalS)));
+ }
+
+ double myBField = FieldMap.getFieldFromMap(rTmp.x(), rTmp.y());
+ if (_debugForward) {
+ System.out.println("rTmp.x() = " + rTmp.x() + " field = " + myBField);
+ }
+ setTrack(pTmp, rTmp, q, myBField);
+ rTmp = _trajectory.getPointAtDistance(step);
+ pTmp = VecOp.mult(pTot, _trajectory.getUnitTangentAtLength(step));
+ pXTmp = pTmp.x();
+ xtmp = rTmp.x();
+ if (_debugForward) {
+ System.out.println("############## done... #############");
+
+ System.out.println("\n");
+ }
+ totalS += step;
+ }
+
+ //Go with finer granularity in the end
+ rTmp = _trajectory.getPointAtDistance(0);
+ xtmp = rTmp.x();
+ pTmp = VecOp.mult(pTot, _trajectory.getUnitTangentAtLength(step));
+ pXTmp = pTmp.x();
+ step = step / 10.0;
+
+ while (Math.signum(step) * xtmp < Math.signum(step) * xFinal && Math.signum(pXOrig * pXTmp) > 0) {
+ if (_debugForward) {
+ System.out.println("New step in Fringe Field");
+ System.out.println("rTmp = " + rTmp.toString());
+ System.out.println("pTmp = " + pTmp.toString());
+ System.out.println("OriginalHelix pos = " + HelixUtils.PointOnHelix(this, totalS));
+ System.out.println("OriginalHelix Momentum = " + VecOp.mult(pTot, HelixUtils.Direction(this, totalS)));
+ }
+
+ double myBField = FieldMap.getFieldFromMap(rTmp.x(), rTmp.y());
+ if (_debugForward) {
+ System.out.println("rTmp.x() = " + rTmp.x() + " field = " + myBField);
+ }
+ setTrack(pTmp, rTmp, q, myBField);
+ rTmp = _trajectory.getPointAtDistance(step);
+ pTmp = VecOp.mult(pTot, _trajectory.getUnitTangentAtLength(step));
+ pXTmp = pTmp.x();
+ xtmp = rTmp.x();
+ if (_debugForward) {
+ System.out.println("############## done... #############");
+
+ System.out.println("\n");
+ }
+ totalS += step;
+ }
+
+ //ok, done with field.
+ Hep3Vector pointInTrking = new BasicHep3Vector(rTmp.x(), rTmp.y(), rTmp.z());
+ if (_debugForward) {
+ System.out.println("Position xfinal (tracking) : x = " + xFinal + "; y = " + pointInTrking.y() + "; z = " + pointInTrking.z());
+ }
+ Hep3Vector[] out = {HPSTransformations.transformVectorToDetector(pointInTrking), HPSTransformations.transformVectorToDetector(pTmp)};
+
+ return out;
+ }
+
+ private double getPhi(double x, double y, double xc, double yc, double sign) {
+ // System.out.println("Math.atan2(y - yc, x - xc)="+Math.atan2(y - yc, x - xc));
+ return Math.atan2(y - yc, x - xc) - sign * Math.PI / 2;
+ }
+
+ private Hep3Vector extrapolateStraight(Hep3Vector dir, double deltaX) {
+ double deltaY = deltaX * dir.y();
+ double deltaZ = deltaX * dir.z();
+ return new BasicHep3Vector(deltaX, deltaY, deltaZ);
+ }
+
+ //field that changes linearly from Bmax->0
+ private double getFringe(double x, double halfWidth) {
+// System.out.println("x = " + x + "; halfWidth = " + halfWidth);
+ if (x / halfWidth > 1) {
+ return 1;
+ }
+ if (x / halfWidth < -1) {
+ return 0;
+ }
+
+ return (1.0 / 2.0) * (1 + x / halfWidth);
+ }
+
+ private Hep3Vector getDirection(double phi, double sign) {
+ double ux = Math.cos(phi) * this.sth();
+ double uy = Math.sin(phi) * this.sth();
+ double uz = this.cth();
+ // Return the direction unit vector
+ return new BasicHep3Vector(ux, uy, uz);
+ }
+
+ private double findPathToDocaZ() {
+ double step = 0.1;//100 um step size
+ double maxS = 100.0; //go to 10cm
+ double s = -30;
+ double minDist = 999999;
+ double minS = s;
+ double dist = 999998;
+ //once the distance starts increasing, quit and return
+ while (dist < minDist) {
+ Hep3Vector pos = HelixUtils.PointOnHelix(this, s);
+ dist = pos.y() * pos.y() + pos.z() * pos.z();
+ s += step;
+ }
+ return minS;
+ }
+
+ private void setTrack(Hep3Vector p0, SpacePoint r0, double q, double B) {
+ SpaceVector p = new CartesianVector(p0.v());
+ double phi = Math.atan2(p.y(), p.x());
+ double lambda = Math.atan2(p.z(), p.rxy());
+ double field = B * fieldConversion;
+
+ if (q != 0 && field != 0) {
+ double radius = p.rxy() / (q * field);
+ _trajectory = new Helix(r0, radius, phi, lambda);
+ } else {
+ _trajectory = new Line(r0, phi, lambda);
+ }
+ }
+
+ public Trajectory getTrajectory() {
+ return this._trajectory;
+ }
+
+ /**
+ * Get the MC Particle associated with the HelicalTrackFit
+ *
+ * @return mcParticle :
+ */
+ public MCParticle getMCParticle() {
+ return this.mcParticle;
+ }
+
+ /**
+ * Set the MC Particle associated with the HelicalTrackFit
+ *
+ * @param mcParticle :
+ */
+ public void setMCParticle(MCParticle mcParticle) {
+ this.mcParticle = mcParticle;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSTransformations.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HPSTransformations.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,66 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Matrix;
+import hep.physics.vec.Hep3Matrix;
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.detector.Rotation3D;
+import org.lcsim.detector.Transform3D;
+
+/**
+ * Class that contains the transformations between the JLAB and lcsim tracking coordinate systems
+ * @author mgraham, phansson
+ * created 6/27/2011
+ * made static 10/14/2013
+ *
+ */
+public class HPSTransformations {
+
+ private static final Transform3D _detToTrk = HPSTransformations.initialize();
+
+ /**
+ * Private constructor to prevent initialization
+ */
+ private HPSTransformations() {
+ }
+
+ /**
+ * Static private initialization of transform
+ * @return transform
+ */
+ private static Transform3D initialize() {
+ BasicHep3Matrix tmp = new BasicHep3Matrix();
+ tmp.setElement(0, 2, 1);
+ tmp.setElement(1, 0, 1);
+ tmp.setElement(2, 1, 1);
+ return new Transform3D(new Rotation3D(tmp));
+ }
+
+ public static Hep3Vector transformVectorToTracking(Hep3Vector vec) {
+ return _detToTrk.transformed(vec);
+ }
+
+ public static SymmetricMatrix transformCovarianceToTracking(SymmetricMatrix cov) {
+ return _detToTrk.transformed(cov);
+ }
+
+ public static Hep3Vector transformVectorToDetector(Hep3Vector vec) {
+ return (_detToTrk.inverse()).transformed(vec);
+ }
+
+ public static SymmetricMatrix transformCovarianceToDetector(SymmetricMatrix cov) {
+ return (_detToTrk.inverse()).transformed(cov);
+ }
+ public static Transform3D getTransform(){
+ return _detToTrk;
+ }
+ public static Hep3Matrix getMatrix(){
+ return _detToTrk.getRotation().getRotationMatrix();
+ }
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HelicalTrackHitDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,571 @@
+package org.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 static org.hps.conditions.deprecated.StereoPair.detectorVolume;
+
+import org.hps.conditions.deprecated.StereoPair;
+import org.hps.conditions.deprecated.SvtUtils;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+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.RawTrackerHit;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseRelationalTable;
+import org.lcsim.event.base.MyLCRelation;
+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.recon.tracking.digitization.sisim.SiTrackerHit;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.digitization.sisim.TrackerHitType;
+
+/**
+ *
+ * @author Mathew Graham <[log in to unmask]>
+ * @author Per Hansson <[log in to unmask]>
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: HelicalTrackHitDriver.java,v 1.10 2013/10/17 22:08:33 omoreno Exp $
+ */
+public class HelicalTrackHitDriver extends org.lcsim.fit.helicaltrack.HelicalTrackHitDriver {
+
+ private boolean _debug = false;
+ private double _clusterTimeCut = -99; // if negative, don't cut..otherwise,
+ // dt cut time in ns
+ private String _subdetectorName = "Tracker";
+ private String _clusterCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+
+ private Map<String, String> _stereomap = new HashMap<String, String>();
+ private List<String> _colnames = new ArrayList<String>();
+ private boolean _doTransformToTracking = true;
+
+ public enum LayerGeometryType {
+ Split, Common
+ }
+
+ private LayerGeometryType _layerGeometryType = LayerGeometryType.Split;
+
+ /**
+ * Default Ctor
+ */
+ public HelicalTrackHitDriver() {
+ this.addCollection("StripClusterer_SiTrackerHitStrip1D");
+ }
+
+ // --- Setters ---//
+ // ---------------//
+
+ /**
+ *
+ * @param geomType
+ */
+ public void setLayerGeometryType(String geomType) {
+ this._layerGeometryType = LayerGeometryType.valueOf(geomType);
+ }
+
+ /**
+ *
+ * @param dtCut
+ */
+ public void setClusterTimeCut(double dtCut) {
+ this._clusterTimeCut = dtCut;
+ }
+
+ /**
+ *
+ * @param subdetectorName
+ */
+ public void setSubdetectorName(String subdetectorName) {
+ this._subdetectorName = subdetectorName;
+ }
+
+ /**
+ *
+ * @param debug
+ */
+ public void setDebug(boolean debug) {
+ this._debug = debug;
+ }
+
+ /**
+ *
+ * @param trans
+ */
+ public void setTransformToTracking(boolean trans) {
+ this._doTransformToTracking = trans;
+ }
+
+ /**
+ *
+ * @param stripHitsCollectionName
+ */
+ public void setStripHitsCollectionName(String stripHitsCollectionName) {
+ HitRelationName(stripHitsCollectionName);
+ }
+
+ /**
+ *
+ * @param helicalTrackHitRelationsCollectionName
+ */
+ public void setHelicalTrackHitRelationsCollectionName(String helicalTrackHitRelationsCollectionName) {
+ HitRelationName(helicalTrackHitRelationsCollectionName);
+ }
+
+ /**
+ *
+ * @param helicalTrackMCRelationsCollectionName
+ */
+ public void setHelicalTrackMCRelationsCollectionName(String helicalTrackMCRelationsCollectionName) {
+ MCRelationName(helicalTrackMCRelationsCollectionName);
+ }
+
+ /**
+ *
+ * @param outputHitCollectionName
+ */
+ public void setOutputHitCollectionName(String outputHitCollectionName) {
+ OutputCollection(outputHitCollectionName);
+ }
+
+ @Override
+ public void process(EventHeader event) {
+
+ // Instantiate the list of HelicalTrackCrosses and HelicalTrackHits
+ List<HelicalTrackCross> stereoCrosses = new ArrayList<HelicalTrackCross>();
+ List<HelicalTrackHit> helhits = new ArrayList<HelicalTrackHit>();
+
+ // Create an LCRelation from a HelicalTrackHit to
+ List<LCRelation> hitrelations = new ArrayList<LCRelation>();
+
+ // Create an LCRelation from a HelicalTrackHit to an MC particle used to
+ // create it
+ List<LCRelation> mcrelations = new ArrayList<LCRelation>();
+
+ RelationalTable hittomc = new BaseRelationalTable(RelationalTable.Mode.ONE_TO_MANY, RelationalTable.Weighting.UNWEIGHTED);
+ if (event.hasCollection(LCRelation.class, "SVTTrueHitRelations")) {
+ List<LCRelation> trueHitRelations = event.get(LCRelation.class, "SVTTrueHitRelations");
+ for (LCRelation relation : trueHitRelations) {
+ if (relation != null && relation.getFrom() != null && relation.getTo() != null) {
+ hittomc.add(relation.getFrom(), relation.getTo());
+ }
+ }
+ }
+
+ if (LayerGeometryType.Common == _layerGeometryType) {
+
+ for (String _colname : this._colnames) {
+
+ if (!event.hasCollection(SiTrackerHit.class, _colname))
+ continue;
+
+ // Get the list of SiTrackerHits for this collection
+ List<SiTrackerHit> hitlist = event.get(SiTrackerHit.class, _colname);
+
+ if (_debug) {
+ System.out.printf("%s: found %d SiTrackerHits\n", 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!
+ // With our detector setup, when is this not true?
+ 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);
+ for (RawTrackerHit rth : h.getRawHits()) {
+ for (Object simHit : hittomc.allFrom(rth)) {
+ strip.addMCParticle(((SimTrackerHit) simHit).getMCParticle());
+ }
+ }
+
+ // 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);
+ }
+
+ if ((_clusterTimeCut > 0 && Math.abs(h.getTime()) < _clusterTimeCut) || _clusterTimeCut < 0) {
+ // 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 layer %d\n", this.getClass().getSimpleName(), strip.origin().toString(), strip.layer());
+ }
+ }
+ } else {
+
+ // If not a 1D strip hit, make a pixel hit
+ // This should be removed as it is never used.
+ HelicalTrackHit hit3d = this.makeDigi3DHit(hit);
+ helhits.add(hit3d);
+ hitrelations.add(new MyLCRelation(hit3d, hit));
+ }
+
+ } // Loop over SiTrackerHits
+
+
+ if (_debug)
+ System.out.printf("%s: Create stereo hits from %d strips \n", this.getClass().getSimpleName(), striplistmap.size());
+
+ // Loop over the stereo layer pairs
+ // TODO: Change this so that it makes use of StereoPairs
+ for (String id1 : _stereomap.keySet()) {
+
+ // Get the second layer
+ String id2 = _stereomap.get(id1);
+
+ if (_debug) {
+ System.out.printf("%s: Form stereo hits from sensor id %s with %d hits and %s with %d hits\n", this.getClass().getSimpleName(), id1, striplistmap.get(id1) == null ? 0
+ : striplistmap.get(id1).size(), id2, striplistmap.get(id2) == null ? 0 : striplistmap.get(id2).size());
+ }
+
+ /*
+ * 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)));
+ }
+ }
+
+ } // End of loop over stereo pairs
+
+ if (_debug) {
+ System.out.printf("%s: added %d stereo hits from %s collection \n", this.getClass().getSimpleName(), stereoCrosses.size(), _colname);
+ }
+
+ } // End of loop over collection names
+
+ if (_debug) {
+ System.out.printf("%s: totally added %d stereo hits:\n", this.getClass().getSimpleName(), stereoCrosses.size());
+ for (HelicalTrackCross cross : stereoCrosses) {
+ System.out.printf("%s: %.2f,%.2f,%.2f \n", this.getClass().getSimpleName(), cross.getPosition()[0], cross.getPosition()[1], cross.getPosition()[2]);
+ }
+ }
+
+ // 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);
+ }
+
+ } else if (LayerGeometryType.Split == _layerGeometryType) {
+
+
+ // If the event does not have hit clusters, skip it.
+ if (!event.hasCollection(SiTrackerHit.class, _clusterCollectionName)){
+ if(_debug){
+ System.out.println("Event: " + event.getRunNumber() + " does not contain the collection " + _clusterCollectionName);
+ }
+ return;
+ }
+
+ // Get the list of SiTrackerHits for this collection
+ List<SiTrackerHit> hitlist = event.get(SiTrackerHit.class, _clusterCollectionName);
+
+
+ if (_debug) {
+ System.out.printf("%s: found %d SiTrackerHits\n", this.getClass().getSimpleName(), hitlist.size());
+ }
+
+ Map<HelicalTrackStrip, SiTrackerHitStrip1D> stripmap = new HashMap<HelicalTrackStrip, SiTrackerHitStrip1D>();
+ Map<SiSensor, List<HelicalTrackStrip>> striplistmap = new HashMap<SiSensor, List<HelicalTrackStrip>>();
+ for (SiTrackerHit hit : hitlist) {
+
+ // Cast the hit as a 1D strip hit and find the identifier
+ // for the detector/layer combo
+ SiTrackerHitStrip1D h = (SiTrackerHitStrip1D) hit;
+ SiSensor sensor = h.getSensor();
+
+ List<HelicalTrackStrip> hitsOnSensor = striplistmap.get(sensor);
+
+ // If no hits on that sensor yet -> create the list
+ if (hitsOnSensor == null) {
+ hitsOnSensor = new ArrayList<HelicalTrackStrip>();
+ striplistmap.put(sensor, hitsOnSensor);
+ }
+
+ // Create a HelicalTrackStrip for this hit
+ HelicalTrackStrip strip = makeDigiStrip(h);
+ for (RawTrackerHit rth : h.getRawHits()) {
+ for (Object simHit : hittomc.allFrom(rth)) {
+ strip.addMCParticle(((SimTrackerHit) simHit).getMCParticle());
+ }
+ }
+
+ if ((_clusterTimeCut > 0 && Math.abs(h.getTime()) < _clusterTimeCut) || _clusterTimeCut < 0) {
+ // Add the strip to the list of strips on this sensor
+ hitsOnSensor.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 layer %d\n", this.getClass().getSimpleName(), strip.origin().toString(), strip.layer());
+ }
+ } // Loop over SiTrackerHits
+
+
+ // for(StereoPair pair : _det.getStereoPairs()) {
+ for (StereoPair stereoPair : SvtUtils.getInstance().getStereoPairs()) {
+
+ /*
+ * 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> helicalTrackCrosses = null;
+ if (stereoPair.getDetectorVolume() == detectorVolume.Top) {
+ helicalTrackCrosses = _crosser.MakeHits(striplistmap.get(stereoPair.getAxialSensor()), striplistmap.get(stereoPair.getStereoSensor()));
+ } else if (stereoPair.getDetectorVolume() == detectorVolume.Bottom) {
+ helicalTrackCrosses = _crosser.MakeHits(striplistmap.get(stereoPair.getStereoSensor()), striplistmap.get(stereoPair.getAxialSensor()));
+ }
+
+ if (_debug)
+ System.out.printf("%s: Found %d stereo hits from sensors\n%s: %s : %d hits\n%s: %s with %d hits\n", this.getClass().getSimpleName(), helicalTrackCrosses.size(), this.getClass()
+ .getSimpleName(), stereoPair.getAxialSensor().getName(), striplistmap.get(stereoPair.getAxialSensor()) == null ? 0 : striplistmap.get(stereoPair.getAxialSensor()).size(),
+ this.getClass().getSimpleName(), stereoPair.getStereoSensor().getName(),
+ striplistmap.get(stereoPair.getStereoSensor()) == null ? 0 : striplistmap.get(stereoPair.getStereoSensor()).size());
+
+ for (HelicalTrackCross cross : helicalTrackCrosses) {
+ 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)));
+ }
+ if (_debug)
+ System.out.printf("%s: cross at %.2f,%.2f,%.2f \n", this.getClass().getSimpleName(), cross.getPosition()[0], cross.getPosition()[1], cross.getPosition()[2]);
+
+ }
+
+ } // Loop over stereo pairs
+
+ if (_debug) {
+ System.out.printf("%s: totally added %d stereo hits:\n", this.getClass().getSimpleName(), stereoCrosses.size());
+ for (HelicalTrackCross cross : stereoCrosses) {
+ System.out.printf("%s: %.2f,%.2f,%.2f \n", this.getClass().getSimpleName(), cross.getPosition()[0], cross.getPosition()[1], cross.getPosition()[2]);
+ }
+ }
+
+ // 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 \n", 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.");
+ }
+
+
+ if (LayerGeometryType.Common == this._layerGeometryType) {
+
+ int nLayersTotal = detector.getSubdetector(_subdetectorName).getLayering().getLayers().getNumberOfLayers();
+ if (_debug) {
+ System.out.printf("%s: %d layers \n", 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.");
+ }
+ List<int[]> pairs = new ArrayList<int[]>();
+ for (int i = 1; i <= (nLayersTotal) - 1; i += 2) {
+ int[] pair = { i, i + 1 };
+ if (_debug)
+ System.out.printf("%s: Adding stereo pair: %d,%d\n", this.getClass().getSimpleName(), 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 \n", this.getClass().getSimpleName(), pair[0], pair[1]);
+ setStereoPair(_subdetectorName, pair[0], pair[1]);
+ }
+
+ }
+
+ if (_debug)
+ System.out.printf("%s: %d stereo modules added", this.getClass().getSimpleName(), this._stereomap.size());
+
+ }
+
+ private HelicalTrackStrip makeDigiStrip(SiTrackerHitStrip1D h) {
+
+ 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));
+ for (MCParticle mcp : cross.getMCParticles()) {
+ newhit.addMCParticle(mcp);
+ }
+ 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);
+
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HelixConverter.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HelixConverter.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,142 @@
+
+package org.hps.recon.tracking;
+
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.matrix.Matrix;
+import hep.physics.matrix.MatrixOp;
+import hep.physics.matrix.MutableMatrix;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.util.swim.Helix;
+
+/**
+ * Convert a helix to a straight line track at a specified reference plane normal to the x axis.
+ * This code was developed for simulating the Heavy Photon Search experiment where the target is
+ * located outside the magnetic field volume.
+ *
+ * @author Richard Partridge
+ */
+public class HelixConverter {
+
+ private double _xref;
+
+ /**
+ * Constructor for the HelixConverter used to convert helices to StraightLineTracks
+ * at the magnetic field boundary. The reference point xref identifies
+ * the x coordinate that specifies the magnetic field boundary. The StraightLineTracks
+ * produced by this class will use xref as their reference point.
+ *
+ * @param xref x coordinate that specifies the magnetic field boundary
+ */
+ public HelixConverter(double xref) {
+ _xref = xref;
+ }
+
+ /**
+ * Convert a helix to a StraightLineTrack.
+ *
+ * @param helix helix to be converted
+ * @return resulting StraightLineTrack
+ */
+ public StraightLineTrack Convert(HelicalTrackFit helix) {
+
+ // Get helix parameters used in this calculation
+ double RC = helix.R();
+ double xc = helix.xc();
+ double yc = helix.yc();
+ double phi0 = helix.phi0();
+ double d0 = helix.dca();
+ double slope = helix.slope();
+ double z0 = helix.z0();
+
+ // First find path length to reference point
+ double arg = (xc - _xref) / RC;
+ if (Math.abs(arg) > 1.0) return null;
+ double phi = Math.asin(arg);
+ double dphi = phi0 - phi;
+ if (dphi > Math.PI) dphi -= 2. * Math.PI;
+ if (dphi < -Math.PI) dphi += 2. * Math.PI;
+ double s = RC * dphi;
+ double cphi = Math.cos(phi);
+ double sphi = Math.sin(phi);
+ double cphi0 = Math.cos(phi0);
+ double sphi0 = Math.sin(phi0);
+
+ // Get the track position at the reference point
+ double xref = xc - RC * sphi;
+ if (Math.abs(xref - _xref) > 1.e-10) System.out.println("Bad path length - x0: "+xref+" xref: "+_xref);
+ double yref = yc + RC * cphi;
+ double zref = z0 + s * slope;
+
+ // Get dy/dx and dz/dx for the straight-line track
+ double dydx = sphi / cphi;
+ double dzdx = slope / cphi;
+
+ // Calculate the Jacobian between the straight line track parameters and the helix parameters
+ MutableMatrix deriv = new BasicMatrix(4,5);
+ double dydcurv = (cphi0 + s / RC * sphi - cphi) * RC*RC;
+ deriv.setElement(StraightLineTrack.y0Index, HelicalTrackFit.curvatureIndex, dydcurv);
+ deriv.setElement(StraightLineTrack.y0Index, HelicalTrackFit.dcaIndex, cphi0);
+ double dydphi0 = (RC - d0) * sphi0 - RC * sphi;
+ deriv.setElement(StraightLineTrack.y0Index, HelicalTrackFit.phi0Index, dydphi0);
+ deriv.setElement(StraightLineTrack.z0Index, HelicalTrackFit.z0Index, 1.);
+ deriv.setElement(StraightLineTrack.z0Index, HelicalTrackFit.slopeIndex, s);
+ deriv.setElement(StraightLineTrack.dydxIndex, HelicalTrackFit.curvatureIndex, -s / (cphi*cphi));
+ deriv.setElement(StraightLineTrack.dydxIndex, HelicalTrackFit.phi0Index, 1. / (cphi*cphi));
+ double dzslopedphi0 = sphi * slope / (cphi*cphi);
+ deriv.setElement(StraightLineTrack.dzdxIndex, HelicalTrackFit.curvatureIndex, -s * dzslopedphi0);
+ deriv.setElement(StraightLineTrack.dzdxIndex, HelicalTrackFit.phi0Index, dzslopedphi0);
+ deriv.setElement(StraightLineTrack.dzdxIndex, HelicalTrackFit.slopeIndex, 1. / cphi);
+
+ // Calculate the covariance matrix
+ Matrix derivT = MatrixTranspose(deriv);
+ SymmetricMatrix hcov = helix.covariance();
+ Matrix cov = MatrixOp.mult(deriv, MatrixOp.mult(hcov, derivT));
+ SymmetricMatrix scov = new SymmetricMatrix(cov);
+
+ return new StraightLineTrack(xref, yref, zref, dydx, dzdx, scov);
+ }
+
+ /**
+ * Convert a helix to a StraightLineTrack.
+ *
+ * @param helix helix to be converted
+ * @return resulting StraightLineTrack
+ */
+ public StraightLineTrack Convert(Helix helix) {
+
+ Hep3Vector unitVec = helix.getUnitTangentAtLength(0);
+ Hep3Vector posVec = helix.getPointAtDistance(0);
+ double dzdx = unitVec.z()/unitVec.x();
+ double dydx = unitVec.y()/unitVec.x();
+ double zref = posVec.z() - dzdx*(posVec.x()-_xref);
+ double yref = posVec.y() - dydx*(posVec.x()-_xref);
+ SymmetricMatrix scov = null;
+ StraightLineTrack slt = new StraightLineTrack(_xref, yref, zref, dydx, dzdx, scov);
+ //System.out.printf("%s: unitVec %s posVec %s\n",this.getClass().getSimpleName(),unitVec.toString(),posVec.toString());
+ //System.out.printf("%s: dzdx=%f dydx=%s\n",this.getClass().getSimpleName(),dzdx,dydx);
+ //System.out.printf("%s: ref = %f,%f,%f\n",this.getClass().getSimpleName(),_xref,yref,zref);
+ return slt;
+ }
+
+
+
+ /**
+ * Returns the transpose of the matrix (inexplicably not handled by
+ * the matrix package for non-square matrices).
+ *
+ * @param m matrix to be transposed
+ * @return transposed matrix
+ */
+ private Matrix MatrixTranspose(Matrix m) {
+ MutableMatrix mt = new BasicMatrix(m.getNColumns(), m.getNRows());
+ for (int i = 0; i < m.getNRows(); i++) {
+ for (int j = 0; j < m.getNColumns(); j++) {
+ mt.setElement(j, i, m.e(i, j));
+ }
+ }
+ return mt;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HelixFitter.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/HelixFitter.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,29 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+
+/**
+ * HPS extension of the fitter algorithm to enable the use of local classes
+ * @author Per Hansson Adrian <[log in to unmask]>
+ * @version $Id: HelixFitter.java,v 1.2 2013/11/07 03:54:58 phansson Exp $ $Date: 2013/11/07 03:54:58 $ $Author: phansson $
+ */
+public class HelixFitter extends org.lcsim.recon.tracking.seedtracker.HelixFitter {
+
+ public HelixFitter(MaterialManager materialManager) {
+ super(materialManager);
+ //replace the multiple scattering to that given as parameter to be able to use a local version and not lcsim one
+ _scattering = new MultipleScattering(materialManager);
+
+ }
+
+ public void setDebug(boolean debug) {
+ super.setDebug(debug);
+ _scattering.setDebug(debug);
+ }
+
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/LCIOTrackAnalysis.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/LCIOTrackAnalysis.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,169 @@
+package org.hps.recon.tracking;
+
+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.hps.conditions.deprecated.SvtUtils;
+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;
+
+/**
+ *
+ * @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/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/MaterialManager.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/MaterialManager.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,43 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lcsim.recon.tracking.seedtracker.MaterialXPlane;
+
+
+
+/**
+ *
+ * Extension to lcsim MaterialManager to allow more flexibility in track reconstruction
+ *
+ * @author Per Hansson Adrian <[log in to unmask]>
+ * @version $Id: MaterialManager.java,v 1.3 2013/11/07 03:54:58 phansson Exp $ $Date: 2013/11/07 03:54:58 $ $Author: phansson $
+ */
+public class MaterialManager extends org.lcsim.recon.tracking.seedtracker.MaterialManager {
+
+ protected boolean _includeMS = true;
+ private final static List<MaterialXPlane> _emptyMaterialXPlaneList = new ArrayList<MaterialXPlane>();
+ public MaterialManager() {
+ super();
+ }
+ public MaterialManager(boolean includeMS) {
+ super();
+ this._includeMS = includeMS;
+ }
+ @Override
+ public List<MaterialXPlane> getMaterialXPlanes() {
+ return this._includeMS ? super.getMaterialXPlanes() : _emptyMaterialXPlaneList;
+ }
+
+ @Override
+ public void setDebug(boolean debug) {
+ super.setDebug(debug);
+ }
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/MaterialSupervisor.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/MaterialSupervisor.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,421 @@
+package org.hps.recon.tracking;
+
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.conditions.deprecated.SvtUtils;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.IGeometryInfo;
+import org.lcsim.detector.ILogicalVolume;
+import org.lcsim.detector.IPhysicalVolume;
+import org.lcsim.detector.IPhysicalVolumeContainer;
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.Translation3D;
+import org.lcsim.detector.material.IMaterial;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.solids.ISolid;
+import org.lcsim.detector.solids.Polygon3D;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
+import org.lcsim.geometry.Detector;
+
+
+
+/**
+ * Material manager using the detector geometry.
+
+ * Uses a private class to set up detector volumes.
+ * This can probably make use of the DetectorGeometry classes from lcsim instead for the model.
+ * Something to consider in the future.
+ *
+ * @author Per Hansson Adrian <[log in to unmask]>
+ * @version $Id: MaterialSupervisor.java,v 1.4 2013/11/07 03:54:58 phansson Exp $ $Date: 2013/11/07 03:54:58 $ $Author: phansson $
+ */
+public class MaterialSupervisor extends MaterialManager {
+
+ private List<ScatteringDetectorVolume> _detectorVolumes = new ArrayList<ScatteringDetectorVolume>();
+
+
+ public MaterialSupervisor() {
+ super();
+ this._includeMS = true;
+ }
+ public MaterialSupervisor(boolean includeMS) {
+ super(includeMS);
+ }
+
+ @Override
+ public void setDebug(boolean debug) {
+ super.setDebug(debug);
+ }
+
+ public List<ScatteringDetectorVolume> getMaterialVolumes() {
+ return _detectorVolumes;
+ }
+
+ @Override
+ public void buildModel(Detector det) {
+ //super.buildModel(det);
+ //if(DEBUG)
+ System.out.printf("%s: ###########################################################\n",this.getClass().getSimpleName());
+ System.out.printf("%s: Build detector model\n",this.getClass().getSimpleName());
+ List<SiSensor> sensors = det.getSubdetector("Tracker").getDetectorElement().findDescendants(SiSensor.class);
+ //List<SiTrackerModule> modules = det.getDetectorElement().findDescendants(SiTrackerModule.class);
+ System.out.printf("%s: %d sensors\n",this.getClass().getSimpleName(),sensors.size());
+ System.out.printf("%s: %5s %32s %22s %15s %10s %10s\n",this.getClass().getSimpleName(),"ID","Pos (mm)","size(mm)","t(mm)","t(%R.L)","type");
+ for (SiSensor module: sensors) {
+
+ SiStripPlane plane = new SiStripPlane(module);
+
+ System.out.printf("%s: %5d %32s %15.2fx%.2f %10.2f %10.3f %10s\n",this.getClass().getSimpleName(),plane.getId(),plane.origin().toString(),
+ plane.getUnmeasuredDimension(),plane.getMeasuredDimension(),
+ plane.getThickness(),plane.getThicknessInRL()*100,
+ SvtUtils.getInstance().isAxial(module) ? "axial" : "stereo");
+ _detectorVolumes.add(plane);
+ }
+ System.out.printf("%s: ###########################################################\n",this.getClass().getSimpleName());
+ }
+
+
+
+ public interface ScatteringDetectorVolume {
+ public String getName();
+ public double getMaterialTraversed(Hep3Vector dir);
+ public double getMaterialTraversedInRL(Hep3Vector dir);
+ public void print();
+ public IDetectorElement getDetectorElement();
+ }
+
+ //public abstract class DetectorPlane extends SiSensor {
+ public interface DetectorPlane extends ScatteringDetectorVolume{
+ public double getThickness();
+ public double getThicknessInRL();
+ public double getLength();
+ public double getWidth();
+ public Hep3Vector origin();
+ public Hep3Vector normal();
+ public int getId();
+
+ }
+
+ private abstract class SiPlane implements DetectorPlane {
+ abstract void addMaterial();
+ }
+
+ public class SiStripPlane extends SiPlane {
+ private Hep3Vector _org = null; // origin
+ private Hep3Vector _w = null; // normal to plane
+ private Hep3Vector _u = null;
+ private Hep3Vector _v = null;
+ private Materials _materials = new Materials();
+ private SiSensor _sensor;
+ private double _length;
+ private double _width;
+
+ public SiStripPlane(SiSensor module) {
+ _sensor = module;
+ setOrigin();
+ setNormal();
+ setMeasuredCoordinate();
+ setUnmeasuredCoordinate();
+ setDimensions();
+ addMaterial();
+
+ }
+
+ @Override
+ public IDetectorElement getDetectorElement() {
+ return getSensor();
+ }
+
+ private SiTrackerModule getModule() {
+ return (SiTrackerModule)getGeometry().getDetectorElement().getParent();
+ }
+
+
+ private IGeometryInfo getGeometry() {
+ return getSensor().getGeometry();
+ }
+
+ SiSensor getSensor() {
+ return _sensor;
+ }
+
+ Polygon3D getPsidePlane() {
+ return getSensor().getBiasSurface(ChargeCarrier.HOLE);
+ }
+
+ Polygon3D getNsidePlane() {
+ return getSensor().getBiasSurface(ChargeCarrier.ELECTRON);
+ }
+
+
+
+ @Override
+ public double getMaterialTraversed(Hep3Vector dir) {
+ //the distance inside the plane (note I don't care about sign of unit vector only projection distance)
+ double cth = Math.abs(VecOp.dot(dir, _w));
+ double t = _materials.getThickness();
+ return t/cth;
+ }
+
+ @Override
+ public double getMaterialTraversedInRL(Hep3Vector dir) {
+ //the distance inside the plane (note I don't care about sign of unit vector only projection distance)
+ double cth = Math.abs(VecOp.dot(dir, _w));
+ double t = _materials.getThicknessInRL();
+ return t/cth;
+ }
+
+ @Override
+ protected void addMaterial() {
+
+ IPhysicalVolume parent = getModule().getGeometry().getPhysicalVolume();
+ IPhysicalVolumeContainer daughters = parent.getLogicalVolume().getDaughters();
+ //System.out.printf("%s found %d daugters to SiTrackerModule\n",this.getClass().getSimpleName(),daughters.size());
+ for(IPhysicalVolume daughter : daughters) {
+ ILogicalVolume logicalVolume = daughter.getLogicalVolume();
+ IMaterial material = logicalVolume.getMaterial();
+ String name = material.getName();
+ double X0 = 10.0* material.getRadiationLength()/material.getDensity();
+ Box solid = (Box) logicalVolume.getSolid();
+ //System.out.printf("%s x %f y %f z %f box\n",this.getClass().getSimpleName(),solid.getXHalfLength(),solid.getYHalfLength(),solid.getZHalfLength());
+ double halfThickness = solid.getZHalfLength();
+ addMaterial(name, material.getDensity()/1000.0, X0,2.0*halfThickness);
+ }
+ }
+
+ public void addMaterial(String type, double density, double radLen, double t) {
+ _materials.add(type, density, radLen, t);
+ }
+
+
+ @Override
+ public double getThickness() {
+ return _materials.getThickness();
+ }
+
+ @Override
+ public double getThicknessInRL() {
+ return _materials.getThicknessInRL();
+ }
+
+ private void setDimensions() {
+ // The dimensions are taken from the full module
+ IPhysicalVolume physVol_parent = getModule().getGeometry().getPhysicalVolume();
+ ILogicalVolume logVol_parent = physVol_parent.getLogicalVolume();
+ ISolid solid_parent = logVol_parent.getSolid();
+ Box box_parent;
+ if(Box.class.isInstance(solid_parent)) {
+ box_parent = (Box) solid_parent;
+ } else {
+ throw new RuntimeException("Couldn't cast the module volume to a box!?");
+ }
+ _length = box_parent.getXHalfLength()*2.0;
+ _width = box_parent.getYHalfLength()*2.0;
+
+ }
+
+ @Override
+ public Hep3Vector origin() {
+
+ return _org;
+ }
+
+ public void setOrigin(Hep3Vector org) {
+
+ this._org = org;
+ }
+
+ private void setOrigin() {
+ // Use origin of p-side surface
+ Hep3Vector origin = VecOp.mult(HPSTransformations.getMatrix(),_sensor.getGeometry().getPosition());
+ //transform to p-side
+ Polygon3D psidePlane = this.getPsidePlane();
+ Translation3D transformToPside = new Translation3D(VecOp.mult(-1*psidePlane.getDistance(), psidePlane.getNormal()));
+ this._org = transformToPside.translated(origin);
+ }
+
+ @Override
+ public Hep3Vector normal() {
+ if(_w==null) {
+ _w = this.getPsidePlane().getNormal();
+ System.out.printf("setting normal from pside normal %s\n",_w.toString());
+ _w = VecOp.mult(VecOp.mult(HPSTransformations.getMatrix(),getSensor().getReadoutElectrodes(ChargeCarrier.HOLE).getLocalToGlobal().getRotation().getRotationMatrix()), _w);
+ System.out.printf("normal after local to global to tracking rotation %s\n",_w.toString());
+ }
+ return this._w;
+ }
+
+ private void setNormal() {
+ _w = this.getPsidePlane().getNormal();
+ _w = VecOp.mult(VecOp.mult(HPSTransformations.getMatrix(),getSensor().getReadoutElectrodes(ChargeCarrier.HOLE).getLocalToGlobal().getRotation().getRotationMatrix()), _w);
+ }
+
+ public void setNormal(Hep3Vector w) {
+ this._w = w;
+ }
+
+ @Override
+ public void print() {
+ System.out.printf("DetectorPlane: org %s normal vector %s %.2fx%.2fmm thickness %f R.L. (%fmm)\n",
+ origin().toString(),normal().toString(),getLength(),getWidth(),
+ getThicknessInRL(),getThickness());
+ }
+
+ @Override
+ public int getId() {
+ return _sensor.getSensorID();
+ }
+
+ @Override
+ public String getName() {
+ return _sensor.getName();
+ }
+
+ @Override
+ public double getLength() {
+ return _length;
+ }
+
+ @Override
+ public double getWidth() {
+ return _width;
+ }
+
+ double getMeasuredDimension() {
+ return getLength();
+ }
+
+ double getUnmeasuredDimension() {
+ return getWidth();
+ }
+
+ Hep3Vector getUnmeasuredCoordinate() {
+ return _v;
+ }
+ Hep3Vector getMeasuredCoordinate() {
+ return _u;
+ }
+
+ private void setMeasuredCoordinate()
+ {
+ // p-side unit vector
+ ITransform3D electrodes_to_global = getSensor().getReadoutElectrodes(ChargeCarrier.HOLE).getLocalToGlobal();
+ Hep3Vector measuredCoordinate = getSensor().getReadoutElectrodes(ChargeCarrier.HOLE).getMeasuredCoordinate(0);
+ measuredCoordinate = VecOp.mult(VecOp.mult(HPSTransformations.getMatrix(),electrodes_to_global.getRotation().getRotationMatrix()), measuredCoordinate);
+ _u = measuredCoordinate;
+ }
+
+ private void setUnmeasuredCoordinate()
+ {
+ // p-side unit vector
+ ITransform3D electrodes_to_global = getSensor().getReadoutElectrodes(ChargeCarrier.HOLE).getLocalToGlobal();
+ Hep3Vector unmeasuredCoordinate = getSensor().getReadoutElectrodes(ChargeCarrier.HOLE).getUnmeasuredCoordinate(0);
+ unmeasuredCoordinate = VecOp.mult(VecOp.mult(HPSTransformations.getMatrix(),electrodes_to_global.getRotation().getRotationMatrix()), unmeasuredCoordinate);
+ _v = unmeasuredCoordinate;
+ }
+
+
+
+
+ }
+
+
+
+
+
+
+ private static class Material {
+ private String _name;
+ private double _X0;
+ private double _density;
+ private double _thickness;
+ public Material(String _name, double _X0, double _density, double _thickness) {
+ this._name = _name;
+ this._X0 = _X0;
+ this._density = _density;
+ this._thickness = _thickness;
+ }
+ private void add(double t) {
+ _thickness+=t;
+ }
+
+ public double getThickness() {
+ return _thickness;
+ }
+
+ public double getDensity() {
+ return _density;
+ }
+
+ public double getX0() {
+ return _X0;
+ }
+
+ }
+
+ private static class Materials {
+ private List<Material> _materials = new ArrayList<Material>();
+ private double _tot_X0 = -1;
+ public Materials() {
+ }
+ public int numberOfMaterials() {
+ return _materials.size();
+ }
+ public void add(String mat,double density, double radLen, double t) {
+ boolean found = false;
+ for(Material m : _materials) {
+ if(m._name==mat) {
+ m.add(t);
+ found=true;
+ break;
+ }
+ }
+ if (!found) {
+ //System.out.printf("%s: Adding %.2fmm of %s \n",this.getClass().getSimpleName(),t,mat);
+ _materials.add(new Material(mat,radLen,density,t));
+ }
+
+ }
+ public double getThicknessInRL() {
+ if(_materials.isEmpty()) return 0;
+ if(_tot_X0<0) {
+ double sum = 0.;
+ for(Material m : _materials) {
+ sum += m.getDensity()*m.getThickness();
+ }
+ //System.out.printf("sum = %f\n",sum);
+ double tot_X0 = 0.;
+ for(Material m : _materials) {
+ double w_j = m._density*m.getThickness()/(numberOfMaterials()*sum);
+ tot_X0 += w_j/(m.getThickness()/m.getX0());
+ }
+ //System.out.printf("tot_X0 = %f\n",tot_X0);
+ _tot_X0 = 1.0/tot_X0;
+ }
+ return _tot_X0;
+ }
+
+ private double getThickness() {
+ double t_tot = 0.;
+ for(Material m : _materials) {
+ t_tot += m.getThickness();
+ }
+ return t_tot;
+ }
+
+ }
+
+
+
+
+
+
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/MultipleScattering.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/MultipleScattering.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,455 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.hps.recon.tracking.MaterialSupervisor.ScatteringDetectorVolume;
+import org.hps.recon.tracking.MaterialSupervisor.SiStripPlane;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.solids.Inside;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.recon.tracking.seedtracker.ScatterAngle;
+
+
+/**
+ * Extention of lcsim class to allow use of local classes.
+ * Finds scatter points and magnitude from detector geometry directly.
+ * @author Per Hansson Adrian <[log in to unmask]>
+ * @version $Id: MultipleScattering.java,v 1.7 2013/11/07 03:54:58 phansson Exp $ $Date: 2013/11/07 03:54:58 $ $Author: phansson $
+ */
+public class MultipleScattering extends org.lcsim.recon.tracking.seedtracker.MultipleScattering {
+
+
+
+ //public MultipleScattering(MaterialSupervisor materialmanager) {
+ // super(materialmanager);
+ //}
+
+ public MultipleScattering(MaterialManager materialmanager) {
+ super(materialmanager);
+ }
+
+ /**
+ * Override lcsim version and select material manager depending on object type. This allows to use a local extension of the material manager in teh lcsim track fitting code.
+ *
+ * @param helix
+ * @return a list of ScatterAngle.
+ */
+ public List<ScatterAngle> FindScatters(HelicalTrackFit helix) {
+ if(_debug) System.out.printf("\n%s: FindScatters() for helix:\n%s\n",this.getClass().getSimpleName(),helix.toString());
+
+ if(MaterialSupervisor.class.isInstance(this._materialmanager)) {
+ if(_debug) System.out.printf("%s: use HPS scattering model",this.getClass().getSimpleName());
+ return this.FindHPSScatters(helix);
+ } else {
+ if(_debug) System.out.printf("%s: use default lcsim material manager to find scatters\n",this.getClass().getSimpleName());
+ return super.FindScatters(helix);
+ }
+ }
+
+ /**
+ * Extra interface to keep a function returning the same type as the lcsim version
+ *
+ * @param helix
+ * @return a list of ScatterAngle.
+ */
+ private List<ScatterAngle> FindHPSScatters(HelicalTrackFit helix) {
+ ScatterPoints scatterPoints = this.FindHPSScatterPoints(helix);
+ return scatterPoints.getScatterAngleList();
+ }
+
+
+
+ /**
+ * Find scatter points along helix using the local material manager
+ *
+ * @param helix
+ * @return the points of scatter along the helix
+ */
+ public ScatterPoints FindHPSScatterPoints(HelicalTrackFit helix) {
+ if(_debug) System.out.printf("\n%s: FindHPSScatters() for helix:\n%s\n",this.getClass().getSimpleName(),helix.toString());
+
+ // Check that B Field is set
+ if (_bfield == 0.) throw new RuntimeException("B Field must be set before calling FindScatters method");
+
+ // Create a new list to contain the mutliple scatters
+ //List<ScatterAngle> scatters = new ArrayList<ScatterAngle>();
+ ScatterPoints scatters = new ScatterPoints();
+
+ MaterialSupervisor materialSupervisor = (MaterialSupervisor) this._materialmanager;
+
+ List<ScatteringDetectorVolume> materialVols = materialSupervisor.getMaterialVolumes();
+
+ if(_debug) System.out.printf("%s: there are %d detector volumes in the model\n",this.getClass().getSimpleName(),materialVols.size());
+
+ for(ScatteringDetectorVolume vol : materialVols) {
+
+ if(_debug) System.out.printf("\n%s: found detector volume \"%s\"\n",this.getClass().getSimpleName(),vol.getName());
+
+ // find intersection pathpoint with helix
+ Hep3Vector pos = getHelixIntersection(helix,vol);
+
+ if(pos!=null) {
+
+ if(_debug) System.out.printf("%s: intersection position %s\n",this.getClass().getSimpleName(),pos.toString());
+
+ // find the track direction at the plane
+
+ double s = HelixUtils.PathToXPlane(helix, pos.x(), 0.,0).get(0);
+
+ if(_debug) System.out.printf("%s: path length %f\n",this.getClass().getSimpleName(),s);
+
+ Hep3Vector dir = HelixUtils.Direction(helix, s);
+
+ if(_debug) System.out.printf("%s: track dir %s\n",this.getClass().getSimpleName(),dir.toString());
+
+
+ //Calculate the material the track will traverse
+ double radlen = vol.getMaterialTraversedInRL(dir);
+
+ if(_debug) System.out.printf("%s: material traversed: %f R.L. (%fmm) \n",
+ this.getClass().getSimpleName(),radlen,vol.getMaterialTraversed(dir));
+
+ double p = helix.p(this._bfield);
+ double msangle = this.msangle(p, radlen);
+
+ ScatterAngle scat = new ScatterAngle(s,msangle);
+
+ if(_debug) System.out.printf("%s: scatter angle %f rad for p %f GeV at path length %f\n",
+ this.getClass().getSimpleName(),scat.Angle(),p,scat.PathLen());
+
+ ScatterPoint scatterPoint = new ScatterPoint(vol.getDetectorElement(),scat);
+ scatters.addPoint(scatterPoint);
+
+ } else {
+
+ if(_debug) System.out.printf("\n%s: helix did not intersect this volume \n",this.getClass().getSimpleName());
+
+ }
+
+ }
+
+ // Sort the multiple scatters by their path length
+ Collections.sort(scatters._points);
+
+ if(_debug) {
+ System.out.printf("\n%s: found %d scatters for this helix:\n",this.getClass().getSimpleName(),scatters.getPoints().size());
+ System.out.printf("%s: %10s %10s\n",this.getClass().getSimpleName(),"s (mm)","theta(rad)");
+ for (ScatterPoint p : scatters.getPoints()) {
+ System.out.printf("%s: %10.2f %10f\n",this.getClass().getSimpleName(),p.getScatterAngle().PathLen(),p.getScatterAngle().Angle());
+ }
+ }
+ return scatters;
+
+ }
+
+
+ public Hep3Vector getHelixIntersection(HelicalTrackFit helix, ScatteringDetectorVolume plane) {
+
+ if(SiStripPlane.class.isInstance(plane)) {
+ return getHelixIntersection( helix, (SiStripPlane)plane);
+ } else {
+ throw new UnsupportedOperationException("This det volume type is not supported yet.");
+ }
+ }
+
+ /*
+ * Returns interception between helix and plane
+ * Uses the origin x posiution of the plane
+ * and extrapolates linearly to find teh intersection
+ * If inside use an iterative "exact" way to determine the final position
+ */
+
+ public Hep3Vector getHelixIntersection(HelicalTrackFit helix, SiStripPlane plane) {
+
+ if(this._debug) {
+ System.out.printf("%s: calculate simple helix intercept\n",this.getClass().getSimpleName());
+ System.out.printf("%s: StripSensorPlane:\n",this.getClass().getSimpleName());
+ plane.print();
+ }
+
+
+ double s_origin = HelixUtils.PathToXPlane(helix, plane.origin().x(),0.,0).get(0);
+
+ if(Double.isNaN(s_origin)) {
+ if(this._debug) System.out.printf("%s: could not extrapolate to XPlane, too large curvature: origin is at %s \n", this.getClass().getSimpleName(),plane.origin().toString());
+ return null;
+ }
+
+ Hep3Vector pos = HelixUtils.PointOnHelix(helix, s_origin);
+ Hep3Vector direction = HelixUtils.Direction(helix, s_origin);
+
+ if(this._debug) System.out.printf("%s: position at x=origin is %s with path length %f and direction %s\n",
+ this.getClass().getSimpleName(),pos.toString(),s_origin,direction.toString());
+
+ // Use this approximate position to get a first estimate if the helix intercepted the plane
+ // This is only because the real intercept position is an iterative procedure and we'd
+ // like to avoid using it if possible
+ // Consider the plane as pure x-plane i.e. no rotations
+ //-> this is not very general, as it assumes that strips are (mostly) along y -> FIX THIS!?
+
+
+ // Transformation from tracking to detector frame
+ Hep3Vector pos_det = VecOp.mult(VecOp.inverse(HPSTransformations.getMatrix()),pos);
+ Hep3Vector direction_det = VecOp.mult(VecOp.inverse(HPSTransformations.getMatrix()),direction);
+
+
+ if(this._debug) System.out.printf("%s: position in det frame %s and direction %s\n",
+ this.getClass().getSimpleName(),pos_det.toString(),direction_det.toString());
+
+ // Transformation from detector frame to sensor frame
+ Hep3Vector pos_sensor = plane.getSensor().getReadoutElectrodes(ChargeCarrier.HOLE).getGlobalToLocal().transformed(pos_det);
+ Hep3Vector direction_sensor = plane.getSensor().getReadoutElectrodes(ChargeCarrier.HOLE).getGlobalToLocal().rotated(direction_det);
+
+
+ if(this._debug) System.out.printf("%s: position in sensor frame %s and direction %s\n",
+ this.getClass().getSimpleName(),pos_sensor.toString(),direction_sensor.toString());
+
+
+ // find step in w to cross sensor plane
+ double delta_w = -1.0*pos_sensor.z()/direction_sensor.z();
+
+ // find the point where it crossed the plane
+
+ Hep3Vector pos_int = VecOp.add(pos_sensor, VecOp.mult(delta_w, direction_sensor));
+ Hep3Vector pos_int_det = plane.getSensor().getReadoutElectrodes(ChargeCarrier.HOLE).getLocalToGlobal().transformed(pos_int);
+ // find the intercept in the tracking frame
+ Hep3Vector pos_int_trk = VecOp.mult(HPSTransformations.getMatrix(),pos_int_det);
+
+
+ if(this._debug) System.out.printf("%s: take step %f to get intercept position in sensor frame %s (det: %s trk: %s)\n",
+ this.getClass().getSimpleName(), delta_w, pos_int, pos_int_det.toString(), pos_int_trk.toString());
+
+ // check if it's inside the sensor
+ Inside result_inside = plane.getDetectorElement().getGeometry().getPhysicalVolume().getMotherLogicalVolume().getSolid().inside(pos_int);
+ Inside result_inside_module = plane.getSensor().getGeometry().getDetectorElement().getParent().getGeometry().inside(pos_int_det);
+
+ if(this._debug) System.out.printf("%s: Inside result sensor: %s module: %s\n",
+ this.getClass().getSimpleName(),
+ result_inside.toString(),
+ result_inside_module.toString());
+
+
+
+ boolean isInsideSolid = false;
+ if(result_inside.equals(Inside.INSIDE) || result_inside.equals(Inside.SURFACE)) {
+ isInsideSolid = true;
+ }
+
+ boolean isInsideSolidModule = false;
+ if(result_inside_module.equals(Inside.INSIDE) || result_inside_module.equals(Inside.SURFACE)) {
+ isInsideSolidModule = true;
+ }
+
+
+ boolean isInside = true;
+ if(Math.abs(pos_int.x()) > plane.getMeasuredDimension()/2.0) {
+ if(this._debug) System.out.printf("%s: intercept is outside in u\n", this.getClass().getSimpleName());
+ isInside = false;
+ }
+
+ if(Math.abs(pos_int.y()) > plane.getUnmeasuredDimension()/2.0) {
+ if(this._debug) System.out.printf("%s: intercept is outside in v\n", this.getClass().getSimpleName());
+ isInside = false;
+ }
+
+
+ if(!isInside) return null;
+
+ if(this._debug) {
+ System.out.printf("%s: found intercept at %s \n",this.getClass().getSimpleName(),pos_int_trk.toString());
+ }
+
+
+ // Check if it's inside sensor and module and if it contradicts the manual calculation
+ // For now: trust manual calculation and output warning if it's outside BOTH sensor AND module -> FIX THIS!?
+
+ if(!isInsideSolid ) {
+ if(_debug) System.out.printf("%s: manual calculation says inside sensor, inside solid says outside -> contradiction \n", this.getClass().getSimpleName());
+ if(isInsideSolidModule) {
+ if(_debug) System.out.printf("%s: this intercept is outside sensor but inside module\n", this.getClass().getSimpleName());
+ } else {
+ if(_debug) System.out.printf("%s: warning: this intercept at %s, in sensor frame %s, (sensor origin at %s ) is outside sensor and module!\n",
+ this.getClass().getSimpleName(),pos_int_trk.toString(),pos_int.toString(),plane.origin().toString());
+ }
+ }
+
+
+
+
+ // Catch special cases where the incidental iteration procedure seem to fail -> FIX THIS!
+ if(helix.p(Math.abs(_bfield)) < 0.3) {
+
+ if(this._debug) System.out.printf("%s: momentum is low skip the iterative calculation\n",this.getClass().getSimpleName());
+
+ return pos_int_trk;
+ }
+
+ if(this._debug) System.out.printf("%s: calculate iterative helix intercept\n",this.getClass().getSimpleName());
+
+
+ pos = TrackUtils.getHelixPlaneIntercept(helix, plane.normal(), plane.origin(), _bfield);
+
+ if(pos==null) {
+
+// throw new RuntimeException(String.format("%s: iterative intercept failed for helix \n%s\n with org=%s,w=%s, B=%f\n pdef=%f and pdef_pos=%s",
+// this.getClass().getSimpleName(),helix.toString(),plane.origin().toString(),plane.normal().toString(),_bfield,s_origin,pos));
+//
+ System.out.printf("%s: iterative intercept failed for helix \n%s\n at sensor with org=%s, unit w=%s => use approx intercept pos=%s at path %f\n",
+ this.getClass().getSimpleName(),helix.toString(),plane.origin().toString(),plane.normal().toString(),pos, s_origin);
+
+ return pos_int_trk;
+
+ }
+
+
+ if(this._debug) {
+ System.out.printf("%s: iterative helix intercept point at %s (diff to approx: %s) \n",this.getClass().getSimpleName(),pos.toString(),VecOp.sub(pos, pos_int_trk).toString());
+ }
+
+
+
+ // find position in sensor frame
+ pos_int_det = VecOp.mult(VecOp.inverse(HPSTransformations.getMatrix()), pos);
+ Hep3Vector pos_int_sensor = plane.getSensor().getGeometry().getGlobalToLocal().transformed(VecOp.mult(VecOp.inverse(HPSTransformations.getMatrix()), pos));
+
+ if(this._debug) System.out.printf("%s: found iterative helix intercept in sensor coordinates at %s\n",
+ this.getClass().getSimpleName(),pos_int_sensor.toString());
+ result_inside = plane.getDetectorElement().getGeometry().getPhysicalVolume().getMotherLogicalVolume().getSolid().inside(pos_int_sensor);
+ result_inside_module = plane.getSensor().getGeometry().getDetectorElement().getParent().getGeometry().inside(pos_int_det);
+
+ if(this._debug) System.out.printf("%s: Inside result sensor: %s module: %s\n",
+ this.getClass().getSimpleName(),
+ result_inside.toString(),
+ result_inside_module.toString());
+
+
+
+ isInsideSolid = false;
+ if(result_inside.equals(Inside.INSIDE) || result_inside.equals(Inside.SURFACE)) {
+ isInsideSolid = true;
+ }
+
+ isInsideSolidModule = false;
+ if(result_inside_module.equals(Inside.INSIDE) || result_inside_module.equals(Inside.SURFACE)) {
+ isInsideSolidModule = true;
+ }
+
+
+ isInside = true;
+ if(Math.abs(pos_int.x()) > plane.getMeasuredDimension()/2.0) {
+ if(this._debug) System.out.printf("%s: intercept is outside in u\n", this.getClass().getSimpleName());
+ isInside = false;
+ }
+
+ if(Math.abs(pos_int.y()) > plane.getUnmeasuredDimension()/2.0) {
+ if(this._debug) System.out.printf("%s: intercept is outside in v\n", this.getClass().getSimpleName());
+ isInside = false;
+ }
+
+
+
+
+ // Check if it's inside sensor and module and if it contradicts the manual calculation
+ // For now: trust manual calculation and output warning if it's outside BOTH sensor AND module -> FIX THIS!?
+
+ if(!isInsideSolid ) {
+ if(_debug) System.out.printf("%s: manual iterative calculation says inside sensor, inside solid says outside -> contradiction \n", this.getClass().getSimpleName());
+ if(isInsideSolidModule) {
+ if(_debug) System.out.printf("%s: this iterative intercept is outside sensor but inside module\n", this.getClass().getSimpleName());
+ } else {
+ if(_debug) System.out.printf("%s: warning: this iterative intercept %s, sensor frame %s, (sensor origin %s ) is outside sensor and module!\n",
+ this.getClass().getSimpleName(),pos_int_trk.toString(),pos_int.toString(),plane.origin().toString());
+ }
+ }
+
+ if(!isInside) return null;
+
+ if(this._debug) {
+ System.out.printf("%s: found intercept at %s \n",this.getClass().getSimpleName(),pos_int_trk.toString());
+ }
+
+ return pos_int_trk;
+
+
+
+ }
+
+ @Override
+ public void setDebug(boolean debug) {
+ _debug = debug;
+ }
+
+ public MaterialManager getMaterialManager() {
+ // Should be safe to cast here
+ return (MaterialManager)_materialmanager;
+ }
+
+ /**
+ * Nested class to encapsulate the scatter angles and which detector element it is related to
+ */
+ public class ScatterPoint implements Comparable<ScatterPoint> {
+ IDetectorElement _det;
+ ScatterAngle _scatterAngle;
+ public ScatterPoint(IDetectorElement det, ScatterAngle scatterAngle) {
+ _det = det;
+ _scatterAngle = scatterAngle;
+ }
+ public IDetectorElement getDet() {
+ return _det;
+ }
+ public ScatterAngle getScatterAngle() {
+ return _scatterAngle;
+ }
+
+ @Override
+ public int compareTo(ScatterPoint p) {
+ return p.getScatterAngle().PathLen() > this._scatterAngle.PathLen() ? -1 : 1;
+ }
+ }
+
+ /**
+ * Nested class to encapsulate a list of scatters
+ *
+ */
+ public class ScatterPoints {
+ private List<ScatterPoint> _points;
+ public ScatterPoints(List<ScatterPoint> _points) {
+ this._points = _points;
+ }
+ private ScatterPoints() {
+ _points = new ArrayList<ScatterPoint>();
+ }
+ public List<ScatterPoint> getPoints() {
+ return _points;
+ }
+ public void addPoint(ScatterPoint point) {
+ _points.add(point);
+ }
+ private List<ScatterAngle> getScatterAngleList() {
+ List<ScatterAngle> scatters = new ArrayList<ScatterAngle>();
+ for(ScatterPoint p : _points) scatters.add(p._scatterAngle);
+ return scatters;
+ }
+
+ public ScatterPoint getScatterPoint(IDetectorElement detectorElement) {
+ for(ScatterPoint p : _points) {
+ if(p.getDet().equals(detectorElement)) {
+ return p;
+ }
+ }
+ return null;
+ }
+ }
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/NoiselessReadoutChip.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/NoiselessReadoutChip.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,318 @@
+/*
+ * Class BasicReadoutChip
+ */
+package org.hps.recon.tracking;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.recon.tracking.digitization.sisim.ReadoutChip;
+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
+ */
+ @Override
+ 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
+ */
+ @Override
+ 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
+ */
+ @Override
+ 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
+ */
+ @Override
+ 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/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/RunAlignment.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/RunAlignment.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,96 @@
+package org.hps.recon.tracking;
+
+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/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SVTBadChannelFilterDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SVTBadChannelFilterDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,45 @@
+package org.hps.recon.tracking;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.EventHeader.LCMetaData;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: SVTBadChannelFilterDriver.java,v 1.2 2012/08/29 21:02:46 meeg Exp $
+ */
+public class SVTBadChannelFilterDriver extends Driver {
+
+ private String rawTrackerHitCollection = "SVTRawTrackerHits";
+
+ @Override
+ public void process(EventHeader event) {
+ if (event.hasCollection(RawTrackerHit.class, rawTrackerHitCollection)) {
+ List<RawTrackerHit> hits = event.get(RawTrackerHit.class, rawTrackerHitCollection);
+ LCMetaData meta = event.getMetaData(hits);
+ Iterator<RawTrackerHit> i = hits.iterator();
+ while (i.hasNext()) {
+ RawTrackerHit hit = i.next();
+ hit.setMetaData(meta);
+ int strip = hit.getIdentifierFieldValue("strip");
+ SiSensor sensor = (SiSensor) hit.getDetectorElement();
+
+// System.out.format("module %d, layer %d, strip %d\n", hit.getIdentifierFieldValue("module"), hit.getIdentifierFieldValue("layer"), hit.getIdentifierFieldValue("strip"));
+ if (HPSSVTCalibrationConstants.isBadChannel(sensor, strip)) {
+ i.remove();
+ }
+
+ if (!sensor.getReadout().getHits(RawTrackerHit.class).isEmpty()) {
+ throw new RuntimeException(this.getClass().getSimpleName() + " must be run before any SVT readout drivers.");
+ }
+ }
+ }
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SVTRawTrackerHitThresholdDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SVTRawTrackerHitThresholdDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,80 @@
+package org.hps.recon.tracking;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+
+/**
+ *
+ * @author mgraham
+ */
+public class SVTRawTrackerHitThresholdDriver extends Driver {
+
+ private String rawTrackerHitCollectionName = "RawTrackerHitMaker_RawTrackerHits";
+ private String outputHitCollectionName = "RawTrackerHitsThreshold";
+ private String calibFileName = "foobar";
+ private String trackerName = "Tracker";
+ private Detector detector;
+ private List<SiSensor> sensors;
+ private double noiseThreshold = 3;
+ private int nhitsAboveNoise = 2;
+
+ public SVTRawTrackerHitThresholdDriver() {
+ }
+
+ public void setRawTrackerHitCollectionName(String rawTrackerHitCollectionName) {
+ this.rawTrackerHitCollectionName = rawTrackerHitCollectionName;
+ }
+
+ public void setOutputHitCollectionName(String outputHitCollectionName) {
+ this.outputHitCollectionName = outputHitCollectionName;
+ }
+
+ public void setCalibFileName(String calibFileName) {
+ this.calibFileName = calibFileName;
+ }
+
+ public void setNoiseThreshold(double thres){
+ this.noiseThreshold=thres;
+ }
+
+ public void setNhitsAboveNoise(int nhits){
+ this.nhitsAboveNoise=nhits;
+ }
+
+ protected void detectorChanged(Detector detector) {
+ }
+
+ public void process(EventHeader event) {
+ if (event.hasCollection(RawTrackerHit.class, rawTrackerHitCollectionName)) {
+ // Get RawTrackerHit collection from event.
+ List<RawTrackerHit> rawTrackerHits = event.get(RawTrackerHit.class, rawTrackerHitCollectionName);
+ List<RawTrackerHit> outputHits = new ArrayList<RawTrackerHit>();
+
+ // Increment strip hit count.
+ for (RawTrackerHit hit : rawTrackerHits) {
+ SiSensor sensor=(SiSensor) hit.getDetectorElement();
+ int strip=hit.getIdentifierFieldValue("strip");
+ short[] adcVal=hit.getADCValues();
+ double ped=HPSSVTCalibrationConstants.getPedestal(sensor, strip);
+ double noise=HPSSVTCalibrationConstants.getNoise(sensor, strip);
+ int nAbove=0;
+ for(int i=0;i<6;i++){
+ double pedSubNorm=(adcVal[i]-ped)/noise;
+ if(pedSubNorm>noiseThreshold)
+ nAbove++;
+ }
+ if(nAbove>=nhitsAboveNoise)
+ outputHits.add(hit);
+ }
+
+ event.put(outputHitCollectionName, outputHits, RawTrackerHit.class, 0);
+ }
+ }
+}
\ No newline at end of file
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SeedTracker.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SeedTracker.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,76 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+import java.util.List;
+
+import org.lcsim.recon.tracking.seedtracker.SeedStrategy;
+import org.lcsim.recon.tracking.seedtracker.SeedTrackFinder;
+
+/**
+ * Class extending lcsim version to allow extra flexibility
+ * @author Per Hansson Adrian <[log in to unmask]>
+ * @version $Id: SeedTracker.java,v 1.4 2013/11/07 03:54:58 phansson Exp $ $Date: 2013/11/07 03:54:58 $ $Author: phansson $
+ */
+public class SeedTracker extends org.lcsim.recon.tracking.seedtracker.SeedTracker {
+
+ public SeedTracker(List<SeedStrategy> strategylist) {
+ // use base class only if this constructor is called!
+ super(strategylist);
+ }
+
+ public SeedTracker(List<SeedStrategy> strategylist,boolean includeMS) {
+ super(strategylist);
+ initialize(strategylist, true, includeMS);
+ }
+
+ public SeedTracker(List<SeedStrategy> strategylist,boolean useHPSMaterialManager, boolean includeMS) {
+ super(strategylist);
+ initialize(strategylist, useHPSMaterialManager, includeMS);
+ }
+
+ private void initialize(List<SeedStrategy> strategylist,boolean useHPSMaterialManager, boolean includeMS) {
+
+ // Explicitly only replace the objects that might change to avoid getting the lcsim versions
+
+ // Instantiate the material manager for HPS, the helix fitter and seed track finder as tey depends on the material manager
+ if(useHPSMaterialManager) {
+ MaterialSupervisor materialSupervisor = new MaterialSupervisor(includeMS);
+ _materialmanager = materialSupervisor;
+ _helixfitter = new HelixFitter(materialSupervisor);
+ } else {
+ MaterialManager materialmanager = new MaterialManager(includeMS);
+ _materialmanager = materialmanager; //mess around with types here...
+ _helixfitter = new HelixFitter(materialmanager);
+ }
+ // Instantiate the helix finder since it depends on the material manager
+ _finder = new SeedTrackFinder(_hitmanager, _helixfitter);
+ }
+
+ /**
+ * Set to enable debug output
+ *
+ * @param debug switch
+ */
+ @Override
+ public void setDebug(boolean debug) {
+ super.setDebug(debug);
+ _materialmanager.setDebug(debug);
+ _helixfitter.setDebug(debug);
+ }
+
+ /**
+ * Set to enable the sectoring to use the sector bins in checking for consistent hits.
+ *
+ * @param applySectorBinning apply sector binning switch
+ */
+ public void setApplySectorBinning(boolean applySectorBinning) {
+ _finder.setApplySectorBinning(applySectorBinning);
+ _finder.getConfirmer().setApplySectorBinning(applySectorBinning);
+
+ }
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SimpleSvtReadout.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SimpleSvtReadout.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,425 @@
+package org.hps.recon.tracking;
+
+//--- java ---//
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.PriorityQueue;
+import java.util.Set;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants;
+import org.hps.conditions.deprecated.HPSSVTConstants;
+import org.hps.conditions.deprecated.SvtUtils;
+import org.hps.readout.ecal.ReadoutTimestamp;
+import org.hps.readout.ecal.TriggerableDriver;
+//--- lcsim ---//
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCRelation;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseLCRelation;
+import org.lcsim.event.base.BaseRawTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.util.ClockSingleton;
+import org.lcsim.hps.util.RandomGaussian;
+import org.lcsim.lcio.LCIOConstants;
+import org.lcsim.recon.tracking.digitization.sisim.CDFSiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeData;
+import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeDataCollection;
+import org.lcsim.recon.tracking.digitization.sisim.SiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
+
+/**
+ *
+ * @author Sho Uemura <[log in to unmask]>
+ * @version $Id: SimpleSvtReadout.java,v 1.19 2013/08/07 23:38:32 meeg Exp $
+ */
+public class SimpleSvtReadout extends TriggerableDriver {
+
+ private SimTrackerHitReadoutDriver readoutDriver = new SimTrackerHitReadoutDriver();
+ private SiSensorSim siSimulation = new CDFSiSensorSim();
+ private String outputCollection = "SVTRawTrackerHits";
+ private String relationCollection = "SVTTrueHitRelations";
+ private Map<SiSensor, PriorityQueue<StripHit>[]> hitMap = new HashMap<SiSensor, PriorityQueue<StripHit>[]>();
+ //readout period time offset in ns
+ private double readoutOffset = 0.0;
+ private double readoutLatency = 240.0;
+ private double pileupCutoff = 300.0;
+ private String readout = "TrackerHits";
+ private double timeOffset = 30.0;
+ private boolean noPileup = false;
+ private boolean addNoise = true;
+ //cut settings
+ private boolean enableThresholdCut = true;
+ private int samplesAboveThreshold = 3;
+ private double noiseThreshold = 2.0;
+ private boolean enablePileupCut = true;
+ private boolean dropBadChannels = true;
+
+ public SimpleSvtReadout() {
+ add(readoutDriver);
+ triggerDelay = 100.0;
+ }
+
+ public void setAddNoise(boolean addNoise) {
+ this.addNoise = addNoise;
+ }
+
+ public void setEnablePileupCut(boolean enablePileupCut) {
+ this.enablePileupCut = enablePileupCut;
+ }
+
+ public void setEnableThresholdCut(boolean enableThresholdCut) {
+ this.enableThresholdCut = enableThresholdCut;
+ }
+
+ public void setNoiseThreshold(double noiseThreshold) {
+ this.noiseThreshold = noiseThreshold;
+ }
+
+ public void setSamplesAboveThreshold(int samplesAboveThreshold) {
+ this.samplesAboveThreshold = samplesAboveThreshold;
+ }
+
+ public void setNoPileup(boolean noPileup) {
+ this.noPileup = noPileup;
+ }
+
+ public void setDropBadChannels(boolean dropBadChannels) {
+ this.dropBadChannels = dropBadChannels;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void detectorChanged(Detector detector) {
+ super.detectorChanged(detector);
+
+ String[] readouts = {readout};
+ readoutDriver.setCollections(readouts);
+
+ if (!noPileup) {
+ for (SiSensor sensor : SvtUtils.getInstance().getSensors()) {
+ PriorityQueue<StripHit>[] hitQueues = new PriorityQueue[HPSSVTConstants.TOTAL_STRIPS_PER_SENSOR];
+ hitMap.put(sensor, hitQueues);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void process(EventHeader event) {
+ super.process(event);
+
+ List<StripHit> stripHits = doSiSimulation();
+
+ if (!noPileup) {
+ for (StripHit stripHit : stripHits) {
+ SiSensor sensor = stripHit.sensor;
+ int channel = stripHit.channel;
+
+ PriorityQueue<StripHit>[] hitQueues = hitMap.get(sensor);
+ if (hitQueues[channel] == null) {
+ hitQueues[channel] = new PriorityQueue<StripHit>();
+ }
+ hitQueues[channel].add(stripHit);
+ }
+
+ // dump stale hits
+ for (SiSensor sensor : SvtUtils.getInstance().getSensors()) {
+ PriorityQueue<StripHit>[] hitQueues = hitMap.get(sensor);
+ for (int i = 0; i < hitQueues.length; i++) {
+ if (hitQueues[i] != null) {
+ while (!hitQueues[i].isEmpty() && hitQueues[i].peek().time < ClockSingleton.getTime() - (readoutLatency + pileupCutoff)) {
+// System.out.format("Time %f: Dump stale hit with time %f\n",ClockSingleton.getTime(),hitQueues[i].peek().time);
+ hitQueues[i].poll();
+ }
+ if (hitQueues[i].isEmpty()) {
+ hitQueues[i] = null;
+ }
+ }
+ }
+ }
+
+ // If an ECal trigger is received, make hits from pipelines
+ checkTrigger(event);
+ } else {
+ // Create a list to hold the analog data
+ List<RawTrackerHit> hits = new ArrayList<RawTrackerHit>();
+
+ for (StripHit stripHit : stripHits) {
+ SiSensor sensor = stripHit.sensor;
+ int channel = stripHit.channel;
+ double amplitude = stripHit.amplitude;
+ short[] samples = new short[6];
+
+ double[] signal = new double[6];
+ for (int i = 0; i < 6; i++) {
+ signal[i] = HPSSVTCalibrationConstants.getPedestal(sensor, channel);
+ }
+ if (addNoise) {
+ addNoise(sensor, channel, signal);
+ }
+
+ for (int i = 0; i < 6; i++) {
+ double time = i * HPSSVTConstants.SAMPLING_INTERVAL - timeOffset;
+ signal[i] += amplitude * pulseAmplitude(time, HPSSVTCalibrationConstants.getTShaping(sensor, channel));
+// signal[i] += amplitude * pulseAmplitude(time, HPSSVTCalibrationConstants.getTShaping(sensor, channel)) + HPSSVTCalibrationConstants.getPedestal(sensor, channel);
+ samples[i] = (short) Math.round(signal[i]);
+ }
+
+ long cell_id = SvtUtils.makeCellID(sensor, channel);
+
+ RawTrackerHit hit = new BaseRawTrackerHit(0, cell_id, samples, new ArrayList<SimTrackerHit>(stripHit.simHits), sensor);
+// System.out.println("Making RTH");
+ if (readoutCuts(hit)) {
+// System.out.println("RTH passed cuts");
+ hits.add(hit);
+ }
+ }
+
+ int flags = 1 << LCIOConstants.TRAWBIT_ID1;
+// flags += 1 << LCIOConstants.RTHBIT_HITS;
+ event.put(outputCollection, hits, RawTrackerHit.class, flags, readout);
+// System.out.println("Made " + hits.size() + " RawTrackerHits");
+ }
+ }
+
+ private List<StripHit> doSiSimulation() {
+ List<StripHit> stripHits = new ArrayList<StripHit>();
+ for (SiSensor sensor : SvtUtils.getInstance().getSensors()) {
+
+ // Set the sensor to be used in the charge deposition simulation
+ siSimulation.setSensor(sensor);
+
+ // Perform the charge deposition simulation
+ Map<ChargeCarrier, SiElectrodeDataCollection> electrodeDataMap = siSimulation.computeElectrodeData();
+
+ for (ChargeCarrier carrier : ChargeCarrier.values()) {
+
+ // If the sensor is capable of collecting the given charge carrier
+ // then obtain the electrode data for the sensor
+ if (sensor.hasElectrodesOnSide(carrier)) {
+
+ SiElectrodeDataCollection electrodeDataCol = electrodeDataMap.get(carrier);
+
+ // If there is no electrode data available create a new instance of electrode data
+ if (electrodeDataCol == null) {
+ electrodeDataCol = new SiElectrodeDataCollection();
+ }
+
+ // Loop over all sensor channels
+ for (Integer channel : electrodeDataCol.keySet()) {
+
+ // Get the electrode data for this channel
+ SiElectrodeData electrodeData = electrodeDataCol.get(channel);
+ Set<SimTrackerHit> simHits = electrodeData.getSimulatedHits();
+
+ // compute hit time as the unweighted average of SimTrackerHit times; this is dumb but okay since there's generally only one SimTrackerHit
+ double time = 0.0;
+ for (SimTrackerHit hit : simHits) {
+ time += hit.getTime();
+ }
+ time /= simHits.size();
+ time += ClockSingleton.getTime();
+
+ // Get the charge in units of electrons
+ double charge = electrodeData.getCharge();
+
+ double resistorValue = 100; // Ohms
+ double inputStageGain = 1.5;
+ double amplitude = (charge / HPSSVTConstants.MIP) * resistorValue * inputStageGain * Math.pow(2, 14) / 2000;
+
+ stripHits.add(new StripHit(sensor, channel, amplitude, time, simHits));
+ }
+ }
+ }
+ // Clear the sensors of all deposited charge
+ siSimulation.clearReadout();
+ }
+ return stripHits;
+ }
+
+ private void addNoise(SiSensor sensor, int channel, double[] signal) {
+ double noise = HPSSVTCalibrationConstants.getNoise(sensor, channel);
+ for (int i = 0; i < 6; i++) {
+ signal[i] += RandomGaussian.getGaussian(0, noise);
+ }
+ }
+
+ private boolean readoutCuts(RawTrackerHit hit) {
+ if (enableThresholdCut && !samplesAboveThreshold(hit)) {
+// System.out.println("Failed threshold cut");
+ return false;
+ }
+ if (enablePileupCut && !pileupCut(hit)) {
+// System.out.println("Failed pileup cut");
+ return false;
+ }
+ if (dropBadChannels && !badChannelCut(hit)) {
+// System.out.println("Failed bad channel cut");
+ return false;
+ }
+ return true;
+ }
+
+ private boolean badChannelCut(RawTrackerHit hit) {
+ SiSensor sensor = (SiSensor) hit.getDetectorElement();
+ int channel = hit.getIdentifierFieldValue("strip");
+ return !HPSSVTCalibrationConstants.isBadChannel(sensor, channel);
+ }
+
+ private boolean pileupCut(RawTrackerHit hit) {
+ short[] samples = hit.getADCValues();
+ return (samples[2] > samples[1] || samples[3] > samples[2]);
+ }
+
+ private boolean samplesAboveThreshold(RawTrackerHit hit) {
+ SiSensor sensor = (SiSensor) hit.getDetectorElement();
+ int channel = hit.getIdentifierFieldValue("strip");
+ HPSSVTCalibrationConstants.getChannelConstants(sensor, channel);
+ double pedestal = HPSSVTCalibrationConstants.getPedestal(sensor, channel);
+ double noise = HPSSVTCalibrationConstants.getNoise(sensor, channel);
+ int count = 0;
+ short[] samples = hit.getADCValues();
+ for (int i = 0; i < samples.length; i++) {
+// System.out.format("%d, %d\n", samples[i] - pedestal, noise * 3.0);
+ if (samples[i] - pedestal > noise * noiseThreshold) {
+ count++;
+ }
+ }
+ return count >= samplesAboveThreshold;
+ }
+
+ @Override
+ protected void processTrigger(EventHeader event) {
+ if (noPileup) {
+ return;
+ }
+// System.out.println("Got trigger");
+
+ // Create a list to hold the analog data
+ List<RawTrackerHit> hits = new ArrayList<RawTrackerHit>();
+ List<LCRelation> trueHitRelations = new ArrayList<LCRelation>();
+ // Calculate time of first sample
+ double firstSample = Math.floor((ClockSingleton.getTime() - readoutLatency - readoutOffset) / HPSSVTConstants.SAMPLING_INTERVAL) * HPSSVTConstants.SAMPLING_INTERVAL + readoutOffset;
+
+ for (SiSensor sensor : SvtUtils.getInstance().getSensors()) {
+ PriorityQueue<StripHit>[] hitQueues = hitMap.get(sensor);
+ for (int channel = 0; channel < hitQueues.length; channel++) {
+ if (!addNoise && (hitQueues[channel] == null || hitQueues[channel].isEmpty())) {
+ continue;
+ }
+ double[] signal = new double[6];
+ for (int i = 0; i < 6; i++) {
+ signal[i] = HPSSVTCalibrationConstants.getPedestal(sensor, channel);
+ }
+ if (addNoise) {
+ addNoise(sensor, channel, signal);
+ }
+
+ List<SimTrackerHit> simHits = new ArrayList<SimTrackerHit>();
+
+ if (hitQueues[channel] != null) {
+ for (StripHit hit : hitQueues[channel]) {
+ double totalContrib = 0;
+ for (int i = 0; i < 6; i++) {
+ double sampleTime = firstSample + i * HPSSVTConstants.SAMPLING_INTERVAL;
+ double signalAtTime = hit.amplitude * pulseAmplitude(sampleTime - hit.time, HPSSVTCalibrationConstants.getTShaping(sensor, channel));
+ totalContrib += signalAtTime;
+ signal[i] += signalAtTime;
+// System.out.format("new value of signal[%d] = %f\n", i, signal[i]);
+ }
+ if (totalContrib > 4.0 * HPSSVTCalibrationConstants.getNoise(sensor, channel)) {
+// System.out.format("adding %d simHits\n", hit.simHits.size());
+ simHits.addAll(hit.simHits);
+ }
+ }
+ }
+
+ short[] samples = new short[6];
+ for (int i = 0; i < 6; i++) {
+ samples[i] = (short) Math.round(signal[i]);
+ }
+// if (hitQueues[channel] != null && !hitQueues[channel].isEmpty()) {
+// for (int i = 0; i < 6; i++) {
+// System.out.format("samples[%d] = %d\n", i, samples[i]);
+// }
+// }
+ long cell_id = SvtUtils.makeCellID(sensor, channel);
+ RawTrackerHit hit = new BaseRawTrackerHit(0, cell_id, samples, simHits, sensor);
+ if (readoutCuts(hit)) {
+ hits.add(hit);
+// System.out.format("simHits: %d\n", simHits.size());
+ for (SimTrackerHit simHit : hit.getSimTrackerHits()) {
+ LCRelation hitRelation = new BaseLCRelation(hit, simHit);
+ trueHitRelations.add(hitRelation);
+ }
+ }
+ }
+ }
+
+ int flags = 1 << LCIOConstants.TRAWBIT_ID1;
+// flags += 1 << LCIOConstants.RTHBIT_HITS;
+ event.put(outputCollection, hits, RawTrackerHit.class, flags, readout);
+ event.put(relationCollection, trueHitRelations, LCRelation.class, 0);
+ System.out.println("Made " + hits.size() + " RawTrackerHits");
+ System.out.println("Made " + trueHitRelations.size() + " LCRelations");
+ }
+
+ @Override
+ public double readoutDeltaT() {
+ double triggerTime = ClockSingleton.getTime() + triggerDelay;
+// int cycle = (int) Math.floor((triggerTime - readoutOffset + ClockSingleton.getDt()) / Apv25Constants.SAMPLING_INTERVAL);
+ // Calculate time of first sample
+ double firstSample = Math.floor((triggerTime - readoutLatency - readoutOffset) / HPSSVTConstants.SAMPLING_INTERVAL) * HPSSVTConstants.SAMPLING_INTERVAL + readoutOffset;
+
+ return firstSample;
+ }
+
+ private class StripHit implements Comparable {
+
+ SiSensor sensor;
+ int channel;
+ double amplitude;
+ double time;
+ Set<SimTrackerHit> simHits;
+
+ public StripHit(SiSensor sensor, int channel, double amplitude, double time, Set<SimTrackerHit> simHits) {
+ this.sensor = sensor;
+ this.channel = channel;
+ this.amplitude = amplitude;
+ this.time = time;
+ this.simHits = simHits;
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ double deltaT = time - ((StripHit) o).time;
+ if (deltaT > 0) {
+ return 1;
+ } else if (deltaT < 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ private double pulseAmplitude(double time, double tp) {
+ if (time <= 0.0) {
+ return 0.0;
+ }
+ return (time / tp) * Math.exp(1.0 - time / tp);
+ }
+
+ public int getTimestampType() {
+ return ReadoutTimestamp.SYSTEM_TRACKER;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SimpleTrackerDigiDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/SimpleTrackerDigiDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,70 @@
+package org.hps.recon.tracking;
+
+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/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/StraightLineTrack.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/StraightLineTrack.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,193 @@
+package org.hps.recon.tracking;
+
+import hep.physics.matrix.SymmetricMatrix;
+
+/**
+ * Encapsulate position, direction, and covariance matrix for a straight-line track
+ *
+ * @author Richard Partridge
+ */
+public class StraightLineTrack {
+
+ public static int y0Index = 0;
+ public static int z0Index = 1;
+ public static int dydxIndex = 2;
+ public static int dzdxIndex = 3;
+ private double _x0;
+ private double _y0;
+ private double _z0;
+ private double _dydx;
+ private double _dzdx;
+ private SymmetricMatrix _cov;
+ private double[] _poca = {0, 0, 0};
+ private double[] _yzT = {0, 0};
+
+ /**
+ * Fully qualified constructor for the StraightLineTrack class. A StraightLineTrack
+ * is specified by providing a position and the direction derivatives dydx and dzdx used
+ * in the vertex fitting. It is assumed that the track is traveling in the +x direction
+ * (i.e., from the field-free region into the magnetized region).
+ *
+ * @param x0 x coordinate of the reference plane
+ * @param y0 y coordinate at the reference plane
+ * @param z0 z coordinate at the reference plane
+ * @param dydx dy/dx for the track
+ * @param dzdx dz/dx for the track
+ * @param cov covariance matrix for the track parameters (y0, z0, dy/dx, and dz/dx)
+ */
+ public StraightLineTrack(double x0, double y0, double z0, double dydx, double dzdx, SymmetricMatrix cov) {
+ _x0 = x0;
+ _y0 = y0;
+ _z0 = z0;
+ _dydx = dydx;
+ _dzdx = dzdx;
+ _cov = cov;
+ calculatePoca();
+ calculateTargetYZ();
+ }
+
+ /**
+ * Return the x coordinate of the reference plane.
+ *
+ * @return x coordinate of the reference plane
+ */
+ public double x0() {
+ return _x0;
+ }
+
+ /**
+ * Return the y coordinate at the reference plane.
+ *
+ * @return y coordinate
+ */
+ public double y0() {
+ return _y0;
+ }
+
+ /**
+ * Return the z coordinate at the reference plane.
+ *
+ * @return z coordinate
+ */
+ public double z0() {
+ return _z0;
+ }
+
+ /**
+ * Return the direction derivative dy/dx.
+ *
+ * @return dy/dx
+ */
+ public double dydx() {
+ return _dydx;
+ }
+
+ /**
+ * Return the direction derivative dz/dx.
+ *
+ * @return dz/dx
+ */
+ public double dzdx() {
+ return _dzdx;
+ }
+
+ /**
+ * Return the xPoca .
+ *
+ * @return xPoca
+ */
+ public double xPoca() {
+ return _poca[0];
+ }
+
+ /**
+ * Return the yPoca .
+ *
+ * @return yPoca
+ */
+ public double yPoca() {
+ return _poca[1];
+ }
+
+ /**
+ * Return the zPoca .
+ *
+ * @return zPoca
+ */
+ public double zPoca() {
+ return _poca[2];
+ }
+
+ /**
+ * Return the Doca .
+ *
+ * @return Doca
+ */
+ public double Doca() {
+ return Math.sqrt(_poca[1] * _poca[1] + _poca[2] * _poca[2]);
+ }
+
+ /**
+ * Return the Poca .
+ *
+ * @return Poca
+ */
+ public double[] Poca() {
+ return _poca;
+ }
+
+ /**
+ * Return the Y and Z positions of the track at X=0 (target).
+ *
+ * @return yzT
+ */
+ public double[] TargetYZ() {
+ return _yzT;
+ }
+
+ public double[] getYZAtX(double xVal){
+ return calculateYZAtX(xVal);
+ }
+
+ /**
+ * Return the covariance matrix.
+ *
+ * @return covariance matrix
+ */
+ public SymmetricMatrix cov() {
+ return _cov;
+ }
+
+ // mg--for now just calculate the simple POCA (to the x-axis)...no errors
+ private void calculatePoca() {
+ _poca[0] = _x0-(_y0 * _dydx + _z0 * _dzdx) / (_dydx * _dydx + _dzdx * _dzdx);
+ _poca[1] = _y0 + _dydx * (_poca[0]-_x0);
+ _poca[2] = _z0 + _dzdx * (_poca[0]-_x0);
+ }
+
+ private void calculateTargetYZ() {
+ _yzT[0] = _y0 - _x0 * _dydx;
+ _yzT[1] = _z0 - _x0 * _dzdx;
+ }
+
+ private double[] calculateYZAtX(double xVal) {
+ double[] yzAtX={-66,-66};
+ if(xVal>_x0) //_x0 is where the field region starts...if xVal is bigger than this, need to get position on helix
+ return yzAtX;
+ yzAtX[0] = _y0 + (xVal-_x0) * _dydx;
+ yzAtX[1] = _z0 + (xVal-_x0) * _dzdx;
+ return yzAtX;
+ }
+
+ public double calculateXAtZEquals0() {
+ return _x0-_z0/_dzdx;
+ }
+
+ public double[] calculateXYAtZ(double zVal) {
+ double[] xyAtZ = {-99999,-99999};
+ xyAtZ[0] = (zVal-_z0)/(_dzdx)+_x0;
+ xyAtZ[1] = this.calculateYZAtX(xyAtZ[0])[0];
+ return xyAtZ;
+ }
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackAnalysis.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackAnalysis.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,298 @@
+/*
+ * TrackAnalysis.java
+ *
+ * Created on October 16, 2008, 6:09 PM
+ *
+ */
+package org.hps.recon.tracking;
+
+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;
+import java.util.Set;
+
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RelationalTable;
+import org.lcsim.event.Track;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrack2DHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackCross;
+import org.lcsim.fit.helicaltrack.HelicalTrackHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+
+/**
+ *
+ * @author Richard Partridge & Matt Graham
+ */
+public class TrackAnalysis {
+
+ private enum HelixPar {
+ Curvature, Phi0, DCA, Z0, Slope
+ };
+ private MCParticle _mcp = null;
+ private int _nhits;
+ private int _nbadhits;
+ private double _purity;
+ private MCParticle _mcpNew = null;
+ private int _nhitsNew;
+ private int _nbadhitsNew;
+ private double _purityNew;
+ private int _nAxialhits;
+ private int _nZhits;
+ private int _nbadAxialhits;
+ private int _nbadZhits;
+ private boolean _hasLayerOne;
+ List<Integer> badHitList = new ArrayList();
+ List<Integer> sharedHitList = new ArrayList();
+ List<Integer> trackLayerList = new ArrayList();
+ Map<MCParticle, HelicalTrackCross> badhits = new HashMap<MCParticle, HelicalTrackCross>();
+ private int[] _nMCHitsPerLayer={0,0,0,0,0,0,0,0,0,0,0,0};
+ private int[] _nStripHitsPerLayer={0,0,0,0,0,0,0,0,0,0,0,0};
+ Map<Integer, Hep3Vector> _hitLocationPerLayer = new HashMap<Integer,Hep3Vector>();
+
+ /** Creates a new instance of TrackAnalysis */
+ public TrackAnalysis(Track trk, RelationalTable hittomc) {
+
+ // 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>();
+ Map<MCParticle, Integer> mcmapAll = new HashMap<MCParticle, Integer>();
+ Map<MCParticle, Integer> mcmapAxial = new HashMap<MCParticle, Integer>();
+ Map<MCParticle, Integer> mcmapZ = new HashMap<MCParticle, Integer>();
+ _hasLayerOne = false;
+ // Loop over the hits on the track and make sure we have HelicalTrackHits (which contain the MC particle)
+ for (TrackerHit hit : trk.getTrackerHits()) {
+ // get the set of MCParticles associated with this hit and update the hit count for each MCParticle
+ Set<MCParticle> mclist = hittomc.allFrom(hit);
+ for (MCParticle mcp : mclist) {
+ Integer mchits = 0;
+ if (mcmap.containsKey(mcp))
+ mchits = mcmap.get(mcp);
+ mchits++;
+ mcmap.put(mcp, mchits);
+ }
+
+ BasicHep3Vector axial = new BasicHep3Vector();
+ axial.setV(0, 1, 0);
+ HelicalTrackHit htc = (HelicalTrackHit) hit;
+ if (hit instanceof HelicalTrackCross) {
+ HelicalTrackCross cross = (HelicalTrackCross) hit;
+ List<HelicalTrackStrip> clusterlist = cross.getStrips();
+
+ for (HelicalTrackStrip cl : clusterlist) {
+ int layer = cl.layer();
+ if (layer == 1) _hasLayerOne = true;
+
+ _nStripHitsPerLayer[layer - 1] = cl.rawhits().size();
+ _hitLocationPerLayer.put(layer,clusterPosition(cl));
+ _nhitsNew++;
+ double axdotu = VecOp.dot(cl.u(), axial);
+ boolean isAxial = false;
+ if (axdotu > 0.5) {
+ isAxial = true;
+ _nAxialhits++;
+ } else _nZhits++;
+ List<MCParticle> mcPartList = cl.MCParticles();
+ _nMCHitsPerLayer[layer-1] = mcPartList.size();
+ for (MCParticle mcp : mcPartList) {
+ Integer mchits = 0;
+ if (mcmapAll.containsKey(mcp))
+ mchits = mcmapAll.get(mcp);
+ mchits++;
+ mcmapAll.put(mcp, mchits);
+ if (isAxial) {
+ Integer mchitsAxial = 0;
+ if (mcmapAxial.containsKey(mcp))
+ mchitsAxial = mcmapAxial.get(mcp);
+ mchitsAxial++;
+ mcmapAxial.put(mcp, mchitsAxial);
+ } else {
+ Integer mchitsZ = 0;
+ if (mcmapZ.containsKey(mcp))
+ mchitsZ = mcmapZ.get(mcp);
+ mchitsZ++;
+ mcmapZ.put(mcp, mchitsZ);
+ }
+ }
+ }
+ } else {
+ _nhitsNew++;
+ _nAxialhits++;
+ HelicalTrack2DHit hit2d = (HelicalTrack2DHit) hit;
+ List<MCParticle> mcPartList = hit2d.getMCParticles();
+ //assume that lone hits are all axial
+ boolean isAxial = true;
+ for (MCParticle mcp : mcPartList) {
+ Integer mchits = 0;
+ if (mcmapAll.containsKey(mcp))
+ mchits = mcmapAll.get(mcp);
+ mchits++;
+ mcmapAll.put(mcp, mchits);
+ Integer mchitsAxial = 0;
+ if (mcmapAxial.containsKey(mcp))
+ mchitsAxial = mcmapAxial.get(mcp);
+ mchitsAxial++;
+ mcmapAxial.put(mcp, mchitsAxial);
+ }
+ }
+ }
+
+ // 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;
+
+
+//single strip layer accounting.
+ int nbestAll = 0;
+ MCParticle mcbestAll = null;
+ for (MCParticle mcp : mcmapAll.keySet()) {
+ int count = mcmapAll.get(mcp);
+ if (count > nbestAll) {
+ nbestAll = count;
+ mcbestAll = mcp;
+ }
+ }
+
+ if (nbestAll > 0)
+ _mcpNew = mcbestAll;
+ _purityNew = (double) nbestAll / (double) _nhitsNew;
+ _nbadhitsNew = _nhitsNew - nbestAll;
+
+ for (TrackerHit hit : trk.getTrackerHits()) {
+ HelicalTrackHit htc = (HelicalTrackHit) hit;
+ if (hit instanceof HelicalTrackCross) {
+ HelicalTrackCross cross = (HelicalTrackCross) hit;
+ List<HelicalTrackStrip> clusterlist = cross.getStrips();
+ for (HelicalTrackStrip cl : clusterlist){
+ trackLayerList.add(cl.layer());
+ if (!(cl.MCParticles().contains(_mcpNew))) {
+ badHitList.add(cl.layer());
+ badhits.put(_mcpNew, cross);
+ }
+ if(cl.MCParticles().size()>1)
+ sharedHitList.add(cl.layer());
+ }
+ }
+ }
+
+
+
+ if (_nAxialhits > 0)
+ if (mcmapAxial.containsKey(_mcpNew))
+ _nbadAxialhits = _nAxialhits - mcmapAxial.get(_mcpNew);
+ else _nbadAxialhits = _nAxialhits;
+ if (_nZhits > 0)
+ if (mcmapZ.containsKey(_mcpNew))
+ _nbadZhits = _nZhits - mcmapZ.get(_mcpNew);
+ else _nbadZhits = _nZhits;
+
+ }
+
+ public Hep3Vector clusterPosition(HelicalTrackStrip cl) {
+ Hep3Vector corigin = cl.origin();
+ Hep3Vector u = cl.u();
+ double umeas = cl.umeas();
+ Hep3Vector uvec = VecOp.mult(umeas, u);
+ return VecOp.add(corigin, uvec);
+
+ }
+
+ public MCParticle getMCParticle() {
+ return _mcp;
+ }
+
+ public int getNHits() {
+ return _nhits;
+ }
+
+ public int getNBadHits() {
+ return _nbadhits;
+ }
+
+ public double getPurity() {
+ return _purity;
+ }
+
+ public MCParticle getMCParticleNew() {
+ return _mcpNew;
+ }
+
+ public int getNHitsNew() {
+ return _nhitsNew;
+ }
+
+ public int getNAxialHits() {
+ return _nAxialhits;
+ }
+
+ public int getNZHits() {
+ return _nZhits;
+ }
+
+ public int getNBadHitsNew() {
+ return _nbadhitsNew;
+ }
+
+ public double getPurityNew() {
+ return _purityNew;
+ }
+
+ public int getNBadAxialHits() {
+ return _nbadAxialhits;
+ }
+
+ public int getNBadZHits() {
+ return _nbadZhits;
+ }
+
+ public boolean hasLayerOne() {
+ return _hasLayerOne;
+ }
+
+ public Hep3Vector getClusterPosition(Integer layer) {
+ return _hitLocationPerLayer.get(layer);
+ }
+
+ public int getNumberOfMCParticles(int layer) {
+ return _nMCHitsPerLayer[layer - 1];
+ }
+
+ public int getNumberOfStripHits(int layer) {
+ return _nStripHitsPerLayer[layer - 1];
+ }
+
+ public List<Integer> getBadHitList() {
+ return badHitList;
+ }
+ public List<Integer> getSharedHitList() {
+ return sharedHitList;
+ }
+
+ public List<Integer> getTrackLayerList() {
+ return trackLayerList;
+ }
+
+ public Map<MCParticle, HelicalTrackCross> getBadHits() {
+ return badhits;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackUtils.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,735 @@
+package org.hps.recon.tracking;
+
+//--- hep ---//
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Matrix;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.SpacePoint;
+import hep.physics.vec.VecOp;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.hps.conditions.deprecated.BeamlineConstants;
+import org.hps.conditions.deprecated.SvtUtils;
+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.event.MCParticle;
+import org.lcsim.event.RawTrackerHit;
+//--- org.lcsim ---//
+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.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.fit.helicaltrack.HelixParamCalculator;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+import org.lcsim.fit.helicaltrack.HitUtils;
+import org.lcsim.fit.helicaltrack.MultipleScatter;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+import org.lcsim.util.swim.Helix;
+
+/**
+ * Assorted helper functions for the track and helix objects in lcsim.
+ * Re-use as much of HelixUtils as possible.
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: TrackUtils.java,v 1.34 2013/11/14 01:50:43 phansson Exp $
+ * TODO: Switch to tracking/LCsim coordinates for the extrapolation output!
+ */
+
+public class TrackUtils {
+
+ /**
+ * Private constructor to make class static only
+ */
+ private TrackUtils(){
+ }
+
+ /**
+ * Extrapolate track to a position along the x-axis. Turn the track into a helix object in order to use HelixUtils.
+ * @param track
+ * @param x
+ * @return
+ */
+ public static Hep3Vector extrapolateHelixToXPlane(Track track, double x){
+ return extrapolateHelixToXPlane(getHTF(track),x);
+ }
+
+ /**
+ * Extrapolate helix to a position along the x-axis. Re-use HelixUtils.
+ * @param track
+ * @param x
+ * @return
+ */
+ public static Hep3Vector extrapolateHelixToXPlane(HelicalTrackFit htf, double x){
+ double s = HelixUtils.PathToXPlane(htf, x, 0., 0).get(0);
+ return HelixUtils.PointOnHelix(htf, s);
+ }
+
+ // ==========================================================================
+ // Helper functions for track parameters and commonly used derived variables
+
+ public static double getPhi(Track track, Hep3Vector position){
+ double x = Math.sin(getPhi0(track)) - (1/getR(track))*(position.x() - getX0(track));
+ double y = Math.cos(getPhi0(track)) + (1/getR(track))*(position.y() - getY0(track));
+ return Math.atan2(x, y);
+ }
+ public static double getX0(Track track) {
+ return -1*getDoca(track)*Math.sin(getPhi0(track));
+ }
+ public static double getR(Track track) {
+ return 1.0/track.getTrackStates().get(0).getOmega();
+ }
+ public static double getY0(Track track) {
+ return getDoca(track)*Math.cos(getPhi0(track));
+ }
+ public static double getDoca(Track track) {
+ return track.getTrackStates().get(0).getD0();
+ }
+ public static double getPhi0(Track track) {
+ return track.getTrackStates().get(0).getPhi();
+ }
+ public static double getZ0(Track track) {
+ return track.getTrackStates().get(0).getZ0();
+ }
+ public static double getTanLambda(Track track) {
+ return track.getTrackStates().get(0).getTanLambda();
+ }
+ public static double getSinTheta(Track track){
+ return 1/Math.sqrt(1 + Math.pow(getTanLambda(track), 2));
+ }
+ public static double getCosTheta(Track track){
+ return getTanLambda(track)/Math.sqrt(1 + Math.pow(getTanLambda(track), 2));
+ }
+ // ==========================================================================
+
+
+
+ /**
+ * Calculate the point of interception between the helix and a plane in space. Uses an iterative procedure.
+ * @param helfit - helix
+ * @param unit_vec_normal_to_plane - unit vector normal to the plane
+ * @param point_on_plane - point on the plane
+ * @param bfield - magnetic field value
+ * @return point at intercept
+ */
+ public static Hep3Vector getHelixPlaneIntercept(HelicalTrackFit helfit, Hep3Vector unit_vec_normal_to_plane,Hep3Vector point_on_plane, double bfield) {
+ boolean debug = false;
+ boolean flipBfield = true; // be careful
+ Hep3Vector B = new BasicHep3Vector(0,0,flipBfield?-1:1);
+ WTrack wtrack = new WTrack(helfit,bfield,flipBfield); //
+ if(debug) System.out.printf("getHelixPlaneIntercept:find intercept between plane defined by point on plane %s, unit vec %s, bfield %.3f, h=%s and WTrack \n%s \n",point_on_plane.toString(),unit_vec_normal_to_plane.toString(), bfield, B.toString(),wtrack.toString());
+ Hep3Vector intercept_point = wtrack.getHelixAndPlaneIntercept(point_on_plane, unit_vec_normal_to_plane, B);
+ if(debug) System.out.printf("getHelixPlaneIntercept: found intercept point at %s\n",intercept_point.toString());
+ return intercept_point;
+ }
+
+ /**
+ * Calculate the point of interception between the helix and a plane in space. Uses an iterative procedure.
+ * @param helfit - helix
+ * @param strip - strip cluster that will define the plane
+ * @param bfield - magnetic field value
+ * @return point at intercept
+ */
+ public static Hep3Vector getHelixPlaneIntercept(HelicalTrackFit helfit, HelicalTrackStrip strip, double bfield) {
+ Hep3Vector point_on_plane = strip.origin();
+ Hep3Vector unit_vec_normal_to_plane = VecOp.cross(strip.u(),strip.v());//strip.w();
+ Hep3Vector intercept_point = getHelixPlaneIntercept(helfit, unit_vec_normal_to_plane, point_on_plane, bfield);
+ return intercept_point;
+ }
+
+
+ /*
+ * Calculates the point on the helix in the x-y plane at the intercept with plane
+ * The normal of the plane is in the same x-y plane as the circle.
+ *
+ * @param helix
+ * @param vector normal to plane
+ * @param origin of plane
+ * @return point in the x-y plane of the intercept
+ *
+ */
+ public Hep3Vector getHelixXPlaneIntercept(HelicalTrackFit helix, Hep3Vector w, Hep3Vector origin) {
+ throw new RuntimeException("this function is not working properly; don't use it");
+
+ // FInd the intercept point x_int,y_int, between the circle and sensor, which becomes a line in the x-y plane in this case.
+ // y_int = k*x_int + m
+ // R^2 = (y_int-y_c)^2 + (x_int-x_c)^2
+ // solve for x_int
+
+ }
+
+
+
+
+ /**
+ * Get position of a track extrapolated to the HARP in the HPS test run 2012
+ * @param track
+ * @return position at HARP
+ */
+ public static Hep3Vector getTrackPositionAtHarp(Track track){
+ return extrapolateTrack(track, BeamlineConstants.HARP_POSITION_TESTRUN);
+ }
+
+ /**
+ * Get position of a track extrapolated to the ECAL face in the HPS test run 2012
+ * @param track
+ * @return position at ECAL
+ */
+ public static Hep3Vector getTrackPositionAtEcal(Track track){
+ return extrapolateTrack(track, BeamlineConstants.ECAL_FACE_TESTRUN);
+ }
+
+ /**
+ * Extrapolate track to given position.
+ * @param helix - to be extrapolated
+ * @param track - position along the x-axis of the helix in lcsim coordiantes
+ * @return
+ */
+ public static Hep3Vector extrapolateTrack(Track track, double z){
+
+ Hep3Vector trackPosition = null;
+ double dz = 0;
+ if(z >= BeamlineConstants.DIPOLE_EDGE_TESTRUN){
+ trackPosition = extrapolateHelixToXPlane(track, BeamlineConstants.DIPOLE_EDGE_TESTRUN);
+ dz = z - BeamlineConstants.DIPOLE_EDGE_TESTRUN;
+ } else if(z <= BeamlineConstants.DIPOLE_EDGELOW_TESTRUN){
+ trackPosition = extrapolateHelixToXPlane(track, BeamlineConstants.DIPOLE_EDGELOW_TESTRUN);
+ dz = z - trackPosition.x();
+ } else {
+ Hep3Vector detVecTracking = extrapolateHelixToXPlane(track,z);
+ //System.out.printf("detVec %s\n", detVecTracking.toString());
+ return new BasicHep3Vector(detVecTracking.y(),detVecTracking.z(),detVecTracking.x());
+ }
+
+ // Get the track azimuthal angle
+ double phi = getPhi(track, trackPosition);
+
+ // Find the distance to the point of interest
+ double r = dz/(getSinTheta(track)*Math.cos(phi));
+ double dx = r*getSinTheta(track)*Math.sin(phi);
+ double dy = r*getCosTheta(track);
+
+ // Find the track position at the point of interest
+ double x = trackPosition.y() + dx;
+ double y = trackPosition.z() + dy;
+
+ return new BasicHep3Vector(x, y, z);
+ }
+
+ /**
+ * Extrapolate helix to given position
+ * @param helix - to be extrapolated
+ * @param z - position along the x-axis of the helix in lcsim coordiantes
+ * @return
+ */
+ public static Hep3Vector extrapolateTrack(HelicalTrackFit helix, double z){
+ SeedTrack trk = new SeedTrack();
+ //bfield = Math.abs((detector.getFieldMap().getField(new BasicHep3Vector(0, 0, 0)).y()));
+ double bfield = 0.;
+ // Here we aren't really using anything related to momentum so B-field is not important
+ trk.setTrackParameters(helix.parameters(), bfield); // Sets first TrackState.
+ trk.setCovarianceMatrix(helix.covariance()); // Modifies first TrackState.
+ trk.setChisq(helix.chisqtot());
+ trk.setNDF(helix.ndf()[0]+helix.ndf()[1]);
+ return TrackUtils.extrapolateTrack(trk,z);
+ }
+
+ /**
+ * @param helix input helix object
+ * @param origin of the plane to intercept
+ * @param normal of the plane to intercept
+ * @param eps criteria on the distance to the plane before stopping iteration
+ * @return position in space at the intercept of the plane
+ */
+ public static Hep3Vector getHelixPlanePositionIter(HelicalTrackFit helix, Hep3Vector origin, Hep3Vector normal, double eps) {
+ boolean debug = false;
+ if(debug) {
+ System.out.printf("--- getHelixPlanePositionIter ---\n");
+ System.out.printf("Target origin [%.10f %.10f %.10f] normal [%.10f %.10f %.10f]\n",origin.x(),origin.y(),origin.z(),normal.x(),normal.y(),normal.z());
+ System.out.printf("%.10f %.10f %.10f %.10f %.10f\n",helix.dca(),helix.z0(),helix.phi0(),helix.slope(),helix.R());
+ }
+ double x = origin.x();
+ double d = 9999.9;
+ double dx = 0.0;
+ int nIter = 0;
+ Hep3Vector pos = null;
+ while( Math.abs(d) > eps && nIter < 50) {
+ // Calculate position on helix at x
+ pos = getHelixPosAtX(helix, x + dx);
+ // Check if we are on the plane
+ d = VecOp.dot(VecOp.sub(pos, origin), normal);
+ dx += -1.0 * d / 2.0;
+ if(debug) System.out.printf("%d d %.10f pos [%.10f %.10f %.10f] dx %.10f\n", nIter, d, pos.x(),pos.y(),pos.z(), dx);
+ nIter += 1;
+ }
+ return pos;
+ }
+
+ /*
+ * Calculates the point on the helix at a given point along the x-axis
+ * The normal of the plane is in the same x-y plane as the circle.
+ *
+ * @param helix
+ * @param x point along x-axis
+ * @return point on helix at x-coordinate
+ *
+ */
+ private static Hep3Vector getHelixPosAtX(HelicalTrackFit helix, double x) {
+ //double C = (double)Math.round(helix.curvature()*1000000)/1000000;
+ //double R = 1.0/C;
+ double R = helix.R();
+ double dca = helix.dca();
+ double z0 = helix.z0();
+ double phi0 = helix.phi0();
+ double slope = helix.slope();
+ //System.out.printf("%.10f %.10f %.10f %.10f %.10f\n",dca,z0,phi0,slope,R);
+
+ double xc = (R - dca) * Math.sin(phi0);
+ double sinPhi = (xc - x)/R;
+ double phi_at_x = Math.asin(sinPhi);
+ double dphi_at_x = phi_at_x - phi0;
+ if (dphi_at_x > Math.PI) dphi_at_x -= 2.0 * Math.PI;
+ if (dphi_at_x < -Math.PI) dphi_at_x += 2.0 * Math.PI;
+ double s_at_x = -1.0 * dphi_at_x * R;
+ double y = dca * Math.cos(phi0) - R * Math.cos(phi0) + R * Math.cos(phi_at_x);
+ double z = z0 + s_at_x * slope;
+ BasicHep3Vector pos = new BasicHep3Vector(x,y,z);
+ //System.out.printf("pos %s xc %f phi_at_x %f dphi_at_x %f s_at_x %f\n", pos.toString(),xc,phi_at_x,dphi_at_x,s_at_x);
+ Hep3Vector posXCheck =TrackUtils.extrapolateHelixToXPlane(helix, x);
+ if(VecOp.sub(pos,posXCheck).magnitude()>0.0000001) {
+ throw new RuntimeException(String.format("ERROR the helix propagation equations do not agree? (%f,%f,%f) vs (%f,%f,%f) in HelixUtils",pos.x(),pos.y(),pos.z(),posXCheck.x(),posXCheck.y(),posXCheck.z()));
+ }
+ return pos;
+ }
+
+
+
+ /**
+ *
+ */
+ public static 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);
+ }
+
+
+ /**
+ *
+ */
+ public static boolean sensorContainsTrack(Hep3Vector trackPosition, SiSensor sensor){
+ boolean debug = false;
+ ITransform3D localToGlobal = sensor.getGeometry().getLocalToGlobal();
+
+ Box sensorSolid = (Box) sensor.getGeometry().getLogicalVolume().getSolid();
+ Polygon3D sensorFace = sensorSolid.getFacesNormalTo(new BasicHep3Vector(0, 0, 1)).get(0);
+ if(debug){
+ System.out.println("sensorContainsTrack: Sensor: " + SvtUtils.getInstance().getDescription(sensor));
+ System.out.println("sensorContainsTrack: 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("sensorContainsTrack: Vertex 1 Position: " + vertices.get(0).toString());
+ //System.out.println("sensorContainsTrack: 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("sensorContainsTrack: Vertex 2 Position: " + vertices.get(1).toString());
+ //System.out.println("sensorContainsTrack: 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("sensorContainsTrack: Vertex 3 Position: " + vertices.get(2).toString());
+ //System.out.println("sensorContainsTrack: 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("sensorContainsTrack: Vertex 4 Position: " + vertices.get(3).toString());
+ //System.out.println("sensorContainsTrack: Transformed Vertex 4 Position: " + localToGlobal.transformed(vertex).toString());
+ }
+ }
+ }
+
+ double area1 = TrackUtils.findTriangleArea(vertices.get(0).x(), vertices.get(0).y(), vertices.get(1).x(), vertices.get(1).y(), trackPosition.y(), trackPosition.z());
+ double area2 = TrackUtils.findTriangleArea(vertices.get(1).x(), vertices.get(1).y(), vertices.get(2).x(), vertices.get(2).y(), trackPosition.y(), trackPosition.z());
+ double area3 = TrackUtils.findTriangleArea(vertices.get(2).x(), vertices.get(2).y(), vertices.get(3).x(), vertices.get(3).y(), trackPosition.y(), trackPosition.z());
+ double area4 = TrackUtils.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 static Map<String,Double> calculateTrackHitResidual(HelicalTrackHit hth,HelicalTrackFit track, boolean includeMS ) {
+
+ boolean debug = false;
+ Map<String,Double> residuals = new HashMap<String,Double>();
+
+ Map<HelicalTrackHit, MultipleScatter> msmap = track.ScatterMap();
+ double msdrphi = 0;
+ double msdz = 0;
+
+ if(includeMS) {
+ msdrphi = msmap.get(hth).drphi();
+ msdz = msmap.get(hth).dz();
+ }
+
+ //Calculate the residuals that are being used in the track fit
+
+ //Start with the bendplane y
+ double drphi_res = hth.drphi();
+ double wrphi = Math.sqrt(drphi_res*drphi_res + msdrphi*msdrphi);
+ //This is the normal way to get s
+ double s_wrong = track.PathMap().get(hth);
+ //This is how I do it with HelicalTrackFits
+ double s = HelixUtils.PathToXPlane(track, hth.x(), 0, 0).get(0);
+ //System.out.printf("x %f s %f smap %f\n",hth.x(),s,s_wrong);
+ if(Double.isNaN(s)) {
+ double xc=track.xc();
+ double RC = track.R();
+ System.out.printf("calculateTrackHitResidual: s is NaN. p=%.3f RC=%.3f, x=%.3f, xc=%.3f\n",track.p(-0.491),RC,hth.x(),xc);
+ return residuals;
+ }
+
+ Hep3Vector posOnHelix = HelixUtils.PointOnHelix(track, s);
+ double resy = hth.y() - posOnHelix.y();
+ double erry = includeMS ? wrphi : drphi_res;
+
+ //Now the residual for the "measurement" direction z
+ double resz = hth.z() - posOnHelix.z();
+ double dz_res = HitUtils.zres(hth, msmap, track);
+ double dz_res2 = hth.getCorrectedCovMatrix().diagonal(2);
+
+ if(Double.isNaN(resy)) {
+ System.out.printf("calculateTrackHitResidual: resy is NaN. hit at %s posOnHelix=%s path=%.3f wrong_path=%.3f helix:\n%s\n",hth.getCorrectedPosition().toString(),posOnHelix.toString(),s,s_wrong,track.toString());
+ return residuals;
+ }
+
+
+ residuals.put("resy", resy);
+ residuals.put("erry", erry);
+ residuals.put("drphi", drphi_res);
+ residuals.put("msdrphi",msdrphi);
+
+ residuals.put("resz",resz);
+ residuals.put("errz",dz_res);
+ residuals.put("dz_res",Math.sqrt(dz_res2));
+ residuals.put("msdz",msdz);
+
+
+ if(debug) {
+ System.out.printf("calculateTrackHitResidual: HTH hit at (%f,%f,%f)\n",hth.x(),hth.y(),hth.z());
+ System.out.printf("calculateTrackHitResidual: helix params d0=%f phi0=%f R=%f z0=%f slope=%f chi2=%f/%f chi2tot=%f\n",track.dca(),track.phi0(),track.R(),track.z0(),track.slope(),track.chisq()[0],track.chisq()[1],track.chisqtot());
+ System.out.printf("calculateTrackHitResidual: => resz=%f resy=%f at s=%f\n",resz,resy,s);
+ //System.out.printf("calculateTrackHitResidual: resy=%f eresy=%f drphi=%f msdrphi=%f \n",resy,erry,drphi_res,msdrphi);
+ //System.out.printf("calculateTrackHitResidual: resz=%f eresz=%f dz_res=%f msdz=%f \n",resz,dz_res,Math.sqrt(dz_res2),msdz);
+ }
+
+
+ return residuals;
+ }
+
+
+ public static Map<String,Double> calculateLocalTrackHitResiduals(Track track, HelicalTrackHit hth, HelicalTrackStrip strip, double bFieldInZ) {
+
+ SeedTrack st = (SeedTrack) track;
+ SeedCandidate seed = st.getSeedCandidate();
+ HelicalTrackFit _trk = seed.getHelix();
+ Map<HelicalTrackHit,MultipleScatter> msmap = seed.getMSMap();
+ double msdrdphi = msmap.get(hth).drphi();
+ double msdz = msmap.get(hth).dz();
+ return calculateLocalTrackHitResiduals(_trk, strip, msdrdphi, msdz, bFieldInZ);
+ }
+
+ public static Map<String,Double> calculateLocalTrackHitResiduals(HelicalTrackFit _trk, HelicalTrackStrip strip, double msdrdphi, double msdz, double bFieldInZ) {
+
+
+ boolean debug = false;
+ boolean includeMS = true;
+
+
+ Hep3Vector u = strip.u();
+ Hep3Vector corigin = strip.origin();
+
+ //Find interception with plane that the strips belongs to
+ Hep3Vector trkpos = TrackUtils.getHelixPlaneIntercept(_trk, strip, bFieldInZ);
+
+ if(debug) {
+ System.out.printf("calculateLocalTrackHitResiduals: found interception point at %s \n",trkpos.toString());
+ }
+
+
+ if(Double.isNaN(trkpos.x()) || Double.isNaN(trkpos.y()) || Double.isNaN(trkpos.z())) {
+ System.out.printf("calculateLocalTrackHitResiduals: failed to get interception point (%s) \n",trkpos.toString());
+ System.out.printf("calculateLocalTrackHitResiduals: track params\n%s\n",_trk.toString());
+ System.out.printf("calculateLocalTrackHitResiduals: track pT=%.3f chi2=[%.3f][%.3f] \n",_trk.pT(bFieldInZ),_trk.chisq()[0],_trk.chisq()[1]);
+ trkpos = TrackUtils.getHelixPlaneIntercept(_trk, strip, bFieldInZ);
+ 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);
+ double msuError = VecOp.dot(mserr, u);
+
+ Hep3Vector vdiffTrk = VecOp.sub(trkpos, corigin);
+ TrackerHitUtils thu = new TrackerHitUtils(debug);
+ Hep3Matrix trkToStrip = thu.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 vmeas = 0;
+ double vError = (strip.vmax() - strip.vmin()) / Math.sqrt(12);
+ double wmeas = 0;
+ double wError = 10.0/Math.sqrt(12); //0.001;
+
+ Map<String,Double> res = new HashMap<String,Double>();
+ res.put("ures", umeas-umc);
+ res.put("ureserr", includeMS ? Math.sqrt(uError * uError + msuError * msuError) : uError);
+ res.put("vres", vmeas-vmc);
+ res.put("vreserr", vError);
+ res.put("wres", wmeas-wmc);
+ res.put("wreserr", wError);
+
+ res.put("vdiffTrky",vdiffTrk.y());
+
+ return res;
+ }
+
+
+ public static int[] getHitsInTopBottom(Track track) {
+ int n[] = {0,0};
+ List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+ for(TrackerHit hit : hitsOnTrack) {
+ HelicalTrackHit hth = (HelicalTrackHit) hit;
+ if(SvtUtils.getInstance().isTopLayer((SiSensor)((RawTrackerHit)hth.getRawHits().get(0)).getDetectorElement())) {
+ n[0] = n[0] + 1;
+ } else {
+ n[1] = n[1] + 1;
+ }
+ }
+ return n;
+ }
+
+ public static boolean isTopTrack(Track track,int minhits) {
+ return isTopOrBottomTrack(track,minhits)==1?true:false;
+ }
+
+ public static boolean isBottomTrack(Track track,int minhits) {
+ return isTopOrBottomTrack(track,minhits)==0?true:false;
+ }
+
+ public static int isTopOrBottomTrack(Track track,int minhits) {
+ int nhits[] = getHitsInTopBottom(track);
+ if (nhits[0]>=minhits && nhits[1]==0) {
+ return 1;
+ } else if (nhits[1]>=minhits && nhits[0]==0) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
+ public static boolean hasTopBotHit(Track track) {
+ int nhits[] = getHitsInTopBottom(track);
+ if (nhits[0]>0 && nhits[1]>0) return true;
+ else return false;
+ }
+
+ public static boolean isSharedHit(TrackerHit hit, List<Track> othertracks) {
+ HelicalTrackHit hth = (HelicalTrackHit) hit;
+ for(Track track : othertracks) {
+ List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+ for(TrackerHit loop_hit : hitsOnTrack) {
+ HelicalTrackHit loop_hth = (HelicalTrackHit) loop_hit;
+ if(hth.equals(loop_hth)) {
+ //System.out.printf("share hit at layer %d at %s (%s) with track w/ chi2=%f\n",hth.Layer(),hth.getCorrectedPosition().toString(),loop_hth.getCorrectedPosition().toString(),track.getChi2());
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static int numberOfSharedHits(Track track, List<Track> tracklist) {
+ List<Track> tracks = new ArrayList<Track>();
+ //System.out.printf("%d tracks in event\n",tracklist.size());
+ //System.out.printf("look for another track with chi2=%f and px=%f \n",track.getChi2(),track.getTrackStates().get(0).getMomentum()[0]);
+ for(Track t: tracklist) {
+ //System.out.printf("add track with chi2=%f and px=%f ?\n",t.getChi2(),t.getTrackStates().get(0).getMomentum()[0]);
+ if(t.equals(track)) {
+ //System.out.printf("NOPE\n");
+ continue;
+ }
+ //System.out.printf("YEPP\n");
+ tracks.add(t);
+ }
+ List<TrackerHit> hitsOnTrack = track.getTrackerHits();
+ int n_shared = 0;
+ for(TrackerHit hit : hitsOnTrack) {
+ if (isSharedHit(hit,tracks)) {
+ ++n_shared;
+ }
+ }
+ return n_shared;
+ }
+
+ public static boolean hasSharedHits(Track track,List<Track> tracklist) {
+ return numberOfSharedHits( track, tracklist)==0?false:true;
+ }
+
+ public static void cut(int cuts[],EventQuality.Cut bit) {
+ cuts[0] = cuts[0] | (1 << bit.getValue());
+ }
+
+
+ public static boolean isGoodTrack(Track track, List<Track> tracklist, EventQuality.Quality trk_quality) {
+ int cuts = passTrackSelections(track, tracklist, trk_quality);
+ return cuts==0?true:false;
+ }
+
+ public static int passTrackSelections(Track track, List<Track> tracklist, EventQuality.Quality trk_quality) {
+ int cuts[] = {0};
+ if(track.getTrackStates().get(0).getMomentum()[0] < EventQuality.instance().getCutValue(EventQuality.Cut.PZ, trk_quality))
+ cut(cuts,EventQuality.Cut.PZ);
+ if(track.getChi2()>= EventQuality.instance().getCutValue(EventQuality.Cut.CHI2, trk_quality))
+ cut(cuts,EventQuality.Cut.CHI2);
+ if(numberOfSharedHits(track,tracklist) > ((int)Math.round(EventQuality.instance().getCutValue(EventQuality.Cut.SHAREDHIT, trk_quality))))
+ cut(cuts,EventQuality.Cut.SHAREDHIT);
+ if(hasTopBotHit(track))
+ cut(cuts,EventQuality.Cut.TOPBOTHIT);
+ if(track.getTrackerHits().size()< ((int)Math.round(EventQuality.instance().getCutValue(EventQuality.Cut.NHITS, trk_quality))))
+ cut(cuts,EventQuality.Cut.NHITS);
+ return cuts[0];
+ }
+
+ public static boolean isTopTrack(HelicalTrackFit htf) {
+ return htf.slope()>0;
+ }
+
+ public static boolean isBottomTrack(HelicalTrackFit htf) {
+ return !isTopTrack(htf);
+ }
+
+ /**
+ * Transform MCParticle into a Helix object.
+ * Note that it produces the helix parameters at nominal x=0 and assumes that there is no field at x<0
+ *
+ * @param mcp MC particle to be transformed
+ * @return helix object based on the MC particle
+ */
+ public static HelicalTrackFit getHTF(MCParticle mcp, double Bz) {
+ Hep3Vector org = HPSTransformations.transformVectorToTracking(mcp.getOrigin());
+ Hep3Vector p = HPSTransformations.transformVectorToTracking(mcp.getMomentum());
+ // Move to x=0 if needed
+ double targetX = BeamlineConstants.DIPOLE_EDGELOW_TESTRUN;
+ if(org.x() < targetX) {
+ double dydx = p.y()/p.x();
+ double dzdx = p.z()/p.x();
+ double delta_x = targetX - org.x();
+ double y = delta_x * dydx + org.y();
+ double z = delta_x * dzdx + org.z();
+ double x = org.x() + delta_x;
+ if( Math.abs(x-targetX) > 1e-8) throw new RuntimeException("Error: origin is not zero!");
+ org = new BasicHep3Vector(x,y,z);
+ //System.out.printf("org %s p %s -> org %s\n", old.toString(),p.toString(),org.toString());
+ }
+
+ //System.out.printf("outside org %s p %s \n",p.toString(),org.toString());
+
+
+
+ HelixParamCalculator helixParamCalculator = new HelixParamCalculator(p, org, -1*((int)mcp.getCharge()), Bz);
+ double par[] = new double[5];
+ par[HelicalTrackFit.dcaIndex] = helixParamCalculator.getDCA();
+ par[HelicalTrackFit.slopeIndex] = helixParamCalculator.getSlopeSZPlane();
+ par[HelicalTrackFit.phi0Index] = helixParamCalculator.getPhi0();
+ par[HelicalTrackFit.curvatureIndex] = 1.0/helixParamCalculator.getRadius();
+ par[HelicalTrackFit.z0Index] = helixParamCalculator.getZ0();
+ HelicalTrackFit htf = getHTF(par);
+ //System.out.printf("d0 %f z0 %f R %f phi %f lambda %s\n", htf.dca(),htf.z0(),htf.R(),htf.phi0(),htf.slope() );
+ return htf;
+ }
+
+ public static HelicalTrackFit getHTF(Track track) {
+ if( track.getClass().isInstance(SeedTrack.class) ) {
+ return ((SeedTrack) track).getSeedCandidate().getHelix();
+ } else {
+ return getHTF(track.getTrackStates().get(0).getParameters());
+ }
+ }
+
+ public static HelicalTrackFit getHTF(double par[]) {
+ // need to have matrix that makes sense? Really?
+ SymmetricMatrix cov = new SymmetricMatrix(5);
+ for(int i=0;i<cov.getNRows();++i) cov.setElement(i, i, 1.);
+ HelicalTrackFit htf = new HelicalTrackFit(par, cov, new double[2], new int[2], null, null);
+ return htf;
+ }
+
+ public static StraightLineTrack findSLTAtZ(Track trk1, double zVal, boolean useFringe) {
+ SeedTrack s1 = (SeedTrack) trk1;
+ HelicalTrackFit htf1 = s1.getSeedCandidate().getHelix();
+ HPSTrack hpstrk1 = new HPSTrack(htf1);
+ Hep3Vector pos1;
+ if(useFringe) {
+ pos1 = hpstrk1.getPositionAtZMap(100.0, zVal, 5.0)[0];
+ } else {
+ pos1 = TrackUtils.extrapolateTrack(trk1,zVal);
+ }
+ //System.out.printf("%s: Position1 at edge of fringe %s\n",this.getClass().getSimpleName(),pos1.toString());
+ Helix traj = (Helix)hpstrk1.getTrajectory();
+ if(traj==null) {
+ SpacePoint r0 = new SpacePoint(HelixUtils.PointOnHelix(htf1,0));
+ traj = new Helix(r0,htf1.R(), htf1.phi0(), Math.atan(htf1.slope()));
+ }
+ HelixConverter converter = new HelixConverter(0.);
+ StraightLineTrack slt1 =converter.Convert(traj);
+ //System.out.printf("%s: straight line track: x0=%f,y0=%f,z0=%f dz/dx=%f dydx=%f targetY=%f targetZ=%f \n",this.getClass().getSimpleName(),slt1.x0(),slt1.y0(),slt1.z0(),slt1.dzdx(),slt1.dydx(),slt1.TargetYZ()[0],slt1.TargetYZ()[1]);
+ return slt1;
+ }
+
+}
+
+
+
+
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackerDigiDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackerDigiDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,299 @@
+package org.hps.recon.tracking;
+
+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.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiTrackerModule;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.lcio.LCIOUtil;
+import org.lcsim.recon.tracking.digitization.sisim.BasicReadoutChip;
+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.SiDigitizer;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHit;
+import org.lcsim.recon.tracking.digitization.sisim.SiTrackerHitStrip1D;
+import org.lcsim.recon.tracking.digitization.sisim.StripHitMaker;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
+import org.lcsim.util.Driver;
+
+/**
+ * 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.
+ *
+ * @author jeremym
+ * @version $Id: TrackerDigiDriver.java,v 1.12 2012/11/20 19:59:35 meeg Exp $
+ */
+public class TrackerDigiDriver extends Driver {
+ // Debug switch for development.
+
+ private boolean debug = false;
+ // Collection name.
+ protected String readoutCollectionName = "TrackerHits";
+ // Subdetector name.
+ protected String subdetectorName = "Tracker";
+ // Name of RawTrackerHit output collection.
+ private String rawTrackerHitOutputCollectionName = "RawTrackerHitMaker_RawTrackerHits";
+ // Name of StripHit1D output collection.
+ private String stripHitOutputCollectionName = "StripClusterer_SiTrackerHitStrip1D";
+ // Readout parameters.
+ protected double readoutNoiseIntercept = 270.0;
+ protected double readoutNoiseSlope = 36.0;
+ protected double readoutNoiseThreshold = 4.0;
+ protected double readoutNeighborThreshold = 4.0;
+ protected int readoutNBits = 10;
+ protected int readoutDynamicRange = 40;
+ // Clustering parameters.
+ protected double clusterSeedThreshold = 4.0;
+ protected double clusterNeighborThreshold = 3.0;
+ protected double clusterThreshold = 4.0;
+ protected int clusterMaxSize = 10;
+ protected int clusterCentralStripAveragingThreshold = 4;
+ // Clustering errors by number of TrackerHits.
+ private static final double clusterErrorMultiplier = 1.0;
+ protected double oneClusterErr = clusterErrorMultiplier / Math.sqrt(12.);
+ protected double twoClusterErr = clusterErrorMultiplier / 5.0;
+ protected double threeClusterErr = clusterErrorMultiplier / 3.0;
+ protected double fourClusterErr = clusterErrorMultiplier / 2.0;
+ protected double fiveClusterErr = clusterErrorMultiplier / 1.0;
+ // Various data lists required by digitization.
+ protected List<String> readouts = new ArrayList<String>();
+ protected List<String> processPaths = new ArrayList<String>();
+ private List<IDetectorElement> processDEs = new ArrayList<IDetectorElement>();
+ private Set<SiSensor> processSensors = new HashSet<SiSensor>();
+ private Set<SiTrackerModule> processModules = new HashSet<SiTrackerModule>();
+ // Digi class objects.
+ protected SiDigitizer stripDigitizer;
+ protected StripHitMaker stripClusterer;
+
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
+ public void setReadoutCollectionName(String readoutCollectionName) {
+ this.readoutCollectionName = readoutCollectionName;
+ }
+
+ public void setSubdetectorName(String subdetectorName) {
+ this.subdetectorName = subdetectorName;
+ }
+
+ public void setRawTrackerHitOutputCollectionName(String rawTrackerHitOutputCollectionName) {
+ this.rawTrackerHitOutputCollectionName = rawTrackerHitOutputCollectionName;
+ }
+
+ public void setStripHitOutputCollectionName(String stripHitOutputCollectionName) {
+ this.stripHitOutputCollectionName = stripHitOutputCollectionName;
+ }
+
+ public void setReadoutNoiseIntercept(double readoutNoiseIntercept) {
+ this.readoutNoiseIntercept = readoutNoiseIntercept;
+ }
+
+ public void setReadoutNoiseSlope(double readoutNoiseSlope) {
+ this.readoutNoiseSlope = readoutNoiseSlope;
+ }
+
+ public void setReadoutNeighborThreshold(double readoutNeighborThreshold) {
+ this.readoutNeighborThreshold = readoutNeighborThreshold;
+ }
+
+ public void setReadoutNBits(int readoutNBits) {
+ this.readoutNBits = readoutNBits;
+ }
+
+ public void setReadoutDynamicRange(int readoutDynamicRange) {
+ this.readoutDynamicRange = readoutDynamicRange;
+ }
+
+ public void setClusterSeedThreshold(double clusterSeedThreshold) {
+ this.clusterSeedThreshold = clusterSeedThreshold;
+ }
+
+ public void setClusterNeighborThreshold(double clusterNeighborThreshold) {
+ this.clusterNeighborThreshold = clusterNeighborThreshold;
+ }
+
+ public void setClusterThreshold(double clusterThreshold) {
+ this.clusterThreshold = clusterThreshold;
+ }
+
+ public void setClusterMaxSize(int clusterMaxSize) {
+ this.clusterMaxSize = clusterMaxSize;
+ }
+
+ public void setClusterCentralStripAveragingThreshold(int clusterCentralStripAveragingThreshold) {
+ this.clusterCentralStripAveragingThreshold = clusterCentralStripAveragingThreshold;
+ }
+
+ public void setOneClusterErr(double oneClusterErr) {
+ this.oneClusterErr = oneClusterErr;
+ }
+
+ public void setTwoClusterErr(double twoClusterErr) {
+ this.twoClusterErr = twoClusterErr;
+ }
+
+ public void setThreeClusterErr(double threeClusterErr) {
+ this.threeClusterErr = threeClusterErr;
+ }
+
+ public void setFourClusterErr(double fourClusterErr) {
+ this.fourClusterErr = fourClusterErr;
+ }
+
+ public void setFiveClusterErr(double fiveClusterErr) {
+ this.fiveClusterErr = fiveClusterErr;
+ }
+
+ /**
+ * Creates a new instance of TrackerHitDriver.
+ */
+ public TrackerDigiDriver() {
+ }
+
+ /**
+ * Initializes this Driver's objects with the job parameters.
+ */
+ protected void initialize() {
+
+ // Create the sensor simulation.
+ CDFSiSensorSim stripSim = new CDFSiSensorSim();
+
+ // Create the readout chips and set the noise parameters.
+ BasicReadoutChip stripReadout = new BasicReadoutChip();
+ stripReadout.setNoiseIntercept(readoutNoiseIntercept);
+ stripReadout.setNoiseSlope(readoutNoiseSlope);
+ stripReadout.setNoiseThreshold(readoutNoiseThreshold);
+ stripReadout.setNeighborThreshold(readoutNeighborThreshold);
+ 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);
+ }
+
+ /**
+ * This is executed before detectorChanged and initialization of
+ * digitization objects is done here.
+ */
+ @Override
+ public void startOfData() {
+
+ // At start of job, setup digitization objects needed by this Driver.
+ initialize();
+
+ // If readouts not already set, set them up.
+ if (!readouts.isEmpty()) {
+ System.out.println("Adding SimTrackerHitIdentifierReadoutDriver with readouts: " + readouts);
+ super.add(new SimTrackerHitReadoutDriver(readouts));
+ }
+ super.startOfData();
+ readouts.clear(); // FIXME Is this needed?
+ }
+
+ /**
+ * Do initialization once we get a Detector.
+ */
+ @Override
+ public void detectorChanged(Detector detector) {
+
+ // Call sub-Driver's detectorChanged methods.
+ super.detectorChanged(detector);
+
+ // Process detectors specified by path, otherwise process entire
+ // detector
+ IDetectorElement deDetector = detector.getDetectorElement();
+
+ for (String path : processPaths) {
+ processDEs.add(deDetector.findDetectorElement(path));
+ }
+
+ if (processDEs.isEmpty()) {
+ processDEs.add(deDetector);
+ }
+
+ for (IDetectorElement detectorElement : processDEs) {
+ processSensors.addAll(detectorElement.findDescendants(SiSensor.class));
+ //if (debug)
+ // System.out.println("added " + processSensors.size() + " sensors");
+ processModules.addAll(detectorElement.findDescendants(SiTrackerModule.class));
+ //if (debug)
+ // System.out.println("added " + processModules.size() + " modules");
+ }
+ }
+
+ /**
+ * Perform the digitization.
+ */
+ @Override
+ public void process(EventHeader event) {
+ // Call sub-Driver processing.
+ super.process(event);
+
+ // Make new lists for output.
+ List<RawTrackerHit> rawHits = new ArrayList<RawTrackerHit>();
+ List<SiTrackerHit> stripHits1D = new ArrayList<SiTrackerHit>();
+
+ if (event.hasCollection(SimTrackerHit.class, this.readoutCollectionName)) {
+ // Make raw hits.
+ for (SiSensor sensor : processSensors) {
+ rawHits.addAll(stripDigitizer.makeHits(sensor));
+ }
+
+ // Make strip hits.
+ for (SiSensor sensor : processSensors) {
+ stripHits1D.addAll(stripClusterer.makeHits(sensor));
+ }
+
+ // Debug prints.
+ if (debug) {
+ if (event.hasCollection(SimTrackerHit.class, this.readoutCollectionName)) {
+ List<SimTrackerHit> simHits = event.get(SimTrackerHit.class, this.readoutCollectionName);
+ System.out.println("SimTrackerHit collection " + this.readoutCollectionName + " has " + simHits.size() + " hits.");
+ System.out.println("RawTrackerHit collection " + this.rawTrackerHitOutputCollectionName + " has " + rawHits.size() + " hits.");
+ System.out.println("TrackerHit collection " + this.stripHitOutputCollectionName + " has " + stripHits1D.size() + " hits.");
+ } else {
+ System.out.println("SimTrackerHit collection " + this.readoutCollectionName + " not found.");
+ }
+ }
+ }
+
+ // Put output hits into collection.
+ int flag = LCIOUtil.bitSet(0, 31, true); // Turn on 64-bit cell ID.
+ event.put(this.rawTrackerHitOutputCollectionName, rawHits, RawTrackerHit.class, flag, toString());
+ event.put(this.stripHitOutputCollectionName, stripHits1D, SiTrackerHitStrip1D.class, 0, toString());
+ }
+}
\ No newline at end of file
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackerHitUtils.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackerHitUtils.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,280 @@
+package org.hps.recon.tracking;
+
+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.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.hps.conditions.deprecated.SvtUtils;
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.ITransform3D;
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifier;
+import org.lcsim.detector.identifier.IIdentifierDictionary;
+import org.lcsim.detector.identifier.IIdentifierHelper;
+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.SimTrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.fit.helicaltrack.HelicalTrackStrip;
+import org.lcsim.fit.helicaltrack.HelixUtils;
+
+/**
+ *
+ * @author Per Hansson <[log in to unmask]>
+ * @version $Id: TrackerHitUtils.java,v 1.4 2013/10/15 00:33:53 phansson Exp $
+ */
+public class TrackerHitUtils {
+
+ private boolean _DEBUG = false;
+
+ public TrackerHitUtils() {
+ }
+
+ public TrackerHitUtils(boolean debug) {
+ _DEBUG = debug;
+ }
+
+ public void setDebug(boolean debug) {
+ _DEBUG = debug;
+ }
+
+
+ public Hep3Matrix detToTrackRotationMatrix() {
+ return (BasicHep3Matrix) HPSTransformations.getMatrix();
+ }
+
+ public ITransform3D GetGlobalToLocal(HelicalTrackStrip strip) {
+ //Transform from JLab frame (RawTrackerHit) to sensor frame (i.e. u,v,w)
+ 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();
+ }
+
+ public Hep3Matrix getStripToTrackRotation(HelicalTrackStrip strip) {
+ //This function transforms the hit to the tracking coordinates
+
+ //Transform from JLab frame to sensor frame (done through the RawTrackerHit)
+ ITransform3D detToStrip = GetGlobalToLocal(strip);
+ //Get rotation matrix
+ Hep3Matrix detToStripMatrix = (BasicHep3Matrix) detToStrip.getRotation().getRotationMatrix();
+ //Transformation between the JLAB and tracking coordinate systems
+ 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(detToTrackMatrix,VecOp.inverse(detToStripMatrix));
+ }
+
+ public Hep3Matrix getTrackToStripRotation(HelicalTrackStrip strip) {
+ //This function transforms the hit to the sensor coordinates
+
+ //Transform from JLab frame to sensor frame (done through the RawTrackerHit)
+ ITransform3D detToStrip = this.GetGlobalToLocal(strip);
+ //Get rotation matrix
+ Hep3Matrix detToStripMatrix = (BasicHep3Matrix) detToStrip.getRotation().getRotationMatrix();
+ //Transformation between the JLAB and tracking coordinate systems
+ Hep3Matrix detToTrackMatrix = this.detToTrackRotationMatrix();
+
+ 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));
+ }
+
+
+
+ public Hep3Vector getClusterPosition(HelicalTrackStrip strip, boolean stripInTrackingFrame) {
+ if(_DEBUG) System.out.println(this.getClass().getSimpleName() + " getClusterPosition--");
+ Hep3Vector origin = stripInTrackingFrame ? strip.origin() : VecOp.mult(HPSTransformations.getMatrix(),strip.origin());
+ if(_DEBUG) System.out.println(this.getClass().getSimpleName() + " origin " + origin.toString());
+ Hep3Vector hit_vec_LOCAL = new BasicHep3Vector(strip.umeas(),0,0);
+ if(_DEBUG) System.out.println(this.getClass().getSimpleName() + " hit_vec_LOCAL " + hit_vec_LOCAL.toString());
+ Hep3Matrix stripToTrack = this.getStripToTrackRotation(strip);
+ if(_DEBUG) System.out.println(this.getClass().getSimpleName() + " stripToTrack " + stripToTrack.toString());
+ Hep3Vector hit_vec_TRACK = VecOp.mult(stripToTrack, hit_vec_LOCAL);
+ if(_DEBUG) System.out.println(this.getClass().getSimpleName() + " hit_vec_TRACK " + hit_vec_TRACK.toString());
+ Hep3Vector strip_pos = VecOp.add(origin, hit_vec_TRACK);
+ if(_DEBUG) System.out.println(this.getClass().getSimpleName() + " strip_pos " + strip_pos.toString());
+
+ // Hep3Vector hit_vec_LOCAL_dep = new BasicHep3Vector(strip.umeas(),0,0.16);
+ // if(_DEBUG) System.out.println(this.getClass().getSimpleName() + " hit_vec_LOCAL_dep " + hit_vec_LOCAL_dep.toString());
+ // Hep3Vector hit_vec_TRACK_dep = VecOp.mult(stripToTrack, hit_vec_LOCAL_dep);
+ // Hep3Vector strip_pos_dep = VecOp.add(origin, hit_vec_TRACK_dep);
+ // if(_DEBUG) System.out.println(this.getClass().getSimpleName() + " strip_pos ALTERNATE " + strip_pos_dep.toString());
+
+ return strip_pos;
+ }
+
+ public Hep3Vector CalculateStripUncertaintyInGlobalFrame(HelicalTrackStrip strip, HelicalTrackFit trk, double msdrdphi, double msdz) {
+
+ if(_DEBUG) System.out.println("--- CalculateStripUncertainyInGlobalFrame ---");
+ if(_DEBUG) System.out.println("Strip origin = " + strip.origin().toString());
+ 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 xint = this.calculateHelixInterceptXPlane(_trk, strip);
+ double s = HelixUtils.PathToXPlane(trk, xint, 0,0).get(0);
+ double phi = -s/R + phi0;
+ if(_DEBUG) System.out.println("phi0 " + phi0 + " R " + R + " xint " + xint + " s " + s + " phi " + phi);
+ //if(_DEBUG) System.out.println("trkpos = "+trkpos.toString());
+ //if(_DEBUG) System.out.println("origin = "+corigin.toString());
+
+ Hep3Vector mserr = new BasicHep3Vector(msdrdphi * Math.sin(phi), msdrdphi * Math.sin(phi), msdz);
+ if(_DEBUG) System.out.println("msdrdphi = " + msdrdphi + " msdz = " + msdz);
+ if(_DEBUG) System.out.println("mserr = " + mserr.toString());
+ double uHitError = strip.du();
+ double msuError = VecOp.dot(mserr, u);
+ double uError = Math.sqrt(uHitError * uHitError + msuError * msuError);
+ if(_DEBUG) System.out.println("uError = " + uError + "(MS "+msuError + ",u=" + u.toString()+")");
+ double vHitError = (strip.vmax() - strip.vmin()) / Math.sqrt(12);
+ double msvError = VecOp.dot(mserr, v);
+ double vError = Math.sqrt(vHitError * vHitError + msvError * msvError);
+ if(_DEBUG) System.out.println("vError = " + vError + "(MS "+msvError + ",v=" + v.toString()+")");
+
+ double wHitError = 10.0/Math.sqrt(12); //0.001;
+ double mswError = VecOp.dot(mserr, w);
+ double wError = Math.sqrt(wHitError * wHitError + mswError * mswError);
+ if(_DEBUG) System.out.println("wError = " + wError + "(MS "+mswError + ",w=" + w.toString()+")");
+
+ Hep3Vector dq_local = new BasicHep3Vector(uError,vError,wError);
+ if(_DEBUG) System.out.println("dq_local = " + dq_local.toString());
+ Hep3Matrix trackToStripRot = getTrackToStripRotation(strip);
+ if(_DEBUG) System.out.println("trackToStripRot:\n " + trackToStripRot.toString());
+ Hep3Matrix stripToTrackRot = VecOp.inverse(trackToStripRot);
+ if(_DEBUG) System.out.println("stripToTrackRot:\n " + stripToTrackRot.toString());
+ Hep3Vector dq_global = VecOp.mult(stripToTrackRot, dq_local);
+ if(_DEBUG) System.out.println("q_global = " + dq_global.toString());
+ return dq_global;
+ }
+
+ public List<SimTrackerHit> stripClusterToSimHits(HelicalTrackStrip strip, List<SimTrackerHit> simTrackerHits, boolean stripsInTrackingFrame){
+
+ int layer = strip.layer();
+ Hep3Vector stripPosition = this.getClusterPosition(strip,stripsInTrackingFrame);
+
+ // Sort the SimTrackerHits by Layer
+ Map<Integer, List<SimTrackerHit>> layerToSimTrackerHit = new HashMap<Integer, List<SimTrackerHit>>();
+ for(SimTrackerHit simTrackerHit : simTrackerHits){
+ if(!layerToSimTrackerHit.containsKey(simTrackerHit.getLayer()))
+ layerToSimTrackerHit.put(simTrackerHit.getLayer(), new ArrayList<SimTrackerHit>());
+ layerToSimTrackerHit.get(simTrackerHit.getLayer()).add(simTrackerHit);
+ }
+
+ //
+ List<SimTrackerHit> simhits = new ArrayList<SimTrackerHit>();
+
+ if(layerToSimTrackerHit.get(strip.layer()) == null) {
+ System.out.println(this.getClass().getSimpleName() + ": WARNING there is a strip in layer " + strip.layer() + " but no SimTrackerHits");
+ return simhits;
+ }
+
+ // If there is only a single SimTrackerHit on a layer and it's in the same volume as the
+ // strip hit then they likely match to each other
+ if(layerToSimTrackerHit.get(strip.layer()).size() == 1){
+ Hep3Vector simTrackerHitPosition = layerToSimTrackerHit.get(strip.layer()).get(0).getPositionVec();
+ if(Math.signum(simTrackerHitPosition.y()) == Math.signum(stripPosition.z())){
+ simhits.add(layerToSimTrackerHit.get(strip.layer()).get(0));
+ layerToSimTrackerHit.remove(strip.layer());
+ if(_DEBUG) {
+ System.out.println(this.getClass().getSimpleName() + ": SimTrackerHit position: " + simTrackerHitPosition.toString());
+ System.out.println(this.getClass().getSimpleName() + ": Cluster position: " + stripPosition.toString());
+ }
+ } else {
+ System.out.println(this.getClass().getSimpleName() + ": Cluster and SimTrackerHit are on different volumes");
+ }
+ }
+ else if(layerToSimTrackerHit.get(strip.layer()).size() > 1){
+ if(_DEBUG) System.out.println(this.getClass().getSimpleName() + ": found " + layerToSimTrackerHit.get(strip.layer()).size() + " SimTrackerHits to match to strip in layer " + strip.layer());
+ //System.exit(1);
+ double deltaZ = Double.MAX_VALUE;
+ SimTrackerHit simTrackerHitMatch = null;
+ for(SimTrackerHit simTrackerHit : layerToSimTrackerHit.get(strip.layer())){
+ if(Math.abs(simTrackerHit.getPositionVec().y() - stripPosition.z()) < deltaZ){
+ deltaZ = Math.abs(simTrackerHit.getPositionVec().y() - stripPosition.z());
+ simTrackerHitMatch = simTrackerHit;
+ }
+ }
+ simhits.add(simTrackerHitMatch);
+ layerToSimTrackerHit.remove(strip.layer()).remove(simTrackerHitMatch);
+ if(_DEBUG) {
+ System.out.println(this.getClass().getSimpleName() + ": SimTrackerHit position: " + simTrackerHitMatch.getPositionVec().toString());
+ System.out.println(this.getClass().getSimpleName() + ": Cluster position: " + stripPosition);
+ }
+ }
+
+
+
+ return simhits;
+ }
+
+ /**
+ * Make a SimTrackerHit {@link IIdentifier} for a given layer number
+ *
+ * @param sensor : The sensor on which the SimTrackerHit is created on
+ * @return A 32-bit SimTrackerHit identifier
+ */
+ public static IIdentifier makeSimTrackerHitId(SiSensor sensor){
+
+ // Get the sensors identifier
+ IExpandedIdentifier id = new ExpandedIdentifier(sensor.getExpandedIdentifier());
+
+ // Get the helper and dictionary
+ IIdentifierHelper helper = sensor.getIdentifierHelper();
+ IIdentifierDictionary dictionary = helper.getIdentifierDictionary();
+
+ // Fill in the layer number
+ id.setValue(dictionary.getFieldIndex("layer"), SvtUtils.getInstance().getLayerNumber(sensor));
+
+ // Pack and return the identifier
+ return helper.pack(id);
+
+ }
+
+ // public List<SiTrackerHit> stripClusterToSiHits(HelicalTrackStrip strip, List<SiTrackerHit> siTrackerHits, boolean stripsInTrackingFrame)
+ // {
+ //
+ // //Should be a one to one match with a strip!
+ // Hep3Vector stripPosition = this.getClusterPosition(strip,stripsInTrackingFrame);
+ // if(_DEBUG) System.out.println("Strip position " + stripPosition.toString() + " ( " + strip.origin().toString() + ")");
+ //
+ // for(SiTrackerHit siTrackerHit : siTrackerHits){
+ // SiTrackerHitStrip1D h = (SiTrackerHitStrip1D) siTrackerHit;
+ // if(_DEBUG) System.out.println("SiTrackerHit origin position " + h.getPositionAsVector().toString());
+ //
+ // }
+ //
+ // List<SiTrackerHit> hits = new ArrayList<SiTrackerHit>();
+ // return hits;
+ //
+ // }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackerReconDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/TrackerReconDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,202 @@
+package org.hps.recon.tracking;
+
+import hep.physics.vec.BasicHep3Vector;
+
+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.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 TrackerReconDriver 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;
+ // number of repetitive fits on confirmed/extended tracks
+ private int _iterativeConfirmed = 3;
+ // use HPS implementation of material manager
+ private boolean _useHPSMaterialManager = true;
+ // enable the use of sectoring using sector binning in SeedTracker
+ private boolean _applySectorBinning = true;
+
+ public TrackerReconDriver() {
+ }
+
+ 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;
+ }
+
+ /**
+ * Set to enable the use of the HPS material manager implementation
+ *
+ * @param useHPSMaterialManager switch
+ */
+ public void setUseHPSMaterialManager(boolean useHPSMaterialManager) {
+ this._useHPSMaterialManager = useHPSMaterialManager;
+ }
+
+ public void setIterativeFits(int val) {
+ this._iterativeConfirmed = val;
+ }
+
+ /**
+ * Set to enable the sectoring to use the sector bins in checking for consistent hits.
+ *
+ * @param applySectorBinning apply sector binning switch
+ */
+ public void setApplySectorBinning(boolean applySectorBinning) {
+ this._applySectorBinning = applySectorBinning;
+ }
+
+ /**
+ * 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\n",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._useHPSMaterialManager,this.includeMS);
+ stFinal.setApplySectorBinning(_applySectorBinning);
+ stFinal.setUseDefaultXPlane(false);
+ stFinal.setDebug(this.debug);
+ stFinal.setIterativeConfirmed(_iterativeConfirmed);
+ 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/sandbox/tracking/src/main/java/org/hps/recon/tracking
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/WTrack.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/WTrack.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,338 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+
+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/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/Apv25AnalogData.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/Apv25AnalogData.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,123 @@
+package org.hps.recon.tracking.apv25;
+
+//--- org.lcsim ---//
+import org.lcsim.detector.tracker.silicon.SiSensor;
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: Apv25AnalogData.java,v 1.3 2012/08/17 01:17:08 omoreno Exp $
+ */
+public class Apv25AnalogData {
+
+ private SiSensor sensor = null;
+ private int apv25;
+
+ // APV25 output stream
+ private double[] apv25AnalogOutput = new double[140];
+ private double[] header = {4.0, 4.0, 4.0};
+ private double[] address = {-4.0, -4.0, -4.0, -4.0, -4.0, -4.0, -4.0, -4.0};
+ private double error = 4.0;
+ private double[] samples = new double[128];
+
+ /**
+ * Default Ctor
+ */
+ public Apv25AnalogData(){
+
+
+
+ // Copy the header, address, error and samples
+ System.arraycopy(header, 0, apv25AnalogOutput, 0, header.length);
+ System.arraycopy(address, 0, apv25AnalogOutput, 3, address.length);
+ apv25AnalogOutput[11] = error;
+
+ // Create the array which will contain the output. The array values will range
+ // from -4 microAmps to 4 microAmps
+ for(int index = 12; index < apv25AnalogOutput.length; index++){
+ apv25AnalogOutput[index] = -4.0; // microAmps
+ }
+ }
+
+ /**
+ *
+ */
+ public Apv25AnalogData(SiSensor sensor, int apv25){
+ this();
+
+ // Set the sensor and APV number associated with this data
+ this.sensor = sensor;
+ this.apv25 = apv25;
+ }
+
+ /**
+ *
+ */
+ public void setChannelData(int channel, double data){
+ apv25AnalogOutput[12 + channel] += data;
+ }
+
+ /**
+ *
+ */
+ public void setSensor(SiSensor sensor){
+ this.sensor = sensor;
+ }
+
+ /**
+ *
+ */
+ public void setApv(int apv25){
+ this.apv25 = apv25;
+ }
+
+ /**
+ *
+ */
+ public double[] getHeader(){
+ return header;
+ }
+
+ /**
+ *
+ */
+ public double[] getAddress(){
+ return address;
+ }
+
+ /**
+ *
+ */
+ public double getErrorBit(){
+ return error;
+ }
+
+ /**
+ *
+ */
+ public double[] getSamples(){
+ System.arraycopy(apv25AnalogOutput, 12, samples, 0, samples.length);
+ return samples;
+ }
+
+ /**
+ *
+ */
+ public double[] getApv25AnalogOutput(){
+ return this.apv25AnalogOutput;
+ }
+
+ /**
+ *
+ */
+ public SiSensor getSensor(){
+ return this.sensor;
+ }
+
+ /**
+ *
+ */
+ public int getApvNumber(){
+ return this.apv25;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/Apv25DigitalData.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/Apv25DigitalData.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,92 @@
+package org.hps.recon.tracking.apv25;
+
+//--- org.lcsim ---//
+import org.lcsim.detector.tracker.silicon.SiSensor;
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: Apv25DigitalData.java,v 1.3 2012/08/17 01:17:08 omoreno Exp $
+ */
+public class Apv25DigitalData {
+
+ // TODO: Add ability to associate the analog data to a SiSensor and APV25
+ private SiSensor sensor = null;
+ private int apv25;
+
+ // APV25 output stream
+ private double[] apv25DigitalOutput = new double[140];
+ private double[] header = new double[3];
+ private double[] address = new double[8];
+ private double error;
+ private double[] samples = new double[128];
+
+ /**
+ * Default Ctor
+ */
+ public Apv25DigitalData(SiSensor sensor, int apv25, double[] apv25DigitalOutput){
+
+ // Check if the output format is valid
+ if(apv25DigitalOutput.length != this.apv25DigitalOutput.length)
+ throw new RuntimeException("APV25 output format is invalid!");
+
+ System.arraycopy(apv25DigitalOutput, 0, this.apv25DigitalOutput, 0, apv25DigitalOutput.length);
+ System.arraycopy(apv25DigitalOutput, 0, header, 0, header.length);
+ System.arraycopy(apv25DigitalOutput, 3, address, 0, address.length);
+ error = apv25DigitalOutput[11];
+ System.arraycopy(apv25DigitalOutput, 12, samples, 0, samples.length);
+
+ // Set the sensor and APV number associated with this data
+ this.sensor = sensor;
+ this.apv25 = apv25;
+ }
+
+ /**
+ *
+ */
+ public double[] getHeader(){
+ return header;
+ }
+
+ /**
+ *
+ */
+ public double[] getAddress(){
+ return address;
+ }
+
+ /**
+ *
+ */
+ public double getErrorBit(){
+ return error;
+ }
+
+ /**
+ *
+ */
+ public double[] getSamples(){
+ return samples;
+ }
+
+ /**
+ *
+ */
+ public double[] getApv25DigitalOutput(){
+ return apv25DigitalOutput;
+ }
+
+ /**
+ *
+ */
+ public SiSensor getSensor(){
+ return this.sensor;
+ }
+
+ /**
+ *
+ */
+ public int getApv(){
+ return this.apv25;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/Apv25Full.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/Apv25Full.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,290 @@
+package org.hps.recon.tracking.apv25;
+
+//--- Constants ---//
+import org.hps.conditions.deprecated.HPSSVTConstants;
+//--- hps-java ---//
+import org.lcsim.hps.util.ClockSingleton;
+import org.lcsim.hps.util.RingBuffer;
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: Apv25Full.java,v 1.9 2013/04/25 22:11:14 meeg Exp $
+ */
+public class Apv25Full {
+
+ // APV25 trigger bit
+ public static boolean readoutBit = false;
+ protected int triggerLatency = 0; // Clock cycles
+ protected int triggerLatencyTime = 240; // ns
+
+ // APV25 Channels; An APV25 Readout Chip contains a total of 128 channels
+ private Apv25Channel[] channels = new Apv25Channel[HPSSVTConstants.CHANNELS];
+
+ /**
+ * Default Ctor
+ */
+ public Apv25Full(){
+
+ // Instantiate all APV25 channels
+ for(int channelN = 0; channelN < HPSSVTConstants.CHANNELS; channelN++){
+ channels[channelN] = new Apv25Channel();
+ }
+ // Set the trigger latency
+ this.setLatency(triggerLatencyTime);
+ }
+
+ /**
+ *
+ */
+ public void setLatency(int triggerLatencyTime /*ns*/){
+ this.triggerLatency = (int) Math.floor(triggerLatencyTime/HPSSVTConstants.SAMPLING_INTERVAL);
+ for(int channelN = 0; channelN < HPSSVTConstants.CHANNELS; channelN++) channels[channelN].getPipeline().resetPointerPositions();
+ }
+
+ /**
+ * Return an instance of an APV25 channel
+ *
+ * @param channel: APV25 channel of interest (0-127)
+ * @return an instance of an Apv25Channel
+ */
+ public Apv25Channel getChannel(int channel){
+ if(channel >= HPSSVTConstants.CHANNELS) throw new RuntimeException();
+ return channels[channel];
+ }
+
+ /**
+ * Inject charge into a channel and shape the signal. The resulting
+ * shaper signal is then sampled into the analog pipeline
+ *
+ * @param charge : Total charge being injected
+ * @param pipeline : Analog pipeline associated with a channel
+ */
+ public void injectCharge(int channel, double charge) {
+
+ // Shape the injected charge
+ this.getChannel(channel).shapeSignal(charge);
+
+ // Sample the resulting shaper signal
+ this.getChannel(channel).sampleShaperSignal();
+ }
+
+ /**
+ *
+ */
+ public void incrementPointerPositions(){
+ for(int channel = 0; channel < channels.length; channel++){
+ channels[channel].pipeline.step();
+ }
+ }
+
+ /**
+ *
+ */
+ public Apv25AnalogData readOut(){
+
+ Apv25AnalogData data = new Apv25AnalogData();
+ for(int channel = 0; channel < HPSSVTConstants.CHANNELS; channel++){
+
+ // Only readout the channel if the channel isn't bad
+ if(!this.getChannel(channel).isBadChannel()){
+ // Readout the value stored in the buffer
+ double sample = (this.getChannel(channel).getPipeline().readout()/HPSSVTConstants.FRONT_END_GAIN)*HPSSVTConstants.MULTIPLEXER_GAIN;
+ data.setChannelData(channel, sample);
+ }
+ }
+ return data;
+ }
+
+ //------------------------------------------//
+ // APV25 Channel //
+ //------------------------------------------//
+ public class Apv25Channel {
+
+ private Apv25ShaperSignal shaperSignal;
+ private Apv25Pipeline pipeline = new Apv25Pipeline();
+
+ private double shapingTime = 50; // [ns]
+ boolean badChannel = false;
+
+ /**
+ * Default Constructor
+ */
+ public Apv25Channel(){
+ }
+
+ /**
+ * Set the shaping time
+ *
+ * @param shapingTime : APV25 shaping time. The default Tp is set to 50 ns.
+ */
+ public void setShapingTime(double shapingTime) {
+ this.shapingTime = shapingTime;
+ }
+
+ /**
+ *
+ */
+ public void markAsBadChannel(){
+ badChannel = true;
+ }
+
+ /**
+ *
+ */
+ public boolean isBadChannel(){
+ return badChannel;
+ }
+
+ /**
+ *
+ */
+ public Apv25Pipeline getPipeline(){
+ return pipeline;
+ }
+
+ /**
+ * Shape the injected charge
+ *
+ * @param charge
+ */
+ public void shapeSignal(double charge){
+ shaperSignal = new Apv25ShaperSignal(charge);
+ }
+
+ /**
+ *
+ */
+ public void sampleShaperSignal(){
+
+ // Obtain the beam time
+ double beamTime = ClockSingleton.getTime();
+
+ // Fill the analog pipeline starting with the cell to which the writer pointer is pointing
+ // to. Signals arriving within the same bucket of length <samplingTime> will be shifted in
+ // time depending on when they arrive.
+ for(int cell = 0; cell < HPSSVTConstants.ANALOG_PIPELINE_LENGTH; cell++){
+
+ // Time at which the shaper signal will be sampled
+ int sampleTime = cell*((int) HPSSVTConstants.SAMPLING_INTERVAL) - (int) (beamTime%HPSSVTConstants.SAMPLING_INTERVAL);
+
+ // Sample the shaper signal
+ double sample = shaperSignal.getAmplitudeAtTime(sampleTime, shapingTime);
+
+ // Add the value to the pipeline
+ pipeline.addToCell(cell, sample);
+ }
+ }
+ }
+
+ //-------------------------------------//
+ // APV25 Analog Pipeline //
+ //-------------------------------------//
+ public class Apv25Pipeline extends RingBuffer {
+
+ // TODO: Possibly store the pipeline in the event
+
+ // Note: ptr gives the position of the trigger pointer
+ private int writerPointer = 0;
+
+ /**
+ * Constructor
+ */
+ public Apv25Pipeline(){
+
+ // Initialize the pipeline to the APV25 pipeline length
+ super(HPSSVTConstants.ANALOG_PIPELINE_LENGTH);
+
+ // Initialize the position of the trigger pointer to a random position
+ this.ptr = (int) (Math.random()*HPSSVTConstants.ANALOG_PIPELINE_LENGTH);
+ }
+
+ /**
+ *
+ */
+ public void resetPointerPositions(){
+ writerPointer = (ptr + triggerLatency)%HPSSVTConstants.ANALOG_PIPELINE_LENGTH;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void addToCell(int position, double element){
+ int writePosition = (writerPointer + position)%HPSSVTConstants.ANALOG_PIPELINE_LENGTH;
+ if(writePosition == this.ptr) return;
+ array[writePosition] += element;
+ }
+
+ /**
+ *
+ */
+ public double readout(){
+ double triggerPointerValue = this.currentValue();
+ array[ptr] = 0;
+ return triggerPointerValue;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void step(){
+ super.step();
+ writerPointer = (ptr + triggerLatency)%HPSSVTConstants.ANALOG_PIPELINE_LENGTH;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public String toString(){
+ String analogPipeline = "[ ";
+ for(int element = 0; element < HPSSVTConstants.ANALOG_PIPELINE_LENGTH; element++){
+ if(element == ptr) analogPipeline += " TP ===>";
+ else if(element == writerPointer) analogPipeline += " WP ===>";
+ analogPipeline += (array[element] + ", ");
+ }
+ analogPipeline += "] ";
+ return analogPipeline;
+ }
+
+ /**
+ *
+ */
+ public double getWriterPointerValue(){
+ return array[writerPointer];
+ }
+ }
+
+ //-----------------------------------//
+ // APV25 Shaper Signal //
+ //-----------------------------------//
+ public class Apv25ShaperSignal {
+
+ // Shaper signal maximum amplitude
+ private double maxAmp = 0;
+
+ /**
+ * Constructor
+ *
+ * @param charge: Charge injected into a channel
+ */
+ Apv25ShaperSignal(double charge) {
+ // Find the maximum amplitude of the shaper signal
+ maxAmp = (charge/HPSSVTConstants.MIP)*HPSSVTConstants.FRONT_END_GAIN; // mV
+ }
+
+ /**
+ * Get the amplitude at a time t
+ *
+ * @param time: time at which the shaper signal is to be sampled
+ */
+ public double getAmplitudeAtTime(double time, double shapingTime) {
+ return maxAmp * (Math.max(0, time) / shapingTime) * Math.exp(1 - (time / shapingTime));
+ }
+
+ }
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/DataProcessingModule.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/DataProcessingModule.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,117 @@
+package org.hps.recon.tracking.apv25;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.hps.conditions.deprecated.SvtUtils;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+/**
+ *
+ * @author Omar Moreno
+ * @version $Id: DataProcessingModule.java,v 1.1 2013/03/15 21:05:28 meeg Exp $
+ */
+public abstract class DataProcessingModule extends Driver{
+
+ Map<SiSensor, SvtDataBlocks> sensorToDataBlocks = new HashMap<SiSensor, SvtDataBlocks>();
+
+ // Collection Names
+ String apv25DigitalDataCollectionName = "AVP25DigitalData";
+ String rawTrackerHitsCollectionName = "SVTRawTrackerHits";
+
+ int nSamples = 0; // Number of samples which have been processed
+ int totalSamples = 6; // Number of samples which are read out
+
+ /**
+ * Set the number of shaper signal samples to be readout
+ */
+ public void setNumberOfSamplesToReadOut(int totalSamples){
+ this.totalSamples = totalSamples;
+ }
+
+ protected abstract List<RawTrackerHit> findRawHits();
+
+ @Override
+ public void detectorChanged(Detector detector){
+ for(SiSensor sensor : SvtUtils.getInstance().getSensors()){
+ sensorToDataBlocks.put(sensor, new SvtDataBlocks());
+ }
+ }
+
+ @Override
+ public void process(EventHeader event){
+
+ // If the event does not contain any data to process, skip it
+ if(!event.hasCollection(Apv25DigitalData.class, apv25DigitalDataCollectionName)) return;
+
+ // Get the digital data from the event
+ List<Apv25DigitalData> digitalData = event.get(Apv25DigitalData.class, apv25DigitalDataCollectionName);
+
+ // Block the data together
+ for(Apv25DigitalData digitalDatum : digitalData){
+ SiSensor sensor = digitalDatum.getSensor();
+ int apvN = digitalDatum.getApv();
+
+ double[] apv25DigitalOutput = new double[128];
+ System.arraycopy(digitalDatum.getSamples(), 0, apv25DigitalOutput, 0, apv25DigitalOutput.length);
+
+ for(int channel = 0; channel < apv25DigitalOutput.length; channel++){
+
+ // Calculate the physical number
+ int physicalChannel = 639 - (apvN*128 + 127 - channel);
+
+ sensorToDataBlocks.get(sensor).addSample(physicalChannel, nSamples, (short) apv25DigitalOutput[channel]);
+ }
+ }
+ nSamples++;
+
+ // If the expected number of samples has been collected, process the data
+ if(nSamples == totalSamples){
+
+ // Add RawTrackerHits to the event
+ event.put(rawTrackerHitsCollectionName, this.findRawHits(), RawTrackerHit.class, 0);
+ nSamples = 0;
+ }
+ }
+
+ protected class SvtDataBlocks {
+
+ Map<Integer /* sample number */, short[]> channelToSamples = new HashMap<Integer, short[]>();
+
+ /**
+ *
+ */
+ public SvtDataBlocks(){
+ }
+
+ public void addSample(Integer physicalChannel, int sampleN, short value){
+ if(!channelToSamples.containsKey(physicalChannel)) channelToSamples.put(physicalChannel, new short[6]);
+ channelToSamples.get(physicalChannel)[sampleN] = value;
+ }
+
+ /**
+ *
+ */
+ public short[] getSamples(int physicalChannel){
+ return channelToSamples.get(physicalChannel);
+ }
+
+ /**
+ *
+ */
+ public String printSamples(int physicalChannel){
+ String sampleString = "[ ";
+ short[] samples = this.getSamples(physicalChannel);
+ for(int index = 0; index < samples.length -1; index++){
+ sampleString += samples[index] + ", ";
+ }
+ sampleString += samples[samples.length - 1] + "]";
+ return sampleString;
+ }
+ }
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSAPV25.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSAPV25.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,353 @@
+package org.hps.recon.tracking.apv25;
+
+//--- Java ---//
+import java.util.HashMap;
+import java.util.Map;
+
+//--- org.lcsim ---//
+import org.hps.recon.tracking.apv25.HPSAPV25.APV25Channel.APV25AnalogPipeline;
+//--- hps-java ---//
+import org.lcsim.hps.util.ClockSingleton;
+import org.lcsim.hps.util.RingBuffer;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: HPSAPV25.java,v 1.8 2012/08/03 00:05:26 meeg Exp $
+ */
+public class HPSAPV25 {
+
+ //--- APV25 parameters ---//
+ //------------------------//
+ private static final double APV25_FRONT_END_GAIN = 100.0; // [mV/MIP]
+ private static final double APV25_MULTIPLEXER_GAIN = 1; // mA/MIP
+ private static final double APV25_NOISE_INTERCEPT_PEAK = 270; // e- RMS
+ private static final double APV25_NOISE_INTERCEPT_DECON = 396; //e- RMS
+ private static final double APV25_NOISE_SLOPE_PEAK = 36; // e- rms/pF
+ private static final double APV25_NOISE_SLOPE_DECON = 59.4; // e- rms/pF
+
+ // Number of electron-hole pairs created by a min. ionizing particle
+ // in 300 micrometers of Si
+ private static final int MIP = 25000; // electron-hole pairs
+
+ // Total number of channels per APV25 chip
+ private static final int APV25_CHANNELS = 128;
+
+ // APV25 trigger bit
+ public static boolean readoutBit = false;
+
+ //
+ private int apv25ShapingTime = 35; // [ns]
+ private int apv25SamplingTime = 24; // [ns]
+ private double analogDCLevel = 0; // [mA] (Pedestal)
+ public int apv25ClockCycle = 0;
+ private String apv25Mode = "multi-peak";
+
+ // APV25 Channel
+ private APV25Channel channel;
+
+ // Histograms
+ protected AIDA aida = AIDA.defaultInstance();
+
+ /**
+ * Constructor
+ */
+ public HPSAPV25() {
+ // Create a single instance of an APV25 channel
+ channel = new APV25Channel();
+
+ }
+
+ //--- Methods ---//
+ //---------------//
+ /**
+ * Set the APV25 shaping time
+ *
+ * @param shapingTime : APV25 shaping time
+ */
+ public void setShapingTime(int shapingTime) {
+ apv25ShapingTime = shapingTime;
+ }
+
+ /**
+ * Set the operating mode of the APV25 to either "peak",
+ * "deconvolution", or "multi-peak".
+ *
+ * @param mode : APV25 operating mode
+ */
+ public void setAPV25Mode(String mode) {
+ apv25Mode = mode;
+ }
+
+ /**
+ * Set the time interval at which the shaper output is sampled
+ *
+ * @param sampleTime : time interval
+ */
+ public void setSamplingTime(int sampleTime) {
+ apv25SamplingTime = sampleTime;
+ }
+
+ /**
+ *
+ */
+ public void setAnalogDCLevel(double dcLevel) {
+ analogDCLevel = dcLevel;
+ }
+
+ /**
+ * Return an instance of an APV25 channel. Currently, there is only a
+ * single instance of the channel ( instead of 128 that the actual chip
+ * has). However, the analog buffers of each channels are distinct and
+ * are stored in a sorted map for later use.
+ *
+ * @return an instance of APV25Channel
+ */
+ public APV25Channel getChannel() {
+ return channel;
+ }
+
+ /**
+ * Inject charge into a channel and shape the signal. The resulting
+ * shaper signal is then sampled into the analog pipeline
+ *
+ * @param charge : Total charge being injected
+ * @param pipeline : Analog pipeline associated with a channel
+ */
+ public void injectCharge(double charge, double noiseRMS, APV25AnalogPipeline pipeline) {
+
+ // Shape the injected charge
+ getChannel().shapeSignal(charge);
+
+ // Sample the resulting shaper signal
+ getChannel().sampleShaperSignal(pipeline, noiseRMS);
+ }
+
+ /**
+ * Increment the position of the trigger and writer pointers of all
+ * channels
+ *
+ * @param analogPipelineMap :
+ */
+ public void incrementAllPointerPositions(Map<Integer, APV25AnalogPipeline> analogPipelineMap) {
+ // Loop through all of the channels and increment the position of
+ // all the trigger and writer pointers
+ for (Map.Entry<Integer, APV25AnalogPipeline> entry : analogPipelineMap.entrySet()) {
+ entry.getValue().step();
+ }
+ }
+
+ /**
+ *
+ */
+ public int getSamplingTime() {
+ return apv25SamplingTime;
+ }
+
+ /**
+ * Increment the APV25 clock cycle by one
+ */
+ public void stepAPV25Clock() {
+ apv25ClockCycle += 1;
+ }
+
+ /**
+ *
+ */
+ public Map<Integer, double[]> APV25Multiplexer(
+ Map<Integer, APV25AnalogPipeline> pipelineMap) {
+
+ Map<Integer /* chip */, double[]> apv25Map = new HashMap<Integer, double[]>();
+
+ // The address of the APV25. There is only a single address for all
+ // chips
+ double[] apv25Address = {4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0};
+ double[] output;
+
+ // Create the data streams
+ for (int chipIndex = 0; chipIndex < Math.ceil((double) pipelineMap.size() / APV25_CHANNELS); chipIndex++) {
+ apv25Map.put(chipIndex, createOutputArray(apv25Address, -4));
+ }
+
+ // Loop over all channels and readout the cells which the
+ // trigger pointer points to
+ for (int channelN = 0; channelN < pipelineMap.size(); channelN++) {
+ output = apv25Map.get((int) Math.floor(channelN / APV25_CHANNELS));
+ output[channelN % 128 + 12] += (pipelineMap.get(channelN).readOut() / APV25_FRONT_END_GAIN) * APV25_MULTIPLEXER_GAIN + analogDCLevel;
+ }
+ return apv25Map;
+ }
+
+ /**
+ *
+ */
+ private double[] createOutputArray(double[] address, double error) {
+
+ // Create the array which will contain the output format. The array values
+ // will range from -4 microAmps to 4 microAmps.
+ double[] output = new double[141];
+ for (int index = 0; index < output.length; index++) {
+ output[ index] = -4.0; // microAmps
+ }
+
+ // Header
+ double[] header = {4.0, 4.0, 4.0};
+
+ // Fill the array with the header, address and error bit and tick
+ System.arraycopy(header, 0, output, 0, 3);
+ output[header.length] = error;
+ System.arraycopy(address, 0, output, 4, 8);
+ output[ output.length - 1] = 4.0;
+
+ return output;
+ }
+
+ //------------------------------------------//
+ // APV25 Channel //
+ //-----------------------------------------//
+ public class APV25Channel {
+
+ // Analog pipeline length
+ private static final int ANALOG_PIPELINE_LENGTH = 192;
+ // Shaper signal
+ private APV25ShaperSignal shaperSignal;
+
+ /**
+ * Constructor
+ */
+ public APV25Channel() {
+ }
+
+ /**
+ * Shape the injected charge
+ *
+ * @param charge
+ */
+ private void shapeSignal(double charge) {
+ shaperSignal = new APV25ShaperSignal(charge);
+ }
+
+ /**
+ * Return the noise in electrons for a given strip capacitance
+ *
+ * @param capacitance : strip capacitance in pF
+ * @return noise in electrons
+ */
+ public double computeNoise(double capacitance) {
+ if (apv25Mode.equals("peak") || apv25Mode.equals("multi-peak"))
+ return APV25_NOISE_INTERCEPT_PEAK + APV25_NOISE_SLOPE_PEAK * capacitance;
+ else return APV25_NOISE_INTERCEPT_DECON + APV25_NOISE_SLOPE_DECON * capacitance;
+ }
+
+ /**
+ * Sample the shaper signal and fill the analog pipeline.
+ *
+ * @param channel : Channel number
+ */
+ private void sampleShaperSignal(
+ APV25AnalogPipeline pipeline, double noiseRMS) {
+
+ // Obtain the beam time
+ double beam_time = ClockSingleton.getTime();
+
+ // Fill the analog pipeline starting with the cell to which
+ // the writer pointer is pointing to. Signals arriving within
+ // the same bucket of length apv25SamplingTime will be shifted
+ // in time depending on when they arrive.
+ for (int cell = 0; cell < ANALOG_PIPELINE_LENGTH; cell++) {
+
+ // Time at which the shaper signal will be sampled
+ int sample_time = cell * apv25SamplingTime
+ - ((int) beam_time) % apv25SamplingTime;
+ // Sample the shaper signal
+ double sample = shaperSignal.getAmplitudeAtTime(sample_time);
+
+ pipeline.addToCell(cell, sample);
+ }
+ }
+
+ //-----------------------------------//
+ //--- APV25 Shaper Signal ---//
+ //-----------------------------------//
+ /**
+ *
+ */
+ private class APV25ShaperSignal {
+
+ // Shaper signal maximum amplitude
+ private double maxAmp = 0;
+
+ /**
+ * Constructor
+ *
+ * @param charge : input charge into the channel
+ */
+ APV25ShaperSignal(double charge) {
+
+ maxAmp = (charge / MIP) * APV25_FRONT_END_GAIN; // mV
+
+ //--->
+ aida.histogram1D("Shaper Signal Max Amplitude", 100, 0, 500).fill(maxAmp);
+ //--->
+ }
+
+ /**
+ * Get the amplitude at a time t
+ *
+ * @param time : time at which the shaper signal is to be
+ * sampled
+ */
+ private double getAmplitudeAtTime(double time) {
+ return maxAmp * (Math.max(0, time) / apv25ShapingTime) * Math.exp(1 - (time / apv25ShapingTime));
+ }
+ }
+
+ //-------------------------------------//
+ //--- APV25 Analog Pipeline ---//
+ //-------------------------------------//
+ // Note that the buffer is modeled after a circular buffer
+ public class APV25AnalogPipeline extends RingBuffer {
+ private int _trigger_latency = (int) Math.floor(270 / apv25SamplingTime);
+
+ public APV25AnalogPipeline() { super(ANALOG_PIPELINE_LENGTH); }
+
+ /**
+ * Set the trigger latency
+ *
+ * @param latency : trigger latency in [ns]
+ */
+ public void setTriggerLatency(int latency) {
+ _trigger_latency = (int) Math.floor(latency / apv25SamplingTime);
+ }
+
+ private double readOut() {
+ double pipelineValue = currentValue();
+ array[0] = 0;
+ return pipelineValue;
+ }
+
+ @Override
+ public void addToCell(int position, double element) {
+ if (position + _trigger_latency > array.length) {
+ return;
+ }
+ super.addToCell(position + _trigger_latency, element);
+ }
+
+ public void printAnalogPipeline() {
+ System.out.print("[ ");
+ for (int index = 0; index < array.length; index++) {
+ if (index == ptr) {
+ System.out.print("TP====>");
+ }
+ if (index == ptr + _trigger_latency) {
+ System.out.print("WP====>");
+ }
+ System.out.print(array[index] + ", ");
+ }
+ System.out.println("] ");
+ }
+ }
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSDataProcessingModule.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSDataProcessingModule.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,398 @@
+package org.hps.recon.tracking.apv25;
+
+//--- Java ---//
+import static org.hps.conditions.deprecated.HPSSVTConstants.SVT_TOTAL_FPGAS;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_APV25_CHANNELS;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_APV25_PER_HYBRID;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_HYBRIDS_PER_FPGA;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+//--- org.lcsim ---//
+import java.util.Set;
+
+import org.hps.conditions.deprecated.SvtUtils;
+import org.hps.recon.tracking.HPSSVTData;
+import org.lcsim.detector.IReadout;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseRawTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+//--- Constants ---//
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: HPSDataProcessingModule.java,v 1.3 2013/03/15 21:05:28 meeg Exp $
+ */
+public class HPSDataProcessingModule extends Driver {
+
+ // A map relating a sensor to all sample blocks collected from that sensor
+ Map<SiSensor, Map<Integer, List<Double>>> sensorToSamplesMap;
+
+ // Relate a channel to its six samples
+ Map<Integer, List<Double>> channelToBlock;
+
+ // Relate a sensor Identifier to the actual sensor
+ Map<Long, SiSensor> sensorMap = new HashMap<Long, SiSensor>();
+
+ // Collection of all sensors
+ Set<SiSensor> sensorSet = new HashSet<SiSensor>();
+
+ // Collections of RawTrackerHits
+ List<RawTrackerHit> rawHits; // Cuts are applied
+ List<RawTrackerHit> rawHitsNoCuts; // No cuts are applied to samples
+
+ // Collection of all SVT data
+ List<HPSSVTData> svtData;
+ List<HPSSVTData> svtFpgaData;
+ List<Double> samples;
+
+ int numberOfSamples = 0; // Total number of APV25 samples
+ int nSamplesAboveThresh = 3; // Number of samples above noise threshold
+ int pedestal = 1638; // [ADC counts] For now, all channels have the same pedestal
+ int flags = 0; //
+ int noise = 18; // [ADC Counts] RMS noise
+ int noiseThreshold = 3; // Units of RMS noise
+ int physicalChannel;
+
+ private boolean thresholdCut = false; // Apply threshold cut?
+ private boolean tailCut = false; // Apply tail cut?
+ private boolean noiseSuppression = false; // Apply noise suppression?
+ boolean debug = false;
+
+ double[] apv25DataStream;
+
+ String RawTrackerHitsCollectionName = "RawTrackerHits";
+ String RawTrackerHitsNoCutsCollectionName = "RawTrackerHitsNoCuts";
+ String svtCollectionName = "SVTData";
+
+ /**
+ * Default Constructor
+ */
+ public HPSDataProcessingModule() {
+ channelToBlock = new HashMap<Integer, List<Double>>();
+ sensorToSamplesMap = new HashMap<SiSensor, Map<Integer, List<Double>>>();
+ rawHits = new ArrayList<RawTrackerHit>();
+ rawHitsNoCuts = new ArrayList<RawTrackerHit>();
+ svtData = new ArrayList<HPSSVTData>();
+ svtFpgaData = new ArrayList<HPSSVTData>();
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void detectorChanged(Detector detector) {
+
+ for (SiSensor sensor : SvtUtils.getInstance().getSensors()) {
+ // Map a sensor to its corresponding samples
+ sensorToSamplesMap.put(sensor, new HashMap<Integer, List<Double>>());
+ }
+ }
+
+ /**
+ * Set the SVT collection name
+ */
+ public void setSvtCollectionName(String svtCollectionName) {
+ this.svtCollectionName = svtCollectionName;
+ }
+
+ /**
+ * Set the number of samples above threshold a signal must have
+ */
+ public void setSamplesAboveThresh(int nSamplesAboveThresh) {
+ this.nSamplesAboveThresh = nSamplesAboveThresh;
+ }
+
+ /**
+ * Set the noise RMS [ADC Counts]
+ */
+ public void setNoise(int noise) {
+ this.noise = noise;
+ }
+
+ /**
+ * Set the noise threshold in units of RMS noise
+ */
+ public void setNoiseThreshold(int noiseThreshold) {
+ this.noiseThreshold = noiseThreshold;
+ }
+
+ /**
+ * Set the pedestal value for all channels
+ */
+ public void setPedestal(int pedestal) {
+ this.pedestal = pedestal;
+ }
+
+ /**
+ * Enable the threshold cut. The threshold cut requires a certain number
+ * of samples per hit to be above a noise threshold.
+ */
+ public void enableThresholdCut() {
+ this.thresholdCut = true;
+ }
+
+ /**
+ * Enable the tail cut. The tail cut requires sample 1 to be greater than
+ * sample 0 or sample 2 to be greater than sample 1. This eliminates
+ * hits that may arise due to shaper signal tails.
+ */
+ public void enableTailCut() {
+ this.tailCut = true;
+ }
+
+ /**
+ * Enable noise suppression cut. Requires samples 2 or 3 to be above a
+ * threshold noiseThreshold + noise.
+ */
+ public void enableNoiseSuppressionCut() {
+ this.noiseSuppression = true;
+ }
+
+ /**
+ * Buffer a sample that has been readout from a sensor.
+ *
+ * @param sensorToDigitalMap
+ * A map relating a sensor to the digital samples readout from the
+ * sensor
+ */
+ public void addSample(Map<SiSensor, Map<Integer, double[]>> sensorToDigitalMap) {
+
+ /*
+ * Integer: Chip Number
+ * double[]: APV25 Data Analog Data
+ */
+
+ int physicalChannel;
+
+ // Loop through the list of all sensors
+ for (Map.Entry<SiSensor, Map<Integer, double[]>> sensor : sensorToDigitalMap.entrySet()) {
+
+ // Loop through all APV25s
+ for (Map.Entry<Integer, double[]> chipData : sensor.getValue().entrySet()) {
+
+ // Copy the sample to avoid concurrent modification
+ apv25DataStream = chipData.getValue();
+
+ // Strip the APV25 data stream of all header information
+ apv25DataStream = Arrays.copyOfRange(apv25DataStream, 12, apv25DataStream.length - 1);
+
+ // Loop through all channels
+ for (int channel = 0; channel < apv25DataStream.length; channel++) {
+
+ physicalChannel = channel + chipData.getKey() * 128;
+
+ // Check if a block has been created for this channel. If not create it
+ if (!sensorToSamplesMap.get(sensor.getKey()).containsKey(physicalChannel)) {
+ sensorToSamplesMap.get(sensor.getKey()).put(physicalChannel, new ArrayList<Double>(6));
+ }
+ sensorToSamplesMap.get(sensor.getKey()).get(physicalChannel).add(apv25DataStream[channel]);
+ }
+ }
+ }
+ numberOfSamples++;
+ }
+
+ /**
+ * Finds hits that satisfied all required cuts and creates both
+ * RawTrackerHits and SVTData
+ */
+ public void findHits() {
+
+ int fpgaNumber, hybridNumber, apvNumber, rawChannel;
+
+ // Clear the list of raw tracker hits
+ rawHits.clear();
+ rawHitsNoCuts.clear();
+ svtData.clear();
+
+ // Loop through all sensors and the corresponding blocks
+ for (Map.Entry<SiSensor, Map<Integer, List<Double>>> sensor : sensorToSamplesMap.entrySet()) {
+
+ // Get the FPGA number
+ fpgaNumber = SvtUtils.getInstance().getFPGA(sensor.getKey());
+ if(fpgaNumber > SVT_TOTAL_FPGAS || fpgaNumber < 0)
+ throw new RuntimeException("FPGA Number out of range!");
+ if(debug) System.out.println(this.getClass().getSimpleName() + ": FPGA Number: " + fpgaNumber);
+
+ // Clear the temporary list
+ svtFpgaData.clear();
+
+ for (Map.Entry<Integer, List<Double>> samples : sensor.getValue().entrySet()) {
+ short[] adc = new short[6];
+
+ // Convert ADC value to a short
+ for (int index = 0; index < adc.length; index++)
+ adc[index] = samples.getValue().get(index).shortValue();
+
+ // If a strip had any charge deposited on it, create a RawTrackerHit
+ if(!(samplesAboveThreshold(adc) >= 1)){
+ samples.getValue().clear();
+ continue;
+ }
+
+ RawTrackerHit rawHit = makeRawTrackerHit(samples.getKey(), sensor.getKey(), adc);
+ rawHitsNoCuts.add(rawHit);
+
+ // Check if a block has the appropriate number of blocks above threshold
+ if (thresholdCut && !(samplesAboveThreshold(adc) >= nSamplesAboveThresh)) {
+ samples.getValue().clear();
+ continue;
+ }
+
+ // Apply the tail cut
+ if (tailCut && !tailCut(adc)) {
+ samples.getValue().clear();
+ continue;
+ }
+
+ // Apply noise suppression cut
+ if (noiseSuppression && !noiseSuppressionCut(adc)) {
+ samples.getValue().clear();
+ continue;
+ }
+
+ // If all cuts are satisfied, add the hit to the list of hits to be saved
+ rawHits.add(rawHit);
+
+ // Get the hybrid number
+ hybridNumber = SvtUtils.getInstance().getHybrid(sensor.getKey());
+ if(hybridNumber > TOTAL_HYBRIDS_PER_FPGA || hybridNumber < 0)
+ throw new RuntimeException("Hybrid number is out of range!");
+ //if(debug) System.out.println(this.getClass().getSimpleName() + ": Hybrid Number: " + hybridNumber);
+
+ // Find the APV number. Note that strip numbering is from 639 to 0
+ apvNumber = (TOTAL_APV25_PER_HYBRID - 1) - (int) Math.floor(samples.getKey()/128);
+ if(apvNumber > TOTAL_APV25_PER_HYBRID || apvNumber < 0)
+ throw new RuntimeException("APV25 Number out of range!");
+ //if(debug) System.out.println(this.getClass().getSimpleName() + ": APV Number: " + apvNumber);
+
+ // Find the raw channel number from the physical channel
+ rawChannel = samples.getKey() - (TOTAL_APV25_CHANNELS*TOTAL_APV25_PER_HYBRID - 1)
+ + apvNumber*TOTAL_APV25_CHANNELS + (TOTAL_APV25_CHANNELS - 1);
+ if(rawChannel > TOTAL_APV25_CHANNELS || rawChannel < 0)
+ throw new RuntimeException("APV25 Channel " + rawChannel + " out of range!");
+ //if(debug) System.out.println(this.getClass().getSimpleName() + ": Raw Channel Number: " + rawChannel);
+
+ // Create an svtData packet
+ HPSSVTData data = new HPSSVTData(hybridNumber, apvNumber, rawChannel, fpgaNumber, adc);
+ svtData.add(data);
+ svtFpgaData.add(data);
+
+ samples.getValue().clear();
+ }
+
+ HPSSVTDataBuffer.addToBuffer(svtFpgaData, fpgaNumber);
+ }
+ if(debug) System.out.println(this.getClass().getName() + ": Total RawTrackerHits before cuts: " + rawHitsNoCuts.size());
+ if(debug) System.out.println(this.getClass().getName() + ": Total RawTrackerHits: " + rawHits.size());
+ if(debug) System.out.println(this.getClass().getName() + ": Total SVTData: " + svtData.size());
+ }
+
+ /**
+ * Creates a rawTrackerHit
+ *
+ * @param channelNumber
+ * Si Strip from which the hit originates from
+ * @param sensor
+ * Sensor from which the hit originates from
+ * @param adcValues
+ * Shaper signal samples
+ * @return RawTrackerHit
+ */
+ private RawTrackerHit makeRawTrackerHit(Integer channelNumber, SiSensor sensor, short[] adcValues) {
+ IReadout ro = sensor.getReadout();
+
+ // No time yet
+ int time = 0;
+ long cell_id = sensor.makeStripId(channelNumber, 1).getValue();
+
+ RawTrackerHit rawHit = new BaseRawTrackerHit(time, cell_id, adcValues, new ArrayList<SimTrackerHit>(), sensor);
+
+ ro.addHit(rawHit);
+
+ return rawHit;
+ }
+
+ /**
+ * Finds how many samples are above a given threshold
+ *
+ * @param adc
+ * Shaper signal samples
+ * @return Number of samples above threshold
+ */
+ private int samplesAboveThreshold(short[] adc) {
+ // Number of samples above threshold
+ int nSamplesAboveThreshold = 0;
+
+ for (int sample = 0; sample < adc.length; sample++) {
+ if (adc[sample] >= pedestal + noiseThreshold * noise) {
+ nSamplesAboveThreshold++;
+ }
+ }
+ return nSamplesAboveThreshold;
+ }
+
+ /**
+ * Applies tail cut
+ *
+ * @param adc
+ * Shaper signal samples
+ * @return true if the cut is satisfied, false otherwise
+ */
+ private boolean tailCut(short[] adc) {
+ if (adc[3] > adc[2] || adc[4] > adc[3]) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Applies noise suppression cut
+ *
+ * @param adc
+ * Shaper signal samples
+ * @return true if the cut is satisfied, false otherwise
+ */
+ private boolean noiseSuppressionCut(short[] adc) {
+ if (adc[3] > pedestal + noiseThreshold * noise || adc[4] > pedestal + noiseThreshold * noise) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void process(EventHeader event) {
+ super.process(event);
+
+ // If six samples have been collected process the data
+ if (numberOfSamples == 6) {
+
+ // Find hits
+ findHits();
+
+ // Add RawTrackerHits to the event
+ event.put(RawTrackerHitsCollectionName, rawHits, RawTrackerHit.class, flags);
+
+ // Add SVTData to event
+ System.out.println("Adding SVTData Collection of size: " + svtData.size() + " to the Event");
+ event.put(this.svtCollectionName, this.svtData, HPSSVTData.class, 0);
+
+
+ //
+ numberOfSamples = 0;
+ }
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSRTM.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSRTM.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,127 @@
+
+package org.hps.recon.tracking.apv25;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: HPSRTM.java,v 1.3 2013/03/15 21:05:28 meeg Exp $
+ */
+public class HPSRTM {
+
+ private Map<Integer, double[]> analogData;
+ private Map<Integer, double[]> digitalData;
+
+ private static double INPUT_STAGE_GAIN = 2;
+ private static double RESISTOR_VALUE = 100; // Ohms
+
+ double adcHighRef = 1000; // mVolts
+ double adcLowRef = -1000; // mVolts
+ double adcResolution = 0; //bits
+ double adcVoltageResolution = 0; // Volts
+ int voltageIntervals;
+
+
+ /**
+ * Constructor
+ */
+ public HPSRTM(int bits)
+ {
+ // To do: In order to increase speed, HashMap should be initialized
+ // to a specified capacity
+ digitalData = new HashMap<Integer, double[]>();
+
+ adcResolution = bits;
+ voltageIntervals = (int) Math.pow(2, bits);
+
+ adcVoltageResolution
+ = (adcHighRef - adcLowRef)/voltageIntervals; // mV
+
+ }
+
+ //--- Methods ---//
+ //---------------//
+
+
+ /**
+ *
+ * @param data
+ */
+ public Map<Integer, double[]> digitize( Map<Integer, double[]> data )
+ {
+ digitalData = data;
+
+ // Amplify the incoming analog signal
+ amplifySignal();
+
+ // Loop over all apv25 analog signals and digitize them
+ for(Map.Entry<Integer, double[]> entry : digitalData.entrySet()){
+
+
+
+ // Aquire the amplified signal
+ double[] digitalSignal = entry.getValue();
+
+ // Digitize the apv25 output
+ for(int index = 0; index < digitalSignal.length; index++){
+
+ digitalSignal[index]
+ = Math.floor((digitalSignal[index]
+ - adcLowRef)/adcVoltageResolution);
+ }
+
+ digitalData.put(entry.getKey(), digitalSignal);
+
+ }
+
+ return digitalData;
+ }
+
+ /**
+ *
+ */
+ public void amplifySignal()
+ {
+
+ // Loop over all apv25 analog data
+ for(Map.Entry<Integer, double[]> entry : digitalData.entrySet() )
+ {
+ // Obtain the apv25 output
+ double[] apv25Output = entry.getValue();
+
+ for(int index = 0; index < apv25Output.length; index++ ){
+
+ // Convert input current to voltage
+ apv25Output[index] *= RESISTOR_VALUE;
+
+ // Amplify the input signal
+ apv25Output[index] *= INPUT_STAGE_GAIN;
+ }
+
+ // Store the amplified APV25 output
+ digitalData.put(entry.getKey(), apv25Output);
+
+ }
+ }
+
+ /**
+ *
+ */
+ public void setResolution( int bits )
+ {
+ adcResolution = bits;
+ }
+
+ /**
+ *
+ */
+ public void printData()
+ {
+
+ double[] data = digitalData.get("1");
+ System.out.println(data.length);
+ System.out.println(" ]");
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSSVTDataBuffer.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSSVTDataBuffer.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,158 @@
+
+package org.hps.recon.tracking.apv25;
+
+import static org.hps.conditions.deprecated.HPSSVTConstants.SVT_TOTAL_FPGAS;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TEMP_MASK;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+// Constants
+import org.hps.recon.tracking.FpgaData;
+import org.hps.recon.tracking.HPSSVTData;
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: HPSSVTDataBuffer.java,v 1.1 2013/03/15 21:05:28 meeg Exp $
+ */
+public class HPSSVTDataBuffer {
+
+ // Map the FPGA to the data emerging from it
+ private Map<Integer, List<Integer>> fpgaToData = new HashMap<Integer, List<Integer>>();
+
+ // Singleton
+ private static final HPSSVTDataBuffer instance = new HPSSVTDataBuffer();
+ private static int eventNumber = 0;
+
+ int[] header = new int[6];
+ int temp = FpgaData.temperatureToInt(23.0); // C
+
+ boolean debug = false;
+
+ /**
+ * Default constructor; Set to private to prevent instantiation
+ */
+ private HPSSVTDataBuffer(){
+ //
+ for(int fpgaNumber = 0; fpgaNumber <= SVT_TOTAL_FPGAS; fpgaNumber++)
+ fpgaToData.put(fpgaNumber, new ArrayList<Integer>());
+ }
+
+ /**
+ * Add data to SVT buffer
+ *
+ * @param svtData : List of SVT data packets
+ * @param fpga : FPGA from which the data emerges from
+ */
+ public static void addToBuffer(List<HPSSVTData> svtData, int fpga){
+ // If the FPGA data block is empty, add header information and data, otherwise
+ // just add the data
+ instance.encapsulateSVTData(svtData, fpga);
+ }
+
+ /**
+ * Readout data stored in the SVT buffer
+ *
+ * @param fpga : FPGA from which data is to be read from
+ * @return data : An FPGA data packet
+ *
+ */
+ public static int[] readoutBuffer(int fpga){
+ // Add the event number to the beginning
+ instance.addEventNumber(fpga);
+
+ // Add the tail to the data
+ instance.addTail(fpga);
+
+ // Copy the data in the map so that the buffer can be cleared
+ int[] data = new int[instance.fpgaToData.get(fpga).size()];
+ int index = 0;
+ for(Integer datum : instance.fpgaToData.get(fpga)){
+ data[index] = datum;
+ index++;
+ }
+
+ // Clear the buffer
+ instance.fpgaToData.get(fpga).clear();
+
+ // Return the
+ return data;
+ }
+
+ /**
+ * Encapsulate SVT data by FPGA
+ *
+ * @param svtData : List of SVT data packets
+ * @param fpga : FPGA from which the data emerges from
+ */
+ private void encapsulateSVTData(List<HPSSVTData> svtData, int fpga){
+ // Ignore FPGA 7 for now
+ if(fpga == 7) return;
+
+ // If the FPGA data block is empty, add the header information and increment the event number
+ if(instance.fpgaToData.get(fpga).isEmpty()){
+
+ // Insert the temperature information. All temperatures are currently
+ // set to 23 C
+ header[0] = (header[0] &= ~TEMP_MASK) | (temp & TEMP_MASK);
+ header[0] = (header[0] &= ~(TEMP_MASK << 16)) | ((temp & TEMP_MASK) << 16);
+
+ header[1] = (header[1] &= ~TEMP_MASK) | (temp & TEMP_MASK);
+ header[1] = (header[1] &= ~(TEMP_MASK << 16)) | ((temp & TEMP_MASK) << 16);
+
+ header[2] = (header[2] &= ~TEMP_MASK) | (temp & TEMP_MASK);
+ header[2] = (header[2] &= ~(TEMP_MASK << 16)) | ((temp & TEMP_MASK) << 16);
+
+ header[3] = (header[3] &= ~TEMP_MASK) | (temp & TEMP_MASK);
+ header[3] = (header[3] &= ~(TEMP_MASK << 16)) | ((temp & TEMP_MASK) << 16);
+
+ header[4] = (header[4] &= ~TEMP_MASK) | (temp & TEMP_MASK);
+ header[4] = (header[4] &= ~(TEMP_MASK << 16)) | ((temp & TEMP_MASK) << 16);
+
+ header[5] = (header[5] &= ~TEMP_MASK) | (temp & TEMP_MASK);
+ header[5] = (header[5] &= ~(TEMP_MASK << 16)) | ((temp & TEMP_MASK) << 16);
+
+ for(int index = 0; index < header.length; index++) fpgaToData.get(fpga).add(header[index]);
+
+ eventNumber++;
+ }
+
+ // Add all samples emerging from this FPGA
+ if(!svtData.isEmpty()){
+ for(HPSSVTData svtDatum : svtData){
+ if(debug){
+ System.out.println("FPGA: " + svtDatum.getFPGAAddress() + " Hybrid: " + svtDatum.getHybridNumber() + " APV: "
+ + svtDatum.getAPVNumber() + " Channel: " + svtDatum.getChannelNumber());
+ }
+ for(int index = 0; index < svtDatum.getData().length; index++){
+ fpgaToData.get(fpga).add(svtDatum.getData()[index]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Add a tail to the FPGA data packet. In real data, this may be
+ * non-zero which would indicate an error.
+ *
+ * @param fpga : FPGA from which the data emerges from
+ */
+ private void addTail(int fpga){
+
+ // For now just make it zero
+ instance.fpgaToData.get(fpga).add(0);
+ }
+
+ /**
+ * Add an SVT event number to the top of the FPGA data packet.
+ *
+ * @param fpga : FPGA from which the data emerges from
+ */
+ private void addEventNumber(int fpga){
+
+ instance.fpgaToData.get(fpga).add(0, eventNumber);
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSSiSensorReadout.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/HPSSiSensorReadout.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,474 @@
+package org.hps.recon.tracking.apv25;
+
+//--- Java ---//
+import hep.aida.ref.histogram.Profile1D;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Queue;
+import java.util.Random;
+import java.util.Set;
+
+//--- apache ---//
+import org.apache.commons.math.MathException;
+import org.apache.commons.math.distribution.BinomialDistribution;
+import org.apache.commons.math.distribution.BinomialDistributionImpl;
+import org.apache.commons.math.distribution.NormalDistribution;
+import org.apache.commons.math.distribution.NormalDistributionImpl;
+import org.hps.conditions.deprecated.SvtUtils;
+//--- hps-java ---//
+import org.hps.recon.tracking.apv25.HPSAPV25.APV25Channel.APV25AnalogPipeline;
+//--- org.lcsim ---//
+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.EventHeader;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.util.ClockSingleton;
+import org.lcsim.math.probability.Erf;
+import org.lcsim.recon.tracking.digitization.sisim.CDFSiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeData;
+import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeDataCollection;
+import org.lcsim.recon.tracking.digitization.sisim.SiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ * Class used to Readout HPS APV25's
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: HPSSiSensorReadout.java,v 1.12 2013/03/15 21:05:28 meeg Exp $
+ */
+public class HPSSiSensorReadout extends Driver {
+
+ //
+ boolean debug = true;
+ String subdetectorName = "tracker";
+ // Array to store the trigger time
+ public static final List<Double> triggerTimeStamp = new ArrayList<Double>();
+ //
+ List<String> readouts = new ArrayList<String>();
+ // FIFO queue to store trigger times
+ public Queue<Integer> triggerQueue;
+ private HPSAPV25 apv25;
+ private SiSensorSim siSimulation;
+ private HPSRTM rtm;
+ private HPSDataProcessingModule dpm;
+ private static Random random = new Random();
+ private static BinomialDistribution binomial = new BinomialDistributionImpl(1, 1);
+ private static NormalDistribution gaussian = new NormalDistributionImpl(0.0, 1.0);
+ private double noiseThreshold = 4; // e- RMS
+ private boolean addNoise = false;
+ // A map used to associate a sensor to the channels and analog pipelines
+ // of the APV25s being used to readout the sensor
+ public Map<SiSensor /* sensor */, Map<Integer /* channel */, APV25AnalogPipeline>> sensorToPipelineMap;
+ // A map used to associate an APV25 channel to its analog pipeline
+ public Map<Integer /* channel */, APV25AnalogPipeline> analogPipelineMap;
+ // A map used to associate a sensor to the output of the APV25s being
+ // used to readout the sensor
+ public Map<SiSensor, Map<Integer /* chip # */, double[]>> sensorToAnalogDataMap;
+ // A map used to associate a sensor to the digitized output of the APV25s
+ // being used to readout the sensor
+ public Map<SiSensor, Map<Integer /*chip # */, double[]>> sensorToDigitalDataMap;
+ //
+ public Map<Integer, double[]> analogData;
+ public Map<Integer, double[]> digitalData;
+ //
+ protected AIDA aida = AIDA.defaultInstance();
+ public Profile1D pipe;
+ int n_events = 0;
+
+ /**
+ * Constructor
+ */
+ public HPSSiSensorReadout() {
+
+ sensorToPipelineMap = new HashMap<SiSensor, Map<Integer, APV25AnalogPipeline>>();
+ sensorToAnalogDataMap = new HashMap<SiSensor, Map<Integer, double[]>>();
+ sensorToDigitalDataMap = new HashMap<SiSensor, Map<Integer, double[]>>();
+
+ //--- Sensor Simulation ---//
+ //-------------------------//
+ siSimulation = new CDFSiSensorSim();
+
+ //--- APV25 Simulation ---//
+ //------------------------//
+ apv25 = new HPSAPV25();
+ // Set the APV25 Shaping time [ns]
+ apv25.setShapingTime(35);
+ // Set the APV25 operating mode
+ apv25.setAPV25Mode("multi-peak");
+ // Set the APV25 analog pipeline sampling time
+ apv25.setSamplingTime(24);
+
+ //
+ rtm = new HPSRTM(14);
+
+ // Instantiate the DPM
+ dpm = new HPSDataProcessingModule();
+ dpm.setNoise(18);
+ dpm.setNoiseThreshold(2);
+ dpm.setSamplesAboveThresh(3);
+ dpm.setPedestal(1638);
+ dpm.enableThresholdCut();
+ dpm.enableTailCut();
+
+ add(dpm);
+
+ // Instantiate trigger time queue
+ triggerQueue = new LinkedList<Integer>();
+
+ // Specify the readouts to process
+ readouts.add("TrackerHits");
+
+ }
+
+ public void setAddNoise(boolean addNoise) {
+ this.addNoise = addNoise;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void detectorChanged(Detector detector) {
+ // Call the sub-Drivfer's detectorChanged methods
+ super.detectorChanged(detector);
+
+ // Instantiate all maps
+ for (SiSensor sensor : SvtUtils.getInstance().getSensors()) {
+
+ sensorToPipelineMap.put(sensor, new HashMap<Integer, APV25AnalogPipeline>());
+
+ // Instantiate all analog pipelines
+ for (int channel = 0; channel < sensor.getReadoutElectrodes(ChargeCarrier.HOLE).getNCells(); channel++) {
+ sensorToPipelineMap.get(sensor).put(channel, apv25.getChannel().new APV25AnalogPipeline());
+ }
+
+ if (debug) {
+ System.out.println(this.getClass().getSimpleName() + ": Sensor: " + sensor.getName()
+ + ": Number of Analog Pipelines: " + sensorToPipelineMap.get(sensor).size());
+ }
+
+ sensorToAnalogDataMap.put(sensor, new HashMap<Integer, double[]>());
+ sensorToDigitalDataMap.put(sensor, new HashMap<Integer, double[]>());
+ }
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void startOfData() {
+ // Set up readouts if they haven't been set
+ if (!readouts.isEmpty()) {
+ super.add(new SimTrackerHitReadoutDriver(readouts));
+ }
+
+ super.startOfData();
+ readouts.clear();
+
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void process(EventHeader event) {
+
+
+ super.process(event);
+
+ if ((ClockSingleton.getTime() + ClockSingleton.getDt()) % 24 == 0) {
+ for (Map.Entry<SiSensor, Map<Integer, APV25AnalogPipeline>> sensor : sensorToPipelineMap.entrySet()) {
+ apv25.incrementAllPointerPositions(sensor.getValue());
+ }
+ apv25.stepAPV25Clock();
+ }
+
+ // Loop over all sensors
+ for (SiSensor sensor : SvtUtils.getInstance().getSensors()) {
+ // Readout the sensors
+ readoutSensor(sensor);
+ }
+
+ // If a trigger is received readout the APV25 and digitize all hits
+ if (HPSAPV25.readoutBit) {
+
+ triggerTimeStamp.add(ClockSingleton.getTime());
+
+ // Only add the trigger if there isn't another trigger being
+ // processed
+ if (!triggerQueue.contains(apv25.apv25ClockCycle)) {
+ // Add the time at which each of the six samples should be
+ // collected to the trigger queue
+ for (int sample = 0; sample < 6; sample++) {
+ triggerQueue.offer(apv25.apv25ClockCycle + sample);
+ }
+ }
+ // Reset the APV25 trigger bit
+ HPSAPV25.readoutBit = false;
+ }
+
+ // Process any triggers in the queue
+ if (triggerQueue.peek() != null) {
+
+ // Remove any samples that might have already been processed
+ if (triggerQueue.peek() < apv25.apv25ClockCycle) {
+ for (int sample = 0; sample < 6; sample++) {
+ triggerQueue.remove();
+ }
+ } else if (triggerQueue.peek() == apv25.apv25ClockCycle) {
+ readoutAPV25();
+ triggerQueue.remove();
+ }
+ }
+ }
+
+ /**
+ * Readout the electrodes of an HPS Si sensor and inject the charge into
+ * the APV25 readout chip.
+ *
+ * @param sensor : HPS Si sensor
+ */
+ public void readoutSensor(SiSensor sensor) {
+ // Set the sensor to be used in the charge deposition simulation
+ siSimulation.setSensor(sensor);
+
+ // Perform the charge deposition simulation
+ Map<ChargeCarrier, SiElectrodeDataCollection> electrodeDataMap = siSimulation.computeElectrodeData();
+
+ // Loop over each charge carrier (electron or hole)
+ for (ChargeCarrier carrier : ChargeCarrier.values()) {
+
+ // If the sensor is capable of collecting the given charge carrier
+ // then obtain the electrode data for the sensor
+ if (sensor.hasElectrodesOnSide(carrier)) {
+
+ SiElectrodeDataCollection electrodeDataCol = electrodeDataMap.get(carrier);
+
+ // If there is no electrode data available create a new instance of electrode data
+ if (electrodeDataCol == null) {
+ electrodeDataCol = new SiElectrodeDataCollection();
+ }
+
+ // Get the readout electrodes
+ SiSensorElectrodes readoutElectrodes = sensor.getReadoutElectrodes(carrier);
+
+ // Add noise to the electrodes
+ if (addNoise) {
+ addNoise(electrodeDataCol, readoutElectrodes);
+ }
+
+ // Get the analog pipeline map associated with this sensor
+ analogPipelineMap = sensorToPipelineMap.get(sensor);
+
+ // Loop over all channels
+ for (Integer channel : electrodeDataCol.keySet()) {
+
+ // Get the electrode data for this channel
+ SiElectrodeData electrodeData = electrodeDataCol.get(channel);
+
+ // Get the charge in units of electrons
+ double charge = electrodeData.getCharge();
+
+ //====> Charge deposition on electrode
+ aida.histogram1D("Charge", 100, 0, 200000).fill(charge);
+ //====>
+
+ // Get the RMS noise for this channel
+ double noise = apv25.getChannel().computeNoise(
+ readoutElectrodes.getCapacitance(channel));
+
+ //===>
+ aida.histogram1D(this.getClass().getName() + " - RMS Noise - All Channels", 1000, 3500, 4500).fill(noise);
+ //===>
+
+ // Check to see if an analog pipeline for this channel
+ // exist. If it doesn't, create one.
+ if (!analogPipelineMap.containsKey(channel)) {
+ analogPipelineMap.put(channel,
+ apv25.getChannel().new APV25AnalogPipeline());
+ }
+
+ // Get the analog pipeline associated with this channel
+ APV25AnalogPipeline pipeline = analogPipelineMap.get(channel);
+
+ // Inject the charge into the APV25 amplifier chain
+ apv25.injectCharge(charge, noise, pipeline);
+ }
+ }
+ }
+
+ // Place the analog pipeline back into the sensor map
+ sensorToPipelineMap.put(sensor, analogPipelineMap);
+
+ // Clear the sensors of all deposited charge
+ siSimulation.clearReadout();
+ }
+
+ /**
+ *
+ */
+ public void readoutAPV25() {
+ // Readout all apv25s
+ for (Map.Entry<SiSensor, Map<Integer, APV25AnalogPipeline>> sensor : sensorToPipelineMap.entrySet()) {
+ sensorToAnalogDataMap.put(sensor.getKey(), apv25.APV25Multiplexer(sensor.getValue()));
+ }
+
+ // Digitize all signals
+ for (Map.Entry<SiSensor, Map<Integer, double[]>> sensor : sensorToAnalogDataMap.entrySet()) {
+ sensorToDigitalDataMap.put(sensor.getKey(), rtm.digitize(sensor.getValue()));
+ }
+
+ // Buffer the samples for further processing
+ //---> Needs to change!
+ dpm.addSample(sensorToDigitalDataMap);
+ //--->
+ }
+
+ /**
+ *
+ * @param electrodeDataCol
+ * @param electrodes
+ */
+ public void addNoise(SiElectrodeDataCollection electrodeDataCol,
+ SiSensorElectrodes electrodes) {
+ // First add readout noise to the strips in the
+ // SiElectrodeDataCollection.
+
+ // Loop over the entries in the SiElectrodeDataCollection
+ for (Entry electrodeDatum : electrodeDataCol.entrySet()) {
+
+ // Get the channel number and electrode data for this entry
+ int channel = (Integer) electrodeDatum.getKey();
+ SiElectrodeData electrodeData = (SiElectrodeData) electrodeDatum.getValue();
+
+ // Get the RMS noise for this channel in units of electrons
+ double noise = apv25.getChannel().computeNoise(
+ electrodes.getCapacitance(channel));
+
+ // Add readout noise to the deposited charge
+ int noiseCharge = (int) Math.round(random.nextGaussian() * noise);
+ electrodeData.addCharge(noiseCharge);
+ }
+
+ // Find the number of strips that are not currently hit
+ int nElectrodes = electrodes.getNCells();
+ int nElectrodesEmpty = nElectrodes - electrodeDataCol.size();
+
+ // Get the noise threshold in units of the noise charge
+
+ // Calculate how many channels should get noise hits
+ double integral = Erf.phic(noiseThreshold);
+ int nChannelsThrow = drawBinomial(nElectrodesEmpty, integral);
+
+ // Now throw Gaussian randoms above the seed threshold and put signals
+ // on unoccupied channels
+ for (int ithrow = 0; ithrow < nChannelsThrow; ithrow++) {
+ // Throw to get a channel number
+ int channel = random.nextInt(nElectrodes);
+ while (electrodeDataCol.keySet().contains(channel)) {
+ channel = random.nextInt(nElectrodes);
+ }
+
+ // Calculate the noise for this channel in units of electrons
+ double noise = apv25.getChannel().computeNoise(
+ electrodes.getCapacitance(channel));
+
+ // Throw Gaussian above threshold
+ int charge = (int) Math.round(drawGaussianAboveThreshold(integral) * noise);
+
+ // Add the noise hit to the electrode data collection
+ electrodeDataCol.add(channel, new SiElectrodeData(charge));
+ }
+
+ // Now throw to lower threshold on channels that neighbor hits until
+ // we are exhausted
+
+ nChannelsThrow = 1;
+ while (nChannelsThrow > 0) {
+
+ // Get neighbor channels
+ Set<Integer> neighbors = new HashSet<Integer>();
+ for (int channel : electrodeDataCol.keySet()) {
+ neighbors.addAll(electrodes.getNearestNeighborCells(channel));
+ }
+ neighbors.removeAll(electrodeDataCol.keySet());
+
+ nElectrodesEmpty = neighbors.size();
+
+ integral = Erf.phic(noiseThreshold);
+ nChannelsThrow = drawBinomial(nElectrodesEmpty, integral);
+
+ // Now throw Gaussian randoms above a threshold and put signals on
+ // unoccopied channels
+ for (int ithrow = 0; ithrow < nChannelsThrow; ithrow++) {
+
+ // Throw to get a channel number
+ List<Integer> neighborList = new ArrayList<Integer>(neighbors);
+
+ int channel = neighborList.get(random.nextInt(nElectrodesEmpty));
+
+ while (electrodeDataCol.keySet().contains(channel)) {
+ channel = neighborList.get(random.nextInt(nElectrodesEmpty));
+
+ }
+
+ // Calculate the noise for this channel in units of electrons
+ double noise = apv25.getChannel().computeNoise(
+ electrodes.getCapacitance(channel));
+
+ // Throw Gaussian above threshold
+ int charge = (int) Math.round(drawGaussianAboveThreshold(integral) * noise);
+
+ // Add the noise hit to the electrode data collection
+ electrodeDataCol.add(channel, new SiElectrodeData(charge));
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public static int drawBinomial(int ntrials, double probability) {
+ binomial.setNumberOfTrials(ntrials);
+ binomial.setProbabilityOfSuccess(probability);
+
+ int nsuccess = 0;
+ try {
+ nsuccess = binomial.inverseCumulativeProbability(random.nextDouble());
+ } catch (MathException exception) {
+ throw new RuntimeException("APV25 failed to calculate inverse cumulative probability of binomial!");
+ }
+ return nsuccess;
+ }
+
+ /**
+ * Return a random variable following normal distribution, but beyond
+ * threshold provided during initialization.
+ */
+ public static double drawGaussianAboveThreshold(double prob_above_threshold) {
+ double cumulative_probability;
+
+ cumulative_probability = 1.0 + prob_above_threshold * (random.nextDouble() - 1.0);
+
+ assert cumulative_probability < 1.0 : "cumulProb=" + cumulative_probability + ", probAboveThreshold=" + prob_above_threshold;
+ assert cumulative_probability >= 0.0 : "cumulProb=" + cumulative_probability + ", probAboveThreshold=" + prob_above_threshold;
+
+ double gaussian_random = 0;
+ try {
+ gaussian_random = gaussian.inverseCumulativeProbability(cumulative_probability);
+ } catch (MathException e) {
+ System.out.println("MathException caught: " + e);
+ }
+
+ return gaussian_random;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/RearTransitionModule.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/RearTransitionModule.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,135 @@
+package org.hps.recon.tracking.apv25;
+
+//--- java ---//
+//--- Constants ---//
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants;
+import org.hps.conditions.deprecated.HPSSVTConstants;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_STRIPS_PER_SENSOR;
+//--- org.lcsim ---//
+import org.lcsim.event.EventHeader;
+import org.lcsim.hps.util.RandomGaussian;
+import org.lcsim.util.Driver;
+//--- hps-java ---//
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: RearTransitionModule.java,v 1.2 2013/04/25 22:11:14 meeg Exp $
+ */
+public class RearTransitionModule extends Driver {
+
+ String apv25AnalogDataCollectionName = "APV25AnalogData";
+ String apv25DigitalDataCollectionName = "AVP25DigitalData";
+
+ double adcVHighRef = 1000; // mVolts
+ double adcVLowRef = -1000; // mVolts
+ int adcResolution = 14; // bits
+ double adcVoltageResolution = 1; // mV
+ int quantizationLevels = 256;
+
+ double resistorValue = 100; // Ohms
+ double inputStageGain = 1.5;
+
+ boolean noiseless = false;
+
+ /**
+ * Default Ctor
+ */
+ public RearTransitionModule(){
+
+ // Find the number of quantization levels
+ int quantizationLevels = (int) Math.pow(2, adcResolution);
+
+ // Find the ADC voltage resolution
+ adcVoltageResolution = (adcVHighRef - adcVLowRef)/quantizationLevels; // mV
+ }
+
+ /**
+ *
+ */
+ public void setResolution(int bits){
+ adcResolution = bits;
+
+ // Find the number of quantization levels
+ quantizationLevels = (int) Math.pow(2, adcResolution);
+
+
+ // Find the ADC voltage resolution
+ adcVoltageResolution = (adcVHighRef - adcVLowRef)/quantizationLevels; // mV
+ }
+
+ /**
+ *
+ */
+ public void setADCSpan(double adcVHighRef, double adcVLowRef){
+ this.adcVHighRef = adcVHighRef;
+ this.adcVLowRef = adcVLowRef;
+
+ // Find the ADC voltage resolution
+ adcVoltageResolution = (adcVHighRef - adcVLowRef)/quantizationLevels; // mV
+ }
+
+ /**
+ * Turn readout noise on/off
+ */
+ public void setNoiseless(boolean noiseless){
+ this.noiseless = noiseless;
+ }
+
+ /**
+ *
+ */
+ @Override
+ protected void process(EventHeader event){
+ super.process(event);
+
+ // If the event does not contain any analog data that needs to be digitized, skip the event
+ if(!event.hasCollection(Apv25AnalogData.class, apv25AnalogDataCollectionName)) return;
+
+ // Get the analog data from the event
+ List<Apv25AnalogData> analogData = event.get(Apv25AnalogData.class, apv25AnalogDataCollectionName);
+
+ // Create a list hold the digital data
+ List<Apv25DigitalData> digitalData = new ArrayList<Apv25DigitalData>();
+
+ // Amplify the analog data
+ for(Apv25AnalogData analogDatum : analogData){
+
+ // Make a hard copy of the APV25 analog output to avoid modification of the original
+ double[] apv25Output = new double[140];
+ System.arraycopy(analogDatum.getApv25AnalogOutput(), 0, apv25Output, 0, apv25Output.length);
+
+ for(int index = 0; index < apv25Output.length; index++){
+
+ // For now, don't digitize the header
+ if(index < 12) continue;
+
+ // Get the physical channel
+ int physicalChannel = TOTAL_STRIPS_PER_SENSOR
+ - (analogDatum.getApvNumber()*HPSSVTConstants.CHANNELS + (HPSSVTConstants.CHANNELS - 1) - (index - 12));
+
+ apv25Output[index] += 4; // mA
+ apv25Output[index] *= (HPSSVTConstants.MIP/HPSSVTConstants.MULTIPLEXER_GAIN);
+
+ // Digitize the signal
+ apv25Output[index] *= HPSSVTCalibrationConstants.getGain(analogDatum.getSensor(), physicalChannel);
+
+ // Add pedestal and noise
+ double pedestal = HPSSVTCalibrationConstants.getPedestal(analogDatum.getSensor(), physicalChannel);
+ double noise = HPSSVTCalibrationConstants.getNoise(analogDatum.getSensor(), physicalChannel);
+ if(!noiseless)
+ apv25Output[index] += RandomGaussian.getGaussian(pedestal, noise);
+ else
+ apv25Output[index] += pedestal;
+ }
+
+ // Add the digital data to the list
+ digitalData.add(new Apv25DigitalData(analogDatum.getSensor(), analogDatum.getApvNumber(), apv25Output));
+ }
+
+ event.put(apv25DigitalDataCollectionName, digitalData, Apv25DigitalData.class, 0);
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/SvtHalfModule.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/SvtHalfModule.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,59 @@
+package org.hps.recon.tracking.apv25;
+
+//--- constants ---//
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_APV25_PER_HYBRID;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants;
+import org.hps.conditions.deprecated.HPSSVTConstants;
+//--- lcsim ---//
+import org.lcsim.detector.tracker.silicon.SiSensor;
+
+/**
+ *
+ * @author Omar Moreno
+ * @version $Id: SvtHalfModule.java,v 1.7 2013/04/25 22:11:14 meeg Exp $
+ */
+public class SvtHalfModule {
+
+ private SiSensor sensor;
+ private Apv25Full[] apv25 = new Apv25Full[5];
+
+ public SvtHalfModule(SiSensor sensor){
+
+ // Set the sensor associated with this half-module
+ this.sensor = sensor;
+
+ // Instantiate the APV25's
+ for(int chip = 0; chip < TOTAL_APV25_PER_HYBRID; chip++){
+ apv25[chip] = new Apv25Full();
+ for(int channel = 0; channel < HPSSVTConstants.CHANNELS; channel++){
+ int physicalChannel = 639 - (chip*128 + 127 - channel);
+
+ // Mark all bad channels which were found during QA
+ if(HPSSVTCalibrationConstants.isBadChannel(sensor, physicalChannel)){
+ apv25[chip].getChannel(channel).markAsBadChannel();
+ }
+
+ // Set the shaping time
+ double tp = HPSSVTCalibrationConstants.getTShaping(sensor, physicalChannel);
+ apv25[chip].getChannel(channel).setShapingTime(tp);
+ }
+ }
+ }
+
+ public SiSensor getSensor(){
+ return sensor;
+ }
+
+ public Apv25Full getAPV25(int physicalChannel){
+ return apv25[this.getAPV25Number(physicalChannel)];
+ }
+
+ public int getAPV25Number(int physicalChannel){
+ return (int) ((TOTAL_APV25_PER_HYBRID - 1) - Math.floor(physicalChannel/HPSSVTConstants.CHANNELS));
+ }
+
+ public Apv25Full[] getAllApv25s(){
+ return apv25;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/SvtReadout.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/SvtReadout.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,318 @@
+
+package org.hps.recon.tracking.apv25;
+
+//--- java ---//
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_APV25_CHANNELS;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_NUMBER_OF_SAMPLES;
+import static org.hps.conditions.deprecated.HPSSVTConstants.TOTAL_STRIPS_PER_SENSOR;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+import org.hps.conditions.deprecated.HPSSVTConstants;
+import org.hps.conditions.deprecated.SvtUtils;
+//--- lcsim ---//
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.hps.util.ClockSingleton;
+import org.lcsim.recon.tracking.digitization.sisim.CDFSiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeData;
+import org.lcsim.recon.tracking.digitization.sisim.SiElectrodeDataCollection;
+import org.lcsim.recon.tracking.digitization.sisim.SiSensorSim;
+import org.lcsim.recon.tracking.digitization.sisim.config.SimTrackerHitReadoutDriver;
+import org.lcsim.util.Driver;
+//--- Constants ---//
+//--- hps-java ---//
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: SvtReadout.java,v 1.12 2013/04/25 22:11:14 meeg Exp $
+ */
+public class SvtReadout extends Driver {
+
+ private Set<SvtHalfModule> halfModules = new HashSet<SvtHalfModule>();
+ private SiSensorSim siSimulation = new CDFSiSensorSim();
+ SimTrackerHitReadoutDriver readout = null;
+ // FIFO queue used to store readout times
+ private Queue<Double> fifo = new LinkedList<Double>();
+
+ List<String> readouts = new ArrayList<String>();
+ Map<SiSensor, List<Integer>> sensorToChannel = new HashMap<SiSensor, List<Integer>>();
+
+ // Assuming at 41.6 MHz clock, minimum readout time per sample is 3.36 us
+ // For now, a dead time of 250 ns is fine
+ double readoutDeadTimePerSample = 250; // ns
+ double lastTriggerTime = 0;
+
+ static private int nTriggers = 0;
+ int nTriggersDropped = 0;
+ int triggerLatencyTime = 0; // ns
+ int eventNumber = 0;
+
+ boolean debug = false;
+ boolean pedestalRun = false;
+
+ // Collection Names
+ String apv25AnalogDataCollectioName = "APV25AnalogData";
+ String simTrackerHitCollectionName = "TrackerHits";
+
+ /**
+ * Default Ctor
+ */
+ public SvtReadout(){
+ }
+
+ /**
+ *
+ */
+ public void setDebug(boolean debug){
+ this.debug = debug;
+ }
+
+ /**
+ *
+ */
+ public void setPedestalRun(boolean pedestalRun){
+ this.pedestalRun = pedestalRun;
+ }
+
+ /**
+ *
+ */
+ public void setTriggerLatencyTime(int triggerLatencyTime /* ns */){
+ this.triggerLatencyTime = triggerLatencyTime;
+ }
+
+ /**
+ *
+ */
+ static public int getNumberOfTriggers(){
+ return nTriggers;
+ }
+
+ /**
+ *
+ */
+ public void setReadoutDeadTime(int readoutDeadTimePerSample){
+ this.readoutDeadTimePerSample = readoutDeadTimePerSample;
+ }
+
+ /**
+ * Set the SimTrackerHit collection name
+ */
+ public void setSimTrackerHitCollectionName(String simTrackerHitCollectionName){
+ this.simTrackerHitCollectionName = simTrackerHitCollectionName;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void detectorChanged(Detector detector){
+ super.detectorChanged(detector);
+
+ // Instantiate all SVT Half modules
+ for(SiSensor sensor : SvtUtils.getInstance().getSensors()){
+ halfModules.add(new SvtHalfModule(sensor));
+ }
+
+ // Set the trigger latency
+ for(SvtHalfModule halfModule : halfModules){
+ for(Apv25Full apv : halfModule.getAllApv25s()){
+ apv.setLatency(triggerLatencyTime);
+ }
+ sensorToChannel.put(halfModule.getSensor(), new ArrayList<Integer>());
+ }
+
+ // Load the driver which transfers SimTrackerHits to their
+ // corresponding sensor readout
+ if(readout == null){
+ add(new SimTrackerHitReadoutDriver(readouts));
+ }
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void process(EventHeader event){
+ super.process(event);
+
+ eventNumber++;
+
+ // Increment all trigger pointer and writer positions when necessary
+ if((ClockSingleton.getTime() + ClockSingleton.getDt()) % HPSSVTConstants.SAMPLING_INTERVAL == 0){
+ for(SvtHalfModule halfModule : halfModules){
+ for(Apv25Full apv : halfModule.getAllApv25s()){
+ apv.incrementPointerPositions();
+ }
+ }
+ }
+
+ // Create a list to hold the analog data
+ List<Apv25AnalogData> analogData = new ArrayList<Apv25AnalogData>();
+
+ // Loop over all half-modules, perform charge deposition simulation and read them out
+ for(SvtHalfModule halfModule : halfModules){
+ this.readoutSensor(halfModule);
+ }
+
+ // If an Ecal trigger is received, readout six samples from each APV25
+ if(Apv25Full.readoutBit){
+
+ nTriggers++;
+ Apv25Full.readoutBit = false;
+
+ // An APV25 cannot receive a trigger while it's still reading out samples;
+ // drop the trigger
+ if(ClockSingleton.getTime() >= (lastTriggerTime + readoutDeadTimePerSample*TOTAL_NUMBER_OF_SAMPLES)){
+
+ if(debug) System.out.println(this.getClass().getSimpleName() + ": APVs have been triggered on event " + eventNumber);
+
+ lastTriggerTime = ClockSingleton.getTime();
+
+ for(int sample = 0; sample < TOTAL_NUMBER_OF_SAMPLES; sample++){
+
+ // Add the time at which each of the six samples should be collected
+ // the trigger queue
+ fifo.offer(ClockSingleton.getTime() + sample*24);
+ }
+ } else {
+ if(debug) System.out.println(this.getClass().getSimpleName() + ": Trigger has been dropped!");
+ //make an empty hit collection to make the DAQ happy
+ //TODO: block the event builder from making an event
+ event.put("SVTRawTrackerHits", new ArrayList<RawTrackerHit>(), RawTrackerHit.class, 0);
+ nTriggersDropped++;
+ nTriggers--;
+ }
+ }
+
+ // Process any triggers in the queue
+ if(fifo.peek() != null){
+
+ if(fifo.peek() == ClockSingleton.getTime()){
+
+ // Clear the analog data and readout all APV25's
+ analogData.addAll(this.readoutAPV25s());
+ fifo.remove();
+ }
+ }
+
+ if(!analogData.isEmpty())
+ event.put(apv25AnalogDataCollectioName, analogData, Apv25AnalogData.class, 0);
+ }
+
+ /**
+ * Readout the electrodes of an HPS Si sensor and inject the charge into
+ * the APV25 readout chip.
+ *
+ * @param halfModule : SVT Half Module
+ */
+ public void readoutSensor(SvtHalfModule halfModule){
+
+ // Set the sensor to be used in the charge deposition simulation
+ siSimulation.setSensor(halfModule.getSensor());
+
+ // Perform the charge deposition simulation
+ Map<ChargeCarrier, SiElectrodeDataCollection> electrodeDataMap = siSimulation.computeElectrodeData();
+
+ for (ChargeCarrier carrier : ChargeCarrier.values()) {
+
+ // If the sensor is capable of collecting the given charge carrier
+ // then obtain the electrode data for the sensor
+ if (halfModule.getSensor().hasElectrodesOnSide(carrier)) {
+
+ SiElectrodeDataCollection electrodeDataCol = electrodeDataMap.get(carrier);
+
+ // If there is no electrode data available create a new instance of electrode data
+ if (electrodeDataCol == null) {
+ electrodeDataCol = new SiElectrodeDataCollection();
+ }
+
+ // Loop over all sensor channels
+ for(Integer physicalChannel : electrodeDataCol.keySet()){
+
+ // find the APV channel number from the physical channel
+ int channel = physicalChannel - TOTAL_STRIPS_PER_SENSOR
+ + halfModule.getAPV25Number(physicalChannel)*TOTAL_APV25_CHANNELS + (TOTAL_APV25_CHANNELS - 1);
+
+ // Only inject charge if the channels isn't considered bad
+ if(halfModule.getAPV25(physicalChannel).getChannel(channel).isBadChannel()) continue;
+
+ // Get the electrode data for this channel
+ SiElectrodeData electrodeData = electrodeDataCol.get(physicalChannel);
+
+ // Get the charge in units of electrons
+ double charge = pedestalRun ? 0 : electrodeData.getCharge();
+
+ if(debug){
+ if(charge > 0){
+ System.out.println(this.getClass().getSimpleName()
+ + ": Sensor: " + SvtUtils.getInstance().getDescription(halfModule.getSensor())
+ + ": Injecting charge " + charge + " into channel " + physicalChannel);
+ sensorToChannel.get(halfModule.getSensor()).add(physicalChannel);
+ }
+ }
+
+ // Inject the charge into the APV25 amplifier chain
+ halfModule.getAPV25(physicalChannel).injectCharge(channel, charge);
+ }
+ }
+ }
+
+ // Clear the sensors of all deposited charge
+ siSimulation.clearReadout();
+ }
+
+ /**
+ *
+ */
+ public List<Apv25AnalogData> readoutAPV25s(){
+
+ // Create a list to hold the analog data
+ List<Apv25AnalogData> analogData = new ArrayList<Apv25AnalogData>();
+
+ for(SvtHalfModule halfModule : halfModules){
+
+ // Get the sensor associated with this half-module
+ SiSensor sensor = halfModule.getSensor();
+
+ // Get all of the APVs associated with the sensor
+ Apv25Full[] apv25 = halfModule.getAllApv25s();
+
+ if(debug){
+ for(int physicalChannel = 0; physicalChannel < TOTAL_APV25_CHANNELS; physicalChannel++){
+ if(sensorToChannel.get(halfModule.getSensor()).contains(physicalChannel)){
+ int channel = physicalChannel - TOTAL_STRIPS_PER_SENSOR
+ + halfModule.getAPV25Number(physicalChannel)*TOTAL_APV25_CHANNELS + (TOTAL_APV25_CHANNELS - 1);
+ System.out.println("\nPhysical Channel: " + physicalChannel
+ + " Sensor: " + SvtUtils.getInstance().getDescription(halfModule.getSensor())
+ + apv25[halfModule.getAPV25Number(physicalChannel)].getChannel(channel).getPipeline().toString() + "\n");
+ }
+ }
+ }
+
+ // Readout all APV25's
+ for(int apvN = 0; apvN < apv25.length; apvN++){
+ Apv25AnalogData analogDatum = apv25[apvN].readOut();
+ analogDatum.setSensor(sensor);
+ analogDatum.setApv(apvN);
+ analogData.add(analogDatum);
+
+ }
+ sensorToChannel.get(halfModule.getSensor()).clear();
+ }
+
+ return analogData;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/TestRunDataProcessingModule.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/apv25/TestRunDataProcessingModule.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,134 @@
+package org.hps.recon.tracking.apv25;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.hps.conditions.deprecated.HPSSVTCalibrationConstants;
+import org.lcsim.detector.IReadout;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseRawTrackerHit;
+
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: TestRunDataProcessingModule.java,v 1.1 2013/03/15 21:05:28 meeg Exp $
+ */
+public class TestRunDataProcessingModule extends DataProcessingModule {
+
+ int nSamplesAboveThreshold = 1; // Number of samples above noise threshold
+ int noiseThreshold = 3; // Units of RMS noise
+
+ boolean enablePileUpCut = true;
+ boolean enableThresholdCut = true;
+
+ /**
+ * Default Ctor
+ */
+ public TestRunDataProcessingModule(){
+ };
+
+ /**
+ *
+ */
+ public void setNumberOfSamplesAboveThreshold(int nSamplesAboveThreshold){
+ this.nSamplesAboveThreshold = nSamplesAboveThreshold;
+ }
+
+ /**
+ *
+ */
+ public void setNoiseThreshold(int noiseThreshold /* Noise RMS */){
+ this.noiseThreshold = noiseThreshold;
+ }
+
+ /**
+ *
+ */
+ public void setEnablePileUpCut(boolean enablePileUpCut){
+ this.enablePileUpCut = enablePileUpCut;
+ }
+
+ /**
+ *
+ */
+ public void setEnableThresholdCut(boolean enableThresholdCut){
+ this.enableThresholdCut = enableThresholdCut;
+ }
+
+ protected List<RawTrackerHit> findRawHits(){
+
+ List<RawTrackerHit> rawHits = new ArrayList<RawTrackerHit>();
+
+ // Loop through all blocked data
+ for(Map.Entry<SiSensor, SvtDataBlocks> sensor : sensorToDataBlocks.entrySet()){
+
+ SvtDataBlocks blocks = sensor.getValue();
+
+ for(int channel = 0; channel < 639; channel++){
+
+ if(HPSSVTCalibrationConstants.isBadChannel(sensor.getKey(), channel)) continue;
+
+ short[] samples = blocks.getSamples(channel);
+
+ if(enableThresholdCut && !this.samplesAboveThreshold(sensor.getKey(), channel, samples)) continue;
+
+ if(enablePileUpCut && !this.pileUpCut(samples)) continue;
+
+ // Create a RawTrackerHit
+ int sideNumber;
+ int time = 0;
+ if(sensor.getKey().hasElectrodesOnSide(ChargeCarrier.HOLE)){
+ sideNumber = ChargeCarrier.HOLE.charge();
+ } else {
+ sideNumber = ChargeCarrier.ELECTRON.charge();
+ }
+ long cellID = sensor.getKey().makeStripId(channel, sideNumber).getValue();
+ RawTrackerHit rawHit = new BaseRawTrackerHit(time, cellID, samples, new ArrayList<SimTrackerHit>(), sensor.getKey());
+ rawHits.add(rawHit);
+
+ // Add the raw hit to the sensor readout
+ IReadout readOut = sensor.getKey().getReadout();
+ readOut.addHit(rawHit);
+ }
+ }
+
+ System.out.println(this.getClass().getSimpleName() + ": Number of RawTrackerHits created: " + rawHits.size());
+ return rawHits;
+ }
+
+ /**
+ *
+ */
+ private boolean samplesAboveThreshold(SiSensor sensor, int channel, short[] samples){
+ // Number of samples above threshold
+ int nSamplesAboveThreshold = 0;
+
+ // Get the pedestal and noise for this channel
+ double pedestal = HPSSVTCalibrationConstants.getPedestal(sensor, channel);
+ double noise = HPSSVTCalibrationConstants.getNoise(sensor, channel);
+
+ // Calculate the threshold
+ int threshold = (int) (pedestal + noise*this.noiseThreshold);
+
+ for(int index = 0; index < 6; index++){
+ if(samples[index] >= threshold) nSamplesAboveThreshold++;
+ }
+
+ // If the prerequisite number of samples are above threshold return true
+ if(nSamplesAboveThreshold >= this.nSamplesAboveThreshold ) return true;
+ return false;
+ }
+
+ /**
+ *
+ */
+ private boolean pileUpCut(short[] sample){
+ if(sample[2] > sample[1] || sample[3] > sample[2]) return true;
+ return false;
+ }
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLEventData.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLEventData.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,89 @@
+package org.hps.recon.tracking.gbl;
+
+import org.lcsim.event.GenericObject;
+
+public class GBLEventData implements GenericObject {
+
+ /*
+ *
+ * Interface enumerator to access the correct data
+ *
+ */
+ private static class GBLINT {
+ public static final int RUNNR = 0;
+ public static final int BANK_INT_SIZE = 1;
+ }
+ private static class GBLDOUBLE {
+ public static final int BFIELD = 0;
+ public static final int BANK_DOUBLE_SIZE = 1;
+ }
+ // array holding the integer data
+ private int bank_int[] = new int[GBLINT.BANK_INT_SIZE];
+ private double bank_double[] = new double[GBLDOUBLE.BANK_DOUBLE_SIZE];
+
+
+ /**
+ * Constructor with event number as parameter
+ * @param eventNumber the event number
+ *
+ */
+ public GBLEventData(int eventNumber,double Bz) {
+ setRunNr(eventNumber);
+ setBfield(Bz);
+ }
+
+ public void setRunNr(int val) {
+ bank_int[GBLINT.RUNNR] = val;
+ }
+
+ public int getRunNr() {
+ return this.getIntVal(GBLINT.RUNNR);
+ }
+
+ public void setBfield(double val) {
+ bank_double[GBLDOUBLE.BFIELD] = val;
+ }
+
+ public double getBfield() {
+ return this.getDoubleVal(GBLDOUBLE.BFIELD);
+ }
+
+
+ @Override
+ public int getNInt() {
+ return GBLINT.BANK_INT_SIZE;
+ }
+
+ @Override
+ public int getNFloat() {
+ return 0;
+ }
+
+ @Override
+ public int getNDouble() {
+ return GBLDOUBLE.BANK_DOUBLE_SIZE;
+ }
+
+ @Override
+ public int getIntVal(int index) {
+ return bank_int[index];
+ }
+
+ @Override
+ public float getFloatVal(int index) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public double getDoubleVal(int index) {
+ return bank_double[index];
+ }
+
+ @Override
+ public boolean isFixedSize() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLFileIO.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLFileIO.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,255 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking.gbl;
+
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.Hep3Matrix;
+import hep.physics.vec.Hep3Vector;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.hps.recon.tracking.RunAlignment;
+import org.hps.recon.tracking.gbl.GBLOutput.ClParams;
+import org.hps.recon.tracking.gbl.GBLOutput.PerigeeParams;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+
+/**
+ * Handles text file printing for the GBL text file
+ * @author Per Hansson Adrian <[log in to unmask]>
+ * @version $Id: GBLFileIO.java,v 1.9 2013/11/07 03:54:58 phansson Exp $ $Date: 2013/11/07 03:54:58 $ $Author: phansson $
+ */
+public class GBLFileIO {
+
+ PrintWriter _pWriter;
+ FileWriter _fWriter;
+
+ GBLFileIO(String fileName) {
+ openFile(fileName);
+ }
+
+ public void printEventInfo(int evtnr, double Bz) {
+ addLine(String.format("New Event %d %.12f", evtnr, Bz));
+ }
+
+ protected void addLine(String line) {
+ this._pWriter.println(line);
+ }
+
+ public void closeFile() {
+ try {
+ _pWriter.close();
+ _fWriter.close();
+ } catch(IOException ex) {
+ Logger.getLogger(RunAlignment.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ private void openFile(String fileName) {
+ if(fileName.equalsIgnoreCase("")) {
+ System.out.printf("%s: no file name specified \n", this.getClass().getSimpleName());
+ System.exit(1);
+ }
+ try {
+ _fWriter = new FileWriter(fileName);
+ _pWriter = new PrintWriter(_fWriter);
+ } catch (IOException ex) {
+ Logger.getLogger(RunAlignment.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ void printTrackID(int iTrack) {
+ addLine(String.format("New Track %d", iTrack));
+ }
+
+ void printOldPerTrackParam(HelicalTrackFit htf) {
+ addLine(String.format("Track perPar (R phi0 slope d0 z0) %.12f %.12f %.12f %.12f %.12f",htf.R(),htf.phi0(),htf.slope(),htf.dca(),htf.z0()));
+ }
+
+ String getPerTrackParamStr(PerigeeParams perPar) {
+ return String.format("Track perPar (R theta phi d0 z0) %.12f %.12f %.12f %.12f %.12f",1.0/perPar.getKappa(),perPar.getTheta(),perPar.getPhi(),perPar.getD0(),perPar.getZ0());
+ }
+
+ void printPerTrackParam(PerigeeParams perPar) {
+ addLine(this.getPerTrackParamStr(perPar));
+ }
+
+ String getPerTrackParamTruthStr(PerigeeParams perPar) {
+ return String.format("Truth perPar (kappa theta phi d0 z0) %.12f %.12f %.12f %.12f %.12f",perPar.getKappa(),perPar.getTheta(),perPar.getPhi(),perPar.getD0(),perPar.getZ0());
+ }
+
+ void printPerTrackParamTruth(PerigeeParams perPar) {
+ addLine(this.getPerTrackParamTruthStr(perPar));
+ }
+
+ String getClTrackParamTruthStr(ClParams perPar) {
+ return String.format("Truth clPar (q/p lambda phi xT yT) %.12f %.12f %.12f %.12f %.12f",perPar.getQoverP(),perPar.getLambda(),perPar.getPhi(),perPar.getXt(),perPar.getYt());
+ }
+
+ void printClTrackParamTruth(ClParams perPar) {
+ addLine(this.getClTrackParamTruthStr(perPar));
+ }
+
+ String getClTrackParamStr(ClParams perPar) {
+ return String.format("Track clPar (q/p lambda phi xT yT) %.12f %.12f %.12f %.12f %.12f",perPar.getQoverP(),perPar.getLambda(),perPar.getPhi(),perPar.getXt(),perPar.getYt());
+ }
+ void printClTrackParam(ClParams perPar) {
+ addLine(String.format("%s",this.getClTrackParamStr(perPar)));
+ }
+
+ void printNrHits(int n) {
+ addLine(String.format("Track nr hits <%d>",n));
+ }
+
+ void printStripJacPointToPoint(int id, int layer, double s, BasicMatrix jac) {
+ String str = String.format("Strip id <%d> layer <%d> s <%.10f> jac <",id,layer,s);
+ for(int r=0;r<jac.getNRows();++r) {
+ for(int c=0;c<jac.getNColumns();++c) {
+ str += String.format("%.10f ", jac.e(r, c));
+ }
+ }
+ str += ">";
+ addLine(str);
+ }
+
+
+ void printStripScatJacPointToPoint(int id, int layer, double s, BasicMatrix jac) {
+ String str = String.format("Strip scat id <%d> layer <%d> s <%.10f> jac <",id,layer,s);
+ for(int r=0;r<jac.getNRows();++r) {
+ for(int c=0;c<jac.getNColumns();++c) {
+ str += String.format("%.10f ", jac.e(r, c));
+ }
+ }
+ str += ">";
+ addLine(str);
+ }
+
+ void printStripL2m(int id, int layer, double s, BasicMatrix jac) {
+ String str = String.format("Strip LocalToMeas id <%d> layer <%d> s <%.10f> L2m <",id,layer,s);
+ for(int r=0;r<jac.getNRows();++r) {
+ for(int c=0;c<jac.getNColumns();++c) {
+ str += String.format("%.10f ", jac.e(r, c));
+ }
+ }
+ str += ">";
+ addLine(str);
+ }
+
+ void printPerTrackCov(HelicalTrackFit htf) {
+ String str = "Track perCov (idx: dca,phi0,curv,z0,slope) ";
+ SymmetricMatrix cov = htf.covariance();
+ for(int irow=0;irow<cov.getNRows();++irow) {
+ for(int icol=0;icol<cov.getNColumns();++icol) {
+ str += String.format("%e ", cov.e(irow, icol));
+ }
+ }
+ addLine(str);
+ }
+
+ void printCLTrackCov(BasicMatrix cov) {
+ String str = "Track clCov ";
+ for(int irow=0;irow<cov.getNRows();++irow) {
+ for(int icol=0;icol<cov.getNColumns();++icol) {
+ str += String.format("%.10f ", cov.e(irow, icol));
+ }
+ }
+ addLine(str);
+ }
+
+
+ void printStripTrackDir(double sinPhi, double sinLambda) {
+ String str = String.format("Strip sinPhi sinLambda %.10f %.10f",sinPhi,sinLambda);
+ addLine(str);
+ }
+
+ void printStripTrackDirFull(Hep3Vector dir) {
+ addLine(String.format("Strip track dir %.10f %.10f %.10f",dir.x(),dir.y(),dir.z()));
+ }
+
+ void printStripTrackPos(Hep3Vector pos) {
+ addLine(String.format("Strip track pos %.10f %.10f %.10f",pos.x(),pos.y(),pos.z()));
+ }
+
+ void printStrip(int id, int layer) {
+ addLine(String.format("New Strip id layer %d %d", id,layer));
+ }
+
+ void printStripPathLen(double s) {
+ addLine(String.format("Strip pathLen %.10f", s));
+ }
+
+ void printStripPathLen3D(double s) {
+ addLine(String.format("Strip pathLen3D %.10f", s));
+ }
+
+ void printStereoAngle(double stereoAngle) {
+ addLine(String.format("Strip stereo angle %.10f", stereoAngle));
+ }
+
+ void printStripMeas(double u) {
+ addLine(String.format("Strip u %.10f", u));
+ }
+
+ void printStripMeasRes(double ures, double uresErr) {
+ addLine(String.format("Strip ures %.10f %.10f", ures, uresErr));
+ }
+
+ void printStripMeasResTruth(double ures, double uresErr) {
+ addLine(String.format("Strip truth ures %.10f %.10f", ures, uresErr));
+ }
+
+ void printStripMeasResSimHit(double ures, double uresErr) {
+ addLine(String.format("Strip simhit ures %.10f %.10f", ures, uresErr));
+ }
+
+ void printStripScat(double scatAngle) {
+ addLine(String.format("Strip scatangle %.10f",scatAngle));
+ }
+
+ void printMeasDir(Hep3Vector u) {
+ addLine(String.format("Strip meas dir %.10f %.10f %.10f", u.x(), u.y(), u.z()));
+ }
+
+ void printNonMeasDir(Hep3Vector u) {
+ addLine(String.format("Strip non-meas dir %.10f %.10f %.10f", u.x(), u.y(), u.z()));
+ }
+
+ void printNormalDir(Hep3Vector u) {
+ addLine(String.format("Strip normal dir %.10f %.10f %.10f", u.x(), u.y(), u.z()));
+ }
+
+
+ void printMomentum(double p, double p_truth) {
+ addLine(String.format("Track mom %.10f %.10f", p, p_truth));
+ }
+
+ void printPerToClPrj(Hep3Matrix perToClPrj) {
+ String str = "Track perToClPrj ";
+ for(int irow=0;irow<perToClPrj.getNRows();++irow) {
+ for(int icol=0;icol<perToClPrj.getNColumns();++icol) {
+ str += String.format("%.10f ", perToClPrj.e(irow, icol));
+ }
+ }
+ addLine(str);
+ }
+
+ void printChi2(double[] chisq, int[] ndf) {
+ addLine(String.format("Track chi2/ndf (circle,zfit) %.10f %d %.10f %d",chisq[0],ndf[0],chisq[1],ndf[1]));
+ }
+
+ void printOrigin(Hep3Vector pos) {
+ addLine(String.format("Strip origin pos %.10f %.10f %.10f",pos.x(),pos.y(),pos.z()));
+ }
+
+ void printHitPos3D(Hep3Vector pos) {
+ addLine(String.format("Strip 3D hit pos %.10f %.10f %.10f",pos.x(),pos.y(),pos.z()));
+ }
+
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutput.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutput.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,943 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking.gbl;
+import hep.physics.matrix.BasicMatrix;
+import hep.physics.matrix.Matrix;
+import hep.physics.matrix.MatrixOp;
+import hep.physics.matrix.SymmetricMatrix;
+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.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.hps.recon.tracking.HPSTransformations;
+import org.hps.recon.tracking.MaterialSupervisor;
+import org.hps.recon.tracking.MaterialSupervisor.DetectorPlane;
+import org.hps.recon.tracking.MaterialSupervisor.ScatteringDetectorVolume;
+import org.hps.recon.tracking.MultipleScattering;
+import org.hps.recon.tracking.MultipleScattering.ScatterPoint;
+import org.hps.recon.tracking.MultipleScattering.ScatterPoints;
+import org.hps.recon.tracking.TrackUtils;
+import org.hps.recon.tracking.TrackerHitUtils;
+import org.lcsim.constants.Constants;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.SimTrackerHit;
+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.geometry.Detector;
+import org.lcsim.recon.tracking.seedtracker.ScatterAngle;
+import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
+import org.lcsim.recon.tracking.seedtracker.SeedTrack;
+
+/**
+
+*
+* @author Per Hansson Adrian <[log in to unmask]>
+* @version $Id: GBLOutput.java,v 1.17 2013/11/07 03:30:18 phansson Exp $ $Date: 2013/11/07 03:30:18 $ $Author: phansson $
+*
+*/
+/**
+ * @author phansson
+ *
+ */
+public class GBLOutput {
+
+ private int _debug = 0;
+ private GBLFileIO textFile = null;
+ private Hep3Vector _B;
+ private TrackerHitUtils _trackerHitUtils = new TrackerHitUtils();
+ private MaterialSupervisor _materialmanager;
+ private MultipleScattering _scattering;
+ private double _beamEnergy = 2.2; //GeV
+ private boolean AprimeEvent = false; // do extra checks
+ private boolean hasXPlanes = false;
+
+
+
+
+ /**
+ * Constructor
+ * @param outputFileName is the filename given to the text-based output file. If empty no output file is written
+ * @param bfield magnetic field in Tesla
+ */
+ GBLOutput(String outputFileName,Hep3Vector bfield) {
+ System.out.printf("name \"%s\" \n", outputFileName);
+ if(!outputFileName.equalsIgnoreCase("")) {
+ textFile = new GBLFileIO(outputFileName);
+ }
+ _materialmanager = new MaterialSupervisor();
+ _scattering = new MultipleScattering(_materialmanager);
+ _B = HPSTransformations.transformVectorToTracking(bfield);
+ _scattering.setBField(Math.abs(_B.z())); // only absolute of B is needed as it's used for momentum calculation only
+ }
+
+ public void setDebug(int debug) {
+ _debug = debug;
+ _scattering.setDebug(_debug>0?true:false);
+ }
+ public void buildModel(Detector detector) {
+ _materialmanager.buildModel(detector);
+ }
+ void printNewEvent(int eventNumber,double Bz) {
+ if(textFile != null) {
+ textFile.printEventInfo(eventNumber,Bz);
+ }
+ }
+ void printTrackID(int iTrack) {
+ if(textFile != null) {
+ textFile.printTrackID(iTrack);
+ }
+ }
+ void close() {
+ if(textFile != null) {
+ textFile.closeFile();
+ }
+ }
+ void setAPrimeEventFlag(boolean flag) {
+ this.AprimeEvent = flag;
+ }
+ void setXPlaneFlag(boolean flag) {
+ this.hasXPlanes = flag;
+ }
+ public Hep3Vector get_B() {
+ return _B;
+ }
+ public void set_B(Hep3Vector _B) {
+ this._B = _B;
+ }
+
+
+
+ void printGBL(Track trk, GBLTrackData gtd, List<GBLStripClusterData> stripClusterDataList, List<MCParticle> mcParticles, List<SimTrackerHit> simTrackerHits, boolean isMC) {
+
+ SeedTrack st = (SeedTrack)trk;
+ SeedCandidate seed = st.getSeedCandidate();
+ HelicalTrackFit htf = seed.getHelix();
+
+ // Find scatter points along the path
+ ScatterPoints scatters = _scattering.FindHPSScatterPoints(htf);
+
+ // Hits on track
+ List<HelicalTrackHit> hits = seed.getHits();
+
+ // Find the truth particle of the track
+ MCParticle mcp = null;
+
+ if(isMC) {
+ mcp = getMatchedTruthParticle(trk);
+
+ if(mcp==null) {
+ System.out.printf("%s: no truth particle found in event!\n",this.getClass().getSimpleName());
+ this.printMCParticles(mcParticles);
+ System.exit(1);
+ } else {
+ if(_debug>0) System.out.printf("%s: truth particle (pdgif %d ) found in event!\n",this.getClass().getSimpleName(),mcp.getPDGID());
+ }
+
+ if(AprimeEvent ) {
+ checkAprimeTruth(mcp,mcParticles);
+ }
+ }
+
+ // Get track parameters from MC particle
+ HelicalTrackFit htfTruth = isMC ? TrackUtils.getHTF(mcp,-1.0*this._B.z()) : null;
+
+ // Use the truth helix as the initial track for GBL?
+ //htf = htfTruth;
+
+
+ // Get perigee parameters to curvilinear frame
+ PerigeeParams perPar = new PerigeeParams(htf);
+ PerigeeParams perParTruth = new PerigeeParams(htfTruth);
+ if(textFile != null) {
+ textFile.printPerTrackParam(perPar);
+ textFile.printPerTrackParamTruth(perParTruth);
+ }
+
+ //GBLDATA
+ gtd.setPerigeeTrackParameters(perPar);
+
+ // Get curvilinear parameters
+ ClParams clPar = new ClParams(htf);
+ ClParams clParTruth = new ClParams(htfTruth);
+ if(textFile != null) {
+ textFile.printClTrackParam(clPar);
+ textFile.printClTrackParamTruth(clParTruth);
+
+ if(_debug>0) {
+ System.out.printf("%s\n",textFile.getClTrackParamStr(clPar));
+ System.out.printf("%s\n",textFile.getPerTrackParamStr(perPar));
+ }
+ }
+
+
+ // find the projection from the I,J,K to U,V,T curvilinear coordinates
+ Hep3Matrix perToClPrj = getPerToClPrj(htf);
+
+ if(textFile != null) {
+ textFile.printPerToClPrj(perToClPrj);
+ }
+
+ //GBLDATA
+ for(int row=0; row<perToClPrj.getNRows();++row) {
+ for(int col=0; col<perToClPrj.getNColumns();++col) {
+ gtd.setPrjPerToCl(row, col, perToClPrj.e(row, col));
+ }
+ }
+
+
+
+ //GBLDATA
+ for(int row=0; row<perToClPrj.getNRows();++row) {
+ for(int col=0; col<perToClPrj.getNColumns();++col) {
+ gtd.setPrjPerToCl(row, col, perToClPrj.e(row, col));
+ }
+ }
+
+
+ // print chi2 of fit
+ if(textFile != null) {
+ textFile.printChi2(htf.chisq(),htf.ndf());
+ }
+
+ // build map of layer to SimTrackerHits that belongs to the MC particle
+ Map<Integer, SimTrackerHit> simHitsLayerMap = new HashMap<Integer, SimTrackerHit >();
+ for (SimTrackerHit sh : simTrackerHits) {
+ if(sh.getMCParticle()==mcp) {
+ int layer = sh.getIdentifierFieldValue("layer");
+ if(!simHitsLayerMap.containsKey(layer) || (sh.getPathLength() < simHitsLayerMap.get(layer).getPathLength()) ) {
+ simHitsLayerMap.put(layer, sh);
+ }
+ }
+ }
+
+
+ // covariance matrix from the fit
+ if(textFile != null) {
+ textFile.printPerTrackCov(htf);
+ }
+
+ // dummy cov matrix for CL parameters
+ BasicMatrix clCov = new BasicMatrix(5,5);
+ initUnit(clCov);
+ clCov = (BasicMatrix) MatrixOp.mult(0.1*0.1,clCov);
+
+ if(textFile != null) {
+ textFile.printCLTrackCov(clCov);
+ }
+
+ if(_debug>0) {
+ System.out.printf("%s: perPar covariance matrix\n%s\n",this.getClass().getSimpleName(),htf.covariance().toString());
+ double chi2_truth = truthTrackFitChi2(perPar,perParTruth,htf.covariance());
+ System.out.printf("%s: truth perPar chi2 %f\n",this.getClass().getSimpleName(),chi2_truth);
+ }
+
+ if(_debug>0) System.out.printf("%d hits\n",hits.size());
+
+
+ int istrip = 0;
+ for(int ihit=0;ihit!=hits.size();++ihit) {
+
+ HelicalTrackHit hit = hits.get(ihit);
+ HelicalTrackCross htc = (HelicalTrackCross) hit;
+ List<HelicalTrackStrip> strips = htc.getStrips();
+
+ for(HelicalTrackStrip strip : strips) {
+
+ if(_debug>0) System.out.printf("%s: layer %d\n",this.getClass().getSimpleName(),strip.layer());
+
+ if(textFile != null) {
+ textFile.printStrip(istrip,strip.layer());
+ }
+
+ //GBLDATA
+ GBLStripClusterData stripData = new GBLStripClusterData(strip.layer());
+ //Add to output list
+ stripClusterDataList.add(stripData);
+
+
+
+ //Center of the sensor
+ Hep3Vector origin = strip.origin();
+
+ if(textFile != null) {
+ textFile.printOrigin(origin);
+ }
+
+ // associated 3D position of the crossing of this and it's stereo partner sensor
+ if(textFile != null) {
+ textFile.printHitPos3D(hit.getCorrectedPosition());
+ }
+
+ //Find intercept point with sensor in tracking frame
+ Hep3Vector trkpos = TrackUtils.getHelixPlaneIntercept(htf, strip, Math.abs(_B.z()));
+ Hep3Vector trkposTruth = isMC ? TrackUtils.getHelixPlaneIntercept(htfTruth, strip, Math.abs(_B.z())) : new BasicHep3Vector(-999999.9,-999999.9,-999999.9);
+ if(textFile != null) {
+ textFile.printStripTrackPos(trkpos);
+ }
+ if(_debug>0) {
+ System.out.printf("trkpos at intercept [%.10f %.10f %.10f]\n",trkpos.x(),trkpos.y(),trkpos.z());
+ System.out.printf("trkposTruth at intercept %s\n",trkposTruth.toString());
+ }
+
+ // cross-check intercept point
+ if(hasXPlanes ) {
+ Hep3Vector trkposXPlaneIter = TrackUtils.getHelixPlanePositionIter(htf, strip.origin(), strip.w(), 1.0e-8);
+ Hep3Vector trkposDiff = VecOp.sub(trkposXPlaneIter, trkpos);
+ if(trkposDiff.magnitude() > 1.0e-7) {
+ System.out.printf("WARNING trkposDiff mag = %.10f [%.10f %.10f %.10f]\n",trkposDiff.magnitude(),trkposDiff.x(),trkposDiff.y(),trkposDiff.z());
+ System.exit(1);
+ }
+ if(_debug>0) System.out.printf("trkposXPlaneIter at intercept [%.10f %.10f %.10f]\n",trkposXPlaneIter.x(),trkposXPlaneIter.y(),trkposXPlaneIter.z());
+ }
+
+
+ // Find the sim tracker hit for this layer
+ SimTrackerHit simHit = simHitsLayerMap.get(strip.layer());
+
+ if( isMC ) {
+ if(simHit==null) {
+ System.out.printf("%s: no sim hit for strip hit at layer %d\n",this.getClass().getSimpleName(),strip.layer());
+ System.out.printf("%s: it as %d mc particles associated with it:\n",this.getClass().getSimpleName(),hit.getMCParticles().size());
+ for (MCParticle particle : hit.getMCParticles()) System.out.printf("%s: %d p %s \n",this.getClass().getSimpleName(),particle.getPDGID(),particle.getMomentum().toString());
+ System.out.printf("%s: these are sim hits in the event:\n",this.getClass().getSimpleName());
+ for (SimTrackerHit simhit : simTrackerHits) System.out.printf("%s sim hit at %s with MC particle pdgid %d with p %s \n",this.getClass().getSimpleName(),simhit.getPositionVec().toString(),simhit.getMCParticle().getPDGID(),simhit.getMCParticle().getMomentum().toString());
+ System.out.printf("%s: these are all the MC particles in the event:\n",this.getClass().getSimpleName());
+ System.exit(1);
+ }
+
+ if(_debug>0) {
+ double s_truthSimHit = HelixUtils.PathToXPlane(htfTruth, simHit.getPositionVec().z(), 0, 0).get(0);
+ Hep3Vector trkposTruthSimHit = HelixUtils.PointOnHelix(htfTruth, s_truthSimHit);
+ Hep3Vector resTruthSimHit = VecOp.sub(HPSTransformations.transformVectorToTracking(simHit.getPositionVec()),trkposTruthSimHit);
+ System.out.printf("TruthSimHit residual %s for layer %d\n",resTruthSimHit.toString(),strip.layer());
+ }
+ }
+
+ //path length to intercept
+ double s = HelixUtils.PathToXPlane(htf,trkpos.x(),0,0).get(0);
+ double s3D = s / Math.cos(Math.atan(htf.slope()));
+ if(textFile != null) {
+ textFile.printStripPathLen(s);
+ textFile.printStripPathLen3D(s3D);
+ }
+
+ //GBLDATA
+ stripData.setPath(s);
+ stripData.setPath3D(s3D);
+
+
+
+ //print stereo angle in YZ plane
+ if(textFile != null) {
+ textFile.printMeasDir(strip.u());
+ textFile.printNonMeasDir(strip.v());
+ textFile.printNormalDir(strip.w());
+ }
+
+ //GBLDATA
+ stripData.setU(strip.u());
+ stripData.setV(strip.v());
+ stripData.setW(strip.w());
+
+
+ //Print track direction at intercept
+ Hep3Vector tDir = HelixUtils.Direction(htf, s);
+ double phi = htf.phi0() - s/htf.R();
+ double lambda = Math.atan(htf.slope());
+ if(textFile != null) {
+ textFile.printStripTrackDir(Math.sin(phi),Math.sin(lambda));
+ textFile.printStripTrackDirFull(tDir);
+ }
+
+ //GBLDATA
+ stripData.setTrackDir(tDir);
+ stripData.setTrackPhi(phi);
+ stripData.setTrackLambda(lambda);
+
+
+
+
+ //Print residual in measurement system
+
+ // start by find the distance vector between the center and the track position
+ Hep3Vector vdiffTrk = VecOp.sub(trkpos, origin);
+ Hep3Vector vdiffTrkTruth = VecOp.sub(trkposTruth, origin);
+
+ // then find the rotation from tracking to measurement frame
+ Hep3Matrix trkToStripRot = _trackerHitUtils.getTrackToStripRotation(strip);
+
+ // then rotate that vector into the measurement frame to get the predicted measurement position
+ Hep3Vector trkpos_meas = VecOp.mult(trkToStripRot, vdiffTrk);
+ Hep3Vector trkposTruth_meas = VecOp.mult(trkToStripRot, vdiffTrkTruth);
+
+
+ // hit measurement and uncertainty in measurement frame
+ Hep3Vector m_meas = new BasicHep3Vector(strip.umeas(),0.,0.);
+ Hep3Vector res_err_meas = new BasicHep3Vector(strip.du(),(strip.vmax() - strip.vmin()) / Math.sqrt(12),10.0/Math.sqrt(12));
+
+ if(textFile != null) {
+ textFile.printStripMeas(m_meas.x());
+ }
+
+ //GBLDATA
+ stripData.setMeas(strip.umeas());
+ stripData.setTrackPos(trkpos_meas);
+
+ // residual in measurement frame
+ Hep3Vector res_meas = VecOp.sub(m_meas, trkpos_meas);
+ Hep3Vector resTruth_meas = VecOp.sub(m_meas, trkposTruth_meas);
+ if(textFile != null) {
+ textFile.printStripMeasRes(res_meas.x(),res_err_meas.x());
+ textFile.printStripMeasResTruth(resTruth_meas.x(),res_err_meas.x());
+ }
+
+ //GBLDATA
+ stripData.setMeasErr(res_err_meas.x());
+
+
+
+ if(_debug>0) System.out.printf("layer %d uRes %.10f\n",strip.layer(),res_meas.x());
+
+ // sim hit residual
+
+ if(simHit!=null) {
+ Hep3Vector simHitPos = HPSTransformations.transformVectorToTracking(simHit.getPositionVec());
+ if(_debug>0) System.out.printf("simHitPos %s\n",simHitPos.toString());
+ Hep3Vector vdiffSimHit = VecOp.sub(simHitPos, trkpos);
+ Hep3Vector simHitPos_meas = VecOp.mult(trkToStripRot, vdiffSimHit);
+ if(textFile != null) {
+ textFile.printStripMeasResSimHit(simHitPos_meas.x(),res_err_meas.x());
+ }
+ } else {
+ if(textFile != null) {
+ textFile.printStripMeasResSimHit(-999999.9,-999999.9);
+ }
+ }
+
+ // find scattering angle
+ ScatterPoint scatter = scatters.getScatterPoint(((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement());
+ double scatAngle;
+
+ if(scatter != null) {
+ scatAngle = scatter.getScatterAngle().Angle();
+ }
+ else {
+ System.out.printf("%s: WARNING cannot find scatter for detector %s with strip cluster at %s\n",this.getClass(),((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement().getName(),strip.origin().toString());
+ //can be edge case where helix is outside, but close to sensor, so use hack with the sensor origin closest to hit -> FIX THIS!
+ DetectorPlane closest = null;
+ double dx = 999999.9;
+ if(MaterialSupervisor.class.isInstance(_scattering.getMaterialManager())) {
+ MaterialSupervisor matSup = (MaterialSupervisor)_scattering.getMaterialManager();
+ for(ScatteringDetectorVolume vol : matSup.getMaterialVolumes()) {
+ DetectorPlane plane = (DetectorPlane)vol;
+ double dx_loop = Math.abs(strip.origin().x() - plane.origin().x());
+ if(dx_loop<dx) {
+ dx = dx_loop;
+ closest = plane;
+ }
+ }
+ if(closest==null) {
+ throw new RuntimeException("cannot find any plane that is close to strip!");
+ } else {
+ // find scatterlength
+ double s_closest = HelixUtils.PathToXPlane(htf,closest.origin().x(), 0., 0).get(0);
+ double X0 = closest.getMaterialTraversedInRL(HelixUtils.Direction(htf, s_closest));
+ ScatterAngle scatterAngle = new ScatterAngle(s_closest, _scattering.msangle(htf.p(this._B.magnitude()),X0));
+ scatAngle = scatterAngle.Angle();
+ }
+ }
+ else {
+ throw new UnsupportedOperationException("Should not happen. This problem is only solved with the MaterialSupervisor.");
+ }
+ }
+
+
+ //print scatterer to file
+ if(textFile != null) {
+ textFile.printStripScat(scatAngle);
+ }
+
+ //GBLDATA
+ stripData.setScatterAngle(scatAngle);
+
+ ++istrip;
+
+
+
+ }
+
+ }
+
+
+
+ }
+
+
+ private void checkAprimeTruth(MCParticle mcp, List<MCParticle> mcParticles) {
+ List<MCParticle> mcp_pair = getAprimeDecayProducts(mcParticles);
+
+ if(_debug>0) {
+ double invMassTruth = Math.sqrt( Math.pow(mcp_pair.get(0).getEnergy()+mcp_pair.get(1).getEnergy(),2) - VecOp.add(mcp_pair.get(0).getMomentum(), mcp_pair.get(1).getMomentum()).magnitudeSquared() );
+ double invMassTruthTrks = getInvMassTracks(TrackUtils.getHTF(mcp_pair.get(0),-1.0*this._B.z()),TrackUtils.getHTF(mcp_pair.get(1),-1.0*this._B.z()));
+ System.out.printf("%s: invM = %f\n",this.getClass().getSimpleName(),invMassTruth);
+ System.out.printf("%s: invMTracks = %f\n",this.getClass().getSimpleName(),invMassTruthTrks);
+ }
+
+ // cross-check
+ if(!mcp_pair.contains(mcp)) {
+ boolean hasBeamElectronParent = false;
+ for(MCParticle parent : mcp.getParents()) {
+ if(parent.getGeneratorStatus()!=MCParticle.FINAL_STATE && parent.getPDGID()==11 && parent.getMomentum().y()==0.0 && Math.abs(parent.getMomentum().magnitude() - _beamEnergy)<0.01) {
+ hasBeamElectronParent = true;
+ }
+ }
+ if(!hasBeamElectronParent) {
+ System.out.printf("%s: the matched MC particle is not an A' daughter and not a the recoil electrons!?\n",this.getClass().getSimpleName());
+ System.out.printf("%s: %s %d p %s org %s\n",this.getClass().getSimpleName(),mcp.getGeneratorStatus()==MCParticle.FINAL_STATE?"F":"I",mcp.getPDGID(),mcp.getMomentum().toString(),mcp.getOrigin().toString());
+ printMCParticles(mcParticles);
+ System.exit(1);
+ } else {
+ if(_debug>0) System.out.printf("%s: the matched MC particle is the recoil electron\n",this.getClass().getSimpleName());
+ }
+ }
+
+ }
+
+
+ MCParticle getMatchedTruthParticle(Track track) {
+ boolean debug = false;
+
+ Map<MCParticle,Integer> particlesOnTrack = new HashMap<MCParticle,Integer>();
+
+ if(debug) System.out.printf("getmatched mc particle from %d tracker hits on the track \n",track.getTrackerHits().size());
+
+
+ for(TrackerHit hit : track.getTrackerHits()) {
+ List<MCParticle> mcps = ((HelicalTrackHit)hit).getMCParticles();
+ if(mcps==null) {
+ System.out.printf("%s: warning, this hit (layer %d pos=%s) has no mc particles.\n",this.getClass().getSimpleName(),((HelicalTrackHit)hit).Layer(),((HelicalTrackHit)hit).getCorrectedPosition().toString());
+ }
+ else {
+ if( debug ) System.out.printf("%s: this hit (layer %d pos=%s) has %d mc particles.\n",this.getClass().getSimpleName(),((HelicalTrackHit)hit).Layer(),((HelicalTrackHit)hit).getCorrectedPosition().toString(),mcps.size());
+ for(MCParticle mcp : mcps) {
+ if( !particlesOnTrack.containsKey(mcp) ) {
+ particlesOnTrack.put(mcp, 0);
+ }
+ int c = particlesOnTrack.get(mcp);
+ particlesOnTrack.put(mcp, c+1);
+ }
+ }
+ }
+ if(debug) {
+ System.out.printf("Track p=[ %f, %f, %f] \n",track.getTrackStates().get(0).getMomentum()[0],track.getTrackStates().get(0).getMomentum()[1],track.getTrackStates().get(0).getMomentum()[1]);
+ System.out.printf("FOund %d particles\n",particlesOnTrack.size());
+ for(Map.Entry<MCParticle, Integer> entry : particlesOnTrack.entrySet()) {
+ System.out.printf("%d hits assigned to %d p=%s \n",entry.getValue(),entry.getKey().getPDGID(),entry.getKey().getMomentum().toString());
+ }
+ }
+ Map.Entry<MCParticle,Integer> maxEntry = null;
+ for(Map.Entry<MCParticle,Integer> entry : particlesOnTrack.entrySet()) {
+ if ( maxEntry == null || entry.getValue().compareTo(maxEntry.getValue()) > 0 ) maxEntry = entry;
+ //if ( maxEntry != null ) {
+ // if(entry.getValue().compareTo(maxEntry.getValue()) < 0) continue;
+ //}
+ //maxEntry = entry;
+ }
+ if(debug) {
+ if (maxEntry != null ) {
+ System.out.printf("Matched particle with pdgId=%d and mom %s to track with charge %d and momentum [%f %f %f]\n",
+ maxEntry.getKey().getPDGID(),maxEntry.getKey().getMomentum().toString(),
+ track.getCharge(),track.getTrackStates().get(0).getMomentum()[0],track.getTrackStates().get(0).getMomentum()[1],track.getTrackStates().get(0).getMomentum()[2]);
+ } else {
+ System.out.printf("No truth particle found on this track\n");
+ }
+ }
+ return maxEntry == null ? null : maxEntry.getKey();
+ }
+
+
+ private BasicMatrix getPerParVector(HelicalTrackFit htf) {
+ BasicMatrix perPar = new BasicMatrix(1,5);
+ if( htf != null) {
+ double kappa = -1.0*Math.signum(htf.R())*Constants.fieldConversion*this._B.z()/htf.pT(Math.abs(_B.z()));
+ double theta = Math.PI/2.0 - Math.atan(htf.slope());
+ perPar.setElement(0,0,kappa);
+ perPar.setElement(0,1,theta);
+ perPar.setElement(0,2,htf.phi0());
+ perPar.setElement(0,3,htf.dca());
+ perPar.setElement(0,4,htf.z0());
+ }
+ return perPar;
+
+ }
+
+
+
+
+ private BasicMatrix getJacPerToCl(HelicalTrackFit htf) {
+ System.out.printf("%s: getJacPerToCl\n",this.getClass().getSimpleName());
+ //use propoerly normalized B-field
+ Hep3Vector Bnorm = VecOp.mult(Constants.fieldConversion, _B);
+ //init jacobian to zero
+ BasicMatrix j = new BasicMatrix(5,5);
+ initZero(j);
+ double lambda = Math.atan(htf.slope());
+ double q = Math.signum(htf.R());
+ double theta = Math.PI/2.0 - lambda;
+ Hep3Vector T = HelixUtils.Direction(htf, 0.);
+ Hep3Vector p = VecOp.mult(htf.p(Math.abs(_B.z())), T);
+ double pT = htf.pT(Math.abs(_B.z()));
+ Hep3Vector H = VecOp.mult(1./(Bnorm.magnitude()), Bnorm);
+ Hep3Vector Z = new BasicHep3Vector(0,0,1);
+ Hep3Vector J = VecOp.mult(1./VecOp.cross(T,Z).magnitude(), VecOp.cross(T, Z));
+ Hep3Vector U = VecOp.mult(-1, J);
+ Hep3Vector V = VecOp.cross(T, U);
+ double alpha = VecOp.cross(H,T).magnitude();
+ Hep3Vector N = VecOp.mult(1./alpha,VecOp.cross(H, T));
+ Hep3Vector K = Z;
+ double Q = -Bnorm.magnitude()*q/p.magnitude();
+ double kappa = -1.0*q*Bnorm.z()/pT;
+
+ if (this._debug!=0) {
+ System.out.printf("%s: Bnorm=%s mag(Bnorm)=%f\n",this.getClass().getSimpleName(),Bnorm.toString(),Bnorm.magnitude());
+ System.out.printf("%s: p=%s |p|=%f pT=%f\n",this.getClass().getSimpleName(),p.toString(),p.magnitude(),pT);
+ System.out.printf("%s: q=%f\n",this.getClass().getSimpleName(),q);
+ System.out.printf("%s: q/p=%f\n",this.getClass().getSimpleName(),q/p.magnitude());
+ System.out.printf("%s: T=%s\n",this.getClass().getSimpleName(),T.toString());
+ System.out.printf("%s: H=%s\n",this.getClass().getSimpleName(),H.toString());
+ System.out.printf("%s: kappa=%f\n",this.getClass().getSimpleName(),kappa);
+ System.out.printf("%s: alpha=%f Q=%f \n",this.getClass().getSimpleName(),alpha,Q);
+ System.out.printf("%s: J=%s \n",this.getClass().getSimpleName(),J.toString());
+ System.out.printf("%s: V=%s \n",this.getClass().getSimpleName(),V.toString());
+ System.out.printf("%s: N=%s \n",this.getClass().getSimpleName(),N.toString());
+ System.out.printf("%s: TdotJ=%f \n",this.getClass().getSimpleName(),VecOp.dot(T, J));
+ System.out.printf("%s: VdotN=%f \n",this.getClass().getSimpleName(),VecOp.dot(V, N));
+ System.out.printf("%s: TdotK=%f \n",this.getClass().getSimpleName(),VecOp.dot(T, K));
+ System.out.printf("%s: UdotN=%f \n",this.getClass().getSimpleName(),VecOp.dot(U, N));
+ }
+
+
+
+
+
+ j.setElement(0,0,-1.0*Math.sin(theta)/Bnorm.z());
+
+ j.setElement(0,1,q/(p.magnitude()*Math.tan(theta)));
+
+ j.setElement(1,1,-1);
+
+ j.setElement(1,3,-alpha*Q*VecOp.dot(T, J)*VecOp.dot(V, N));
+
+ j.setElement(1,4,-alpha*Q*VecOp.dot(T, K)*VecOp.dot(V, N));
+
+ j.setElement(2,2,1);
+
+ j.setElement(2,3,-alpha*Q*VecOp.dot(T,J)*VecOp.dot(U, N)/Math.cos(lambda));
+
+ j.setElement(2,4,-alpha*Q*VecOp.dot(T,K)*VecOp.dot(U, N)/Math.cos(lambda));
+
+ j.setElement(3,3,-1);
+
+ j.setElement(4,4,VecOp.dot(V, K));
+
+
+ if(_debug>0) {
+ System.out.printf("%s: lambda= J(1,1)=%f * theta + J(1,3)=%f * eps + J(1,4)=%f * z0 \n",
+ this.getClass().getSimpleName(),
+ j.e(1, 1),j.e(1,3),j.e(1,4));
+
+ }
+
+
+ return j;
+
+ }
+
+
+
+
+
+
+ private void initUnit(BasicMatrix mat) {
+ for(int row=0;row!=mat.getNRows();row++) {
+ for(int col=0;col!=mat.getNColumns();col++) {
+ if(row!=col) mat.setElement(row, col, 0);
+ else mat.setElement(row, col, 1);
+ }
+ }
+ }
+
+ private void initZero(BasicMatrix mat) {
+ for(int row=0;row!=mat.getNRows();row++) {
+ for(int col=0;col!=mat.getNColumns();col++) {
+ mat.setElement(row, col, 0);
+ }
+ }
+ }
+
+
+
+ /**
+ * Transform MCParticle into a Helix object.
+ * Note that it produces the helix parameters at nominal x=0 and assumes that there is no field at x<0
+ *
+ * @param mcp MC particle to be transformed
+ * @return helix object based on the MC particle
+ */
+// private HelicalTrackFit getHTF(MCParticle mcp) {
+// Hep3Vector org = this._hpstrans.transformVectorToTracking(mcp.getOrigin());
+// Hep3Vector p = this._hpstrans.transformVectorToTracking(mcp.getMomentum());
+// // Move to x=0 if needed
+// if(org.x() < 0.) {
+// double dydx = p.y()/p.x();
+// double dzdx = p.z()/p.x();
+// double delta_x = -1. * org.x();
+// double y = delta_x * dydx;
+// double z = delta_x * dzdx;
+// double x = org.x() + delta_x;
+// if( Math.abs(x) > 1e-8) throw new RuntimeException("Error: origin is not zero!");
+// Hep3Vector old = org;
+// org = new BasicHep3Vector(x,y,z);
+// System.out.printf("org %s p %s -> org %s\n", old.toString(),p.toString(),org.toString());
+// } else {
+// org = this._hpstrans.transformVectorToTracking(mcp.getOrigin());
+// }
+//
+//
+//
+// HelixParamCalculator helixParamCalculator = new HelixParamCalculator(p, org, -1*((int)mcp.getCharge()), -1.0*this._B.z());
+// double par[] = new double[5];
+// par[HelicalTrackFit.dcaIndex] = helixParamCalculator.getDCA();
+// par[HelicalTrackFit.slopeIndex] = helixParamCalculator.getSlopeSZPlane();
+// par[HelicalTrackFit.phi0Index] = helixParamCalculator.getPhi0();
+// par[HelicalTrackFit.curvatureIndex] = 1.0/helixParamCalculator.getRadius();
+// par[HelicalTrackFit.z0Index] = helixParamCalculator.getZ0();
+// SymmetricMatrix cov = new SymmetricMatrix(5);
+// for(int i=0;i<cov.getNRows();++i) cov.setElement(i, i, 1.);
+// HelicalTrackFit htf = new HelicalTrackFit(par, cov, new double[2], new int[2], null, null);
+// return htf;
+// }
+
+ private double truthTrackFitChi2(PerigeeParams perPar, PerigeeParams perParTruth, SymmetricMatrix covariance) {
+ //re-shuffle the param vector to match the covariance order of parameters
+ BasicMatrix p = new BasicMatrix(1,5);
+ p.setElement(0, 0, perPar.getD0());
+ p.setElement(0, 1, perPar.getPhi());
+ p.setElement(0, 2, perPar.getKappa());
+ p.setElement(0, 0, perPar.getZ0());
+ p.setElement(0, 4, Math.tan(Math.PI/2.0-perPar.getTheta()));
+ BasicMatrix pt = new BasicMatrix(1,5);
+ pt.setElement(0, 0, perParTruth.getD0());
+ pt.setElement(0, 1, perParTruth.getPhi());
+ pt.setElement(0, 2, perParTruth.getKappa());
+ pt.setElement(0, 0, perParTruth.getZ0());
+ pt.setElement(0, 4, Math.tan(Math.PI/2.0-perParTruth.getTheta()));
+ Matrix error_matrix = MatrixOp.inverse(covariance);
+ BasicMatrix res = (BasicMatrix) MatrixOp.sub(p, pt);
+ BasicMatrix chi2 = (BasicMatrix) MatrixOp.mult(res,MatrixOp.mult(error_matrix, MatrixOp.transposed(res)));
+ if(chi2.getNColumns()!=1 ||chi2.getNRows()!=1) {
+ throw new RuntimeException("matrix dim is screwed up!");
+ }
+ return chi2.e(0, 0);
+ }
+
+
+
+ private List<MCParticle> getAprimeDecayProducts(List<MCParticle> mcParticles) {
+ List<MCParticle> pair = new ArrayList<MCParticle>();
+ for(MCParticle mcp : mcParticles) {
+ if(mcp.getGeneratorStatus()!=MCParticle.FINAL_STATE) continue;
+ boolean hasAprimeParent = false;
+ for(MCParticle parent : mcp.getParents()) {
+ if(Math.abs(parent.getPDGID())==622) hasAprimeParent = true;
+ }
+ if(hasAprimeParent) pair.add(mcp);
+ }
+ if(pair.size()!=2) {
+ System.out.printf("%s: ERROR this event has %d mcp with 622 as parent!!?? \n",this.getClass().getSimpleName(),pair.size());
+ this.printMCParticles(mcParticles);
+ System.exit(1);
+ }
+ if( Math.abs(pair.get(0).getPDGID()) != 11 || Math.abs(pair.get(1).getPDGID()) != 11 ) {
+ System.out.printf("%s: ERROR decay products are not e+e-? \n",this.getClass().getSimpleName());
+ this.printMCParticles(mcParticles);
+ System.exit(1);
+ }
+ if(pair.get(0).getPDGID()*pair.get(1).getPDGID() > 0) {
+ System.out.printf("%s: ERROR decay products have the same sign? \n",this.getClass().getSimpleName());
+ this.printMCParticles(mcParticles);
+ System.exit(1);
+ }
+ return pair;
+
+ }
+
+ private void printMCParticles(List<MCParticle> mcParticles) {
+ System.out.printf("%s: printMCParticles \n",this.getClass().getSimpleName());
+ System.out.printf("%s: %d mc particles \n",this.getClass().getSimpleName(),mcParticles.size());
+ for(MCParticle mcp : mcParticles) {
+ if(mcp.getGeneratorStatus()!=MCParticle.FINAL_STATE) continue;
+ System.out.printf("\n%s: (%s) %d p %s org %s %s \n",this.getClass().getSimpleName(),
+ mcp.getGeneratorStatus()==MCParticle.FINAL_STATE?"F":"I",mcp.getPDGID(),mcp.getMomentum().toString(),mcp.getOrigin().toString(),
+ mcp.getParents().size()>0?"parents:":"");
+ for(MCParticle parent : mcp.getParents()) {
+ System.out.printf("%s: (%s) %d p %s org %s %s \n",this.getClass().getSimpleName(),
+ parent.getGeneratorStatus()==MCParticle.FINAL_STATE?"F":"I",parent.getPDGID(),parent.getMomentum().toString(),parent.getOrigin().toString(),
+ parent.getParents().size()>0?"parents:":"");
+ for(MCParticle grparent : parent.getParents()) {
+ System.out.printf("%s: (%s) %d p %s org %s %s \n",this.getClass().getSimpleName(),
+ grparent.getGeneratorStatus()==MCParticle.FINAL_STATE?"F":"I",grparent.getPDGID(),grparent.getMomentum().toString(),grparent.getOrigin().toString(),
+ grparent.getParents().size()>0?"parents:":"");
+ }
+
+ }
+ }
+ return;
+ }
+
+ private double getInvMassTracks(HelicalTrackFit htf1, HelicalTrackFit htf2) {
+ double p1 = htf1.p(this._B.magnitude());
+ double p2 = htf2.p(this._B.magnitude());
+ Hep3Vector p1vec = VecOp.mult(p1, HelixUtils.Direction(htf1, 0));
+ Hep3Vector p2vec = VecOp.mult(p2, HelixUtils.Direction(htf2, 0));
+ double me = 0.000510998910;
+ double E1 = Math.sqrt(p1*p1 + me*me);
+ double E2 = Math.sqrt(p2*p2 + me*me);
+ //System.out.printf("p1 %f %s E1 %f\n",p1,p1vec.toString(),E1);
+ //System.out.printf("p2 %f %s E2 %f\n",p2,p2vec.toString(),E2);
+ return Math.sqrt( Math.pow(E1+E2,2) - VecOp.add(p1vec, p2vec).magnitudeSquared() );
+ }
+
+
+ public class PerigeeParams {
+ private BasicMatrix _params;
+
+ private PerigeeParams(HelicalTrackFit htf) {
+ _params = GBLOutput.this.getPerParVector(htf);
+ }
+ public BasicMatrix getParams() {
+ return _params;
+ }
+ public double getKappa() {
+ return _params.e(0, 0);
+ }
+ public double getTheta() {
+ return _params.e(0, 1);
+ }
+ public double getPhi() {
+ return _params.e(0, 2);
+ }
+ public double getD0() {
+ return _params.e(0, 3);
+ }
+ public double getZ0() {
+ return _params.e(0, 4);
+ }
+ }
+
+ /**
+ * Computes the projection matrix from the perigee XY plane variables
+ * dca and z0 into the curvilinear xT,yT,zT frame (U,V,T)
+ * @param htf input helix to find the track direction
+ * @return 3x3 projection matrix
+ */
+ Hep3Matrix getPerToClPrj(HelicalTrackFit htf) {
+ Hep3Vector Z = new BasicHep3Vector(0,0,1);
+ Hep3Vector T = HelixUtils.Direction(htf, 0.);
+ Hep3Vector J = VecOp.mult(1./VecOp.cross(T,Z).magnitude(), VecOp.cross(T, Z));
+ Hep3Vector K = Z;
+ Hep3Vector U = VecOp.mult(-1, J);
+ Hep3Vector V = VecOp.cross(T, U);
+ Hep3Vector I = VecOp.cross(J, K);
+
+ BasicHep3Matrix trans = new BasicHep3Matrix();
+ trans.setElement(0, 0, VecOp.dot(I, U));
+ trans.setElement(0, 1, VecOp.dot(J, U));
+ trans.setElement(0, 2, VecOp.dot(K, U));
+ trans.setElement(1, 0, VecOp.dot(I, V));
+ trans.setElement(1, 1, VecOp.dot(J, V));
+ trans.setElement(1, 2, VecOp.dot(K, V));
+ trans.setElement(2, 0, VecOp.dot(I, T));
+ trans.setElement(2, 1, VecOp.dot(J, T));
+ trans.setElement(2, 2, VecOp.dot(K, T));
+ return trans;
+
+ }
+
+
+
+
+ public class ClParams {
+ private BasicMatrix _params = new BasicMatrix(1,5);
+ private ClParams(HelicalTrackFit htf) {
+
+ if (htf == null) return;
+
+ Hep3Matrix perToClPrj = GBLOutput.this.getPerToClPrj(htf);
+
+ double d0 = -1 * htf.dca(); //sign convention for curvilinear frame
+ double z0 = htf.z0();
+ Hep3Vector vecPer = new BasicHep3Vector(0.,d0,z0);
+ //System.out.printf("%s: vecPer=%s\n",this.getClass().getSimpleName(),vecPer.toString());
+
+ Hep3Vector vecCl = VecOp.mult(perToClPrj, vecPer);
+ //System.out.printf("%s: vecCl=%s\n",this.getClass().getSimpleName(),vecCl.toString());
+ double xT = vecCl.x();
+ double yT = vecCl.y();
+ //double zT = vecCl.z();
+
+ Hep3Vector T = HelixUtils.Direction(htf, 0.);
+ Hep3Vector p = VecOp.mult(htf.p(Math.abs(_B.z())), T);
+ double lambda = Math.atan(htf.slope());
+ double q = Math.signum(htf.R());
+ double qOverP = q/p.magnitude();
+ double phi = htf.phi0();
+
+ _params.setElement(0, 0, qOverP);
+ _params.setElement(0, 1, lambda);
+ _params.setElement(0, 2, phi);
+ _params.setElement(0, 3, xT);
+ _params.setElement(0, 4, yT);
+
+ }
+
+ public BasicMatrix getParams() {
+ return _params;
+ }
+
+ double getLambda() {
+ return _params.e(0,1);
+ }
+ double getQoverP() {
+ return _params.e(0,0);
+ }
+ double getPhi() {
+ return _params.e(0,2);
+ }
+ double getXt() {
+ return _params.e(0,3);
+ }
+ double getYt() {
+ return _params.e(0,4);
+ }
+
+ }
+
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutputDriver.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLOutputDriver.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,199 @@
+package org.hps.recon.tracking.gbl;
+
+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.hps.recon.tracking.EventQuality;
+import org.hps.recon.tracking.TrackUtils;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.LCRelation;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.Track;
+import org.lcsim.event.base.MyLCRelation;
+import org.lcsim.geometry.Detector;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+* This driver class is used to
+* 1) write lcio collection of GBL info objects OR
+* 2) write GBL info into a unstructures text-based output
+*
+* It uses a helper class that does the actual work. We will port GBL to java and that will replace this driver.
+*
+* @author Per Hansson Adrian <[log in to unmask]>
+* @version $Id: GBLOutputDriver.java,v 1.9 2013/11/07 03:54:58 phansson Exp $ $Date: 2013/11/07 03:54:58 $ $Author: phansson $
+*
+*/
+public class GBLOutputDriver extends Driver {
+
+ private AIDA aida = AIDA.defaultInstance();
+ int nevt = 0;
+ GBLOutput gbl;
+ TruthResiduals truthRes = null;
+ private String gblFileName = "";
+ private String outputPlotFileName="";
+ private String MCParticleCollectionName = "MCParticle";
+ private int _debug = 0;
+ private boolean isMC = true;
+ private int totalTracks=0;
+ private int totalTracksProcessed=0;
+ private int iTrack = 0;
+ private int iEvent = 0;
+
+
+
+ public GBLOutputDriver() {
+ }
+
+
+ @Override
+ public void detectorChanged(Detector detector) {
+ Hep3Vector bfield = detector.getFieldMap().getField(new BasicHep3Vector(0., 0., 1.));
+
+ // Create the class that handles all the GBL output
+ gbl = new GBLOutput(gblFileName,bfield); // if filename is empty no text file is written
+ gbl.setDebug(_debug);
+ gbl.buildModel(detector);
+ gbl.setAPrimeEventFlag(false);
+ gbl.setXPlaneFlag(false);
+
+ //Create the class that makes residual plots for cross-checking
+ //truthRes = new TruthResiduals(bfield);
+ //truthRes.setDebug(_debug);
+ //truthRes.setHideFrame(hideFrame);
+ }
+
+
+
+ @Override
+ public void process(EventHeader event) {
+
+
+ List<Track> tracklist = null;
+ if(event.hasCollection(Track.class,"MatchedTracks")) {
+ tracklist = event.get(Track.class, "MatchedTracks");
+ if(_debug>0) {
+ System.out.printf("%s: Event %d has %d tracks\n", this.getClass().getSimpleName(),event.getEventNumber(),tracklist.size());
+ }
+ }
+
+
+ List<MCParticle> mcParticles = new ArrayList<MCParticle>();
+ if(event.hasCollection(MCParticle.class,this.MCParticleCollectionName)) {
+ mcParticles = event.get(MCParticle.class,this.MCParticleCollectionName);
+ }
+
+ List<SimTrackerHit> simTrackerHits = new ArrayList<SimTrackerHit>();
+ if (event.hasCollection(SimTrackerHit.class, "TrackerHits")) {
+ simTrackerHits = event.getSimTrackerHits("TrackerHits");
+ }
+
+ if(isMC) {
+ if(truthRes != null) {
+ truthRes.processSim(mcParticles, simTrackerHits);
+ }
+ }
+
+
+ List<Track> selected_tracks = new ArrayList<Track>();
+ for (Track trk : tracklist) {
+ totalTracks++;
+ if(TrackUtils.isGoodTrack(trk, tracklist, EventQuality.Quality.MEDIUM)) {
+ if(_debug>0) System.out.printf("%s: Track failed selection\n", this.getClass().getSimpleName());
+ selected_tracks.add(trk);
+ }
+ }
+
+ // GBLData
+ // containers and data
+ List<GBLEventData> gblEventData = new ArrayList<GBLEventData>();
+ gblEventData.add(new GBLEventData(event.getEventNumber(),gbl.get_B().z()));
+ List<GBLTrackData> gblTrackDataList = new ArrayList<GBLTrackData>();
+ List<GBLStripClusterData> gblStripDataListAll = new ArrayList<GBLStripClusterData>();
+ List<GBLStripClusterData> gblStripDataList = new ArrayList<GBLStripClusterData>();
+ List<LCRelation> gblTrackToStripClusterRelationListAll = new ArrayList<LCRelation>();
+ List<LCRelation> trackToGBLTrackRelationListAll = new ArrayList<LCRelation>();
+
+ gbl.printNewEvent(iEvent,gbl.get_B().z());
+
+ iTrack = 0;
+ for (Track trk : selected_tracks) {
+ if(_debug>0) System.out.printf("%s: Print GBL output for this track\n", this.getClass().getSimpleName());
+
+ //GBLDATA
+ GBLTrackData gblTrackData = new GBLTrackData(iTrack);
+ gblTrackDataList.add(gblTrackData);
+
+ //print to text file
+ gbl.printTrackID(iTrack);
+ gbl.printGBL(trk,gblTrackData,gblStripDataList,mcParticles,simTrackerHits,this.isMC);
+
+ //GBLDATA
+ //add relation to normal track object
+ trackToGBLTrackRelationListAll.add(new MyLCRelation(trk,gblTrackData));
+ // add strip clusters to lists
+ for(GBLStripClusterData gblStripClusterData : gblStripDataList) {
+ // add all strip clusters from this track to output list
+ gblStripDataListAll.add(gblStripClusterData);
+ // add LC relations between cluster and track
+ gblTrackToStripClusterRelationListAll.add(new MyLCRelation(gblTrackData,gblStripClusterData));
+ }
+ // clear list of strips for next track
+ gblStripDataList.clear();
+
+ totalTracksProcessed++;
+ ++iTrack;
+ }
+
+ // Put GBL info into event
+ event.put("GBLEventData", gblEventData, GBLEventData.class, 0);
+ event.put("GBLTrackData", gblTrackDataList, GBLTrackData.class, 0);
+ event.put("GBLStripClusterData", gblStripDataListAll, GBLStripClusterData.class, 0);
+ event.put("GBLTrackToStripData", gblTrackToStripClusterRelationListAll, LCRelation.class, 0);
+ event.put("TrackToGBLTrack", trackToGBLTrackRelationListAll, LCRelation.class, 0);
+
+ ++iEvent;
+
+ }
+
+ @Override
+ public void endOfData() {
+ gbl.close();
+ if (!"".equals(outputPlotFileName)) {
+ try {
+ aida.saveAs(outputPlotFileName);
+ } catch (IOException ex) {
+ Logger.getLogger(GBLOutputDriver.class.getName()).log(Level.SEVERE, "Couldn't save aida plots to file " + outputPlotFileName, ex);
+ }
+ }
+ System.out.println(this.getClass().getSimpleName() + ": Total Number of Events = "+iEvent);
+ System.out.println(this.getClass().getSimpleName() + ": Total Number of Tracks = "+totalTracks);
+ System.out.println(this.getClass().getSimpleName() + ": Total Number of Tracks Processed = "+totalTracksProcessed);
+
+
+ }
+
+ public void setDebug(int v) {
+ this._debug = v;
+ }
+ public void setGblFileName(String filename) {
+ gblFileName = filename;
+ }
+ public void setOutputPlotFileName(String filename) {
+ outputPlotFileName = filename;
+ }
+ public void setIsMC(boolean isMC) {
+ this.isMC = isMC;
+ }
+
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLStripClusterData.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLStripClusterData.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,307 @@
+package org.hps.recon.tracking.gbl;
+
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+
+import org.lcsim.event.GenericObject;
+
+/**
+ * A class providing for storing strip clusters for GBL
+ *
+ * @author phansson
+ *
+ */
+public class GBLStripClusterData implements GenericObject {
+
+ /*
+ *
+ * Interface enumerator to access the correct data
+ *
+ */
+ private static class GBLINT {
+ public static final int ID = 0;
+ public static final int BANK_INT_SIZE = 1;
+ }
+ private static class GBLDOUBLE {
+ public static final int PATH3D = 0;
+ public static final int PATH = 1;
+ public static final int UX = 2;
+ public static final int UY = 3;
+ public static final int UZ = 4;
+ public static final int VX = 5;
+ public static final int VY = 6;
+ public static final int VZ = 7;
+ public static final int WX = 8;
+ public static final int WY = 9;
+ public static final int WZ = 10;
+ public static final int TDIRX = 11;
+ public static final int TDIRY = 12;
+ public static final int TDIRZ = 13;
+ public static final int TPHI = 14;
+ public static final int UMEAS = 15;
+ public static final int TPOSU = 16 ;
+ public static final int TPOSV = 17;
+ public static final int TPOSW = 18;
+ public static final int UMEASERR = 19;
+ public static final int MSANGLE = 20;
+ public static final int TLAMBDA = 21;
+
+
+ public static final int BANK_DOUBLE_SIZE = 22;
+
+ }
+ // array holding the integer data
+ private int bank_int[] = new int[GBLINT.BANK_INT_SIZE];
+ // array holding the double data
+ private double bank_double[] = new double[GBLDOUBLE.BANK_DOUBLE_SIZE];
+
+ /**
+ * Default constructor
+ */
+ public GBLStripClusterData(int id) {
+ setId(id);
+ }
+
+ /**
+ * @param set track id to val
+ */
+ public void setId(int val) {
+ bank_int[GBLINT.ID] = val;
+ }
+
+ /**
+ * @return track id for this object
+ */
+ public int getId() {
+ return this.getIntVal(GBLINT.ID);
+ }
+
+ /**
+ * Set path length to this strip cluster
+ * @param val
+ */
+ public void setPath(double val) {
+ bank_double[GBLDOUBLE.PATH] = val;
+ }
+
+ /**
+ * Get path length to this strip cluster
+ */
+ public double getPath() {
+ return getDoubleVal(GBLDOUBLE.PATH);
+ }
+
+ /**
+ * Set path length to this strip cluster
+ * @param val
+ */
+ public void setPath3D(double val) {
+ bank_double[GBLDOUBLE.PATH3D] = val;
+ }
+
+ /**
+ * Get path length to this strip cluster
+ */
+ public double getPath3D() {
+ return getDoubleVal(GBLDOUBLE.PATH3D);
+ }
+
+
+ /**
+ * Set and get u vector for this strip sensor
+ */
+ public void setU(Hep3Vector u) {
+ bank_double[GBLDOUBLE.UX] = u.x();
+ bank_double[GBLDOUBLE.UY] = u.y();
+ bank_double[GBLDOUBLE.UZ] = u.z();
+ }
+ public Hep3Vector getU() {
+ return new BasicHep3Vector(getUx(),getUy(),getUz());
+ }
+ public double getUx() {
+ return getDoubleVal(GBLDOUBLE.UX);
+ }
+ public double getUy() {
+ return getDoubleVal(GBLDOUBLE.UY);
+ }
+ public double getUz() {
+ return getDoubleVal(GBLDOUBLE.UZ);
+ }
+
+ /**
+ * Set and get v vector for this strip sensor
+ */
+
+ public void setV(Hep3Vector v) {
+ bank_double[GBLDOUBLE.VX] = v.x();
+ bank_double[GBLDOUBLE.VY] = v.y();
+ bank_double[GBLDOUBLE.VZ] = v.z();
+ }
+ public Hep3Vector getV() {
+ return new BasicHep3Vector(getVx(),getVy(),getVz());
+ }
+ public double getVx() {
+ return getDoubleVal(GBLDOUBLE.VX);
+ }
+ public double getVy() {
+ return getDoubleVal(GBLDOUBLE.VY);
+ }
+ public double getVz() {
+ return getDoubleVal(GBLDOUBLE.VZ);
+ }
+
+ /**
+ * Set and get w vector for this strip sensor
+ */
+
+ public void setW(Hep3Vector v) {
+ bank_double[GBLDOUBLE.WX] = v.x();
+ bank_double[GBLDOUBLE.WY] = v.y();
+ bank_double[GBLDOUBLE.WZ] = v.z();
+ }
+ public Hep3Vector getW() {
+ return new BasicHep3Vector(getWx(),getWy(),getWz());
+ }
+ public double getWx() {
+ return getDoubleVal(GBLDOUBLE.WX);
+ }
+ public double getWy() {
+ return getDoubleVal(GBLDOUBLE.WY);
+ }
+ public double getWz() {
+ return getDoubleVal(GBLDOUBLE.WZ);
+ }
+
+ /**
+ * Set track direction at this cluster
+ *
+ * @param tDir
+ */
+ public void setTrackDir(Hep3Vector v) {
+ bank_double[GBLDOUBLE.TDIRX] = v.x();
+ bank_double[GBLDOUBLE.TDIRY] = v.y();
+ bank_double[GBLDOUBLE.TDIRZ] = v.z();
+ }
+ public Hep3Vector getTrackDirection() {
+ return new BasicHep3Vector(getTx(),getTy(),getTz());
+ }
+ public double getTx() {
+ return getDoubleVal(GBLDOUBLE.TDIRX);
+ }
+ public double getTy() {
+ return getDoubleVal(GBLDOUBLE.TDIRY);
+ }
+ public double getTz() {
+ return getDoubleVal(GBLDOUBLE.TDIRY);
+ }
+
+ public void setTrackPhi(double phi) {
+ bank_double[GBLDOUBLE.TPHI] = phi;
+ }
+
+ public double getTrackPhi() {
+ return getDoubleVal(GBLDOUBLE.TPHI);
+ }
+
+ public void setTrackLambda(double lambda) {
+ bank_double[GBLDOUBLE.TLAMBDA] = lambda;
+ }
+
+ public double getTrackLambda() {
+ return getDoubleVal(GBLDOUBLE.TLAMBDA);
+ }
+
+
+ public void setMeas(double umeas) {
+ bank_double[GBLDOUBLE.UMEAS] = umeas;
+ }
+
+ public double getMeas() {
+ return getDoubleVal(GBLDOUBLE.UMEAS);
+ }
+
+ public void setMeasErr(double x) {
+ bank_double[GBLDOUBLE.UMEASERR] = x;
+ }
+
+ public double getMeasErr() {
+ return getDoubleVal(GBLDOUBLE.UMEASERR);
+ }
+
+
+ /**
+ * Set track position in local frame
+ * @param trkpos_meas
+ */
+ public void setTrackPos(Hep3Vector trkpos_meas) {
+ bank_double[GBLDOUBLE.TPOSU] = trkpos_meas.x();
+ bank_double[GBLDOUBLE.TPOSV] = trkpos_meas.y();
+ bank_double[GBLDOUBLE.TPOSW] = trkpos_meas.z();
+ }
+
+ public Hep3Vector getTrackPos() {
+ return new BasicHep3Vector(getTrackPosU(),getTrackPosV(),getTrackPosW());
+ }
+
+ public double getTrackPosU() {
+ return getDoubleVal(GBLDOUBLE.TPOSU);
+ }
+
+ public double getTrackPosV() {
+ return getDoubleVal(GBLDOUBLE.TPOSV);
+ }
+
+ public double getTrackPosW() {
+ return getDoubleVal(GBLDOUBLE.TPOSW);
+ }
+
+ public void setScatterAngle(double scatAngle) {
+ bank_double[GBLDOUBLE.MSANGLE] = scatAngle;
+ }
+
+ public double getScatterAngle() {
+ return getDoubleVal(GBLDOUBLE.MSANGLE);
+ }
+
+
+
+
+
+
+ /*
+ * The functions below are all overide from
+ * @see org.lcsim.event.GenericObject#getNInt()
+ */
+
+ public int getNInt() {
+ return GBLINT.BANK_INT_SIZE;
+ }
+
+ public int getNFloat() {
+ return 0;
+ }
+
+ public int getNDouble() {
+ return GBLDOUBLE.BANK_DOUBLE_SIZE;
+ }
+
+ public int getIntVal(int index) {
+ return bank_int[index];
+ }
+
+ public float getFloatVal(int index) {
+ return 0;
+ }
+
+ public double getDoubleVal(int index) {
+ return bank_double[index];
+ }
+
+ public boolean isFixedSize() {
+ return false;
+ }
+
+
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLTrackData.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/GBLTrackData.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,108 @@
+package org.hps.recon.tracking.gbl;
+
+import org.hps.recon.tracking.gbl.GBLOutput.PerigeeParams;
+import org.lcsim.event.GenericObject;
+
+public class GBLTrackData implements GenericObject {
+
+ /*
+ *
+ * Interface enumerator to access the correct data
+ *
+ */
+ private static class GBLINT {
+ public static final int ID = 0;
+ public static final int BANK_INT_SIZE = 1;
+ }
+ private static class GBLDOUBLE {
+ public static final int PERKAPPA =0;
+ public static final int PERTHETA = 1;
+ public static final int PERPHI = 2;
+ public static final int PERD0 = 3;
+ public static final int PERZ0 = 4;
+ // 9 entries from projection matrix from perigee to curvilinear frame
+ public static final int BANK_DOUBLE_SIZE = 5+9;
+ }
+ // array holding the integer data
+ private int bank_int[] = new int[GBLINT.BANK_INT_SIZE];
+ // array holding the double data
+ private double bank_double[] = new double[GBLDOUBLE.BANK_DOUBLE_SIZE];
+
+ /**
+ * Default constructor
+ */
+ public GBLTrackData(int id) {
+ setTrackId(id);
+ }
+
+ /**
+ * @param set track id to val
+ */
+ public void setTrackId(int val) {
+ bank_int[GBLINT.ID] = val;
+ }
+
+ /**
+ * @return track id for this object
+ */
+ public int getTrackId() {
+ return this.getIntVal(GBLINT.ID);
+ }
+
+ /**
+ * @param perPar is the perigee parameters that is added to object
+ */
+ public void setPerigeeTrackParameters(PerigeeParams perPar) {
+ this.bank_double[GBLDOUBLE.PERKAPPA] = perPar.getKappa();
+ this.bank_double[GBLDOUBLE.PERTHETA] = perPar.getTheta();
+ this.bank_double[GBLDOUBLE.PERPHI] = perPar.getPhi();
+ this.bank_double[GBLDOUBLE.PERD0] = perPar.getD0();
+ this.bank_double[GBLDOUBLE.PERZ0] = perPar.getZ0();
+ }
+
+
+ public void setPrjPerToCl(int row, int col, double val) {
+ int idx = col + row*3;
+ if(idx>8) {
+ System.out.printf("%s: ERROR to large matrix\n", this.getClass().getSimpleName());
+ System.exit(1);
+ }
+ this.bank_double[idx+5] = val;
+ }
+
+
+ /*
+ * The functions below are all overide from
+ * @see org.lcsim.event.GenericObject#getNInt()
+ */
+
+ public int getNInt() {
+ return GBLINT.BANK_INT_SIZE;
+ }
+
+ public int getNFloat() {
+ return 0;
+ }
+
+ public int getNDouble() {
+ return GBLDOUBLE.BANK_DOUBLE_SIZE;
+ }
+
+ public int getIntVal(int index) {
+ return bank_int[index];
+ }
+
+ public float getFloatVal(int index) {
+ return 0;
+ }
+
+ public double getDoubleVal(int index) {
+ return bank_double[index];
+ }
+
+ public boolean isFixedSize() {
+ return false;
+ }
+
+
+}
java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/TruthResiduals.java (rev 0)
+++ java/sandbox/tracking/src/main/java/org/hps/recon/tracking/gbl/TruthResiduals.java 2014-03-26 00:20:42 UTC (rev 348)
@@ -0,0 +1,349 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.hps.recon.tracking.gbl;
+
+import hep.aida.IAnalysisFactory;
+import hep.aida.IHistogram;
+import hep.aida.IHistogram1D;
+import hep.aida.IHistogram2D;
+import hep.aida.IHistogramFactory;
+import hep.aida.IPlotter;
+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.hps.recon.tracking.HPSTransformations;
+import org.hps.recon.tracking.TrackUtils;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.fit.helicaltrack.HelicalTrackFit;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ * Calculates and plots truth residuals for track
+ * @author Per Hansson Adrian <[log in to unmask]>
+ * @version $Id: TruthResiduals.java,v 1.10 2013/11/07 03:54:58 phansson Exp $ $Date: 2013/11/07 03:54:58 $ $Author: phansson $
+ */
+public class TruthResiduals {
+
+ private int _debug;
+ private boolean _hideFrame = true;
+ private Hep3Vector _B;
+ private AIDA aida = AIDA.defaultInstance();
+ private IAnalysisFactory af = aida.analysisFactory();
+ private Map<Integer, List<IHistogram1D> > res_truthsimhit = null;
+ private Map<Integer, List<IHistogram1D> > res_truthsimhit_top_plus = null;
+ private Map<Integer, List<IHistogram1D> > res_truthsimhit_bot_plus = null;
+ private Map<Integer, List<IHistogram1D> > res_truthsimhit_top_minus = null;
+ private Map<Integer, List<IHistogram1D> > res_truthsimhit_bot_minus = null;
+ private IHistogram2D h_mcp_org;
+ private IHistogram2D trkpos_y_vs_x;
+ private boolean firstWeirdTrack = true;
+
+
+
+ /*
+ * file name
+ * Bz in Tesla
+ */
+ public TruthResiduals(Hep3Vector bfield) {
+ _B = HPSTransformations.transformVectorToTracking(bfield);
+ System.out.printf("%s: B field %s\n",this.getClass().getSimpleName(),_B.toString());
+ }
+ public void setDebug(int debug) {
+ _debug = debug;
+ }
+ public void setHideFrame(boolean hide) {
+ _hideFrame = hide;
+ }
+
+
+ public void processSim(List<MCParticle> mcParticles, List<SimTrackerHit> simTrackerHits) {
+
+ if(res_truthsimhit == null) makePlots();
+
+
+ // map layer, mcparticles and sim hits
+ Map<Integer, List<SimTrackerHit>> simHitsLayerMap = new HashMap<Integer, List<SimTrackerHit> >();
+ Map<MCParticle, List<SimTrackerHit> > mcPartSimHitsMap = new HashMap<MCParticle, List<SimTrackerHit > >();
+ for(SimTrackerHit sh : simTrackerHits) {
+ Hep3Vector shpos = HPSTransformations.transformVectorToTracking(sh.getPositionVec());
+ if(Math.abs(shpos.x()) < 50.0) {
+ System.out.printf("%s: Weird hit at %s (%s) in layer %d for MC part %d org %s p %s\n",
+ this.getClass().getSimpleName(),sh.getPositionVec().toString(),shpos.toString(),sh.getIdentifierFieldValue("layer"),
+ sh.getMCParticle().getPDGID(),sh.getMCParticle().getOrigin().toString(),sh.getMCParticle().getMomentum().toString());
+ System.exit(1);
+ }
+
+ int layer = sh.getIdentifierFieldValue("layer");
+ if(!simHitsLayerMap.containsKey(layer)) {
+ simHitsLayerMap.put(layer, new ArrayList<SimTrackerHit>());
+ }
+ simHitsLayerMap.get(layer).add(sh);
+
+ MCParticle part = sh.getMCParticle();
+ if(!mcPartSimHitsMap.containsKey(part)) {
+ mcPartSimHitsMap.put(part, new ArrayList<SimTrackerHit>());
+ }
+ mcPartSimHitsMap.get(part).add(sh);
+ }
+
+
+ for(MCParticle mcp : mcPartSimHitsMap.keySet()) {
+ this.h_mcp_org.fill(mcp.getOriginX(), mcp.getOriginY());
+ }
+
+ // Find the particle responsible for the hit in each layer and compute the residual
+
+ for(int layer=1;layer<13;++layer) {
+ //System.out.printf("layer %d: \n",layer);
+
+ List<SimTrackerHit> simHitsLayer = simHitsLayerMap.get(layer);
+
+
+ if(simHitsLayer != null ) {
+
+ if(simHitsLayer.size()==2) continue;
+
+ for(SimTrackerHit simHit : simHitsLayer) {
+
+ // Find the MC particle
+ MCParticle mcp = simHit.getMCParticle();
+
+ if(mcp.getMomentum().magnitude()<0.5) continue;
+
+ // Position in tracking coord
+ Hep3Vector simHitPosTracking = HPSTransformations.transformVectorToTracking(simHit.getPositionVec());
+
+ if(_debug>0) {
+ System.out.printf("%s: simHit for layer %d at %s (%s) from MC part %d org %s p %s\n",
+ this.getClass().getSimpleName(),layer,simHit.getPositionVec().toString(),simHitPosTracking.toString(),
+ simHit.getMCParticle().getPDGID(),simHit.getMCParticle().getOrigin().toString(),simHit.getMCParticle().getMomentum().toString());
+
+ if(simHitPosTracking.x()<50.) System.exit(1);
+
+ }
+
+
+
+ // Get track parameters from MC particle
+ //HelicalTrackFit htfTruth = TrackUtils.getHTF(mcp, -1*this._B.z());
+ HelicalTrackFit htfTruth = TrackUtils.getHTF(mcp, -1*this._B.z());
+
+ Hep3Vector trkposExtraPolator = TrackUtils.extrapolateTrack(htfTruth,simHitPosTracking.x());
+ //System.out.printf("trkposextrapol (det) %s\n",trkposExtraPolator.toString());
+
+ trkposExtraPolator = HPSTransformations.transformVectorToTracking(trkposExtraPolator);
+
+ // Calculate residuals
+ Hep3Vector res = VecOp.sub(simHitPosTracking, trkposExtraPolator);
+
+ //System.out.printf("trkpos %s trkposextrapol %s res %s\n",trkpos.toString(),trkposExtraPolator.toString(),res.toString());
+
+ // Fill residuals
+ this.res_truthsimhit.get(layer).get(0).fill(res.y());
+ this.res_truthsimhit.get(layer).get(1).fill(res.z());
+ if(simHit.getPositionVec().y()>0) {
+ if(simHit.getMCParticle().getPDGID()<0) {
+ this.res_truthsimhit_top_plus.get(layer).get(0).fill(res.y());
+ this.res_truthsimhit_top_plus.get(layer).get(1).fill(res.z());
+ }
+ else {
+ this.res_truthsimhit_top_minus.get(layer).get(0).fill(res.y());
+ this.res_truthsimhit_top_minus.get(layer).get(1).fill(res.z());
+ }
+ }
+ else {
+ if(simHit.getMCParticle().getPDGID()<0) {
+ this.res_truthsimhit_bot_plus.get(layer).get(0).fill(res.y());
+ this.res_truthsimhit_bot_plus.get(layer).get(1).fill(res.z());
+ }
+ else {
+ this.res_truthsimhit_bot_minus.get(layer).get(0).fill(res.y());
+ this.res_truthsimhit_bot_minus.get(layer).get(1).fill(res.z());
+ }
+ }
+
+ if(layer == 1 && res.y() > 0.1 && this.firstWeirdTrack) {
+ double dx = 1.0;
+ double xpos = mcp.getOriginZ();
+ while(xpos< 100.) {
+ xpos += dx;
+ trkposExtraPolator = HPSTransformations.transformVectorToTracking(TrackUtils.extrapolateTrack(htfTruth,xpos));
+ double ypos = trkposExtraPolator.y();
+ trkpos_y_vs_x.fill(xpos,ypos);
+ }
+
+ int idummy = 0;
+ while(idummy<2) {
+ trkpos_y_vs_x.fill(simHitPosTracking.x(),simHitPosTracking.y());
+ idummy++;
+ //System.out.printf("weird simhit res pos %s \n", simHitPosTracking.toString());
+ }
+
+ this.firstWeirdTrack = false;
+
+ }
+
+
+ }
+ }
+ }
+
+ }
+
+
+ public IHistogram getResidual(int layer,String coord) {
+ if( !this.res_truthsimhit.containsKey(layer) )
+ throw new RuntimeException("Error the layer number is not valid");
+ if( coord!="x" || coord!="y")
+ throw new RuntimeException("Error the coord is not valid");
+ IHistogram1D h = this.res_truthsimhit.get(layer).get(coord=="x"?0:1);
+ return h;
+ }
+
+
+
+ private void makePlots() {
+
+
+ res_truthsimhit = new HashMap<Integer, List<IHistogram1D> >();
+ res_truthsimhit_top_plus = new HashMap<Integer, List<IHistogram1D> >();
+ res_truthsimhit_bot_plus = new HashMap<Integer, List<IHistogram1D> >();
+ res_truthsimhit_top_minus = new HashMap<Integer, List<IHistogram1D> >();
+ res_truthsimhit_bot_minus = new HashMap<Integer, List<IHistogram1D> >();
+
+
+
+
+
+ IHistogramFactory hf = aida.histogramFactory();
+ double min=-1.;
+ double max=1.;
+
+ List<IPlotter> plotter1 = new ArrayList<IPlotter>();
+ List<IPlotter> plotter2 = new ArrayList<IPlotter>();
+ List<IPlotter> plotter3 = new ArrayList<IPlotter>();
+ List<IPlotter> plotter4 = new ArrayList<IPlotter>();
+ List<IPlotter> plotter5 = new ArrayList<IPlotter>();
+
+
+ for(int idir=0;idir<2;++idir) {
+ String dir = idir==0?"x":"y";
+ IPlotter pl1 = af.createPlotterFactory().create(String.format("SimHit-Truth Track Residual %s",dir));
+ pl1.createRegions(3, 4);
+ IPlotter pl2 = af.createPlotterFactory().create(String.format("SimHit-Truth Track Residual %s",dir));
+ pl2.createRegions(3, 4);
+ IPlotter pl3 = af.createPlotterFactory().create(String.format("SimHit-Truth Track Residual %s",dir));
+ pl3.createRegions(3, 4);
+ IPlotter pl4 = af.createPlotterFactory().create(String.format("SimHit-Truth Track Residual %s",dir));
+ pl4.createRegions(3, 4);
+ IPlotter pl5 = af.createPlotterFactory().create(String.format("SimHit-Truth Track Residual %s",dir));
+ pl5.createRegions(3, 4);
+
+ for(int layer=1;layer<13;++layer) {
+
+ if(!res_truthsimhit.containsKey(layer)) {
+ res_truthsimhit.put(layer, new ArrayList<IHistogram1D>());
+ res_truthsimhit_top_plus.put(layer, new ArrayList<IHistogram1D>());
+ res_truthsimhit_bot_plus.put(layer, new ArrayList<IHistogram1D>());
+ res_truthsimhit_top_minus.put(layer, new ArrayList<IHistogram1D>());
+ res_truthsimhit_bot_minus.put(layer, new ArrayList<IHistogram1D>());
+ }
+
+ if(layer<2) {
+ max = 0.05;//0.07;
+ min = -0.05;//-0.07;
+ } else if(layer<3) {
+ max = 0.3;//0.07;
+ min = -0.3;//-0.07;
+ } else {
+ max = 0.5 * layer;
+ min = -1.0*max;
+ }
+
+ IHistogram1D h = hf.createHistogram1D(String.format("dres_truthsimhit_layer%d_%s",layer,dir),50, min, max);
+ h.setTitle(String.format("L%d SimHit-Truth Track Residual in %s",layer , dir));
+ res_truthsimhit.get(layer).add(h);
+ pl1.region(layer-1).plot(h);
+
+ h = hf.createHistogram1D(String.format("res_truthsimhit_top_plus_layer%d_%s",layer,dir),50, min, max);
+ h.setTitle(String.format("L%d SimHit-Truth Track (top,q=+1) Residual in %s",layer , dir));
+ res_truthsimhit_top_plus.get(layer).add(h);
+ pl2.region(layer-1).plot(h);
+
+ h = hf.createHistogram1D(String.format("res_truthsimhit_top_minus_layer%d_%s",layer,dir),50, min, max);
+ h.setTitle(String.format("L%d SimHit-Truth Track (top,q=-1) Residual in %s",layer , dir));
+ res_truthsimhit_top_minus.get(layer).add(h);
+ pl3.region(layer-1).plot(h);
+
+ h = hf.createHistogram1D(String.format("res_truthsimhit_bot_minus_layer%d_%s",layer,dir),50, min, max);
+ h.setTitle(String.format("L%d SimHit-Truth Track (bot,q=-1) Residual in %s",layer , dir));
+ res_truthsimhit_bot_minus.get(layer).add(h);
+ pl4.region(layer-1).plot(h);
+
+ h = hf.createHistogram1D(String.format("res_truthsimhit_bot_plus_layer%d_%s",layer,dir),50, min, max);
+ h.setTitle(String.format("L%d SimHit-Truth Track (bot,q=+1) Residual in %s",layer , dir));
+ res_truthsimhit_bot_plus.get(layer).add(h);
+ pl5.region(layer-1).plot(h);
+
+
+ }
+ plotter1.add(pl1);
+ plotter2.add(pl2);
+ plotter3.add(pl3);
+ plotter4.add(pl4);
+ plotter5.add(pl5);
+
+ if(!this._hideFrame) {
+ pl1.show();
+ pl2.show();
+ pl3.show();
+ pl4.show();
+ pl5.show();
+ }
+ else {
+ pl1.hide();
+ pl2.hide();
+ pl3.hide();
+ pl4.hide();
+ pl5.hide();
+ }
+
+ }
+
+
+ this.h_mcp_org = hf.createHistogram2D("MC particle origin", 50, -0.2,0.2,50,-0.2,0.2);
+ IPlotter pl_org = af.createPlotterFactory().create("MC particle origin");
+ pl_org.createRegions(1, 1);
+ pl_org.region(0).plot(h_mcp_org);
+ pl_org.region(0).style().setParameter("hist2DStyle", "colorMap");
+ pl_org.region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ if(this._hideFrame) pl_org.hide();
+ else pl_org.show();
+
+
+ trkpos_y_vs_x = hf.createHistogram2D("Track pos y vs x", 300, -150,150,100,-4,4);
+ IPlotter pl_pos_y_vs_x = af.createPlotterFactory().create("Track pos y vs x");
+ pl_pos_y_vs_x.createRegions(1, 1);
+ pl_pos_y_vs_x.region(0).plot(trkpos_y_vs_x);
+ pl_pos_y_vs_x.region(0).style().setParameter("hist2DStyle", "colorMap");
+ pl_pos_y_vs_x.region(0).style().dataStyle().fillStyle().setParameter("colorMapScheme", "rainbow");
+ if(this._hideFrame) pl_pos_y_vs_x.hide();
+ else pl_pos_y_vs_x.show();
+
+
+
+
+ }
+
+
+
+
+}
SVNspam 0.1