12 #include <TRotation.h>
13 #include <TParticlePDG.h>
16 #include <TDatabasePDG.h>
29 #define _SQR_(x) ((x)*(x))
44 int EicCalorimeterDigiHitProducer::UseFakeMoCaPointDatabase(
const char *dbFileName, UInt_t energyBinNum)
47 TString expandedFileName(dbFileName);
50 if (!expandedFileName.BeginsWith(
"./") && !expandedFileName.BeginsWith(
"/"))
52 TString wrkDir = getenv(
"VMCWORKDIR");
54 expandedFileName = wrkDir +
"/input/" + expandedFileName;
57 TFile dbFile(expandedFileName);
63 TTree *dbTree = (TTree*)dbFile.Get(
mDetName->
Name() +
"EicFakeMoCaPointDatabase"); assert(dbTree);
66 EicFakeMoCaPointDbEntry *dbEntry =
new EicFakeMoCaPointDbEntry();
68 TBranch *branch = dbTree->GetBranch(
"EicFakeMoCaPointDbEntry"); assert(branch);
69 branch->SetAddress(&dbEntry);
71 mFakeDB =
new EicFakeMoCaPointDatabase();
73 mFakeDB->mEnergyBinNum = energyBinNum; assert(energyBinNum);
76 dbFile.GetObject(
mDetName->
Name() +
"EnergyCutOffTable", mFakeDB->mCutOffMap);
77 assert(mFakeDB->mCutOffMap);
79 for (std::map<Int_t, std::pair<Double_t,Double_t> >::iterator
it=mFakeDB->mCutOffMap->begin();
80 it!=mFakeDB->mCutOffMap->end(); ++
it)
81 mFakeDB->mDB[
abs(
it->first)] =
new std::vector<EicFakeMoCaPointDbEntry>[mFakeDB->mEnergyBinNum];
84 unsigned evtNum = dbTree->GetEntries();
85 printf(
" -I- Importing '%s' fake MC hit database (%d DB entries) ...\n",
87 for(
unsigned evt=0; evt<evtNum; evt++)
89 dbTree->GetEntry(evt);
91 unsigned hitNum = dbEntry->fHits->GetEntriesFast();
95 TDatabasePDG *pdgTable = TDatabasePDG::Instance(); assert(pdgTable);
97 Int_t PDG = dbEntry->getPrimaryParticlePDG();
101 if (mFakeDB->mCutOffMap->find(
abs(PDG)) == mFakeDB->mCutOffMap->end())
103 printf(
"\n *** Primary mother PDG is not present in the DB map; "
104 "(must be the wrong input DB file)! ***\n\n");
108 double eLogMin = log((*mFakeDB->mCutOffMap)[
abs(PDG)].first);
109 double eLogMax = log((*mFakeDB->mCutOffMap)[
abs(PDG)].second);
110 double bWidth = (eLogMax - eLogMin)/mFakeDB->mEnergyBinNum;
112 double mass = ((TParticlePDG*)pdgTable->GetParticle(PDG))->Mass();
113 double eKin = sqrt(
mass*
mass + dbEntry->fP.Mag2()) -
mass;
114 double eLogKin = log(eKin);
115 int bId = (int)floor((eLogKin - eLogMin)/bWidth);
119 if (bId < 0 || bId >= mFakeDB->mEnergyBinNum)
121 printf(
"\n *** Primary mother energy out of range; "
122 "(must be the wrong input MC file)! ***\n\n");
127 mFakeDB->mDB[
abs(PDG)][bId].push_back(*dbEntry);
128 mFakeDB->mDB[
abs(PDG)][bId][mFakeDB->mDB[
abs(PDG)][bId].size()-1].fHits =
130 new TClonesArray(*dbEntry->fHits);
146 if (!
mDigi || !tRange || !tDim)
return -1;
167 const std::pair<TString, double> *entry =
245 const std::pair<TString, double> *entry =
251 if (entry) volumePlottingName = entry->first.Data();
267 double towerLength = cGptr ? 0.1 * cGptr->
mCellLength : 0.0, local[3];
276 printf(
"\n *** either mDigi->mZCoordDim != 1 or mDigi->mAttenuationLength != 0.0 ***\n"
277 " *** but tower length unknown, sorry! ***\n\n");
287 double midarr[3] = {middle.X(), middle.Y(), middle.Z()};
296 node->
mGeoMtx->MasterToLocal(midarr, local);
302 double zCoord = towerLength ? local[2] + towerLength/2. : 0.0;
306 int nz = towerLength ? (int)floor(zCoord/(towerLength/
mDigi->
mZCoordDim)) : 0;
321 double qTime = point->
GetTime();
334 zbin->
mTime += dE*qTime;
335 zbin->
mZ += dE*zCoord;
358 UGeo_t xyPoint = GetGptr()->remapGeantMultiIndex(point->fMultiIndex) & 0xFFFFFFFF;
359 CalorimeterLookupTableEntry *node =
360 mLookup + GetGptr()->getX(xyPoint)*mRealDim[1]*mRealDim[2] + GetGptr()->getY(xyPoint)*mRealDim[2] + GetGptr()->getZ(xyPoint);
364 node->gMtx->MasterToLocal(master, local);
371 for(
unsigned nd=0; nd<mDim3D; nd++)
373 CalorimeterLookupTableEntry *node = mLookup + nd;
375 if (!node->gNode)
continue;
378 node->gMtx->MasterToLocal(master, local);
384 if (node->gNode->GetVolume()->GetShape()->Contains(local))
return node;
405 UGeo_t xyPoint = mGeometryHub->GetGptr()->RemapMultiIndex(point->fMultiIndex) & 0xFFFFFFFF;
406 unsigned ixyzPoint[3] = {mGeometryHub->GetGptr()->GetX(xyPoint),
407 mGeometryHub->GetGptr()->GetY(xyPoint),
408 mGeometryHub->GetGptr()->GetZ(xyPoint)};
409 unsigned dMax[3], lrDist[2][3], d3Max = 0;
412 for(
unsigned iq=0; iq<3; iq++)
414 lrDist[0][iq] = ixyzPoint[iq];
415 lrDist[1][iq] = mGeometryHub->GetRealDim(iq) - ixyzPoint[iq] - 1;
416 dMax [iq] = lrDist[0][iq] > lrDist[1][iq] ? lrDist[0][iq] : lrDist[1][iq];
421 double dMinOverall = 0.0;
424 for(
unsigned dst=0; dst<d3Max; dst++)
428 for(
unsigned ix=0; ix<=dst; ix++)
429 for(
unsigned iy=0; iy<=dst-ix; iy++)
432 unsigned iz = dst - ix - iy;
435 for(
unsigned ixlr=0; ixlr<2; ixlr++)
437 if (ix > lrDist[ixlr][0])
continue;
439 unsigned idX = ixyzPoint[0] + (ixlr ? ix : -ix);
441 for(
unsigned iylr=0; iylr<2; iylr++)
443 if (iy > lrDist[iylr][1])
continue;
445 unsigned idY = ixyzPoint[1] + (iylr ? iy : -iy);
447 for(
unsigned izlr=0; izlr<2; izlr++)
449 if (iz > lrDist[izlr][2])
continue;
451 unsigned idZ = ixyzPoint[2] + (izlr ? iz : -iz);
455 CalorimeterLookupTableEntry *node =
456 mGeometryHub->mLookup + idX*mGeometryHub->mRealDim[1]*mGeometryHub->mRealDim[2] +
457 idY*mGeometryHub->mRealDim[2] + idZ;
459 if (!node->mGeoNode)
continue;
462 node->
mGeoMtx->MasterToLocal(master, local);
467 double dd = sqrt(
_SQR_(local[0]) +
_SQR_(local[1]));
474 if ((!dMinOverall || dd <= dMinOverall) &&
475 node->mGeoNode->GetVolume()->GetShape()->Contains(local))
481 if (!dMin || dd < dMin) dMin = dd;
482 if (!dMinOverall || dd < dMinOverall) dMinOverall = dd;
496 if (dMinOverall && dMin > dMinOverall)
break;
508 int EicCalorimeterDigiHitProducer::ProcessFakeMoCaPoints(
void )
512 TDatabasePDG *pdgTable = TDatabasePDG::Instance(); assert(pdgTable);
514 unsigned nEntries = fFakeMoCaPointArray->GetEntriesFast();
517 for(
unsigned iq=0; iq<nEntries; iq++)
519 EicFakeMoCaPoint *point = (EicFakeMoCaPoint*) fFakeMoCaPointArray->At(iq);
522 int PDG = point->getPDG();
523 TParticlePDG *
particle = pdgTable->GetParticle(PDG);
524 double mass = particle->Mass(), eKin = sqrt(
_SQR_(mass) + point->p().Mag2()) - mass;
527 EicFakeMoCaPointDbEntry *dbEntry = mFakeDB->getDbEntry(PDG, point->p());
532 std::cout <<
"-E- EicCalorimeterDigiHitProducer::ProcessFakeMoCaPoints(): mFakeDB->getDbEntry() returned NULL!" << std::endl;
537 double eKinDb = sqrt(
_SQR_(mass) + dbEntry->fP.Mag2()) - mass;
538 double scale = eKin / eKinDb;
540 unsigned nHits = dbEntry->fHits->GetEntriesFast();
546 TVector3 axis = dbEntry->fP.Cross(point->p());
549 double angle = dbEntry->fP.Angle(point->p()), yaangle = gRandom->Uniform(2.*TMath::Pi());
554 for(
unsigned ip=0;
ip<nHits;
ip++)
556 EicFakeMoCaPointDbHit *dbHit = (EicFakeMoCaPointDbHit*)dbEntry->fHits->At(
ip);
561 TVector3 origOffset = dbHit->getHitCoord() - dbEntry->getPrimaryVtx();
563 TVector3 rotOffset = rr.Rotate(angle, axis) * origOffset;
565 TVector3
vtx = point->vtx() + rr.Rotate(yaangle, point->p()) * rotOffset;
566 double master[3] = {vtx.x(), vtx.y(), vtx.z()}, local[3];
569 CalorimeterLookupTableEntry *node = findHitNode(point, master, local);
573 UGeo_t xy = node->gGeo;
580 &
mCells[std::pair<UInt_t, UInt_t>(xy,
mDigi->mAcknowledgePrimaryMother ? point->fPrimaryMotherId : 0)];
586 if (
mDigi->mTDim && !cell->fTimeSpectrum) cell->initializeTimeSpectrum(
mDigi->mTDim);
587 if ( !cell->mZCoordBins) cell->initializeZSpectrum (
mDigi->mZDim);
591 if (!cell->fzLen) cell->fzLen = 2*fGeoH->GetSensorDimensionsPath(point->fVolumePath)[2];
593 double zCoord = local[2] + cell->fzLen/2.;
596 int nz = (int)floor(zCoord/(cell->fzLen/
mDigi->mZDim));
598 if (nz < 0 || nz >=
mDigi->mZDim)
604 if (nz ==
mDigi->mZDim)
605 nz =
mDigi->mZDim - 1;
613 double qTime = point->GetTime();
616 double dE = scale * dbHit->getEnergyLoss();
620 zbin->fTime += dE*qTime;
621 zbin->
mZ += dE*zCoord;
626 std::cout <<
"-E- EicCalorimeterDigiHitProducer::HandleHitCore(): faled!" << std::endl;
659 if (mFakeMoCaPointArray->GetEntriesFast() && !mFakeDB)
661 std::cout <<
"-E- EicCalorimeterDigiHitProducer::PostExec(): fFakeMoCaPointArray entries present," << std::endl;
662 std::cout <<
"-E- but no fake hit database available -> forgot useFakeMoCaPointDatabase() call?" << std::endl;
669 if (mFakeDB && ProcessFakeMoCaPoints())
671 std::cout <<
"-E- EicCalorimeterDigiHitProducer::PostExec(): ProcessFakeMoCaPoints() failed!" << std::endl;
678 std::map<std::string, EnergyDeposit> EnergyDepositSum;
683 std::cout <<
"-E- EicCalorimeterDigiHitProducer::PostExec(): light yield is not defined!" << std::endl;
693 std::cout <<
"-E- EicCalorimeterDigiHitProducer::PostExec(): simulating noise "
694 "requires timing gate set!" << std::endl;
703 std::cout <<
"-E- EicCalorimeterDigiHitProducer::PostExec(): sensor type is not defined!" << std::endl;
710 std::cout <<
"-E- EicCalorimeterDigiHitProducer::PostExec(): timing control requires "
711 "light propagation velocity set!" << std::endl;
719 std::cout <<
"-E- EicCalorimeterDigiHitProducer::PostExec(): at least one of the upstream/downstream "
720 "ends should be equipped with sensors!" << std::endl;
726 const double towerLength = cGptr ? 0.1 * cGptr->
mCellLength : 0.0;
730 for (std::map<ULogicalIndex_t, CalorimeterCell>::iterator
it=
mCells.begin();
it!=
mCells.end(); ++
it) {
752 for(
unsigned ud=0; ud<2; ud++) {
770 double attenuation = 1.0, distance = ud ? towerLength - zbin->
mZ : zbin->
mZ;
807 (
mDigi->mLightYieldRescaled/2.)/
818 for(
unsigned ng=0; ng<NG; ng++)
822 if (gRandom->Uniform() > attenuation)
continue;
832 dTime += (sgroup->groupType == qREFLECTION ? distance + cell->fzLen : distance)/
838 int tid = (int)floor(dTime/
mDigi->mTBinWidth);
839 if (tid < 0 || tid >=
mDigi->mTDim)
continue;
841 cell->fTimeSpectrum[tid]++;
853 cell->mPhotonCount += 1;
864 gRandom->PoissonD(attenuation*
897 for(std::map<std::string, EnergyDeposit>::iterator itr=
it->second.mEnergyDeposits.begin();
898 itr!=
it->second.mEnergyDeposits.end(); itr++) {
901 EnergyDepositSum[itr->first].mPassive += itr->second.mPassive;
902 EnergyDepositSum[itr->first].mSensitive += itr->second.mSensitive;
903 EnergyDepositSum[itr->first].mSensitiveBirk += itr->second.mSensitiveBirk;
938 for(std::map<std::string, EnergyDeposit>::iterator itr=EnergyDepositSum.begin();
939 itr!=EnergyDepositSum.end(); itr++) {
940 printf(
"%-20s -> %9.3f MeV (passive) ... %9.3f MeV (sensitive) ->"
941 " %9.3f MeV (after Birk)\n", itr->first.c_str(),
942 1E3*itr->second.mPassive, 1E3*itr->second.mSensitive, 1E3*itr->second.mSensitiveBirk);
945 if (itr->second.mPassive)
947 std::string(
"-dE-passive")).c_str(), 1E3*itr->second.mPassive);
950 if (itr->second.mSensitive) {
952 std::string(
"-dE-sensitive")).c_str(), 1E3*itr->second.mSensitive);
955 std::string(
"-dE-sensitive-Birk")).c_str(), 1E3*itr->second.mSensitiveBirk);
974 itr->second->Write();