Print

Print


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