16 #include "G4EventManager.hh"
17 #include "G4LogicalVolumeStore.hh"
18 #include "G4LogicalVolume.hh"
19 #include "G4SDManager.hh"
22 #include "G4VProcess.hh"
23 #include "G4GFlashSpot.hh"
24 #include "G4ParticleTable.hh"
25 #include "G4SystemOfUnits.hh"
26 #include "G4PhysicalConstants.hh"
27 #include "DD4hep/Filter.h"
43 G4VGFlashSensitiveDetector(),
46 m_trackManager(manager),
48 ignoreTrackID(ignoreTkID),
53 bool dd4hep =
p.getParameter<
bool>(
"g4GeometryDD4hepSource");
54 int addlevel =
dd4hep ? 1 : 0;
58 std::vector<double> eminHits = m_CaloSD.
getParameter<std::vector<double>>(
"EminHits");
59 std::vector<double> tmaxHits = m_CaloSD.
getParameter<std::vector<double>>(
"TmaxHits");
60 std::vector<std::string> hcn = m_CaloSD.
getParameter<std::vector<std::string>>(
"HCNames");
61 std::vector<int> useResMap = m_CaloSD.
getParameter<std::vector<int>>(
"UseResponseTables");
62 std::vector<double> eminHitX = m_CaloSD.
getParameter<std::vector<double>>(
"EminHitsDepth");
71 double beamZ = m_CaloSD.
getParameter<
double>(
"BeamPosition") * CLHEP::cm;
72 correctT = beamZ / CLHEP::c_light / CLHEP::nanosecond;
75 std::vector<std::string> fineNames = m_CaloSD.
getParameter<std::vector<std::string>>(
"FineCaloNames");
76 std::vector<int> fineLevels = m_CaloSD.
getParameter<std::vector<int>>(
"FineCaloLevels");
77 std::vector<int> useFines = m_CaloSD.
getParameter<std::vector<int>>(
"UseFineCalo");
78 for (
auto&
level : fineLevels)
81 SetVerboseLevel(verbn);
83 for (
unsigned int k = 0;
k < hcn.size(); ++
k) {
85 if (
k < eminHits.size())
87 if (
k < eminHitX.size())
89 if (
k < tmaxHits.size())
91 if (
k < useResMap.size() && useResMap[
k] > 0) {
97 slave = std::make_unique<CaloSlaveSD>(
name);
113 <<
" before saving the hit\n Correct TOF globally by " <<
correctT
115 <<
" ns and if energy is above " <<
eminHit /
CLHEP::MeV <<
" MeV (for depth 0) or "
121 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Have a possibility of " << fineNames.size() <<
" fine calorimeters of which "
122 << useFines.size() <<
" are selected";
123 for (
unsigned int k = 0;
k < fineNames.size(); ++
k)
124 edm::LogVerbatim(
"CaloSim") <<
"[" <<
k <<
"] " << fineNames[
k] <<
" at " << fineLevels[
k];
125 std::ostringstream st1;
126 for (
unsigned int k = 0;
k < useFines.size(); ++
k)
127 st1 <<
" [" <<
k <<
"] " << useFines[
k] <<
":" << fineNames[useFines[
k]];
129 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
130 std::vector<G4LogicalVolume*>::const_iterator lvcite;
131 for (
unsigned int i = 0;
i < useFines.size();
i++) {
132 G4LogicalVolume* lv =
nullptr;
133 G4String
name = static_cast<G4String>(fineNames[useFines[
i]]);
134 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
135 G4String namx(static_cast<std::string>(dd4hep::dd::noNamespace((*lvcite)->GetName())));
145 detector.level = fineLevels[useFines[
i]];
154 <<
" pointer to LV: " <<
detector.lv;
166 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" ID= " << aStep->GetTrack()->GetTrackID()
167 <<
" prID= " << aStep->GetTrack()->GetParentID()
168 <<
" Eprestep= " << aStep->GetPreStepPoint()->GetKineticEnergy()
169 <<
" step= " << aStep->GetStepLength() <<
" Edep= " << aStep->GetTotalEnergyDeposit();
175 aStep->GetTrack()->SetTrackStatus(fStopAndKill);
176 auto tv = aStep->GetSecondary();
177 auto vol = aStep->GetPreStepPoint()->GetPhysicalVolume();
178 for (
auto& tk : *tv) {
179 if (tk->GetVolume() == vol) {
180 tk->SetTrackStatus(fStopAndKill);
190 auto const theTrack = aStep->GetTrack();
193 double time = theTrack->GetGlobalTime() / nanosecond;
198 if (aStep->GetTotalEnergyDeposit() > 0.0 && (!
ignoreReject)) {
199 const G4TouchableHistory* touch = static_cast<const G4TouchableHistory*>(theTrack->GetTouchable());
201 <<
" Detector: " << GetName() <<
" trackID= " << theTrack->GetTrackID() <<
" "
202 << theTrack->GetDefinition()->GetParticleName()
203 <<
"\n Edep= " << aStep->GetTotalEnergyDeposit()
204 <<
" PV: " << touch->GetVolume(0)->GetName()
205 <<
" PVid= " << touch->GetReplicaNumber(0) <<
" MVid= " << touch->GetReplicaNumber(1);
210 if (aStep->GetTotalEnergyDeposit() == 0.0) {
222 G4TouchableHistory* touch = (G4TouchableHistory*)(theTrack->GetTouchable());
223 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" PV:" << touch->GetVolume(0)->GetName()
224 <<
" PVid=" << touch->GetReplicaNumber(0) <<
" MVid=" << touch->GetReplicaNumber(1)
226 <<
edepositHAD <<
" ID=" << theTrack->GetTrackID() <<
" pID=" << theTrack->GetParentID()
227 <<
" E=" << theTrack->GetKineticEnergy() <<
" S=" << aStep->GetStepLength() <<
"\n "
228 << theTrack->GetDefinition()->GetParticleName() <<
" primaryID= " << primaryID
245 const G4Track*
track = aSpot->GetOriginatorTrack()->GetPrimaryTrack();
247 double edep = aSpot->GetEnergySpot()->GetEnergy();
253 G4StepPoint* fFakePreStepPoint = fFakeStep.GetPreStepPoint();
254 G4StepPoint* fFakePostStepPoint = fFakeStep.GetPostStepPoint();
255 fFakePreStepPoint->SetPosition(aSpot->GetPosition());
256 fFakePostStepPoint->SetPosition(aSpot->GetPosition());
258 G4TouchableHandle fTouchableHandle = aSpot->GetTouchableHandle();
259 fFakePreStepPoint->SetTouchableHandle(fTouchableHandle);
260 fFakeStep.SetTotalEnergyDeposit(edep);
287 posGlobal = aSpot->GetEnergySpot()->GetPosition();
316 int level = ((touch->GetHistoryDepth()) + 1);
320 G4LogicalVolume* lv = touch->GetVolume(
ii)->GetLogicalVolume();
323 std::string name1 = (lv == 0) ?
"Unknown" : lv->GetName();
338 edm::LogVerbatim(
"CaloSim") <<
"CaloSD : Initialize called for " << GetName();
358 if (
theHC ==
nullptr)
359 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: EndofEvent entered with no entries";
373 theHC->PrintAllHits();
378 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Tries to transfer " <<
slave.get()->hits().size() <<
" hits for "
379 <<
slave.get()->name() <<
" " << hname;
381 if (
slave.get()->name() == hname) {
384 slave.get()->Clean();
388 return touch->GetHistory()->GetTopTransform().TransformPoint(global);
392 return touch->GetHistory()->GetTopTransform().Inverse().TransformPoint(
local);
409 posGlobal = aStep->GetPreStepPoint()->GetPosition();
420 std::map<CaloHitID, CaloG4Hit*>::const_iterator it =
hitMap.find(
currentID);
428 int maxhit =
nhits - 1;
430 for (
int j = maxhit;
j > minhit; --
j) {
452 std::stringstream
ss;
453 for (
long unsigned int i = 0;
i < decayChain.size();
i++) {
476 edm::LogVerbatim(
"DoFineCalo") <<
"currentTrack " << currentTrack->GetTrackID()
478 <<
" ; recording it for hit " <<
hit->getUnitID();
488 std::vector<unsigned int> decayChain;
489 decayChain.push_back(currentTrack->GetTrackID());
492 unsigned int recordTrackID = currentTrack->GetParentID();
494 edm::LogVerbatim(
"DoFineCalo") <<
"Trying to find the first parent of hit " <<
hit->getUnitID()
495 <<
" that passes saving criterion (crosses boundary or specific criterion)"
496 <<
"; starting with first parent track " << recordTrackID;
499 if (recordTrackID <= 0) {
502 throw cms::Exception(
"Unknown",
"CaloSD") <<
"ERROR: Track " << currentTrack->GetTrackID()
503 <<
" has no parent, does not fit saving criteria, but left hit "
504 <<
hit->getUnitID() <<
"; recording it but it's weird!";
509 decayChain.push_back(recordTrackID);
511 if (recordTrackID < (
unsigned int)hitID.
trackID()) {
519 edm::LogVerbatim(
"DoFineCalo") <<
"History-tracking progressed to track " << recordTrackID
520 <<
", which is an earlier ancestor than current primary " << hitID.
trackID()
521 <<
"; overwriting it.";
528 edm::LogVerbatim(
"DoFineCalo") <<
"Recording track " << recordTrackID <<
" as source of hit " <<
hit->getUnitID()
529 <<
"; crossed boundary at pos=("
544 edm::LogVerbatim(
"DoFineCalo") <<
"Track " << recordTrackID <<
" did not cross the boundary or fit other criteria";
546 recordTrackID = recordTrackWithHistory->
parentID();
547 if (recordTrackID <= 0) {
551 <<
"Hit " <<
hit->getUnitID() <<
" does not have any parent track that passes the criteria!"
556 recordTrackWithHistory->
save();
560 edm::LogVerbatim(
"DoFineCalo") <<
"Stored the following bookeeping for hit " <<
hit->getUnitID()
561 <<
" hitID.trackID()=" << hitID.
trackID()
563 <<
" recordTrackWithHistory->trackID()=" << recordTrackWithHistory->
trackID()
564 <<
" recordTrackWithHistory->saved()=" << recordTrackWithHistory->
saved();
574 << theTrack->GetDefinition()->GetParticleName()
575 <<
" E(GeV)= " << theTrack->GetKineticEnergy() /
CLHEP::GeV
576 <<
" parentID= " << theTrack->GetParentID() <<
"\n Ein= " <<
incidentEnergy
601 bool currentlyInsideFineVolume =
isItFineCalo(aStep->GetPostStepPoint()->GetTouchable());
605 << (currentlyInsideFineVolume ?
"FINECALO" :
"normal CaloSD")
608 <<
" isItFineCalo(aStep->GetPostStepPoint()->GetTouchable())="
609 <<
isItFineCalo(aStep->GetPostStepPoint()->GetTouchable())
610 <<
" isItFineCalo(aStep->GetPreStepPoint()->GetTouchable())="
611 <<
isItFineCalo(aStep->GetPreStepPoint()->GetTouchable())
612 <<
" theTrack=" << theTrack->GetTrackID() <<
" ("
613 <<
" parentTrackId=" << theTrack->GetParentID()
628 etrack = theTrack->GetKineticEnergy();
643 if (trkh !=
nullptr) {
673 auto const preStepPoint = aStep->GetPreStepPoint();
678 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::resetForNewPrimary for " << GetName()
687 double charge = aStep->GetPreStepPoint()->GetCharge();
688 double length = aStep->GetStepLength();
690 if (
charge != 0. && length > 0.) {
691 double density = aStep->GetPreStepPoint()->GetMaterial()->GetDensity();
692 double dedx = aStep->GetTotalEnergyDeposit() / length;
694 double c = birk2 * rkb * rkb;
697 weight = 1. / (1. + rkb * dedx +
c * dedx * dedx);
699 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::getAttenuation in " << aStep->GetPreStepPoint()->GetMaterial()->GetName()
700 <<
" Charge " <<
charge <<
" dE/dx " << dedx <<
" Birk Const " << rkb <<
", " <<
c
701 <<
" Weight = " <<
weight <<
" dE " << aStep->GetTotalEnergyDeposit();
711 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Dispatched BeginOfEvent for " << GetName() <<
" !";
718 int id = (*trk)()->GetTrackID();
720 int lastTrackID = -1;
723 if (
id == lastTrackID) {
725 if (trksForThisEvent !=
nullptr) {
726 int it = (
int)(trksForThisEvent->size()) - 1;
732 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: get track " << it <<
" from Container of size "
733 << trksForThisEvent->size() <<
" with ID " << trkH->
trackID();
735 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: get track " << it <<
" from Container of size "
736 << trksForThisEvent->size() <<
" with no ID";
757 int hc_entries =
theHC->entries();
758 for (
int i = 0;
i < hc_entries; ++
i) {
763 double x = (*theHC)[
i]->getEM();
766 x = (*theHC)[
i]->getHadr();
769 tt += (*theHC)[
i]->getTimeSlice();
770 ee += (*theHC)[
i]->getIncidentEnergy();
775 double norm = (
count > 0) ? 1.0 /
count : 0.0;
790 <<
" hits not passing cuts\n EmeanEM= " << eEM <<
" ErmsEM= " << eEM2
791 <<
"\n EmeanHAD= " << eHAD <<
" ErmsHAD= " << eHAD2 <<
" TimeMean= " <<
tt
792 <<
" E0mean= " << ee <<
" Zglob= " << zglob <<
" Zloc= " << zloc <<
" ";
795 std::vector<std::unique_ptr<CaloG4Hit>>().
swap(
reusehit);
805 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Clears hit vector for " << GetName()
806 <<
" and initialise slave: " <<
slave.get()->name();
808 slave.get()->Initialize();
833 primaryID = aTrack->GetTrackID();
835 edm::LogWarning(
"CaloSim") <<
"CaloSD: Problem with primaryID **** set by force to TkID **** " << primaryID;
842 auto const theTrack = aStep->GetTrack();
845 if (primaryID <= 0) {
846 primaryID = theTrack->GetTrackID();
858 <<
" trackID= " << aStep->GetTrack()->GetTrackID() <<
" primaryID= " << primaryID;
867 if (
hit->getDepth() > 0)
870 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::filterHit(..) Depth " <<
hit->getDepth() <<
" Emin = " << emin <<
" ("
916 <<
"aHit " << aHit->
getUnitID() <<
" has fine trackID " << tkID <<
", which is NOT IN THE TRACK MANAGER";
920 throw cms::Exception(
"Unknown",
"CaloSD") <<
"m_trackManager not set, saveHit ok=false!";
923 slave.get()->processHits(
943 <<
" (no fineTrackID)";
945 slave.get()->processHits(
953 <<
" by SimTrackManager Status " <<
ok;
958 << aHit->
getDepth() <<
" due to " << tkID <<
" in time " <<
time <<
" of energy "
969 primary = (*trk)()->GetTrackID();
983 if (
theHC->entries() > 0)
989 std::vector<CaloG4Hit*>* theCollection =
theHC->GetVector();
999 std::vector<CaloG4Hit*> hitvec;
1001 hitvec.swap(*theCollection);
1004 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: sort hits in buffer starting from "
1006 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
1007 if (hitvec[
i] ==
nullptr)
1016 for (
unsigned int j =
i + 1;
j < hitvec.size() &&
equal(hitvec[
i], hitvec[
j]); ++
j) {
1019 (*hitvec[
i]).addEnergyDeposit(*hitvec[
j]);
1020 (*hitvec[
j]).setEM(0.);
1021 (*hitvec[
j]).setHadr(0.);
1023 hitvec[
j] =
nullptr;
1028 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: cleanHitCollection merge the hits in buffer ";
1029 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
1030 if (hitvec[
i] ==
nullptr)
1038 std::stable_partition(hitvec.begin() +
cleanIndex, hitvec.end(), [](
CaloG4Hit*
p) {
return p !=
nullptr; }),
1041 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: remove the merged hits in buffer,"
1042 <<
" new size = " << hitvec.size();
1044 hitvec.swap(*theCollection);
1050 <<
" Size of reusehit= " <<
reusehit.size()
1051 <<
"\n starting hit selection from index = " <<
cleanIndex;
1055 for (
unsigned int i =
cleanIndex;
i < theCollection->size(); ++
i) {
1071 reusehit.emplace_back((*theCollection)[
i]);
1072 (*theCollection)[
i] =
nullptr;
1079 <<
" Number of added hit = " << addhit;
1084 for (
int ii = addhit - 1;
ii >= 0; --
ii) {
1092 theCollection->erase(
1093 std::stable_partition(
1094 theCollection->begin() +
cleanIndex, theCollection->end(), [](
CaloG4Hit*
p) {
return p !=
nullptr; }),
1095 theCollection->end());
1097 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: hit collection after selection, size = " <<
theHC->entries();
1098 theHC->PrintAllHits();
1106 int level = ((touch->GetHistoryDepth()) + 1);
1107 std::ostringstream st1;
1108 st1 <<
level <<
" Levels:";
1112 G4VPhysicalVolume*
pv = touch->GetVolume(
i);
1114 st1 <<
" " <<
name <<
":" << touch->GetReplicaNumber(
i);