11 added files
lcsim/src/org/lcsim/contrib/onoprien/mcTrackFinder
diff -N ExampleDriver.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ExampleDriver.java 6 Apr 2007 21:40:27 -0000 1.1
@@ -0,0 +1,97 @@
+package org.lcsim.contrib.onoprien.mcTrackFinder;
+
+import java.util.*;
+import org.lcsim.event.*;
+import org.lcsim.util.swim.HelixSwimmer;
+import org.lcsim.util.Driver;
+import org.lcsim.spacegeom.*;
+import org.lcsim.util.aida.AIDA;
+import org.lcsim.recon.cat.GarfieldHitConverter;
+import org.lcsim.constants.Constants;
+
+/**
+ * An example driver showing how to use MCTrackFinder.
+ * In this case, the track finder is configured to emulate the performance of a
+ * vertex detector seeded algorithm by requiring hits in at least 3 VXD layers.
+ *
+ *
+ *
+ * @author D. Onoprienko
+ * @version $Id: ExampleDriver.java,v 1.1 2007/04/06 21:40:27 onoprien Exp $
+ */
+public class ExampleDriver extends Driver {
+
+ //private AIDA aida = AIDA.defaultInstance();
+
+ public ExampleDriver() {
+
+// GarfieldHitConverter hitDigitizer = new GarfieldHitConverter();
+//
+// hitDigitizer.set("OUTPUT_COLLECTION_NAME", "GarfieldHitsRaw");
+// add(hitDigitizer);
+
+// MCTrackFinder mcTrackFinder = new MCTrackFinder();
+// mcTrackFinder.addTrackerHitList("GarfieldHitsRaw"); // Set input TrackerHit collection name
+// mcTrackFinder.set("Track_Collection_Name", "CheaterTracks"); // Set output Track collection name
+// mcTrackFinder.set("Min_VXD_Layers", 3); // Set cut on number of layers with SimTrackerHits
+// add(mcTrackFinder);
+ }
+
+ public void process(EventHeader event) {
+ System.out.println("Processing event " + event.getEventNumber());
+ super.process(event);
+
+ int count2 = 0;
+ List<List<SimTrackerHit>> hitLists = event.get(SimTrackerHit.class);
+ for (List<SimTrackerHit> hitList : hitLists) {
+ for (SimTrackerHit hit : hitList) {
+ count2++;;
+ }
+ }
+
+ HashMap<MCParticle, List<SimTrackerHit>> map = MCTrackFinder.getMCParticleToSimTrackerHitMap(event);
+ List<MCParticle> mcList = event.getMCParticles();
+ int count1 = 0;
+ for (MCParticle mc : mcList) {
+ System.out.println(" ");
+ System.out.println("Particle " + mc.getType().getName());
+ List<SimTrackerHit> hitList = map.get(mc);
+ for (SimTrackerHit hit : hitList) {
+ count1++;
+ System.out.println(" mc : " + hit.getMCParticle().getType().getName());
+ }
+ }
+ System.out.println(" ");
+ System.out.println("Expected " + count2 + " Found " + count1);
+
+
+// List<MCTrack> tracks = event.get(MCTrack.class,"CheaterTracks");
+// System.out.println("Field " + Const.bField);
+// int count = 0;
+// for (MCTrack track : tracks) {
+// count++;
+// double[] pAuto = track.getMomentum();
+// MCParticle mcPart = track.getMCParticle();
+// HelixSwimmer swimmer = new HelixSwimmer(Const.bField);
+// swimmer.setTrack(mcPart.getMomentum(), mcPart.getOrigin(), (int) mcPart.getCharge());
+// double alpha = swimmer.getDistanceToPoint(new SpacePoint());
+// SpaceVector pPCA = swimmer.getMomentumAtDistance(alpha);
+// double[] pMan = pPCA.v();
+//// if (true) {
+// if (Math.sqrt((pAuto[0]-pMan[0])*(pAuto[0]-pMan[0]) + (pAuto[1]-pMan[1])*(pAuto[1]-pMan[1]) + (pAuto[2]-pMan[2])*(pAuto[2]-pMan[2])) > 10e-10) {
+// System.out.println(" ");
+// double Pt = track.getPt();
+// double radius = Pt/(Const.bField*Constants.fieldConversion);
+// System.out.println("MC: Mom "+ mcPart.getMomentum() +" Charge "+ mcPart.getCharge() +" Pos "+mcPart.getOrigin() +" Rad " + radius);
+// System.out.println(" ");
+// System.out.println("Auto Mom " + pAuto[0] +" "+ pAuto[1] +" "+ pAuto[2] +" Alpha "+ track.getChi2());
+// System.out.println("Manual Mom " + pMan[0] +" "+ pMan[1] +" "+ pMan[2] +" Alpha "+ alpha);
+// System.out.println("Points: Auto = " + track.getReferencePointX() +" "+ track.getReferencePointY());
+// System.out.println("Points: Man = " + swimmer.getPointAtDistance(alpha));
+// }
+// }
+// System.out.println("Count " + count);
+// System.out.println(" ");
+ }
+
+}
\ No newline at end of file
lcsim/src/org/lcsim/contrib/onoprien/mcTrackFinder
diff -N MCTrack.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ MCTrack.java 6 Apr 2007 21:40:27 -0000 1.1
@@ -0,0 +1,235 @@
+package org.lcsim.contrib.onoprien.mcTrackFinder;
+
+import java.util.*;
+import org.lcsim.recon.cat.util.BasicTrack;
+import org.lcsim.recon.cat.util.Const;
+import org.lcsim.event.*;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Vector;
+import org.lcsim.spacegeom.SpacePoint;
+import org.lcsim.spacegeom.SpaceVector;
+import org.lcsim.geometry.Subdetector;
+
+/**
+ * Representation of a track found by the "cheater" track finder.
+ * Implements {@link Track}, and provides access to the underlying {@link MCParticle}
+ * object and to associated tracker hits.
+ * <p>
+ * An object of this class can be assigned any number of integer status codes through
+ * the call to {@link #setStatus(int,int) setStatus(int category, int status)} method.
+ * This allows users to mark Monte Carlo tracks that belong to a certain group, for example.
+ * Assigned statuses are retrieved by {@link #getStatus(int) getStatus(int category)}.
+ *
+ * @author D. Onoprienko
+ * @version $Id: MCTrack.java,v 1.1 2007/04/06 21:40:27 onoprien Exp $
+ */
+public class MCTrack extends BasicTrack {
+
+// -- Private fields : --------------------------------------------------------
+
+ private MCParticle _mcParticle;
+ private ArrayList<SimTrackerHit> _simHits;
+ private boolean _hitsSorted;
+
+ HashMap<Integer,Integer> _status;
+
+// -- Constructors : ----------------------------------------------------------
+
+ private void commonInit(MCParticle mcParticle) {
+ _mcParticle = mcParticle;
+ setHelixParameters(new SpacePoint(new BasicHep3Vector()), new SpacePoint(mcParticle.getOrigin()),
+ new SpaceVector(mcParticle.getMomentum()), (int)mcParticle.getCharge());
+ _status = new HashMap<Integer,Integer>(2);
+ }
+
+ public MCTrack(MCParticle mcParticle) {
+ super();
+ commonInit(mcParticle);
+ _simHits = new ArrayList<SimTrackerHit>(10);
+ _hitsSorted = false;
+ }
+
+ public MCTrack(MCParticle mcParticle, List<TrackerHit> hitList) {
+ super();
+ commonInit(mcParticle);
+ _hits = new ArrayList<TrackerHit>(hitList.size());
+ _hits.addAll(hitList);
+ _simHits = new ArrayList<SimTrackerHit>(10);
+ sortHits();
+ _hitsSorted = true;
+ }
+
+ public MCTrack(MCParticle mcParticle, List<TrackerHit> hitList, List<SimTrackerHit> simHitList) {
+ super();
+ commonInit(mcParticle);
+ _hits = new ArrayList<TrackerHit>(hitList.size());
+ _hits.addAll(hitList);
+ _simHits = new ArrayList<SimTrackerHit>(simHitList.size());
+ _simHits.addAll(simHitList);
+ sortHits();
+ _hitsSorted = true;
+ }
+
+// -- Getters : ---------------------------------------------------------------
+
+ /** Returns MCParticle that produced this track. */
+ public MCParticle getMCParticle() {return _mcParticle;}
+
+ /** Returns a list of associated tracker hits. */
+ public List<TrackerHit> getTrackerHits() {
+ if (!_hitsSorted) {
+ sortHits();
+ _hitsSorted = true;
+ }
+ return _hits;
+ }
+
+ /** Returns a list of associated SimTrackerHits hits. */
+ public List<SimTrackerHit> getSimTrackerHits() {
+ if (!_hitsSorted) {
+ sortHits();
+ _hitsSorted = true;
+ }
+ return _simHits;
+ }
+
+ /** Returns number of layers with SimTrackerHits that belong to this track. */
+ public int getNLayers() {
+ ArrayList<Layer> layers = new ArrayList<Layer>();
+ for (SimTrackerHit hit : _simHits) {
+ Layer layer = new Layer(hit.getLayer(), hit.getSubdetector());
+ if (!layers.contains(layer)) layers.add(layer);
+ }
+ return layers.size();
+ }
+
+ /** Returns number of VXD layers with SimTrackerHits that belong to this track. */
+ public int getNVxdLayers() {
+ ArrayList<Layer> layers = new ArrayList<Layer>();
+ Layer layer;
+ for (SimTrackerHit hit : _simHits) {
+ Subdetector sub = hit.getSubdetector();
+ if (Const.det().isVXD(sub)) {
+ layer = new Layer(hit.getLayer(), sub);
+ if (!layers.contains(layer)) layers.add(layer);
+ }
+ }
+ return layers.size();
+ }
+
+ /**
+ * Returns a status flag that has been previously assigned to this track through
+ * the call to {@link #setStatus(int,int) setStatus(int category, int status)}.
+ */
+ public int getStatus(int category) {
+ return _status.get(category);
+ }
+
+ /** Returns THETA angle of the MCParticle that rpoduced the track. */
+ public double getTheta() {
+ return Math.acos(_momentum[2]/getP());
+ }
+
+ /** Returns radius of innermost hit associated with this track. */
+ public double getRadiusOfInnermostHit() {
+ double rad = 0.;
+ if (!_hits.isEmpty()) {
+ if (!_hitsSorted) {
+ sortHits();
+ _hitsSorted = true;
+ }
+ double[] pos = _hits.get(0).getPosition();
+ rad = Math.hypot(pos[0], pos[1]);
+ }
+ return rad;
+ }
+
+// -- Setters : ---------------------------------------------------------------
+
+ /** Add hit to the list of tracker hits associated with this track. */
+ public void addTrackerHit(TrackerHit hit) {
+ if (! _hits.contains(hit)) {
+ _hits.add(hit);
+ _hitsSorted = false;
+ }
+ }
+
+ /** Add hits to the list of tracker hits associated with this track. */
+ public void addTrackerHits(List<TrackerHit> hitList) {
+ for (TrackerHit hit : hitList) if (! _hits.contains(hit)) _hits.add(hit);
+ _hitsSorted = false;
+ }
+
+ /** Add hit to the list of SimTrackerHits associated with this track. */
+ public void addSimTrackerHit(SimTrackerHit hit) {
+ if (! _hits.contains(hit)) {
+ _simHits.add(hit);
+ _hitsSorted = false;
+ }
+ }
+
+ /** Add hits to the list of SimTrackerHits associated with this track. */
+ public void addSimTrackerHits(List<SimTrackerHit> hitList) {
+ for (SimTrackerHit hit : hitList) if (! _simHits.contains(hit)) _simHits.add(hit);
+ _hitsSorted = false;
+ }
+
+ /**
+ * Set an integer status flag for this track.
+ *
+ * @param category Identifier of a status category. A track can be assigned
+ * statuses in any number of categories.
+ * @param status Status flag that can be later retrieved through the call to
+ * {@link #getStatus(int) getStatus(int category)}
+ */
+ public void setStatus(int category, int status) {_status.put(category, status);}
+
+// -- Private helper methods : ------------------------------------------------
+
+ /**
+ * Sort hits in the order of increasing distance from the detector center.
+ */
+ private void sortHits() {
+ Collections.sort(_hits, new Comparator<TrackerHit>() {
+ public int compare(TrackerHit hit1, TrackerHit hit2) {
+ double[] pos = hit1.getPosition();
+ double r1 = pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2];
+ pos = hit2.getPosition();
+ double r2 = pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2];
+ return (int)Math.signum(r1-r2);
+ }
+ });
+ Collections.sort(_simHits, new Comparator<SimTrackerHit>() {
+ public int compare(SimTrackerHit hit1, SimTrackerHit hit2) {
+ double[] pos = hit1.getPoint();
+ double r1 = pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2];
+ pos = hit2.getPoint();
+ double r2 = pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2];
+ return (int)Math.signum(r1-r2);
+ }
+ });
+
+ }
+
+// -- Helper class to pack (subdetector, layer) pair : ------------------------
+
+ private class Layer {
+
+ final int _layer;
+ final Subdetector _subDet;
+
+ Layer(int layer, org.lcsim.geometry.Subdetector subDet) {
+ _layer = layer;
+ _subDet = subDet;
+ }
+
+ public boolean equals(Object object) {
+ if (object.getClass() == Layer.class) {
+ Layer obj = (Layer)object;
+ return (obj._layer == _layer && obj._subDet == _subDet);
+ }
+ return super.equals(object);
+ }
+ }
+
+}
lcsim/src/org/lcsim/contrib/onoprien/mcTrackFinder
diff -N MCTrackFinder.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ MCTrackFinder.java 6 Apr 2007 21:40:27 -0000 1.1
@@ -0,0 +1,233 @@
+package org.lcsim.contrib.onoprien.mcTrackFinder;
+
+import java.util.*;
+import org.lcsim.recon.cat.util.NoSuchParameterException;
+import org.lcsim.event.*;
+import org.lcsim.util.Driver;
+import hep.physics.particle.Particle;
+
+/**
+ * Configurable "cheater" track finder.
+ * See descriptions of <tt>set()</tt> methods for the list of parameters that can be changed.
+ * <p>
+ * In addition, the cheater can be customized by overriding {@link #filter(MCParticle)}
+ * method that selects potentially reconstructable Monte Carlo particles,
+ * {@link #filter(MCTrack)} method that selects <tt>MCTracks</tt> to be saved into
+ * the output list, and {@link #findRelatedHits(MCParticle, List<TrackerHit>)} method
+ * that controls association of hits with <tt>MCParticle</tt>s.
+ * <p>
+ * The class also provides a number of static utility methods.
+ *
+ * @author D. Onoprienko
+ * @version $Id: MCTrackFinder.java,v 1.1 2007/04/06 21:40:27 onoprien Exp $
+ */
+public class MCTrackFinder extends Driver {
+
+// -- Constructors : ----------------------------------------------------------
+
+ public MCTrackFinder() {}
+
+// -- Setters : ---------------------------------------------------------------
+
+ /**
+ * Add a list of TrackerHits to be processed.
+ * Hits from these collections will be associated with found tracks.
+ */
+ public void addTrackerHitList(String name) {
+ _trackerHitListNames.add(name);
+ _trackerHitListNames.trimToSize();
+ }
+
+ /**
+ * Set any <tt>String</tt> parameter.
+ * The following parameters can be set with this method:<br>
+ * <tt>"Track_Collection_Name"</tt> - name of track collection to be saved into the event. Default: "MCTracks".
+ * @param name Name of parameter to be set
+ * @param value Value to be assigned to the parameter.
+ * @throws NoSuchParameterException Thrown if the supplied parameter name is unknown.
+ * Subclasses may catch this exception after a call to <tt>super.set()</tt>
+ * and set their own parameters.
+ */
+ public void set(String name, String value) {
+ if (name == "Track_Collection_Name") {
+ _trackListName = value;
+ } else {
+ throw new NoSuchParameterException(name, this.getClass());
+ }
+ }
+
+ /**
+ * Set any integer parameter.
+ * The following parameters can be set with this method:<br>
+ * <tt>"Min_Hits"</tt> - minimum number of TrackerHits required for the track to be found. Default: 0.<br>
+ * <tt>"Min_Sim_Hits"</tt> - minimum number of SimTrackerHits required for the track to be found. Default: 1.<br>
+ * <tt>"Min_Layers"</tt> - minimum number of layers with hits required for the track to be found. Default: 0.<br>
+ * <tt>"Min_VXD_Layers"</tt> - minimum number of vertex detector layers with hits required for the track to be found. Default: 0.<br>
+ * @param name Name of parameter to be set
+ * @param value Value to be assigned to the parameter.
+ * @throws NoSuchParameterException Thrown if the supplied parameter name is unknown.
+ * Subclasses may catch this exception after a call to <tt>super.set()</tt>
+ * and set their own parameters.
+ */
+ public void set(String name, int value) {
+ if (name.equalsIgnoreCase("Min_Hits")) {
+ _minHits = value;
+ } else if (name.equalsIgnoreCase("Min_Sim_Hits")) {
+ _minSimHits = value;
+ } else if (name.equalsIgnoreCase("Min_Layers")) {
+ _minLayers = value;
+ } else if (name.equalsIgnoreCase("Min_VXD_Layers")) {
+ _minVxdLayers = value;
+ } else {
+ throw new NoSuchParameterException(name, this.getClass());
+ }
+ }
+
+// -- Processing event : ------------------------------------------------------
+
+ /** Process event. */
+ public void process(EventHeader event) {
+
+ super.process(event);
+
+ // Create list of eligible MCParticles :
+
+ List<MCParticle> list = event.getMCParticles();
+ ArrayList<MCParticle> mcPartList = new ArrayList<MCParticle>(list.size());
+ for (MCParticle mcPart : list) {
+ if (filter(mcPart)) mcPartList.add(mcPart);
+ }
+
+ // Create list of TrackerHit hits to be supplied to the finder :
+
+ List<TrackerHit> hitList = new ArrayList<TrackerHit>();
+ for (String name : _trackerHitListNames) {
+ hitList.addAll(event.get(TrackerHit.class, name));
+ }
+
+ List<List<SimTrackerHit>> simTrackerHitLists = event.get(SimTrackerHit.class);
+
+ // Create list of Monte Carlo Tracks
+
+ ArrayList<MCTrack> mcTrackList = new ArrayList<MCTrack>(100);
+ for (MCParticle mcPart : mcPartList) {
+ // Find TrackerHits related to this MCParticle
+ List<TrackerHit> hits = findRelatedHits(mcPart, hitList);
+ // Find SimTrackerHits related to this MCParticle
+ ArrayList<SimTrackerHit> simHits = new ArrayList<SimTrackerHit>(100);
+ for (List<SimTrackerHit> hList : simTrackerHitLists) {
+ for (SimTrackerHit simHit : hList) {
+ if (simHit.getMCParticle() == mcPart) simHits.add(simHit);
+ }
+ }
+ // Create MCTrack and add it to the output list if it passes the cuts
+ MCTrack mcTrack = new MCTrack(mcPart, hits, simHits);
+ if (filter(mcTrack)) mcTrackList.add(mcTrack);
+ }
+ mcTrackList.trimToSize();
+
+ // Put list of tracks into the event :
+
+ event.put(_trackListName, mcTrackList, MCTrack.class, 0);
+
+ }
+
+ /**
+ * Selects hits from the supplied list that are associated with the given MCParticle.
+ * Default implementation assumes that <tt>getRawHits()</tt> method of hits in the list
+ * returns a list of <tt>SimTrackerHit</tt>s, and associates the hit with <tt>MCParticle</tt>
+ * if at least one of those <tt>SimTrackerHit</tt>s was produced by it.
+ * Method can be overwritten by subclasses to use a different algorithm.
+ */
+ protected List<TrackerHit> findRelatedHits(MCParticle mcPart, List<TrackerHit> hitList) {
+ ArrayList outList = new ArrayList<TrackerHit>();
+ for (TrackerHit hit : hitList) {
+ List rawHits = hit.getRawHits();
+ for (Object obj : rawHits) {
+ if (mcPart == ((SimTrackerHit)obj).getMCParticle()) {
+ outList.add(hit);
+ break;
+ }
+ }
+ }
+ return outList;
+ }
+
+ /**
+ * Returns true if the finder should try to find the track produced by this MCParticle.
+ * Default implementation accepts all charged particles with generator status other than
+ * DOCUMENTATION or INTERMEDIATE. Method can be overwritten by subclasses to use different
+ * selection criteria.
+ */
+ protected boolean filter(MCParticle mcParticle) {
+ return mcParticle.getGeneratorStatus() != Particle.DOCUMENTATION &&
+ mcParticle.getGeneratorStatus() != Particle.INTERMEDIATE &&
+ Math.abs(mcParticle.getCharge()) > .7;
+ }
+
+
+ /**
+ * Returns true the track should be saved in the output list.
+ * Default implementation uses cut on number of layers with hits.
+ * Method can be overwritten by subclasses to use different selection criteria.
+ */
+ protected boolean filter(MCTrack track) {
+
+ if (_minLayers > 0 && track.getNLayers() < _minLayers) return false;
+ if (_minVxdLayers > 0 && track.getNVxdLayers() < _minVxdLayers) return false;
+
+ if (track.getSimTrackerHits().size() < _minSimHits) return false;
+ if (track.getTrackerHits().size() < _minHits) return false;
+
+ return true;
+ }
+
+// -- Static convenience methods : --------------------------------------------
+
+ /**
+ * Returns a mapping between <tt>MCParticle</tt> and found <tt>MCTrack</tt> objects.<br>
+ * An empty map is returned if <tt>MCTrackFinder</tt> has not been run for this event.
+ */
+ static public HashMap<MCParticle, MCTrack> getMCParticleToMCTrackMap(EventHeader event) {
+ List<List<MCTrack>> trackLists = event.get(MCTrack.class);
+ HashMap<MCParticle, MCTrack> map = new HashMap<MCParticle, MCTrack>();
+ for (List<MCTrack> trackList : trackLists) {
+ for (MCTrack track : trackList) {
+ map.put(track.getMCParticle(), track);
+ }
+ }
+ return map;
+ }
+
+ /**
+ * Returns a mapping between <tt>MCParticle</tt> and a list of <tt>SimTrackerHit</tt>s produced by it.<br>
+ * Warning: this is a time-expensive operation.
+ */
+ static public HashMap<MCParticle, List<SimTrackerHit>> getMCParticleToSimTrackerHitMap(EventHeader event) {
+ List<List<SimTrackerHit>> hitLists = event.get(SimTrackerHit.class);
+ List<MCParticle> mcList = event.getMCParticles();
+ HashMap<MCParticle, List<SimTrackerHit>> map
+ = new HashMap<MCParticle, List<SimTrackerHit>>(Math.round(mcList.size()*1.5f));
+ for (MCParticle mc : mcList) map.put(mc, new ArrayList<SimTrackerHit>(100));
+ for (List<SimTrackerHit> hitList : hitLists) {
+ for (SimTrackerHit hit : hitList) {
+ map.get(hit.getMCParticle()).add(hit);
+ }
+ }
+ for (List<SimTrackerHit> hitList : map.values()) {
+ ((ArrayList<SimTrackerHit>)hitList).trimToSize();
+ }
+ return map;
+ }
+
+// -- Private parts : ---------------------------------------------------------
+
+ protected ArrayList<String> _trackerHitListNames = new ArrayList<String>(1);
+ protected String _trackListName = "MCTracks";
+
+ protected int _minLayers = 0;
+ protected int _minVxdLayers = 0;
+ protected int _minSimHits = 1;
+ protected int _minHits = 0;
+
+}
lcsim/src/org/lcsim/contrib/onoprien/mcTrackFinder
diff -N package.html
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ package.html 6 Apr 2007 21:40:27 -0000 1.1
@@ -0,0 +1,11 @@
+<html>
+<body>
+"Cheater" track finder that uses Monte Carlo truth information to find tracks.
+The track finder is configurable so that it can, for example, simulate
+performance of a VXD-based algorithm (by requiring hits in at least 3 VXD
+layers).
+<p>
+{@link MCTrackFinder} class also provides a number of utility methods for
+mapping <tt>MCParticle</tt>s to simulated hits and found tracks.
+</body>
+</html>
lcsim/src/org/lcsim/contrib/onoprien/tester
diff -N ExampleDriverTrackingTest.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ExampleDriverTrackingTest.java 6 Apr 2007 21:40:27 -0000 1.1
@@ -0,0 +1,51 @@
+package org.lcsim.contrib.onoprien.tester;
+
+import java.util.*;
+import org.lcsim.recon.cat.EmcalMipStubs;
+import org.lcsim.recon.cat.GarfieldHitConverter;
+import org.lcsim.recon.cat.GarfieldTrackFinder;
+import org.lcsim.recon.cat.util.Const;
+import org.lcsim.event.*;
+import org.lcsim.recon.cluster.nn.NearestNeighborClusterDriver;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+import org.lcsim.contrib.onoprien.mcTrackFinder.*;
+
+/**
+ * An example driver that runs calorimeter-assisted track finder, and uses
+ * tester package to analyse its performance.
+ *
+ * @author D. Onoprienko
+ * @version $Id: ExampleDriverTrackingTest.java,v 1.1 2007/04/06 21:40:27 onoprien Exp $
+ */
+public class ExampleDriverTrackingTest extends Driver {
+
+ private AIDA aida = AIDA.defaultInstance();
+
+ public ExampleDriverTrackingTest() {
+
+ GarfieldHitConverter hitDigitizer = new GarfieldHitConverter();
+ hitDigitizer.set("OUTPUT_COLLECTION_NAME", "GarfieldHits");
+ add(hitDigitizer);
+
+ add(new NearestNeighborClusterDriver(2, 2, 1, 2, 0.));
+
+ add(new EmcalMipStubs("GarfieldMipStubs",0));
+ add(new GarfieldTrackFinder(0));
+
+ MCTrackFinder mcFinder = new MCTrackFinder();
+ mcFinder.addTrackerHitList("GarfieldHits");
+ mcFinder.set("Track_Collection_Name", "CheaterTracks");
+ mcFinder.set("Min_Layers", 3);
+ add(mcFinder);
+
+ TrackingTest test = new TrackingTest("General Track Finding Test");
+ test.set("RECONSTRUCTED_TRACK_COLLECTION_NAME", "GarfieldTracks");
+ test.set("MC_TRACK_COLLECTION_NAME", "CheaterTracks");
+ test.set("MCTrackCut_Pt", 1.0*Const.GeV);
+ test.set("MCTrackCut_Theta", 45.*Const.degree);
+ test.set("MCTrackCut_nLayers", 3);
+ add(test);
+ }
+
+}
\ No newline at end of file
lcsim/src/org/lcsim/contrib/onoprien/tester
diff -N PiFinder.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ PiFinder.java 6 Apr 2007 21:40:28 -0000 1.1
@@ -0,0 +1,27 @@
+package org.lcsim.contrib.onoprien.tester;
+
+import org.lcsim.event.*;
+import org.lcsim.contrib.onoprien.mcTrackFinder.MCTrackFinder;
+import org.lcsim.contrib.onoprien.mcTrackFinder.MCTrack;
+import org.lcsim.recon.cat.util.Const;
+
+/**
+ * Cheater track finder that finds only tracks left by charged pions from K short decays.
+ *
+ * @author onoprien
+ * @version $Id: PiFinder.java,v 1.1 2007/04/06 21:40:28 onoprien Exp $
+ */
+public class PiFinder extends MCTrackFinder {
+
+ public PiFinder() {}
+
+ /**
+ * Overrides {@link MCTrackFinder.filter(MCParticle)} to select charged pions from KS0 decays.
+ */
+ protected boolean filter(MCParticle mcParticle) {
+ return super.filter(mcParticle) &&
+ (mcParticle.getPDGID() == Const.Particle.PI_MINUS.PDGID || mcParticle.getPDGID() == Const.Particle.PI_PLUS.PDGID ) &&
+ (mcParticle.getParents().get(0).getPDGID() == Const.Particle.K_SHORT.PDGID);
+ }
+
+}
lcsim/src/org/lcsim/contrib/onoprien/tester
diff -N PiTest.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ PiTest.java 6 Apr 2007 21:40:28 -0000 1.1
@@ -0,0 +1,50 @@
+package org.lcsim.contrib.onoprien.tester;
+
+
+import java.util.*;
+import org.lcsim.recon.cat.EmcalMipStubs;
+import org.lcsim.recon.cat.GarfieldHitConverter;
+import org.lcsim.recon.cat.GarfieldTrackFinder;
+import org.lcsim.event.*;
+import org.lcsim.recon.cluster.nn.NearestNeighborClusterDriver;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+import org.lcsim.contrib.onoprien.mcTrackFinder.*;
+
+/**
+ * Track finding efficiency test for charged pions from K short decays.
+ *
+ * @author D. Onoprienko
+ * @version $Id: PiTest.java,v 1.1 2007/04/06 21:40:28 onoprien Exp $
+ */
+public class PiTest extends TrackingTest {
+
+// -- Constructor : -----------------------------------------------------------
+
+ public PiTest() {
+
+ super("KS0 Pions Track Finding Test");
+
+ GarfieldHitConverter hitDigitizer = new GarfieldHitConverter();
+ hitDigitizer.set("OUTPUT_COLLECTION_NAME", "GarfieldHits");
+ add(hitDigitizer);
+
+ add(new NearestNeighborClusterDriver(2, 2, 1, 2, 0.));
+
+ add(new EmcalMipStubs("GarfieldMipStubs",0));
+ add(new GarfieldTrackFinder(0));
+
+ MCTrackFinder mcFinder = new PiFinder();
+ mcFinder.addTrackerHitList("GarfieldHits");
+ mcFinder.set("Track_Collection_Name", "PiTracks");
+ mcFinder.set("Min_Layers", 0);
+ add(mcFinder);
+
+ set("RECONSTRUCTED_TRACK_COLLECTION_NAME", "GarfieldTracks");
+ set("MC_TRACK_COLLECTION_NAME", "PiTracks");
+ //set("MCTrackCut_Pt", 1.0*Const.GeV);
+ //set("MCTrackCut_Theta", 45.*Const.degree);
+ set("MCTrackCut_nLayers", 3);
+ }
+
+}
lcsim/src/org/lcsim/contrib/onoprien/tester
diff -N RatedTrack.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ RatedTrack.java 6 Apr 2007 21:40:28 -0000 1.1
@@ -0,0 +1,67 @@
+package org.lcsim.contrib.onoprien.tester;
+
+import hep.physics.matrix.SymmetricMatrix;
+import java.util.*;
+import org.lcsim.event.*;
+import org.lcsim.contrib.onoprien.mcTrackFinder.MCTrack;
+
+/**
+ * The class keeps references to a reconstructed track, associated
+ * Monte Carlo tracks, and allows assignment and retrieval of any number
+ * of integer status flags.
+ *
+ * @author D. Onoprienko
+ * @version $Id: RatedTrack.java,v 1.1 2007/04/06 21:40:28 onoprien Exp $
+ */
+public class RatedTrack {
+
+// -- Constructors : ----------------------------------------------------------
+
+ /** Create RatedTrack by wrapping a reconstructed track. */
+ public RatedTrack(Track track) {
+ _track = track;
+ _mcTrackList = new ArrayList<MCTrack>(1);
+ _status = new HashMap<Integer,Integer>(2);
+ }
+
+// -- Getters : ---------------------------------------------------------------
+
+ /** Returns underlying reconstructed Track object. */
+ public Track getTrack() {return _track;}
+
+ /** Returns a list of associated Monte Carlo tracks. */
+ public List<MCTrack> getMCTracks() {return _mcTrackList;}
+
+ /**
+ * Returns a status flag that has been previously assigned to this track through
+ * the call to {@link #setStatus(int,int) setStatus(int category, int status)}.
+ */
+ public int getStatus(int category) {return _status.get(category);}
+
+// -- Setters : ---------------------------------------------------------------
+
+ /**
+ * Add an <tt>MCTrack</tt> to the list of Monte Carlo
+ * tracks associated with this <tt>RatedTrack</tt>.
+ */
+ public void addMCTrack(MCTrack mcTrack) {_mcTrackList.add(mcTrack);}
+
+ /**
+ * Set an integer status flag for this track.
+ *
+ * @param category Identifier of a status category. A track can be assigned
+ * statuses in any number of categories.
+ * @param status Status flag that can be later retrieved through the call to
+ * {@link #getStatus(int) getStatus(int category)}
+ */
+ public void setStatus(int category, int status) {_status.put(category, status);}
+
+
+// -- Private data : ----------------------------------------------------------
+
+ private Track _track;
+ private ArrayList<MCTrack> _mcTrackList;
+
+ HashMap<Integer,Integer> _status;
+
+}
lcsim/src/org/lcsim/contrib/onoprien/tester
diff -N TrackingTest.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ TrackingTest.java 6 Apr 2007 21:40:28 -0000 1.1
@@ -0,0 +1,121 @@
+package org.lcsim.contrib.onoprien.tester;
+
+import java.util.*;
+import java.lang.reflect.*;
+import org.lcsim.event.*;
+import org.lcsim.contrib.onoprien.mcTrackFinder.*;
+import org.lcsim.util.Driver;
+import hep.physics.particle.Particle;
+import org.lcsim.util.aida.AIDA;
+import hep.aida.ITree;
+
+/**
+ * A general track finding performance test.
+ * See {@link ExampleDriverTrackingTest} for an example of use.
+ *
+ * @author D. Onoprienko
+ * @version $Id: TrackingTest.java,v 1.1 2007/04/06 21:40:28 onoprien Exp $
+ */
+public class TrackingTest extends TrackingTestBase {
+
+// -- Indices into the statistics (per event and cumulative) arrays : ---------
+
+ protected final int _I_nTotal;
+ protected final int _I_eTotal;
+ protected final int _I_ptTotal;
+ protected final int _I_nGood;
+ protected final int _I_eGood;
+ protected final int _I_ptGood;
+ protected final int _I_nGoodFound;
+ protected final int _I_eGoodFound;
+ protected final int _I_ptGoodFound;
+ protected final int _I_nFound;
+ protected final int _I_nFake;
+
+// -- Constructors : ----------------------------------------------------------
+
+ /** Default constructor. */
+ public TrackingTest() {
+ super("TrackingTest");
+ _I_nTotal = createIndex("Number of MCTracks tracks");
+ _I_eTotal = createIndex("Total energy of MCTracks tracks");
+ _I_ptTotal = createIndex("Total Pt of MCTracks tracks");
+ _I_nGood = createIndex("Number of reconstructable MCTracks");
+ _I_eGood = createIndex("Total energy of reconstructable MCTracks", IndexType.NOPRINT);
+ _I_ptGood = createIndex("Total Pt of reconstructable tracks", IndexType.NOPRINT);
+ _I_nGoodFound = createIndex("Number of found reconstructable tracks");
+ _I_eGoodFound = createIndex("Total energy of found reconstructable tracks", IndexType.NOPRINT);
+ _I_ptGoodFound = createIndex("Total Pt of found reconstructable tracks", IndexType.NOPRINT);
+ _I_nFound = createIndex("Number of found tracks", IndexType.NOPRINT);
+ _I_nFake = createIndex("Number of fake tracks", IndexType.PRINTEVENT);
+ }
+
+ /** Constructor taking the name of the test. */
+ public TrackingTest(String name) {
+ this();
+ set("TEST_NAME", name);
+ }
+
+// -- Processing event : ------------------------------------------------------
+
+ protected void analyzeEvent(EventHeader event) {
+
+ // Number, energy, and Pt of all tracks, reconstructable tracks, and found reconstructable tracks
+
+ for (MCTrack mcTrack : _mcTrackList) {
+ _statE[_I_nTotal] += 1.;
+ _statE[_I_eTotal] += mcTrack.getMCParticle().getEnergy();
+ _statE[_I_ptTotal] += mcTrack.getPt();
+ if (mcTrack.getStatus(IN_CLASS) == YES) {
+ _statE[_I_nGood] += 1.;
+ _statE[_I_eGood] += mcTrack.getMCParticle().getEnergy();
+ _statE[_I_ptGood] += mcTrack.getPt();
+ if (isReconstructed(mcTrack)) {
+ _statE[_I_nGoodFound] += 1.;
+ _statE[_I_eGoodFound] += mcTrack.getMCParticle().getEnergy();
+ _statE[_I_ptGoodFound] += mcTrack.getPt();
+ }
+ }
+ }
+
+ // Number of reconstracted tracks and fakes
+
+ _statE[_I_nFound] = _ratedTrackList.size();
+ for (RatedTrack rTrack : _ratedTrackList) {
+ if (isFake(rTrack)) _statE[_I_nFake] += 1.;
+ }
+
+ // Fill histograms for reconstructed tracks in class :
+
+// for (RatedTrack rTrack : _ratedTrackList) {
+// MCTrack mcTrack = rTrack.getMCTrack();
+// if (mcTrack != null && mcTrack.getStatus(IN_CLASS) == YES) {
+// double p = mcTrack.getP();
+// double dp = rTrack.getP()-p;
+// _aida.cloud1D(_testName + " deltaP over P").fill(dp/p);
+// }
+// }
+
+ }
+
+ protected void endOfRun() {
+
+ System.out.println("");
+ System.out.println(" End-of-run statictics from " + _testName);
+ System.out.println("");
+
+ System.out.println("Reconstructable to all tracks ratios:");
+ System.out.println(" Tracks: " + _statC[_I_nGood]/_statC[_I_nTotal]);
+ System.out.println(" Energy: " + _statC[_I_eGood]/_statC[_I_eTotal]);
+ System.out.println(" Pt: " + _statC[_I_ptGood]/_statC[_I_ptTotal]);
+
+ System.out.println("Track finding efficiency (Found/Reconstructable):");
+ System.out.println(" Tracks: " + _statC[_I_nGoodFound]/_statC[_I_nGood]);
+ System.out.println(" Energy: " + _statC[_I_eGoodFound]/_statC[_I_eGood]);
+ System.out.println(" Pt: " + _statC[_I_ptGoodFound]/_statC[_I_ptGood]);
+
+ System.out.println("Purity: " + (1.-_statC[_I_nFake]/_statC[_I_nFound]));
+ }
+
+// -- Private fields : --------------------------------------------------------
+}
lcsim/src/org/lcsim/contrib/onoprien/tester
diff -N TrackingTestBase.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ TrackingTestBase.java 6 Apr 2007 21:40:28 -0000 1.1
@@ -0,0 +1,509 @@
+package org.lcsim.contrib.onoprien.tester;
+
+import java.util.*;
+import java.lang.reflect.*;
+import javax.swing.*;
+import java.io.*;
+import org.lcsim.recon.cat.util.NoSuchParameterException;
+import org.lcsim.event.*;
+import org.lcsim.contrib.onoprien.mcTrackFinder.*;
+import org.lcsim.util.Driver;
+import org.lcsim.geometry.Detector;
+import hep.physics.particle.Particle;
+import org.lcsim.util.aida.AIDA;
+import hep.aida.ITree;
+
+
+/**
+ * Abstract driver class that provides infrastructure and utility methods for testing track finders.
+ * See {@link TrackingTest} and {@link TrackingTestKs} for examples of use.
+ * <p>
+ * Classes implementing particular tests should extend this class, overriding<br>
+ * {@link #analyzeEvent(EventHeader)}<br>
+ * and, if necessary,<br>
+ * {@link #eventFilter(EventHeader event)},<br>
+ * {@link #matchTracks(Track track, MCTrack mcTrack)},<br>
+ * {@link #mcTrackFilter(MCTrack mcTrack)},<br>
+ * {@link #isReconstructed(MCTrack mcTrack)},<br>
+ * {@link #isFake(RatedTrack track)},<br>
+ * {@link #startOfRun()}, and {@link #endOfRun()} methods.<br>
+ * Default implementations are provided for these methods.
+ * <p>
+ * Subclusses extending this driver should be added to the event processing chain
+ * after track findind stage. Cheater track finder
+ * (see {@link org.lcsim.contrib.onoprien.mcTrackFinder}) should also be run before the test
+ * to create a list of MCTracks and put it into the event.
+ * <p>
+ * When the driver's {@link #process(EventHeader event)}
+ * method is called by the framework, it fetches a list of Monte Carlo tracks,
+ * marks those for which {@link #mcTrackFilter(MCTrack mcTrack)} returns
+ * <tt>true</tt> as being in the requested class (subsequent calls to
+ * {@link MCTrack#getStatus(int) mcTrack.getStatus(TrackingTestBase.IN_CLASS)}
+ * will return <tt>TrackingTestBase.YES</tt>),
+ * associates MCTracks and reconstructed tracks for which
+ * {@link #matchTracks(Track track, MCTrack mcTrack)} returns <tt>true</tt> with
+ * each other, and then calls
+ * {@link #analyzeEvent(EventHeader)} method that should be implemented by subclasses.
+ * <p>
+ * Only events for which {@link #eventFilter(EventHeader)} returns <tt>true</tt> are processed.
+ * <p>
+ * There is an optional facility for accumulating and printing statistics.
+ * Any number of variables for accumulating statistics can be created with
+ * {@link #createIndex(String name, IndexType... args)}. Data put into
+ * these variables is automatically accumulated at the end of event processing,
+ * and can be printed out with {@link #printStatistics(EventHeader event)} and
+ * {@link #printCumulativeStatistics()}.
+ *
+ * @author D. Onoprienko
+ * @version $Id: TrackingTestBase.java,v 1.1 2007/04/06 21:40:28 onoprien Exp $
+ */
+abstract public class TrackingTestBase extends Driver {
+
+// -- Constants defining status categories and values: ------------------------
+
+ public static final int IN_CLASS = -1;
+ public static final int FAKE = -2;
+
+ public static final int YES = -1;
+ public static final int NO = -2;
+
+// -- Constructors : ----------------------------------------------------------
+
+ /** Default constructor. */
+ public TrackingTestBase() {
+ _testName = "";
+ _aida = AIDA.defaultInstance();
+ _tree = _aida.tree();
+ _mcTrackListName = "";
+ _recoTrackListName = "";
+ _runInProgress = false;
+ }
+
+ /** Constructor taking the name of the test. */
+ public TrackingTestBase(String name) {
+ this();
+ set("TEST_NAME", name);
+ }
+
+ // -- Setters : -------------------------------------------------------------
+
+ /**
+ * Set any <tt>String</tt> parameter.
+ * The following parameters can be set with this method:<br>
+ * <tt>"TEST_NAME"</tt> - name of the test. The name will printed with the test output statistics.<br>
+ * <tt>"RECONSTRUCTED_TRACK_COLLECTION_NAME"</tt> - name of reconstructed track
+ * collection produced by the track finder being tested.<br>
+ * <tt>"MC_TRACK_COLLECTION_NAME"</tt> - name of MCTrack collection created by previously run MCTrackFinder.
+ * @param name Name of parameter to be set. Case ignored.
+ * @param value Value to be assigned to the parameter.
+ * @throws NoSuchParameterException Thrown if the supplied parameter name is unknown.
+ * Subclasses may catch this exception after a call to <tt>super.set()</tt>
+ * and set their own parameters.
+ */
+ public void set(String name, String value) {
+ if (name.equalsIgnoreCase("TEST_NAME")) {
+ _testName = value;
+ } else if (name.equalsIgnoreCase("RECONSTRUCTED_TRACK_COLLECTION_NAME")) {
+ _recoTrackListName = value;
+ } else if (name.equalsIgnoreCase("MC_TRACK_COLLECTION_NAME")) {
+ _mcTrackListName = value;
+ } else {
+ throw new NoSuchParameterException(name, this.getClass());
+ }
+ }
+
+ /**
+ * Set any double parameter.
+ * The following parameters can be set with this method:<br>
+ * <tt>"MCTrackCut_Pt"</tt> - cut on Pt for MCTrack to be considered reconstructable. Default: 0.<br>
+ * <tt>"MCTrackCut_Theta"</tt> - cut on Theta for MCTrack to be considered reconstructable. Default: 0.<br>
+ * <tt>"MCTrackCut_Rapidity"</tt> - cut on pseudo-rapidity for MCTrack to be considered reconstructable. Default: infinity.<br>
+ * @param name Name of parameter to be set. Case ignored.
+ * @param value Value to be assigned to the parameter.
+ * @throws NoSuchParameterException Thrown if the supplied parameter name is unknown.
+ * Subclasses may catch this exception after a call to <tt>super.set()</tt>
+ * and set their own parameters.
+ */
+ public void set(String name, double value) {
+ if (name.equalsIgnoreCase("MCTrackCut_Pt")) {
+ _mcTrackCut_Pt = value;
+ } else if (name.equalsIgnoreCase("MCTrackCut_Theta")) {
+ _mcTrackCut_theta = value;
+ } else if (name.equalsIgnoreCase("MCTrackCut_Rapidity")) {
+ if (value < 10000.) {
+ _mcTrackCut_theta = 2.*Math.atan(Math.exp(-value));
+ } else {
+ _mcTrackCut_theta = 0.;
+ }
+ } else {
+ throw new NoSuchParameterException(name, this.getClass());
+ }
+ }
+
+ /**
+ * Set any integer parameter.
+ * The following parameters can be set with this method:<br>
+ * <tt>"MCTrackCut_nLayers"</tt> - cut on minimum number of layers with hits
+ * for MCTrack to be considered reconstructable. Default: 3.<br>
+ * @param name Name of parameter to be set. Case ignored.
+ * @param value Value to be assigned to the parameter.
+ * @throws NoSuchParameterException Thrown if the supplied parameter name is unknown.
+ * Subclasses may catch this exception after a call to <tt>super.set()</tt>
+ * and set their own parameters.
+ */
+ public void set(String name, int value) {
+ if (name.equalsIgnoreCase("MCTrackCut_nLayers")) {
+ _mcTrackCut_nLayers = value;
+ } else {
+ throw new NoSuchParameterException(name, this.getClass());
+ }
+ }
+
+// -- Processing event : ------------------------------------------------------
+
+ /** Process event. */
+ public final void process(EventHeader event) {
+
+ super.process(event);
+
+ // Skip undesired events
+
+ if (!eventFilter(event)) return;
+
+ // Reset "per event" statistics
+
+ if (_statE != null) Arrays.fill(_statE, 0.);
+
+ // Fetch list of Monte Carlo Tracks, and set IN_CLASS flag for them
+
+ _mcTrackList = event.get(MCTrack.class, _mcTrackListName);
+ for (MCTrack mcTrack : _mcTrackList) {
+ mcTrack.setStatus(IN_CLASS, mcTrackFilter(mcTrack) ? YES : NO);
+ }
+
+ // Associate reconstructed tracks with Monte Carlo Tracks
+
+ _recoTrackList = event.get(Track.class, _recoTrackListName);
+ _ratedTrackList = new ArrayList<RatedTrack>(_recoTrackList.size());
+
+ for (Track track : _recoTrackList) {
+ RatedTrack ratedTrack = new RatedTrack(track);
+ for (MCTrack mcTrack : _mcTrackList) {
+ if (matchTracks(track, mcTrack)) {
+ ratedTrack.addMCTrack(mcTrack);
+ mcTrack.addTrack(track);
+ }
+ }
+ _ratedTrackList.add(ratedTrack);
+ }
+
+ // User's analysis
+
+ analyzeEvent(event);
+
+ // Update cumulative statistics
+
+ if (_statE != null) {
+ for (int i=0; i<_statE.length; i++) _statC[i] += _statE[i];
+ }
+ _nEvents++;
+
+ // Clean up
+
+ for (MCTrack mcTrack : _mcTrackList) {
+ mcTrack.removeTracks();
+ }
+ _mcTrackList = null;
+ _recoTrackList = null;
+ _ratedTrackList = null;
+
+ }
+
+// -- Selector methods to be overridden by subclasses : -----------------------
+
+ /**
+ * Returns <code>true</code> for events that should be included in analysis.
+ * Default implementation always returns <code>true</code>.
+ * Subclasses should overwrite this method if some events need to be excluded.
+ */
+ protected boolean eventFilter(EventHeader event) {
+ return true;
+ }
+
+ /**
+ * Returns <tt>true</tt> if Monte Carlo track belongs to the class that needs to be included in analysis.
+ * Cuts on Pt, Theta, and a minimum number of layers with hits.
+ * Cut values can be set at run time, leaving them at default values means no cuts.
+ * Subclasses can overwrite this method to provide their own definition of "reconstructable" track.
+ */
+ protected boolean mcTrackFilter(MCTrack mcTrack) {
+ if (mcTrack.getPt() < _mcTrackCut_Pt) return false;
+ if (mcTrack.getTheta() < _mcTrackCut_theta) return false;
+ if (mcTrack.getNLayers() < _mcTrackCut_nLayers) return false;
+ return true;
+ }
+
+ /**
+ * Returns <code>true</code> if reconstructed track and Monte Carlo track are deemed to describe the same track.
+ * Default implementation: tracks match if they have common hits in at least 3 layers.
+ * (Alternative definition to be considered later: Tracks match if MCParticle
+ * contributed to hits of reconstructed track in at least 3 layers).
+ * <i>Current implementation simply asks for 3 common hits since
+ * {@link TrackerHit} is completely "detector blind" at the moment.</i>
+ * Subclasses can overwrite this method to provide their own definition of matching tracks.
+ */
+ protected boolean matchTracks(Track track, MCTrack mcTrack) {
+ List<TrackerHit> recoTrackHitList = track.getTrackerHits();
+ List<TrackerHit> mcTrackHitList = mcTrack.getTrackerHits();
+ int nMatch = 0;
+ for (TrackerHit hit : mcTrackHitList) {
+ if (recoTrackHitList.contains(hit)) nMatch++;
+ }
+ return nMatch > 2;
+ }
+
+ /**
+ * Definition of a successfully reconstracted MCTrack.
+ * This method is not called internally by any <tt>TrackingTestBase</tt> methods,
+ * but can be used (or overridded) by subclasses.
+ * What I would like to do here is to require that there is a reconstructed
+ * track that picked up hits from this MCTrack in at least 3 layers.
+ * Given current limitations of {@link TrackerHit} that has no layer information,
+ * the default implementation returns <tt>true</tt> if any reconstructed
+ * tracks have been associated with MCTrack supplied as a parameter. If default
+ * implementation of {@link matchTracks(Track, MCTrack)} is used, that means
+ * requiring a reconstructed track with 3 hits common with the given MCTrack.
+ */
+ protected boolean isReconstructed(MCTrack mcTrack) {
+ return mcTrack.getTracks().size() > 0;
+ }
+
+ /**
+ * Definition of fake track.
+ * This method is not called internally by any <tt>TrackingTestBase</tt> methods,
+ * but can be used (or overridded) by subclasses.
+ * In the future, I'd like to consider the track fake if there is no MCParticle
+ * that contributed to its hits in all but one layer.
+ * Given current limitations of {@link TrackerHit}, the actual definition is:
+ * the track is fake if there is no MCTrack that contains all but one of its hits.
+ */
+ protected boolean isFake(RatedTrack track) {
+ List<MCTrack> mcTrackList = track.getMCTracks();
+ if (mcTrackList.size() == 0) return true;
+ List<TrackerHit> recoHitList = track.getTrack().getTrackerHits();
+ for (MCTrack mcTrack : mcTrackList) {
+ int nSomeoneElsesHits = 0;
+ for (TrackerHit hit : recoHitList) {
+ if (!mcTrack.getTrackerHits().contains(hit)) nSomeoneElsesHits++;
+ }
+ if (nSomeoneElsesHits <= 1) return false;
+ }
+ return true;
+ }
+
+// -- User analysis hooks : ---------------------------------------------------
+
+ /** User analysis before the run. */
+ protected void startOfRun(Detector detector) {}
+
+ /** User analysis of the event. */
+ abstract protected void analyzeEvent(EventHeader event);
+
+ /** User analysis before the run. */
+ protected void endOfRun() {}
+
+ /**
+ * Called when all data processing is finished.
+ * Unless overwritten in the subclass, prints out standard cumulative statistics.
+ */
+ final protected void endOfData() {
+ super.endOfData();
+ endOfRun();
+ _runInProgress = false;
+ }
+
+ /**
+ * Called before the first event is processed, or after a rewind.
+ * Unless overwritten in the subclass, resets standard cumulative statistics.
+ */
+ final public void detectorChanged(Detector detector) {
+ super.detectorChanged(detector);
+ if (_runInProgress) {
+ endOfRun();
+ }
+ _nEvents = 0;
+ if (_statE != null) Arrays.fill(_statC, 0.);
+ _runInProgress = true;
+ startOfRun(detector);
+ }
+
+// -- Protected helper methods: -----------------------------------------------
+
+ /**
+ * Print to the log.
+ * The output destination can be set with <tt>set("LOG_FILE", destination)</tt>.
+ * See {@link #set(String, String)} for details.
+ */
+ protected void printLog(String title, String... messages) {
+ if (title != null) {
+ System.out.println("");
+ System.out.println(title);
+ System.out.println("");
+ }
+ for (String line : messages) {
+ System.out.println(line);
+ }
+ }
+
+ protected enum IndexType {NOSUM, SUM, SUM2, NOPRINT, PRINTEVENT, PRINTSUM, PRINTALL}
+
+ /**
+ * Creates a new statistical variable and returns an index that can be used to access it.
+ * "Per event" data can be put into <code>_statE[index]</code>, these variables are reset
+ * to zero at the beginning of each event. At the end of the event, statistics is
+ * automatically accumulated into <code>_statC[index]</code>. The name of the variable
+ * is accessable through <code>_statName[index]</code>.
+ *
+ * @param name Name to be assigned to the variable.
+ * @param args Optional flags defining accumulation type and printing preferences. Possible flags and their meanings:<p>
+ * NOSUM - do not accumulate this variable.<br>
+ * SUM - <code>_statE[index]</code> added to <code>_statC[index]</code> at the end of event.<br>
+ * SUM2 - square of <code>_statE[index]</code> added to <code>_statC[index]</code> at the end of event.<br>
+ * If no flag is given, SUM is assumed.<p>
+ * NOPRINT - variable is not printed by {@link #printStatistics(EventHeader event)} and {@link #printCumulativeStatistics()}<br>
+ * PRINTEVENT - variable is printed by {@link #printStatistics(EventHeader event)} but not by {@link #printCumulativeStatistics()}<br>
+ * PRINTSUM - variable is printed by {@link #printCumulativeStatistics()} but not by {@link #printStatistics(EventHeader event)}<br>
+ * PRINTALL - variable is printed by both {@link #printCumulativeStatistics()} and {@link #printStatistics(EventHeader event)}<br>
+ * If no flag is given, PRINTALL is assumed.<p>
+ * @return Index into {@link #_statE}, {@link #_statC}, and {@link #_statName} arrays that can be used to access the variable being created.
+ */
+ protected int createIndex(String name, IndexType... args) {
+
+ int size;
+ if (_statE == null) {
+ _statE = new double[] {0.};
+ _statC = new double[] {0.};
+ _statName = new String[] {name};
+ _statAccumulateFlag = new IndexType[] {IndexType.SUM};
+ _statPrintFlag = new IndexType[] {IndexType.PRINTALL};
+ size = 0;
+ } else {
+
+ size = _statE.length;
+
+ double[] tempD = new double[size+1];
+ System.arraycopy(_statE, 0, tempD, 0, size);
+ _statE = tempD;
+ _statE[size] = 0.;
+
+ tempD = new double[size+1];
+ System.arraycopy(_statC, 0, tempD, 0, size);
+ _statC = tempD;
+ _statC[size] = 0.;
+
+ String[] tempS = new String[size+1];
+ System.arraycopy(_statName, 0, tempS, 0, size);
+ _statName = tempS;
+ _statName[size] = name;
+
+ IndexType[] tempI = new IndexType[size+1];
+ System.arraycopy(_statAccumulateFlag, 0, tempI, 0, size);
+ _statAccumulateFlag = tempI;
+ _statAccumulateFlag[size] = IndexType.SUM;
+
+ tempI = new IndexType[size+1];
+ System.arraycopy(_statPrintFlag, 0, tempI, 0, size);
+ _statPrintFlag = tempI;
+ _statPrintFlag[size] = IndexType.PRINTSUM;
+ }
+
+ if (args != null) {
+ for (IndexType type : args) {
+ switch (type) {
+ case NOSUM:
+ case SUM:
+ case SUM2:
+ _statAccumulateFlag[size] = type; break;
+ case NOPRINT:
+ case PRINTEVENT:
+ case PRINTSUM:
+ case PRINTALL:
+ _statPrintFlag[size] = type; break;
+ }
+ }
+ }
+
+ return size;
+ }
+
+ /** Print standard statistics at the end of an event to standard output. */
+ protected void printStatistics(EventHeader event) {
+ System.out.println("");
+ System.out.println("Tracking test: " + _testName + ", statistics for event " + event.getEventNumber());
+ for (int i=0; i<_statE.length; i++) {
+ if (_statPrintFlag[i] == IndexType.PRINTEVENT || _statPrintFlag[i] == IndexType.PRINTALL) {
+ System.out.println(" " + _statName[i] + " " + _statE[i]);
+ }
+ }
+ System.out.println("");
+ }
+
+ /**
+ * Print cumulative statistics to the log.
+ * The output destination can be set with <tt>set("LOG_FILE", destination)</tt>.
+ * See {@link #set(String, String)} for details.
+ * @param messages Array of strings that should be printed before standard statistics.
+ * @param printStandard Flag to indicate whether to print standard statistics.
+ */
+ protected void printCumulativeStatistics(boolean printStandard, String... messages) {
+ ArrayList<String> msgList = new ArrayList<String>(20);
+ msgList.add("");
+ if (messages != null) for (String msg : messages) msgList.add(" " + msg);
+ if (printStandard && _nEvents > 0) {
+ for (int i=0; i<_statE.length; i++) {
+ if (_statPrintFlag[i] == IndexType.PRINTSUM || _statPrintFlag[i] == IndexType.PRINTALL) {
+ msgList.add(" Average " + _statName[i] + " " + _statC[i]/_nEvents);
+ }
+ }
+ }
+ msgList.add("");
+ String[] msgArray = new String[msgList.size()];
+ msgArray = msgList.toArray(msgArray);
+ printLog("Tracking test: " + _testName + " cumulative statistics (" + _nEvents + " events)", msgArray);
+ }
+
+ /**
+ * Print standard cumulative statistics.
+ * The output destination can be set with <tt>set("LOG_FILE", destination)</tt>.
+ * See {@link #set(String, String)} for details.
+ */
+ protected void printCumulativeStatistics() {printCumulativeStatistics(true);}
+
+// -- Private fields : --------------------------------------------------------
+
+ protected String _testName = "";
+
+ protected List<MCTrack> _mcTrackList;
+ protected List<Track> _recoTrackList;
+ protected ArrayList<RatedTrack> _ratedTrackList;
+
+ protected String _mcTrackListName;
+ protected String _recoTrackListName;
+
+ protected double _mcTrackCut_Pt = 0.;
+ protected double _mcTrackCut_theta = 0.;
+ protected int _mcTrackCut_nLayers = 0;
+
+ protected int _nEvents; // Number of events analyzed
+ protected double[] _statE; // Array to hold per event statistics
+ protected double[] _statC; // Array to hold cumulative statistics
+ protected String[] _statName; // Array to hold names of statical variables
+ protected IndexType[] _statAccumulateFlag; // Array to hold flags indicating accumulation methods
+ protected IndexType[] _statPrintFlag ; // Array to hold flags indicating accumulation printing options
+
+ protected AIDA _aida;
+ protected ITree _tree;
+
+ private boolean _runInProgress;
+
+}
lcsim/src/org/lcsim/contrib/onoprien/tester
diff -N package.html
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ package.html 6 Apr 2007 21:40:28 -0000 1.1
@@ -0,0 +1,8 @@
+<html>
+<body>
+Performance testing package for track finders.
+<p>
+The package contains a base class ({@link TrackingTestBase}) for writing track finder
+performance tests, and a number of concrete tests.
+</body>
+</html>
CVSspam 0.2.8