Author: [log in to unmask]
Date: Mon Dec 15 00:55:29 2014
New Revision: 1730
Log:
Added work-in-progress online version of the GTP clustering algorithm. This is needed for trigger diagnostics.
Added:
java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPOnlineClusterer.java
Added: java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPOnlineClusterer.java
=============================================================================
--- java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPOnlineClusterer.java (added)
+++ java/trunk/ecal-recon/src/main/java/org/hps/recon/ecal/GTPOnlineClusterer.java Mon Dec 15 00:55:29 2014
@@ -0,0 +1,232 @@
+package org.hps.recon.ecal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.util.Driver;
+
+public class GTPOnlineClusterer extends Driver {
+ private String hitCollectionName = "EcalCalHits";
+ private int eventNum = 0;
+ private double timeBefore = 4;
+ private double timeAfter = 12;
+
+ public void process(EventHeader event) {
+ // Increment the event number.
+ eventNum++;
+
+ // Check if the event has a collection of the appropriate type
+ // and name for readout hits.
+ boolean hasHits = event.hasCollection(CalorimeterHit.class, hitCollectionName);
+
+ // DEBUG :: Indicate whether the event has hits.
+ System.out.printf("Event %7d :: Has hits [%5b]%n", eventNum, hasHits);
+
+ if(event.hasCollection(CalorimeterHit.class, hitCollectionName)) {
+ // Get the hits.
+ List<CalorimeterHit> hitList = event.get(CalorimeterHit.class, hitCollectionName);
+
+ // Sort the hits by time in reverse order.
+ Collections.sort(hitList, new Comparator<CalorimeterHit>() {
+ @Override
+ public int compare(CalorimeterHit firstHit, CalorimeterHit secondHit) {
+ return Double.compare(secondHit.getTime(), firstHit.getTime());
+ }
+ });
+
+ // DEBUG :: Print the hit information.
+ for(CalorimeterHit hit : hitList) {
+ int ix = hit.getIdentifierFieldValue("ix");
+ int iy = hit.getIdentifierFieldValue("iy");
+ double energy = hit.getCorrectedEnergy();
+ double time = hit.getTime();
+
+ System.out.printf("\tHit --> %.3f GeV at (%3d, %3d) and at t = %.2f%n", energy, ix, iy, time);
+ }
+
+ // A seed hit is a hit that is the largest both within its
+ // spatial range (+/- 1 in the ix and iy direction) and
+ // within a certain temporal window. If a hit is a seed, all
+ // hits within the 3x3 spatial range around it that are also
+ // within the temporal window are considered part of the
+ // cluster.
+
+ // Track the valid clusters.
+ List<HPSEcalCluster> clusterList = new ArrayList<HPSEcalCluster>();
+
+ // Iterate over each hit and see if it qualifies as a seed hit.
+ seedLoop:
+ for(CalorimeterHit seed : hitList) {
+ // Create a cluster for the potential seed.
+ HPSEcalCluster protoCluster = new HPSEcalCluster(seed.getCellID());
+
+ // Iterate over the other hits and if the are within
+ // the clustering spatiotemporal window, compare their
+ // energies.
+ for(CalorimeterHit hit : hitList) {
+ // Do not perform the comparison if the hit is the
+ // current potential seed.
+ if(hit != seed) {
+ // Check if the hit is within the spatiotemporal
+ // clustering window.
+ if(withinTimeWindow(seed, hit) && withinSpatialWindow(seed, hit)) {
+ // Check if the hit invalidates the potential
+ // seed.
+ if (isValidSeed(seed, hit)) {
+ // Add the hit to the seed's component
+ // hits and continue checking.
+ protoCluster.addHit(hit);
+ }
+
+ // If it is not, then skip the rest of the
+ // loop; the potential seed is not really
+ // a seed.
+ else { continue seedLoop; }
+ }
+ }
+ }
+
+ // If this point is reached, then the seed was not
+ // invalidated by any of the other hits and is really
+ // a cluster center. Add the cluster to the list.
+ clusterList.add(protoCluster);
+ }
+
+ // DEBUG :: Print out all the clusters in the event.
+ for(HPSEcalCluster cluster : clusterList) {
+ int ix = cluster.getSeedHit().getIdentifierFieldValue("ix");
+ int iy = cluster.getSeedHit().getIdentifierFieldValue("iy");
+ double energy = cluster.getEnergy();
+ double time = cluster.getSeedHit().getTime();
+
+ System.out.printf("\tCluster --> %.3f GeV at (%3d, %3d) and at t = %.2f%n", energy, ix, iy, time);
+
+ for(CalorimeterHit hit : cluster.getCalorimeterHits()) {
+ int hix = hit.getIdentifierFieldValue("ix");
+ int hiy = hit.getIdentifierFieldValue("iy");
+ double henergy = hit.getCorrectedEnergy();
+ double htime = hit.getTime();
+ System.out.printf("\t\tCompHit --> %.3f GeV at (%3d, %3d) and at t = %.2f%n", henergy, hix, hiy, htime);
+ }
+ }
+ }
+
+ // DEBUG :: Print a new line.
+ System.out.println();
+ }
+
+ private boolean isValidSeed(CalorimeterHit seed, CalorimeterHit hit) {
+ // Get the hit and seed energies.
+ double henergy = hit.getCorrectedEnergy();
+ double senergy = seed.getCorrectedEnergy();
+
+ // If the hit energy is less than the seed, the seed is valid.
+ if(henergy < senergy) {
+ return true;
+ }
+
+ // If the hit energy is the same as the seed energy, spatial
+ // comparisons are used to ensure the uniqueness of the seed.
+ if(henergy == senergy) {
+ // Get the x-indices of the hits.
+ int six = seed.getIdentifierFieldValue("ix");
+ int hix = hit.getIdentifierFieldValue("ix");
+
+ // The hit closest to the electron-side of the detector
+ // is considered the seed.
+ if(six < hix) { return true; }
+ else if(six > hix) { return false; }
+
+ // If both hits are at the same x-index, compare how close
+ // they are to the beam gap.
+ else {
+ // Get the y-indices. The absolute values are used
+ // because closeness to iy = 0 represents closeness
+ // to the beam gap.
+ int siy = Math.abs(seed.getIdentifierFieldValue("iy"));
+ int hiy = Math.abs(seed.getIdentifierFieldValue("iy"));
+
+ // If the seed is closer, it is valid.
+ if(siy < hiy) { return true; }
+ else if(siy > hiy) { return false; }
+
+ // If the y-index is the same, these are the same hit.
+ // This case shouldn't really ever happen, but for the
+ // compiler's sake, it returns true. A hit can not render
+ // itself invalid for the purpose of being a seed.
+ else { return true; }
+ }
+ }
+
+ // Otherwise, the seed is invalid.
+ else { return false; }
+ }
+
+ private boolean withinSpatialWindow(CalorimeterHit seed, CalorimeterHit hit) {
+ // Get the x-indices of each hit.
+ int six = seed.getIdentifierFieldValue("ix");
+ int hix = hit.getIdentifierFieldValue("ix");
+
+ // Check that the x indices are either the same or within a
+ // range of one of one another.
+ if((six == hix) || (six + 1 == hix) || (six - 1 == hix)) {
+ // Get the y-indices of each hit.
+ int siy = seed.getIdentifierFieldValue("iy");
+ int hiy = hit.getIdentifierFieldValue("iy");
+
+ // Ensure that the y-indices are either the same or are
+ // within one of one another.
+ return (siy == hiy) || (siy + 1 == hiy) || (siy - 1 == hiy);
+ }
+
+ // If the x-index comparison fails, return false.
+ return false;
+ }
+
+ private boolean withinTimeWindow(CalorimeterHit seed, CalorimeterHit hit) {
+ // Get the hit time and seed time.
+ double hitTime = hit.getTime();
+ double seedTime = seed.getTime();
+
+ // If the hit is before the seed, use the before window.
+ if(hitTime < seedTime) {
+ return (seedTime - hitTime) <= timeBefore;
+ }
+
+ // If the hit occurs after the seed, use the after window.
+ else if(hitTime > seedTime) {
+ return (hitTime - seedTime) <= timeAfter;
+ }
+
+ // If the times are the same, the 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; }
+ }
+
+ public void startOfData() {
+ // DEBUG :: Print the class variable information.
+ System.out.printf("%s Settings:%n", getClass().getSimpleName());
+ System.out.printf("\tHit Collection :: %s%n", hitCollectionName);
+ System.out.printf("\tTime Window Before :: %.0f ns%n", timeBefore);
+ System.out.printf("\tTime Window After :: %.0f ns%n", timeAfter);
+ }
+
+ public void setHitCollectionName(String hitCollectionName) {
+ this.hitCollectionName = hitCollectionName;
+ }
+
+ public void setWindowBefore(int cyclesBefore) {
+ timeBefore = cyclesBefore * 4;
+ }
+
+ public void setWindowAfter(int cyclesAfter) {
+ timeAfter = cyclesAfter * 4;
+ }
+}
|