View Javadoc

1   /*
2    * NNAlgo.java
3    *
4    * Created on April 4, 2006, 11:16 AM
5    *
6    * $Id: $
7    */
8   
9   package org.lcsim.recon.cluster.localequivalence;
10  
11  import java.util.ArrayList;
12  import java.util.Collection;
13  import java.util.Collections;
14  import java.util.HashMap;
15  import java.util.Iterator;
16  import java.util.List;
17  import java.util.Map;
18  import java.util.Set;
19  import java.util.SortedSet;
20  import org.lcsim.event.CalorimeterHit;
21  import org.lcsim.geometry.IDDecoder;
22  
23  /**
24   * A nearest-neighbor clustering algorithm which associates hits with their
25   * highest-energy neighboring hit
26   * 
27   * @author Norman Graf
28   */
29  public class NNAlgo
30  {
31      
32  //  miniumum cluster energy...
33      private double _minValue = 0.;
34      private int _deltaLayer = 1;
35      private int _deltaTheta = 1;
36      private int _deltaPhi = 1;
37      
38      public NNAlgo(double  min)
39      {
40          _minValue = min;
41      }
42      
43      public NNAlgo(double  min, int deltaLayer, int deltaTheta, int deltaPhi)
44      {
45          _minValue = min;
46          _deltaLayer = deltaLayer;
47          _deltaTheta = deltaTheta;
48          _deltaPhi = deltaPhi;
49      }
50      
51      public void setMinValue(double min)
52      {
53          _minValue = min;
54      }
55      
56      public List<NNCluster> cluster(Map<Long, CalorimeterHit> hitmap)
57      {
58          List<Cell> cells = new ArrayList<Cell>();
59          Map<Long, Cell> cellmap = new HashMap<Long, Cell>();
60          Collection<CalorimeterHit> hits = hitmap.values();
61          for(CalorimeterHit hit : hits)
62          {
63              Cell3D cell = new Cell3D(hit);
64              cells.add(cell);
65              long key = hit.getCellID();
66              cellmap.put(key, cell);
67  //            System.out.println(decodeCalHit(hit));
68          }
69          Collections.sort(cells);
70          Collections.reverse(cells);
71  //        System.out.println(cells);
72          // now loop over the energy-sorted list of cells...
73          for(Cell cell : cells)
74          {
75              Cell3D c3d = (Cell3D) cell;
76  //            System.out.println(c3d);
77              Cell pointsto = cell.pointsTo();
78              double max = cell.value();
79              CalorimeterHit c = c3d.getCalorimeterHit();
80              IDDecoder decoder = c.getIDDecoder();
81              decoder.setID(c.getCellID());
82              // loop over neighbors...
83              long[] neighbors = decoder.getNeighbourIDs(_deltaLayer, _deltaTheta, _deltaPhi);
84  //            System.out.println("");
85  //            System.out.println("");
86  //            System.out.println("  hit "+decodeCalHit(c));
87              for (int j=0; j<neighbors.length; ++j)
88              {
89  //                System.out.println("  j: "+j);
90  //                System.out.println("  "+decodeCellID(neighbors[j],c.getIDDecoder()));
91  //                System.out.println(c3d.cellID()+ " j= "+j+" neighbor= "+neighbors[j]);
92                  CalorimeterHit h = hitmap.get(neighbors[j]);
93                  // is the neighboring cell id hit?
94                  // if so, does it meet or exceed threshold?
95                  if (h != null)
96                  {
97  //                    System.out.println("   hit neighbor "+ decodeCalHit(h));
98                      Cell neigh = cellmap.get(neighbors[j]);
99                      // find highest neighbor to point to...
100                     if (neigh.value() > max) //Note difference between > and >=
101                     {
102                         max = neigh.value();
103                         pointsto = neigh;
104                     }
105                 }
106             } // end of loop over neighbors...
107             // If cell does not point to itself set pointedto and pointsto
108             if (cell != pointsto)
109             {
110                 cell.pointsTo(pointsto);
111                 pointsto.pointedTo().pointsTo(cell);
112                 cell.pointedTo(pointsto.pointedTo());           
113                 pointsto.pointedTo(cell);
114             }
115         }
116         
117         // This is the end of the clustering algorithm
118 //        System.out.println("Done clustering! \n");
119 //        System.out.println(cells);
120         // Build clusters here, with deletion of map entries
121         
122         // A collection to hold the clusters
123         List<NNCluster> clusters = new ArrayList<NNCluster>();
124 //                // The set of linked cells in the map
125         Set set = cellmap.entrySet();
126 //
127         int cluster  = 0;
128         int size = cellmap.size();
129         Iterator it;
130         while(size>0)
131         {
132             it = set.iterator();
133             Map.Entry entry = (Map.Entry) it.next();
134             Cell cell = (Cell) entry.getValue();
135             Cell nextcell = cell.pointsTo();
136             
137             ++cluster;
138             NNCluster clus = new NNCluster();
139             // loop over all cells pointed to by this cell recursively
140             while(cellmap.containsValue(cell))
141             {
142                 clus.addCell(cell);
143                 cellmap.remove(cell.cellID());
144 //
145                 cell = nextcell;
146                 nextcell = cell.pointsTo();
147             }
148             // done with this cluster
149             // If over threshold, add it to the list of clusters to return
150             if(clus.value()>_minValue)
151             {
152                 clusters.add(clus);
153                 SortedSet clusCells = clus.cells();
154                 for(Object o : clusCells)
155                 {
156                     Cell3D c = (Cell3D) o;
157                     // remove the associated calorimeter hit from the input map.
158                     hitmap.remove(c.cellID());
159                 }
160             }
161             size = cellmap.size();
162         } // end of clustering loop over map
163         return clusters;
164     }
165     
166     public String toString()
167     {
168         return "A Nearest Neighbor Clusterer with min value "+_minValue;
169     }
170     
171     String decodeCalHit(CalorimeterHit hit)
172     {
173         StringBuffer sb = new StringBuffer();
174         IDDecoder decoder = hit.getIDDecoder();
175         decoder.setID(hit.getCellID());
176         int nFields = decoder.getFieldCount();
177         for(int i=0; i<nFields; ++i)
178         {
179             sb.append(" "+decoder.getFieldName(i)+" : "+decoder.getValue(i));
180         }
181         return sb.toString();
182     }
183     
184     String decodeCellID(long key, IDDecoder decoder)
185     {
186         StringBuffer sb = new StringBuffer();
187         decoder.setID(key);
188         int nFields = decoder.getFieldCount();
189         for(int i=0; i<nFields; ++i)
190         {
191             sb.append(" "+decoder.getFieldName(i)+" : "+decoder.getValue(i));
192         }
193         return sb.toString();
194     }
195 }