Commit in java/trunk/users/src on MAIN
main/java/org/lcsim/hps/users/ngraf/NearestNeighborCluster.java+58added 136
                                   /NearestNeighborClusterDriver.java+116added 136
test/java/org/lcsim/hps/users/ngraf/NearestNeighborClusterDriverTest.java+35added 136
+209
3 added files
Nearest Neighbor Clustering algorithm for the ECal. 
Should be useful for cosmic ray analyses.
Work in progress.

java/trunk/users/src/main/java/org/lcsim/hps/users/ngraf
NearestNeighborCluster.java added at 136
--- java/trunk/users/src/main/java/org/lcsim/hps/users/ngraf/NearestNeighborCluster.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/ngraf/NearestNeighborCluster.java	2014-01-29 23:52:37 UTC (rev 136)
@@ -0,0 +1,58 @@
+package org.lcsim.hps.users.ngraf;
+
+import java.util.Map;
+import java.util.Set;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.base.BaseCluster;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+
+/**
+ * This is a cluster created using a nearest-neighbor clustering algorithm. It
+ * currently extends BaseCluster but should extend a base HPS Cluster at some
+ * time
+ *
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ */
+public class NearestNeighborCluster extends BaseCluster
+{
+
+    /**
+     *
+     * @param map A Map of CalorimeterHit keyed on CellID, Hits added to this
+     * cluster are removed from the map
+     * @param hit A CalorimeterHit representing a hit crystal
+     * @param threshold The energy threshold below which a hit crystal should
+     * NOT be added to the cluster
+     * @param neighborMap The map of HPS crystal neighbors.
+     */
+    public NearestNeighborCluster(Map<Long, CalorimeterHit> map, CalorimeterHit hit, double threshold, HPSEcal3.NeighborMap neighborMap)
+    {
+        // start by adding this hit to the cluster
+        addHit(hit);
+        // remove this hit from the map so it can't be used again
+        map.remove(hit.getCellID());
+        //  loop over the hits in the cluster and add all its neighbors
+        // note that hits.size() grows as we add cells, so we recursively find neighbors of neighbors
+        for (int i = 0; i < hits.size(); ++i) {
+            CalorimeterHit c = hits.get(i);
+            // Get neighbor crystal IDs.
+            Set<Long> neighbors = neighborMap.get(c.getCellID());
+            // loop over all neighboring cell Ids
+            for (Long neighborId : neighbors) {
+                // Find the neighbor hit in the event if it exists.
+                CalorimeterHit neighborHit = map.get(neighborId);
+                // Was this neighbor cell hit?
+                if (neighborHit != null) {
+                    // if so, does it meet or exceed threshold?
+                    if (neighborHit.getRawEnergy() >= threshold) {
+                        addHit(neighborHit);
+                    }
+                    //remove this hit from the map so it can't be used again
+                    map.remove(neighborHit.getCellID());
+                }
+            }
+        }
+    }
+}

java/trunk/users/src/main/java/org/lcsim/hps/users/ngraf
NearestNeighborClusterDriver.java added at 136
--- java/trunk/users/src/main/java/org/lcsim/hps/users/ngraf/NearestNeighborClusterDriver.java	                        (rev 0)
+++ java/trunk/users/src/main/java/org/lcsim/hps/users/ngraf/NearestNeighborClusterDriver.java	2014-01-29 23:52:37 UTC (rev 136)
@@ -0,0 +1,116 @@
+package org.lcsim.hps.users.ngraf;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.SimCalorimeterHit;
+import org.lcsim.geometry.Detector;
+import org.lcsim.geometry.subdetector.HPSEcal3;
+import org.lcsim.hps.recon.ecal.ECalUtils;
+import org.lcsim.lcio.LCIOConstants;
+import org.lcsim.util.Driver;
+import org.lcsim.util.aida.AIDA;
+
+/**
+ * This is a test
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ */
+public class NearestNeighborClusterDriver extends Driver
+{
+    // Histogram manager
+    private AIDA aida;
+    // Minimum E for cluster seed.
+    double seedEMin = .00 * ECalUtils.GeV;
+    // Minimum E to add hit to cluster.
+    double addEMin = .00 * ECalUtils.GeV;
+    // Map of crystals to their neighbors.
+    HPSEcal3.NeighborMap _neighborMap = null;
+
+    @Override
+    public void processChildren(EventHeader event)
+    {
+        boolean debug = true;
+        // This is example code to run over a simple lcio file output from slic
+        // on which no calorimeter digitzation has been done.
+        // Therefore need to convert from SimCalorimeterHit to CalorimeterHit
+        // This would normally be done as a part of the reconstruction
+        if (event.hasCollection(SimCalorimeterHit.class, "EcalHits")) {
+            // Get the list of sim ECal hits.
+            List<SimCalorimeterHit> hits = event.get(SimCalorimeterHit.class, "EcalHits");
+
+            // create a list of CalorimeterHits
+            // Make a hit map for quick lookup by ID.
+            Map<Long, CalorimeterHit> hitMap = new HashMap<Long, CalorimeterHit>();
+            for (SimCalorimeterHit hit : hits) {
+                hitMap.put(hit.getCellID(), hit);
+            }
+
+            // Cluster the hits using a nearest neighbor algorithm
+            int flag = 1 << LCIOConstants.CLBIT_HITS;
+            List<NearestNeighborCluster> clusters = createNearestNeighborClusters(hitMap);
+            // quick analysis example
+            if(debug) System.out.println("found " + clusters.size() + " clusters");
+            double eTop = 0.;
+            double eBottom = 0.;
+            for (Cluster clus : clusters) {
+                if(debug)System.out.println("x: " + clus.getPosition()[0] + " y: " + clus.getPosition()[1] + " iPhi: " + clus.getIPhi() + " iTheta " + clus.getITheta());
+                if(clus.getPosition()[1]>0)
+                {
+                    eTop+=clus.getEnergy();
+                }
+                else
+                {
+                    eBottom += clus.getEnergy();
+                }
+            }
+            //fill the histograms
+            aida.cloud1D("Top energy sum").fill(eTop);
+            aida.cloud1D("Bottom energy sum").fill(eBottom);
+            aida.cloud1D("energy diff").fill(eTop-eBottom);
+            //add the list of clusters to the event
+            event.put("NearestNeighborClusters", clusters, NearestNeighborCluster.class, flag);
+        }
+    }
+
+    @Override
+    protected void detectorChanged(Detector detector)
+    {
+        // Get the Subdetector.
+        HPSEcal3 ecal = (HPSEcal3) detector.getSubdetector("Ecal");
+        // Cache the neighbor map for use by the nearest neighbor clustering algorithm
+        _neighborMap = ecal.getNeighborMap();
+        // set up some plotting infrastructure
+        aida = AIDA.defaultInstance();
+        aida.tree().cd("/");
+    }
+
+    /**
+     * Run the clustering algorithm over the list of hit crystals
+     * @param map Map of CalorimeterHit keyed on CellID. Note that this map is modified
+     * @return The list of found clusters
+     */
+    public List<NearestNeighborCluster> createNearestNeighborClusters(Map<Long, CalorimeterHit> map)
+    {
+        // New Cluster list to be added to event.
+        List<NearestNeighborCluster> clusters = new ArrayList<NearestNeighborCluster>();
+
+        while (!map.isEmpty()) {
+            Long k = map.keySet().iterator().next();
+            CalorimeterHit hit = map.get(k);
+            NearestNeighborCluster nnclus = new NearestNeighborCluster(map, hit, addEMin, _neighborMap);
+            //done with this cluster, let's compute some shape properties
+            if (nnclus.getSize() > 1) {
+                nnclus.calculateProperties();
+                clusters.add(nnclus);
+            }
+        }
+        return clusters;
+    }
+}
\ No newline at end of file

java/trunk/users/src/test/java/org/lcsim/hps/users/ngraf
NearestNeighborClusterDriverTest.java added at 136
--- java/trunk/users/src/test/java/org/lcsim/hps/users/ngraf/NearestNeighborClusterDriverTest.java	                        (rev 0)
+++ java/trunk/users/src/test/java/org/lcsim/hps/users/ngraf/NearestNeighborClusterDriverTest.java	2014-01-29 23:52:37 UTC (rev 136)
@@ -0,0 +1,35 @@
+package org.lcsim.hps.users.ngraf;
+
+import java.io.File;
+import java.net.URL;
+import junit.framework.TestCase;
+import org.lcsim.util.cache.FileCache;
+import org.lcsim.util.loop.LCSimLoop;
+
+/**
+ *
+ * @author ngraf
+ */
+public class NearestNeighborClusterDriverTest extends TestCase
+{
+ static final String testURLBase = "http://www.slac.stanford.edu/~ngraf/hps_data/";
+    static final String testFileName = "outfile3.slcio";
+    private final int nEvents = 500;
+
+    public void testClustering() throws Exception {
+
+        File lcioInputFile = null;
+
+        URL testURL = new URL(testURLBase + "/" + testFileName);
+        FileCache cache = new FileCache();
+        lcioInputFile = cache.getCachedFile(testURL);
+
+        //Process and write out the file
+        LCSimLoop loop = new LCSimLoop();
+        loop.setLCIORecordSource(lcioInputFile);
+        loop.add(new NearestNeighborClusterDriver());
+        loop.loop(nEvents, null);
+        loop.dispose();
+
+    }
+}
SVNspam 0.1