Author: [log in to unmask] Date: Wed Dec 3 16:05:37 2014 New Revision: 1647 Log: Add ECAL cosmic cluster Driver. Added: java/trunk/users/src/main/java/org/hps/users/jeremym/EcalCosmicClusterDriver.java Added: java/trunk/users/src/main/java/org/hps/users/jeremym/EcalCosmicClusterDriver.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/jeremym/EcalCosmicClusterDriver.java (added) +++ java/trunk/users/src/main/java/org/hps/users/jeremym/EcalCosmicClusterDriver.java Wed Dec 3 16:05:37 2014 @@ -0,0 +1,203 @@ +package org.hps.users.jeremym; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.lcsim.detector.identifier.IIdentifierHelper; +import org.lcsim.detector.identifier.Identifier; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.event.Cluster; +import org.lcsim.event.EventHeader; +import org.lcsim.event.base.BaseCluster; +import org.lcsim.geometry.Detector; +import org.lcsim.geometry.subdetector.HPSEcal3; +import org.lcsim.lcio.LCIOConstants; +import org.lcsim.util.Driver; + +/** + * Cluster input hit list of raw ECAL data for cosmic events. + * + * @author Jeremy McCormick <[log in to unmask]> + * @author Tim "THammer" Nelson <[log in to unmask]> + */ +public class EcalCosmicClusterDriver extends Driver { + + String inputHitCollectionName = "SelectedEcalCalHits"; + String outputClusterCollectionName = "EcalCosmicClusters"; + String ecalName = "Ecal"; + HPSEcal3 ecal = null; + IIdentifierHelper helper = null; + int minimumClusterSize = 3; + int minimumRows = 3; + int maximumHitsPerRow = 2; + + public void setEcalName(String ecalName) { + this.ecalName = ecalName; + } + + public void setInputHitCollectionName(String inputHitCollectionName) { + this.inputHitCollectionName = inputHitCollectionName; + } + + public void setOutputClusterCollectionName(String outputClusterCollectionName) { + this.outputClusterCollectionName = outputClusterCollectionName; + } + + public void setMinimumClusterSize(int minimumClusterSize) { + this.minimumClusterSize = minimumClusterSize; + } + + public void setMinimumRows(int minimumRows) { + this.minimumRows = minimumRows; + } + + public void setMaximumHitsPerRow(int maximumHitsPerRow) { + this.maximumHitsPerRow = maximumHitsPerRow; + } + + public void detectorChanged(Detector detector) { + ecal = (HPSEcal3) detector.getSubdetector(ecalName); + if (ecal == null) { + throw new RuntimeException("There is no HPSEcal3 subdetector called " + ecalName + " in this detector."); + } + helper = ecal.getDetectorElement().getIdentifierHelper(); + if (helper == null) { + throw new RuntimeException("Panic! Could not find IIdentifierHelper for " + ecalName + " subdetector."); + } + } + + public void process(EventHeader event) { + if (event.hasCollection(CalorimeterHit.class, inputHitCollectionName)) { + List<CalorimeterHit> calHits = event.get(CalorimeterHit.class, inputHitCollectionName); + List<List<CalorimeterHit>> clusteredHitList = createClusteredHits(calHits); + List<List<CalorimeterHit>> selectedClusteredHitList = applyCuts(clusteredHitList); + List<Cluster> clusterCollection = new ArrayList<Cluster>(); + for (List<CalorimeterHit> hits : selectedClusteredHitList) { + BaseCluster calCluster = new BaseCluster(); + double totalEnergy = 0; + for (CalorimeterHit hit : hits) { + calCluster.addHit(hit); + totalEnergy += hit.getCorrectedEnergy(); + } + calCluster.setEnergy(totalEnergy); + clusterCollection.add(calCluster); + } + if (clusterCollection.size() > 0) { + int flags = 1 << LCIOConstants.CLBIT_HITS; + event.put(outputClusterCollectionName, clusterCollection, Cluster.class, flags); + //System.out.println("added cluster to " + outputClusterCollectionName + " with size " + clusterCollection.size()); + } else { + throw new NextEventException(); + } + } + } + + private Set<Long> findNeighborHitIDs(CalorimeterHit hit, Map<Long, CalorimeterHit> hitMap) { + Set<Long> neigbhors = ecal.getNeighborMap().get(hit.getCellID()); + Set<Long> neighborHitIDs = new HashSet<Long>(); + for (long neighborID : neigbhors) { + if (hitMap.containsKey(neighborID)) { + neighborHitIDs.add(neighborID); + } + } + return neighborHitIDs; + } + + private Map<Long, CalorimeterHit> createHitMap(List<CalorimeterHit> hitList) { + Map<Long, CalorimeterHit> hitMap = new HashMap<Long, CalorimeterHit>(); + for (CalorimeterHit hit : hitList) { + hitMap.put(hit.getCellID(), hit); + } + return hitMap; + } + + private List<List<CalorimeterHit>> createClusteredHits(List<CalorimeterHit> hitList) { + + // Create empty list of clusters which are just lists of hits. + List<List<CalorimeterHit>> clusterList = new ArrayList<List<CalorimeterHit>>(); + + // Create map of IDs to hits for convenience. + Map<Long, CalorimeterHit> hitMap = createHitMap(hitList); + + // Create list of hits that are clusterable, which is initially all of them. + Set<CalorimeterHit> clusterable = new HashSet<CalorimeterHit>(); + clusterable.addAll(hitList); + + // Loop over all hits in the map. + for (CalorimeterHit hit : hitList) { + + // Is hit clusterable? + if (!clusterable.contains(hit)) { + // Continue to next hit. + continue; + } + + // Create list for clustering this hit. + List<CalorimeterHit> clusterHits = new ArrayList<CalorimeterHit>(); + + // Set of hits whose neighbors have not been checked yet. + LinkedList<CalorimeterHit> uncheckedHits = new LinkedList<CalorimeterHit>(); + uncheckedHits.add(hit); + + // While there are still unchecked hits in the cluster. + while (uncheckedHits.size() > 0) { + + // Get the first hit and add it to the cluster. + CalorimeterHit clusterHit = uncheckedHits.removeFirst(); + + // Add hit to the cluster. + clusterHits.add(clusterHit); + + // Remove the hit from the clusterable list. + clusterable.remove(clusterHit); + + // Loop over the neighbors and add IDs with hits to the unchecked list. + for (Long neighborHitID : this.findNeighborHitIDs(clusterHit, hitMap)) { + CalorimeterHit neighborHit = hitMap.get(neighborHitID); + if (clusterable.contains(neighborHit)) { + uncheckedHits.add(neighborHit); + } + } + } + + if (clusterHits.size() >= this.minimumClusterSize) { + //System.out.println("adding cosmic cluster of size " + clusterHits.size()); + clusterList.add(clusterHits); + } + } + return clusterList; + } + + List<List<CalorimeterHit>> applyCuts(List<List<CalorimeterHit>> clusteredHitLists) { + List<List<CalorimeterHit>> selectedHitLists = new ArrayList<List<CalorimeterHit>>(); + for (List<CalorimeterHit> hitList : clusteredHitLists) { + Map<Integer, Set<CalorimeterHit>> rowMap = new HashMap<Integer, Set<CalorimeterHit>>(); + for (CalorimeterHit hit : hitList) { + int row = helper.getValue(new Identifier(hit.getCellID()), "iy"); + if (rowMap.get(row) == null) { + rowMap.put(row, new HashSet<CalorimeterHit>()); + } + rowMap.get(row).add(hit); + } + if (rowMap.size() >= minimumRows) { + boolean okay = true; + rowMapLoop: for (Entry<Integer, Set<CalorimeterHit>> entries : rowMap.entrySet()) { + if (entries.getValue().size() > maximumHitsPerRow) { + okay = false; + break rowMapLoop; + } + } + if (okay) { + selectedHitLists.add(hitList); + } + } + } + return selectedHitLists; + } +}