15 #include "G4EventManager.hh"
16 #include "G4LogicalVolumeStore.hh"
17 #include "G4LogicalVolume.hh"
18 #include "G4SDManager.hh"
21 #include "G4VProcess.hh"
22 #include "G4GFlashSpot.hh"
23 #include "G4ParticleTable.hh"
24 #include "G4SystemOfUnits.hh"
25 #include "G4PhysicalConstants.hh"
26 #include "DD4hep/Filter.h"
41 G4VGFlashSensitiveDetector(),
44 m_trackManager(manager),
46 ignoreTrackID(ignoreTkID),
51 bool dd4hep =
p.getParameter<
bool>(
"g4GeometryDD4hepSource");
52 int addlevel =
dd4hep ? 1 : 0;
56 std::vector<double> eminHits = m_CaloSD.
getParameter<std::vector<double>>(
"EminHits");
57 std::vector<double> tmaxHits = m_CaloSD.
getParameter<std::vector<double>>(
"TmaxHits");
58 std::vector<std::string> hcn = m_CaloSD.
getParameter<std::vector<std::string>>(
"HCNames");
59 std::vector<int> useResMap = m_CaloSD.
getParameter<std::vector<int>>(
"UseResponseTables");
60 std::vector<double> eminHitX = m_CaloSD.
getParameter<std::vector<double>>(
"EminHitsDepth");
69 double beamZ = m_CaloSD.
getParameter<
double>(
"BeamPosition") * CLHEP::cm;
70 correctT = beamZ / CLHEP::c_light / CLHEP::nanosecond;
73 std::vector<std::string> fineNames = m_CaloSD.
getParameter<std::vector<std::string>>(
"FineCaloNames");
74 std::vector<int> fineLevels = m_CaloSD.
getParameter<std::vector<int>>(
"FineCaloLevels");
75 std::vector<int> useFines = m_CaloSD.
getParameter<std::vector<int>>(
"UseFineCalo");
76 for (
auto&
level : fineLevels)
79 SetVerboseLevel(verbn);
81 for (
unsigned int k = 0;
k < hcn.size(); ++
k) {
83 if (
k < eminHits.size())
85 if (
k < eminHitX.size())
87 if (
k < tmaxHits.size())
89 if (
k < useResMap.size() && useResMap[
k] > 0) {
95 slave = std::make_unique<CaloSlaveSD>(
name);
111 <<
" before saving the hit\n Correct TOF globally by " <<
correctT
113 <<
" ns and if energy is above " <<
eminHit /
CLHEP::MeV <<
" MeV (for depth 0) or "
116 <<
doFineCalo_ <<
"\nBeam Position " << beamZ / CLHEP::cm <<
" cm";
119 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Have a possibility of " << fineNames.size() <<
" fine calorimeters of which "
120 << useFines.size() <<
" are selected";
121 for (
unsigned int k = 0;
k < fineNames.size(); ++
k)
122 edm::LogVerbatim(
"CaloSim") <<
"[" <<
k <<
"] " << fineNames[
k] <<
" at " << fineLevels[
k];
123 std::ostringstream st1;
124 for (
unsigned int k = 0;
k < useFines.size(); ++
k)
125 st1 <<
" [" <<
k <<
"] " << useFines[
k] <<
":" << fineNames[useFines[
k]];
127 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
128 std::vector<G4LogicalVolume*>::const_iterator lvcite;
129 for (
unsigned int i = 0;
i < useFines.size();
i++) {
130 G4LogicalVolume* lv =
nullptr;
131 G4String
name = static_cast<G4String>(fineNames[useFines[
i]]);
132 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
133 G4String namx(static_cast<std::string>(dd4hep::dd::noNamespace((*lvcite)->GetName())));
143 detector.level = fineLevels[useFines[
i]];
152 <<
" pointer to LV: " <<
detector.lv;
164 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" ID= " << aStep->GetTrack()->GetTrackID()
165 <<
" prID= " << aStep->GetTrack()->GetParentID()
166 <<
" Eprestep= " << aStep->GetPreStepPoint()->GetKineticEnergy()
167 <<
" step= " << aStep->GetStepLength() <<
" Edep= " << aStep->GetTotalEnergyDeposit();
173 aStep->GetTrack()->SetTrackStatus(fStopAndKill);
174 auto tv = aStep->GetSecondary();
175 auto vol = aStep->GetPreStepPoint()->GetPhysicalVolume();
176 for (
auto& tk : *tv) {
177 if (tk->GetVolume() == vol) {
178 tk->SetTrackStatus(fStopAndKill);
188 auto const theTrack = aStep->GetTrack();
191 double time = theTrack->GetGlobalTime() / nanosecond;
196 if (aStep->GetTotalEnergyDeposit() > 0.0 && (!
ignoreReject)) {
197 const G4TouchableHistory* touch = static_cast<const G4TouchableHistory*>(theTrack->GetTouchable());
199 <<
" Detector: " << GetName() <<
" trackID= " << theTrack->GetTrackID() <<
" "
200 << theTrack->GetDefinition()->GetParticleName()
201 <<
"\n Edep= " << aStep->GetTotalEnergyDeposit()
202 <<
" PV: " << touch->GetVolume(0)->GetName()
203 <<
" PVid= " << touch->GetReplicaNumber(0) <<
" MVid= " << touch->GetReplicaNumber(1);
208 if (aStep->GetTotalEnergyDeposit() == 0.0) {
220 G4TouchableHistory* touch = (G4TouchableHistory*)(theTrack->GetTouchable());
221 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" PV:" << touch->GetVolume(0)->GetName()
222 <<
" PVid=" << touch->GetReplicaNumber(0) <<
" MVid=" << touch->GetReplicaNumber(1)
224 <<
edepositHAD <<
" ID=" << theTrack->GetTrackID() <<
" pID=" << theTrack->GetParentID()
225 <<
" E=" << theTrack->GetKineticEnergy() <<
" S=" << aStep->GetStepLength() <<
"\n "
226 << theTrack->GetDefinition()->GetParticleName() <<
" primaryID= " << primaryID
243 const G4Track*
track = aSpot->GetOriginatorTrack()->GetPrimaryTrack();
245 double edep = aSpot->GetEnergySpot()->GetEnergy();
251 G4StepPoint* fFakePreStepPoint = fFakeStep.GetPreStepPoint();
252 G4StepPoint* fFakePostStepPoint = fFakeStep.GetPostStepPoint();
253 fFakePreStepPoint->SetPosition(aSpot->GetPosition());
254 fFakePostStepPoint->SetPosition(aSpot->GetPosition());
256 G4TouchableHandle fTouchableHandle = aSpot->GetTouchableHandle();
257 fFakePreStepPoint->SetTouchableHandle(fTouchableHandle);
258 fFakeStep.SetTotalEnergyDeposit(edep);
285 posGlobal = aSpot->GetEnergySpot()->GetPosition();
314 int level = ((touch->GetHistoryDepth()) + 1);
318 G4LogicalVolume* lv = touch->GetVolume(
ii)->GetLogicalVolume();
321 std::string name1 = (lv == 0) ?
"Unknown" : lv->GetName();
336 edm::LogVerbatim(
"CaloSim") <<
"CaloSD : Initialize called for " << GetName();
356 if (
theHC ==
nullptr)
357 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: EndofEvent entered with no entries";
371 theHC->PrintAllHits();
376 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Tries to transfer " <<
slave.get()->hits().size() <<
" hits for "
377 <<
slave.get()->name() <<
" " << hname;
379 if (
slave.get()->name() == hname) {
382 slave.get()->Clean();
386 return touch->GetHistory()->GetTopTransform().TransformPoint(global);
390 return touch->GetHistory()->GetTopTransform().Inverse().TransformPoint(
local);
407 posGlobal = aStep->GetPreStepPoint()->GetPosition();
418 std::map<CaloHitID, CaloG4Hit*>::const_iterator it =
hitMap.find(
currentID);
426 int maxhit =
nhits - 1;
428 for (
int j = maxhit;
j > minhit; --
j) {
450 std::stringstream
ss;
451 for (
long unsigned int i = 0;
i < decayChain.size();
i++) {
474 edm::LogVerbatim(
"DoFineCalo") <<
"currentTrack " << currentTrack->GetTrackID()
476 <<
" ; recording it for hit " <<
hit->getUnitID();
486 std::vector<unsigned int> decayChain;
487 decayChain.push_back(currentTrack->GetTrackID());
490 unsigned int recordTrackID = currentTrack->GetParentID();
492 edm::LogVerbatim(
"DoFineCalo") <<
"Trying to find the first parent of hit " <<
hit->getUnitID()
493 <<
" that passes saving criterion (crosses boundary or specific criterion)"
494 <<
"; starting with first parent track " << recordTrackID;
497 if (recordTrackID <= 0) {
500 throw cms::Exception(
"Unknown",
"CaloSD") <<
"ERROR: Track " << currentTrack->GetTrackID()
501 <<
" has no parent, does not fit saving criteria, but left hit "
502 <<
hit->getUnitID() <<
"; recording it but it's weird!";
507 decayChain.push_back(recordTrackID);
509 if (recordTrackID < (
unsigned int)hitID.
trackID()) {
517 edm::LogVerbatim(
"DoFineCalo") <<
"History-tracking progressed to track " << recordTrackID
518 <<
", which is an earlier ancestor than current primary " << hitID.
trackID()
519 <<
"; overwriting it.";
526 edm::LogVerbatim(
"DoFineCalo") <<
"Recording track " << recordTrackID <<
" as source of hit " <<
hit->getUnitID()
527 <<
"; crossed boundary at pos=("
542 edm::LogVerbatim(
"DoFineCalo") <<
"Track " << recordTrackID <<
" did not cross the boundary or fit other criteria";
544 recordTrackID = recordTrackWithHistory->
parentID();
545 if (recordTrackID <= 0) {
549 <<
"Hit " <<
hit->getUnitID() <<
" does not have any parent track that passes the criteria!"
554 recordTrackWithHistory->
save();
558 edm::LogVerbatim(
"DoFineCalo") <<
"Stored the following bookeeping for hit " <<
hit->getUnitID()
559 <<
" hitID.trackID()=" << hitID.
trackID()
561 <<
" recordTrackWithHistory->trackID()=" << recordTrackWithHistory->
trackID()
562 <<
" recordTrackWithHistory->saved()=" << recordTrackWithHistory->
saved();
572 << theTrack->GetDefinition()->GetParticleName()
573 <<
" E(GeV)= " << theTrack->GetKineticEnergy() /
CLHEP::GeV
574 <<
" parentID= " << theTrack->GetParentID() <<
"\n Ein= " <<
incidentEnergy
603 << (currentlyInsideFineVolume ?
"FINECALO" :
"normal CaloSD")
606 <<
" isItFineCalo(aStep->GetPostStepPoint()->GetTouchable())="
607 <<
isItFineCalo(aStep->GetPostStepPoint()->GetTouchable())
608 <<
" isItFineCalo(aStep->GetPreStepPoint()->GetTouchable())="
609 <<
isItFineCalo(aStep->GetPreStepPoint()->GetTouchable())
610 <<
" theTrack=" << theTrack->GetTrackID() <<
" ("
611 <<
" parentTrackId=" << theTrack->GetParentID()
618 if (currentlyInsideFineVolume) {
626 etrack = theTrack->GetKineticEnergy();
641 if (trkh !=
nullptr) {
671 auto const preStepPoint = aStep->GetPreStepPoint();
676 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::resetForNewPrimary for " << GetName()
685 double charge = aStep->GetPreStepPoint()->GetCharge();
686 double length = aStep->GetStepLength();
688 if (
charge != 0. && length > 0.) {
689 double density = aStep->GetPreStepPoint()->GetMaterial()->GetDensity();
690 double dedx = aStep->GetTotalEnergyDeposit() / length;
692 double c = birk2 * rkb * rkb;
695 weight = 1. / (1. + rkb * dedx +
c * dedx * dedx);
697 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::getAttenuation in " << aStep->GetPreStepPoint()->GetMaterial()->GetName()
698 <<
" Charge " <<
charge <<
" dE/dx " << dedx <<
" Birk Const " << rkb <<
", " <<
c
699 <<
" Weight = " <<
weight <<
" dE " << aStep->GetTotalEnergyDeposit();
709 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Dispatched BeginOfEvent for " << GetName() <<
" !";
716 int id = (*trk)()->GetTrackID();
718 int lastTrackID = -1;
721 if (
id == lastTrackID) {
723 if (trksForThisEvent !=
nullptr) {
724 int it = (
int)(trksForThisEvent->size()) - 1;
730 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: get track " << it <<
" from Container of size "
731 << trksForThisEvent->size() <<
" with ID " << trkH->
trackID();
733 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: get track " << it <<
" from Container of size "
734 << trksForThisEvent->size() <<
" with no ID";
755 int hc_entries =
theHC->entries();
756 for (
int i = 0;
i < hc_entries; ++
i) {
761 double x = (*theHC)[
i]->getEM();
764 x = (*theHC)[
i]->getHadr();
767 tt += (*theHC)[
i]->getTimeSlice();
768 ee += (*theHC)[
i]->getIncidentEnergy();
773 double norm = (
count > 0) ? 1.0 /
count : 0.0;
788 <<
" hits not passing cuts\n EmeanEM= " << eEM <<
" ErmsEM= " << eEM2
789 <<
"\n EmeanHAD= " << eHAD <<
" ErmsHAD= " << eHAD2 <<
" TimeMean= " <<
tt
790 <<
" E0mean= " << ee <<
" Zglob= " << zglob <<
" Zloc= " << zloc <<
" ";
793 std::vector<std::unique_ptr<CaloG4Hit>>().
swap(
reusehit);
803 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Clears hit vector for " << GetName()
804 <<
" and initialise slave: " <<
slave.get()->name();
806 slave.get()->Initialize();
831 primaryID = aTrack->GetTrackID();
833 edm::LogWarning(
"CaloSim") <<
"CaloSD: Problem with primaryID **** set by force to TkID **** " << primaryID;
840 auto const theTrack = aStep->GetTrack();
843 if (primaryID <= 0) {
844 primaryID = theTrack->GetTrackID();
856 <<
" trackID= " << aStep->GetTrack()->GetTrackID() <<
" primaryID= " << primaryID;
865 if (
hit->getDepth() > 0)
868 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::filterHit(..) Depth " <<
hit->getDepth() <<
" Emin = " << emin <<
" ("
914 <<
"aHit " << aHit->
getUnitID() <<
" has fine trackID " << tkID <<
", which is NOT IN THE TRACK MANAGER";
918 throw cms::Exception(
"Unknown",
"CaloSD") <<
"m_trackManager not set, saveHit ok=false!";
921 slave.get()->processHits(
941 <<
" (no fineTrackID)";
943 slave.get()->processHits(
951 <<
" by SimTrackManager Status " <<
ok;
956 << aHit->
getDepth() <<
" due to " << tkID <<
" in time " <<
time <<
" of energy "
967 primary = (*trk)()->GetTrackID();
981 if (
theHC->entries() > 0)
987 std::vector<CaloG4Hit*>* theCollection =
theHC->GetVector();
997 std::vector<CaloG4Hit*> hitvec;
999 hitvec.swap(*theCollection);
1002 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: sort hits in buffer starting from "
1004 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
1005 if (hitvec[
i] ==
nullptr)
1014 for (
unsigned int j =
i + 1;
j < hitvec.size() &&
equal(hitvec[
i], hitvec[
j]); ++
j) {
1017 (*hitvec[
i]).addEnergyDeposit(*hitvec[
j]);
1018 (*hitvec[
j]).setEM(0.);
1019 (*hitvec[
j]).setHadr(0.);
1021 hitvec[
j] =
nullptr;
1026 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: cleanHitCollection merge the hits in buffer ";
1027 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
1028 if (hitvec[
i] ==
nullptr)
1036 std::stable_partition(hitvec.begin() +
cleanIndex, hitvec.end(), [](
CaloG4Hit*
p) {
return p !=
nullptr; }),
1039 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: remove the merged hits in buffer,"
1040 <<
" new size = " << hitvec.size();
1042 hitvec.swap(*theCollection);
1048 <<
" Size of reusehit= " <<
reusehit.size()
1049 <<
"\n starting hit selection from index = " <<
cleanIndex;
1053 for (
unsigned int i =
cleanIndex;
i < theCollection->size(); ++
i) {
1069 reusehit.emplace_back((*theCollection)[
i]);
1070 (*theCollection)[
i] =
nullptr;
1077 <<
" Number of added hit = " << addhit;
1082 for (
int ii = addhit - 1;
ii >= 0; --
ii) {
1090 theCollection->erase(
1091 std::stable_partition(
1092 theCollection->begin() +
cleanIndex, theCollection->end(), [](
CaloG4Hit*
p) {
return p !=
nullptr; }),
1093 theCollection->end());
1095 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: hit collection after selection, size = " <<
theHC->entries();
1096 theHC->PrintAllHits();
1104 int level = ((touch->GetHistoryDepth()) + 1);
1105 std::ostringstream st1;
1106 st1 <<
level <<
" Levels:";
1110 G4VPhysicalVolume*
pv = touch->GetVolume(
i);
1112 st1 <<
" " <<
name <<
":" << touch->GetReplicaNumber(
i);