java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPEcalClusterer.java 2014-08-07 16:51:33 UTC (rev 840)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPEcalClusterer.java 2014-08-07 17:01:37 UTC (rev 841)
@@ -16,25 +16,22 @@
import org.lcsim.util.Driver;
/**
- * Class
- * <code>GTPCalorimeterClusterer</code> processes events and converts hits into
- * clusters, where appropriate. It uses the modified 2014 clustering algorithm.
- *
+ * Class <code>GTPCalorimeterClusterer</code> processes events and converts hits
+ * into clusters, where appropriate. It uses the modified 2014 clustering algorithm.<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.
- *
+ * cluster energy that exceeds another tunable minimum threshold.<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
*/
public class GTPEcalClusterer extends Driver {
-
/**
* <b>calorimeter</b><br/><br/>
* <code>private HPSEcal3 <b>calorimeter</b></code><br/><br/>
@@ -48,14 +45,14 @@
* <code>
* Detector</code> object for this run.
*/
- String ecalName;
+ private String ecalName;
/**
* <b>clusterCollectionName</b><br/><br/>
* <code>private String <b>clusterCollectionName</b></code><br/><br/>
* The name of the LCIO collection name in which the clusters will be
* stored.
*/
- String clusterCollectionName = "EcalClusters";
+ private String clusterCollectionName = "EcalClusters";
/**
* <b>clusterWindow</b><br/><br/>
* <code>private int <b>clusterWindow</b></code><br/><br/>
@@ -63,7 +60,7 @@
* after a given cycle that should be considered when checking if a cluster
* is a local maximum in space-time.
*/
- int clusterWindow = 2;
+ private int clusterWindow = 2;
/**
* <b>hitBuffer</b><br/><br/>
* <code>private LinkedList<List<CalorimeterHit>> <b>hitBuffer</b></code><br/><br/>
@@ -77,7 +74,7 @@
* The name of LCIO collection containing the calorimeter hits that are to
* be used for clustering.
*/
- String ecalCollectionName;
+ private String ecalCollectionName;
/**
* <b>neighborMap</b><br/><br/>
* <code>private NeighborMap <b>neighborMap</b></code><br/><br/>
@@ -92,11 +89,16 @@
* The minimum energy required for a hit to be considered as a cluster
* center. Hits with energy less than this value will be ignored.
*/
- double seedEnergyThreshold = 0.05;
-
+ private double seedEnergyThreshold = 0.05;
/**
- * <b>detectorChanged</b><br/><br/>
- * <code>public void <b>detectorChanged</b>(Detector detector)</code><br/><br/>
+ * <b>limitClusterRange</b><br/><br/>
+ * <code>private boolean <b>limitClusterRange</b></code><br/><br/>
+ * Whether an asymmetric or symmetric window should be used for
+ * adding hits to a cluster.
+ */
+ private boolean limitClusterRange = false;
+
+ /**
* Initializes detector-dependent parameters for clustering. Method is
* responsible for determining which crystals are valid cluster centers
* (stored in
@@ -112,14 +114,12 @@
public void detectorChanged(Detector detector) {
// Get the calorimeter object.
calorimeter = (HPSEcal3) detector.getSubdetector(ecalName);
-
+
// Get a map to associate crystals with their neighbors.
neighborMap = calorimeter.getNeighborMap();
}
-
+
/**
- * <b>getClusters</b><br/><br/>
- * <code>public List<HPSEcalCluster> <b>getClusters</b>()</code><br/><br/>
* 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.
@@ -130,10 +130,10 @@
public List<HPSEcalCluster> getClusters() {
// Generate a list for storing clusters.
List<HPSEcalCluster> clusters = new ArrayList<HPSEcalCluster>();
-
+
// Get the list of hits at the current time in the event buffer.
Map<Long, CalorimeterHit> currentHits = hitBuffer.get(clusterWindow);
-
+
// 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.
@@ -141,45 +141,48 @@
for (Long currentID : currentHits.keySet()) {
// Get the actual hit object.
CalorimeterHit currentHit = currentHits.get(currentID);
-
+
// Store the energy of the current hit.
double currentEnergy = currentHit.getRawEnergy();
-
+
// If the hit energy is lower than the minimum threshold,
// then we immediately reject this hit as a possible cluster.
if (currentEnergy < seedEnergyThreshold) {
continue seedLoop;
}
-
+
// Store the crystals that are part of this potential cluster,
// starting with the cluster seed candidate.
HPSEcalCluster cluster = new HPSEcalCluster(currentHit);
cluster.addHit(currentHit);
-
+
// Get the set of neighbors for this hit.
Set<Long> neighbors = neighborMap.get(currentHit.getCellID());
-
+
// Sort through each event stored in the buffer.
- addLoop:
+ 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) {
continue seedLoop;
- } // If the buffer hit is smaller, then add its energy
+ }
+
+ // If the buffer hit is smaller, then add its energy
// to the cluster total energy.
else {
- cluster.addHit(bufferHit);
+ 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.
@@ -188,33 +191,37 @@
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) {
continue seedLoop;
- } // If the buffer neighbor hit is smaller, then
+ }
+
+ // If the buffer neighbor hit is smaller, then
// add its energy to the cluster total energy.
else {
- cluster.addHit(neighborHit);
+ 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);
}
-
+
// Return the generated list of clusters.
return clusters;
}
-
+
/**
- * <b>process</b><br/><br/>
- * <code>public void <b>process</b>(EventHeader event)</code><br/><br/>
* 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.
@@ -228,30 +235,28 @@
if (event.hasCollection(CalorimeterHit.class, ecalCollectionName)) {
// Get the list of calorimeter hits from the event.
List<CalorimeterHit> hitList = event.get(CalorimeterHit.class, ecalCollectionName);
-
+
// Store each hit in a set by its cell ID so that it may be
// easily acquired later.
HashMap<Long, CalorimeterHit> hitMap = new HashMap<Long, CalorimeterHit>();
for (CalorimeterHit hit : hitList) {
hitMap.put(hit.getCellID(), hit);
}
-
+
// Remove the last event from the hit buffer and add the new one.
hitBuffer.removeLast();
hitBuffer.addFirst(hitMap);
-
+
// Run the clustering algorithm on the buffer.
List<HPSEcalCluster> clusterList = getClusters();
-
+
// Store the cluster list in the LCIO collection.
int flag = 1 << LCIOConstants.CLBIT_HITS;
event.put(clusterCollectionName, clusterList, HPSEcalCluster.class, flag);
}
}
-
+
/**
- * <b>setEcalCollectionName</b><br/><br/>
- * <code>public void <b>setEcalCollectionName</b>(String ecalCollectionName)</code><br/><br/>
* Sets the name of the LCIO collection containing the calorimeter hits
* which should be used for clustering.
*
@@ -260,10 +265,8 @@
public void setEcalCollectionName(String ecalCollectionName) {
this.ecalCollectionName = ecalCollectionName;
}
-
+
/**
- * <b>setClusterCollectionName</b><br/><br/>
- * <code>public void <b>setClusterCollectionName</b>(String clusterCollectionName)</code><br/><br/>
* Sets the name of the LCIO collection in which the clusters should be
* stored.
*
@@ -272,10 +275,8 @@
public void setClusterCollectionName(String clusterCollectionName) {
this.clusterCollectionName = clusterCollectionName;
}
-
+
/**
- * <b>setEcalName</b><br/><br/>
- * <code>public void <b>setEcalName</b>(String ecalName)</code><br/><br/>
* Sets the name of the calorimeter sub-detector stored in the
* <code>Detector</code> object that is to be used for this run.
*
@@ -284,10 +285,8 @@
public void setEcalName(String ecalName) {
this.ecalName = ecalName;
}
-
+
/**
- * <b>setClusterWindow</b><br/><br/>
- * <code>public void <b>setClusterWindow</b>(int clusterWindow)</code><br/><br/>
* 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
@@ -304,15 +303,28 @@
// The cluster window of must always be at least zero.
if (clusterWindow < 0) {
this.clusterWindow = 0;
- } // If the cluster window is non-zero, then store it.
+ }
+
+ // If the cluster window is non-zero, then store it.
else {
this.clusterWindow = clusterWindow;
}
}
-
+
/**
- * <b>setSeedEnergyThreshold</b><br/><br/>
- * <code>public void <b>setSeedEnergyThreshold</b>(double seedEnergyThreshold)</code><br/><br/>
+ * 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.
+ */
+ public void setLimitClusterRange(boolean limitClusterRange) {
+ this.limitClusterRange = limitClusterRange;
+ }
+
+ /**
* Sets the minimum energy threshold below which hits will not be considered
* as cluster centers.
*
@@ -328,10 +340,8 @@
this.seedEnergyThreshold = seedEnergyThreshold;
}
}
-
+
/**
- * <b>startOfData</b><br/><br/>
- * <code>public void <b>startOfData</b>()</code><br/><br/>
* Initializes the clusterer. This ensures that the collection name for the
* calorimeter hits from which clusters are to be generated, along with the
* calorimeter name, have been defined. Method also initializes the event
@@ -344,15 +354,15 @@
if (ecalCollectionName == null) {
throw new RuntimeException("The parameter ecalCollectionName was not set!");
}
-
+
// Make sure that there is a calorimeter detector.
if (ecalName == null) {
throw new RuntimeException("The parameter ecalName was not set!");
}
-
+
// 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