Author: [log in to unmask]
Date: Thu Aug 6 17:19:42 2015
New Revision: 3348
Log:
Updated documentation for many ecal-recon drivers. Classes TDCData and HeadBankData require documentation still; I am not familiar enough with their function to provide it.
Modified:
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterDriver.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterer.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterDriver.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterer.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/ConfigurationManager.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/DAQConfigDriver.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/EvioDAQParser.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/AbstractIntData.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/SSPCluster.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/TIData.java
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/TriggerModule.java
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterDriver.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterDriver.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterDriver.java Thu Aug 6 17:19:42 2015
@@ -1,24 +1,36 @@
package org.hps.recon.ecal.cluster;
/**
- * Class <code>GTPClusterDriver</code> instantiates an instance of
- * the clustering algorithm framework for the Monte Carlo version
- * of the GTP algorithm. This version assumes that events are equal
- * to 2 ns beam bunches. The class also allows the seed energy threshold
- * and cluster window to be set as well as whether or not the algorithm
- * should employ an asymmetric time window and write out verbose debug
- * text.
+ * Class <code>GTPClusterDriver</code> is an implementation of the
+ * <code>ClusterDriver</code> class that defines employs the readout
+ * variant of the GTP hardware clustering algorithm. Specifics on the
+ * behavior of this algorithm can be found in its documentation.<br/>
+ * <br/>
+ * <code>GTPClusterDriver</code> allows for all of the variable settings
+ * used by the GTP algorithm to be defined. It also can be set to
+ * "verbose" mode, where it will output detailed information on each
+ * event and the cluster forming process. This is disabled by default,
+ * but can be enabled for debugging purposes.<br/>
+ * <br/>
+ * <code>GTPClusterDriver</code> is designed to read from Monte Carlo
+ * data organized into 2-ns beam bunches. It can not be used for hardware
+ * readout data, or Monte Carlo formatted in this style. For this data,
+ * the <code>GTPOnlineClusterer</code> should be employed instead.
*
* @author Kyle McCarty <[log in to unmask]>
* @author Jeremy McCormick <[log in to unmask]>
* @see GTPClusterer
*/
public class GTPClusterDriver extends ClusterDriver {
- // The GTP clustering algorithm.
+ /** An instance of the clustering algorithm object for producing
+ * cluster objects. */
private final GTPClusterer gtp;
/**
- * Instantiates a new <code>GTPClusterer</code>.
+ * Instantiates a new <code>GTPClusterer</code>, which will produce
+ * clusters using the GTP algorithm in the 2-ns beam bunch scheme.
+ * It will, by default, use a 50 MeV seed energy cut with +/- 2 a
+ * clock-cycle verification and inclusion window.
*/
public GTPClusterDriver() {
clusterer = ClustererFactory.create("GTPClusterer");
@@ -27,66 +39,77 @@
}
/**
- * Sets whether hits should be added to a cluster from the entire
- * cluster window or just the "future" hits, plus one clock-cycle
- * of "past" hits as a safety buffer to account for time uncertainty.
- *
- * @param limitClusterRange - <code>true</code> indicates that
- * the asymmetric clustering window should be used and <code>
- * false</code> that the symmetric window should be used.
+ * Sets whether the behavior of the hit inclusion window with respect
+ * to the hit verification window. If set to <code>false</code>,
+ * both windows will be identical in size. Otherwise, the inclusion
+ * window will be equal in size after the seed hit, but encompass
+ * only one clock-cycle before the seed hit. This should be replaced
+ * by the method <code>setAsymmetricWindow</code>.
+ * @param limitClusterRange - <code>true</code> indicates that the
+ * asymmetric window should be used and <code>false</code> that it
+ * should not.
*/
@Deprecated
public void setLimitClusterRange(boolean limitClusterRange) {
- gtp.setLimitClusterRange(limitClusterRange);
+ gtp.setAsymmetricWindow(limitClusterRange);
}
/**
- * Sets the number of clock-cycles (4 ns) before and after a hit
- * in which the hit must be the maximum energy hit in its 3 x 3
- * window in order to be considered a seed hit and form a cluster.
+ * Sets the size of the hit verification temporal window. Note
+ * that this defines the size of the window in one direction, so
+ * the full time window will be <code>(2 * clusterWindow) + 1</code>
+ * clock-cycles in length. (i.e., it will be a length of
+ * <code>clusterWindow</code> before the seed hit, a length of
+ * <code>clusterWindow</code> after the seed hit, plus the cycle
+ * that includes the seed hit.) Time length is in clock-cycles.
* @param clusterWindow - The number of clock-cycles around the
- * hit in one direction; i.e. a value of 1 indicates that the full
- * window will include the current clock-cycle, plus one cycle both
- * before and after the current cycle. This gives a total number
- * of cycles equal to (2 * clusterWindow) + 1.
+ * hit in one direction.
*/
public void setClusterWindow(int clusterWindow) {
gtp.getCuts().setValue("clusterWindow", clusterWindow);
}
/**
- * Sets the minimum energy needed for a seed hit to form a cluster.
- * @param seedEnergyThreshold - The minimum seed energy in GeV.
+ * Sets the minimum seed energy needed for a hit to be considered
+ * for forming a cluster. This is the seed energy lower bound trigger
+ * cut and is in units of GeV.
+ * @param seedEnergyThreshold - The minimum cluster seed energy in
+ * GeV.
*/
public void setSeedEnergyThreshold(double seedEnergyThreshold) {
gtp.getCuts().setValue("seedEnergyThreshold", seedEnergyThreshold);
}
/**
- * Sets whether the clustering algorithm should use an asymmetric
- * clustering window. The asymmetric window will include hits in
- * a cluster that are present within the full time window ahead of
- * the seed hit, but only one clock-cycle behind it. This is to
- * allow for variation in hit timing with respect to the seed due
- * to jitter in the hardware.
+ * Sets whether the behavior of the hit inclusion window with respect
+ * to the hit verification window. If set to <code>false</code>,
+ * both windows will be identical in size. Otherwise, the inclusion
+ * window will be equal in size after the seed hit, but encompass
+ * only one clock-cycle before the seed hit.
* @param asymmetricWindow - <code>true</code> indicates that the
* asymmetric window should be used and <code>false</code> that it
* should not.
*/
public void setAsymmetricWindow(boolean asymmetricWindow) {
- gtp.setLimitClusterRange(asymmetricWindow);
+ gtp.setAsymmetricWindow(asymmetricWindow);
}
/**
* Sets whether the clustering algorithm should output diagnostic
* text or not.
- * @param verbose <code>true</code> indicates that the driver should
+ * @param verbose - <code>true</code> indicates that the driver should
* output diagnostic text and <code>false</code> that it should not.
*/
public void setVerbose(boolean verbose) {
gtp.setVerbose(verbose);
}
+ /**
+ * Defines whether the output of this clusterer should be persisted
+ * to LCIO or not. By default, this
+ * @param state - <code>true</code> indicates that clusters will
+ * be persisted, and <code>false</code> that they will not.
+ */
@Override
public void setWriteClusterCollection(boolean state) {
// Set the flag as appropriate with the superclass.
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterer.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterer.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPClusterer.java Thu Aug 6 17:19:42 2015
@@ -15,37 +15,70 @@
import org.lcsim.event.base.BaseCluster;
/**
- * Class <code>GTPCalorimeterClusterer</code> processes events and
- * converts hits into clusters, where appropriate. It uses the modified
- * 2014 clustering algorithm.<br/>
+ * Class <code>GTPClusterer</code> is an implementation of the abstract
+ * class <code>AbstractClusterer</code> that is responsible for producing
+ * clusters using the GTP algorithm employed by the hardware.<br/>
* <br/>
- * For a hit to be a cluster center, it is required to have an energy
- * above some tunable minimum threshold. Additionally, the hit must be
- * a local maximum with respect to its neighbors and itself over a tunable
- * (default 2) clock cycles. Hits that pass these checks are then required
- * to additional have a total cluster energy that exceeds another tunable
- * minimum threshold.<br/>
+ * The GTP algorithm produces clusters by finding hits representing
+ * local spatiotemporal energy maxima and forming a cluster from the
+ * hits within the aforementioned spatiotemporal window. A given hit
+ * is first checked to see if it exceeds some minimum energy threshold
+ * (referred to as the "seed energy threshold"). If this is the case,
+ * the algorithm looks at all hits that occurred in the same crystal as
+ * the comparison hit, or any crystal directly adjacent to it, within
+ * a programmable time window. If the hit exceeds all hits meeting these
+ * criteria in energy, the hit is considered the âseed hitâ of a cluster.
+ * Then, all hits within the 3x3 spatial window which occur in the time
+ * window are added to a <code>Cluster</code> object.<br/>
* <br/>
- * A hit is added to a cluster as a component if it has a non-zero energy
- * and within the aforementioned tunable time buffer used for clustering
- * and is either at the same location as the seed hit or is a neighbor
- * to the seed hit.
- * @author Kyle McCarty
- * @author Sho Uemura
+ * Note that the algorithm employs two distinct temporal windows. The
+ * first is the âverificationâ window. This is used to check that the
+ * potential seed hit is a local maximum in energy, and is required to
+ * be symmetric (i.e. as long before the seed time as after it) to ensure
+ * consistency. The second temporal window is the âinclusionâ window,
+ * which determines which hits are included in the cluster. The inclusion
+ * window can be asymmetric, but can not exceed the verification window
+ * in length. As an example, one could choose a 12 ns verification window,
+ * meaning that the algorithm would 12 ns before and after the seed hit
+ * to check that it has the highest energy, but use a 4 ns/12 ns inclusion
+ * window, meaning that the algorithm would only include hits in 3x3
+ * spatial window up to 4 ns before and up to 12 ns after the seed hit
+ * in the cluster. Due to the way the hardware processes hits, the higher
+ * energy parts of a cluster always occur first in time, so it is not
+ * necessarily desirable to include hits significantly before the seed.
+ * It is however, necessary to verify a hitâs status as a maximum across
+ * the full time window to ensure consistency in cluster formation.
+ * <code>GTPClusterer</code> automatically defines the inclusion window
+ * in terms of the verification window.<br/>
+ * <br/>
+ * <code>GTPClusterer</code> requires as input a collection of
+ * <code>CalorimeterHit</code> objects representing the event hits. It
+ * will then produce a collection of <code>Cluster</code> objects
+ * representing the GTP algorithm output. It is designed to be run on
+ * Monte Carlo events where each event represents a 2 ns beam bunch.
+ * If the input data is formatted in the style of hardware readout, the
+ * sister class <code>GTPOnlineClusterer</code> should be used instead.
+ *
+ * @author Kyle McCarty <[log in to unmask]>
+ * @author Sho Uemura <[log in to unmask]>
+ * @see Cluster
+ * @see CalorimeterHit
+ * @see AbstractClusterer
+ * @see GTPOnlineClusterer
*/
public class GTPClusterer extends AbstractClusterer {
-
/**
* The minimum energy required for a hit to be considered as a
* cluster center. Hits with energy less than this value will be
- * ignored.
+ * ignored. This is the seed energy lower bound cut.
*/
private double seedEnergyThreshold;
/**
* Indicates the number of FADC clock cycles (each cycle is 4 ns)
* before and after a given cycle that should be considered when
- * checking if a cluster is a local maximum in space-time.
+ * checking if a cluster is a local maximum in space-time. This
+ * is the hit verification temporal window.
*/
private int clusterWindow;
@@ -58,7 +91,8 @@
/**
* Whether an asymmetric or symmetric window should be used for
- * adding hits to a cluster.
+ * adding hits to a cluster. This defines the hit inclusion temporal
+ * window with respect to the verification window.
*/
private boolean limitClusterRange = false;
@@ -75,213 +109,23 @@
private boolean writeHitCollection = true;
/**
- * Instantiates the clusterer.
+ * Instantiates a new instance of a Monte Carlo GTP clustering
+ * algorithm. It will use the default seed energy threshold of
+ * 50 MeV and a default hit inclusion window of +/- 2 ns. By
+ * default the cluster inclusion and verification windows are
+ * identical.
*/
GTPClusterer() {
- super(new String[] { "seedEnergyThreshold", "clusterWindow" }, new double[] { 0.00, 2.});
- }
-
- /**
- * Sets the clustering algorithm parameters.
- */
- @Override
- public void initialize() {
- // Set cuts.
- setSeedEnergyThreshold(getCuts().getValue("seedEnergyThreshold"));
- setClusterWindow((int) getCuts().getValue("clusterWindow"));
-
- // Initiate the hit buffer.
- hitBuffer = new LinkedList<Map<Long, CalorimeterHit>>();
-
- // Populate the event buffer with (2 * clusterWindow + 1)
- // empty events. These empty events represent the fact that
- // the first few events will not have any events in the past
- // portion of the buffer.
- int bufferSize = (2 * clusterWindow) + 1;
- for (int i = 0; i < bufferSize; i++) {
- hitBuffer.add(new HashMap<Long, CalorimeterHit>(0));
- }
- }
-
- /**
- * Generates a list of clusters from the current hit buffer. The
- * "present" event is taken to be the list of hits occurring at
- * index <code>clusterWindow</code>, which is the middle of the
- * buffer.
- * @return Returns a <code>List</code> of <code>HPSEcalCluster
- * </code> objects generated from the current event.
- */
- private List<Cluster> getClusters() {
- // Generate a list for storing clusters.
- List<Cluster> clusters = new ArrayList<Cluster>();
-
- // Get the list of hits at the current time in the event buffer.
- Map<Long, CalorimeterHit> currentHits = hitBuffer.get(clusterWindow);
-
- // VERBOSE :: Print the cluster window.
- if(verbose) {
- // Print the event header.
- System.out.printf("%n%nEvent:%n");
-
- // Calculate some constants.
- int window = (hitBuffer.size() - 1) / 2;
- int bufferNum = 0;
-
- // Print out all of the hits in the event buffer.
- for(Map<Long, CalorimeterHit> bufferMap : hitBuffer) {
- System.out.printf("Buffer %d:%n", hitBuffer.size() - bufferNum - window - 1);
- CalorimeterHit hit = null;
-
- for(Entry<Long, CalorimeterHit> entry : bufferMap.entrySet()) {
- hit = entry.getValue();
- System.out.printf("\t(%3d, %3d) --> %.4f (%.4f)%n", hit.getIdentifierFieldValue("ix"),
- hit.getIdentifierFieldValue("iy"), hit.getCorrectedEnergy(), hit.getRawEnergy());
- }
-
- bufferNum++;
- }
-
- // If there are not hits, indicate this.
- if(currentHits.isEmpty()) { System.out.println("\tNo hits this event!"); }
- }
-
- // For a hit to be a cluster center, it must be a local maximum
- // both with respect to its neighbors and itself both in the
- // present time and at all times within the event buffer.
- seedLoop:
- for (Long currentID : currentHits.keySet()) {
- // Get the actual hit object.
- CalorimeterHit currentHit = currentHits.get(currentID);
-
- // VERBOSE :: Print the current cluster.
- if(verbose) {
- System.out.printf("Cluster Check:%n");
- System.out.printf("\t(%3d, %3d) --> %.4f%n", currentHit.getIdentifierFieldValue("ix"),
- currentHit.getIdentifierFieldValue("iy"), currentHit.getCorrectedEnergy());
- }
-
- // Store the energy of the current hit.
- double currentEnergy = currentHit.getCorrectedEnergy();
-
- // If the hit energy is lower than the minimum threshold,
- // then we immediately reject this hit as a possible cluster.
- if (currentEnergy < seedEnergyThreshold) {
- // VERBOSE :: Note the reason the potential seed was
- // rejected.
- if(verbose) { System.out.printf("\tREJECT :: Does not exceed seed threshold %.4f.%n", seedEnergyThreshold); }
-
- // Skip to the next potential seed.
- continue seedLoop;
- }
-
- // Store the crystals that are part of this potential cluster,
- // starting with the cluster seed candidate.
- BaseCluster cluster = createBasicCluster();
- cluster.addHit(currentHit);
- cluster.setPosition(currentHit.getDetectorElement().getGeometry().getPosition().v());
- cluster.setNeedsPropertyCalculation(false);
-
- // Get the set of neighbors for this hit.
- Set<Long> neighbors = neighborMap.get(currentHit.getCellID());
-
- // Sort through each event stored in the buffer.
- int bufferIndex = 0;
- for (Map<Long, CalorimeterHit> bufferHits : hitBuffer) {
- // Get the hit energy at the current hit's position in
- // the buffer, if it exists. Ignore the current seed candidate.
- CalorimeterHit bufferHit = bufferHits.get(currentID);
- if (bufferHit != null && bufferHit != currentHit) {
- double bufferHitEnergy = bufferHit.getRawEnergy();
-
- // Check to see if the hit at this point in the buffer
- // is larger than then original hit. If it is, we may
- // stop the comparison because this is not a cluster.
- if (bufferHitEnergy > currentEnergy) {
- // VERBOSE :: Output the reason the potential
- // seed was rejected along with the
- // hit that caused it.
- if(verbose) {
- System.out.printf("\tREJECT :: Buffer hit surpasses hit energy.");
- System.out.printf("\tBUFFER HIT :: (%3d, %3d) --> %.4f%n", bufferHit.getIdentifierFieldValue("ix"),
- bufferHit.getIdentifierFieldValue("iy"), bufferHit.getCorrectedEnergy(), bufferHit.getRawEnergy());
- }
-
- // Skip to the next potential seed.
- continue seedLoop;
- }
-
- // If the buffer hit is smaller, then add its energy
- // to the cluster total energy.
- else {
- if(limitClusterRange && bufferIndex <= clusterWindow + 1) { cluster.addHit(bufferHit); }
- else if(!limitClusterRange) { cluster.addHit(bufferHit); }
- }
- }
-
- // We must also make sure that the original hit is
- // larger than all of the neighboring hits at this
- // point in the buffer as well.
- for (Long neighborID : neighbors) {
- // Get the neighbor hit energy if it exists.
- CalorimeterHit neighborHit = bufferHits.get(neighborID);
- if (neighborHit != null) {
- double neighborHitEnergy = neighborHit.getRawEnergy();
-
- // Check to see if the neighbor hit at this point
- // in the buffer is larger than then original hit.
- // If it is, we may stop the comparison because this
- // is not a cluster.
- if (neighborHitEnergy > currentEnergy) {
- // VERBOSE :: Output the reason the potential
- // seed was rejected along with the
- // hit that caused it.
- if(verbose) {
- System.out.printf("\tREJECT :: Buffer hit surpasses hit energy.%n");
- System.out.printf("\tBUFFER HIT :: (%3d, %3d) --> %.4f%n", neighborHit.getIdentifierFieldValue("ix"),
- neighborHit.getIdentifierFieldValue("iy"), neighborHit.getCorrectedEnergy(), neighborHit.getRawEnergy());
- }
-
- // Skip to the next potential seed.
- continue seedLoop;
- }
-
- // If the buffer neighbor hit is smaller, then
- // add its energy to the cluster total energy.
- else {
- if(limitClusterRange && bufferIndex <= clusterWindow + 1) { cluster.addHit(neighborHit); }
- else if(!limitClusterRange) { cluster.addHit(neighborHit); }
- }
- }
- }
-
- // Increment the buffer index.
- bufferIndex++;
- }
-
- // Add the cluster to the list of clusters.
- clusters.add(cluster);
-
- // VERBOSE :: Output the clusters generated from this event.
- if(verbose) {
- System.out.printf("Cluster added.%n");
- System.out.printf("\t(%3d, %3d) --> %.4f GeV --> %d hits%n", cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("ix"),
- cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("iy"), cluster.getEnergy(), cluster.getCalorimeterHits().size());
- for(CalorimeterHit hit : cluster.getCalorimeterHits()) {
- System.out.printf("\t\tCLUSTER HIT :: (%3d, %3d) --> %.4f%n", hit.getIdentifierFieldValue("ix"),
- hit.getIdentifierFieldValue("iy"), hit.getCorrectedEnergy(), hit.getRawEnergy());
- }
- }
- }
-
- // Return the generated list of clusters.
- return clusters;
- }
-
- /**
- * Places hits from the current event into the event hit buffer
- * and processes the buffer to extract clusters. Clusters are then
- * stored in the event object.
- * @param event - The event to process.
+ super(new String[] { "seedEnergyThreshold", "clusterWindow" }, new double[] { 0.050, 2 });
+ }
+
+ /**
+ * Processes the argument <code>CalorimeterHit</code> collection and
+ * forms a collection of <code>Cluster</code> objects according to
+ * the GTP clustering algorithm.
+ * @param event - The object containing event data.
+ * @param hitList - A list of <code>CalorimeterHit</code> objects
+ * from which clusters should be formed.
*/
public List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hits) {
// Store each hit in a set by its cell ID so that it may be
@@ -327,61 +171,93 @@
}
/**
+ * Indicates the type of cluster that is generated by this algorithm.
+ * @return Returns the type of cluster as a <code>ClusterType</code>
+ * object; specifically, returns <code>ClusterType.GTP</code>.
+ */
+ @Override
+ public ClusterType getClusterType() {
+ return ClusterType.GTP;
+ }
+
+ /**
+ * Sets the clustering algorithm parameters.
+ */
+ @Override
+ public void initialize() {
+ // Set cuts.
+ setSeedEnergyThreshold(getCuts().getValue("seedEnergyThreshold"));
+ setClusterWindow((int) getCuts().getValue("clusterWindow"));
+
+ // Initiate the hit buffer.
+ hitBuffer = new LinkedList<Map<Long, CalorimeterHit>>();
+
+ // Populate the event buffer with (2 * clusterWindow + 1)
+ // empty events. These empty events represent the fact that
+ // the first few events will not have any events in the past
+ // portion of the buffer.
+ int bufferSize = (2 * clusterWindow) + 1;
+ for (int i = 0; i < bufferSize; i++) {
+ hitBuffer.add(new HashMap<Long, CalorimeterHit>(0));
+ }
+ }
+
+ /**
* Sets the number of clock cycles before and after a given cycle
* that will be used when checking whether a given hit is a local
* maximum in both time and space. Note that a value of <code>N</code>
* indicates that <code>N</code> clock cycles before and
* <code>N</code> clock cycles after will be considered. Thusly, a
- * total of <code>2N + 1</code> clock cycles will be used.
+ * total of <code>2N + 1</code> clock cycles will be used. This
+ * defines the size of the hit verification window. The inclusion
+ * window is defined as a function of this, as discussed in the
+ * method <code>setLimitClusterRange</code>.
* @param clusterWindow - The number of additional clock cycles to
* include in the clustering checks. A negative value will be treated
* as zero.
*/
void setClusterWindow(int clusterWindow) {
// The cluster window of must always be at least zero.
- if (clusterWindow < 0) {
- this.clusterWindow = 0;
- }
+ if (clusterWindow < 0) { this.clusterWindow = 0; }
// If the cluster window is non-zero, then store it.
- else {
- this.clusterWindow = clusterWindow;
- }
- }
-
- /**
- * Sets whether hits should be added to a cluster from the entire
- * cluster window or just the "future" hits, plus one clock-cycle
- * of "past" hits as a safety buffer to account for time uncertainty.
+ else { this.clusterWindow = clusterWindow; }
+ }
+
+ /**
+ * Sets the behavior of the hit inclusion and verification temporal
+ * windows. If set to <code>true</code>, the hit inclusion window
+ * will be defined as one clock-cycle before the seed hit and the
+ * regular length of the verification window after the seed hit. If
+ * <code>false</code>, the inclusion window and the verification
+ * window are set to be identical.
* @param limitClusterRange - <code>true</code> indicates that the
* asymmetric clustering window should be used and <code>false</code>
* that the symmetric window should be used.
*/
- void setLimitClusterRange(boolean limitClusterRange) {
+ void setAsymmetricWindow(boolean limitClusterRange) {
this.limitClusterRange = limitClusterRange;
}
/**
- * Sets the minimum energy threshold below which hits will not be
- * considered as cluster centers.
- * @param seedEnergyThreshold - The minimum energy for a cluster center.
+ * Sets the minimum energy a hit must have before it will be
+ * considered for cluster formation.
+ * @param seedThreshold - The seed threshold in GeV.
*/
void setSeedEnergyThreshold(double seedEnergyThreshold) {
// A negative energy threshold is non-physical. All thresholds
// be at least zero.
- if (seedEnergyThreshold < 0.0) {
- this.seedEnergyThreshold = 0.0;
- } // If the energy threshold is valid, then use it.
- else {
- this.seedEnergyThreshold = seedEnergyThreshold;
- }
- }
-
- /**
- * Sets whether diagnostic text should be written out or not.
- * @param verbose - <code>true</code> indicates that diagnostic
- * text will be written out and <code>false</code> that it will
- * not.
+ if (seedEnergyThreshold < 0.0) { this.seedEnergyThreshold = 0.0; }
+
+ // If the energy threshold is valid, then use it.
+ else { this.seedEnergyThreshold = seedEnergyThreshold; }
+ }
+
+ /**
+ * Sets whether the clusterer should output diagnostic text or not.
+ * @param verbose - <code>true</code> indicates that the clusterer
+ * should output diagnostic text and <code>false</code> that it
+ * should not.
*/
void setVerbose(boolean verbose) {
this.verbose = verbose;
@@ -398,13 +274,177 @@
writeHitCollection = state;
}
- /**
- * Indicates the type of cluster that is generated by this algorithm.
- * @return Returns the type of cluster as a <code>ClusterType</code>
- * object, specifically, <code>ClusterType.GTP</code>.
- */
- @Override
- public ClusterType getClusterType() {
- return ClusterType.GTP;
- }
+/**
+ * Generates a list of clusters from the current hit buffer. The
+ * "present" event is taken to be the list of hits occurring at
+ * index <code>clusterWindow</code>, which is the middle of the
+ * buffer.
+ * @return Returns a <code>List</code> of <code>HPSEcalCluster
+ * </code> objects generated from the current event.
+ */
+private List<Cluster> getClusters() {
+ // Generate a list for storing clusters.
+ List<Cluster> clusters = new ArrayList<Cluster>();
+
+ // Get the list of hits at the current time in the event buffer.
+ Map<Long, CalorimeterHit> currentHits = hitBuffer.get(clusterWindow);
+
+ // VERBOSE :: Print the cluster window.
+ if(verbose) {
+ // Print the event header.
+ System.out.printf("%n%nEvent:%n");
+
+ // Calculate some constants.
+ int window = (hitBuffer.size() - 1) / 2;
+ int bufferNum = 0;
+
+ // Print out all of the hits in the event buffer.
+ for(Map<Long, CalorimeterHit> bufferMap : hitBuffer) {
+ System.out.printf("Buffer %d:%n", hitBuffer.size() - bufferNum - window - 1);
+ CalorimeterHit hit = null;
+
+ for(Entry<Long, CalorimeterHit> entry : bufferMap.entrySet()) {
+ hit = entry.getValue();
+ System.out.printf("\t(%3d, %3d) --> %.4f (%.4f)%n", hit.getIdentifierFieldValue("ix"),
+ hit.getIdentifierFieldValue("iy"), hit.getCorrectedEnergy(), hit.getRawEnergy());
+ }
+
+ bufferNum++;
+ }
+
+ // If there are not hits, indicate this.
+ if(currentHits.isEmpty()) { System.out.println("\tNo hits this event!"); }
+ }
+
+ // For a hit to be a cluster center, it must be a local maximum
+ // both with respect to its neighbors and itself both in the
+ // present time and at all times within the event buffer.
+ seedLoop:
+ for (Long currentID : currentHits.keySet()) {
+ // Get the actual hit object.
+ CalorimeterHit currentHit = currentHits.get(currentID);
+
+ // VERBOSE :: Print the current cluster.
+ if(verbose) {
+ System.out.printf("Cluster Check:%n");
+ System.out.printf("\t(%3d, %3d) --> %.4f%n", currentHit.getIdentifierFieldValue("ix"),
+ currentHit.getIdentifierFieldValue("iy"), currentHit.getCorrectedEnergy());
+ }
+
+ // Store the energy of the current hit.
+ double currentEnergy = currentHit.getCorrectedEnergy();
+
+ // If the hit energy is lower than the minimum threshold,
+ // then we immediately reject this hit as a possible cluster.
+ if (currentEnergy < seedEnergyThreshold) {
+ // VERBOSE :: Note the reason the potential seed was
+ // rejected.
+ if(verbose) { System.out.printf("\tREJECT :: Does not exceed seed threshold %.4f.%n", seedEnergyThreshold); }
+
+ // Skip to the next potential seed.
+ continue seedLoop;
+ }
+
+ // Store the crystals that are part of this potential cluster,
+ // starting with the cluster seed candidate.
+ BaseCluster cluster = createBasicCluster();
+ cluster.addHit(currentHit);
+ cluster.setPosition(currentHit.getDetectorElement().getGeometry().getPosition().v());
+ cluster.setNeedsPropertyCalculation(false);
+
+ // Get the set of neighbors for this hit.
+ Set<Long> neighbors = neighborMap.get(currentHit.getCellID());
+
+ // Sort through each event stored in the buffer.
+ int bufferIndex = 0;
+ for (Map<Long, CalorimeterHit> bufferHits : hitBuffer) {
+ // Get the hit energy at the current hit's position in
+ // the buffer, if it exists. Ignore the current seed candidate.
+ CalorimeterHit bufferHit = bufferHits.get(currentID);
+ if (bufferHit != null && bufferHit != currentHit) {
+ double bufferHitEnergy = bufferHit.getRawEnergy();
+
+ // Check to see if the hit at this point in the buffer
+ // is larger than then original hit. If it is, we may
+ // stop the comparison because this is not a cluster.
+ if (bufferHitEnergy > currentEnergy) {
+ // VERBOSE :: Output the reason the potential
+ // seed was rejected along with the
+ // hit that caused it.
+ if(verbose) {
+ System.out.printf("\tREJECT :: Buffer hit surpasses hit energy.");
+ System.out.printf("\tBUFFER HIT :: (%3d, %3d) --> %.4f%n", bufferHit.getIdentifierFieldValue("ix"),
+ bufferHit.getIdentifierFieldValue("iy"), bufferHit.getCorrectedEnergy(), bufferHit.getRawEnergy());
+ }
+
+ // Skip to the next potential seed.
+ continue seedLoop;
+ }
+
+ // If the buffer hit is smaller, then add its energy
+ // to the cluster total energy.
+ else {
+ if(limitClusterRange && bufferIndex <= clusterWindow + 1) { cluster.addHit(bufferHit); }
+ else if(!limitClusterRange) { cluster.addHit(bufferHit); }
+ }
+ }
+
+ // We must also make sure that the original hit is
+ // larger than all of the neighboring hits at this
+ // point in the buffer as well.
+ for (Long neighborID : neighbors) {
+ // Get the neighbor hit energy if it exists.
+ CalorimeterHit neighborHit = bufferHits.get(neighborID);
+ if (neighborHit != null) {
+ double neighborHitEnergy = neighborHit.getRawEnergy();
+
+ // Check to see if the neighbor hit at this point
+ // in the buffer is larger than then original hit.
+ // If it is, we may stop the comparison because this
+ // is not a cluster.
+ if (neighborHitEnergy > currentEnergy) {
+ // VERBOSE :: Output the reason the potential
+ // seed was rejected along with the
+ // hit that caused it.
+ if(verbose) {
+ System.out.printf("\tREJECT :: Buffer hit surpasses hit energy.%n");
+ System.out.printf("\tBUFFER HIT :: (%3d, %3d) --> %.4f%n", neighborHit.getIdentifierFieldValue("ix"),
+ neighborHit.getIdentifierFieldValue("iy"), neighborHit.getCorrectedEnergy(), neighborHit.getRawEnergy());
+ }
+
+ // Skip to the next potential seed.
+ continue seedLoop;
+ }
+
+ // If the buffer neighbor hit is smaller, then
+ // add its energy to the cluster total energy.
+ else {
+ if(limitClusterRange && bufferIndex <= clusterWindow + 1) { cluster.addHit(neighborHit); }
+ else if(!limitClusterRange) { cluster.addHit(neighborHit); }
+ }
+ }
+ }
+
+ // Increment the buffer index.
+ bufferIndex++;
+ }
+
+ // Add the cluster to the list of clusters.
+ clusters.add(cluster);
+
+ // VERBOSE :: Output the clusters generated from this event.
+ if(verbose) {
+ System.out.printf("Cluster added.%n");
+ System.out.printf("\t(%3d, %3d) --> %.4f GeV --> %d hits%n", cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("ix"),
+ cluster.getCalorimeterHits().get(0).getIdentifierFieldValue("iy"), cluster.getEnergy(), cluster.getCalorimeterHits().size());
+ for(CalorimeterHit hit : cluster.getCalorimeterHits()) {
+ System.out.printf("\t\tCLUSTER HIT :: (%3d, %3d) --> %.4f%n", hit.getIdentifierFieldValue("ix"),
+ hit.getIdentifierFieldValue("iy"), hit.getCorrectedEnergy(), hit.getRawEnergy());
+ }
+ }
+ }
+
+ // Return the generated list of clusters.
+ return clusters;
}
+}
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterDriver.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterDriver.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterDriver.java Thu Aug 6 17:19:42 2015
@@ -8,18 +8,49 @@
import org.lcsim.event.EventHeader;
/**
- * Class <code>GTPOnlineClusterDriver</code> allows parameters for the
- * readout variant of the GTP algorithm to be set.
+ * Class <code>GTPOnlineClusterDriver</code> is an implementation of
+ * the <code>ClusterDriver</code> class that defines employs the readout
+ * variant of the GTP hardware clustering algorithm. Specifics on the
+ * behavior of this algorithm can be found in its documentation.<br/>
+ * <br/>
+ * <code>GTPOnlineClusterDriver</code> allows for all of the variable
+ * settings used by the GTP algorithm to be defined. It also can be
+ * set to "verbose" mode, where it will output detailed information on
+ * each event and the cluster forming process. This is disabled by
+ * default, but can be enabled for debugging purposes.<br/>
+ * <br/>
+ * Lastly, <code>GTPOnlineClusterDriver</code> can be set to draw its
+ * settings from the <code>ConfigurationManager</code> static class,
+ * which reads and stores settings extracted directly from EvIO data.
+ * This option is disabled by default, and can be activated with the
+ * method <code>setUseDAQConfig</code>. When enabled, no clusters will
+ * be generated until <code>ConfigurationManager</code> reads a config
+ * event. This requires that the driver <code>DAQConfigDriver</code>
+ * be included in the driver chain.<br/>
+ * <br/>
+ * <code>GTPOnlineClusterDriver</code> is designed for use on hardware
+ * readout data or Monte Carlo formatted in this style. It can not be
+ * used for 2-ns beam bunch formatted data. <code>GTPClusterDriver</code>
+ * should be used for this data instead.
*
* @author Kyle McCarty <[log in to unmask]>
+ * @see GTPOnlineClusterer
+ * @see ConfigurationManager
+ * @see org.hps.recon.ecal.daqconfig.DAQConfigDriver
*/
public class GTPOnlineClusterDriver extends ClusterDriver {
+ /** An instance of the clustering algorithm object for producing
+ * cluster objects. */
private final GTPOnlineClusterer gtp;
+ /** Indicates whether the <code>ConfigurationManager</code> object
+ * should be used for clustering settings or not. */
private boolean useDAQConfig = false;
/**
- * Instantiates a new clustering algorithm using the readout
- * variant of the GTP clustering algorithm.
+ * Initializes a clustering driver. This implements the readout
+ * variant of the hardware GTP algorithm, as defined in the class
+ * <code>GTPClusterer</code>.
+ * @see GTPOnlineClusterer
*/
public GTPOnlineClusterDriver() {
// Instantiate the clusterer.
@@ -48,6 +79,15 @@
});
}
+ /**
+ * Processes an an <code>EventHeader</code> object to generate
+ * clusters. Events will not be processed if <code>UseDAQConfig</code>
+ * is <code>true</code> unless the <code>ConfigurationManager</code>
+ * static class has received a DAQ configuration from the event
+ * stream and is initialized. Driver <code>DAQConfigDriver</code>
+ * must be in the driver chain for this to occur.
+ * @see org.hps.recon.ecal.daqconfig.DAQConfigDriver
+ */
@Override
public void process(EventHeader event) {
// Only process an event if either the DAQ configuration is not
@@ -58,7 +98,8 @@
}
/**
- * Outputs the clusterer settings.
+ * Outputs the clusterer settings at driver initialization, assuming
+ * <code>setVerbose</code> is set to <code>true</code>.
*/
@Override
public void startOfData() {
@@ -68,7 +109,8 @@
/**
* Sets the minimum seed energy needed for a hit to be considered
- * for forming a cluster.
+ * for forming a cluster. This is the seed energy lower bound trigger
+ * cut and is in units of GeV.
* @param seedEnergyThreshold - The minimum cluster seed energy in
* GeV.
*/
@@ -80,6 +122,9 @@
/**
* Sets the number of clock-cycles to include in the clustering
* window before the seed hit. One clock-cycle is four nanoseconds.
+ * This defines the first half of the temporal hit inclusion window.
+ * The temporal hit verification window is defined as
+ * <code>max(windowAfter, windowBefore) * 2) + 1</code>.
* @param cyclesBefore - The length of the clustering window before
* the seed hit in clock cycles.
*/
@@ -90,8 +135,12 @@
/**
* Sets the number of clock-cycles to include in the clustering
* window after the seed hit. One clock-cycle is four nanoseconds.
+ * This defines the latter half of the temporal hit inclusion window.
+ * The temporal hit verification window is defined as
+ * <code>max(windowAfter, windowBefore) * 2) + 1</code>.
* @param cyclesAfter - The length of the clustering window after
* the seed hit in clock cycles.
+ * @see GTPOnlineClusterer
*/
public void setWindowAfter(int cyclesAfter) {
gtp.setWindowAfter(cyclesAfter);
@@ -109,9 +158,14 @@
/**
* Sets whether GTP settings should be drawn from the EvIO data
- * DAQ configuration or read from the steering file.
+ * DAQ configuration or read from the steering file. If this is
+ * set to <code>true</code>, no clusters will be generated until
+ * the static class <code>ConfigurationManager</code> has received
+ * a DAQ settings event and initialized. If this class is not part
+ * of the driver chain, then no clusters will ever be created.
* @param state - <code>true</code> means that DAQ configuration
* will be used and <code>false</code> that it will not.
+ * @see org.hps.recon.ecal.daqconfig.DAQConfigDriver
*/
public void setUseDAQConfig(boolean state) {
useDAQConfig = state;
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterer.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterer.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/GTPOnlineClusterer.java Thu Aug 6 17:19:42 2015
@@ -16,74 +16,115 @@
/**
* Class <code>GTPOnlineClusterer</code> is an implementation of the
- * GTP clustering algorithm for EVIO readout data for use in either
- * online reconstruction/diagnostics or for general analysis of EVIO
- * readout data.<br/>
+ * abstract class <code>AbstractClusterer</code> that is responsible
+ * for producing clusters using the GTP algorithm employed by the
+ * hardware.<br/>
* <br/>
- * The GTP algorithm searches the set of hits in a readout event and
- * compares them to select those that are a maximum in their 3x3 window
- * and across a period of time that can be set. Hits that are maxima
- * are declared "cluster seeds" and a cluster is created from them.
- * All hits within the clustering window of the seed time are then
- * added to the cluster and it is written to the event stream.<br/>
+ * The GTP algorithm produces clusters by finding hits representing
+ * local spatiotemporal energy maxima and forming a cluster from the
+ * hits within the aforementioned spatiotemporal window. A given hit
+ * is first checked to see if it exceeds some minimum energy threshold
+ * (referred to as the "seed energy threshold"). If this is the case,
+ * the algorithm looks at all hits that occurred in the same crystal as
+ * the comparison hit, or any crystal directly adjacent to it, within
+ * a programmable time window. If the hit exceeds all hits meeting these
+ * criteria in energy, the hit is considered the âseed hitâ of a cluster.
+ * Then, all hits within the 3x3 spatial window which occur in the time
+ * window are added to a <code>Cluster</code> object.<br/>
* <br/>
- * The GTP algorithm uses three time windows. THe verification window
- * is the time around the seed hit in which it is required to have more
- * energy than any other hits in the 3x3 spatial window surrounding it.
- * This is always symmetric. The other two windows combined define the
- * clustering window. The clustering window is composed of a window
- * before and a window after the seed time. These may be defined using
- * different values. The window after should be as long or longer than
- * the window before to make physical sense. The verification window is
- * then defined as the larger of the two constituents of the clustering
- * window. This is required for clustering to be consistent.
+ * Note that the algorithm employs two distinct temporal windows. The
+ * first is the âverificationâ window. This is used to check that the
+ * potential seed hit is a local maximum in energy, and is required to
+ * be symmetric (i.e. as long before the seed time as after it) to ensure
+ * consistency. The second temporal window is the âinclusionâ window,
+ * which determines which hits are included in the cluster. The inclusion
+ * window can be asymmetric, but can not exceed the verification window
+ * in length. As an example, one could choose a 12 ns verification window,
+ * meaning that the algorithm would 12 ns before and after the seed hit
+ * to check that it has the highest energy, but use a 4 ns/12 ns inclusion
+ * window, meaning that the algorithm would only include hits in 3x3
+ * spatial window up to 4 ns before and up to 12 ns after the seed hit
+ * in the cluster. Due to the way the hardware processes hits, the higher
+ * energy parts of a cluster always occur first in time, so it is not
+ * necessarily desirable to include hits significantly before the seed.
+ * It is however, necessary to verify a hitâs status as a maximum across
+ * the full time window to ensure consistency in cluster formation.
+ * <code>GTPOnlineClusterer</code> automatically selects the larger of
+ * the two inclusion window parts as the verification window length.<br/>
+ * <br/>
+ * <code>GTPOnlineClusterer</code> requires as input a collection of
+ * <code>CalorimeterHit</code> objects representing the event hits. It
+ * will then produce a collection of <code>Cluster</code> objects
+ * representing the GTP algorithm output. It also produces a series of
+ * distribution plots under the âGTP(O) Cluster Plotsâ header. It is
+ * designed to be run on readout events, either from the hardware or
+ * Monte Carlo that has been processed through the readout simulation.
+ * If the input data is formatted into constant-time beam bunches, the
+ * sister class <code>GTPClusterer</code> should be used instead.
*
* @author Kyle McCarty <[log in to unmask]>
+ * @see Cluster
+ * @see CalorimeterHit
+ * @see AbstractClusterer
+ * @see GTPClusterer
*/
public class GTPOnlineClusterer extends AbstractClusterer {
-
- // The size of the temporal window in nanoseconds. By default,
- // this is 1 clock-cycle before and 3 clock-cycles after.
+ /**
+ * The length of the temporal window for inclusing clusters that
+ * occur before the seed hit.
+ */
private double timeBefore = 4;
+
+ /**
+ * The length of the temporal window for including clusters that
+ * occur after the seed hit.
+ */
private double timeAfter = 12;
+
+ /**
+ * The length of the temporal window for verifying that a hit is
+ * a local maximum in energy. This length represents both halves
+ * of the verification window, so the full length would be defined
+ * by <code>timeWindow * 2 + 4</code> ns.
+ */
private double timeWindow = 12;
-
- // Cluster formation energy thresholds. Currently, the hardware
- // only supports a lower bound seed energy. Units are in GeV.
+
+ /**
+ * The minimum energy a hit must have to be considered for cluster
+ * seed formation. Units are in GeV.
+ */
private double seedThreshold = 0.050;
- // Internal variables.
+ /**
+ * Controls whether or not verbose diagnostic information is output.
+ */
private boolean verbose = false;
// Diagnostic plots.
private AIDA aida = AIDA.defaultInstance();
- IHistogram1D hitEnergy = aida.histogram1D("GTP(O) Cluster Plots :: Hit Energy Distribution", 256, -1.0, 2.2);
- IHistogram1D clusterSeedEnergy = aida.histogram1D("GTP(O) Cluster Plots :: Cluster Seed Energy Distribution", 176, 0.0, 2.2);
- IHistogram1D clusterHitCount = aida.histogram1D("GTP(O) Cluster Plots :: Cluster Hit Count Distribution", 9, 1, 10);
- IHistogram1D clusterTotalEnergy = aida.histogram1D("GTP(O) Cluster Plots :: Cluster Total Energy Distribution", 176, 0.0, 2.2);
- IHistogram2D hitDistribution = aida.histogram2D("GTP(O) Cluster Plots :: Hit Distribution", 46, -23, 23, 11, -5.5, 5.5);
- IHistogram2D clusterDistribution = aida.histogram2D("GTP(O) Cluster Plots :: Cluster Seed Distribution", 46, -23, 23, 11, -5.5, 5.5);
- IHistogram1D energyDistribution = aida.histogram1D("GTP(O) Cluster Plots :: Percent Negative Energy Distribution", 100, 0.0, 1.0);
+ private IHistogram1D hitEnergy = aida.histogram1D("GTP(O) Cluster Plot/Hit Energy Distribution", 256, -1.0, 2.2);
+ private IHistogram1D clusterSeedEnergy = aida.histogram1D("GTP(O) Cluster Plots/Cluster Seed Energy Distribution", 176, 0.0, 2.2);
+ private IHistogram1D clusterHitCount = aida.histogram1D("GTP(O) Cluster Plots/Cluster Hit Count Distribution", 9, 1, 10);
+ private IHistogram1D clusterTotalEnergy = aida.histogram1D("GTP(O) Cluster Plots/Cluster Total Energy Distribution", 176, 0.0, 2.2);
+ private IHistogram2D hitDistribution = aida.histogram2D("GTP(O) Cluster Plots/Hit Distribution", 46, -23, 23, 11, -5.5, 5.5);
+ private IHistogram2D clusterDistribution = aida.histogram2D("GTP(O) Cluster Plots/Cluster Seed Distribution", 46, -23, 23, 11, -5.5, 5.5);
+ private IHistogram1D energyDistribution = aida.histogram1D("GTP(O) Cluster Plots/Percent Negative Energy Distribution", 100, 0.0, 1.0);
/**
* Instantiates a new instance of a readout GTP clustering algorithm.
+ * This will use the default seed energy threshold of 50 MeV.
*/
GTPOnlineClusterer() {
super(new String[] { "seedThreshold" }, new double[] { 0.050 });
}
/**
- * Gets any relevant cuts from the superclass and sets the local
- * clusterer variables accordingly.
- */
- public void initialize() {
- seedThreshold = getCuts().getValue("seedThreshold");
- }
-
- /**
- * Reads in hits and processes them into clusters as per the GTP
- * clustering algorithm implemented in the hardware.
+ * Processes the argument <code>CalorimeterHit</code> collection and
+ * forms a collection of <code>Cluster</code> objects according to
+ * the GTP clustering algorithm.
* @param event - The object containing event data.
+ * @param hitList - A list of <code>CalorimeterHit</code> objects
+ * from which clusters should be formed.
*/
@Override
public List<Cluster> createClusters(EventHeader event, List<CalorimeterHit> hitList) {
@@ -95,6 +136,7 @@
System.out.println("=== GTP Readout Clusterer ============================================");
System.out.println("======================================================================");
+ // Sort the hits by x-index and then by y-index.
Collections.sort(hitList, new Comparator<CalorimeterHit>() {
@Override
public int compare(CalorimeterHit firstHit, CalorimeterHit secondHit) {
@@ -106,6 +148,8 @@
}
}
});
+
+ // Print the hit collection.
System.out.println("Event Hit Collection:");
for(CalorimeterHit hit : hitList) {
int ix = hit.getIdentifierFieldValue("ix");
@@ -155,7 +199,7 @@
protoCluster.setPosition(seed.getDetectorElement().getGeometry().getPosition().v());
protoCluster.setNeedsPropertyCalculation(false);
- // Iterate over the other hits and if the are within
+ // Iterate over the other hits and if they are within
// the clustering spatiotemporal window, compare their
// energies.
hitLoop:
@@ -217,16 +261,18 @@
// VERBOSE :: Print out all the clusters in the event.
if(verbose) {
+ // Print the clusters.
System.out.println("Event Cluster Collection:");
for(Cluster cluster : clusterList) {
+ // Output basic cluster positional and energy data.
CalorimeterHit seedHit = cluster.getCalorimeterHits().get(0);
int ix = seedHit.getIdentifierFieldValue("ix");
int iy = seedHit.getIdentifierFieldValue("iy");
double energy = cluster.getEnergy();
double time = seedHit.getTime();
-
System.out.printf("\tCluster --> %6.3f GeV at (%3d, %3d) and at t = %.2f%n", energy, ix, iy, time);
+ // Output the cluster hit collection.
for(CalorimeterHit hit : cluster.getCalorimeterHits()) {
int hix = hit.getIdentifierFieldValue("ix");
int hiy = hit.getIdentifierFieldValue("iy");
@@ -241,16 +287,125 @@
// VERBOSE :: Print a new line.
if(verbose) { System.out.println(); }
+ // Return the list of clusters.
return clusterList;
}
/**
- * Checks whether the hit <code>hit</code> keeps the hit <code>seed
- * </code> from meeting the criteria for being a seed hit. Note that
- * this does not check to see if the two hits are within the valid
- * spatiotemporal window of one another.
+ * Gets the type of cluster produced by this clusterer.
+ * @return Returns the cluster type as a <code>ClusterType</code>
+ * enumerable.
+ */
+ @Override
+ public ClusterType getClusterType() {
+ return ClusterType.GTP_ONLINE;
+ }
+
+ /**
+ * Gets the seed energy lower bound threshold in units of GeV.
+ * @return Returns the threshold as a <code>double</code>.
+ */
+ public double getSeedLowThreshold() { return seedThreshold; }
+
+ /**
+ * Gets the number of nanoseconds before the seed hit time that
+ * the clusterer will look to include hits when a cluster is formed.
+ * @return Returns the time window as a <code>double</code>.
+ */
+ public double getWindowBefore() { return timeBefore; }
+
+ /**
+ * Gets the number of nanoseconds after the seed hit time that
+ * the clusterer will look to include hits when a cluster is formed.
+ * @return Returns the time window as a <code>double</code>.
+ */
+ public double getWindowAfter() { return timeAfter; }
+
+ /**
+ * Sets up the clusterer parameters so that it is ready to be used.
+ * This should be run before the cluster formation.
+ */
+ @Override
+ public void initialize() {
+ seedThreshold = getCuts().getValue("seedThreshold");
+ }
+
+ /**
+ * Returns whether the clusterer will output verbose diagnostic
+ * information.
+ * @return Returns <code>true</code> if the clusterer will output
+ * diagnostic information and <code>false</code> otherwise.
+ */
+ boolean isVerbose() { return verbose; }
+
+ /**
+ * Sets the minimum energy a hit must have before it will be
+ * considered for cluster formation.
+ * @param seedThreshold - The seed threshold in GeV.
+ */
+ void setSeedLowThreshold(double seedThreshold) {
+ this.seedThreshold = seedThreshold;
+ }
+
+ /**
+ * Sets whether the clusterer should output diagnostic text or not.
+ * @param verbose - <code>true</code> indicates that the clusterer
+ * should output diagnostic text and <code>false</code> that it
+ * should not.
+ */
+ void setVerbose(boolean verbose) {
+ this.verbose = verbose;
+ }
+
+ /**
+ * Sets the number of clock-cycles to include in the clustering
+ * window before the seed hit. One clock-cycle is four nanoseconds.
+ * Note that the larger of this time and the time defined in method
+ * <code>setWindowAfter</code> will be the verification window size.
+ * @param cyclesBefore - The length of the clustering window before
+ * the seed hit in clock cycles.
+ */
+ void setWindowBefore(int cyclesBefore) {
+ // The cluster window can not be negative.
+ if(cyclesBefore < 0) { cyclesBefore = 0; }
+
+ // Convert the window to nanoseconds and set the two time
+ // windows appropriately.
+ timeBefore = cyclesBefore * 4;
+ timeWindow = Math.max(timeBefore, timeAfter);
+ }
+
+ /**
+ * Sets the number of clock-cycles to include in the clustering
+ * window after the seed hit. One clock-cycle is four nanoseconds.
+ * Note that the larger of this time and the time defined in method
+ * <code>setWindowBefore</code> will be the verification window size.
+ * @param cyclesAfter - The length of the clustering window after
+ * the seed hit in clock cycles.
+ */
+ void setWindowAfter(int cyclesAfter) {
+ // The cluster window can not be negative.
+ if(cyclesAfter < 0) { cyclesAfter = 0; }
+
+ // Convert the window to nanoseconds and set the two time
+ // windows appropriately.
+ timeAfter = cyclesAfter * 4;
+ timeWindow = Math.max(timeBefore, timeAfter);
+ }
+
+ /**
+ * Compares the argument <code>CalorimeterHit</code> <code>hit</code>
+ * against the <code>CalorimeterHit</code> <code>seed</code> to see
+ * if <code>seed</code> meets the criteria for a seed hit given the
+ * presence of <code>hit</code>, which is assumed to be located in
+ * the appropriate spatiotemporal window.<br/>
+ * <br/>
+ * Note that it is the responsibility of the calling method to
+ * ascertain whether the two <code>CalorimeterHit</code> objects
+ * are actually within the proper spatial and temporal windows of
+ * one another.
* @param seed - The potential seed hit.
- * @param hit - The hit to compare with the seed.
+ * @param hit - The hit with which to compare the seed.
* @return Returns <code>true</code> if either the two hits are the
* same hit or if the hit does not invalidate the potential seed.
* Returns <code>false</code> otherwise.
@@ -303,10 +458,12 @@
}
/**
- * Checks whether the hit <code>hit</code> falls within the spatial
- * window of the hit <code>Seed</code>. This is defined as within
- * 1 index of the seed's x-index and similarly for the seed's
- * y-index.
+ * Checks whether the <code>CalorimeterHit</code> <code>hit</code>
+ * is within the 3x3 spatial window of <code>CalorimeterHit</code>
+ * <code>seed</code>. This is defined as <code>seed</code> having
+ * an x-index within +/-1 of the x-index of <code>hit</code> and
+ * similarly for the y-index. Allowance is made for the fact that
+ * the x-indices go from -1 to 1 and skip zero.
* @param seed - The seed hit.
* @param hit - The comparison hit.
* @return Returns <code>true</code> if either both hits are the
@@ -353,9 +510,9 @@
}
/**
- * Checks whether the hit <code>hit</code> is within the temporal
- * window of the hit <code>seed</code> for the purpose of seed
- * verification.
+ * Checks whether <code>CalorimeterHit</code> <code>hit</code> is
+ * within the verification temporal window for potential seed hit
+ * <code>seed</code>.
* @param seed - The seed hit.
* @param hit - The comparison hit.
* @return Returns <code>true</code> if the comparison hit is within
@@ -373,9 +530,9 @@
}
/**
- * Checks whether the hit <code>hit</code> is within the temporal
- * window of the hit <code>seed</code> for the purpose of adding
- * a hit to a cluster.
+ * Checks whether <code>CalorimeterHit</code> <code>hit</code> is
+ * within the inclusion temporal window for potential seed hit
+ * <code>seed</code>.
* @param seed - The seed hit.
* @param hit - The comparison hit.
* @return Returns <code>true</code> if the comparison hit is within
@@ -397,87 +554,11 @@
return (hitTime - seedTime) <= timeAfter;
}
- // If the times are the same, the are within the window.
+ // If the times are the same, they are within the window.
if(hitTime == seedTime) { return true; }
// Otherwise, one or both times is undefined and should not be
// treated as within time.
else { return false; }
}
-
- /**
- * Gets the seed energy lower bound threshold in units of GeV.
- * @return Returns the seed energy lower bound threshold.
- */
- public double getSeedLowThreshold() { return seedThreshold; }
-
- /**
- * Gets the number of nanoseconds before the seed hit time the
- * clusterer will look to verify the seed hit.
- * @return Returns the size of the time window before the seed
- * hit time.
- */
- public double getWindowBefore() { return timeBefore; }
-
- /**
- * Gets the number of nanoseconds after the seed hit time the
- * clusterer will look to verify the seed hit.
- * @return Returns the size of the time window after the seed
- * hit time.
- */
- public double getWindowAfter() { return timeAfter; }
-
- /**
- * Returns whether the clusterer will output verbose diagnostic
- * information.
- * @return Returns <code>true</code> if the clusterer will output
- * diagnostic information and <code>false</code> otherwise.
- */
- public boolean isVerbose() { return verbose; }
-
- /**
- * Sets the minimum energy a hit must have before it will be
- * considered for cluster formation.
- * @param seedThreshold - The seed threshold in GeV.
- */
- public void setSeedLowThreshold(double seedThreshold) {
- this.seedThreshold = seedThreshold;
- }
-
- /**
- * Sets the number of clock-cycles to include in the clustering
- * window before the seed hit. One clock-cycle is four nanoseconds.
- * @param cyclesBefore - The length of the clustering window before
- * the seed hit in clock cycles.
- */
- public void setWindowBefore(int cyclesBefore) {
- timeBefore = cyclesBefore * 4;
- timeWindow = Math.max(timeBefore, timeAfter);
- }
-
- /**
- * Sets the number of clock-cycles to include in the clustering
- * window after the seed hit. One clock-cycle is four nanoseconds.
- * @param cyclesAfter - The length of the clustering window after
- * the seed hit in clock cycles.
- */
- public void setWindowAfter(int cyclesAfter) {
- timeAfter = cyclesAfter * 4;
- timeWindow = Math.max(timeBefore, timeAfter);
- }
-
- /**
- * Sets whether the clusterer should output diagnostic text or not.
- * @param verbose - <code>true</code> indicates that the clusterer
- * should output diagnostic text and <code>false</code> that it
- * should not.
- */
- public void setVerbose(boolean verbose) {
- this.verbose = verbose;
- }
-
- @Override
- public ClusterType getClusterType() {
- return ClusterType.GTP_ONLINE;
- }
}
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/ConfigurationManager.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/ConfigurationManager.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/ConfigurationManager.java Thu Aug 6 17:19:42 2015
@@ -10,7 +10,7 @@
* the DAQ configuration that can be parsed from EVIO files. It works
* in conjunction with the <code>DAQConfigDriver</code>, which obtains
* the configuration parser object when available and passes it to this
- * manager, and <code>TriggerConfig</code>, which parses the EVIO data.
+ * manager, and <code>EvioDAQParser</code>, which parses the EVIO data.
*
* @author Kyle McCarty <[log in to unmask]>
* @see DAQConfigDriver
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/DAQConfigDriver.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/DAQConfigDriver.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/DAQConfigDriver.java Thu Aug 6 17:19:42 2015
@@ -5,8 +5,25 @@
import org.lcsim.event.EventHeader;
import org.lcsim.util.Driver;
+/**
+ * Class <code>DAQConfigDriver</code> is responsible for checking events
+ * for DAQ configuration settings, and then passing them to the associated
+ * class <code>ConfigurationManager</code> so that they can be accessed
+ * by other classes.<br/>
+ * <br/>
+ * This driver must be included in the driver chain if any other drivers
+ * in the chain rely on <code>ConfigurationManager</code>, as it can
+ * not be initialized otherwise.
+ *
+ * @author Kyle McCarty
+ * @see ConfigurationManager
+ */
public class DAQConfigDriver extends Driver {
-
+ /**
+ * Checks an event for the DAQ configuration banks and passes them
+ * to the <code>ConfigurationManager</code>.
+ * @param - The event to check.
+ */
@Override
public void process(EventHeader event) {
// Check if a trigger configuration bank exists.
@@ -21,5 +38,4 @@
ConfigurationManager.updateConfiguration(daqConfig);
}
}
-
}
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/EvioDAQParser.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/EvioDAQParser.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/daqconfig/EvioDAQParser.java Thu Aug 6 17:19:42 2015
@@ -12,6 +12,18 @@
import org.hps.conditions.ecal.EcalChannel;
import org.hps.conditions.ecal.EcalConditions;
+/**
+ * Class <code>EvioDAQParser</code> takes DAQ configuration banks from
+ * EvIO data and extracts the configuration parameters from them. These
+ * are then stored within package-accessible variables within the class.
+ * <br/><br/>
+ * Note that this class should not be used directly to acquire DAQ
+ * configuration data. It is intended to be used internally by the EvIO
+ * parser and the class <code>ConfigurationManager</code>. The latter
+ * should be used for accessing this information for any other classes.
+ *
+ * @author Nathan Baltzell <[log in to unmask]>
+ */
public class EvioDAQParser {
/*
* Read/Parse/Save the DAQ trigger configuration settings.
@@ -22,135 +34,271 @@
*
* GTP settings and Prescale factors will need to be added to this class when added to EVIO.
*
- * TODO: Error in EVIO format for Crate 39 for 2014 data requires another JEVIO workaround (realized Feb 16).
+ * TODO: Error in EVIO format for Crate 39 for 2014 data requires another JEVIO workaround (realized Feb. 16).
* ** This was fixed in EVIO for data after run 4044.
*
* TODO: Manually put in GTP settings based on run number for 2014 data.
* TODO: Manually deal with change in format of SSP_HPS_SINGLES_NMIN (at 3312(?)).
*
- * TODO: Restructure, clean up..
- *
- * @author <[log in to unmask]>
- */
- public int nBanks = 0;
+ * TODO: Restructure, clean up...
+ */
+ /** The EvIO bank identification tag for DAQ configuration banks. */
public static final int BANK_TAG = 0xE10E;
- // need to know these in order to interpret DAQ strings:
+ // Stores the hardware codes for each trigger type.
private static final int[] singlesIOsrc = { 20, 21 };
private static final int[] pairsIOsrc = { 22, 23 };
// Dump everything read from the DAQ Configuration Bank, minimal interpretation:
- Map<String,List<String>> configMap = new HashMap<String,List<String>>();
-
- // link ECAL FADC channel settings to EcalChannels:
- Map<EcalChannel,Float> GAIN = new HashMap<EcalChannel,Float>();
- Map<EcalChannel,Float> PEDESTAL = new HashMap<EcalChannel,Float>();
- Map<EcalChannel,Integer> THRESHOLD = new HashMap<EcalChannel,Integer>();
-
- // private boolean debug = true;
+ private Map<String, List<String>> configMap = new HashMap<String, List<String>>();
+
+ // Class parameters.
+ private int nBanks = 0;
private boolean debug = false;
// FADC Config:
+ /** The length of time after a pulse-crossing event that the pulse
+ * should be integrated. Uses units of clock-cycles. */
int fadcNSA = 0;
+ /** The length of time before a pulse-crossing event that the pulse
+ * should be integrated. Uses units of clock-cycles. */
int fadcNSB = 0;
+ /** The maximum number of pulses that will be extracted from a single
+ * channel within a readout window. */
int fadcNPEAK = 0;
+ /** The pulse-processing mode used by the FADC. This should be 1,
+ * 3, or 7. */
int fadcMODE = 0;
+ /** The size of readout window in nanoseconds. */
int fadcWIDTH = 0;
+ /** The time-offset of the readout window in ns. */
int fadcOFFSET = 0;
+ /** Map of <code>EcalChannel</code> to the gain for that channel.
+ * Uses units of ADC / MeV for the mapped value. */
+ Map<EcalChannel, Float> GAIN = new HashMap<EcalChannel, Float>();
+ /** Map of <code>EcalChannel</code> to the pedestal for that channel.
+ * Uses units of ADC for the mapped value. */
+ Map<EcalChannel, Float> PEDESTAL = new HashMap<EcalChannel, Float>();
+ /** Map of <code>EcalChannel</code> to the threshold for that channel.
+ * Uses units of ADC for the mapped value. */
+ Map<EcalChannel, Integer> THRESHOLD = new HashMap<EcalChannel, Integer>();
// GTP Clustering Cut Values:
+ /** The seed energy lower bound cut used by the clusterer. Value is
+ * in units of MeV. */
int gtpMinSeedEnergy = 0;
+ /** The length of the clustering verification/inclusion window before
+ * the seed hit. Uses units of clock-cycles. */
int gtpWindowBefore = 0;
+ /** The length of the clustering verification/inclusion window after
+ * the seed hit. Uses units of clock-cycles. */
int gtpWindowAfter = 0;
// Triggers Enabled:
+ /** Indicates whether the singles triggers are enabled or not. Uses
+ * the format <code>{ Singles0_Enabled, Singles1_Enabled }</code>. */
boolean[] singlesEn = { false, false };
+ /** Indicates whether the pair triggers are enabled or not. Uses
+ * the format <code>{ Pair0_Enabled, Pair1_Enabled }</code>. */
boolean[] pairsEn = { false, false };
// Singles Cuts Enabled:
+ /** Indicates whether the singles trigger cluster hit count cuts
+ * are enabled or not. Uses the format
+ * <code>{ Singles0_Cut_Enabled, Singles1_Cut_Enabled }</code>. */
boolean[] singlesNhitsEn = { false, false };
+ /** Indicates whether the singles trigger cluster total energy lower
+ * bound cuts are enabled or not. Uses the format
+ * <code>{ Singles0_Cut_Enabled, Singles1_Cut_Enabled }</code>. */
boolean[] singlesEnergyMinEn = { false, false };
+ /** Indicates whether the singles trigger cluster total energy upper
+ * bound cuts are enabled or not. Uses the format
+ * <code>{ Singles0_Cut_Enabled, Singles1_Cut_Enabled }</code>. */
boolean[] singlesEnergyMaxEn = { false, false };
// Pairs Cuts Enabled:
+ /** Indicates whether the pair trigger pair energy sum cuts are
+ * enabled or not. Uses the format
+ * <code>{ Pair0_Cut_Enabled, Pair1_Cut_Enabled }</code>. */
boolean[] pairsEnergySumMaxMinEn = { false, false };
+ /** Indicates whether the pair trigger pair energy difference cuts
+ * are enabled or not. Uses the format
+ * <code>{ Pair0_Cut_Enabled, Pair1_Cut_Enabled }</code>. */
boolean[] pairsEnergyDiffEn = { false, false };
+ /** Indicates whether the pair trigger pair coplanarity cuts are
+ * enabled or not. Uses the format
+ * <code>{ Pair0_Cut_Enabled, Pair1_Cut_Enabled }</code>. */
boolean[] pairsCoplanarityEn = { false, false };
+ /** Indicates whether the pair trigger pair energy slope cuts are
+ * enabled or not. Uses the format
+ * <code>{ Pair0_Cut_Enabled, Pair1_Cut_Enabled }</code>. */
boolean[] pairsEnergyDistEn = { false, false };
// Singles Cut Values:
+ /** Specifies the value of the singles trigger cluster hit count
+ * cuts. Use the format, in units of hits,
+ * <code>{ Singles0_Cut_Value, Singles1_Cut_Value }</code>. */
int[] singlesNhits = { 0, 0 };
+ /** Specifies the value of the singles trigger cluster total energy
+ * lower bound cuts. Use the format, in units of MeV,
+ * <code>{ Singles0_Cut_Value, Singles1_Cut_Value }</code>. */
int[] singlesEnergyMin = { 0, 0 };
+ /** Specifies the value of the singles trigger cluster total energy
+ * upper bound cuts. Use the format, in units of MeV,
+ * <code>{ Singles0_Cut_Value, Singles1_Cut_Value }</code>. */
int[] singlesEnergyMax = { 0, 0 };
// Pairs Cut Values:
+ /** Specifies the value of the pair trigger cluster hit count cuts.
+ * Use the format, in units of hits,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
int[] pairsNhitsMin = { 0, 0 };
+ /** Specifies the value of the pair trigger cluster total energy
+ * lower bound cuts. Use the format, in units of MeV,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
int[] pairsEnergyMin = { 0, 0 };
+ /** Specifies the value of the pair trigger cluster total energy
+ * upper bound cuts. Use the format, in units of MeV,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
int[] pairsEnergyMax = { 0, 0 };
+ /** Specifies the value of the pair trigger pair energy sum upper
+ * bound cuts. Use the format, in units of MeV,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
int[] pairsEnergySumMin = { 0, 0 };
+ /** Specifies the value of the pair trigger pair energy sum lower
+ * bound cuts. Use the format, in units of MeV,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
int[] pairsEnergySumMax = { 0, 0 };
+ /** Specifies the value of the pair trigger pair energy difference
+ * cuts. Use the format, in units of MeV,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
int[] pairsEnergyDiffMax = { 0, 0 };
+ /** Specifies the value of the pair trigger pair coplanarity cuts.
+ * Use the format, in units of degrees,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
int[] pairsCoplanarityMax = { 0, 0 };
+ /** Specifies the value of the pair trigger pair time coincidence
+ * cuts. Use the format, in units of nanoseconds,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
int[] pairsTimeDiffMax = { 0, 0 };
+ /** Specifies the value of the pair trigger pair energy slope cuts.
+ * Use the format, in units of MeV,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
int[] pairsEnergyDistMin = { 0, 0 };
// Pairs Cut Parameters:
+ /** Specifies the value of the pair trigger pair energy slope cuts'
+ * parameter F. Use the format, in units of MeV / mm,
+ * <code>{ Pair0_Cut_Value, Pair1_Cut_Value }</code>. */
float[] pairsEnergyDistSlope = { 0, 0 };
- // Have to remember the previous slot line in order to interpret the data:
+ // Tracks the last FADC slot seen. This is needed for parsing FADC
+ // threshold, pedestal, and gain information.
private int thisFadcSlot = 0;
// Cache local set of EcalChannels:
private EcalConditions ecalConditions = null;
private List<EcalChannel> channels = new ArrayList<EcalChannel>();
+ /**
+ * Instantiates the <code>EvioDAQParser</code>.
+ */
public EvioDAQParser() {
+ // Create a map to map crystals to their database channel object.
ecalConditions = DatabaseConditionsManager.getInstance().getEcalConditions();
for (int ii = 0; ii < 442; ii++) {
- channels.add(findChannel(ii+1));
+ channels.add(findChannel(ii + 1));
}
}
- public void parse(int crate, int runNumber, String[] dump) {
+ /**
+ * Parses a set of configuration tables to obtain DAQ configuration
+ * parameters.
+ * @param crate - The crate associated with the configuration tables.
+ * @param runNumber - The run number for the current data set.
+ * @param configurationTables - Tables containing DAQ configuration
+ * parameters.
+ */
+ public void parse(int crate, int runNumber, String[] configurationTables) {
+ // Track the number of banks that have been parsed. If the
+ // parameter values have not been populated after a certain
+ // number of banks, there is missing information.
nBanks++;
- loadConfigMap(crate,dump);
- if (debug) printMap();
+
+ // Create a map that maps an identifier for each configuration
+ // parameter (its parameter key) to any values associated
+ // with it (its parameter values).
+ loadConfigMap(crate, configurationTables);
+
+ // If debugging text is enabled, print the map to the terminal.
+ if(debug) { printMap(); }
+
+ // If this run is known to be missing configuration values,
+ // handle the missing values.
fixConfigMap2014Run(runNumber);
+
+ // Parse the previously generated configuration map and extract
+ // the DAQ configuration from it.
parseConfigMap();
+ // If the expected number of banks have been parsed and debugging
+ // text is enabled, print out all of the parsed variables.
if(nBanks > 2 && debug) { printVars(); }
}
- /*
- * The first parsing routine. Just dumps the config strings
- * into a map whose keys are the first column in the config file.
- * Also treats some special cases.
- */
- private void loadConfigMap(int crate, String[] dump) {
- for(String dump1 : dump) {
- for(String line : dump1.trim().split("\n")) {
+ /**
+ * Converts the textual configuration information into a map, where
+ * the first column value becomes the map entry key and the remainder
+ * becomes the map entry value.
+ * @param crate - The calorimeter crate associated with the textual
+ * configuration data.
+ * @param configTables - An array of textual configuration tables that
+ * contain the DAQ configuration parameters.
+ */
+ private void loadConfigMap(int crate, String[] configTables) {
+ // Iterate over each configuration table.
+ for(String configTable : configTables) {
+ // Split each table into rows and iterate over the rows.
+ rowLoop:
+ for(String line : configTable.trim().split("\n")) {
+ // Split the first column from the row.
+ String[] cols = line.trim().split(" +", 2);
- String[] cols = line.trim().split(" +", 2);
- if(cols.length < 2) continue;
+ // If there are fewer than two segments after the split,
+ // then this is not a valid parameter entry.
+ if(cols.length < 2) continue rowLoop;
+ // The row name is the value of the first column. The
+ // rest are typically values.
String key = cols[0];
- List<String> vals = new ArrayList<String>
- (Arrays.asList(cols[1].trim().split(" +")));
+ List<String> vals = new ArrayList<String>(Arrays.asList(cols[1].trim().split(" +")));
+ // If no values are present, this is not a valid entry.
if (vals.size() < 1) {
- continue;
+ continue rowLoop;
}
-
- // SPECIAL CASE:
- // parse the 16+1 column slot configurations.
+
+ // SPECIAL CASE:: Key "FADC250"
+ // This entry marks parameter values for FADC channels,
+ // such as pedestals, gains, and thresholds. These are
+ // stored in separate lists from the other parameters.
if (key.startsWith("FADC250")) {
parseFADC(crate, key.trim(), vals);
}
- // SPECIAL CASE:
- // figure out which triggers are enabled:
+ // SPECIAL CASE: Key "SSP_HPS_SET_IO_SRC"
+ // This entry indicates which triggers are enabled and
+ // needs to be parsed differently than normal.
else if(key.startsWith("SSP_HPS_SET_IO_SRC")) {
+ // The first "parameter value" is a hardware code
+ // that identifies the trigger. Obtain it.
int trig = Integer.valueOf(vals.get(1));
+
+ // There are two trigger of each type, singles and
+ // pairs. Compare the hardware code to the codes
+ // for each of these triggers to determine which
+ // it this parameter entry represents and then set
+ // its value appropriately.
for (int ii = 0; ii < pairsIOsrc.length; ii++) {
if(trig == singlesIOsrc[ii]) {
singlesEn[ii] = true;
@@ -160,50 +308,60 @@
}
}
}
-
- // GENERAL CASE:
- // Append trigger# onto key:
+
+ // GENERAL CASE: Basic Parameter
+ // This indicates a regular parameter that does not
+ // require any special parsing.
if(vals.size() > 1 && key.startsWith("SSP")) {
+ // List the parameter by "[ROW NAME]_[KEY]" and
+ // remove the key so that only the values remain.
key += "_" + vals.remove(0);
}
- // dump it into the map:
+
+ // Add the parameter key and its values to the map.
configMap.put(key, vals);
}
}
}
- /*
- * This function parses the config map for the cases where the
- * config string has a simple format:
- * TAG VALUE
- * TAG TRIGGER VALUES
+ /**
+ * Parses the configuration parameter map entries and extracts the
+ * parameter values for those parameters which have the standard
+ * format of <code>[PARAMETER KEY] --> { [PARAMETER VALUES] }</code>.
*/
public void parseConfigMap() {
- fadcNSA = Integer.valueOf(getConfig("FADC250_NSA", 0));
- fadcNSB = Integer.valueOf(getConfig("FADC250_NSB", 0));
- fadcNPEAK = Integer.valueOf(getConfig("FADC250_NPEAK", 0));
- fadcMODE = Integer.valueOf(getConfig("FADC250_MODE", 0));
- fadcWIDTH = Integer.valueOf(getConfig("FADC250_W_WIDTH", 0));
- fadcOFFSET = Integer.valueOf(getConfig("FADC250_W_OFFSET", 0));
-
- gtpMinSeedEnergy = Integer.valueOf(getConfig("GTP_CLUSTER_PULSE_THRESHOLD", 0));
- gtpWindowBefore = Integer.valueOf(getConfig("GTP_CLUSTER_PULSE_COIN", 0));
- gtpWindowAfter = Integer.valueOf(getConfig("GTP_CLUSTER_PULSE_COIN", 1));
-
+ // Parse simple FADC data.
+ fadcNSA = Integer.valueOf(getConfigParameter("FADC250_NSA", 0));
+ fadcNSB = Integer.valueOf(getConfigParameter("FADC250_NSB", 0));
+ fadcNPEAK = Integer.valueOf(getConfigParameter("FADC250_NPEAK", 0));
+ fadcMODE = Integer.valueOf(getConfigParameter("FADC250_MODE", 0));
+ fadcWIDTH = Integer.valueOf(getConfigParameter("FADC250_W_WIDTH", 0));
+ fadcOFFSET = Integer.valueOf(getConfigParameter("FADC250_W_OFFSET", 0));
+
+ // Parse GTP data.
+ gtpMinSeedEnergy = Integer.valueOf(getConfigParameter("GTP_CLUSTER_PULSE_THRESHOLD", 0));
+ gtpWindowBefore = Integer.valueOf(getConfigParameter("GTP_CLUSTER_PULSE_COIN", 0));
+ gtpWindowAfter = Integer.valueOf(getConfigParameter("GTP_CLUSTER_PULSE_COIN", 1));
+
+ // Parse trigger data.
for(int ii = 0; ii < 2; ii++) {
+ // Check singles trigger cuts enabled status.
singlesNhitsEn[ii] = getBoolConfigSSP(ii, "SINGLES_NMIN", 1);
singlesEnergyMinEn[ii] = getBoolConfigSSP(ii, "SINGLES_EMIN", 1);
singlesEnergyMaxEn[ii] = getBoolConfigSSP(ii, "SINGLES_EMAX", 1);
+ // Check pair trigger cuts enabled status.
pairsEnergySumMaxMinEn[ii] = getBoolConfigSSP(ii, "PAIRS_SUMMAX_MIN", 2);
pairsEnergyDiffEn[ii] = getBoolConfigSSP(ii, "PAIRS_DIFFMAX", 1);
pairsCoplanarityEn[ii] = getBoolConfigSSP(ii, "PAIRS_COPLANARITY", 1);
pairsEnergyDistEn[ii] = getBoolConfigSSP(ii, "PAIRS_ENERGYDIST", 2);
+ // Get the singles trigger cuts.
singlesNhits[ii] = getIntConfigSSP(ii, "SINGLES_NMIN", 0);
singlesEnergyMin[ii] = getIntConfigSSP(ii, "SINGLES_EMIN", 0);
singlesEnergyMax[ii] = getIntConfigSSP(ii, "SINGLES_EMAX", 0);
+ // Get the pair trigger cuts.
pairsNhitsMin[ii] = getIntConfigSSP(ii, "PAIRS_NMIN", 0);
pairsEnergyMin[ii] = getIntConfigSSP(ii, "PAIRS_EMIN", 0);
pairsEnergyMax[ii] = getIntConfigSSP(ii, "PAIRS_EMAX", 0);
@@ -217,20 +375,18 @@
}
}
-
-
- /*
- * UNFINISHED.
- * This is a fixer-upper for before we had the full config in EVIO
- * or when there was a bug in it.
+ /**
+ * Method corrects parameter data for runs that either did not
+ * correctly record the full configuration data or were bugged.
+ * It populates missing fields with a zero value entry.
+ * @param runNumber - The run number for the current run. This is
+ * used to determine if the run is a "bugged" run.
*/
private void fixConfigMap2014Run(int runNumber) {
+ // If this is a good run, noting should be done. Return.
if(runNumber > 3470 || runNumber < 3100) { return; }
- // TODO: port datacat/python/engrun/engrun_metadata.py
- // 1. SET GTP SETTINGS MANUALLY BASED ON RUN NUMBER
- // 2. FIX SINGLES_NMIN prior to 3312
- for (String key : configMap.keySet()) {
- }
+
+ // Populate missing GTP entries.
List<String> tmp = new ArrayList<String>();
tmp.add("0");
tmp.add("0");
@@ -238,41 +394,90 @@
tmp.add("0");
configMap.put("GTP_CLUSTER_THRESH" ,tmp);
configMap.put("GTP_TIMEDIFF", tmp);
- }
-
- /*
- * These treat the FADC config lines with 16+1 columns.
- * Must keep track of most recent FADC250_SLOT tag, since it's
- * not on the line with the data.
+
+ // TODO: Port datacat/python/engrun/engrun_metadata.py
+ // 1. SET GTP SETTINGS MANUALLY BASED ON RUN NUMBER
+ // 2. FIX SINGLES_NMIN prior to 3312
+ }
+
+ /**
+ * Parses FADC configuration parameter entries. These all have 17
+ * lines, the first of which is the parameter key and the subsequent
+ * being parameter values corresponding to the 16 FADC channels for
+ * the indicated FADC slot. These entries contain thresholds, gains,
+ * and pedestals.
+ * @param crate - The crate associated with this parameter entry.
+ * @param key - The parameter key.
+ * @param vals - A list of 16 values with indices corresponding to
+ * the FADC channel with which they are associated.
*/
private void parseFADC(int crate, String key, List<String> vals) {
- // System.out.println(crate);
- if (key.equals("FADC250_SLOT")) {
+ // The FADC slot is not stored on the same line as the other
+ // data and must be parsed and retained, as it is necessary
+ // for handling the subsequent lines. If this line is the
+ // FADC slot, store it.
+ if(key.equals("FADC250_SLOT")) {
thisFadcSlot = Integer.valueOf(vals.get(0));
}
- else if (key.equals("FADC250_ALLCH_TET")) {
+
+ // Parse the channel thresholds.
+ else if(key.equals("FADC250_ALLCH_TET")) {
setChannelParsInt(crate, thisFadcSlot, THRESHOLD, vals);
}
- else if (key.equals("FADC250_ALLCH_PED")) {
+
+ // Parse the channel pedestals.
+ else if(key.equals("FADC250_ALLCH_PED")) {
setChannelParsFloat(crate, thisFadcSlot, PEDESTAL, vals);
}
- else if (key.equals("FADC250_ALLCH_GAIN")) {
+
+ // Parse the channel gains.
+ else if(key.equals("FADC250_ALLCH_GAIN")) {
setChannelParsFloat(crate, thisFadcSlot, GAIN, vals);
}
}
- private void setChannelParsFloat(int crate, int slot, Map<EcalChannel, Float>map, List<String> vals) {
- for (int ii = 0; ii < 16; ii++) {
- map.put(findChannel(crate, slot, ii),Float.valueOf(vals.get(ii)));
- }
- }
-
- private void setChannelParsInt(int crate, int slot, Map<EcalChannel, Integer>map, List<String> vals) {
- for (int ii = 0; ii < 16; ii++) {
- map.put(findChannel(crate, slot, ii),Integer.valueOf(vals.get(ii)));
- }
- }
-
+ /**
+ * Takes a list of 16 values (in argument <code>vals</code>) and
+ * maps the appropriate database calorimeter channel to the list
+ * value. This assumes that the <code>String</code> values should
+ * be parsed to <code>Float</code> objects.
+ * @param crate - The calorimeter crate associated with the values.
+ * @param slot - The FADC slot associated with the values.
+ * @param map - The map in which to place the values.
+ * @param vals - A <code>List</code> of 16 <code>String</code>
+ * objects representing the channel values. This should correspond
+ * to FADC channels 0 - 15.
+ */
+ private void setChannelParsFloat(int crate, int slot, Map<EcalChannel, Float> map, List<String> vals) {
+ // Iterate over each channel and map the database channel object
+ // to the corresponding list value.
+ for(int ii = 0; ii < 16; ii++) {
+ map.put(findChannel(crate, slot, ii), Float.valueOf(vals.get(ii)));
+ }
+ }
+
+ /**
+ * Takes a list of 16 values (in argument <code>vals</code>) and
+ * maps the appropriate database calorimeter channel to the list
+ * value. This assumes that the <code>String</code> values should
+ * be parsed to <code>Integer</code> objects.
+ * @param crate - The calorimeter crate associated with the values.
+ * @param slot - The FADC slot associated with the values.
+ * @param map - The map in which to place the values.
+ * @param vals - A <code>List</code> of 16 <code>String</code>
+ * objects representing the channel values.
+ */
+ private void setChannelParsInt(int crate, int slot, Map<EcalChannel, Integer> map, List<String> vals) {
+ // Iterate over each channel and map the database channel object
+ // to the corresponding list value.
+ for(int ii = 0; ii < 16; ii++) {
+ map.put(findChannel(crate, slot, ii), Integer.valueOf(vals.get(ii)));
+ }
+ }
+
+ /**
+ * Prints the mapped parameter keys and values to the terminal.
+ */
public void printMap() {
System.out.print("\nTriggerConfigMap::::::::::::::::::::::::::::\n");
for (String key : configMap.keySet()) {
@@ -285,8 +490,10 @@
System.out.println("::::::::::::::::::::::::::::::::::::::::::::");
}
- public void printVars()
- {
+ /**
+ * Prints the parsed parameter values to the terminal.
+ */
+ public void printVars() {
System.out.println("\nTriggerConfigVars%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
System.out.println();
System.out.println(String.format("GTPMINSEED: %d", gtpMinSeedEnergy));
@@ -300,7 +507,6 @@
System.out.println(String.format("FADC250_WIDTH: %d", fadcWIDTH));
System.out.println(String.format("FADC250_OFFSET: %d", fadcOFFSET));
for(EcalChannel cc : ecalConditions.getChannelCollection()) {
- //System.out.print(String.format("SLOT%d CHAN%d --",cc.getSlot(),cc.getChannel()));
if(!PEDESTAL.containsKey(cc)) {
System.out.println("\nP !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
@@ -310,8 +516,6 @@
if(!GAIN.containsKey(cc)) {
System.out.println("\nG !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
- //System.out.println(String.format(" %f %d %f",
- // PEDESTAL.get(cc),THRESHOLD.get(cc),GAIN.get(cc)));
}
System.out.println();
@@ -345,55 +549,138 @@
System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
}
- /*
- * Parsing wrappers to make rest of code easier.
+ /**
+ * Gets an SSP parameter value using a shortened version of the
+ * full parameter key and parses it as a <code>float</code>.
+ * @param itrig - The number of the trigger for which to obtain
+ * the parameter value.
+ * @param stub - The shortened version of the parameter key. This
+ * corresponds to "SSP_HPS_[STUB]_[TRIGGER NUMBER]".
+ * @param ival - The index of the value that is to be obtained.
+ * @return Returns the requested value if it exists. Otherwise, a
+ * value of <code>0</code> is returned and a message is logged.
*/
public float getFloatConfigSSP(int itrig, String stub, int ival) {
return Float.valueOf(getConfigSSP(itrig, stub, ival));
}
+ /**
+ * Gets an SSP parameter value using a shortened version of the
+ * full parameter key and parses it as a <code>int</code>.
+ * @param itrig - The number of the trigger for which to obtain
+ * the parameter value.
+ * @param stub - The shortened version of the parameter key. This
+ * corresponds to "SSP_HPS_[STUB]_[TRIGGER NUMBER]".
+ * @param ival - The index of the value that is to be obtained.
+ * @return Returns the requested value if it exists. Otherwise, a
+ * value of <code>0</code> is returned and a message is logged.
+ */
public int getIntConfigSSP(int itrig, String stub, int ival) {
return Integer.valueOf(getConfigSSP(itrig, stub, ival));
}
+ /**
+ * Gets an SSP parameter value using a shortened version of the
+ * full parameter key and parses it as a <code>boolean</code>.
+ * @param itrig - The number of the trigger for which to obtain
+ * the parameter value.
+ * @param stub - The shortened version of the parameter key. This
+ * corresponds to "SSP_HPS_[STUB]_[TRIGGER NUMBER]".
+ * @param ival - The index of the value that is to be obtained.
+ * @return Returns the requested value if it exists. Otherwise, a
+ * value of <code>false</code> is returned and a message is logged.
+ */
public boolean getBoolConfigSSP(int itrig, String stub, int ival) {
return "1".equals(getConfigSSP(itrig, stub, ival));
}
+ /**
+ * Gets an SSP parameter value using a shortened version of the
+ * full parameter key.
+ * @param itrig - The number of the trigger for which to obtain
+ * the parameter value.
+ * @param stub - The shortened version of the parameter key. This
+ * corresponds to "SSP_HPS_[STUB]_[TRIGGER NUMBER]".
+ * @param ival - The index of the value that is to be obtained.
+ * @return Returns the requested value if it exists. Otherwise, a
+ * value of <code>"0"</code> is returned and a message is logged.
+ */
public String getConfigSSP(int itrig, String stub, int ival) {
String key = "SSP_HPS_" + stub + "_" + itrig;
- return getConfig(key,ival);
- }
-
- public String getConfig(String key, int ival) {
- if (configMap.containsKey(key)) {
+ return getConfigParameter(key, ival);
+ }
+
+ /**
+ * Gets a parameter value associated with a parameter key.
+ * @param key - The parameter key to which the value belongs.
+ * @param ival - The index of the desired parameter value.
+ * @return Returns the requested parameter value if it exists and
+ * returns <code>"0"</code> otherwise. In the event that a parameter
+ * can not be found, an error message is passed to the logger.
+ */
+ public String getConfigParameter(String key, int ival) {
+ // Check the parameter map for the requested parameter key.
+ if(configMap.containsKey(key)) {
+ // Get the list of values associated with this parameter key.
List<String> vals = configMap.get(key);
- if (ival < vals.size()) {
- return configMap.get(key).get(ival);
- } else {
- Logger.getLogger(this.getClass().getName()).log(Level.SEVERE,
- "ConfigMap TOO SHORT: " + ival + " " + configMap.get(key));
+
+ // Check that the list of values contains a parameter for
+ // the requested parameter index. If it does, return it.
+ if (ival < vals.size()) { return configMap.get(key).get(ival); }
+
+ // Otherwise, an error has occurred. Log this and return the
+ // default value of zero.
+ else {
+ Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "ConfigMap TOO SHORT: " + ival + " " + configMap.get(key));
return "0";
}
- } else {
- // this is only necessarily an error if we've read 3 banks:
+ }
+
+ // If the key is not present...
+ else {
+ // If more than 2 banks have been read, the absence of a
+ // key represents an error. Log that this has occurred.
if(nBanks > 2) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "ConfigMap MISSING KEY: " + key);
}
+
+ // Return a default value of zero.
return "0";
}
}
+ /**
+ * Gets the database calorimeter channel for a channel defined by
+ * a crate number, FADC slot, and FADC channel.
+ * @param crate - The crate number.
+ * @param fadcSlot - The FADC slot.
+ * @param fadcChan - The FADC channel.
+ * @return Returns the database channel as a <code>EcalChannel</code>
+ * if it exists, and <code>null</code> if it does not.
+ */
public EcalChannel findChannel(int crate, int fadcSlot, int fadcChan) {
+ // Search through the database channels for a channel that
+ // matches the the argument parameters.
for (EcalChannel cc : channels) {
- // EcalChannel follows different convention on crate numbering:
- if ((cc.getCrate() - 1) * 2 == crate - 37 && cc.getSlot() == fadcSlot && cc.getChannel() == fadcChan) {
+ // A channel matches the argument if the slot and channel
+ // values are the same. Crate number must also match, but
+ // note that EcalChannel follows a different convention
+ // with respect to crate numbering.
+ if( ((cc.getCrate() - 1) * 2 == crate - 37) && (cc.getSlot() == fadcSlot) && (cc.getChannel() == fadcChan) ) {
return cc;
}
}
+
+ // If no matching channel is found, return null.
return null;
}
+ /**
+ * Gets the database crystal channel object based on the crystal's
+ * numerical index.
+ * @param channel_id - The crystal index.
+ * @return Returns the channel as an <code>EcalChannel</code>.
+ */
public EcalChannel findChannel(int channel_id) {
return ecalConditions.getChannelCollection().findChannel(channel_id);
}
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/AbstractIntData.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/AbstractIntData.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/AbstractIntData.java Thu Aug 6 17:19:42 2015
@@ -4,57 +4,64 @@
import org.lcsim.event.GenericObject;
/**
- * GenericObject representation of an INT32/UINT32 bank read from EVIO. The bank
- * header tag identifies the type of data, and is stored as the first int in the
- * GenericObject. The contents of the bank are the remaining N-1 ints.
- * Constructors are provided from int[] (for reading from EVIO) and from
- * GenericObject (for reading from LCIO).
- *
+ * Class <code>GenericObject</code> representation of an INT32/UINT32
+ * bank read from EvIO. The bank header tag identifies the type of
+ * data, and is stored as the first int in the <code>GenericObject</code>.
+ * The contents of the bank are the remaining N-1 <code>int</code>
+ * primitives. Constructors are provided from <code>int[]</code> (for
+ * reading from EvIO) and from <code>GenericObject</code> (for reading
+ * from LCIO).<br/>
+ * <br/>
* Subclasses must implement the two constructors and two abstract methods, plus
* whatever methods are needed to access the parsed data.
*
* @author Sho Uemura <[log in to unmask]>
- * @version $Id: $
+ * @see GenericObject
*/
public abstract class AbstractIntData implements GenericObject {
-
+ /** The data bank. */
protected int[] bank;
-
+
/**
- * Constructor from EVIO int bank. Bank tag must be checked by EVIO reader
- * before the constructor is called.
- *
- * @param bank
+ * Constructs an <code>AbstractIntData</code> from a raw EvIO integer
+ * bank. It is expected that the EvIO reader will verify that the
+ * bank tag is the appropriate type before calling the constructor.
+ * @param bank - An EvIO bank of <code>int</code> data.
*/
protected AbstractIntData(int[] bank) {
- if (bank == null) {
- this.bank = new int[0];
- } else {
- this.bank = Arrays.copyOf(bank, bank.length);
- }
+ if(bank == null) { this.bank = new int[0]; }
+ else { this.bank = Arrays.copyOf(bank, bank.length); }
}
-
+
/**
- * Constructor from LCIO GenericObject. Checks the bank tag; subclass
- * constructor must set the expected value of the tag.
- *
- * @param data
- * @param expectedTag
+ * Create an <code>AbstractIntData</code> object from an LCIO
+ * <code>genericObject</code>. Constructor requires that the
+ * <code>GenericObject</code> tag match the expected EvIO header
+ * tag type as defined by the implementing class.
+ * @param data - The source data bank.
+ * @param expectedTag - The required EvIO bank header tag.
*/
protected AbstractIntData(GenericObject data, int expectedTag) {
- if (getTag(data) != expectedTag) {
+ // If the EvIO bank header tag is not the required type,
+ // produce an exception.
+ if(getTag(data) != expectedTag) {
throw new RuntimeException("expected tag " + expectedTag + ", got " + getTag(data));
}
+
+ // Otherwise, store the bank.
this.bank = getBank(data);
}
-
+
+ /**
+ * Gets the entire, unparsed integer data bank from the object.
+ * @return Returns the data as an <code>int[]</code> array.
+ */
public int[] getBank() {
return bank;
}
-
+
/**
* Return the int bank of an AbstractIntData read from LCIO.
- *
* @param object
* @return
*/
@@ -66,55 +73,55 @@
}
return bank;
}
-
+
/**
- * Return a single value from the int bank of an AbstractIntData.
- *
- * @param object
- * @param index
- * @return
+ * Return a single value from the integer bank of an
+ * <code>AbstractIntData</code>.
+ * @param object - The bank from which to obtain the data.
+ * @param index - The index of the data in the bank.
+ * @return Returns the requested entry from the integer bank.
*/
public static int getBankInt(GenericObject object, int index) {
return object.getIntVal(index + 1);
}
-
+
/**
- * Returns the EVIO bank header tag expected for this data.
- *
- * @return
+ * Returns the EvIO bank header tag expected for this data.
+ * @return Returns the tag as an <code>int</code> primitive.
*/
public abstract int getTag();
-
+
/**
* Returns the EVIO bank tag for a data object.
- *
- * @param data
- * @return
+ * @param data - A <code>GenericObject</code> representing an integer
+ * data bank.
+ * @return Returns the EvIO tag identifying the type of bank the object
+ * represents.
*/
public static int getTag(GenericObject data) {
return data.getIntVal(0);
}
-
+
/**
* Parses the bank so the object can be used in analysis.
*/
protected abstract void decodeData();
-
+
@Override
public int getNInt() {
return bank.length + 1;
}
-
+
@Override
public int getNFloat() {
return 0;
}
-
+
@Override
public int getNDouble() {
return 0;
}
-
+
@Override
public int getIntVal(int index) {
if (index == 0) {
@@ -122,19 +129,19 @@
}
return bank[index - 1];
}
-
+
@Override
public float getFloatVal(int index) {
throw new UnsupportedOperationException("No float values in " + this.getClass().getSimpleName());
}
-
+
@Override
public double getDoubleVal(int index) {
throw new UnsupportedOperationException("No double values in " + this.getClass().getSimpleName());
}
-
+
@Override
public boolean isFixedSize() {
return true;
}
-}
+}
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/SSPCluster.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/SSPCluster.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/SSPCluster.java Thu Aug 6 17:19:42 2015
@@ -7,7 +7,14 @@
/**
* Class <code>SSPCluster</code> stores all of the information on
- * clusters that is reported by the SSP.
+ * clusters that is reported by the SSP. SSP clusters store:
+ * <ul><li>Cluster center x-index</li>
+ * <li>Cluster center y-index</li>
+ * <li>Cluster total energy</li>
+ * <li>Cluster hit count</li>
+ * <li>Cluster time</li></ul>
+ * <code>SSPCluster</code> does not support the ability to track
+ * individual hits that are part of a cluster.
*
* @author Kyle McCarty <[log in to unmask]>
*/
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/TIData.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/TIData.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/TIData.java Thu Aug 6 17:19:42 2015
@@ -2,17 +2,22 @@
import org.lcsim.event.GenericObject;
-//import org.hps.record.evio.EvioEventConstants; // doesn't work
/**
- * TI Trigger Data
+ * Class <code>TIData</code> is an implementation of abstract class
+ * <code>AbstractIntData</code> that represents a TI trigger bit bank.
+ * It contains both a time window length and a set of flags that track
+ * whether a trigger of a given type was registered with the event to
+ * which this bank is attached.
*
* @author Nathan Baltzell <[log in to unmask]>
*/
public class TIData extends AbstractIntData {
-
+ /** The EvIO bank header tag for TI data banks. */
public static final int BANK_TAG = 0xe10a; // EvioEventConstants.TI_TRIGGER_BANK_TAG;
+ /** The expected number of entries in the data bank. */
public static final int BANK_SIZE = 4;
-
+
+ // Store the parsed data bank parameters.
private long time = 0;
private boolean singles0 = false;
private boolean singles1 = false;
@@ -20,69 +25,122 @@
private boolean pairs1 = false;
private boolean calib = false;
private boolean pulser = false;
-
+
+ /**
+ * Creates a <code>TIData</code> bank from a raw EvIO data bank.
+ * It is expected that the EvIO reader will verify that the bank
+ * tag is of the appropriate type.
+ * @param bank - The EvIO data bank.
+ */
public TIData(int[] bank) {
super(bank);
decodeData();
}
-
+
+ /**
+ * Creates a <code>TIData</code> object from an existing LCIO
+ * <code>GenericObject</code>.
+ * @param tiData - The source data bank object.
+ */
public TIData(GenericObject tiData) {
super(tiData, BANK_TAG);
decodeData();
}
-
+
@Override
protected final void decodeData() {
- if (this.bank.length != BANK_SIZE) {
+ // Check that the data bank is the expected size. If not, throw
+ // and exception.
+ if(this.bank.length != BANK_SIZE) {
throw new RuntimeException("Invalid Data Length: " + bank.length);
}
-
+
+ // Check each trigger bit to see if it is active. A value of
+ // 1 indicates a trigger of that type occurred, and 0 that it
+ // did not.
singles0 = ((bank[0] >> 24) & 1) == 1;
singles1 = ((bank[0] >> 25) & 1) == 1;
pairs0 = ((bank[0] >> 26) & 1) == 1;
pairs1 = ((bank[0] >> 27) & 1) == 1;
calib = ((bank[0] >> 28) & 1) == 1;
pulser = ((bank[0] >> 29) & 1) == 1;
-
+
+ // Get the unprocessed start and end times for the bank.
long w1 = bank[2] & 0xffffffffL;
long w2 = bank[3] & 0xffffffffL;
-
+
+ // Process the times into units of clock-cycles.
final long timelo = w1;
final long timehi = (w2 & 0xffff) << 32;
-
- time = 4 * (timelo + timehi); // units ns
+
+ // Store the time difference in nanoseconds.
+ time = 4 * (timelo + timehi);
}
-
+
@Override
public int getTag() {
return BANK_TAG;
}
-
+
+ /**
+ * Gets the time window for the bank.
+ * @return Returns the time window length in nanoseconds.
+ */
public long getTime() {
return time;
}
-
+
+ /**
+ * Indicates whether a singles 0 trigger was registered.
+ * @return Returns <code>true</code> if the trigger occurred, and
+ * <code>false</code> otherwise.
+ */
public boolean isSingle0Trigger() {
return singles0;
}
-
+
+ /**
+ * Indicates whether a singles 1 trigger was registered.
+ * @return Returns <code>true</code> if the trigger occurred, and
+ * <code>false</code> otherwise.
+ */
public boolean isSingle1Trigger() {
return singles1;
}
-
+
+ /**
+ * Indicates whether a pair 0 trigger was registered.
+ * @return Returns <code>true</code> if the trigger occurred, and
+ * <code>false</code> otherwise.
+ */
public boolean isPair0Trigger() {
return pairs0;
}
-
+
+ /**
+ * Indicates whether a pair 1 trigger was registered.
+ * @return Returns <code>true</code> if the trigger occurred, and
+ * <code>false</code> otherwise.
+ */
public boolean isPair1Trigger() {
return pairs1;
}
-
+
+ /**
+ * Indicates whether a cosmic trigger was registered.
+ * @return Returns <code>true</code> if the trigger occurred, and
+ * <code>false</code> otherwise.
+ */
public boolean isCalibTrigger() {
return calib;
}
-
+
+ /**
+ * Indicates whether a random/pulser trigger was registered.
+ * @return Returns <code>true</code> if the trigger occurred, and
+ * <code>false</code> otherwise.
+ */
public boolean isPulserTrigger() {
return pulser;
}
-}
+}
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/TriggerModule.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/TriggerModule.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/triggerbank/TriggerModule.java Thu Aug 6 17:19:42 2015
@@ -20,62 +20,85 @@
* called without initializing an instance of the module.<br/>
* <br/>
* Both <code>Cluster</code> objects and <code>SSPCluster</code> objects
- * are supported.
- *
+ * are supported, except for the seed energy cut, as this value is not
+ * present in <code>SSPCluster</code> objects.<br/>
+ * <br/>
+ * This module supports the following cuts:
+ * <ul><li>Seed Energy Lower Bound</li>
+ * <li>Seed Energy Lower Bound</li>
+ * <li>Seed Energy Upper Bound</li>
+ * <li>Cluster Total Energy Upper Bound</li>
+ * <li>Cluster Total Energy Lower Bound</li>
+ * <li>Cluster Hit Count Lower Bound</li>
+ * <li>Pair Energy Sum Upper Bound</li>
+ * <li>Pair Energy Sum Lower Bound</li>
+ * <li>Pair Energy Difference Upper Bound</li>
+ * <li>Pair Energy Slope Lower Bound</li>
+ * <li>Pair Coplanarity Upper Bound</li>
+ * <li>Pair Time Coincidence Upper Bound</li></ul>
* @author Kyle McCarty <[log in to unmask]>
* @see Cluster
* @see SSPCluster
*/
public final class TriggerModule {
- // The calorimeter mid-plane, defined by the photon beam position
- // (30.52 mrad) at the calorimeter face (z = 1393 mm).
+ /** The calorimeter mid-plane, defined by the photon beam position
+ * (30.52 mrad) at the calorimeter face (z = 1393 mm). */
private static final double ORIGIN_X = 1393.0 * Math.tan(0.03052);
- // Trigger module property names.
/** The value of the parameter "F" in the energy slope equation
- * <code>E_low GeV + R_min mm * F GeV/mm</code>. */
+ * <code>E_low GeV + R_min mm * F GeV/mm</code>. Units are in GeV
+ * / mm. */
public static final String PAIR_ENERGY_SLOPE_F = "pairEnergySlopeF";
/** The lower bound for the pair energy sum cut. The sum of the
- * energies of two clusters must exceed this value to pass the cut. */
+ * energies of two clusters must exceed this value to pass the cut.
+ * Units are in GeV. */
public static final String PAIR_ENERGY_SUM_LOW = "pairEnergySumLow";
/** The upper bound for the pair energy sum cut. The sum of the
- * energies of two clusters must be below this value to pass the cut. */
+ * energies of two clusters must be below this value to pass the
+ * cut. Units are in GeV. */
public static final String PAIR_ENERGY_SUM_HIGH = "pairEnergySumHigh";
/** The threshold for the cluster hit count cut. Clusters must have
* this many hits or more to pass the cut. */
public static final String CLUSTER_HIT_COUNT_LOW = "clusterHitCountLow";
/** The threshold for the energy slope cut. The value of the energy
- * slope equation must exceed this value to pass the cut. */
+ * slope equation must exceed this value to pass the cut. Units are
+ * in GeV. */
public static final String PAIR_ENERGY_SLOPE_LOW = "pairEnergySlopeLow";
/** The bound for the coplanarity cut. The coplanarity angle for
- * the cluster pair must be below this value to pass the cut. */
+ * the cluster pair must be below this value to pass the cut. Units
+ * are in degrees. */
public static final String PAIR_COPLANARITY_HIGH = "pairCoplanarityHigh";
/** The lower bound for the cluster seed energy cut. The seed energy
- * of a cluster must exceed this value to pass the cut. */
+ * of a cluster must exceed this value to pass the cut. Units are in
+ * GeV. */
public static final String CLUSTER_SEED_ENERGY_LOW = "clusterSeedEnergyLow";
/** The upper bound for the cluster seed energy cut. The seed energy
- * of a cluster must be below this value to pass the cut. */
+ * of a cluster must be below this value to pass the cut. Units are
+ * in GeV. */
public static final String CLUSTER_SEED_ENERGY_HIGH = "clusterSeedEnergyHigh";
/** The lower bound for the cluster total energy cut. The energy
* of a cluster must exceed this value to pass the cut. */
public static final String CLUSTER_TOTAL_ENERGY_LOW = "clusterTotalEnergyLow";
/** The upper bound for the cluster total energy cut. The energy
- * of a cluster must be below this value to pass the cut. */
+ * of a cluster must be below this value to pass the cut. Units are
+ * in GeV. */
public static final String CLUSTER_TOTAL_ENERGY_HIGH = "clusterTotalEnergyHigh";
/** The bound for the pair energy difference cut. The absolute value
* of the difference between the energies of the cluster pair must
- * be below this value to pass the cut. */
+ * be below this value to pass the cut. Units are in GeV. */
public static final String PAIR_ENERGY_DIFFERENCE_HIGH = "pairEnergyDifferenceHigh";
/** The maximum amount of time by which two clusters are allowed
- * to be separated. */
+ * to be separated. Units are in ns. */
public static final String PAIR_TIME_COINCIDENCE = "pairTimeCoincidence";
- // Trigger cut settings map.
+ /** Stores each of the cut values used by the module. Map keys are
+ * defined as publicly-accessible static variables in the class. */
private final Map<String, Double> cuts = new HashMap<String, Double>(11);
/**
- * Creates an <code>SSPTriggerModule</code> that accepts all single
- * cluster and cluster pair events.
+ * Creates a default <code>TriggerModule</code>. The cuts are
+ * defined such that all physical clusters (i.e. with energy
+ * above zero) will be accepted.
*/
public TriggerModule() {
// Set the cluster singles cuts to accept all values by default.
@@ -98,21 +121,21 @@
}
/**
- * Creates an <code>SSPTriggerModule</code> that uses the default
- * cut values specified by the argument array. The array should be
- * of size 11. Values are applied in the order:
+ * Creates a <code>TriggerModule</code> with trigger cuts defined
+ * by the argument array. The order of the cut value arguments are
+ * as follows:
* <ul>
- * <li>Cluster Hit Count Lower Bound</li>
- * <li>Cluster Seed Energy Lower Bound</li>
- * <li>Cluster Seed Energy Upper Bound</li>
- * <li>Cluster Seed Total Lower Bound</li>
- * <li>Cluster Seed Total Upper Bound</li>
- * <li>Pair Energy Sum Lower Bound</li>
- * <li>Pair Energy Sum Upper Bound</li>
- * <li>Pair Energy Difference Upper Bound</li>
- * <li>Pair Energy Slope Lower Bound</li>
- * <li>Pair Coplanarity Upper Bound</li>
- * <li>Pair Energy Slope Parameter F</li>
+ * <li>Cluster Hit Count Lower Bound (Hits)</li>
+ * <li>Cluster Seed Energy Lower Bound (GeV)</li>
+ * <li>Cluster Seed Energy Upper Bound (GeV)</li>
+ * <li>Cluster Seed Total Lower Bound (GeV)</li>
+ * <li>Cluster Seed Total Upper Bound (GeV)</li>
+ * <li>Pair Energy Sum Lower Bound (GeV)</li>
+ * <li>Pair Energy Sum Upper Bound (GeV)</li>
+ * <li>Pair Energy Difference Upper Bound (GeV)</li>
+ * <li>Pair Energy Slope Lower Bound (GeV)</li>
+ * <li>Pair Coplanarity Upper Bound (Degrees)</li>
+ * <li>Pair Energy Slope Parameter F (GeV / mm)</li>
* </ul>
*/
public TriggerModule(double... cutValues) {
@@ -139,9 +162,11 @@
/**
* Gets the value of the requested cut, if it exists.
- * @param cut - The identifier of the cut.
+ * @param cut - The identifier of the cut. This can be obtained
+ * through the publicly-accessible static identifiers in this class.
* @return Returns the cut value as a <code>double</code>.
- * @throws IllegalArgumentException Occurs if the cut does not exist.
+ * @throws IllegalArgumentException Occurs if the cut identifier
+ * specified in the argument is not valid.
*/
public double getCutValue(String cut) throws IllegalArgumentException {
// Try to get the indicated cut.
@@ -156,8 +181,9 @@
/**
* Loads triggers settings from the DAQ configuration for a singles
- * trigger. Pair trigger settings will be set to accept all possible
- * values, while singles trigger settings will
+ * trigger. Singles trigger cuts will be set to match those defined
+ * in the configuration object, while pair trigger cuts will be set
+ * to accept all possible clusters.
* @param config - The DAQ configuration settings.
*/
public void loadDAQConfiguration(SinglesTriggerConfig config) {
@@ -205,11 +231,14 @@
}
/**
- * Sets the value of the indicated cut to a new value.
+ * Sets the value of the cut specified by the identifier given in
+ * the argument to the specified value.
* @param cut - The identifier of the cut to which the new value
- * should be assigned.
+ * should be assigned. These can be obtained as publicly-accessible
+ * static variables from this class.
* @param value - The new cut value.
- * @throws IllegalArgumentException Occurs if the cut does not exist.
+ * @throws IllegalArgumentException Occurs if the argument cut
+ * identifier is not valid.
*/
public void setCutValue(String cut, double value) throws IllegalArgumentException {
// Make sure that the cut exists. If it does, change it to the
@@ -230,6 +259,7 @@
* @param cutValues - A string representing the cuts values. This
* must be formatted in the style of "Emin Emax Nmin ...".
*/
+ // TODO: Specify in JavaDoc what the order of these arguments is.
public void setCutValues(boolean isSingles, String cutValues) {
// Make sure that the string is not null.
if(cutValues == null) {
@@ -283,8 +313,8 @@
}
/**
- * Checks whether the argument cluster possesses the minimum
- * allowed hits.
+ * Checks whether a cluster passes the cluster hit count cut. This
+ * is defined as <code>N_hits >= CLUSTER_HIT_COUNT_LOW</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -294,8 +324,8 @@
}
/**
- * Checks whether the argument cluster possesses the minimum
- * allowed hits.
+ * Checks whether a cluster passes the cluster hit count cut. This
+ * is defined as <code>N_hits >= CLUSTER_HIT_COUNT_LOW</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -305,8 +335,9 @@
}
/**
- * Checks whether the argument cluster seed hit falls within the
- * allowed seed hit energy range.
+ * Checks whether a cluster passes the seed energy cut. This is
+ * defined as <code>CLUSTER_SEED_ENERGY_LOW <= E_seed <=
+ * CLUSTER_SEED_ENERGY_HIGH</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -316,8 +347,8 @@
}
/**
- * Checks whether the argument cluster seed hit falls below the
- * allowed seed hit energy upper bound.
+ * Checks whether a cluster passes the seed energy upper bound cut.
+ * This is defined as <code>E_seed <= CLUSTER_SEED_ENERGY_HIGH</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -327,8 +358,8 @@
}
/**
- * Checks whether the argument cluster seed hit falls above the
- * allowed seed hit energy lower bound.
+ * Checks whether a cluster passes the seed energy lower bound cut.
+ * This is defined as <code>CLUSTER_SEED_ENERGY_LOW <= E_seed</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -338,8 +369,9 @@
}
/**
- * Checks whether the argument cluster falls within the allowed
- * cluster total energy range.
+ * Checks whether a cluster passes the cluster total energy cut.
+ * This is defined as <code>CLUSTER_TOTAL_ENERGY_LOW <= E_cluster
+ * <= CLUSTER_TOTAL_ENERGY_HIGH</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -349,8 +381,9 @@
}
/**
- * Checks whether the argument cluster falls below the allowed
- * cluster total energy upper bound.
+ * Checks whether a cluster passes the cluster total energy upper
+ * bound cut. This is defined as <code>E_cluster <=
+ * CLUSTER_TOTAL_ENERGY_HIGH</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -360,8 +393,9 @@
}
/**
- * Checks whether the argument cluster falls above the allowed
- * cluster total energy lower bound.
+ * Checks whether a cluster passes the cluster total energy lower
+ * bound cut. This is defined as <code>CLUSTER_TOTAL_ENERGY_LOW <=
+ * E_cluster</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -371,8 +405,9 @@
}
/**
- * Checks whether the argument cluster falls within the allowed
- * cluster total energy range.
+ * Checks whether a cluster passes the cluster total energy cut.
+ * This is defined as <code>CLUSTER_TOTAL_ENERGY_LOW <= E_cluster
+ * <= CLUSTER_TOTAL_ENERGY_HIGH</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -382,8 +417,9 @@
}
/**
- * Checks whether the argument cluster falls below the allowed
- * cluster total energy upper bound.
+ * Checks whether a cluster passes the cluster total energy upper
+ * bound cut. This is defined as <code>E_cluster <=
+ * CLUSTER_TOTAL_ENERGY_HIGH</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -393,8 +429,9 @@
}
/**
- * Checks whether the argument cluster falls above the allowed
- * cluster total energy lower bound.
+ * Checks whether a cluster passes the cluster total energy lower
+ * bound cut. This is defined as <code>CLUSTER_TOTAL_ENERGY_LOW <=
+ * E_cluster</code>.
* @param cluster - The cluster to check.
* @return Returns <code>true</code> if the cluster passes the cut
* and <code>false</code> if the cluster does not.
@@ -409,6 +446,7 @@
* be calculated.
* @return Returns displacement of the cluster.
*/
+ // TODO: What defines cluster distance?
public static double getClusterDistance(Cluster cluster) {
// Get the variables from the cluster.
double x = getClusterX(cluster);
@@ -419,12 +457,23 @@
}
/**
- * Gets the size of a cluster.
+ * Gets the number of hits in a cluster, as used in the cluster
+ * hit count cut.
* @param cluster - The cluster for which to obtain the size.
* @return Returns the size as an <code>int</code>.
*/
public static final double getClusterHitCount(Cluster cluster) {
return cluster.getCalorimeterHits().size();
+ }
+
+ /**
+ * Gets the number of hits in a cluster, as used in the cluster
+ * hit count cut.
+ * @param cluster - The cluster for which to obtain the size.
+ * @return Returns the size as an <code>int</code>.
+ */
+ public static final double getClusterHitCount(SSPCluster cluster) {
+ return cluster.getHitCount();
}
/**
@@ -442,12 +491,23 @@
}
/**
- * Gets the time-stamp of a cluster.
+ * Gets the time-stamp of a cluster, as used in the time-coincidence
+ * cut.
* @param cluster - The cluster for which to obtain the time.
* @return Returns the time as a <code>double</code>.
*/
public static final double getClusterTime(Cluster cluster) {
return getClusterSeedHit(cluster).getTime();
+ }
+
+ /**
+ * Gets the time-stamp of a cluster, as used in the time-coincidence
+ * cut.
+ * @param cluster - The cluster for which to obtain the time.
+ * @return Returns the time as a <code>double</code>.
+ */
+ public static final double getClusterTime(SSPCluster cluster) {
+ return cluster.getTime();
}
/**
@@ -471,12 +531,21 @@
}
/**
- * Gets the x-index of a cluster.
+ * Gets the x-index of a cluster's
* @param cluster - The cluster for which to obtain the index.
* @return Returns the index as an <code>int</code>.
*/
public static final int getClusterXIndex(Cluster cluster) {
return getClusterSeedHit(cluster).getIdentifierFieldValue("ix");
+ }
+
+ /**
+ * Gets the x-index of a cluster's
+ * @param cluster - The cluster for which to obtain the index.
+ * @return Returns the index as an <code>int</code>.
+ */
+ public static final int getClusterXIndex(SSPCluster cluster) {
+ return cluster.getXIndex();
}
/**
@@ -509,6 +578,15 @@
}
/**
+ * Gets the y-index of a cluster.
+ * @param cluster - The cluster for which to obtain the index.
+ * @return Returns the index as an <code>int</code>.
+ */
+ public static final int getClusterYIndex(SSPCluster cluster) {
+ return cluster.getYIndex();
+ }
+
+ /**
* Gets the z-position of a cluster in millimeters in the hardware
* coordinate system.
* @param cluster - The cluster of which to get the z-position.
@@ -529,27 +607,30 @@
}
/**
- * Gets the value used for the cluster total energy cut.
+ * Gets the value used for the cluster total energy cut. This is
+ * the energy of the entire cluster.
* @param cluster - The cluster from which the value should be
* derived.
- * @return Returns the energy of the entire cluster in GeV.
+ * @return Returns the cluster energy in GeV.
*/
public static double getValueClusterTotalEnergy(Cluster cluster) {
return cluster.getEnergy();
}
/**
- * Gets the value used for the cluster total energy cut.
+ * Gets the value used for the cluster total energy cut. This is
+ * the energy of the entire cluster.
* @param cluster - The cluster from which the value should be
* derived.
- * @return Returns the energy of the entire cluster in GeV.
+ * @return Returns the cluster energy in GeV.
*/
public static double getValueClusterTotalEnergy(SSPCluster cluster) {
return cluster.getEnergy();
}
/**
- * Gets the value used for the cluster hit count cut.
+ * Gets the value used for the cluster hit count cut. This is the
+ * total number of hits included in the cluster.
* @param cluster - The cluster from which the value should be
* derived.
* @return Returns the number of hits in the cluster.
@@ -559,7 +640,8 @@
}
/**
- * Gets the value used for the cluster hit count cut.
+ * Gets the value used for the cluster hit count cut. This is the
+ * total number of hits included in the cluster.
* @param cluster - The cluster from which the value should be
* derived.
* @return Returns the number of hits in the cluster.
@@ -587,14 +669,15 @@
public static double getValueCoplanarity(Cluster[] clusterPair) {
// Get the variables used by the calculation.
double x[] = { getClusterX(clusterPair[0]), getClusterX(clusterPair[1]) };
- double z[] = { getClusterZ(clusterPair[0]), getClusterZ(clusterPair[1]) };
+ double y[] = { getClusterY(clusterPair[0]), getClusterY(clusterPair[1]) };
// Return the calculated value.
- return getValueCoplanarity(x, z);
- }
-
- /**
- * Calculates the value used by the coplanarity cut.
+ return getValueCoplanarity(x, y);
+ }
+
+ /**
+ * Calculates the value used by the coplanarity cut. A value of zero
+ * represents clusters in the same plane.
* @param clusterPair - The cluster pair from which the value should
* be calculated.
* @return Returns the cut value.
@@ -602,10 +685,10 @@
public static double getValueCoplanarity(SSPCluster[] clusterPair) {
// Get the variables used by the calculation.
double x[] = { getClusterX(clusterPair[0]), getClusterX(clusterPair[1]) };
- double z[] = { getClusterZ(clusterPair[0]), getClusterZ(clusterPair[1]) };
+ double y[] = { getClusterY(clusterPair[0]), getClusterY(clusterPair[1]) };
// Return the calculated value.
- return getValueCoplanarity(x, z);
+ return getValueCoplanarity(x, y);
}
/**
@@ -667,10 +750,10 @@
// Get the variables used by the calculation.
double[] energy = { clusterPair[0].getEnergy(), clusterPair[1].getEnergy() };
double x[] = { getClusterX(clusterPair[0]), getClusterX(clusterPair[1]) };
- double z[] = { getClusterZ(clusterPair[0]), getClusterZ(clusterPair[1]) };
+ double y[] = { getClusterY(clusterPair[0]), getClusterY(clusterPair[1]) };
// Perform the calculation.
- return getValueEnergySlope(energy, x, z, energySlopeParamF);
+ return getValueEnergySlope(energy, x, y, energySlopeParamF);
}
/**
@@ -685,10 +768,10 @@
// Get the variables used by the calculation.
double[] energy = { clusterPair[0].getEnergy(), clusterPair[1].getEnergy() };
double x[] = { getClusterX(clusterPair[0]), getClusterX(clusterPair[1]) };
- double z[] = { getClusterZ(clusterPair[0]), getClusterZ(clusterPair[1]) };
+ double y[] = { getClusterY(clusterPair[0]), getClusterY(clusterPair[1]) };
// Perform the calculation.
- return getValueEnergySlope(energy, x, z, energySlopeParamF);
+ return getValueEnergySlope(energy, x, y, energySlopeParamF);
}
/**
@@ -773,7 +856,7 @@
/**
* Checks if a cluster pair is coplanar to the beam within a given
- * angle.
+ * angle. This is defined as <code>θ <= PAIR_COPLANARITY_HIGH</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -784,7 +867,7 @@
/**
* Checks if a cluster pair is coplanar to the beam within a given
- * angle.
+ * angle. This is defined as <code>θ <= PAIR_COPLANARITY_HIGH</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -795,7 +878,8 @@
/**
* Checks if the energy difference between the clusters making up
- * a cluster pair is below an energy difference threshold.
+ * a cluster pair is below an energy difference threshold. This is
+ * defined as <code>|E_1 - E_2| <= PAIR_ENERGY_DIFFERENCE_HIGH</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -806,7 +890,8 @@
/**
* Checks if the energy difference between the clusters making up
- * a cluster pair is below an energy difference threshold.
+ * a cluster pair is below an energy difference threshold. This is
+ * defined as <code>|E_1 - E_2| <= PAIR_ENERGY_DIFFERENCE_HIGH</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -818,7 +903,7 @@
/**
* Requires that the distance from the beam of the lowest energy
* cluster in a cluster pair satisfies the following:<br/>
- * <code>E_low + R_min * F < [ Threshold ]</code>
+ * <code>E_low + R_min * F >= PAIR_ENERGY_SLOPE_LOW</code>
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -830,7 +915,7 @@
/**
* Requires that the distance from the beam of the lowest energy
* cluster in a cluster pair satisfies the following:<br/>
- * <code>E_low + R_min * F < [ Threshold ]</code>
+ * <code>E_low + R_min * F >= PAIR_ENERGY_SLOPE_LOW</code>
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -841,7 +926,9 @@
/**
* Checks if the sum of the energies of the clusters making up a
- * cluster pair is within an energy sum threshold.
+ * cluster pair is within an energy sum threshold. This is defined
+ * as <code>PAIR_ENERGY_SUM_LOW <= E_1 + E_2 <=
+ * PAIR_ENERGY_SUM_HIGH</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -853,6 +940,7 @@
/**
* Checks if the sum of the energies of the clusters making up a
* cluster pair is below the energy sum upper bound threshold.
+ * This is defined as <code>E_1 + E_2 <= PAIR_ENERGY_SUM_HIGH</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -864,6 +952,7 @@
/**
* Checks if the sum of the energies of the clusters making up a
* cluster pair is above the energy sum lower bound threshold.
+ * This is defined as <code>PAIR_ENERGY_SUM_LOW <= E_1 + E_2</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -874,7 +963,9 @@
/**
* Checks if the sum of the energies of clusters making up a cluster
- * pair is below an energy sum threshold.
+ * pair is below an energy sum threshold. This is defined
+ * as <code>PAIR_ENERGY_SUM_LOW <= E_1 + E_2 <=
+ * PAIR_ENERGY_SUM_HIGH</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -886,6 +977,7 @@
/**
* Checks if the sum of the energies of the clusters making up a
* cluster pair is below the energy sum upper bound threshold.
+ * This is defined as <code>E_1 + E_2 <= PAIR_ENERGY_SUM_HIGH</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -897,6 +989,7 @@
/**
* Checks if the sum of the energies of the clusters making up a
* cluster pair is above the energy sum lower bound threshold.
+ * This is defined as <code>PAIR_ENERGY_SUM_LOW <= E_1 + E_2</code>.
* @param clusterPair - The cluster pair to check.
* @return Returns <code>true</code> if the cluster pair passes
* the cut and <code>false</code> if it does not.
@@ -907,7 +1000,8 @@
/**
* Checks if the absolute difference between the times between
- * two clusters is below the time coincidence cut.
+ * two clusters is below the time coincidence cut. This is defined
+ * as <code>|t_1 - t_2| <= PAIR_TIME_COINCIDENCE</code>.
* @param clusterPair - The cluster pair to check.
* @return <code>true</code> if the energy sum passes
* the cut and <code>false</code> if it does not.
@@ -918,7 +1012,8 @@
/**
* Checks if the absolute difference between the times between
- * two clusters is below the time coincidence cut.
+ * two clusters is below the time coincidence cut. This is defined
+ * as <code>|t_1 - t_2| <= PAIR_TIME_COINCIDENCE</code>.
* @param clusterPair - The cluster pair to check.
* @return <code>true</code> if the energy sum passes
* the cut and <code>false</code> if it does not.
@@ -1018,9 +1113,8 @@
* Gets the mapped position used by the SSP for a specific crystal.
* @param ix - The crystal x-index.
* @param iy - The crystal y-index.
- * @return Returns the crystal position as a <double</code> array
- * where the coordinates are ordered from the lowest to highest
- * index as x, y, z.
+ * @return Returns the crystal position as a <code>double</code>
+ * array of form { x, y, z }.
* @throws IndexOutOfBoundsException Occurs if in either of the
* cases where <code>ix == 0</code> or <code>|ix| > 23</code> for
* the x-index and either of the cases where <code>iy == 0</code>
@@ -1034,9 +1128,13 @@
throw new IndexOutOfBoundsException(String.format("Value \"%d\" is invalid for field y-index.", iy));
}
- // Return the mapped position.
- if(ix < 1) { return position[5 - iy][22 - ix]; }
- else { return position[5 - iy][23 - ix]; }
+ // Get the position map.
+ double posMap[];
+ if(ix < 1) { posMap = position[5 - iy][22 - ix]; }
+ else { posMap = position[5 - iy][23 - ix]; }
+
+ // Return the corrected mapped position.
+ return new double[] { posMap[0], posMap[2], posMap[1] };
}
/**
@@ -1047,11 +1145,11 @@
* second clusters' y-positions.
* @return Returns the cluster pair's coplanarity.
*/
- private static double getValueCoplanarity(double[] x, double z[]) {
+ private static double getValueCoplanarity(double[] x, double y[]) {
// Get the cluster angles.
int[] clusterAngle = new int[2];
for(int i = 0; i < 2; i++) {
- clusterAngle[i] = (int) Math.round(Math.atan(x[i] / z[i]) * 180.0 / Math.PI);
+ clusterAngle[i] = (int) Math.round(Math.atan(x[i] / y[i]) * 180.0 / Math.PI);
}
// Calculate the coplanarity cut value.
@@ -1098,33 +1196,7 @@
* energy slope equation E_low + R_min * F.
* @return Returns the cut value.
*/
- private static double getValueEnergySlope(double energy[], double x[], double z[], double energySlopeParamF) {
- // Determine which cluster is the lower-energy cluster.
- int lei = energy[0] < energy[1] ? 0 : 1;
-
- // E + R*F
- // Get the low energy cluster energy.
- double slopeParamE = energy[lei];
-
- // Get the low energy cluster radial distance.
- double slopeParamR = Math.sqrt((x[lei] * x[lei]) + (z[lei] * z[lei]));
-
- // Calculate the energy slope.
- return slopeParamE + slopeParamR * energySlopeParamF;
- }
-
- /**
- * Calculates the value used by the energy slope cut. This version
- * is superseded by the <code>getValueEnergySlope</code>, which
- * more accurately mirrors the hardware behavior.
- * @param clusterPair - The cluster pair from which the value should
- * be calculated.
- * @param energySlopeParamF - The value of the variable F in the
- * energy slope equation E_low + R_min * F.
- * @return Returns the cut value.
- */
- @Deprecated
- private static double getValueEnergySlopeLegacy(double energy[], double x[], double y[], double energySlopeParamF) {
+ private static double getValueEnergySlope(double energy[], double x[], double y[], double energySlopeParamF) {
// Determine which cluster is the lower-energy cluster.
int lei = energy[0] < energy[1] ? 0 : 1;
@@ -1140,6 +1212,32 @@
}
/**
+ * Calculates the value used by the energy slope cut. This version
+ * is superseded by the <code>getValueEnergySlope</code>, which
+ * more accurately mirrors the hardware behavior.
+ * @param clusterPair - The cluster pair from which the value should
+ * be calculated.
+ * @param energySlopeParamF - The value of the variable F in the
+ * energy slope equation E_low + R_min * F.
+ * @return Returns the cut value.
+ */
+ @Deprecated
+ private static double getValueEnergySlopeLegacy(double energy[], double x[], double y[], double energySlopeParamF) {
+ // Determine which cluster is the lower-energy cluster.
+ int lei = energy[0] < energy[1] ? 0 : 1;
+
+ // E + R*F
+ // Get the low energy cluster energy.
+ double slopeParamE = energy[lei];
+
+ // Get the low energy cluster radial distance.
+ double slopeParamR = Math.sqrt((x[lei] * x[lei]) + (y[lei] * y[lei]));
+
+ // Calculate the energy slope.
+ return slopeParamE + slopeParamR * energySlopeParamF;
+ }
+
+ /**
* Calculates the value used by the energy sum cut.
* @param energy - A two-dimensional array consisting of the first
* and second clusters' energies.
@@ -1242,7 +1340,10 @@
* the hardware SSP position mappings for each crystal. Note that
* ix in the array goes from -22 (representing ix = 23) up to 25
* (representing ix = 23) and uses array index x = 0 as a valid
- * parameter, while ix skips zero.
+ * parameter, while ix skips zero.<br/>
+ * <br/>
+ * Note that in this table, position[][] = { x, z, y } by in the
+ * coordinate system employed by the rest of the class.
*/
private static final double[][][] position = {
{ { -340.003, 97.065, 87.845 }, { -324.283, 97.450, 87.875 }, { -308.648, 97.810, 87.900 },
|