4 #include <EVENT/LCCollection.h>
5 #include <EVENT/SimCalorimeterHit.h>
6 #include <IMPL/SimCalorimeterHitImpl.h>
7 #include <IMPL/CalorimeterHitImpl.h>
8 #include <IMPL/LCCollectionVec.h>
9 #include <IMPL/LCRelationImpl.h>
10 #include <marlin/Global.h>
11 #include <gear/GEAR.h>
12 #include <gear/LayerLayout.h>
13 #include <gear/CalorimeterParameters.h>
14 #include <gear/GearParameters.h>
15 #include <EVENT/LCParameters.h>
16 #include <UTIL/CellIDDecoder.h>
17 #include <UTIL/CellIDEncoder.h>
26 #include "CLHEP/Random/RandPoisson.h"
27 #include "CLHEP/Random/RandGauss.h"
28 #include "CLHEP/Random/RandFlat.h"
31 using namespace lcio ;
32 using namespace marlin ;
37 const float pi = acos(-1.0);
45 int operator() (
int ch ) {
46 return std::tolower ( ch );
52 _description =
"Performs simple digitization of sim calo hits..." ;
54 std::vector<std::string> ecalCollections;
55 ecalCollections.push_back(std::string(
"EcalBarrelCollection"));
56 ecalCollections.push_back(std::string(
"EcalEndcapCollection"));
57 ecalCollections.push_back(std::string(
"EcalRingCollection"));
58 registerInputCollections( LCIO::SIMCALORIMETERHIT,
60 "ECAL Collection Names" ,
64 std::vector<std::string> hcalCollections;
65 hcalCollections.push_back(std::string(
"HcalBarrelRegCollection"));
66 hcalCollections.push_back(std::string(
"HcalEndcapRingsCollection"));
67 hcalCollections.push_back(std::string(
"HcalEndcapsCollection"));
68 registerInputCollections( LCIO::SIMCALORIMETERHIT,
70 "HCAL Collection Names" ,
84 registerOutputCollection( LCIO::CALORIMETERHIT,
85 "ECALOutputCollection0" ,
86 "ECAL Collection of real Hits" ,
88 std::string(
"ECALBarrel") );
91 registerOutputCollection( LCIO::CALORIMETERHIT,
92 "ECALOutputCollection1" ,
93 "ECAL Collection of real Hits" ,
95 std::string(
"ECALEndcap") );
97 registerOutputCollection( LCIO::CALORIMETERHIT,
98 "ECALOutputCollection2" ,
99 "ECAL Collection of real Hits" ,
101 std::string(
"ECALOther") ) ;
106 registerOutputCollection( LCIO::CALORIMETERHIT,
107 "HCALOutputCollection0" ,
108 "HCAL Collection of real Hits" ,
110 std::string(
"HCALBarrel") );
112 registerOutputCollection( LCIO::CALORIMETERHIT,
113 "HCALOutputCollection1" ,
114 "HCAL Collection of real Hits" ,
116 std::string(
"HCALEndcap") );
118 registerOutputCollection( LCIO::CALORIMETERHIT,
119 "HCALOutputCollection2" ,
120 "HCAL Collection of real Hits" ,
122 std::string(
"HCALOther") ) ;
124 registerOutputCollection( LCIO::LCRELATION,
125 "RelationOutputCollection" ,
126 "CaloHit Relation Collection" ,
128 std::string(
"RelationCaloHit")) ;
130 registerProcessorParameter(
"ECALThreshold" ,
131 "Threshold for ECAL Hits in GeV" ,
135 registerProcessorParameter(
"ECALThresholdUnit" ,
136 "Unit for ECAL Threshold. Can be \"GeV\", \"MIP\" or \"px\". MIP and px need properly set calibration constants" ,
141 std::vector<float> hcalThresholds;
142 hcalThresholds.push_back(0.00004);
143 registerProcessorParameter(
"HCALThreshold" ,
144 "Threshold for HCAL Hits in GeV" ,
148 registerProcessorParameter(
"HCALThresholdUnit" ,
149 "Unit for HCAL Threshold. Can be \"GeV\", \"MIP\" or \"px\". MIP and px need properly set calibration constants" ,
154 std::vector<int> ecalLayers;
155 ecalLayers.push_back(20);
156 ecalLayers.push_back(100);
157 registerProcessorParameter(
"ECALLayers" ,
158 "Index of ECal Layers" ,
162 std::vector<int> hcalLayers;
163 hcalLayers.push_back(100);
164 registerProcessorParameter(
"HCALLayers" ,
165 "Index of HCal Layers" ,
169 std::vector<float> calibrEcal;
170 calibrEcal.push_back(40.91);
171 calibrEcal.push_back(81.81);
172 registerProcessorParameter(
"CalibrECAL" ,
173 "Calibration coefficients for ECAL" ,
177 std::vector<float> calibrHcalBarrel;
178 calibrHcalBarrel.push_back(0.);
179 registerProcessorParameter(
"CalibrHCALBarrel" ,
180 "Calibration coefficients for Barrel HCAL" ,
184 std::vector<float> calibrHcalEndCap;
185 calibrHcalEndCap.push_back(0.);
186 registerProcessorParameter(
"CalibrHCALEndcap",
187 "Calibration coefficients for EndCap HCAL" ,
191 std::vector<float> calibrHcalOther;
192 calibrHcalOther.push_back(0.);
193 registerProcessorParameter(
"CalibrHCALOther" ,
194 "Calibration coefficients for Other (Ring) HCAL" ,
198 registerProcessorParameter(
"IfDigitalEcal" ,
203 registerProcessorParameter(
"MapsEcalCorrection" ,
204 "Ecal correction for theta dependency of calibration for MAPS" ,
208 registerProcessorParameter(
"IfDigitalHcal" ,
213 registerProcessorParameter(
"ECALGapCorrection" ,
214 "Correct for ECAL gaps" ,
218 registerProcessorParameter(
"HCALGapCorrection" ,
219 "Correct for ECAL gaps" ,
223 registerProcessorParameter(
"ECALEndcapCorrectionFactor" ,
224 "Energy correction for ECAL endcap" ,
228 registerProcessorParameter(
"HCALEndcapCorrectionFactor" ,
229 "Energy correction for HCAL endcap" ,
233 registerProcessorParameter(
"ECALGapCorrectionFactor" ,
234 "Factor applied to gap correction" ,
238 registerProcessorParameter(
"ECALModuleGapCorrectionFactor" ,
239 "Factor applied to module gap correction" ,
243 registerProcessorParameter(
"HCALModuleGapCorrectionFactor" ,
244 "Factor applied to module gap correction" ,
249 registerProcessorParameter(
"Histograms" ,
250 "Hit times histograms" ,
254 registerProcessorParameter(
"UseEcalTiming" ,
255 "Use ECAL hit times" ,
259 registerProcessorParameter(
"ECALCorrectTimesForPropagation" ,
260 "Correct ECAL hit times for propagation: radial distance/c" ,
264 registerProcessorParameter(
"ECALTimeWindowMin" ,
265 "ECAL Time Window minimum time in ns" ,
269 registerProcessorParameter(
"ECALEndcapTimeWindowMax" ,
270 "ECAL Endcap Time Window maximum time in ns" ,
274 registerProcessorParameter(
"ECALBarrelTimeWindowMax" ,
275 "ECAL BarrelTime Window maximum time in ns" ,
279 registerProcessorParameter(
"ECALDeltaTimeHitResolution" ,
280 "ECAL Minimum Delta Time in ns for resolving two hits" ,
284 registerProcessorParameter(
"ECALTimeResolution" ,
285 "ECAL Time Resolution used to smear hit times" ,
289 registerProcessorParameter(
"ECALSimpleTimingCut" ,
290 "Use simple time window cut on hit times? If false: use original hit-time clustering algorithm. If true: use time window defined by ECALBarrelTimeWindowMin and ECALBarrelTimeWindowMax" ,
294 registerProcessorParameter(
"UseHcalTiming" ,
295 "Use HCAL hit times" ,
299 registerProcessorParameter(
"HCALCorrectTimesForPropagation" ,
300 "Correct HCAL hit times for propagation: radial distance/c" ,
305 registerProcessorParameter(
"HCALTimeWindowMin" ,
306 "HCAL Time Window minimum time in ns" ,
310 registerProcessorParameter(
"HCALBarrelTimeWindowMax" ,
311 "HCAL Time Window maximum time in ns" ,
315 registerProcessorParameter(
"HCALEndcapTimeWindowMax" ,
316 "HCAL Time Window maximum time in ns" ,
320 registerProcessorParameter(
"HCALDeltaTimeHitResolution" ,
321 "HCAL Minimum Delta Time in ns for resolving two hits" ,
325 registerProcessorParameter(
"HCALTimeResolution" ,
326 "HCAL Time Resolution used to smear hit times" ,
330 registerProcessorParameter(
"HCALSimpleTimingCut" ,
331 "Use simple time window cut on hit times? If false: use original hit-time clustering algorithm. If true: use time window defined by HCALBarrelTimeWindowMin and HCALBarrelTimeWindowMax" ,
337 registerProcessorParameter(
"CalibECALMIP" ,
338 "calibration to convert ECAL deposited energy to MIPs" ,
342 registerProcessorParameter(
"ECAL_apply_realistic_digi" ,
343 "apply realistic digitisation to ECAL hits? (0=none, 1=silicon, 2=scintillator)" ,
347 registerProcessorParameter(
"ECAL_PPD_PE_per_MIP" ,
348 "# Photo-electrons per MIP (scintillator): used to poisson smear #PEs if >0" ,
352 registerProcessorParameter(
"ECAL_PPD_N_Pixels" ,
353 "ECAL total number of MPPC/SiPM pixels for implementation of saturation effect" ,
357 registerProcessorParameter(
"ECAL_PPD_N_Pixels_uncertainty" ,
358 "ECAL fractional uncertainty of effective total number of MPPC/SiPM pixels" ,
362 registerProcessorParameter(
"ECAL_miscalibration_uncorrel" ,
363 "uncorrelated ECAL random gaussian miscalibration (as a fraction: 1.0 = 100%) " ,
367 registerProcessorParameter(
"ECAL_miscalibration_uncorrel_memorise" ,
368 "store oncorrelated ECAL miscalbrations in memory? (WARNING: can take a lot of memory if used...) " ,
372 registerProcessorParameter(
"ECAL_miscalibration_correl" ,
373 "correlated ECAL random gaussian miscalibration (as a fraction: 1.0 = 100%) " ,
377 registerProcessorParameter(
"ECAL_deadCellRate" ,
378 "ECAL random dead cell fraction (as a fraction: 0->1) " ,
382 registerProcessorParameter(
"ECAL_deadCell_memorise" ,
383 "store dead ECAL cells in memory? (WARNING: can take a lot of memory if used...) " ,
387 registerProcessorParameter(
"ECAL_strip_absorbtionLength",
388 "length scale for absorbtion along scintillator strip (mm)",
392 registerProcessorParameter(
"ECAL_pixel_spread",
393 "variation of mppc/sipm pixels capacitance in ECAL (as a fraction: 0.01=1%)",
397 registerProcessorParameter(
"ECAL_elec_noise_mips",
398 "typical electronics noise (ECAL, in MIP units)",
402 registerProcessorParameter(
"energyPerEHpair" ,
403 "energy required to create e-h pair in silicon (in eV)" ,
407 registerProcessorParameter(
"ECAL_maxDynamicRange_MIP",
408 "maximum of dynamic range for ECAL (in MIPs)",
412 registerProcessorParameter(
"StripEcal_default_nVirtualCells",
413 "default number of virtual cells (used if not found in gear file)",
417 registerProcessorParameter(
"ECAL_default_layerConfig",
418 "default ECAL layer configuration (used if not found in gear file)",
420 std::string(
"000000000000000") );
423 registerProcessorParameter(
"CalibHCALMIP" ,
424 "calibration to convert HCAL deposited energy to MIPs" ,
428 registerProcessorParameter(
"HCAL_apply_realistic_digi" ,
429 "apply realistic digitisation to HCAL hits? (0=none, 1=scintillator/SiPM)" ,
433 registerProcessorParameter(
"HCAL_PPD_PE_per_MIP" ,
434 "# Photo-electrons per MIP (for AHCAL): used to poisson smear #PEs if >0" ,
438 registerProcessorParameter(
"HCAL_PPD_N_Pixels" ,
439 "HCAL total number of MPPC/SiPM pixels for implementation of saturation effect" ,
443 registerProcessorParameter(
"HCAL_PPD_N_Pixels_uncertainty" ,
444 "HCAL fractional uncertainty of effective total number of MPPC/SiPM pixels" ,
448 registerProcessorParameter(
"HCAL_miscalibration_uncorrel" ,
449 "uncorrelated HCAL random gaussian miscalibration (as a fraction: 1.0 = 100%) " ,
453 registerProcessorParameter(
"HCAL_miscalibration_uncorrel_memorise" ,
454 "store oncorrelated HCAL miscalbrations in memory? (WARNING: can take a lot of memory if used...) " ,
458 registerProcessorParameter(
"HCAL_miscalibration_correl" ,
459 "correlated HCAL random gaussian miscalibration (as a fraction: 1.0 = 100%) " ,
463 registerProcessorParameter(
"HCAL_deadCellRate" ,
464 "HCAL random dead cell fraction (as a fraction: 0->1) " ,
468 registerProcessorParameter(
"HCAL_deadCell_memorise" ,
469 "store dead HCAL cells in memory? (WARNING: can take a lot of memory if used...) " ,
473 registerProcessorParameter(
"HCAL_pixel_spread",
474 "variation of mppc/sipm pixels capacitance in HCAL (as a fraction: 0.01=1%)",
478 registerProcessorParameter(
"HCAL_elec_noise_mips",
479 "typical electronics noise (HCAL, in MIP units)",
483 registerProcessorParameter(
"HCAL_maxDynamicRange_MIP",
484 "maximum of dynamic range for HCAL (in MIPs)",
490 registerProcessorParameter(
"CellIDLayerString" ,
491 "name of the part of the cellID that holds the layer" ,
496 registerProcessorParameter(
"CellIDModuleString" ,
497 "name of the part of the cellID that holds the module" ,
501 registerProcessorParameter(
"CellIDStaveString" ,
502 "name of the part of the cellID that holds the stave" ,
507 registerProcessorParameter(
"CellIDIndexIString" ,
508 "name of the part of the cellID that holds the index I" ,
513 registerProcessorParameter(
"CellIDIndexJString" ,
514 "name of the part of the cellID that holds the index J" ,
529 fEcal =
new TH1F(
"fEcal",
"Ecal time profile",1000, 0., 1000.0);
530 fHcal =
new TH1F(
"fHcal",
"Hcal time profile",1000, 0., 1000.0);
532 fEcalC =
new TH1F(
"fEcalC",
"Ecal time profile cor",1000, 0., 1000.0);
533 fHcalC =
new TH1F(
"fHcalC",
"Hcal time profile cor",1000, 0., 1000.0);
535 fEcalC1 =
new TH1F(
"fEcalC1",
"Ecal time profile cor",100, 0., 1000.0);
536 fHcalC1 =
new TH1F(
"fHcalC1",
"Hcal time profile cor",100, 0., 1000.0);
538 fEcalC2 =
new TH1F(
"fEcalC2",
"Ecal time profile cor",10, 0., 1000.0);
539 fHcalC2 =
new TH1F(
"fHcalC2",
"Hcal time profile cor",10, 0., 1000.0);
541 fHcalLayer1 =
new TH2F(
"fHcalLayer1",
"Hcal layer 1 map",300, -4500., 4500.0,300,-4500,4500.);
542 fHcalLayer11 =
new TH2F(
"fHcalLayer11",
"Hcal layer 11 map",300, -4500., 4500.0,300,-4500,4500.);
543 fHcalLayer21 =
new TH2F(
"fHcalLayer21",
"Hcal layer 21 map",300, -4500., 4500.0,300,-4500,4500.);
544 fHcalLayer31 =
new TH2F(
"fHcalLayer31",
"Hcal layer 31 map",300, -4500., 4500.0,300,-4500,4500.);
545 fHcalLayer41 =
new TH2F(
"fHcalLayer41",
"Hcal layer 41 map",300, -4500., 4500.0,300,-4500,4500.);
546 fHcalLayer51 =
new TH2F(
"fHcalLayer51",
"Hcal layer 51 map",300, -4500., 4500.0,300,-4500,4500.);
547 fHcalLayer61 =
new TH2F(
"fHcalLayer61",
"Hcal layer 61 map",300, -4500., 4500.0,300,-4500,4500.);
548 fHcalLayer71 =
new TH2F(
"fHcalLayer71",
"Hcal layer 71 map",300, -4500., 4500.0,300,-4500,4500.);
549 fHcalRLayer1 =
new TH1F(
"fHcalRLayer1",
"Hcal R layer 1",50, 0., 5000.0);
550 fHcalRLayer11 =
new TH1F(
"fHcalRLayer11",
"Hcal R layer 11",50, 0., 5000.0);
551 fHcalRLayer21 =
new TH1F(
"fHcalRLayer21",
"Hcal R layer 21",50, 0., 5000.0);
552 fHcalRLayer31 =
new TH1F(
"fHcalRLayer31",
"Hcal R layer 31",50, 0., 5000.0);
553 fHcalRLayer41 =
new TH1F(
"fHcalRLayer41",
"Hcal R layer 41",50, 0., 5000.0);
554 fHcalRLayer51 =
new TH1F(
"fHcalRLayer51",
"Hcal R layer 51",50, 0., 5000.0);
555 fHcalRLayer61 =
new TH1F(
"fHcalRLayer61",
"Hcal R layer 61",50, 0., 5000.0);
556 fHcalRLayer71 =
new TH1F(
"fHcalRLayer71",
"Hcal R layer 71",50, 0., 5000.0);
557 fHcalRLayerNorm =
new TH1F(
"fHcalRLayerNorm",
"Hcal R layer Norm",50, 0., 5000.0);
559 fEcalLayer1 =
new TH2F(
"fEcalLayer1",
"Ecal layer 1 map",1800, -4500., 4500.0,1800,-4500,4500.);
560 fEcalLayer11 =
new TH2F(
"fEcalLayer11",
"Ecal layer 11 map",1800, -4500., 4500.0,1800,-4500,4500.);
561 fEcalLayer21 =
new TH2F(
"fEcalLayer21",
"Ecal layer 21 map",1800, -4500., 4500.0,1800,-4500,4500.);
562 fEcalRLayer1 =
new TH1F(
"fEcalRLayer1",
"Ecal R layer 1",100, 0., 5000.0);
563 fEcalRLayer11 =
new TH1F(
"fEcalRLayer11",
"Ecal R layer 11",100, 0., 5000.0);
564 fEcalRLayer21 =
new TH1F(
"fEcalRLayer21",
"Ecal R layer 21",100, 0., 5000.0);
565 fEcalRLayerNorm =
new TH1F(
"fEcalRLayerNorm",
"Ecal R layer Norm",100, 0., 5000.0);
574 CellIDDecoder<SimCalorimeterHit>::setDefaultEncoding(
"M:3,S-1:3,I:9,J:9,K-1:6") ;
576 const gear::GearParameters& pMokka = Global::GEAR->getGearParameters(
"MokkaParameters");
582 const gear::CalorimeterParameters& pEcalBarrel = Global::GEAR->getEcalBarrelParameters();
583 const gear::CalorimeterParameters& pEcalEndcap = Global::GEAR->getEcalEndcapParameters();
584 const gear::LayerLayout& ecalBarrelLayout = pEcalBarrel.getLayerLayout();
585 const gear::LayerLayout& ecalEndcapLayout = pEcalEndcap.getLayerLayout();
587 int symmetry = pEcalBarrel.getSymmetryOrder();
594 float nFoldSymmetry =
static_cast<float>(symmetry);
595 float phi0 = pEcalBarrel.getPhi0();
596 for(
int i=0;i<symmetry;++i){
597 float phi = phi0 + i*
twopi/nFoldSymmetry;
603 for(
int i=0;i<ecalBarrelLayout.getNLayers();++i){
609 for(
int i=0;i<ecalEndcapLayout.getNLayers();++i){
619 pEcalBarrel.getIntVal(
"Ecal_barrel_gear_per_sensitiveLayer");
620 }
catch(gear::UnknownParameterException &
e) {
621 streamlog_out (WARNING) <<
"You seem to be using an older version of the Mokka ECAL driver, affected by a bug in the gear file output" << endl;
622 streamlog_out (WARNING) <<
"If you have a mix of silicon/scintillator layers in the ECAL, this may cause some confusion" << endl;
623 streamlog_out (WARNING) <<
"You are recommended to use a later Mokka version, at least for hybrid (si+sc) ECALs" << endl;
629 streamlog_out (MESSAGE) <<
"taking number of virtual cells from calo section of gear file: " <<
_strip_virt_cells << endl;
630 }
catch(gear::UnknownParameterException &e1) {
632 std::string nVirtualMokkaS = pMokka.getStringVal(
"Ecal_Sc_number_of_virtual_cells");
636 std::stringstream convert(nVirtualMokkaS);
638 streamlog_out (ERROR) <<
"could not decipher number of virtual cells! " << nVirtualMokkaS <<
" " <<
_strip_virt_cells << endl;
642 streamlog_out (MESSAGE) <<
"taking number of virtual cells from Mokka section of gear file: " << nVirtualMokkaS <<
" " <<
_strip_virt_cells << endl;
643 }
catch(gear::UnknownParameterException &e2) {
645 streamlog_out (WARNING) <<
"taking number of virtual cells from steering file (not found in gear file): " <<
_strip_virt_cells << endl;
651 _ecalLayout = pEcalBarrel.getStringVal(
"Ecal_Barrel_Sc_Si_mix");
652 streamlog_out (MESSAGE) <<
"taking layer layout from calo sections of gear file: " <<
_ecalLayout << endl;
653 }
catch(gear::UnknownParameterException &e1) {
655 _ecalLayout = pMokka.getStringVal(
"Ecal_Sc_Si_mix");
656 streamlog_out (MESSAGE) <<
"taking layer layout from mokka section of gear file: " <<
_ecalLayout << endl;
657 }
catch(gear::UnknownParameterException &e2) {
659 streamlog_out (WARNING) <<
"taking layer layout from steering file (not found in gear file): " <<
_ecalLayout << endl;
663 }
catch(gear::UnknownParameterException &
e) {
664 streamlog_out (WARNING) <<
"WARNING, could not get ECAL gear parameters!" << endl;
678 streamlog_out(ERROR) <<
"could not identify ECAL threshold unit. Please use \"GeV\", \"MIP\" or \"px\"! Aborting." << std::endl;
696 streamlog_out(ERROR) <<
"could not identify HCAL threshold unit. Please use \"GeV\", \"MIP\" or \"px\"! Aborting." << std::endl;
709 cout <<
"ECAL sc digi:" << endl;
720 cout <<
"HCAL sc digi:" << endl;
753 _flag.setBit(LCIO::CHBIT_LONG);
754 _flag.setBit(LCIO::RCHBIT_TIME);
767 streamlog_out ( DEBUG ) <<
"looking for collection: " << colName << endl;
769 if ( colName.find(
"dummy")!=string::npos ) {
770 streamlog_out ( DEBUG ) <<
"ignoring input ECAL collection name (looks like dummy name)" << colName << endl;
776 CHT::Layout caloLayout = layoutFromString (colName);
779 LCCollection * col = evt->getCollection( colName.c_str() ) ;
780 string initString = col->getParameters().getStringVal(LCIO::CellIDEncoding);
782 CellIDDecoder<SimCalorimeterHit> idDecoder( col );
786 ecalcol->setFlag(
_flag.getFlag());
806 int numElements = col->getNumberOfElements();
807 streamlog_out ( DEBUG ) << colName <<
" number of elements = " << numElements << endl;
809 for (
int j(0); j < numElements; ++j) {
810 SimCalorimeterHit * hit =
dynamic_cast<SimCalorimeterHit*
>( col->getElementAt( j ) ) ;
811 float energy = hit->getEnergy();
815 int cellid = hit->getCellID0();
816 int cellid1 = hit->getCellID1();
825 float calibr_coeff(1.);
826 float x = hit->getPosition()[0];
827 float y = hit->getPosition()[1];
828 float z = hit->getPosition()[2];
829 float r = sqrt(x*x+y*y+z*z);
830 float rxy = sqrt(x*x+y*y);
831 float cost = fabs(z)/r;
844 if(caloLayout == CHT::barrel){
845 float correction = 1.1387 - 0.068*cost - 0.191*cost*cost;
846 calibr_coeff/=correction;
848 float correction = 0.592 + 0.590*cost;
849 calibr_coeff/=correction;
862 float dt = r/300.-0.1;
863 const unsigned int n = hit->getNMCContributions();
865 std::vector<bool> used(n,
false) ;
869 float eCellInTime = 0.;
870 float eCellOutput = 0.;
872 for(
unsigned int i =0; i<n;i++){
873 float timei = hit->getTimeCont(i);
874 float energyi = hit->getEnergyCont(i);
880 float ecor = energyi*calibr_coeff;
887 for(
unsigned int j =i+1; j<n;j++){
889 float timej = hit->getTimeCont(j);
890 float energyj = hit->getEnergyCont(j);
891 float deltat = fabs(timei-timej);
895 energySum += energyj;
902 if(energyj>energyi)timei=timej;
910 used = vector<bool>(n,
true);
911 energyi += energySum;
916 if(caloLayout == CHT::barrel){
917 float correction = 1.1387 - 0.068*cost - 0.191*cost*cost;
918 calibr_coeff/=correction;
920 float correction = 0.592 + 0.590*cost;
921 calibr_coeff/=correction;
931 fEcal->Fill(timei,energyi*calibr_coeff);
932 fEcalC->Fill(timei-dt,energyi*calibr_coeff);
933 fEcalC1->Fill(timei-dt,energyi*calibr_coeff);
934 fEcalC2->Fill(timei-dt,energyi*calibr_coeff);
943 timei = timei - timeCor;
946 CalorimeterHitImpl * calhit =
new CalorimeterHitImpl();
951 calhit->setCellID0(cellid);
952 calhit->setCellID1(cellid1);
954 calhit->setEnergy(calibr_coeff);
956 calhit->setEnergy(calibr_coeff*energyi);
960 eCellOutput+= energyi*calibr_coeff;
962 calhit->setTime(timei);
963 calhit->setPosition(hit->getPosition());
964 calhit->setType( CHT( CHT::em, CHT::ecal , caloLayout , layer ) );
965 calhit->setRawHit(hit);
966 ecalcol->addElement(calhit);
967 LCRelationImpl *rel =
new LCRelationImpl(calhit,hit,1.0);
968 relcol->addElement( rel );
976 CalorimeterHitImpl * calhit =
new CalorimeterHitImpl();
981 float energyi = hit->getEnergy();
986 calhit->setCellID0(cellid);
987 calhit->setCellID1(cellid1);
989 calhit->setEnergy(calibr_coeff);
991 calhit->setEnergy(calibr_coeff*energyi);
994 calhit->setPosition(hit->getPosition());
995 calhit->setType( CHT( CHT::em, CHT::ecal , caloLayout , layer ) );
996 calhit->setRawHit(hit);
997 ecalcol->addElement(calhit);
998 LCRelationImpl *rel =
new LCRelationImpl(calhit,hit,1.0);
999 relcol->addElement( rel );
1009 ecalcol->parameters().setValue(LCIO::CellIDEncoding,initString);
1013 catch(DataNotAvailableException &
e){
1014 streamlog_out(DEBUG) <<
"could not find input ECAL collection " << colName << std::endl;
1022 for(
float x=15;x<3000; x+=30){
1023 for(
float y=15;y<3000; y+=30){
1025 float r = sqrt(x*x+y*y);
1032 for(
float x=2.5;x<3000; x+=5){
1033 for(
float y=2.5;y<3000; y+=5){
1034 float r = sqrt(x*x+y*y);
1048 if ( colName.find(
"dummy")!=string::npos ) {
1049 streamlog_out ( DEBUG ) <<
"ignoring input HCAL collection name (looks like dummy name)" << colName << endl;
1055 CHT::Layout caloLayout = layoutFromString (colName);
1060 string initString = col->getParameters().getStringVal(LCIO::CellIDEncoding);
1061 int numElements = col->getNumberOfElements();
1062 CellIDDecoder<SimCalorimeterHit> idDecoder(col);
1064 hcalcol->setFlag(
_flag.getFlag());
1065 for (
int j(0); j < numElements; ++j) {
1066 SimCalorimeterHit * hit =
dynamic_cast<SimCalorimeterHit*
>( col->getElementAt( j ) ) ;
1067 float energy = hit->getEnergy();
1070 int cellid = hit->getCellID0();
1071 int cellid1 = hit->getCellID1();
1072 float calibr_coeff(1.);
1086 float x = hit->getPosition()[0];
1087 float y = hit->getPosition()[1];
1088 float z = hit->getPosition()[2];
1091 float hcalTimeWindowMax;
1092 if(caloLayout==CHT::barrel){
1098 float r = sqrt(x*x+y*y+z*z);
1099 float dt = r/300-0.1;
1100 const unsigned int n = hit->getNMCContributions();
1102 std::vector<bool> used(n,
false) ;
1106 for(
unsigned int i =0; i<n;i++){
1107 float timei = hit->getTimeCont(i);
1108 float energyi = hit->getEnergyCont(i);
1109 float energySum = 0;
1127 for(
unsigned int j =i; j<n;j++){
1130 float timej = hit->getTimeCont(j);
1131 float energyj = hit->getEnergyCont(j);
1132 float deltat = fabs(timei-timej);
1137 energySum += energyj;
1144 if(energyj>energyi)timei=timej;
1155 used = vector<bool>(n,
true);
1156 energyi += energySum;
1175 timei = timei - timeCor;
1178 CalorimeterHitImpl * calhit =
new CalorimeterHitImpl();
1179 calhit->setCellID0(cellid);
1180 calhit->setCellID1(cellid1);
1182 calhit->setEnergy(calibr_coeff);
1185 calhit->setEnergy(calibr_coeff*energyi);
1188 calhit->setTime(timei);
1189 calhit->setPosition(hit->getPosition());
1190 calhit->setType( CHT( CHT::had, CHT::hcal , caloLayout , layer ) );
1191 calhit->setRawHit(hit);
1192 hcalcol->addElement(calhit);
1193 LCRelationImpl *rel =
new LCRelationImpl(calhit,hit,1.0);
1194 relcol->addElement( rel );
1203 CalorimeterHitImpl * calhit =
new CalorimeterHitImpl();
1204 calhit->setCellID0(cellid);
1205 calhit->setCellID1(cellid1);
1206 float energyi = hit->getEnergy();
1214 calhit->setEnergy(calibr_coeff);
1216 calhit->setEnergy(calibr_coeff*energyi);
1220 calhit->setPosition(hit->getPosition());
1221 calhit->setType( CHT( CHT::had, CHT::hcal , caloLayout , layer ) );
1222 calhit->setRawHit(hit);
1223 hcalcol->addElement(calhit);
1224 LCRelationImpl *rel =
new LCRelationImpl(calhit,hit,1.0);
1225 relcol->addElement( rel );
1232 hcalcol->parameters().setValue(LCIO::CellIDEncoding,initString);
1235 catch(DataNotAvailableException &
e){
1236 streamlog_out(DEBUG) <<
"could not find input HCAL collection " << colName << std::endl;
1253 TFile *hfile =
new TFile(
"calTiming.root",
"recreate");
1254 fEcal->TH1F::Write();
1255 fHcal->TH1F::Write();
1321 float xi = hiti->getPosition()[0];
1322 float yi = hiti->getPosition()[1];
1323 float zi = hiti->getPosition()[2];
1328 float xj = hitj->getPosition()[0];
1329 float yj = hitj->getPosition()[1];
1330 float zj = hitj->getPosition()[2];
1331 float dz = fabs(zi-zj);
1355 if( dz > zmin && dz < zmax && dt < tminm )zgap =
true;
1356 if( dz < zminm && dt > tmin && dt < tmax )tgap =
true;
1357 if( dz > zmin && dz < zmax && dt > tmin && dt < tmax )ztgap=
true;
1359 if(modulei!=modulej){
1364 if(zgap||tgap||ztgap||mgap){
1371 float ei = hiti->getEnergy()*ecor;
1372 float ej = hitj->getEnergy()*ecor;
1373 hiti->setEnergy(ei);
1374 hitj->setEnergy(ej);
1379 float dx = fabs(xi-xj);
1380 float dy = fabs(yi-yj);
1387 float pixsizex, pixsizey;
1396 float xmin = 1.0*pixsizex+
slop;
1397 float xminm = 1.0*pixsizex-
slop;
1398 float xmax = 2.0*pixsizex-
slop;
1399 float ymin = 1.0*pixsizey+
slop;
1400 float yminm = 1.0*pixsizey-
slop;
1401 float ymax = 2.0*pixsizey-
slop;
1403 if(dx > xmin && dx < xmax && dy < yminm )xgap =
true;
1404 if(dx < xminm && dy > ymin && dy < ymax )ygap =
true;
1405 if(dx > xmin && dx < xmax && dy > ymin && dy < ymax )xygap=
true;
1407 if(xgap||ygap||xygap){
1417 if(xgap)ecor = 1.+f*(dx - pixsizex)/2./pixsizex;
1418 if(ygap)ecor = 1.+f*(dy - pixsizey)/2./pixsizey;
1419 if(xygap)ecor= 1.+f*(dx - pixsizex)*(dy - pixsizey)/4./pixsizex/pixsizey;
1423 hiti->setEnergy( hiti->getEnergy()*ecor );
1424 hitj->setEnergy( hitj->getEnergy()*ecor );
1439 float calib_coeff = 0;
1440 unsigned int ilevel = 0;
1441 for(
unsigned int ithresh=1;ithresh<
_thresholdHcal.size();ithresh++){
1449 streamlog_out(ERROR) <<
" Semi-digital level " << ilevel <<
" greater than number of HCAL Calibration Constants (" <<
_calibrCoeffHcalBarrel.size() <<
")" << std::endl;
1456 streamlog_out(ERROR) <<
" Semi-digital level " << ilevel <<
" greater than number of HCAL Calibration Constants (" <<
_calibrCoeffHcalEndCap.size() <<
")" << std::endl;
1463 streamlog_out(ERROR) <<
" Semi-digital level " << ilevel <<
" greater than number of HCAL Calibration Constants (" <<
_calibrCoeffHcalOther.size() <<
")" << std::endl;
1469 streamlog_out(ERROR) <<
" Unknown HCAL Hit Type " << std::endl;
1483 float calib_coeff = 0;
1493 if (layer >= min && layer < max) {
1506 streamlog_out(ERROR) <<
" Unknown HCAL Hit Type " << std::endl;
1517 float calib_coeff = 0;
1527 if (layer >= min && layer < max) {
1539 float calib_coeff = 0;
1550 if (layer >= min && layer < max) {
1567 float e_out(energy);
1579 std::pair <int, int> id(id0, id1);
1597 std::pair <int, int> id(id0, id1);
1606 if (thisDead ==
true){
1627 float e_out(energy);
1639 std::pair <int, int> id(id0, id1);
1657 std::pair <int, int> id(id0, id1);
1666 if (thisDead ==
true){
1687 float smeared_energy = energy*CLHEP::RandPoisson::shoot( nehpairs )/nehpairs;
1695 smeared_energy += CLHEP::RandGauss::shoot(0,
_ecal_elec_noise*_calibEcalMip);
1697 return smeared_energy;
1723 if ( stripOrientation==
SQUARE ) {
1724 streamlog_out ( ERROR ) <<
"ILDCaloDigi::combineVirtualStripCells trying to deal with silicon strips??? I do not know how to do that, refusing to do anything!" << std::endl;
1729 string initString = col->getParameters().getStringVal(LCIO::CellIDEncoding);
1730 CellIDDecoder<SimCalorimeterHit> idDecoder( col );
1734 tempstripcol->setFlag(
_flag.getFlag());
1735 CellIDEncoder<SimCalorimeterHitImpl> idEncoder( initString, tempstripcol );
1739 std::map < std::pair <int, int> , SimCalorimeterHitImpl* > newhits;
1742 int numElements = col->getNumberOfElements();
1745 float tempenergysum(0);
1746 for (
int j(0); j < numElements; ++j) {
1747 SimCalorimeterHit * hit =
dynamic_cast<SimCalorimeterHit*
>( col->getElementAt( j ) ) ;
1748 tempenergysum+=hit->getEnergy();
1751 float scTVirtLengthBar(-99);
1752 float scLVirtLengthBar(-99);
1753 float scTVirtLengthEnd(-99);
1754 float scLVirtLengthEnd(-99);
1756 for (
int j(0); j < numElements; ++j) {
1757 SimCalorimeterHit * hit =
dynamic_cast<SimCalorimeterHit*
>( col->getElementAt( j ) ) ;
1763 int gearlayer = km1+1;
1799 bool collateAlongI = isBarrel ?
1803 streamlog_out ( DEBUG ) <<
"isBarrel = " << isBarrel <<
" : stripOrientation= " << stripOrientation <<
" gear layer = " << gearlayer << endl;
1807 float virtualCellSizeAlongStrip(0);
1809 float* layerpixsize(0);
1810 float* savedPixSize(0);
1814 savedPixSize=&scTVirtLengthBar;
1817 savedPixSize=&scLVirtLengthBar;
1822 savedPixSize=&scTVirtLengthEnd;
1825 savedPixSize=&scLVirtLengthEnd;
1829 virtualCellSizeAlongStrip = layerpixsize[gearlayer];
1830 if ( virtualCellSizeAlongStrip>0 ) {
1831 if ( *savedPixSize<0 ) {
1832 *savedPixSize=virtualCellSizeAlongStrip;
1835 if ( *savedPixSize>0 ) {
1836 virtualCellSizeAlongStrip=*savedPixSize;
1839 std::vector < std::pair <int, int> > layerTypes =
getLayerConfig();
1841 streamlog_out ( DEBUG )
1842 <<
"could not get valid info from gear file..." << endl
1843 <<
"looking through previous layers to get a matching orientation" << endl
1844 <<
"this gear layer " << gearlayer <<
" type: " << layerTypes[gearlayer].first <<
" " << layerTypes[gearlayer].second << endl;
1848 for (
int il=gearlayer-1; il>=0; il--) {
1851 if ( layerTypes[il] == layerTypes[gearlayer] ) {
1852 streamlog_out ( DEBUG )
1853 <<
"found a match! " << il <<
" " <<
1854 layerTypes[il].first <<
" " << layerTypes[il].second <<
" : " << layerpixsize[il] << endl;
1855 virtualCellSizeAlongStrip=layerpixsize[il];
1856 *savedPixSize=virtualCellSizeAlongStrip;
1862 streamlog_out ( DEBUG ) <<
"virtualCellSizeAlongStrip = " << virtualCellSizeAlongStrip << endl;
1872 int relativeIndx = collateAlongI ? i_index : j_index;
1875 relativePos *= virtualCellSizeAlongStrip;
1879 float energy_new = hit->getEnergy();
1881 float energyNonuniformityScaling(1.);
1884 energy_new *= energyNonuniformityScaling;
1889 SimCalorimeterHitImpl * newhit =
new SimCalorimeterHitImpl( );
1897 idEncoder.setCellID( newhit ) ;
1899 int newid0 = newhit->getCellID0();
1900 int newid1 = newhit->getCellID1();
1902 std::pair <int, int> cellids(newid0, newid1);
1909 float stripPos[3]={0};
1912 stripPos[0] = hit->getPosition()[0];
1913 stripPos[1] = hit->getPosition()[1];
1914 stripPos[2] = hit->getPosition()[2] - relativePos;
1917 stripPos[0] = hit->getPosition()[0] - relativePos*cos(phi);
1918 stripPos[1] = hit->getPosition()[1] - relativePos*sin(phi);
1919 stripPos[2] = hit->getPosition()[2];
1922 stripPos[0] = hit->getPosition()[0];
1923 stripPos[1] = hit->getPosition()[1];
1924 stripPos[2] = hit->getPosition()[2];
1927 int xsign = m==6 ? -1 : +1;
1931 if (collateAlongI) stripPos[0] += - xsign*relativePos;
1932 else stripPos[1] += - relativePos;
1935 if (collateAlongI) stripPos[1] += + relativePos;
1936 else stripPos[0] += - xsign*relativePos;
1939 if (collateAlongI) stripPos[0] += + xsign*relativePos;
1940 else stripPos[1] += + relativePos;
1943 if (collateAlongI) stripPos[1] += - relativePos;
1944 else stripPos[0] += + xsign*relativePos;
1954 if ( newhits.find(cellids)!=newhits.end() ) {
1956 SimCalorimeterHitImpl* htt = newhits.find(cellids)->second;
1959 for (
int i=0; i<3; i++) {
1960 if ( fabs( htt->getPosition()[i] - stripPos[i] ) > 1 ) {
1966 streamlog_out ( ERROR ) <<
"strip virtual cell merging: inconsistent position calc!" << std::endl <<
1967 "please check that the parameter ECAL_strip_nVirtualCells is correctly set..." <<
getNumberOfVirtualCells() << std::endl <<
" layer = (k-1) " << km1 <<
" (gear) " << gearlayer << endl;
1970 for (
int i=0; i<3; i++) {
1971 streamlog_out ( DEBUG ) << stripPos[i] <<
" ";
1973 streamlog_out (DEBUG) << endl;
1975 for (
int i=0; i<3; i++) {
1976 streamlog_out (DEBUG) << htt->getPosition()[i] <<
" ";
1978 streamlog_out (DEBUG) << endl;
1997 newhit->setPosition(stripPos);
1998 newhits[cellids] = newhit;
1999 newhit->setEnergy( 0 );
2004 for (
int ij=0; ij<hit->getNMCContributions() ; ij++) {
2005 newhit->addMCParticleContribution( hit->getParticleCont(ij),
2006 hit->getEnergyCont(ij)*energyNonuniformityScaling,
2007 hit->getTimeCont(ij),
2008 hit->getPDGCont(ij) );
2009 eadd+=hit->getEnergyCont(ij)*energyNonuniformityScaling;
2013 for (
int ij=0; ij<newhit->getNMCContributions() ; ij++) {
2014 esum+=newhit->getEnergyCont(ij);
2019 for ( std::map < std::pair <int, int> , SimCalorimeterHitImpl* >::iterator itt = newhits.begin(); itt!=newhits.end(); itt++) {
2020 tempstripcol->addElement(itt->second);
2024 return tempstripcol;
2051 for(std::string::size_type i = 0; i <
_ecalLayout.size(); ++i) {
2095 streamlog_out (ERROR) <<
"ERROR, unknown layer type " << type << endl;
2110 streamlog_out (ERROR) <<
"collection: " << colName << endl;
2111 streamlog_out (ERROR) <<
"you seem to be trying to apply ECAL silicon digitisation to scintillator? Refusing!" << endl;
2112 streamlog_out (ERROR) <<
"check setting of ECAL_apply_realistic_digi: " <<
_applyEcalDigi << endl;
2118 streamlog_out (ERROR) <<
"collection: " << colName << endl;
2119 streamlog_out (ERROR) <<
"you seem to be trying to apply ECAL scintillator digitisation to silicon? Refusing!" << endl;
2120 streamlog_out (ERROR) <<
"check setting of ECAL_apply_realistic_digi: " <<
_applyEcalDigi << endl;
2126 streamlog_out (ERROR) <<
"collection: " << colName << endl;
2127 streamlog_out (ERROR) <<
"some inconsistency in strip orientation?" << endl;
2129 streamlog_out (ERROR) <<
" from layer config string: " << thislayersetup.second << endl;
2137 std::pair < int, int > thislayersetup(-99,-99);
2138 std::string colNameLow(colName);
2139 std::transform(colNameLow.begin(), colNameLow.end(), colNameLow.begin(), ::tolower);
2140 if ( colNameLow.find(
"presh")!=string::npos ) {
2142 streamlog_out (WARNING) <<
"preshower layer with layer index = " << layer <<
" ??? " << endl;
2146 }
else if ( colNameLow.find(
"ring")!=string::npos ) {
2149 thislayersetup = std::pair < int, int > (
SIECAL,
SQUARE);
2151 streamlog_out (WARNING) <<
"unphysical layer number? " << layer <<
" " <<
getLayerConfig().size() << endl;
2157 streamlog_out (WARNING) <<
"unphysical layer number? " << layer <<
" " <<
getLayerConfig().size() << endl;
2160 return thislayersetup;
2164 int orientation(-99);
2165 std::string colNameLow(colName);
2166 std::transform(colNameLow.begin(), colNameLow.end(), colNameLow.begin(), ::tolower);
2167 if ( colNameLow.find(
"trans")!=string::npos ) {
2169 }
else if ( colNameLow.find(
"long")!=string::npos ) {
float ecalEnergyDigi(float energy, int id0, int id1)
virtual void check(LCEvent *evt)
int getStripOrientationFromColName(std::string colName)
bool _misCalibEcal_uncorrel_keep
float digitalHcalCalibCoeff(CHT::Layout, float energy)
float _misCalibEcal_uncorrel
void setElecRange(float x)
float _ecalBarrelTimeWindowMax
float _hcalTimeResolution
float _event_correl_miscalib_ecal
float _misCalibHcal_correl
virtual void fillECALGaps()
std::string _unitThresholdHcal
ScintillatorPpdDigi * _scHcalDigi
float _barrelPixelSizeT[MAX_LAYERS]
float _hcalModuleGapCorrectionFactor
std::vector< std::pair< int, int > > & getLayerConfig()
std::map< std::pair< int, int >, bool > _ECAL_cell_dead
float analogueEcalCalibCoeff(int layer)
float _endcapPixelSizeY[MAX_LAYERS]
float analogueHcalCalibCoeff(CHT::Layout, int layer)
float _misCalibEcal_correl
void setPixSpread(float x)
std::string _ecal_deafult_layer_config
float _deadCellFractionEcal
int _ecalCorrectTimesForPropagation
float _hcalEndcapTimeWindowMax
std::vector< float > _calibrCoeffHcalEndCap
float _ecalDeltaTimeHitResolution
std::vector< float > _calibrCoeffEcal
std::string _cellIDLayerString
float _event_correl_miscalib_hcal
float _ecalGapCorrectionFactor
std::map< std::pair< int, int >, float > _HCAL_cell_miscalibs
std::vector< int > _ecalLayers
float _barrelPixelSizeZ[MAX_LAYERS]
float _barrelStaveDir[MAX_STAVES][2]
std::string _cellIDModuleString
std::string _cellIDStaveString
void setPEperMIP(float x)
std::map< std::pair< int, int >, float > _ECAL_cell_miscalibs
float _hcalBarrelTimeWindowMax
void setCalibMIP(float x)
float _misCalibHcal_uncorrel
float getDigitisedEnergy(float energy)
std::string _cellIDIndexJString
float siliconDigi(float energy)
std::vector< std::pair< int, int > > _layerTypes
LCCollection * combineVirtualStripCells(LCCollection *col, bool isBarrel, int orientation)
float _hcalDeltaTimeHitResolution
void checkConsistency(std::string colName, int layer)
bool _hcalSimpleTimingCut
std::pair< int, int > getLayerProperties(std::string colName, int layer)
std::vector< std::string > _hcalCollections
int _ecalStrip_default_nVirt
bool _ecalSimpleTimingCut
std::vector< int > _hcalLayers
float digitalEcalCalibCoeff(int layer)
std::string _unitThresholdEcal
float _ecalEndcapTimeWindowMax
std::vector< std::string > _outputEcalCollections
std::vector< LCCollection * > LCCollectionVec
std::vector< std::string > _ecalCollections
int _hcalCorrectTimesForPropagation
std::vector< float > _thresholdHcal
int getNumberOfVirtualCells()
float ahcalEnergyDigi(float energy, int id0, int id1)
std::vector< float > _calibrCoeffHcalBarrel
CLHEP::MTwistEngine * _randomEngineDeadCellHcal
float _ecalEndcapCorrectionFactor
virtual void processEvent(LCEvent *evt)
std::vector< int > _calHitsByStaveLayerModule[MAX_STAVES][MAX_LAYERS]
bool _misCalibHcal_uncorrel_keep
float _hcalEndcapCorrectionFactor
void setElecNoise(float x)
float _deadCellFractionHcal
float _ecalTimeResolution
float scintillatorDigi(float energy, bool isEcal)
float _hcal_PPD_pe_per_mip
std::vector< float > _calibrCoeffHcalOther
float _ecal_PPD_pe_per_mip
virtual void processRunHeader(LCRunHeader *run)
std::vector< CalorimeterHitImpl * > _calHitsByStaveLayer[MAX_STAVES][MAX_LAYERS]
CLHEP::MTwistEngine * _randomEngineDeadCellEcal
void setRandomMisCalibNPix(float x)
std::map< std::pair< int, int >, bool > _HCAL_cell_dead
std::string _outputRelCollection
float _ecalModuleGapCorrectionFactor
float _endcapPixelSizeX[MAX_LAYERS]
std::string _cellIDIndexIString
std::vector< std::string > _outputHcalCollections
ScintillatorPpdDigi * _scEcalDigi