14 #include "G4EventManager.hh" 15 #include "G4LogicalVolumeStore.hh" 16 #include "G4LogicalVolume.hh" 17 #include "G4SDManager.hh" 20 #include "G4VProcess.hh" 21 #include "G4GFlashSpot.hh" 22 #include "G4ParticleTable.hh" 23 #include "G4SystemOfUnits.hh" 24 #include "G4PhysicalConstants.hh" 25 #include "DD4hep/Filter.h" 41 G4VGFlashSensitiveDetector(),
43 m_trackManager(manager),
44 ignoreTrackID(ignoreTkID),
48 nHC_ = (newcollName.empty()) ? 1 : 2;
49 for (
int k = 0;
k < 2; ++
k) {
54 bool dd4hep =
p.getParameter<
bool>(
"g4GeometryDD4hepSource");
55 int addlevel =
dd4hep ? 1 : 0;
59 std::vector<double> eminHits = m_CaloSD.
getParameter<std::vector<double>>(
"EminHits");
60 std::vector<double> tmaxHits = m_CaloSD.
getParameter<std::vector<double>>(
"TmaxHits");
63 std::vector<double> eminHitX = m_CaloSD.
getParameter<std::vector<double>>(
"EminHitsDepth");
73 double beamZ = m_CaloSD.
getParameter<
double>(
"BeamPosition") * CLHEP::cm;
74 correctT = beamZ / CLHEP::c_light / CLHEP::nanosecond;
77 std::vector<std::string> fineNames = m_CaloSD.
getParameter<std::vector<std::string>>(
"FineCaloNames");
78 std::vector<int> fineLevels = m_CaloSD.
getParameter<std::vector<int>>(
"FineCaloLevels");
79 std::vector<int> useFines = m_CaloSD.
getParameter<std::vector<int>>(
"UseFineCalo");
80 for (
auto&
level : fineLevels)
83 SetVerboseLevel(verbn);
84 for (
int k = 0;
k < 2; ++
k)
86 for (
unsigned int k = 0;
k <
hcn_.size(); ++
k) {
88 if (
k < eminHits.size())
90 if (
k < eminHitX.size())
92 if (
k < tmaxHits.size())
103 slave[0] = std::make_unique<CaloSlaveSD>(
name);
104 slave[1].reset(
nullptr);
106 for (
int k = 0;
k < 2; ++
k) {
119 for (
int k = 0;
k < 2; ++
k) {
124 <<
" GeV\n Use of HitID Map " <<
useMap <<
"\n Check last " 125 <<
nCheckedHits[0] <<
" before saving the hit\n Correct TOF globally by " 127 <<
tmaxHit <<
" ns and if energy is above " <<
eminHit / CLHEP::MeV
128 <<
" MeV (for depth 0) or " <<
eminHitD / CLHEP::MeV
129 <<
" MeV (for nonzero depths);\n Time Slice Unit " <<
timeSlice 131 <<
"\nBeam Position " << beamZ / CLHEP::cm <<
" cm";
136 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Have a possibility of " << fineNames.size() <<
" fine calorimeters of which " 137 << useFines.size() <<
" are selected";
138 for (
unsigned int k = 0;
k < fineNames.size(); ++
k)
139 edm::LogVerbatim(
"CaloSim") <<
"[" <<
k <<
"] " << fineNames[
k] <<
" at " << fineLevels[
k];
140 std::ostringstream st1;
141 for (
unsigned int k = 0;
k < useFines.size(); ++
k)
142 st1 <<
" [" <<
k <<
"] " << useFines[
k] <<
":" << fineNames[useFines[
k]];
144 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
145 std::vector<G4LogicalVolume*>::const_iterator lvcite;
146 for (
unsigned int i = 0;
i < useFines.size();
i++) {
147 G4LogicalVolume* lv =
nullptr;
148 G4String
name =
static_cast<G4String
>(fineNames[useFines[
i]]);
149 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
150 G4String namx(static_cast<std::string>(dd4hep::dd::noNamespace((*lvcite)->GetName())));
160 detector.level = fineLevels[useFines[
i]];
169 <<
" pointer to LV: " <<
detector.lv;
177 for (
unsigned int k = 0;
k <
hcn_.size(); ++
k) {
185 slave[1] = std::make_unique<CaloSlaveSD>(
name);
199 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" ID= " << aStep->GetTrack()->GetTrackID()
200 <<
" prID= " << aStep->GetTrack()->GetParentID()
201 <<
" Eprestep= " << aStep->GetPreStepPoint()->GetKineticEnergy()
202 <<
" step= " << aStep->GetStepLength() <<
" Edep= " << aStep->GetTotalEnergyDeposit();
214 (aStep->GetTrack())->SetTrackStatus(fStopAndKill);
215 if (0 < aStep->GetNumberOfSecondariesInCurrentStep()) {
216 auto tv = aStep->GetSecondaryInCurrentStep();
217 auto vol = aStep->GetPreStepPoint()->GetPhysicalVolume();
218 for (
auto& tk : *tv) {
219 if (tk->GetVolume() == vol) {
220 const_cast<G4Track*
>(tk)->SetTrackStatus(fStopAndKill);
230 if (aStep->GetTotalEnergyDeposit() <= 0.0) {
236 auto const theTrack = aStep->GetTrack();
239 double time = theTrack->GetGlobalTime() / nanosecond;
245 const G4TouchableHistory* touch =
static_cast<const G4TouchableHistory*
>(theTrack->GetTouchable());
247 <<
" currUnit= " <<
currentID[0].
unitID() <<
" Detector: " << GetName()
248 <<
" trackID= " << theTrack->GetTrackID() <<
" " 249 << theTrack->GetDefinition()->GetParticleName()
250 <<
"\n Edep= " << aStep->GetTotalEnergyDeposit()
251 <<
" PV: " << touch->GetVolume(0)->GetName()
252 <<
" PVid= " << touch->GetReplicaNumber(0) <<
" MVid= " << touch->GetReplicaNumber(1);
272 const G4TouchableHistory* touch =
static_cast<const G4TouchableHistory*
>(theTrack->GetTouchable());
273 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" PV:" << touch->GetVolume(0)->GetName()
274 <<
" PVid=" << touch->GetReplicaNumber(0) <<
" MVid=" << touch->GetReplicaNumber(1)
276 <<
edepositHAD <<
" ID=" << theTrack->GetTrackID() <<
" pID=" << theTrack->GetParentID()
277 <<
" E=" << theTrack->GetKineticEnergy() <<
" S=" << aStep->GetStepLength() <<
"\n " 278 << theTrack->GetDefinition()->GetParticleName() <<
" primaryID= " << primaryID
296 const G4Track*
track = aSpot->GetOriginatorTrack()->GetPrimaryTrack();
298 double edep = aSpot->GetEnergySpot()->GetEnergy();
304 G4StepPoint* fFakePreStepPoint = fFakeStep.GetPreStepPoint();
305 G4StepPoint* fFakePostStepPoint = fFakeStep.GetPostStepPoint();
306 fFakePreStepPoint->SetPosition(aSpot->GetPosition());
307 fFakePostStepPoint->SetPosition(aSpot->GetPosition());
309 G4TouchableHandle fTouchableHandle = aSpot->GetTouchableHandle();
310 fFakePreStepPoint->SetTouchableHandle(fTouchableHandle);
311 fFakeStep.SetTotalEnergyDeposit(edep);
329 double time =
track->GetGlobalTime() / nanosecond;
341 posGlobal = aSpot->GetEnergySpot()->GetPosition();
370 int level = ((touch->GetHistoryDepth()) + 1);
374 G4LogicalVolume* lv = touch->GetVolume(
ii)->GetLogicalVolume();
377 std::string name1 = (lv ==
nullptr) ?
"Unknown" : lv->GetName();
393 for (
int k = 0;
k <
nHC_; ++
k) {
418 for (
int k = 0;
k <
nHC_; ++
k) {
420 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: EndofEvent entered for container " <<
k <<
" with no entries";
422 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: EndofEvent entered for container " <<
k <<
" with " <<
theHC[0]->entries()
433 for (
int k = 0;
k <
nHC_; ++
k) {
442 for (
int k = 0;
k <
nHC_; ++
k) {
444 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Tries to transfer " <<
slave[
k].get()->hits().size() <<
" hits for " 445 <<
slave[
k].get()->name() <<
" " << hname;
455 return touch->GetHistory()->GetTopTransform().TransformPoint(global);
459 return touch->GetHistory()->GetTopTransform().Inverse().TransformPoint(
local);
480 posGlobal = aStep->GetPreStepPoint()->GetPosition();
495 std::map<CaloHitID, CaloG4Hit*>::const_iterator it =
hitMap[
k].find(
currentID[
k]);
503 int maxhit =
nhits - 1;
505 for (
int j = maxhit;
j > minhit; --
j) {
527 std::stringstream
ss;
528 for (
long unsigned int i = 0;
i < decayChain.size();
i++) {
538 std::stringstream
ss;
539 ss << GetName() <<
"/" <<
ID.unitID() <<
"/trk" <<
ID.trackID() <<
"/d" <<
ID.depth() <<
"/time" <<
ID.timeSliceID();
540 if (
ID.isFinecaloTrackID())
553 unsigned int id =
track->GetTrackID();
558 edm::LogVerbatim(
"DoFineCalo") <<
"Track " <<
id <<
" parent already cached: " << it->second;
565 edm::LogVerbatim(
"DoFineCalo") <<
"Track " <<
id <<
" crosses boundary itself";
572 std::vector<unsigned int> decayChain{
id};
574 edm::LogVerbatim(
"DoFineCalo") <<
"Track " <<
id <<
": Traversing history to find boundary-crossing parent";
576 unsigned int parentID =
track->GetParentID();
580 <<
"Hit end of parentage for track " <<
id <<
" without finding a boundary-crossing parent";
586 <<
" boundary-crossing parent already cached: " << it->second;
589 for (
auto ancestorID : decayChain)
593 decayChain.push_back(parentID);
594 while (parentID != it->second) {
596 decayChain.push_back(parentID);
607 decayChain.push_back(parentID);
609 for (
auto ancestorID : decayChain)
612 edm::LogVerbatim(
"DoFineCalo") <<
" Found boundary-crossing ancestor " << parentID <<
" for track " <<
id 618 decayChain.push_back(parentID);
630 <<
" " << theTrack->GetDefinition()->GetParticleName()
631 <<
" E(GeV)= " << theTrack->GetKineticEnergy() / CLHEP::GeV
632 <<
" parentID= " << theTrack->GetParentID() <<
"\n Ein= " <<
incidentEnergy 660 <<
" isItFineCalo(post)=" <<
isItFineCalo(aStep->GetPostStepPoint()->GetTouchable())
661 <<
" isItFineCalo(pre)=" <<
isItFineCalo(aStep->GetPreStepPoint()->GetTouchable());
668 }
else if (
currentID[
k].trackID() == theTrack->GetTrackID()) {
669 etrack = theTrack->GetKineticEnergy();
684 if (trkh !=
nullptr) {
714 auto const preStepPoint = aStep->GetPreStepPoint();
719 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::resetForNewPrimary for " << GetName()
720 <<
" ID= " << aStep->GetTrack()->GetTrackID() <<
" Ein= " <<
incidentEnergy / CLHEP::GeV
728 double charge = aStep->GetPreStepPoint()->GetCharge();
729 double length = aStep->GetStepLength();
731 if (
charge != 0. && length > 0.) {
732 double density = aStep->GetPreStepPoint()->GetMaterial()->GetDensity();
733 double dedx = aStep->GetTotalEnergyDeposit() / length;
735 double c = birk2 * rkb * rkb;
738 weight = 1. / (1. + rkb * dedx +
c * dedx * dedx);
740 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::getAttenuation in " << aStep->GetPreStepPoint()->GetMaterial()->GetName()
741 <<
" Charge " <<
charge <<
" dE/dx " << dedx <<
" Birk Const " << rkb <<
", " <<
c 742 <<
" Weight = " <<
weight <<
" dE " << aStep->GetTotalEnergyDeposit();
752 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Dispatched BeginOfEvent for " << GetName() <<
" !";
759 int id = (*trk)()->GetTrackID();
761 int lastTrackID = -1;
764 if (
id == lastTrackID) {
766 if (!trksForThisEvent->empty()) {
771 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: get track " <<
id <<
" from Container of size " 772 << trksForThisEvent->size() <<
" with ID " << trkH->
trackID();
781 for (
int k = 0;
k <
nHC_; ++
k) {
796 int hc_entries =
theHC[
k]->entries();
797 for (
int i = 0;
i < hc_entries; ++
i) {
815 ee += (*
theHC[
k])[
i]->getIncidentEnergy();
821 double norm = (
count > 0) ? 1.0 /
count : 0.0;
835 <<
" hits not passing cuts\n EmeanEM= " << eEM <<
" ErmsEM= " << eEM2
836 <<
"\n EmeanHAD= " << eHAD <<
" ErmsHAD= " << eHAD2 <<
" TimeMean= " <<
tt 837 <<
" E0mean= " << ee <<
" Zglob= " << zglob <<
" Zloc= " << zloc <<
" ";
848 for (
int k = 0;
k <
nHC_; ++
k) {
853 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Clears hit vector for " << GetName()
854 <<
" and initialise slave: " <<
slave[
k].get()->name();
856 slave[
k].get()->Initialize();
882 primaryID = aTrack->GetTrackID();
884 edm::LogWarning(
"CaloSim") <<
"CaloSD: Problem with primaryID **** set by force to TkID **** " << primaryID;
891 auto const theTrack = aStep->GetTrack();
894 if (primaryID <= 0) {
895 primaryID = theTrack->GetTrackID();
907 <<
" trackID= " << aStep->GetTrack()->GetTrackID() <<
" primaryID= " << primaryID;
918 if (
hit->getDepth() > 0)
921 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::filterHit(..) Depth " <<
hit->getDepth() <<
" Emin = " << emin <<
" (" 962 throw cms::Exception(
"Unknown",
"CaloSD") <<
"m_trackManager not set, needed for finecalo!";
965 <<
"Error on hit " <<
shortreprID(aHit) <<
": Parent track not in track manager";
967 aHit->
getEM() / CLHEP::GeV,
992 slave[
k].get()->processHits(
1000 <<
" by SimTrackManager Status " <<
ok;
1005 << aHit->
getDepth() <<
" due to " << tkID <<
" in time " <<
time <<
" of energy " 1006 << aHit->
getEM() / CLHEP::GeV <<
" GeV (EM) and " << aHit->
getHadr() / CLHEP::GeV
1016 primary = (*trk)()->GetTrackID();
1031 for (
int k = 0;
k <
nHC_; ++
k)
1032 if (
theHC[
k]->entries() > 0)
1040 for (
int k = 0;
k <
nHC_; ++
k) {
1041 std::vector<CaloG4Hit*>* theCollection =
theHC[
k]->GetVector();
1051 std::vector<CaloG4Hit*> hitvec;
1053 hitvec.swap(*theCollection);
1056 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: sort hits in buffer starting from " 1058 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
1059 if (hitvec[
i] ==
nullptr)
1068 for (
unsigned int j =
i + 1;
j < hitvec.size() &&
equal(hitvec[
i], hitvec[
j]); ++
j) {
1071 (*hitvec[
i]).addEnergyDeposit(*hitvec[
j]);
1072 (*hitvec[
j]).setEM(0.);
1073 (*hitvec[
j]).setHadr(0.);
1075 hitvec[
j] =
nullptr;
1080 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: cleanHitCollection merge the hits in buffer ";
1081 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
1082 if (hitvec[
i] ==
nullptr)
1089 hitvec.erase(std::stable_partition(
1093 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: remove the merged hits in buffer, new size = " 1096 hitvec.swap(*theCollection);
1102 <<
" Size of reusehit= " <<
reusehit[
k].size()
1103 <<
"\n starting hit selection from index = " <<
cleanIndex[
k];
1107 for (
unsigned int i =
cleanIndex[
k];
i < theCollection->size(); ++
i) {
1123 reusehit[
k].emplace_back((*theCollection)[
i]);
1124 (*theCollection)[
i] =
nullptr;
1131 <<
" Number of added hit = " << addhit;
1136 for (
int ii = addhit - 1;
ii >= 0; --
ii) {
1144 theCollection->erase(
1145 std::stable_partition(
1146 theCollection->begin() +
cleanIndex[
k], theCollection->end(), [](
CaloG4Hit*
p) {
return p !=
nullptr; }),
1147 theCollection->end());
1150 theHC[
k]->PrintAllHits();
1159 int level = ((touch->GetHistoryDepth()) + 1);
1160 std::ostringstream st1;
1161 st1 <<
level <<
" Levels:";
1165 G4VPhysicalVolume*
pv = touch->GetVolume(
i);
1167 st1 <<
" " <<
name <<
":" << touch->GetReplicaNumber(
i);
CaloG4Hit * currentHit[2]
virtual void processSecondHit(const G4Step *, const G4Track *)
int getNumberOfHits(int k=0)
Int_t getEntry(TBranch *branch, EntryNumber entryNumber)
Log< level::Info, true > LogVerbatim
T getParameter(std::string const &) const
virtual bool getFromLibrary(const G4Step *step)
std::vector< PCaloHit > PCaloHitContainer
G4ThreadLocal G4Allocator< CaloG4Hit > * fpCaloG4HitAllocator
std::map< CaloHitID, CaloG4Hit * > hitMap[2]
virtual uint16_t getDepth(const G4Step *)
virtual double getEnergyDeposit(const G4Step *step)
virtual double EnergyCorrected(const G4Step &step, const G4Track *)
unsigned int findBoundaryCrossingParent(const G4Track *track, bool markParentAsSaveable=true)
TrackWithHistory * getTrackByID(int trackID, bool strict=false) const
void setIncidentEnergy(double e)
const math::XYZVectorD & momentum() const
uint32_t cc[maxCellsPerHit]
void setEntryLocal(double x, double y, double z)
uint32_t setDetUnitId(const G4Step *step) override=0
void newCollection(const std::string &name, edm::ParameterSet const &p)
uint16_t getDepth() const
G4ThreeVector setToLocal(const G4ThreeVector &, const G4VTouchable *) const
virtual int getTrackID(const G4Track *)
CaloG4HitCollection * theHC[2]
void Initialize(G4HCofThisEvent *HCE) override
std::vector< int > useResMap_
void fillHits(edm::PCaloHitContainer &, const std::string &) override
std::vector< Detector > fineDetectors_
void swap(Association< C > &lhs, Association< C > &rhs)
bool saveHit(CaloG4Hit *, int k=0)
bool equal(const T &first, const T &second)
virtual void initEvent(const BeginOfEvent *)
std::unordered_map< unsigned int, unsigned int > boundaryCrossingParentMap_
void cleanHitCollection()
static void clean(char *s)
T getUntrackedParameter(std::string const &, T const &) const
bool isItFineCalo(const G4VTouchable *touch)
void addEnergyDeposit(double em, double hd)
double getResponseWt(const G4Track *, int k=0)
bool isFinecaloTrackID() const
void updateHit(CaloG4Hit *, int k)
CaloG4Hit * createNewHit(const G4Step *, const G4Track *, int k)
static std::string printableDecayChain(const std::vector< unsigned int > &decayChain)
void resetForNewPrimary(const G4Step *)
void setID(uint32_t i, double d, int j, uint16_t k=0)
Abs< T >::type abs(const T &t)
G4bool ProcessHits(G4Step *step, G4TouchableHistory *) override
std::vector< std::string > hcn_
std::vector< std::unique_ptr< CaloG4Hit > > reusehit[2]
G4ThreeVector setToGlobal(const G4ThreeVector &, const G4VTouchable *) const
TrackInformation * cmsTrackInformation(const G4Track *aTrack)
virtual bool filterHit(CaloG4Hit *, double)
void setID(uint32_t unitID, double timeSlice, int trackID, uint16_t depth=0)
CaloSD(const std::string &aSDname, const SensitiveDetectorCatalog &clg, edm::ParameterSet const &p, const SimTrackManager *, float timeSlice=1., bool ignoreTkID=false, const std::string &newcolname="")
double getAttenuation(const G4Step *aStep, double birk1, double birk2, double birk3) const
void EndOfEvent(G4HCofThisEvent *eventHC) override
CSCCFEBTimeSlice const *const timeSlice(T const &data, int nCFEB, int nSample)
void storeHit(CaloG4Hit *, int k=0)
uint32_t getUnitID() const
const std::vector< TrackWithHistory * > * trackContainer() const
bool hitExists(const G4Step *, int k)
bool trackExists(int i) const
void printDetectorLevels(const G4VTouchable *) const
virtual int setTrackID(const G4Step *)
void markAsFinecaloTrackID(bool flag=true)
void setPosition(double x, double y, double z)
void setEntry(double x, double y, double z)
G4THitsCollection< CaloG4Hit > CaloG4HitCollection
static bool isGammaElectronPositron(int pdgCode)
double getTimeSlice() const
std::map< int, TrackWithHistory * > tkMap
int giveMotherNeeded(int i) const
std::unique_ptr< CaloMeanResponse > meanResponse[2]
const SimTrackManager * m_trackManager
std::string shortreprID(const CaloHitID &ID)
Log< level::Warning, false > LogWarning
void clearHits() override
std::unique_ptr< CaloSlaveSD > slave[2]
void NaNTrap(const G4Step *step) const
G4ThreeVector entrancePoint
G4ThreeVector entranceLocal
void update(const BeginOfRun *) override
This routine will be called when the appropriate signal arrives.