View Javadoc

1   package org.lcsim.cal.calib;
2   import java.util.List;
3   import java.util.ArrayList;
4   import org.lcsim.event.EventHeader;
5   import org.lcsim.geometry.subdetector.CylindricalCalorimeter;
6   import org.lcsim.event.CalorimeterHit;
7   import org.lcsim.util.Driver;
8   import org.lcsim.util.aida.AIDA;
9   import hep.aida.ITree;
10  
11  import static java.lang.Math.sqrt;
12  import java.text.DecimalFormat;
13  import java.util.Calendar;
14  import java.util.Date;
15  import java.util.GregorianCalendar;
16  import org.lcsim.conditions.ConditionsManager;
17  import org.lcsim.conditions.ConditionsManager.ConditionsSetNotFoundException;
18  import org.lcsim.conditions.ConditionsSet;
19  import org.lcsim.event.Cluster;
20  import org.lcsim.geometry.IDDecoder;
21  import org.lcsim.recon.emid.hmatrix.HMatrix;
22  import org.lcsim.recon.emid.hmatrix.HMatrixTask;
23  import org.lcsim.recon.emid.hmatrix.HMatrixBuilder;
24  import org.lcsim.recon.emid.hmatrix.HMatrixConditionsConverter;
25  import org.lcsim.math.chisq.ChisqProb;
26  import org.lcsim.math.moments.CentralMomentsCalculator;
27  import org.lcsim.recon.cluster.fixedcone.FixedConeClusterer;
28  import org.lcsim.recon.cluster.fixedcone.FixedConeClusterer.FixedConeDistanceMetric;
29  
30  /**
31   * Reconstruction: EM Clusters
32   */
33  public class EMClusterID extends Driver
34  {
35      private AIDA aida = AIDA.defaultInstance();
36      private ITree _tree;
37      private boolean _initialized;
38      private ConditionsSet _cond;
39      private String _detName;
40      private HMatrixTask _task;
41      private int _nLayers;
42      
43      private HMatrixBuilder _hmb;
44      private HMatrix _hmx;
45      
46      // the number of variables in the measurement vector
47      private int _nmeas;
48      
49      // the vector of measured values
50      double[] _vals;
51      
52      // the mapping of physical layers to measurement space
53      double[] _layerMapping;
54      
55      private DecimalFormat _myFormatter = new DecimalFormat("#.###");
56      
57      private boolean _debug = true;
58      
59      // where to write the HMatrix if in accumulate mode
60      private String _fileLocation = "default.hmx";
61      
62      public EMClusterID()
63      {
64          this(HMatrixTask.ANALYZE);
65  //        this(HMatrixTask.BUILD);
66      }
67      
68      public EMClusterID(HMatrixTask task)
69      {
70          _tree = aida.tree();
71          _task = task;
72          
73          if(task==HMatrixTask.ANALYZE)
74          {
75              // The HMatrix could possibly change, so be sensitive to this.
76              getConditionsManager().registerConditionsConverter(new HMatrixConditionsConverter());
77          }
78          
79      }
80      
81      protected void process(EventHeader event)
82      {
83          super.process(event);
84          
85          //FIXME: need to get the EM calorimeter names from a conditions file
86          // FIXME should get calorimeterhit collection names from a conditions file
87          
88          String[] det = {"EMBarrel","EMEndcap"};
89          String[] hitsToGet = {"EcalBarrHits","EcalEndcapHits"};
90          
91          if(!_initialized)
92          {
93              ConditionsManager mgr = ConditionsManager.defaultInstance();
94              try
95              {
96                  _cond = mgr.getConditions("HMatrix");
97              }
98              catch(ConditionsSetNotFoundException e)
99              {
100                 System.out.println("ConditionSet HMatrix not found for detector "+mgr.getDetector());
101                 System.out.println("Please check that this properties file exists for this detector ");
102             }
103             // sanity check
104             String detectorNameFromFile = _cond.getString("detectorName");
105             if(!detectorNameFromFile.equals(event.getDetectorName()))
106             {
107                 System.out.println("detector name from HMatrix.properties: "+detectorNameFromFile +" detector name from event "+event.getDetectorName());
108                 throw new RuntimeException("detector name mismatch in HMatrix!");
109             }
110             // the vector of measurements starts as the longitudinal layers
111             _nmeas = _cond.getInt("measurementDimension");
112             // would add any additional measurements (e.g. width) here
113             _vals = new double[_nmeas];
114             
115             // add the detector name and measurement dimensionality to the output file
116             _fileLocation = event.getDetectorName()+"_"+_fileLocation+"_"+_nmeas+".hmx";
117             
118             
119             _layerMapping = _cond.getDoubleArray(_nmeas+"layerMapping");
120 //            for (int i=0; i<_layerMapping.length; ++i)
121 //            {
122 //                System.out.println("_layerMapping[ "+i+" ]= "+ _layerMapping[i]);
123 //            }
124             // sanity check
125             
126             CylindricalCalorimeter calsub = (CylindricalCalorimeter)event.getDetector().getSubdetectors().get(det[0]);
127             _nLayers = calsub.getLayering().getLayerCount();
128             if(_nLayers != _layerMapping.length)
129             {
130                 System.out.println("found "+_nLayers+" layers in the "+det[0]);
131                 throw new RuntimeException("layer number mismatch in EMCalorimeter!");
132             }
133             
134             //FIXME key needs to be better defined
135             int key = 0;
136             if(_task==HMatrixTask.ANALYZE)
137             {
138                 //FIXME need to fetch name of HMAtrix file to use from a conditions file
139                 _hmx = getConditionsManager().getCachedConditions(HMatrix.class, "LongitudinalHMatrix"+_nmeas+".hmx").getCachedData();
140             }
141             else if(_task==HMatrixTask.BUILD)
142             {
143                 _hmb = new HMatrixBuilder(_nmeas,key);
144             }
145             _detName = event.getDetectorName();
146             
147             
148             _initialized = true;
149         }
150         
151         List<Cluster> photons = new ArrayList<Cluster>();
152         for(int j=0; j<det.length; ++j)
153         {
154             List<CalorimeterHit> collection = event.get(CalorimeterHit.class,hitsToGet[j]);
155             
156             
157             double radius = 0.5;
158             double seed = 0.;
159             double minE = 0.05;
160             
161             // create the clusterer
162             FixedConeClusterer fcc = new FixedConeClusterer(radius, seed, minE, FixedConeDistanceMetric.DPHIDTHETA);
163             //cluster
164             List<Cluster> clusters = fcc.createClusters(collection);
165             
166             int minHitsInCluster = 20;
167             
168             // add this list of clusters to the event (for event display)
169             event.put(hitsToGet[j]+"Clusters ",clusters);
170             // Loop over all the clusters
171             int nGoodClusters = 0;
172             for (Cluster cluster : clusters)
173             {
174                 int ncells = cluster.getCalorimeterHits().size();
175                 double energy = cluster.getEnergy();
176                 //FIXME should cut on cluster corrected energy
177                 if(ncells > minHitsInCluster)
178                 {
179                     nGoodClusters++;
180                     
181                     aida.cloud1D("Number of cells in cluster").fill(ncells);
182                     aida.cloud2D("Number of cells in cluster vs cluster energy").fill(energy, ncells);
183                     
184                     aida.cloud2D("Hottest cell in cluster vs cluster energy").fill(energy,hottestCellEnergy(cluster));
185 //                    aida.cloud1D("Cluster raw energy").fill(bc.getRawEnergy() );
186                     aida.cloud1D("ClusterCorrected energy").fill(energy);
187                     // should be able to fetch this from the cluster...
188                     double[] layerE = layerFractionalEnergies(cluster);
189                     // accumulate the longitudinal energy fractions into the measurement vector...
190                     for(int i=0; i<layerE.length; ++i)
191                     {
192                         if(_layerMapping[i] != -1)
193                         {
194                             _vals[(int)_layerMapping[i]] += layerE[i];
195 //                            System.out.println("LayerE[ "+i+" ]= "+layerE[i]+" _vals[ "+(int)_layerMapping[i]+" ] "+_vals[(int)_layerMapping[i]]);
196                             aida.cloud2D("Fractional Energy vs physical Layer").fill(i,layerE[i]);
197                             aida.cloud2D("Fractional Energy vs mapped Layer").fill(_layerMapping[i],layerE[i]);
198                             
199                         }
200                     }
201                     
202                     for(int i=0; i<_vals.length; ++i)
203                     {
204                         aida.cloud1D("Fractional Energy for mapped Layer "+i).fill(_vals[i]);
205                         for(int k=i+1; k<_vals.length; ++k)
206                         {
207                             aida.cloud2D("Fractional Energy "+i+" vs "+k).fill(_vals[i], _vals[k]);
208                         }
209                     }
210                     
211                     // have now filled the vector of measurements. need to either accumulate the HMatrix or apply it
212                     if (_task==HMatrixTask.BUILD)
213                     {
214                         _hmb.accumulate(_vals);
215                     }
216                     if (_task==HMatrixTask.ANALYZE)
217                     {
218                         double chisq = _hmx.chisquared(_vals);
219                         aida.cloud1D("Chisq").fill(chisq);
220                         aida.cloud2D("Chisq vs energy").fill(energy,chisq);
221                         if(chisq<500)
222                         {
223                             aida.cloud1D("Chisq(<500)").fill(chisq);
224                             aida.cloud2D("Chisq (<500) vs energy").fill(energy,chisq);
225                         }
226                         aida.cloud1D("Chisq Probability").fill(ChisqProb.gammq(_nmeas,chisq));
227                         
228                         double chisqD = _hmx.chisquaredDiagonal(_vals);
229                         aida.cloud1D("ChisqD").fill(chisqD);
230                         aida.cloud2D("ChisqD vs energy").fill(energy,chisqD);
231                         
232                         double chisqDProb = ChisqProb.gammq(_nmeas,chisqD);
233                         if(chisqDProb<.0000000001) chisqDProb = 0.0000000001;
234                         aida.cloud1D("ChisqD Probability").fill(chisqDProb);
235                         aida.cloud1D("log10 ChisqDProb").fill(Math.log10(chisqDProb));
236                     }
237                     double[] pos = cluster.getPosition();
238                     aida.cloud2D("centroid x vs y").fill(pos[0], pos[1]);
239                     aida.cloud1D("centroid radius").fill( sqrt(pos[0]*pos[0] + pos[1]*pos[1]) );
240                     //
241                     // reset measurement vector...
242                     //
243                     for(int i=0; i<_vals.length; ++i)
244                     {
245                         _vals[i]=0.;
246                     }
247                 }// end over loop over clusters with greater tna minHits
248             }// end of loop over clusters
249             aida.cloud1D(det[j]+ "number of found clusters (above hits threshold)").fill(nGoodClusters);
250         }// end of loop over collections
251         event.put("photons",photons);
252     }
253     
254     private double[] layerFractionalEnergies(Cluster clus)
255     {
256         //FIXME could reuse this array
257         double[] layerEnergies = new double[_nLayers];
258         double clusterEnergy = 0.;
259         List<CalorimeterHit> hits = clus.getCalorimeterHits();
260         for(CalorimeterHit hit : hits)
261         {
262             IDDecoder decoder = hit.getIDDecoder();
263             decoder.setID(hit.getCellID());
264             double e = hit.getCorrectedEnergy();
265             int layer = decoder.getLayer();
266 //            System.out.println("layer "+layer+" energy "+e);
267             clusterEnergy+=e;
268             layerEnergies[layer]+=e;
269         }
270         for(int i=0; i<_nLayers; ++i)
271         {
272             layerEnergies[i]/=clusterEnergy;
273 //            System.out.println("i= "+i+" layerEnergies= "+layerEnergies[i]);
274         }
275 //        System.out.println(clusterEnergy+" "+clus.getEnergy());
276         return layerEnergies;
277     }
278     
279     private double hottestCellEnergy(Cluster clus)
280     {
281         double hottestCellEnergy = 0.;
282         List<CalorimeterHit> hits = clus.getCalorimeterHits();
283 //        System.out.println("New cluster with "+hits.size()+ " hits and energy "+clus.getEnergy());
284         for(CalorimeterHit hit : hits)
285         {
286             double e = hit.getCorrectedEnergy();
287             if(e>hottestCellEnergy) hottestCellEnergy=e;
288         }
289         
290         return hottestCellEnergy;
291     }
292     
293     protected void endOfData()
294     {
295         if (_task==HMatrixTask.BUILD)
296         {
297             _hmb.validate();
298             _hmb.write(_fileLocation,commentForHMatrix());
299         }
300     }
301     
302     public void setHMatrixFileLocation(String filename)
303     {
304         _fileLocation = filename;
305     }
306     
307     private String commentForHMatrix()
308     {
309         Calendar cal = new GregorianCalendar();
310         Date date = new Date();
311         cal.setTime(date);
312         DecimalFormat formatter = new DecimalFormat("00");
313         String day = formatter.format(cal.get(Calendar.DAY_OF_MONTH));
314         String month =  formatter.format(cal.get(Calendar.MONTH)+1);
315         String myDate =cal.get(Calendar.YEAR)+month+day;
316         return _detName+" "+myDate+" "+System.getProperty("user.name");
317     }
318 }