2 #include <EVENT/LCCollection.h>
3 #include <EVENT/MCParticle.h>
4 #include <EVENT/SimCalorimeterHit.h>
5 #include <EVENT/CalorimeterHit.h>
6 #include <EVENT/LCFloatVec.h>
7 #include <EVENT/LCParameters.h>
8 #include <IMPL/CalorimeterHitImpl.h>
9 #include <IMPL/LCCollectionVec.h>
10 #include <IMPL/LCFlagImpl.h>
11 #include <IMPL/LCRelationImpl.h>
12 #include "UTIL/CellIDDecoder.h"
31 using namespace lcio ;
32 using namespace marlin ;
34 const float pi = acos(-1.0);
60 _description =
"Gaseous Calorimeter Digitizer: take 1mm Simulated Hits as input";
62 std::vector<std::string> ecalCollections;
63 ecalCollections.push_back(std::string(
"EcalBarrelSiliconCollection"));
64 ecalCollections.push_back(std::string(
"EcalEndcapSiliconCollection"));
65 ecalCollections.push_back(std::string(
"EcalEndcapRingCollection"));
66 registerInputCollections( LCIO::SIMCALORIMETERHIT,
68 "Input ECAL Hits Collection Names" ,
72 std::vector<std::string> outputEcalCollections;
73 outputEcalCollections.push_back(std::string(
"ECALBarrel"));
74 outputEcalCollections.push_back(std::string(
"ECALEndcap"));
75 outputEcalCollections.push_back(std::string(
"ECALOther"));
76 registerProcessorParameter(
"DigiECALCollection" ,
77 "Name of Digitized ECAL Hit Collections" ,
79 outputEcalCollections);
81 std::vector<float> calibrEcal;
82 calibrEcal.push_back(40.91);
83 calibrEcal.push_back(81.81);
84 registerProcessorParameter(
"CalibrECAL" ,
85 "Calibration coefficients for ECAL" ,
89 registerProcessorParameter(
"NumThinEcalLayer" ,
90 "Num of thiner Ecal layers" ,
94 registerProcessorParameter(
"ECALThreshold" ,
95 "Threshold for ECAL Hits in GeV" ,
99 std::vector<std::string> hcalCollections;
100 hcalCollections.push_back(std::string(
"HcalBarrelRegCollection"));
101 hcalCollections.push_back(std::string(
"HcalEndcapsCollection"));
102 hcalCollections.push_back(std::string(
"HcalEndcapRingsCollection"));
103 registerInputCollections( LCIO::SIMCALORIMETERHIT,
105 "HCAL Collection Names" ,
109 std::vector<std::string> outputHcalCollections;
110 outputHcalCollections.push_back(std::string(
"HCALBarrel"));
111 outputHcalCollections.push_back(std::string(
"HCALEndcap"));
112 outputHcalCollections.push_back(std::string(
"HCALOther"));
113 registerProcessorParameter(
"DigiHCALCollection" ,
114 "Name of Digitized HCAL Hit Collections" ,
116 outputHcalCollections);
118 std::vector<float> ChargeSpatialDistri;
119 ChargeSpatialDistri.push_back(0.1);
120 ChargeSpatialDistri.push_back(0.2);
121 ChargeSpatialDistri.push_back(0.4);
122 ChargeSpatialDistri.push_back(0.2);
123 ChargeSpatialDistri.push_back(0.1);
124 registerProcessorParameter(
"ChargeSpatialDistribution" ,
125 "Spactial Distribution of MIP charge X*Y;" ,
127 ChargeSpatialDistri);
129 std::vector<int> ShowerPositionShiftID;
130 ShowerPositionShiftID.push_back(0);
131 ShowerPositionShiftID.push_back(0);
132 ShowerPositionShiftID.push_back(0);
133 registerProcessorParameter(
"PositionShiftID" ,
134 "Global Position Shift For Overlay" ,
136 ShowerPositionShiftID);
138 registerProcessorParameter(
"DigiCellSize" ,
139 "Size of Digitized Cell (in mm)" ,
143 registerProcessorParameter(
"UsingDefaultDetector",
144 "Flag Parameter Setting (0 ~ self definition, 1 ~ MircoMegas, 2 ~ GRPC_PS, 3 ~ GRPC_SPS)",
148 registerProcessorParameter(
"PolyaParaA" ,
149 "Polya: x^A*exp(-b*x) + c" ,
153 registerProcessorParameter(
"PolyaParaB" ,
154 "Polya: x^a*exp(-B*x) + c" ,
158 registerProcessorParameter(
"PolyaParaC" ,
159 "Polya: x^a*exp(-b*x) + C" ,
163 registerProcessorParameter(
"ChanceOfKink" ,
164 "Chance of one boundary hit to create a multiple hit with boosted charge" ,
168 registerProcessorParameter(
"KinkHitChargeBoost" ,
169 "Scale factor of Charge on boosted multiple hits" ,
181 cout<<
"WARNING! Output Collections Array Smaller than Input"<<endl;
186 cout<<
"WARNING! Better Organize Charge Spatial distribution array in odd integer length"<<endl;
190 if(_UsingDefaultDetector < 0 || _UsingDefaultDetector > 4)
192 cout<<
"Parameter Flag Wrong. Need to be 0 (selfdefine), 1 (MircoMegas), 2 (GRPC_PS) or 3 (GRPC_SPS)"<<endl;
247 float PolyaDomain = 100;
252 _QPolya =
new TF1(
"QPolya",
"x^[0]*exp(-1*x*[1]) + [2]", 0, PolyaDomain);
259 int CoverAreaLength = int((SizeCSD - 1)/2);
262 cout<<
"WARNING! CoverAreaLength is too large comparing to the Digitized Cell Size: to have maximally 4 multiple hit, CoverAreaLength must <= _DigiCellSize - 1"<<endl;
266 float NormalWeightFactor = 0;
268 std::vector<float> NormalWeight(SizeCSD);
274 for(
int i0 = 0; i0 < SizeCSD; i0++ )
279 for(
int i1 = 0; i1 < SizeCSD; i1++ )
286 pair<float, float> WMatrix;
292 tmpIndex = _DigiCellSize*i2 + j2;
298 if( i2 < CoverAreaLength )
300 IndexA = CoverAreaLength - i2;
303 else if( i2 > _DigiCellSize - CoverAreaLength - 1)
305 IndexA = CoverAreaLength + i2 - _DigiCellSize + 1;
309 if( j2 < CoverAreaLength )
311 IndexB = CoverAreaLength - j2;
314 else if( j2 > _DigiCellSize - CoverAreaLength - 1)
316 IndexB = CoverAreaLength + j2 - _DigiCellSize + 1;
320 for(
int i3 = 0; i3 < CoverAreaLength; i3 ++)
322 if(i3 < IndexA) WeightA += NormalWeight[i3];
323 if(i3 < IndexB) WeightB += NormalWeight[i3];
326 WMatrix.first = SignX*WeightA;
327 WMatrix.second = SignY*WeightB;
330 cout<<WMatrix.first<<
"/"<<WMatrix.second<<
", ";
349 int tmpM, tmpS, tmpI, tmpJ, tmpK;
354 float DHChargeWeight = 0;
357 int SingleMCPPID = 0;
358 float SingleMCPPEn = 0;
364 std::vector<float> CurrWeightVec;
375 linkflag.setBit(LCIO::CHBIT_LONG);
376 relcol->setFlag(linkflag.getFlag());
378 LCCollection * MCPCol = evtP->getCollection(
"MCParticle");
379 for (
int s0(0); s0 < MCPCol->getNumberOfElements(); s0++)
381 MCParticle * a_MCP =
dynamic_cast<MCParticle*
> (MCPCol->getElementAt(s0));
382 if( a_MCP->getParents().size() == 0 )
384 SingleMCPPID = a_MCP->getPDG();
385 SingleMCPPEn = a_MCP->getEnergy();
391 flag.setBit(LCIO::CHBIT_LONG);
392 flag.setBit(LCIO::CHBIT_ID1);
393 flag.setBit(LCIO::RCHBIT_ENERGY_ERROR);
398 LCCollection *Ecalcol = evtP->getCollection(
_ecalCollections[k0].c_str() ) ;
399 CellIDDecoder<SimCalorimeterHit> idDecoder( Ecalcol );
400 int NumEcalhit = Ecalcol->getNumberOfElements();
402 ecalcol->setFlag(flag.getFlag());
403 string EcalinitString = Ecalcol->getParameters().getStringVal(LCIO::CellIDEncoding);
404 ecalcol->parameters().setValue(LCIO::CellIDEncoding, EcalinitString);
406 for(
int k1 = 0; k1 < NumEcalhit; k1++)
408 SimCalorimeterHit * SimEcalhit =
dynamic_cast<SimCalorimeterHit*
>( Ecalcol->getElementAt( k1 ) ) ;
409 HitEn = SimEcalhit->getEnergy();
410 LayerNum = idDecoder(SimEcalhit)[
"K-1"];
414 DigiHitEn = HitEn * _calibCoeffEcal[1];
417 CalorimeterHitImpl * DigiEcalhit =
new CalorimeterHitImpl();
418 DigiEcalhit->setPosition(SimEcalhit->getPosition());
419 DigiEcalhit->setCellID0(SimEcalhit->getCellID0());
420 DigiEcalhit->setCellID1(SimEcalhit->getCellID1());
421 DigiEcalhit->setEnergy(DigiHitEn);
422 ecalcol->addElement(DigiEcalhit);
423 LCRelationImpl *rel =
new LCRelationImpl(DigiEcalhit, SimEcalhit, 1.0);
424 relcol->addElement(rel);
430 }
catch(lcio::DataNotAvailableException& zero) { }
437 std::map <int, DigiHit> IDtoDigiHit;
439 std::map <int, TVector3> IDtoPos;
445 int numOrihits = col->getNumberOfElements();
446 CellIDDecoder<SimCalorimeterHit> idDecoder(col);
448 string initString =
"M:3,S-1:3,I:9,J:9,K-1:6";
449 hcalcol->parameters().setValue(LCIO::CellIDEncoding, initString);
450 hcalcol->setFlag(flag.getFlag());
452 for (
int j(0); j < numOrihits; ++j) {
453 SimCalorimeterHit * hit =
dynamic_cast<SimCalorimeterHit*
>( col->getElementAt( j ) ) ;
454 HitEn = hit->getEnergy();
456 tmpM = idDecoder(hit)[
"M"];
457 tmpS = idDecoder(hit)[
"S-1"];
458 tmpI = idDecoder(hit)[
"I"];
459 tmpJ = idDecoder(hit)[
"J"];
460 tmpK = idDecoder(hit)[
"K-1"];
462 RefPosX = hit->getPosition()[0];
463 RefPosY = hit->getPosition()[1];
464 RefPosZ = hit->getPosition()[2];
482 if(fabs(WeiI) > 1E-9)
484 DeltaI = ((WeiI > 0) ? 1: -1);
486 if(fabs(WeiJ) > 1E-9)
488 DeltaJ = ((WeiJ > 0) ? 1: -1);
493 RndCharge =
_QPolya->GetRandom();
495 CurrWeightVec.clear();
496 CurrWeightVec.push_back((1 - fabs(WeiI))*(1 - fabs(WeiJ)));
497 if(DeltaI && !DeltaJ)
499 CurrWeightVec.push_back(fabs(WeiI));
501 else if(DeltaJ && !DeltaI)
503 CurrWeightVec.push_back(fabs(WeiJ));
505 else if(DeltaI && DeltaJ)
507 CurrWeightVec.push_back(fabs(WeiI) * (1 - fabs(WeiJ)));
508 CurrWeightVec.push_back(fabs(WeiJ) * (1 - fabs(WeiI)));
509 CurrWeightVec.push_back(fabs(WeiJ*WeiI));
512 for(
int i0 = 0; i0 < int(CurrWeightVec.size()); i0++)
523 DHIndexI = CurrI + DeltaI;
529 DHIndexJ = CurrJ + DeltaJ;
534 DHIndexI = CurrI + DeltaI;
539 DHIndexI = CurrI + DeltaI;
540 DHIndexJ = CurrJ + DeltaJ;
543 DHChargeWeight = CurrWeightVec[i0];
544 DHCellID0 = (i<<30) + (tmpK<<24) + (DHIndexJ<<15) + (DHIndexI<<6) + (tmpS << 3) + tmpM;
546 if( IDtoDigiHit.find(DHCellID0) == IDtoDigiHit.end() && IDtoPos.find(DHCellID0) == IDtoPos.end() )
548 IDtoDigiHit[DHCellID0].digihitCellID0 = DHCellID0;
549 IDtoDigiHit[DHCellID0].digihitCharge = RndCharge * DHChargeWeight;
550 IDtoDigiHit[DHCellID0].digihitEnergyDepo = HitEn * DHChargeWeight;
551 IDtoDigiHit[DHCellID0].digihitNum1mmCell = 1;
552 IDtoDigiHit[DHCellID0].LeadChargeDepo = RndCharge * DHChargeWeight;
553 IDtoDigiHit[DHCellID0].LeadSimCaloHit = hit;
554 IDtoDigiHit[DHCellID0].ChargeShare = DHChargeWeight;
566 IDtoDigiHit[DHCellID0].PosZ = RefPosZ;
569 HitPos.SetXYZ(IDtoDigiHit[DHCellID0].PosX, IDtoDigiHit[DHCellID0].PosY, IDtoDigiHit[DHCellID0].PosZ);
571 IDtoPos[DHCellID0] = HitPos;
575 IDtoDigiHit[DHCellID0].digihitCharge += RndCharge * DHChargeWeight;
576 IDtoDigiHit[DHCellID0].digihitEnergyDepo += HitEn * DHChargeWeight;
577 IDtoDigiHit[DHCellID0].digihitNum1mmCell ++;
578 if(RndCharge * DHChargeWeight > IDtoDigiHit[DHCellID0].LeadChargeDepo)
580 IDtoDigiHit[DHCellID0].LeadChargeDepo = RndCharge * DHChargeWeight;
581 IDtoDigiHit[DHCellID0].LeadSimCaloHit = hit;
582 IDtoDigiHit[DHCellID0].ChargeShare = DHChargeWeight;
585 if(IDtoDigiHit[DHCellID0].PosX != IDtoPos[DHCellID0].X() )
586 cout<<
"Position Changed.........."<<endl;
595 for(std::map <int, DigiHit>::iterator ff = IDtoDigiHit.begin(); ff!=IDtoDigiHit.end(); ff++)
597 CalorimeterHitImpl * calhit =
new CalorimeterHitImpl();
598 LCRelationImpl *rel =
new LCRelationImpl(calhit, ff->second.LeadSimCaloHit, ff->second.ChargeShare);
599 relcol->addElement(rel);
601 calhit->setCellID0( ff->first );
602 calhit->setEnergy(ff->second.digihitCharge);
603 calhit->setCellID1(SingleMCPPID);
604 calhit->setEnergyError(SingleMCPPEn);
610 DigiHitPos[0] = IDtoPos[ff->first].X();
611 DigiHitPos[1] = IDtoPos[ff->first].Y();
612 DigiHitPos[2] = IDtoPos[ff->first].Z();
614 calhit->setPosition(DigiHitPos);
615 hcalcol->addElement(calhit);
621 catch (lcio::DataNotAvailableException& zero) { }
624 evtP->addCollection(relcol,
"CaloToSimuCaloLink");
626 catch (lcio::DataNotAvailableException& zero) { }
632 std::cout<<
"General Gas Digitizer FINISHED"<<std::endl;
std::vector< int > _ShowerPositionShiftID
std::vector< float > _calibCoeffEcal
std::vector< std::string > _ecalCollections
void processEvent(LCEvent *evtP)
std::map< int, std::pair< float, float > > WeightVector
float _KinkHitChargeBoost
std::vector< float > _ChargeSpatialDistri
std::vector< std::string > _hcalCollections
std::vector< std::string > _outputHcalCollections
int _UsingDefaultDetector
std::vector< LCCollection * > LCCollectionVec
std::vector< std::string > _outputEcalCollections
SimCalorimeterHit * LeadSimCaloHit