lcsim/src/org/lcsim/contrib/garfield/tester
diff -u -r1.2 -r1.3
--- TrackingTest.java 15 Dec 2006 16:54:57 -0000 1.2
+++ TrackingTest.java 23 Jan 2007 03:50:12 -0000 1.3
@@ -17,7 +17,7 @@
* A general example of track finding performance test.
*
* @author D. Onoprienko
- * @version $Id: TrackingTest.java,v 1.2 2006/12/15 16:54:57 onoprien Exp $
+ * @version $Id: TrackingTest.java,v 1.3 2007/01/23 03:50:12 onoprien Exp $
*/
public class TrackingTest extends TrackingTestBase {
@@ -34,12 +34,15 @@
/** Default constructor. */
public TrackingTest() {
+ super("TrackingTest");
_I_nMCTracks = createIndex("Number of reconstructable tracks");
_I_eMCTracks = createIndex("Total momentum of reconstructable tracks", IndexType.NOPRINT);
_I_nMCTracksReconstructed = createIndex("Number of reconstructed reconstructable tracks");
_I_eMCTracksReconstructed = createIndex("Total momentum of reconstructed reconstructable tracks", IndexType.NOPRINT);
_I_nRecoTracks = createIndex("Number of reconstructed tracks", IndexType.NOPRINT);
_I_nRecoTracksFake = createIndex("Number of fake tracks", IndexType.PRINTEVENT);
+
+ _mcTrackCut_nLayers = 3;
}
/** Constructor taking the name of the test. */
@@ -48,55 +51,6 @@
set("TEST_NAME", name);
}
-// -- Setters : ---------------------------------------------------------------
-
- /**
- * 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
- * @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 == "MCTrackCut_nLayers") {
- _mcTrackCut_nLayers = 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
- * @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 == "MCTrackCut_Pt") {
- _mcTrackCut_Pt = value;
- } else if (name == "MCTrackCut_Theta") {
- _mcTrackCut_theta = value;
- } else if (name == "MCTrackCut_Rapidity") {
- if (value < 10000.) {
- _mcTrackCut_theta = 2.*Math.atan(Math.exp(-value));
- } else {
- _mcTrackCut_theta = 0.;
- }
- } else {
- throw new NoSuchParameterException(name, this.getClass());
- }
- }
-
// -- Processing event : ------------------------------------------------------
protected void analyzeEvent(EventHeader event) {
@@ -139,84 +93,15 @@
printStatistics(event);
}
- /**
- * Definition of a successfully reconstracted MCTrack.
- * Require that there is a reconstructed track that picked up hits from this
- * MCTrack in at least 3 layers. Given current limitations of {@link Track},
- * we only check that there is a track with 3 common hits at the moment.
- */
- protected boolean isReconstructed(MCTrack mcTrack) {
- return mcTrack.getTracks().size() > 0;
- }
-
- /**
- * Definition of fake track.
- * What I'd like to have here is that the track is fake if there is no MCParticle
- * that contributed to its hits in all but one layer.
- * Given current limitations of {@link Track}, 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;
- }
-
- protected void suspend() {
+ protected void endOfData() {
if (_statC[_I_nMCTracks] == 0 || _statC[_I_nRecoTracks] == 0) return;
String[] messages = new String[] {
"Reconstruction efficiency: " + _statC[_I_nMCTracksReconstructed]/_statC[_I_nMCTracks],
"Momentum reconstruction efficiency: " + _statC[_I_eMCTracksReconstructed]/_statC[_I_eMCTracks],
"Purity: " + (1.-_statC[_I_nRecoTracksFake]/_statC[_I_nRecoTracks])
};
- printCumulativeStatistics(messages);
- }
-
- protected void endOfData() {suspend();}
-
-// -- Override selector methods from TrackingTestBase : -----------------------
-
- /**
- * Definition of "reconstructable" track.
- * Cuts on Pt, Theta, and a minimum number of layers with hits.
- * Cut values can be set at run time.
- */
- 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;
- }
-
- /**
- * Definition of matching reconstructed and MC tracks.
- * 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).
- * Current implementation simply asks for 3 common hits since
- * {@link TrackerHit} is completely "detector blind" at the moment.
- */
- 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;
+ printCumulativeStatistics(true, messages);
}
// -- Private fields : --------------------------------------------------------
-
- double _mcTrackCut_Pt = 0.;
- double _mcTrackCut_theta = 0.;
- int _mcTrackCut_nLayers = 3;
}
lcsim/src/org/lcsim/contrib/garfield/tester
diff -u -r1.2 -r1.3
--- TrackingTestBase.java 15 Dec 2006 16:54:57 -0000 1.2
+++ TrackingTestBase.java 23 Jan 2007 03:50:12 -0000 1.3
@@ -3,6 +3,7 @@
import java.util.*;
import java.lang.reflect.*;
import javax.swing.*;
+import java.io.*;
import org.lcsim.event.*;
import org.lcsim.contrib.garfield.util.*;
import org.lcsim.contrib.garfield.mcTrackFinder.*;
@@ -15,31 +16,36 @@
/**
- * Abstract class that provides infrastructure and utility methods for testing track finders.
+ * 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
- * {@link #analyzeEvent(EventHeader)} and, if necessary,
- * {@link #eventFilter(EventHeader)},
- * {@link #matchTracks(Track track, MCTrack mcTrack)},
- * {@link #mcTrackFilter(MCTrack mcTrack)},
- * {@link #suspend()}, and {@link #endOfData()} methods.
+ * 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 #suspend()}, {@link #startOfData()}, and {@link #endOfData()} 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. When the driver's {@link #process(EventHeader event)}
- * method is called by the framework, it creates a list of Monte Carlo tracks,
- * associates hits and reconstructed tracks with them, and then calls
- * {@link #analyzeEvent(EventHeader)} method that should be implemented by subclasses.
+ * after track findind stage. Cheater track finder should also be run to create a
+ * list of MCTracks and put it into the event.
* <p>
- * Only events for which {@link #eventFilter(EventHeader)} returns <code>true</code>
- * are processed. Reconstructed track is associated with Monte Carlo track if
- * {@link #matchTracks(Track track, MCTrack mcTrack)} returns <code>true</code>.
- * Monte Carlo tracks for which {@link #mcTrackFilter(MCTrack mcTrack)} returns
- * <code>true</code> are marked as being in the requested class (subsequent calls to
+ * 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 <code>TrackingTestBase.YES</code>. Default implementations are provided
- * for these methods, but subclasses will need to overwrite some or all of them to
- * perform a meaningful test.
+ * 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>
* Any number of variables for accumulating statistics can be created with
* {@link #createIndex(String name, IndexType... args)}. Data put into
@@ -48,7 +54,7 @@
* {@link #printCumulativeStatistics()}.
*
* @author D. Onoprienko
- * @version $Id: TrackingTestBase.java,v 1.2 2006/12/15 16:54:57 onoprien Exp $
+ * @version $Id: TrackingTestBase.java,v 1.3 2007/01/23 03:50:12 onoprien Exp $
*/
abstract public class TrackingTestBase extends Driver {
@@ -61,9 +67,11 @@
public static final int NO = -2;
// -- Constructors : ----------------------------------------------------------
-
+
+ /** Default constructor. */
public TrackingTestBase() {
_testName = "";
+ _logStream = null;
_aida = AIDA.defaultInstance();
_tree = _aida.tree();
_mcTrackListName = "";
@@ -71,12 +79,22 @@
_nEvents = 0;
}
+ /** 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>"LOG_FILE"</tt> - specifies distination where statistics is to be printed. "POPUP" (default) will bring
+ * up a pop-up window; "STDOUT" uses System.out.println() (when running inside JAS3, this
+ * means end-of-run statistics will not be printed at all, due to a bug in the framework;
+ * everything else is treated as a file name.<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.
@@ -89,6 +107,19 @@
public void set(String name, String value) {
if (name == "TEST_NAME") {
_testName = value;
+ } else if (name == "LOG_FILE") {
+ if (_logStream != null) _logStream.close();
+ if (value.equalsIgnoreCase("POPUP")) {
+ _logStream = null;
+ } else if (value.equalsIgnoreCase("STDOUT")) {
+ _logStream = System.out;
+ } else {
+ try {
+ _logStream = new PrintStream(value);
+ } catch (FileNotFoundException e) {
+ System.err.println("Failed to open file: " + value);
+ }
+ }
} else if (name == "RECONSTRUCTED_TRACK_COLLECTION_NAME") {
_recoTrackListName = value;
} else if (name == "MC_TRACK_COLLECTION_NAME") {
@@ -97,6 +128,53 @@
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
+ * @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 == "MCTrackCut_Pt") {
+ _mcTrackCut_Pt = value;
+ } else if (name == "MCTrackCut_Theta") {
+ _mcTrackCut_theta = value;
+ } else if (name == "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
+ * @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 == "MCTrackCut_nLayers") {
+ _mcTrackCut_nLayers = value;
+ } else {
+ throw new NoSuchParameterException(name, this.getClass());
+ }
+ }
// -- Processing event : ------------------------------------------------------
@@ -167,23 +245,74 @@
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 returns <code>true</code> if all hits associated with the reconstructed track are
- * also associated with the MC track. Subclasses should overwrite this method if different algorithm is desired.
+ * 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();
- return mcTrackHitList.containsAll(recoTrackHitList);
+ int nMatch = 0;
+ for (TrackerHit hit : mcTrackHitList) {
+ if (recoTrackHitList.contains(hit)) nMatch++;
+ }
+ return nMatch > 2;
}
- /**
- * Returns <code>true</code> if Monte Carlo track belongs to the class that needs to be included in analysis.
- * Default implementation in <tt>TrackingTestBase</tt> always returns <tt>true</tt>.
- * Subclasses should overwrite this method to provide their own definition of "reconstructable" track.
+ /**
+ * 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 mcTrackFilter(MCTrack 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;
}
@@ -194,15 +323,18 @@
/**
* Called by the framework when the event processing is suspended.
- * Unless overwritten in the subclass, prints out standard cumulative statistics.
+ * Unless overwritten in the subclass, calls {@link #endOfData()}.
*/
- protected void suspend() {printCumulativeStatistics();}
+ protected void suspend() {endOfData();}
/**
* Called when all data processing is finished.
* Unless overwritten in the subclass, prints out standard cumulative statistics.
*/
- protected void endOfData() {printCumulativeStatistics();}
+ protected void endOfData() {
+ printCumulativeStatistics();
+// if (_logStream != null && _logStream != System.out) _logStream.close();
+ }
/**
* Called before the first event is processed, or after a rewind.
@@ -215,6 +347,26 @@
// -- 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 (_logStream != null) {
+ if (title != null) {
+ _logStream.println("");
+ _logStream.println(title);
+ _logStream.println("");
+ }
+ for (String line : messages) {
+ _logStream.println(line);
+ }
+ } else {
+ JOptionPane.showMessageDialog(null, messages, title, JOptionPane.INFORMATION_MESSAGE);
+ }
+ }
+
protected enum IndexType {NOSUM, SUM, SUM2, NOPRINT, PRINTEVENT, PRINTSUM, PRINTALL}
/**
@@ -296,7 +448,7 @@
return size;
}
- /** Print statistics at the end of an event. */
+ /** 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());
@@ -309,11 +461,13 @@
}
/**
- * Print cumulative statistics.
+ * 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(String[] messages, boolean printStandard) {
+ 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);
@@ -325,34 +479,35 @@
}
}
msgList.add("");
- Object[] msgArray = msgList.toArray();
- JOptionPane.showMessageDialog(null, msgArray,
- "Tracking test: " + _testName + " cumulative statistics (" + _nEvents + " events)",
- JOptionPane.INFORMATION_MESSAGE);
+ 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(null, true);}
-
- /**
- * Print cumulative statistics.
- * @param messages Array of strings that should be printed before standard statistics.
- */
- protected void printCumulativeStatistics(String[] messages) {printCumulativeStatistics(messages, true);}
+ protected void printCumulativeStatistics() {printCumulativeStatistics(true);}
// -- Private fields : --------------------------------------------------------
protected String _testName = "";
+ protected PrintStream _logStream;
+
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