View Javadoc

1   package org.lcsim.recon.cluster.util;
2   
3   import java.util.List;
4   import org.lcsim.spacegeom.PrincipalAxesLineFitter;
5   import org.lcsim.event.CalorimeterHit;
6   import org.lcsim.geometry.IDDecoder;
7   import org.lcsim.util.fourvec.Lorentz4Vector;
8   import org.lcsim.util.fourvec.Momentum4Vector;
9   import org.lcsim.event.Cluster;
10  import org.lcsim.event.base.ClusterPropertyCalculator;
11  
12  /**
13   * A class encapsulating the behavior of a calorimeter cluster.
14   *
15   * @author Norman A. Graf
16   * @version 1.0
17   */
18  public class FixedConeClusterPropertyCalculator implements ClusterPropertyCalculator
19  {
20      private IDDecoder _decoder;
21      private Lorentz4Vector _vec;
22      // second moment of the cluster
23      private double _width;
24      private double[] _layerEnergy;
25      private double _clusterEnergy;
26      private double[] _layerWidth;
27      private double[] _centroid;
28      private double[] _directionCosines;
29      private double _samplingFraction;
30      private CalorimeterHit _hottestCell;
31      private double _highestCellEnergy;
32      private boolean _isEndCap;
33      private boolean _isNorth;
34      private double _chisq = 99999.;
35      private int layers;
36      private double _itheta;
37      private double _iphi;
38      
39      /**
40       * Fully qualified constructor
41       */
42      public FixedConeClusterPropertyCalculator()
43      {
44          layers = 100;
45      }
46  
47      public void calculateProperties(Cluster cluster) {
48          calculateProperties(cluster.getCalorimeterHits());
49      }
50  
51      public void calculateProperties(List<CalorimeterHit> hits)
52      {
53          _vec = calculateVec(hits);
54          _layerEnergy = new double[layers];
55          _layerWidth = new double[layers];
56          // the array of cell (x,y,z) coordinates
57          double[][] points = new double[3][hits.size()];
58          int npoints=0;
59          _highestCellEnergy = 0.;
60          
61          for(CalorimeterHit h : hits )
62          {
63              _decoder = h.getIDDecoder();
64              _decoder.setID(h.getCellID());
65              double e = h.getCorrectedEnergy();
66              if (e>_highestCellEnergy)
67              {
68                  _highestCellEnergy = e;
69                  _hottestCell = h;
70                  // for now let highest energy cells determine location
71  //                _isEndCap = cell.isEndcap();
72  //                _isNorth = cell.isNorth();
73              }
74              // calculate the energy-weighted cluster width (second moment)
75              double dtheta=_vec.theta() - _decoder.getTheta();
76              double dphi=_vec.phi() - _decoder.getPhi();
77              // phi-wrap at 0:2pi?
78              if (dphi>Math.PI)
79              {
80                  dphi-=2.*Math.PI;
81              }
82              if (dphi<-Math.PI)
83              {
84                  dphi+=2.*Math.PI;
85              }
86              double dRw=(dtheta*dtheta + dphi*dphi)*e;
87              _width+=dRw;
88              // increment the energy deposited in this layer
89              _layerEnergy[_decoder.getLayer()]+=e;
90              _clusterEnergy+=e;
91              // increment the width (second moment of energy) in this layer
92              _layerWidth[_decoder.getLayer()]+=dRw;
93              //store the hit (x,y,z) coordinates
94              points[0][npoints] = _decoder.getX();
95              points[1][npoints] = _decoder.getY();
96              points[2][npoints] = _decoder.getZ();
97              npoints++;
98          }
99          // normalize the second moments
100         _width /= _clusterEnergy;
101         for(int i=0; i<layers; ++i)
102         {
103             _layerWidth[i]/=_clusterEnergy;
104         }
105         
106         // fit a straight line through the cells and store the results
107         PrincipalAxesLineFitter lf = new PrincipalAxesLineFitter();
108         lf.fit(points);
109         _centroid = lf.centroid();
110         _directionCosines = lf.dircos();
111         double dr = Math.sqrt( (_centroid[0]+_directionCosines[0])*(_centroid[0]+_directionCosines[0]) +
112                 (_centroid[1]+_directionCosines[1])*(_centroid[1]+_directionCosines[1]) +
113                 (_centroid[2]+_directionCosines[2])*(_centroid[2]+_directionCosines[2]) ) -
114                 Math.sqrt(	(_centroid[0])*(_centroid[0]) +
115                 (_centroid[1])*(_centroid[1]) +
116                 (_centroid[2])*(_centroid[2]) ) ;
117         double sign = 1.;
118         if(dr < 0.)sign = -1.;
119         _itheta = Math.acos(_directionCosines[2]);
120         _iphi = Math.atan2(_directionCosines[1],_directionCosines[0]);
121         
122         // finish up the cluster (base class method)
123 //        calculateDerivedQuantities();
124     }
125     
126     /**
127      * Calculate the cluster four-momentum.
128      * The Lorentz four-vector is derived from the cluster cells.
129      *
130      */
131     public Lorentz4Vector calculateVec(List<CalorimeterHit> hits)
132     {
133         Lorentz4Vector sum = new Momentum4Vector();
134         double[] sums = {0.,0.,0.};
135         double wtsum = 0.;
136         for(int i=0;i<hits.size();i++)
137         {
138             CalorimeterHit hit = hits.get(i);
139             double[] pos = new double[3];
140             _decoder = hit.getIDDecoder();
141             _decoder.setID(hit.getCellID());
142             pos[0] = _decoder.getX();
143             pos[1] = _decoder.getY();
144             pos[2] = _decoder.getZ();
145             double wt = hit.getCorrectedEnergy();
146             wtsum += wt;
147             for(int j=0;j<3;j++)
148             {
149                 sums[j] += wt*pos[j];
150             }
151         }
152         sum.plusEquals(new Momentum4Vector(sums[0], sums[1], sums[2], wtsum));
153         return sum;
154     }
155     
156     /**
157      * The cluster width (energy second moment).
158      *
159      * @return The cluster width
160      */
161     public double width()
162     {
163         return _width;
164     }
165     
166     /**
167      * The cluster four-momentum
168      *
169      * @return The Lorentz four-vector
170      */
171     public Lorentz4Vector vector()
172     {
173         return _vec;
174     }
175     
176     /**
177      * The constituent cells
178      *
179      * @return Vector of the CalorimeterHits constituting the cluster.
180      */
181     /**
182      * The cluster energy deposited in a specific layer
183      *
184      * @return  The cluster energy in layer <b>layer</b>
185      */
186     public double layerEnergy(int layer)
187     {
188         return _layerEnergy[layer];
189     }
190     
191     /**
192      * The cluster layer energies
193      *
194      * @return  The array of cluster energies in each layer.
195      */
196     public double[] layerEnergies()
197     {
198         return _layerEnergy;
199     }
200     
201     
202     /**
203      * The cluster energy corrected for sampling fractions
204      *
205      * @return  The cluster energy
206      */
207     public double clusterEnergy()
208     {
209         return _clusterEnergy;
210     }
211     
212     /**
213      * The energy of the highest energy cell in this cluster
214      *
215      * @return The energy of the highest energy cell in this cluster corrected by the sampling fraction.
216      */
217     public double highestCellEnergy()
218     {
219         return _highestCellEnergy;
220     }
221     
222     /**
223      * The CalorimeterHit in this cluster with the highest energy
224      *
225      * @return  The CalorimeterHit in this cluster with the highest energy
226      */
227     public CalorimeterHit hottestCell()
228     {
229         return _hottestCell;
230     }
231     
232     /**
233      * The cluster width (energy second moment) deposited in a specific layer
234      *
235      * @return  The cluster width in layer <b>layer</b>
236      */
237     public double layerWidth(int layer)
238     {
239         return _layerWidth[layer];
240     }
241     
242     /**
243      * The unweighted spatial centroid (x,y,z) of the cluster line fit
244      *
245      * @return The unweighted spatial centroid (x,y,z) of the cluster
246      */
247     public double[] centroid()
248     {
249         return _centroid;
250     }
251     
252     /**
253      * The direction cosines of the cluster line fit
254      *
255      * @return The direction cosines of the cluster
256      */
257     public double[] directionCosines()
258     {
259         return _directionCosines;
260     }
261     
262     
263     /**
264      * Returns topological position of cluster.
265      *
266      * @return true if in EndCap
267      */
268     public boolean isEndCap()
269     {
270         return _isEndCap;
271     }
272     
273     
274     /**
275      * Returns topological position of cluster.
276      *
277      * @return  true if in "North" EndCap
278      */
279     public boolean isNorth()
280     {
281         return _isNorth;
282     }
283     
284     public void setChisq(double chisq)
285     {
286         _chisq = chisq;
287     }
288     
289     public double chisq()
290     {
291         return _chisq;
292     }
293     public double[] getPosition()
294     {
295         return _centroid;
296     }
297     public double[] getPositionError()
298     {
299         double[] positionError = {0.,0.,0.,0.,0.,0.};
300         return positionError;
301     }
302     public double getIPhi()
303     {
304         return _iphi;
305     }
306     public double getITheta()
307     {
308         return _itheta;
309     }
310     public double[] getDirectionError()
311     {
312         double[] directionError = {0.,0.,0.,0.,0.,0.};
313         return directionError;
314     }
315     public double[] getShapeParameters()
316     {
317         double[] shapeParameters = {0.,0.,0.,0.,0.,0.};
318         shapeParameters[0] = _width;
319         return shapeParameters;
320     }
321     
322     
323 }
324