Author: [log in to unmask]
Date: Wed Feb 4 14:03:29 2015
New Revision: 2042
Log:
Copy hit list so that modifications by Clusterer does not effect master list. Add optional validation of output clusters. Setup logger for specific Driver class. HPSJAVA-412
Modified:
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterDriver.java
Modified: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterDriver.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterDriver.java (original)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/cluster/ClusterDriver.java Wed Feb 4 14:03:29 2015
@@ -1,5 +1,6 @@
package org.hps.recon.ecal.cluster;
+import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
@@ -31,9 +32,9 @@
*/
public class ClusterDriver extends Driver {
- protected static Logger logger = LogUtil.create(ClusterDriver.class, new BasicFormatter(ClusterDriver.class.getSimpleName()));
-
- protected String ecalName = "Ecal";
+ Logger logger;
+
+ protected String ecalName = "Ecal";
protected HPSEcal3 ecal;
protected NeighborMap neighborMap;
protected String outputClusterCollectionName = "EcalClusters";
@@ -49,11 +50,13 @@
protected boolean calculateProperties = false;
protected boolean applyCorrections = false;
protected boolean sortHits = false;
+ protected boolean validateClusters = false;
/**
* No argument constructor.
*/
public ClusterDriver() {
+ logger = LogUtil.create(getClass().getSimpleName(), new BasicFormatter(getClass().getSimpleName()));
}
/**
@@ -177,6 +180,14 @@
*/
public void setCuts(double[] cuts) {
this.cuts = cuts;
+ }
+
+ /**
+ * Set whether to validate the output.
+ * @param validateClusters True to validate output.
+ */
+ public void setValidateClusters(boolean validateClusters) {
+ this.validateClusters = validateClusters;
}
/**
@@ -222,7 +233,10 @@
if (event.hasCollection(CalorimeterHit.class, inputHitCollectionName)) {
List<CalorimeterHit> hits = event.get(CalorimeterHit.class, inputHitCollectionName);
logger.fine("input hit collection " + inputHitCollectionName + " has " + hits.size() + " hits");
- List<Cluster> clusters = clusterer.createClusters(event, hits);
+
+ // Cluster the hits, copying the list from the event in case the clustering algorithm modifies it.
+ List<Cluster> clusters = clusterer.createClusters(event, new ArrayList<CalorimeterHit>(hits));
+
if (clusters == null) {
throw new RuntimeException("The clusterer returned a null list from its createClusters method.");
}
@@ -258,6 +272,11 @@
logger.finer("Collection is set to transient and will not be persisted.");
event.getMetaData(clusters).setTransient(true);
}
+
+ if (validateClusters) {
+ // Perform basic validation checks.
+ this.validateClusters(event);
+ }
}
} else {
this.getLogger().severe("The input hit collection " + this.inputHitCollectionName + " is missing from the event.");
@@ -277,7 +296,7 @@
}
/**
- * Get a Clusterer using type inference for the concrete type.
+ * Get a {@link Clusterer} using type inference for the concrete type.
* @return The Clusterer object.
*/
@SuppressWarnings("unchecked")
@@ -285,4 +304,51 @@
// Return the Clusterer and cast it to the type provided by the caller.
return (ClustererType) clusterer;
}
-}
+
+ /**
+ * Perform basic validation of the cluster output collection, including checking
+ * that the cluster collection was created, clusters are not null,
+ * none of the clustered hits are null, and each hit exists in the input
+ * hit collection.
+ * @param event The LCSim event.
+ */
+ void validateClusters(EventHeader event) {
+ if (!event.hasCollection(Cluster.class, outputClusterCollectionName)) {
+ throw new RuntimeException("Cluster collection " + outputClusterCollectionName + " is missing.");
+ }
+ List<Cluster> clusters = event.get(Cluster.class, outputClusterCollectionName);
+ List<CalorimeterHit> inputHitCollection = event.get(CalorimeterHit.class, inputHitCollectionName);
+ for (int clusterIndex = 0; clusterIndex < clusters.size(); clusterIndex++) {
+ logger.finest("checking cluster " + clusterIndex);
+ Cluster cluster = clusters.get(clusterIndex);
+ if (clusters.get(clusterIndex) == null) {
+ throw new RuntimeException("The Cluster at index " + clusterIndex + " is null.");
+ }
+ List<CalorimeterHit> clusterHits = cluster.getCalorimeterHits();
+ logger.finest("cluster has " + clusterHits.size() + " hits");
+ for (int hitIndex = 0; hitIndex < clusterHits.size(); hitIndex++) {
+ logger.finest("checking cluster hit " + hitIndex);
+ CalorimeterHit clusterHit = clusterHits.get(hitIndex);
+ if (clusterHit == null) {
+ throw new RuntimeException("The CalorimeterHit at index " + hitIndex + " in the cluster is null.");
+ }
+ if (!inputHitCollection.contains(clusterHit)) {
+ logger.severe("The CalorimeterHit at index " + hitIndex + " with ID " + clusterHit.getIdentifier().toHexString() + " is missing from the input hit collection.");
+ printHitIDs(inputHitCollection);
+ throw new RuntimeException("The CalorimeterHit at index " + hitIndex + " in the cluster is missing from the input hit collection.");
+ }
+ }
+ }
+ }
+
+ void printHitIDs(List<CalorimeterHit> hits) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("hit IDs");
+ buffer.append('\n');
+ for (CalorimeterHit hit : hits) {
+ buffer.append(hit.getIdentifier().toHexString());
+ buffer.append('\n');
+ }
+ logger.finest(buffer.toString());
+ }
+}
|