Commit in lcsim/src/org/lcsim/recon/tracking/digitization/sisim on MAIN
PixelHitMaker.java+78-621.1 -> 1.2
New pixel clustering code - older code would sometimes go into an infinite loop.

lcsim/src/org/lcsim/recon/tracking/digitization/sisim
PixelHitMaker.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- PixelHitMaker.java	24 Apr 2009 01:22:58 -0000	1.1
+++ PixelHitMaker.java	30 Apr 2009 22:13:13 -0000	1.2
@@ -17,6 +17,7 @@
 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.Set;
@@ -61,8 +62,9 @@
     // Identifier helper (reset once per sensor)
     SiTrackerIdentifierHelper _sid_helper;
     
-    // Temporary map connecting hits to pixel numbers for sake of speed (reset once per sensor)
+    // Temporary maps connecting hits to pixel numbers for sake of speed (reset once per sensor)
     Map<RawTrackerHit,Integer> _pixel_map = new HashMap<RawTrackerHit,Integer>();
+    Map<Integer,RawTrackerHit> _pixel_map_inv = new HashMap<Integer,RawTrackerHit>();
     
     /** Creates a new instance of Tracker1DHitMaker */
     public PixelHitMaker(SiSensorSim simulation, ReadoutChip readout_chip)
@@ -146,6 +148,7 @@
         // Get SiTrackerIdentifierHelper for this sensor and refresh the pixel map used to increase speed
         _sid_helper = (SiTrackerIdentifierHelper)sensor.getIdentifierHelper();
         _pixel_map.clear();
+        _pixel_map_inv.clear();
         
         // Get hits for this sensor
         IReadout ro = sensor.getReadout();
@@ -158,7 +161,15 @@
             
             // get id and create pixel map, get electrodes.
             IIdentifier id = raw_hit.getIdentifier();
-            _pixel_map.put(raw_hit,_sid_helper.getElectrodeValue(id));
+            int pixel_number = _sid_helper.getElectrodeValue(id);
+
+            //  Check for duplicates
+            if (_pixel_map.containsKey(raw_hit) || _pixel_map_inv.containsKey(pixel_number))
+                throw new RuntimeException("Duplicate hit or cell number");
+
+            //  Add this hit to the pixel maps
+            _pixel_map.put(raw_hit, pixel_number);
+            _pixel_map_inv.put(pixel_number, raw_hit);
             
             // Get electrodes and check that they are pixels
             //System.out.println("proc raw hit from: " + DetectorElementStore.getInstance().find(raw_hit.getIdentifier()).get(0).getName());
@@ -189,46 +200,77 @@
     // Make hits for an electrode
     public List<SiTrackerHit> makeHits(SiSensorElectrodes electrodes, List<RawTrackerHit> raw_hits)
     {
-        
-//            System.out.println("Clustering electrodes: "+electrodes_id);
-        
+        //  Check that the seed threshold is at least as large as  the neighbor threshold
+        if (_seed_threshold < _neighbor_threshold)
+            throw new RuntimeException("Tracker hit clustering error: seed threshold below neighbor threshold");
+
+        //  Create a list for the clustered hits
         List<SiTrackerHit> hits = new ArrayList<SiTrackerHit>();
+
+        //  Create list of seed candidates and map showing hit status (true = available for clustering)
+        List<RawTrackerHit> cluster_seeds = new ArrayList<RawTrackerHit>();
+        Map<Integer, Boolean> clusterable = new HashMap<Integer, Boolean>();
         
-        List<RawTrackerHit> unclustered_rawhits = new ArrayList<RawTrackerHit>(raw_hits);
-        
-        for (RawTrackerHit raw_hit : raw_hits)
-        {
-            
+        //  Loop over the raw hits and check if they should be added to the unclustered and/or seed lists
+        for (RawTrackerHit raw_hit : raw_hits) {
+
+            //  Get the signal/noise for this hit
             int pixel_number = _pixel_map.get(raw_hit);
             double signal = _readout_chip.decodeCharge(raw_hit);
             double noise = _readout_chip.getChannel(pixel_number).computeNoise(electrodes.getCapacitance(pixel_number));
-            
-            if (signal/noise > _seed_threshold && unclustered_rawhits.contains(raw_hit))
-            {
-                
-//                    System.out.println("Creating new cluster, # Raw hits on electrodes is: "+hits.size());
-                
+            double SNR = signal / noise;
+
+            //  Mark this hit as available for clustering if it is above the neighbor threshold
+            clusterable.put(pixel_number, SNR > _neighbor_threshold);
+
+            //  Add this hit to the list of seeds if appropriate
+            if (SNR > _seed_threshold) cluster_seeds.add(raw_hit);
+        }
+
+        //  Now loop over the cluster seeds to form clusters
+        for (RawTrackerHit raw_hit : cluster_seeds) {
+
+            //  First check if this hit is still available for clustering
+            int raw_pixel_number = _pixel_map.get(raw_hit);
+            if (clusterable.get(raw_pixel_number)) {
+
+                //  Create a new cluster and add the hit to it
                 List<RawTrackerHit> cluster = new ArrayList<RawTrackerHit>();
-                List<RawTrackerHit> clustered_hits = new ArrayList<RawTrackerHit>();
-                
-                clustered_hits.add(raw_hit);
-                
-                while (clustered_hits.size() != 0)
-                {
-                    cluster.addAll(clustered_hits);
-                    unclustered_rawhits.removeAll(clustered_hits);
-                    clustered_hits = neighborHits(clustered_hits,unclustered_rawhits,electrodes);
-                    
-//                        System.out.println("    Cluster size:  "+cluster.size());
-//                        System.out.println("        # Unclustered hits:  "+unclustered_hits.size());
-//                        System.out.println("        # neighbors found:  "+clustered_hits.size());
+
+                //  Create a queue to hold hits whose neighbors need to be checked for inclusion
+                LinkedList<RawTrackerHit> unchecked = new LinkedList<RawTrackerHit>();
+
+                //  Add the seed hit and mark it as unavailable for clustering
+                unchecked.addLast(raw_hit);
+                clusterable.put(raw_pixel_number, false);
+
+                //  Check the neighbors of hits added to the cluster
+                while (unchecked.size() > 0) {
+
+                    //  Pull the next hit off the queue and add it to the cluster
+                    RawTrackerHit clusteredhit = unchecked.removeFirst();
+                    cluster.add(clusteredhit);
+
+                    //  Get the neigbor cells
+                    Set<Integer> neighbor_cells = electrodes.getNearestNeighborCells(_pixel_map.get(clusteredhit));
+
+                    //   Now loop over the neighbors and see if we can add them to the cluster
+                    for (int cell : neighbor_cells) {
+
+                        //  First see if this neighbor cell is in our clusterable hit map
+                        if (clusterable.containsKey(cell)) {
+
+                           //  Now check if this neighbor cell is still available for clustering
+                           if (clusterable.get(cell)) {
+
+                               //  Add hit to the list of unchecked cluster hits and mark it unavailable for clustering
+                               unchecked.addLast(_pixel_map_inv.get(cell));
+                               clusterable.put(cell, false);
+                           }
+                        }
+                    }
                 }
-                
-//                if (cluster.size() > 10)
-//                {
-//                    System.out.println("Cluster size: "+cluster.size());
-//                }
-                
+
                 // Make a TrackerHit from the cluster if it meets max cluster size requirement
                 if (cluster.size() <= _max_cluster_npixels)
                 {
@@ -244,33 +286,7 @@
         }
         
         return hits;
-    }
-    
-    
-    // Find the hits neigboring a cluster
-    private List<RawTrackerHit> neighborHits(List<RawTrackerHit> clustered_hits, List<RawTrackerHit> unclustered_hits,
-            SiSensorElectrodes electrodes)
-    {
-        List<RawTrackerHit> neighbor_hits = new ArrayList<RawTrackerHit>();
-        
-        for (RawTrackerHit seed_hit : clustered_hits)
-        {
-            Set<Integer> neighbor_cells = electrodes.getNearestNeighborCells(_pixel_map.get(seed_hit));
-            for (RawTrackerHit hit : unclustered_hits)
-            {
-                int pixel_number = _pixel_map.get(hit);
-                double signal = _readout_chip.decodeCharge(hit);
-                double noise = _readout_chip.getChannel(pixel_number).computeNoise(electrodes.getCapacitance(pixel_number));
-                
-                if (neighbor_cells.contains(_pixel_map.get(hit)) && signal/noise > _neighbor_threshold)
-                {
-                    neighbor_hits.add(hit);
-                }
-            }
-        }
-        return neighbor_hits;
-    }
-    
+    }    
     
     //Make the hit
     private SiTrackerHitPixel makeTrackerHit(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes)
CVSspam 0.2.8