19 #include "G4LogicalVolumeStore.hh"
20 #include "G4LogicalVolume.hh"
24 #include "G4SystemOfUnits.hh"
25 #include "G4PhysicalConstants.hh"
26 #include "Randomize.hh"
28 #include "DD4hep/Filter.h"
58 hcalSimConstants_(hscs),
79 bool dd4hep =
p.getParameter<
bool>(
"g4GeometryDD4hepSource");
81 useBirk = m_HC.getParameter<
bool>(
"UseBirkLaw");
83 birk1 = m_HC.getParameter<
double>(
"BirkC1") * bunit;
84 birk2 = m_HC.getParameter<
double>(
"BirkC2");
85 birk3 = m_HC.getParameter<
double>(
"BirkC3");
87 useParam = m_HC.getParameter<
bool>(
"UseParametrize");
88 testNumber = m_HC.getParameter<
bool>(
"TestNumberingScheme");
89 neutralDensity = m_HC.getParameter<
bool>(
"doNeutralDensityFilter");
90 usePMTHit = m_HC.getParameter<
bool>(
"UsePMTHits");
91 betaThr = m_HC.getParameter<
double>(
"BetaThreshold");
92 eminHitHB = m_HC.getParameter<
double>(
"EminHitHB") *
MeV;
93 eminHitHE = m_HC.getParameter<
double>(
"EminHitHE") *
MeV;
94 eminHitHO = m_HC.getParameter<
double>(
"EminHitHO") *
MeV;
95 eminHitHF = m_HC.getParameter<
double>(
"EminHitHF") *
MeV;
98 agingFlagHB = m_HC.getParameter<
bool>(
"HBDarkening");
99 agingFlagHE = m_HC.getParameter<
bool>(
"HEDarkening");
100 bool agingFlagHF = m_HC.getParameter<
bool>(
"HFDarkening");
101 useHF = m_HC.getUntrackedParameter<
bool>(
"UseHF",
true);
102 bool forTBHC = m_HC.getUntrackedParameter<
bool>(
"ForTBHCAL",
false);
103 bool forTBH2 = m_HC.getUntrackedParameter<
bool>(
"ForTBH2",
false);
104 useLayerWt = m_HC.getUntrackedParameter<
bool>(
"UseLayerWt",
false);
106 testNS_ = m_HC.getUntrackedParameter<
bool>(
"TestNS",
false);
108 applyFidCut = m_HF.getParameter<
bool>(
"ApplyFiducialCut");
109 bool dumpGeom = m_HC.getUntrackedParameter<
bool>(
"DumpGeometry",
false);
112 edm::LogVerbatim(
"HcalSim") <<
"***************************************************"
114 <<
"* Constructing a HCalSD with name " <<
name <<
"\n"
116 <<
"***************************************************";
119 <<
"\n Use of shower parametrization set to " <<
useParam
121 <<
"\n Use PMT Hit is set to " <<
usePMTHit <<
" with beta Threshold " <<
betaThr
123 <<
"\n Use of Birks law is set to " <<
useBirk
124 <<
" with three constants kB = " <<
birk1 / bunit <<
", C1 = " <<
birk2
125 <<
", C2 = " <<
birk3;
129 <<
" ions below " <<
kmaxIon <<
" MeV\n"
133 <<
" Flag (HB) " <<
agingFlagHB <<
" Flag (HF) " << agingFlagHF <<
"\n"
139 matNames.emplace_back(
"Scintillator");
155 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
157 const G4LogicalVolume* lv;
174 std::stringstream ss0;
175 ss0 <<
"HCalSD: Names to be tested for Volume = HF has " <<
hfNames.size() <<
" elements";
177 int addlevel =
dd4hep ? 1 : 0;
178 for (
unsigned int i = 0;
i <
hfNames.size(); ++
i) {
179 G4String namv(static_cast<std::string>(dd4hep::dd::noNamespace(
hfNames[
i])));
181 for (
auto lvol : *lvs) {
182 if (dd4hep::dd::noNamespace(lvol->GetName()) == namv) {
187 hfLV.emplace_back(lv);
190 ss0 <<
"\n HF[" <<
i <<
"] = " << namv <<
" LV " << lv <<
" at level " << (
temp[
i] + addlevel);
208 const G4MaterialTable* matTab = G4Material::GetMaterialTable();
209 std::vector<G4Material*>::const_iterator matite;
211 const G4Material* mat =
nullptr;
212 for (matite = matTab->begin(); matite != matTab->end(); ++matite) {
213 if (static_cast<std::string>(dd4hep::dd::noNamespace((*matite)->GetName())) == namx) {
221 std::stringstream ss1;
222 for (
unsigned int i = 0;
i <
matNames.size(); ++
i) {
223 if (
i / 10 * 10 ==
i) {
228 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Material names for HCAL: " << ss1.str();
238 std::stringstream ss2;
239 for (
unsigned int ig = 0; ig <
gpar.size(); ig++) {
240 ss2 <<
"\n gpar[" << ig <<
"] = " <<
gpar[ig] / cm <<
" cm";
243 <<
" gpar (cm)" << ss2.str();
250 for (
int i = 0;
i < 9; ++
i) {
261 if (
tfile.isAvailable()) {
262 static const char*
const labels[] = {
"HB",
273 for (
int i = 0;
i < 9; ++
i) {
275 sprintf(
name,
"HCalSDHit%d",
i);
277 sprintf(
title,
"Energy (MeV)");
279 hit_[
i]->GetYaxis()->SetTitle(
"Hits");
281 sprintf(
name,
"HCalSDTime%d",
i);
283 sprintf(
title,
"Time (ns)");
285 time_[
i]->GetYaxis()->SetTitle(
"Hits");
286 sprintf(
title,
"Longitudinal profile in %s",
labels[
i]);
287 sprintf(
name,
"HCalSDDist%d",
i);
289 sprintf(
title,
"Distance (mm)");
291 dist_[
i]->GetYaxis()->SetTitle(
"Hits");
294 hzvem = hcDir.
make<TH1F>(
"hzvem",
"Longitudinal Profile (EM Part)", 330, 0.0, 1650.0);
295 hzvem->GetXaxis()->SetTitle(
"Longitudinal Profile (EM Part)");
296 hzvhad = hcDir.
make<TH1F>(
"hzvhad",
"Longitudinal Profile (Had Part)", 330, 0.0, 1650.0);
297 hzvhad->GetXaxis()->SetTitle(
"Longitudinal Profile (Hadronic Part)");
311 const std::vector<std::string>& lvnames,
312 std::vector<const G4LogicalVolume*>& lvvec) {
313 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
314 const G4LogicalVolume* lv;
315 std::stringstream ss3;
316 ss3 <<
"HCalSD: " << lvnames.size() <<
" names to be tested for Volume <" <<
value <<
">:";
317 for (
unsigned int i = 0;
i < lvnames.size(); ++
i) {
318 G4String namv(static_cast<std::string>(dd4hep::dd::noNamespace(lvnames[
i])));
320 for (
auto lvol : *lvs) {
321 if (dd4hep::dd::noNamespace(lvol->GetName()) == namv) {
326 lvvec.emplace_back(lv);
327 if (
i / 10 * 10 ==
i) {
336 auto const track = aStep->GetTrack();
337 depth_ = (aStep->GetPreStepPoint()->GetTouchable()->GetReplicaNumber(0)) % 10;
350 G4ThreeVector hitPoint = aStep->GetPreStepPoint()->GetPosition();
351 const double invcm = 1. / CLHEP::cm;
352 double r = hitPoint.perp() * invcm;
353 double z =
std::abs(hitPoint.z()) * invcm;
354 double dose_acquired = 0.;
366 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getFromLibrary: HFLumiDarkening at "
367 <<
"r= " <<
r <<
", z= " <<
z <<
" Dose= " << dose_acquired <<
" weight= " <<
weight_;
374 G4String nameVolume = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetName();
376 <<
" for Track " <<
track->GetTrackID() <<
" ("
377 <<
track->GetDefinition()->GetParticleName() <<
")";
382 auto nameVolume = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetName();
383 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Starts shower library from " << nameVolume <<
" for Track "
384 <<
track->GetTrackID() <<
" (" <<
track->GetDefinition()->GetParticleName() <<
")";
393 <<
track->GetDefinition()->GetParticleName() <<
") kill= " << kill
401 auto const lv = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume();
402 auto const theTrack = aStep->GetTrack();
407 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Hit at Fibre in LV " << lv->GetName() <<
" for track "
408 << aStep->GetTrack()->GetTrackID() <<
" ("
409 << aStep->GetTrack()->GetDefinition()->GetParticleName() <<
")";
421 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Hit from PMT parametrization in LV " << lv->GetName() <<
" for Track "
422 << aStep->GetTrack()->GetTrackID() <<
" ("
423 << aStep->GetTrack()->GetDefinition()->GetParticleName() <<
")";
432 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Hit from straight FibreBundle in LV: " << lv->GetName() <<
" for track "
433 << aStep->GetTrack()->GetTrackID() <<
" ("
434 << aStep->GetTrack()->GetDefinition()->GetParticleName() <<
")";
443 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: Hit from conical FibreBundle PV: " << lv->GetName() <<
" for track "
444 << aStep->GetTrack()->GetTrackID() <<
" ("
445 << aStep->GetTrack()->GetDefinition()->GetParticleName() <<
")";
451 destep = aStep->GetTotalEnergyDeposit();
453 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
468 lay = (touch->GetReplicaNumber(0) / 10) % 100 + 1;
471 <<
" lay: " << lay - 2;
476 G4ThreeVector hitPoint = aStep->GetPreStepPoint()->GetPosition();
501 int pdg = theTrack->GetDefinition()->GetPDGEncoding();
503 double ke = theTrack->GetKineticEnergy();
504 if (
pdg / 1000000000 == 1 && (
pdg / 10000) % 100 > 0 && (
pdg / 10) % 100 > 0 &&
ke <
kmaxIon)
515 const G4Material* mat = aStep->GetPreStepPoint()->GetMaterial();
521 double wt2 = theTrack->GetWeight();
522 double edep =
weight_ * wt1 * destep;
528 <<
" weight= " <<
weight_ <<
" wt0= " << wt0 <<
" wt1= " << wt1 <<
" wt2= " << wt2;
534 auto const prePoint = aStep->GetPreStepPoint();
535 auto const touch = prePoint->GetTouchable();
536 const G4ThreeVector& hitPoint = prePoint->GetPosition();
538 int depth = (touch->GetReplicaNumber(0)) % 10 + 1;
539 int lay = (touch->GetReplicaNumber(0) / 10) % 100 + 1;
540 int det = (touch->GetReplicaNumber(1)) / 1000;
547 edm::LogVerbatim(
"HcalSim") <<
"HCalSD: updates numbering scheme for " << GetName();
559 switch (theId.subdetId()) {
596 <<
" does not match one from relabller for " <<
tmp.subdet <<
":" <<
tmp.etaR <<
":"
597 <<
tmp.phi <<
":" <<
tmp.phis <<
":" <<
tmp.depth <<
":" <<
tmp.lay << std::endl;
603 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
604 int levels = (touch->GetHistoryDepth()) + 1;
605 for (
unsigned int it = 0; it <
hfNames.size(); ++it) {
607 const G4LogicalVolume* lv = touch->GetVolume(
levels -
hfLevels[it])->GetLogicalVolume();
616 for (
const auto& nam :
hfNames)
617 if (
name == static_cast<G4String>(nam)) {
633 if (
name == static_cast<G4String>(nam)) {
640 for (
auto lvol :
pmtLV)
676 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::isItinFidVolume:#PMT= " << npmt <<
" for hit point " << hitPoint;
682 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::isItinFidVolume: point " << hitPoint <<
" return flag " <<
flag;
689 if (!isKilled ||
hits.empty()) {
698 auto const theTrack = aStep->GetTrack();
709 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getFromLibrary " <<
hits.size() <<
" hits for " << GetName() <<
" of "
710 << primaryID <<
" with " << theTrack->GetDefinition()->GetParticleName() <<
" of "
711 << aStep->GetPreStepPoint()->GetKineticEnergy() /
GeV <<
" GeV";
713 for (
unsigned int i = 0;
i <
hits.size(); ++
i) {
714 G4ThreeVector hitPoint =
hits[
i].position;
737 auto const theTrack = aStep->GetTrack();
750 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::hitForFibre " <<
hits.size() <<
" hits for " << GetName() <<
" of "
751 << primaryID <<
" with " << theTrack->GetDefinition()->GetParticleName() <<
" of "
752 << aStep->GetPreStepPoint()->GetKineticEnergy() /
GeV <<
" GeV in detector type " << det;
755 for (
unsigned int i = 0;
i <
hits.size(); ++
i) {
756 G4ThreeVector hitPoint =
hits[
i].position;
774 if (!isKilled ||
hits.empty()) {
782 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getFromParam " <<
hits.size() <<
" hits for " << GetName() <<
" of "
783 << primaryID <<
" with " << aStep->GetTrack()->GetDefinition()->GetParticleName()
784 <<
" of " << aStep->GetPreStepPoint()->GetKineticEnergy() /
GeV
785 <<
" GeV in detector type " << det;
787 for (
unsigned int i = 0;
i <
hits.size(); ++
i) {
788 G4ThreeVector hitPoint =
hits[
i].position;
803 auto const preStepPoint = aStep->GetPreStepPoint();
804 auto const theTrack = aStep->GetTrack();
809 double etrack = preStepPoint->GetKineticEnergy();
812 primaryID = theTrack->GetTrackID();
814 primaryID = theTrack->GetParentID();
816 primaryID = theTrack->GetTrackID();
822 const G4ThreeVector& hitPoint = preStepPoint->GetPosition();
823 double rr = (hitPoint.x() * hitPoint.x() + hitPoint.y() * hitPoint.y());
824 double phi = (
rr == 0. ? 0. : atan2(hitPoint.y(), hitPoint.x()));
831 if (hitPoint.z() < 0)
834 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::Hit for Detector " << det <<
" etaR " << etaR <<
" phi " <<
phi / deg
835 <<
" depth " <<
depth;
837 double time = (aStep->GetPostStepPoint()->GetGlobalTime());
851 double beta = preStepPoint->GetBeta();
852 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getHitPMT 1 hit for " << GetName() <<
" of " << primaryID <<
" with "
853 << theTrack->GetDefinition()->GetParticleName() <<
" of "
854 << preStepPoint->GetKineticEnergy() /
GeV <<
" GeV with velocity " <<
beta <<
" UnitID "
862 auto const preStepPoint = aStep->GetPreStepPoint();
863 auto const theTrack = aStep->GetTrack();
868 double etrack = preStepPoint->GetKineticEnergy();
871 primaryID = theTrack->GetTrackID();
873 primaryID = theTrack->GetParentID();
875 primaryID = theTrack->GetTrackID();
881 const G4ThreeVector& hitPoint = preStepPoint->GetPosition();
882 double rr = hitPoint.x() * hitPoint.x() + hitPoint.y() * hitPoint.y();
883 double phi =
rr == 0. ? 0. : atan2(hitPoint.y(), hitPoint.x());
890 if (hitPoint.z() < 0.)
893 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::Hit for Detector " << det <<
" etaR " << etaR <<
" phi " <<
phi / deg
894 <<
" depth " <<
depth;
896 double time = (aStep->GetPostStepPoint()->GetGlobalTime());
913 double beta = preStepPoint->GetBeta();
914 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::getHitFibreBundle 1 hit for " << GetName() <<
" of " << primaryID
915 <<
" with " << theTrack->GetDefinition()->GetParticleName() <<
" of "
916 << preStepPoint->GetKineticEnergy() /
GeV <<
" GeV with velocity " <<
beta <<
" UnitID "
932 layerWeights.insert(std::pair<uint32_t, double>(
id, wt));
935 edm::LogVerbatim(
"HcalSim") <<
"HCalSD::readWeightFromFile:Entry " <<
entry <<
" ID " << std::hex <<
id
936 <<
std::dec <<
" (" << det <<
"/" <<
zside <<
"/1/" << etaR <<
"/" <<
phi <<
"/"
937 << lay <<
") Weight " << wt;
955 std::map<uint32_t, double>::const_iterator ite =
layerWeights.find(
id);
960 <<
tmp.zside <<
"/1/" <<
tmp.etaR <<
"/" <<
tmp.phis <<
"/" <<
tmp.lay <<
") Weight "
968 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
969 static const unsigned int names = 10;
970 static const G4String modName[
names] = {
971 "HEModule",
"HVQF",
"HBModule",
"MBAT",
"MBBT",
"MBBTC",
"MBBT_R1P",
"MBBT_R1M",
"MBBT_R1PX",
"MBBT_R1MX"};
974 double depth = -2000;
976 for (
int n = 0;
n < touch->GetHistoryDepth(); ++
n) {
977 G4String
name(static_cast<std::string>(dd4hep::dd::noNamespace(touch->GetVolume(
n)->GetName())));
982 if (
name == modName[
ii]) {
984 int dn = touch->GetHistoryDepth() -
n;
985 local = touch->GetHistory()->GetTransform(dn).TransformPoint(global);
989 }
else if (
ii == 1) {
992 }
else if (
ii == 2) {
1009 <<
" depth " <<
depth <<
" ID " <<
id <<
" EDEP " << edep <<
" Time " <<
time;
1017 int jd = 2 *
idx +
id - 7;
1018 if (jd >= 0 && jd < 4) {
1020 if (
hit_[jd] !=
nullptr)
1021 hit_[jd]->Fill(edep);
1022 if (
time_[jd] !=
nullptr)
1024 if (
dist_[jd] !=
nullptr)
1032 if (
hzvem !=
nullptr)
1041 if (
id.subdet == 4) {
1042 int ieta = (
id.zside == 0) ? -
id.etaR :
id.etaR;
1044 if (
id.
depth <= 2) {
1045 if (G4UniformRand() > 0.5)
1049 }
else if ((
id.subdet == 1 ||
id.subdet == 2) &&
testNumber) {
1050 id.depth = (
depth_ == 0) ? 1 : 2;