24 #include "G4LogicalVolumeStore.hh"
25 #include "G4LogicalVolume.hh"
29 #include "G4SystemOfUnits.hh"
30 #include "G4PhysicalConstants.hh"
31 #include "Randomize.hh"
33 #include "DD4hep/Filter.h"
59 hcalConstants_(nullptr),
60 hcalSimConstants_(nullptr),
61 m_HBDarkening(nullptr),
62 m_HEDarkening(nullptr),
81 bool dd4hep =
p.getParameter<
bool>(
"g4GeometryDD4hepSource");
83 useBirk = m_HC.getParameter<
bool>(
"UseBirkLaw");
85 birk1 = m_HC.getParameter<
double>(
"BirkC1") * bunit;
86 birk2 = m_HC.getParameter<
double>(
"BirkC2");
87 birk3 = m_HC.getParameter<
double>(
"BirkC3");
89 useParam = m_HC.getParameter<
bool>(
"UseParametrize");
90 testNumber = m_HC.getParameter<
bool>(
"TestNumberingScheme");
91 neutralDensity = m_HC.getParameter<
bool>(
"doNeutralDensityFilter");
92 usePMTHit = m_HC.getParameter<
bool>(
"UsePMTHits");
93 betaThr = m_HC.getParameter<
double>(
"BetaThreshold");
94 eminHitHB = m_HC.getParameter<
double>(
"EminHitHB") *
MeV;
95 eminHitHE = m_HC.getParameter<
double>(
"EminHitHE") *
MeV;
96 eminHitHO = m_HC.getParameter<
double>(
"EminHitHO") *
MeV;
97 eminHitHF = m_HC.getParameter<
double>(
"EminHitHF") *
MeV;
100 agingFlagHB = m_HC.getParameter<
bool>(
"HBDarkening");
101 agingFlagHE = m_HC.getParameter<
bool>(
"HEDarkening");
102 bool agingFlagHF = m_HC.getParameter<
bool>(
"HFDarkening");
103 useHF = m_HC.getUntrackedParameter<
bool>(
"UseHF",
true);
104 bool forTBHC = m_HC.getUntrackedParameter<
bool>(
"ForTBHCAL",
false);
105 bool forTBH2 = m_HC.getUntrackedParameter<
bool>(
"ForTBH2",
false);
106 useLayerWt = m_HC.getUntrackedParameter<
bool>(
"UseLayerWt",
false);
108 testNS_ = m_HC.getUntrackedParameter<
bool>(
"TestNS",
false);
110 applyFidCut = m_HF.getParameter<
bool>(
"ApplyFiducialCut");
111 bool dumpGeom = m_HC.getUntrackedParameter<
bool>(
"DumpGeometry",
false);
114 edm::LogVerbatim(
"HcalSim") <<
"***************************************************"
116 <<
"* Constructing a HCalSD with name " <<
name <<
"\n"
118 <<
"***************************************************";
121 <<
"\n Use of shower parametrization set to " <<
useParam
123 <<
"\n Use PMT Hit is set to " <<
usePMTHit <<
" with beta Threshold " <<
betaThr
125 <<
"\n Use of Birks law is set to " <<
useBirk
126 <<
" with three constants kB = " <<
birk1 / bunit <<
", C1 = " <<
birk2
127 <<
", C2 = " <<
birk3;
131 <<
" ions below " <<
kmaxIon <<
" MeV\n"
135 <<
" Flag (HB) " <<
agingFlagHB <<
" Flag (HF) " << agingFlagHF <<
"\n"
145 edm::LogError(
"HcalSim") <<
"HCalSD : Cannot find HcalDDDSimConstant";
146 throw cms::Exception(
"Unknown",
"HCalSD") <<
"Cannot find HcalDDDSimConstant\n";
150 matNames.emplace_back(
"Scintillator");
158 edm::LogError(
"HcalSim") <<
"HCalSD : Cannot find HcalDDDSimulationConstant";
159 throw cms::Exception(
"Unknown",
"HCalSD") <<
"Cannot find HcalDDDSimulationConstant\n";
174 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
176 const G4LogicalVolume* lv;
193 std::stringstream ss0;
194 ss0 <<
"HCalSD: Names to be tested for Volume = HF has " <<
hfNames.size() <<
" elements";
196 int addlevel =
dd4hep ? 1 : 0;
197 for (
unsigned int i = 0;
i <
hfNames.size(); ++
i) {
198 G4String namv(static_cast<std::string>(dd4hep::dd::noNamespace(
hfNames[
i])));
200 for (
auto lvol : *lvs) {
201 if (dd4hep::dd::noNamespace(lvol->GetName()) == namv) {
206 hfLV.emplace_back(lv);
209 ss0 <<
"\n HF[" <<
i <<
"] = " << namv <<
" LV " << lv <<
" at level " << (
temp[
i] + addlevel);
227 const G4MaterialTable* matTab = G4Material::GetMaterialTable();
228 std::vector<G4Material*>::const_iterator matite;
230 const G4Material* mat =
nullptr;
231 for (matite = matTab->begin(); matite != matTab->end(); ++matite) {
232 if (static_cast<std::string>(dd4hep::dd::noNamespace((*matite)->GetName())) == namx) {
240 std::stringstream ss1;
241 for (
unsigned int i = 0;
i <
matNames.size(); ++
i) {
242 if (
i / 10 * 10 ==
i) {
247 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Material names for HCAL: " << ss1.str();
257 std::stringstream ss2;
258 for (
unsigned int ig = 0; ig <
gpar.size(); ig++) {
259 ss2 <<
"\n gpar[" << ig <<
"] = " <<
gpar[ig] / cm <<
" cm";
262 <<
" gpar (cm)" << ss2.str();
280 for (
int i = 0;
i < 9; ++
i) {
291 if (
tfile.isAvailable()) {
292 static const char*
const labels[] = {
"HB",
303 for (
int i = 0;
i < 9; ++
i) {
305 sprintf(
name,
"HCalSDHit%d",
i);
307 sprintf(
title,
"Energy (MeV)");
309 hit_[
i]->GetYaxis()->SetTitle(
"Hits");
311 sprintf(
name,
"HCalSDTime%d",
i);
313 sprintf(
title,
"Time (ns)");
315 time_[
i]->GetYaxis()->SetTitle(
"Hits");
316 sprintf(
title,
"Longitudinal profile in %s",
labels[
i]);
317 sprintf(
name,
"HCalSDDist%d",
i);
319 sprintf(
title,
"Distance (mm)");
321 dist_[
i]->GetYaxis()->SetTitle(
"Hits");
324 hzvem = hcDir.
make<TH1F>(
"hzvem",
"Longitudinal Profile (EM Part)", 330, 0.0, 1650.0);
325 hzvem->GetXaxis()->SetTitle(
"Longitudinal Profile (EM Part)");
326 hzvhad = hcDir.
make<TH1F>(
"hzvhad",
"Longitudinal Profile (Had Part)", 330, 0.0, 1650.0);
327 hzvhad->GetXaxis()->SetTitle(
"Longitudinal Profile (Hadronic Part)");
341 const std::vector<std::string>& lvnames,
342 std::vector<const G4LogicalVolume*>& lvvec) {
343 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
344 const G4LogicalVolume* lv;
345 std::stringstream ss3;
346 ss3 <<
"HCalSD: " << lvnames.size() <<
" names to be tested for Volume <" <<
value <<
">:";
347 for (
unsigned int i = 0;
i < lvnames.size(); ++
i) {
348 G4String namv(static_cast<std::string>(dd4hep::dd::noNamespace(lvnames[
i])));
350 for (
auto lvol : *lvs) {
351 if (dd4hep::dd::noNamespace(lvol->GetName()) == namv) {
356 lvvec.emplace_back(lv);
357 if (
i / 10 * 10 ==
i) {
366 auto const track = aStep->GetTrack();
367 depth_ = (aStep->GetPreStepPoint()->GetTouchable()->GetReplicaNumber(0)) % 10;
380 G4ThreeVector hitPoint = aStep->GetPreStepPoint()->GetPosition();
381 const double invcm = 1. / CLHEP::cm;
382 double r = hitPoint.perp() * invcm;
383 double z =
std::abs(hitPoint.z()) * invcm;
384 double dose_acquired = 0.;
396 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getFromLibrary: HFLumiDarkening at "
397 <<
"r= " <<
r <<
", z= " <<
z <<
" Dose= " << dose_acquired <<
" weight= " <<
weight_;
404 G4String nameVolume = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetName();
406 <<
" for Track " <<
track->GetTrackID() <<
" ("
407 <<
track->GetDefinition()->GetParticleName() <<
")";
412 auto nameVolume = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetName();
413 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Starts shower library from " << nameVolume <<
" for Track "
414 <<
track->GetTrackID() <<
" (" <<
track->GetDefinition()->GetParticleName() <<
")";
423 <<
track->GetDefinition()->GetParticleName() <<
") kill= " << kill
431 auto const lv = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume();
432 auto const theTrack = aStep->GetTrack();
437 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Hit at Fibre in LV " << lv->GetName() <<
" for track "
438 << aStep->GetTrack()->GetTrackID() <<
" ("
439 << aStep->GetTrack()->GetDefinition()->GetParticleName() <<
")";
451 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Hit from PMT parametrization in LV " << lv->GetName() <<
" for Track "
452 << aStep->GetTrack()->GetTrackID() <<
" ("
453 << aStep->GetTrack()->GetDefinition()->GetParticleName() <<
")";
462 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Hit from straight FibreBundle in LV: " << lv->GetName() <<
" for track "
463 << aStep->GetTrack()->GetTrackID() <<
" ("
464 << aStep->GetTrack()->GetDefinition()->GetParticleName() <<
")";
473 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Hit from conical FibreBundle PV: " << lv->GetName() <<
" for track "
474 << aStep->GetTrack()->GetTrackID() <<
" ("
475 << aStep->GetTrack()->GetDefinition()->GetParticleName() <<
")";
481 destep = aStep->GetTotalEnergyDeposit();
483 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
498 lay = (touch->GetReplicaNumber(0) / 10) % 100 + 1;
501 <<
" lay: " << lay - 2;
506 G4ThreeVector hitPoint = aStep->GetPreStepPoint()->GetPosition();
531 int pdg = theTrack->GetDefinition()->GetPDGEncoding();
533 double ke = theTrack->GetKineticEnergy();
534 if (
pdg / 1000000000 == 1 && (
pdg / 10000) % 100 > 0 && (
pdg / 10) % 100 > 0 &&
ke <
kmaxIon)
544 const G4Material* mat = aStep->GetPreStepPoint()->GetMaterial();
549 double wt2 = theTrack->GetWeight();
550 double edep =
weight_ * wt1 * destep;
556 <<
" weight= " <<
weight_ <<
" wt1= " << wt1 <<
" wt2= " << wt2;
562 auto const prePoint = aStep->GetPreStepPoint();
563 auto const touch = prePoint->GetTouchable();
564 const G4ThreeVector& hitPoint = prePoint->GetPosition();
566 int depth = (touch->GetReplicaNumber(0)) % 10 + 1;
567 int lay = (touch->GetReplicaNumber(0) / 10) % 100 + 1;
568 int det = (touch->GetReplicaNumber(1)) / 1000;
575 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: updates numbering scheme for " << GetName();
587 switch (theId.subdetId()) {
624 <<
" does not match one from relabller for " <<
tmp.subdet <<
":" <<
tmp.etaR <<
":"
625 <<
tmp.phi <<
":" <<
tmp.phis <<
":" <<
tmp.depth <<
":" <<
tmp.lay << std::endl;
631 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
632 int levels = (touch->GetHistoryDepth()) + 1;
633 for (
unsigned int it = 0; it <
hfNames.size(); ++it) {
635 const G4LogicalVolume* lv = touch->GetVolume(
levels -
hfLevels[it])->GetLogicalVolume();
644 for (
const auto& nam :
hfNames)
645 if (
name == static_cast<G4String>(nam)) {
661 if (
name == static_cast<G4String>(nam)) {
668 for (
auto lvol :
pmtLV)
704 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::isItinFidVolume:#PMT= " << npmt <<
" for hit point " << hitPoint;
710 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::isItinFidVolume: point " << hitPoint <<
" return flag " <<
flag;
717 if (!isKilled ||
hits.empty()) {
726 auto const theTrack = aStep->GetTrack();
737 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getFromLibrary " <<
hits.size() <<
" hits for " << GetName() <<
" of "
738 << primaryID <<
" with " << theTrack->GetDefinition()->GetParticleName() <<
" of "
739 << aStep->GetPreStepPoint()->GetKineticEnergy() /
GeV <<
" GeV";
741 for (
unsigned int i = 0;
i <
hits.size(); ++
i) {
742 G4ThreeVector hitPoint =
hits[
i].position;
765 auto const theTrack = aStep->GetTrack();
778 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::hitForFibre " <<
hits.size() <<
" hits for " << GetName() <<
" of "
779 << primaryID <<
" with " << theTrack->GetDefinition()->GetParticleName() <<
" of "
780 << aStep->GetPreStepPoint()->GetKineticEnergy() /
GeV <<
" GeV in detector type " << det;
783 for (
unsigned int i = 0;
i <
hits.size(); ++
i) {
784 G4ThreeVector hitPoint =
hits[
i].position;
802 if (!isKilled ||
hits.empty()) {
810 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getFromParam " <<
hits.size() <<
" hits for " << GetName() <<
" of "
811 << primaryID <<
" with " << aStep->GetTrack()->GetDefinition()->GetParticleName()
812 <<
" of " << aStep->GetPreStepPoint()->GetKineticEnergy() /
GeV
813 <<
" GeV in detector type " << det;
815 for (
unsigned int i = 0;
i <
hits.size(); ++
i) {
816 G4ThreeVector hitPoint =
hits[
i].position;
831 auto const preStepPoint = aStep->GetPreStepPoint();
832 auto const theTrack = aStep->GetTrack();
837 double etrack = preStepPoint->GetKineticEnergy();
840 primaryID = theTrack->GetTrackID();
842 primaryID = theTrack->GetParentID();
844 primaryID = theTrack->GetTrackID();
850 const G4ThreeVector& hitPoint = preStepPoint->GetPosition();
851 double rr = (hitPoint.x() * hitPoint.x() + hitPoint.y() * hitPoint.y());
852 double phi = (
rr == 0. ? 0. : atan2(hitPoint.y(), hitPoint.x()));
859 if (hitPoint.z() < 0)
862 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::Hit for Detector " << det <<
" etaR " << etaR <<
" phi " <<
phi / deg
863 <<
" depth " <<
depth;
865 double time = (aStep->GetPostStepPoint()->GetGlobalTime());
879 double beta = preStepPoint->GetBeta();
880 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getHitPMT 1 hit for " << GetName() <<
" of " << primaryID <<
" with "
881 << theTrack->GetDefinition()->GetParticleName() <<
" of "
882 << preStepPoint->GetKineticEnergy() /
GeV <<
" GeV with velocity " <<
beta <<
" UnitID "
890 auto const preStepPoint = aStep->GetPreStepPoint();
891 auto const theTrack = aStep->GetTrack();
896 double etrack = preStepPoint->GetKineticEnergy();
899 primaryID = theTrack->GetTrackID();
901 primaryID = theTrack->GetParentID();
903 primaryID = theTrack->GetTrackID();
909 const G4ThreeVector& hitPoint = preStepPoint->GetPosition();
910 double rr = hitPoint.x() * hitPoint.x() + hitPoint.y() * hitPoint.y();
911 double phi =
rr == 0. ? 0. : atan2(hitPoint.y(), hitPoint.x());
918 if (hitPoint.z() < 0.)
921 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::Hit for Detector " << det <<
" etaR " << etaR <<
" phi " <<
phi / deg
922 <<
" depth " <<
depth;
924 double time = (aStep->GetPostStepPoint()->GetGlobalTime());
941 double beta = preStepPoint->GetBeta();
942 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getHitFibreBundle 1 hit for " << GetName() <<
" of " << primaryID
943 <<
" with " << theTrack->GetDefinition()->GetParticleName() <<
" of "
944 << preStepPoint->GetKineticEnergy() /
GeV <<
" GeV with velocity " <<
beta <<
" UnitID "
960 layerWeights.insert(std::pair<uint32_t, double>(
id, wt));
963 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::readWeightFromFile:Entry " <<
entry <<
" ID " << std::hex <<
id
964 <<
std::dec <<
" (" << det <<
"/" <<
zside <<
"/1/" << etaR <<
"/" <<
phi <<
"/"
965 << lay <<
") Weight " << wt;
983 std::map<uint32_t, double>::const_iterator ite =
layerWeights.find(
id);
988 <<
tmp.zside <<
"/1/" <<
tmp.etaR <<
"/" <<
tmp.phis <<
"/" <<
tmp.lay <<
") Weight "
996 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
997 static const unsigned int names = 10;
998 static const G4String modName[
names] = {
999 "HEModule",
"HVQF",
"HBModule",
"MBAT",
"MBBT",
"MBBTC",
"MBBT_R1P",
"MBBT_R1M",
"MBBT_R1PX",
"MBBT_R1MX"};
1000 G4ThreeVector
local;
1002 double depth = -2000;
1004 for (
int n = 0;
n < touch->GetHistoryDepth(); ++
n) {
1005 G4String
name(static_cast<std::string>(dd4hep::dd::noNamespace(touch->GetVolume(
n)->GetName())));
1010 if (
name == modName[
ii]) {
1012 int dn = touch->GetHistoryDepth() -
n;
1013 local = touch->GetHistory()->GetTransform(dn).TransformPoint(global);
1017 }
else if (
ii == 1) {
1020 }
else if (
ii == 2) {
1037 <<
" depth " <<
depth <<
" ID " <<
id <<
" EDEP " << edep <<
" Time " <<
time;
1045 int jd = 2 *
idx +
id - 7;
1046 if (jd >= 0 && jd < 4) {
1048 if (
hit_[jd] !=
nullptr)
1049 hit_[jd]->Fill(edep);
1050 if (
time_[jd] !=
nullptr)
1052 if (
dist_[jd] !=
nullptr)
1060 if (
hzvem !=
nullptr)
1069 if (
id.subdet == 4) {
1070 int ieta = (
id.zside == 0) ? -
id.etaR :
id.etaR;
1072 if (
id.
depth <= 2) {
1073 if (G4UniformRand() > 0.5)
1077 }
else if ((
id.subdet == 1 ||
id.subdet == 2) &&
testNumber) {
1078 id.depth = (
depth_ == 0) ? 1 : 2;