All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
LDCCaloDigi.cc
Go to the documentation of this file.
1 // Calorimeter digitiser for the LDC ECAL and HCAL
2 // For other detectors/models SimpleCaloDigi should be used
3 #include "LDCCaloDigi.h"
4 #include <EVENT/LCCollection.h>
5 #include <EVENT/SimCalorimeterHit.h>
6 #include <IMPL/CalorimeterHitImpl.h>
7 #include <IMPL/LCCollectionVec.h>
8 #include <IMPL/LCFlagImpl.h>
9 #include <IMPL/LCRelationImpl.h>
10 #include <marlin/Global.h>
11 #include <gear/GEAR.h>
12 #include <gear/GearParameters.h>
13 #include <gear/CalorimeterParameters.h>
14 #include <gear/LayerLayout.h>
15 #include <EVENT/LCParameters.h>
16 #include <UTIL/CellIDDecoder.h>
17 #include <iostream>
18 #include <string>
19 #include <cmath>
20 
21 using namespace std;
22 using namespace lcio ;
23 using namespace marlin ;
24 
25 // protect agains rounding errors
26 // will not find caps smaller than this
27 const float slop = 0.25; // (mm)
28 const float pi = acos(-1.0);
29 const float twopi = 2.0*pi;
30 
32 
33 
34 LDCCaloDigi::LDCCaloDigi() : Processor("LDCCaloDigi") {
35 
36  _description = "Performs simple digitization of sim calo hits..." ;
37 
38  std::vector<std::string> ecalCollections;
39 
40  ecalCollections.push_back(std::string("EcalBarrelCollection"));
41  ecalCollections.push_back(std::string("EcalEndcapCollection"));
42  ecalCollections.push_back(std::string("EcalRingCollection"));
43 
44  registerInputCollections( LCIO::SIMCALORIMETERHIT,
45  "ECALCollections" ,
46  "ECAL Collection Names" ,
48  ecalCollections);
49 
50  std::vector<std::string> hcalCollections;
51 
52  hcalCollections.push_back(std::string("HcalBarrelRegCollection"));
53  hcalCollections.push_back(std::string("HcalEndcapRingsCollection"));
54  hcalCollections.push_back(std::string("HcalEndcapsCollection"));
55 
56  registerInputCollections( LCIO::SIMCALORIMETERHIT,
57  "HCALCollections" ,
58  "HCAL Collection Names" ,
60  hcalCollections);
61 
62  registerOutputCollection( LCIO::CALORIMETERHIT,
63  "ECALOutputCollection" ,
64  "ECAL Collection of real Hits" ,
66  std::string("ECAL")) ;
67 
68  registerOutputCollection( LCIO::CALORIMETERHIT,
69  "HCALOutputCollection" ,
70  "HCAL Collection of real Hits" ,
72  std::string("HCAL")) ;
73 
74 
75  registerOutputCollection( LCIO::LCRELATION,
76  "RelationOutputCollection" ,
77  "CaloHit Relation Collection" ,
79  std::string("RelationCaloHit")) ;
80 
81  registerProcessorParameter("ECALThreshold" ,
82  "Threshold for ECAL Hits in GeV" ,
84  (float)5.0e-5);
85 
86  registerProcessorParameter("HCALThreshold" ,
87  "Threshold for HCAL Hits in GeV" ,
89  (float)2.5e-4);
90 
91 
92  std::vector<int> ecalLayers;
93  ecalLayers.push_back(20);
94  ecalLayers.push_back(100);
95 
96 
97  registerProcessorParameter("ECALLayers" ,
98  "Index of ECal Layers" ,
100  ecalLayers);
101 
102 
103 
104  std::vector<int> hcalLayers;
105  hcalLayers.push_back(100);
106 
107  registerProcessorParameter("HCALLayers" ,
108  "Index of HCal Layers" ,
109  _hcalLayers,
110  hcalLayers);
111 
112 
113  std::vector<float> calibrEcal;
114  calibrEcal.push_back(40.91);
115  calibrEcal.push_back(81.81);
116 
117 
118  registerProcessorParameter("CalibrECAL" ,
119  "Calibration coefficients for ECAL" ,
121  calibrEcal);
122 
123 
124  std::vector<float> calibrHcal;
125  calibrHcal.push_back(34.8);
126 
127  registerProcessorParameter("CalibrHCAL" ,
128  "Calibration coefficients for HCAL" ,
130  calibrHcal);
131 
132 
133  registerProcessorParameter("IfDigitalEcal" ,
134  "Digital Ecal" ,
135  _digitalEcal ,
136  0);
137 
138 
139  registerProcessorParameter("IfDigitalHcal" ,
140  "Digital Hcal" ,
141  _digitalHcal ,
142  0);
143 
144  registerProcessorParameter("ECALGapCorrection" ,
145  "Correct for ECAL gaps" ,
147  (int)1);
148 
149  registerProcessorParameter("ECAlEndcapCorrectionFactor" ,
150  "Energy correction for endcap" ,
152  (float)1.025);
153 
154  registerProcessorParameter("ECALGapCorrectionFactor" ,
155  "Factor applied to gap correction" ,
157  (float)1.0);
158 
159  registerProcessorParameter("ECALModuleGapCorrectionFactor" ,
160  "Factor applied to module gap correction" ,
162  (float)0.5);
163 
164 
165 }
166 
168 
169  _nRun = -1;
170  _nEvt = 0;
171 
172  //fg: need to set default encoding in for reading old files...
173  CellIDDecoder<SimCalorimeterHit>::setDefaultEncoding("M:3,S-1:3,I:9,J:9,K-1:6") ;
174 
175 }
176 
177 
178 void LDCCaloDigi::processRunHeader( LCRunHeader* /*run*/) {
179 
180  _nRun++ ;
181  _nEvt = 0;
182 
183  // Calorimeter geometry from GEAR
184  const gear::CalorimeterParameters& pEcalBarrel = Global::GEAR->getEcalBarrelParameters();
185  const gear::CalorimeterParameters& pEcalEndcap = Global::GEAR->getEcalEndcapParameters();
186  // const gear::CalorimeterParameters& pHcalBarrel = Global::GEAR->getHcalBarrelParameters();
187  // const gear::CalorimeterParameters& pHcalEndcap = Global::GEAR->getHcalEndcapParameters();
188  const gear::LayerLayout& ecalBarrelLayout = pEcalBarrel.getLayerLayout();
189  const gear::LayerLayout& ecalEndcapLayout = pEcalEndcap.getLayerLayout();
190  // const gear::LayerLayout& hcalBarrelLayout = pHcalBarrel.getLayerLayout();
191  // const gear::LayerLayout& hcalEndcapLayout = pHcalEndcap.getLayerLayout();
192 
193  // determine geometry of ECAL
194  int symmetry = pEcalBarrel.getSymmetryOrder();
195  _zOfEcalEndcap = (float)pEcalEndcap.getExtent()[2];
196 
197  // Determine ECAL polygon angles
198  // Store radial vectors perpendicular to stave layers in _ecalBarrelStaveDir
199  // ASSUMES Mokka Stave numbering 0 = top, then numbering increases anti-clockwise
200  if(symmetry>1){
201  float nFoldSymmetry = static_cast<float>(symmetry);
202  float phi0 = pEcalBarrel.getPhi0();
203  for(int i=0;i<symmetry;++i){
204  float phi = phi0 + i*twopi/nFoldSymmetry;
205  _barrelStaveDir[i][0] = cos(phi);
206  _barrelStaveDir[i][1] = sin(phi);
207  }
208  }
209 
210  for(int i=0;i<ecalBarrelLayout.getNLayers();++i){
211  _barrelPixelSizeT[i] = ecalBarrelLayout.getCellSize0(i);
212  _barrelPixelSizeZ[i] = ecalBarrelLayout.getCellSize1(i);
213  }
214 
215  for(int i=0;i<ecalEndcapLayout.getNLayers();++i){
216  _endcapPixelSizeX[i] = ecalEndcapLayout.getCellSize0(i);
217  _endcapPixelSizeY[i] = ecalEndcapLayout.getCellSize1(i);
218  }
219 
220 }
221 
222 void LDCCaloDigi::processEvent( LCEvent * evt ) {
223 
224  // create the output collections
225  LCCollectionVec *ecalcol = new LCCollectionVec(LCIO::CALORIMETERHIT);
226  LCCollectionVec *hcalcol = new LCCollectionVec(LCIO::CALORIMETERHIT);
227  LCCollectionVec *relcol = new LCCollectionVec(LCIO::LCRELATION);
228 
229  // copy the flags from the input collection
230  LCFlagImpl flag;
231  flag.setBit(LCIO::CHBIT_LONG);
232  ecalcol->setFlag(flag.getFlag());
233  hcalcol->setFlag(flag.getFlag());
234 
235  // if making gap corrections clear the vectors holding pointers to calhits
236  if(_ecalGapCorrection!=0){
237  for(int is=0;is<MAX_STAVES;is++){
238  for(int il=0;il<MAX_LAYERS;il++){
239  _calHitsByStaveLayer[is][il].clear();
240  _calHitsByStaveLayerModule[is][il].clear();
241  }
242  }
243  }
244 
245  //
246  // * Reading Collections of ECAL Simulated Hits *
247  //
248  string initString;
249  for (unsigned int i(0); i < _ecalCollections.size(); ++i) {
250  try{
251  LCCollection * col = evt->getCollection( _ecalCollections[i].c_str() ) ;
252  initString = col->getParameters().getStringVal(LCIO::CellIDEncoding);
253  int numElements = col->getNumberOfElements();
254  CellIDDecoder<SimCalorimeterHit> idDecoder( col );
255  for (int j(0); j < numElements; ++j) {
256  SimCalorimeterHit * hit = dynamic_cast<SimCalorimeterHit*>( col->getElementAt( j ) ) ;
257  float energy = hit->getEnergy();
258  // apply threshold cut
259  if (energy > _thresholdEcal) {
260  CalorimeterHitImpl * calhit = new CalorimeterHitImpl();
261  int cellid = hit->getCellID0();
262  int cellid1 = hit->getCellID1();
263  float calibr_coeff(1.);
264  int layer = idDecoder(hit)["K-1"];
265  int stave = idDecoder(hit)["S-1"];
266  int module= idDecoder(hit)["M"];
267  // save hits by module/stave/layer if required later
268  if(_ecalGapCorrection!=0){
269  _calHitsByStaveLayer[stave][layer].push_back(calhit);
270  _calHitsByStaveLayerModule[stave][layer].push_back(module);
271  }
272 
273  // retrieve calibration constants
274  for (unsigned int k(0); k < _ecalLayers.size(); ++k) {
275  int min,max;
276  if (k == 0){
277  min = 0;
278  }else{
279  min = _ecalLayers[k-1];
280  }
281  max = _ecalLayers[k];
282  if (layer >= min && layer < max) {
283  calibr_coeff = _calibrCoeffEcal[k];
284  break;
285  }
286  }
287  // apply calibration
288  if (_digitalEcal) {
289  calhit->setEnergy(calibr_coeff);
290  }
291  else {
292  // if in endcap apply additional factor to calibration to account for
293  // the difference in response due to the orientation of B wrt absorber
294  if(fabs(hit->getPosition()[2])>=_zOfEcalEndcap)energy=energy*_ecalEndcapCorrectionFactor;
295  calhit->setEnergy(calibr_coeff*energy);
296  }
297  // set other ECAL quanties
298  calhit->setPosition(hit->getPosition());
299  calhit->setType((int)0);
300  calhit->setRawHit(hit);
301  calhit->setCellID0(cellid);
302  calhit->setCellID1(cellid1);
303  ecalcol->addElement(calhit);
304  // make relation between hit and sim hit
305  LCRelationImpl *rel = new LCRelationImpl(calhit,hit,1.);
306  relcol->addElement( rel );
307  }
308 
309  }
310  }
311  catch(DataNotAvailableException &e){
312 
313  }
314  }
315 
316  // if requested apply gap corrections in ECAL ?
317  if(_ecalGapCorrection!=0)this->fillECALGaps();
318 
319  // add ECAL collection to event
320  ecalcol->parameters().setValue(LCIO::CellIDEncoding,initString);
321  evt->addCollection(ecalcol,_outputEcalCollection.c_str());
322 
323  //
324  // * Reading HCAL Collections of Simulated Hits *
325  //
326 
327  for (unsigned int i(0); i < _hcalCollections.size(); ++i) {
328  try{
329  LCCollection * col = evt->getCollection( _hcalCollections[i].c_str() ) ;
330  initString = col->getParameters().getStringVal(LCIO::CellIDEncoding);
331  int numElements = col->getNumberOfElements();
332  CellIDDecoder<SimCalorimeterHit> idDecoder(col);
333  for (int j(0); j < numElements; ++j) {
334  SimCalorimeterHit * hit = dynamic_cast<SimCalorimeterHit*>( col->getElementAt( j ) ) ;
335  float energy = hit->getEnergy();
336 
337 
338  if (energy > _thresholdHcal) {
339 
340  CalorimeterHitImpl * calhit = new CalorimeterHitImpl();
341  int cellid = hit->getCellID0();
342  int cellid1 = hit->getCellID1();
343  float calibr_coeff(1.);
344  int layer =idDecoder(hit)["K-1"];
345  for (unsigned int k(0); k < _hcalLayers.size(); ++k) {
346  int min,max;
347  if (k == 0)
348  min = 0;
349  else
350  min = _hcalLayers[k-1];
351  max = _hcalLayers[k];
352  if (layer >= min && layer < max) {
353  calibr_coeff = _calibrCoeffHcal[k];
354  break;
355  }
356  }
357  calhit->setCellID0(cellid);
358  calhit->setCellID1(cellid1);
359  if (_digitalHcal) {
360  calhit->setEnergy(calibr_coeff);
361  }
362  else {
363  calhit->setEnergy(calibr_coeff*energy);
364  }
365  calhit->setPosition(hit->getPosition());
366  calhit->setType(int(1));
367  calhit->setRawHit(hit);
368  hcalcol->addElement(calhit);
369  LCRelationImpl *rel = new LCRelationImpl(calhit,hit,1.0);
370  relcol->addElement( rel );
371  }
372 
373  }
374  }
375  catch(DataNotAvailableException &e){
376  }
377  }
378 
379  // add HCAL collection to event
380  hcalcol->parameters().setValue(LCIO::CellIDEncoding,initString);
381  evt->addCollection(hcalcol,_outputHcalCollection.c_str());
382 
383  // add relation collection for ECAL/HCAL to event
384  evt->addCollection(relcol,_outputRelCollection.c_str());
385 
386  _nEvt++;
387 
388 }
389 
390 
391 void LDCCaloDigi::check( LCEvent * /*evt*/ ) { }
392 
394 
395 
397 
398  // Loop over hits in the Barrel
399  // For each layer calculated differences in hit positions
400  // Look for gaps based on expected separation of adjacent hits
401  // loop over staves and layers
402 
403  for (int is=0; is < MAX_STAVES; ++is) {
404  for (int il=0; il < MAX_LAYERS; ++il) {
405  if(_calHitsByStaveLayer[is][il].size()>1){
406  // compare all pairs of hits just once (j>i)
407 
408  for (unsigned int i=0;i<_calHitsByStaveLayer[is][il].size()-1;++i){
409  CalorimeterHitImpl* hiti = _calHitsByStaveLayer[is][il][i];
410  int modulei = _calHitsByStaveLayerModule[is][il][i];
411  float xi = hiti->getPosition()[0];
412  float yi = hiti->getPosition()[1];
413  float zi = hiti->getPosition()[2];
414 
415  for (unsigned int j=i+1;j<_calHitsByStaveLayer[is][il].size();++j){
416  CalorimeterHitImpl* hitj = _calHitsByStaveLayer[is][il][j];
417  int modulej = _calHitsByStaveLayerModule[is][il][j];
418  float xj = hitj->getPosition()[0];
419  float yj = hitj->getPosition()[1];
420  float zj = hitj->getPosition()[2];
421  float dz = fabs(zi-zj);
422  // *** BARREL CORRECTION ***
423  if( fabs(zi)<_zOfEcalEndcap && fabs(zj)<_zOfEcalEndcap){
424  // account for stave directions using normals
425  // calculate difference in hit postions in z and along stave
426  float dx = xi-xj;
427  float dy = yi-yj;
428  float dt = fabs(dx*_barrelStaveDir[is][0] + dy*_barrelStaveDir[is][1]);
429  // flags for evidence for gaps
430  bool zgap = false; // in z direction
431  bool tgap = false; // along stave
432  bool ztgap = false; // in both z and along stave
433  bool mgap = false; // gaps between ECAL modules
434 
435  // criteria gaps in the z and t direction
436  float zminm = 1.0*_barrelPixelSizeZ[il]-slop;
437  float zmin = 1.0*_barrelPixelSizeZ[il]+slop;
438  float zmax = 2.0*_barrelPixelSizeZ[il]-slop;
439  float tminm = 1.0*_barrelPixelSizeT[il]-slop;
440  float tmin = 1.0*_barrelPixelSizeT[il]+slop;
441  float tmax = 2.0*_barrelPixelSizeT[il]-slop;
442 
443  // criteria for gaps
444  // WOULD BE BETTER TO USE GEAR TO CHECK GAPS ARE OF EXPECTED SIZE
445  if( dz > zmin && dz < zmax && dt < tminm )zgap = true;
446  if( dz < zminm && dt > tmin && dt < tmax )tgap = true;
447  if( dz > zmin && dz < zmax && dt > tmin && dt < tmax )ztgap=true;
448 
449  if(modulei!=modulej){
450  if( dz > zmin && dz < 3.0*_barrelPixelSizeZ[il]-slop && dt < tmin)mgap = true;
451  }
452 
453 
454 
455 
456  // found a gap now apply a correction based on area of gap/area of pixel
457  if(zgap||tgap||ztgap||mgap){
458  float ecor = 1.;
459  float f = _ecalGapCorrectionFactor; // fudge
460  if(mgap)f = _ecalModuleGapCorrectionFactor;
461  if(zgap||mgap)ecor = 1.+f*(dz - _barrelPixelSizeZ[il])/2./_barrelPixelSizeZ[il];
462  if(tgap)ecor = 1.+f*(dt - _barrelPixelSizeT[il])/2./_barrelPixelSizeT[il];
463  if(ztgap)ecor= 1.+f*(dt - _barrelPixelSizeT[il])*(dz - _barrelPixelSizeZ[il])/4./_barrelPixelSizeT[il]/_barrelPixelSizeZ[il];
464  float ei = hiti->getEnergy()*ecor;
465  float ej = hitj->getEnergy()*ecor;
466  hiti->setEnergy(ei);
467  hitj->setEnergy(ej);
468  }
469 
470  // *** ENDCAP CORRECTION ***
471  }else if(fabs(zi)>_zOfEcalEndcap && fabs(zj)>_zOfEcalEndcap&&dz<100){
472  float dx = fabs(xi-xj);
473  float dy = fabs(yi-yj);
474  bool xgap = false;
475  bool ygap = false;
476  bool xygap = false;
477  // criteria gaps in the z and t direction
478  float xmin = 1.0*_endcapPixelSizeX[il]+slop;
479  float xminm = 1.0*_endcapPixelSizeX[il]-slop;
480  float xmax = 2.0*_endcapPixelSizeX[il]-slop;
481  float ymin = 1.0*_endcapPixelSizeY[il]+slop;
482  float yminm = 1.0*_endcapPixelSizeY[il]-slop;
483  float ymax = 2.0*_endcapPixelSizeY[il]-slop;
484  // look for gaps
485  if(dx > xmin && dx < xmax && dy < yminm )xgap = true;
486  if(dx < xminm && dy > ymin && dy < ymax )ygap = true;
487  if(dx > xmin && dx < xmax && dy > ymin && dy < ymax )xygap=true;
488 
489  if(xgap||ygap||xygap){
490  // found a gap make correction
491  float ecor = 1.;
492  float f = _ecalGapCorrectionFactor; // fudge
493  if(xgap)ecor = 1.+f*(dx - _endcapPixelSizeX[il])/2./_endcapPixelSizeX[il];
494  if(ygap)ecor = 1.+f*(dy - _endcapPixelSizeY[il])/2./_endcapPixelSizeY[il];
495  if(xygap)ecor= 1.+f*(dx - _endcapPixelSizeX[il])*(dy - _endcapPixelSizeY[il])/4./_endcapPixelSizeX[il]/_endcapPixelSizeY[il];
496  hiti->setEnergy( hiti->getEnergy()*ecor );
497  hitj->setEnergy( hitj->getEnergy()*ecor );
498  }
499  }
500  }
501  }
502  }
503  }
504  }
505 
506  return;
507 
508 }
509 
int _ecalGapCorrection
Definition: LDCCaloDigi.h:124
std::vector< std::string > _ecalCollections
Definition: LDCCaloDigi.h:105
float _ecalModuleGapCorrectionFactor
Definition: LDCCaloDigi.h:126
const int MAX_STAVES
Definition: ILDCaloDigi.h:21
float _ecalEndcapCorrectionFactor
Definition: LDCCaloDigi.h:127
float _ecalGapCorrectionFactor
Definition: LDCCaloDigi.h:125
LDCCaloDigi aLDCCaloDigi
Definition: LDCCaloDigi.cc:31
const float pi
Definition: G2CD.cc:34
int _digitalHcal
Definition: LDCCaloDigi.h:116
std::vector< float > _calibrCoeffHcal
Definition: LDCCaloDigi.h:119
std::vector< int > _hcalLayers
Definition: LDCCaloDigi.h:122
static const float k
virtual void fillECALGaps()
Definition: LDCCaloDigi.cc:396
virtual void init()
Definition: LDCCaloDigi.cc:167
float _barrelPixelSizeT[MAX_LAYERS]
Definition: LDCCaloDigi.h:133
std::string _outputHcalCollection
Definition: LDCCaloDigi.h:109
virtual void check(LCEvent *evt)
Definition: LDCCaloDigi.cc:391
std::vector< float > _calibrCoeffEcal
Definition: LDCCaloDigi.h:118
std::vector< int > _calHitsByStaveLayerModule[MAX_STAVES][MAX_LAYERS]
Definition: LDCCaloDigi.h:130
float _thresholdHcal
Definition: LDCCaloDigi.h:113
float _barrelPixelSizeZ[MAX_LAYERS]
Definition: LDCCaloDigi.h:134
std::vector< int > _ecalLayers
Definition: LDCCaloDigi.h:121
virtual void end()
Definition: LDCCaloDigi.cc:393
std::vector< std::string > _hcalCollections
Definition: LDCCaloDigi.h:106
float _endcapPixelSizeY[MAX_LAYERS]
Definition: LDCCaloDigi.h:136
const float twopi
Definition: ILDCaloDigi.cc:38
static const float e
const int MAX_LAYERS
Definition: ILDCaloDigi.h:20
float _thresholdEcal
Definition: LDCCaloDigi.h:112
std::vector< LCCollection * > LCCollectionVec
Definition: SiStripClus.h:55
std::string _outputRelCollection
Definition: LDCCaloDigi.h:110
std::vector< CalorimeterHitImpl * > _calHitsByStaveLayer[MAX_STAVES][MAX_LAYERS]
Definition: LDCCaloDigi.h:129
float _zOfEcalEndcap
Definition: LDCCaloDigi.h:132
virtual void processRunHeader(LCRunHeader *run)
Definition: LDCCaloDigi.cc:178
int _digitalEcal
Definition: LDCCaloDigi.h:115
const float slop
Definition: ILDCaloDigi.cc:36
std::string _outputEcalCollection
Definition: LDCCaloDigi.h:108
float _barrelStaveDir[MAX_STAVES][2]
Definition: LDCCaloDigi.h:137
virtual void processEvent(LCEvent *evt)
Definition: LDCCaloDigi.cc:222
float _endcapPixelSizeX[MAX_LAYERS]
Definition: LDCCaloDigi.h:135