Print

Print


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;
+	}
+}