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" 40 G4VGFlashSensitiveDetector(),
43 m_trackManager(manager),
45 ignoreTrackID(ignoreTkID),
50 bool dd4hep =
p.getParameter<
bool>(
"g4GeometryDD4hepSource");
51 int addlevel =
dd4hep ? 1 : 0;
55 std::vector<double> eminHits = m_CaloSD.
getParameter<std::vector<double>>(
"EminHits");
56 std::vector<double> tmaxHits = m_CaloSD.
getParameter<std::vector<double>>(
"TmaxHits");
57 std::vector<std::string> hcn = m_CaloSD.
getParameter<std::vector<std::string>>(
"HCNames");
58 std::vector<int> useResMap = m_CaloSD.
getParameter<std::vector<int>>(
"UseResponseTables");
59 std::vector<double> eminHitX = m_CaloSD.
getParameter<std::vector<double>>(
"EminHitsDepth");
68 double beamZ = m_CaloSD.
getParameter<
double>(
"BeamPosition") * CLHEP::cm;
69 correctT = beamZ / CLHEP::c_light / CLHEP::nanosecond;
72 std::vector<std::string> fineNames = m_CaloSD.
getParameter<std::vector<std::string>>(
"FineCaloNames");
73 std::vector<int> fineLevels = m_CaloSD.
getParameter<std::vector<int>>(
"FineCaloLevels");
74 std::vector<int> useFines = m_CaloSD.
getParameter<std::vector<int>>(
"UseFineCalo");
75 for (
auto&
level : fineLevels)
78 SetVerboseLevel(verbn);
80 for (
unsigned int k = 0;
k < hcn.size(); ++
k) {
82 if (
k < eminHits.size())
84 if (
k < eminHitX.size())
86 if (
k < tmaxHits.size())
88 if (
k < useResMap.size() && useResMap[
k] > 0) {
94 slave = std::make_unique<CaloSlaveSD>(
name);
110 <<
" before saving the hit\n Correct TOF globally by " <<
correctT 112 <<
" ns and if energy is above " <<
eminHit / CLHEP::MeV <<
" MeV (for depth 0) or " 113 <<
eminHitD / CLHEP::MeV <<
" MeV (for nonzero depths);\n Time Slice Unit " 115 <<
doFineCalo_ <<
"\nBeam Position " << beamZ / CLHEP::cm <<
" cm";
120 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Have a possibility of " << fineNames.size() <<
" fine calorimeters of which " 121 << useFines.size() <<
" are selected";
122 for (
unsigned int k = 0;
k < fineNames.size(); ++
k)
123 edm::LogVerbatim(
"CaloSim") <<
"[" <<
k <<
"] " << fineNames[
k] <<
" at " << fineLevels[
k];
124 std::ostringstream st1;
125 for (
unsigned int k = 0;
k < useFines.size(); ++
k)
126 st1 <<
" [" <<
k <<
"] " << useFines[
k] <<
":" << fineNames[useFines[
k]];
128 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
129 std::vector<G4LogicalVolume*>::const_iterator lvcite;
130 for (
unsigned int i = 0;
i < useFines.size();
i++) {
131 G4LogicalVolume* lv =
nullptr;
132 G4String
name =
static_cast<G4String
>(fineNames[useFines[
i]]);
133 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
134 G4String namx(static_cast<std::string>(dd4hep::dd::noNamespace((*lvcite)->GetName())));
144 detector.level = fineLevels[useFines[
i]];
153 <<
" pointer to LV: " <<
detector.lv;
165 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" ID= " << aStep->GetTrack()->GetTrackID()
166 <<
" prID= " << aStep->GetTrack()->GetParentID()
167 <<
" Eprestep= " << aStep->GetPreStepPoint()->GetKineticEnergy()
168 <<
" step= " << aStep->GetStepLength() <<
" Edep= " << aStep->GetTotalEnergyDeposit();
180 (aStep->GetTrack())->SetTrackStatus(fStopAndKill);
181 if (0 < aStep->GetNumberOfSecondariesInCurrentStep()) {
182 auto tv = aStep->GetSecondaryInCurrentStep();
183 auto vol = aStep->GetPreStepPoint()->GetPhysicalVolume();
184 for (
auto& tk : *tv) {
185 if (tk->GetVolume() == vol) {
186 const_cast<G4Track*
>(tk)->SetTrackStatus(fStopAndKill);
196 if (aStep->GetTotalEnergyDeposit() <= 0.0) {
202 auto const theTrack = aStep->GetTrack();
205 double time = theTrack->GetGlobalTime() / nanosecond;
211 const G4TouchableHistory* touch =
static_cast<const G4TouchableHistory*
>(theTrack->GetTouchable());
213 <<
" Detector: " << GetName() <<
" trackID= " << theTrack->GetTrackID() <<
" " 214 << theTrack->GetDefinition()->GetParticleName()
215 <<
"\n Edep= " << aStep->GetTotalEnergyDeposit()
216 <<
" PV: " << touch->GetVolume(0)->GetName()
217 <<
" PVid= " << touch->GetReplicaNumber(0) <<
" MVid= " << touch->GetReplicaNumber(1);
237 const G4TouchableHistory* touch =
static_cast<const G4TouchableHistory*
>(theTrack->GetTouchable());
238 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" PV:" << touch->GetVolume(0)->GetName()
239 <<
" PVid=" << touch->GetReplicaNumber(0) <<
" MVid=" << touch->GetReplicaNumber(1)
241 <<
edepositHAD <<
" ID=" << theTrack->GetTrackID() <<
" pID=" << theTrack->GetParentID()
242 <<
" E=" << theTrack->GetKineticEnergy() <<
" S=" << aStep->GetStepLength() <<
"\n " 243 << theTrack->GetDefinition()->GetParticleName() <<
" primaryID= " << primaryID
258 const G4Track*
track = aSpot->GetOriginatorTrack()->GetPrimaryTrack();
260 double edep = aSpot->GetEnergySpot()->GetEnergy();
266 G4StepPoint* fFakePreStepPoint = fFakeStep.GetPreStepPoint();
267 G4StepPoint* fFakePostStepPoint = fFakeStep.GetPostStepPoint();
268 fFakePreStepPoint->SetPosition(aSpot->GetPosition());
269 fFakePostStepPoint->SetPosition(aSpot->GetPosition());
271 G4TouchableHandle fTouchableHandle = aSpot->GetTouchableHandle();
272 fFakePreStepPoint->SetTouchableHandle(fTouchableHandle);
273 fFakeStep.SetTotalEnergyDeposit(edep);
291 double time =
track->GetGlobalTime() / nanosecond;
303 posGlobal = aSpot->GetEnergySpot()->GetPosition();
332 int level = ((touch->GetHistoryDepth()) + 1);
336 G4LogicalVolume* lv = touch->GetVolume(
ii)->GetLogicalVolume();
339 std::string name1 = (lv == 0) ?
"Unknown" : lv->GetName();
354 edm::LogVerbatim(
"CaloSim") <<
"CaloSD : Initialize called for " << GetName();
374 if (
theHC ==
nullptr)
375 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: EndofEvent entered with no entries";
389 theHC->PrintAllHits();
394 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Tries to transfer " <<
slave.get()->hits().size() <<
" hits for " 395 <<
slave.get()->name() <<
" " << hname;
397 if (
slave.get()->name() == hname) {
398 cc =
slave.get()->hits();
400 slave.get()->Clean();
404 return touch->GetHistory()->GetTopTransform().TransformPoint(global);
408 return touch->GetHistory()->GetTopTransform().Inverse().TransformPoint(
local);
425 posGlobal = aStep->GetPreStepPoint()->GetPosition();
436 std::map<CaloHitID, CaloG4Hit*>::const_iterator it =
hitMap.find(
currentID);
444 int maxhit =
nhits - 1;
446 for (
int j = maxhit;
j > minhit; --
j) {
468 std::stringstream
ss;
469 for (
long unsigned int i = 0;
i < decayChain.size();
i++) {
479 std::stringstream
ss;
480 ss << GetName() <<
"/" <<
ID.unitID() <<
"/trk" <<
ID.trackID() <<
"/d" <<
ID.depth() <<
"/time" <<
ID.timeSliceID();
481 if (
ID.isFinecaloTrackID())
494 unsigned int id =
track->GetTrackID();
499 edm::LogVerbatim(
"DoFineCalo") <<
"Track " <<
id <<
" parent already cached: " << it->second;
506 edm::LogVerbatim(
"DoFineCalo") <<
"Track " <<
id <<
" crosses boundary itself";
513 std::vector<unsigned int> decayChain{
id};
515 edm::LogVerbatim(
"DoFineCalo") <<
"Track " <<
id <<
": Traversing history to find boundary-crossing parent";
517 unsigned int parentID =
track->GetParentID();
521 <<
"Hit end of parentage for track " <<
id <<
" without finding a boundary-crossing parent";
527 <<
" boundary-crossing parent already cached: " << it->second;
530 for (
auto ancestorID : decayChain)
534 decayChain.push_back(parentID);
535 while (parentID != it->second) {
537 decayChain.push_back(parentID);
548 decayChain.push_back(parentID);
550 for (
auto ancestorID : decayChain)
553 edm::LogVerbatim(
"DoFineCalo") <<
" Found boundary-crossing ancestor " << parentID <<
" for track " <<
id 559 decayChain.push_back(parentID);
570 << theTrack->GetDefinition()->GetParticleName()
571 <<
" E(GeV)= " << theTrack->GetKineticEnergy() / CLHEP::GeV
572 <<
" parentID= " << theTrack->GetParentID() <<
"\n Ein= " <<
incidentEnergy 600 <<
" isItFineCalo(post)=" <<
isItFineCalo(aStep->GetPostStepPoint()->GetTouchable())
601 <<
" isItFineCalo(pre)=" <<
isItFineCalo(aStep->GetPreStepPoint()->GetTouchable());
609 etrack = theTrack->GetKineticEnergy();
624 if (trkh !=
nullptr) {
654 auto const preStepPoint = aStep->GetPreStepPoint();
659 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::resetForNewPrimary for " << GetName()
660 <<
" ID= " << aStep->GetTrack()->GetTrackID() <<
" Ein= " <<
incidentEnergy / CLHEP::GeV
668 double charge = aStep->GetPreStepPoint()->GetCharge();
669 double length = aStep->GetStepLength();
671 if (
charge != 0. && length > 0.) {
672 double density = aStep->GetPreStepPoint()->GetMaterial()->GetDensity();
673 double dedx = aStep->GetTotalEnergyDeposit() / length;
675 double c = birk2 * rkb * rkb;
678 weight = 1. / (1. + rkb * dedx +
c * dedx * dedx);
680 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::getAttenuation in " << aStep->GetPreStepPoint()->GetMaterial()->GetName()
681 <<
" Charge " <<
charge <<
" dE/dx " << dedx <<
" Birk Const " << rkb <<
", " <<
c 682 <<
" Weight = " <<
weight <<
" dE " << aStep->GetTotalEnergyDeposit();
692 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Dispatched BeginOfEvent for " << GetName() <<
" !";
699 int id = (*trk)()->GetTrackID();
701 int lastTrackID = -1;
704 if (
id == lastTrackID) {
706 if (trksForThisEvent !=
nullptr) {
707 int it = (
int)(trksForThisEvent->size()) - 1;
713 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: get track " << it <<
" from Container of size " 714 << trksForThisEvent->size() <<
" with ID " << trkH->
trackID();
716 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: get track " << it <<
" from Container of size " 717 << trksForThisEvent->size() <<
" with no ID";
738 int hc_entries =
theHC->entries();
739 for (
int i = 0;
i < hc_entries; ++
i) {
744 double x = (*theHC)[
i]->getEM();
747 x = (*theHC)[
i]->getHadr();
750 tt += (*theHC)[
i]->getTimeSlice();
751 ee += (*theHC)[
i]->getIncidentEnergy();
756 double norm = (
count > 0) ? 1.0 /
count : 0.0;
771 <<
" hits not passing cuts\n EmeanEM= " << eEM <<
" ErmsEM= " << eEM2
772 <<
"\n EmeanHAD= " << eHAD <<
" ErmsHAD= " << eHAD2 <<
" TimeMean= " <<
tt 773 <<
" E0mean= " << ee <<
" Zglob= " << zglob <<
" Zloc= " << zloc <<
" ";
776 std::vector<std::unique_ptr<CaloG4Hit>>().
swap(
reusehit);
787 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Clears hit vector for " << GetName()
788 <<
" and initialise slave: " <<
slave.get()->name();
790 slave.get()->Initialize();
815 primaryID = aTrack->GetTrackID();
817 edm::LogWarning(
"CaloSim") <<
"CaloSD: Problem with primaryID **** set by force to TkID **** " << primaryID;
824 auto const theTrack = aStep->GetTrack();
827 if (primaryID <= 0) {
828 primaryID = theTrack->GetTrackID();
840 <<
" trackID= " << aStep->GetTrack()->GetTrackID() <<
" primaryID= " << primaryID;
849 if (
hit->getDepth() > 0)
852 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::filterHit(..) Depth " <<
hit->getDepth() <<
" Emin = " << emin <<
" (" 893 throw cms::Exception(
"Unknown",
"CaloSD") <<
"m_trackManager not set, needed for finecalo!";
896 <<
"Error on hit " <<
shortreprID(aHit) <<
": Parent track not in track manager";
898 aHit->
getEM() / CLHEP::GeV,
922 slave.get()->processHits(
930 <<
" by SimTrackManager Status " <<
ok;
935 << aHit->
getDepth() <<
" due to " << tkID <<
" in time " <<
time <<
" of energy " 936 << aHit->
getEM() / CLHEP::GeV <<
" GeV (EM) and " << aHit->
getHadr() / CLHEP::GeV
946 primary = (*trk)()->GetTrackID();
960 if (
theHC->entries() > 0)
966 std::vector<CaloG4Hit*>* theCollection =
theHC->GetVector();
976 std::vector<CaloG4Hit*> hitvec;
978 hitvec.swap(*theCollection);
981 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: sort hits in buffer starting from " 983 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
984 if (hitvec[
i] ==
nullptr)
993 for (
unsigned int j =
i + 1;
j < hitvec.size() &&
equal(hitvec[
i], hitvec[
j]); ++
j) {
996 (*hitvec[
i]).addEnergyDeposit(*hitvec[
j]);
997 (*hitvec[
j]).setEM(0.);
998 (*hitvec[
j]).setHadr(0.);
1000 hitvec[
j] =
nullptr;
1005 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: cleanHitCollection merge the hits in buffer ";
1006 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
1007 if (hitvec[
i] ==
nullptr)
1015 std::stable_partition(hitvec.begin() +
cleanIndex, hitvec.end(), [](
CaloG4Hit*
p) {
return p !=
nullptr; }),
1018 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: remove the merged hits in buffer," 1019 <<
" new size = " << hitvec.size();
1021 hitvec.swap(*theCollection);
1027 <<
" Size of reusehit= " <<
reusehit.size()
1028 <<
"\n starting hit selection from index = " <<
cleanIndex;
1032 for (
unsigned int i =
cleanIndex;
i < theCollection->size(); ++
i) {
1048 reusehit.emplace_back((*theCollection)[
i]);
1049 (*theCollection)[
i] =
nullptr;
1056 <<
" Number of added hit = " << addhit;
1061 for (
int ii = addhit - 1;
ii >= 0; --
ii) {
1069 theCollection->erase(
1070 std::stable_partition(
1071 theCollection->begin() +
cleanIndex, theCollection->end(), [](
CaloG4Hit*
p) {
return p !=
nullptr; }),
1072 theCollection->end());
1074 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: hit collection after selection, size = " <<
theHC->entries();
1075 theHC->PrintAllHits();
1083 int level = ((touch->GetHistoryDepth()) + 1);
1084 std::ostringstream st1;
1085 st1 <<
level <<
" Levels:";
1089 G4VPhysicalVolume*
pv = touch->GetVolume(
i);
1091 st1 <<
" " <<
name <<
":" << touch->GetReplicaNumber(
i);
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
void updateHit(CaloG4Hit *)
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)
void setIncidentEnergy(double e)
const math::XYZVectorD & momentum() const
void setEntryLocal(double x, double y, double z)
uint32_t setDetUnitId(const G4Step *step) override=0
TrackWithHistory * getTrackByID(unsigned int trackID, bool strict=false) const
uint16_t getDepth() const
G4ThreeVector setToLocal(const G4ThreeVector &, const G4VTouchable *) const
virtual int getTrackID(const G4Track *)
void Initialize(G4HCofThisEvent *HCE) override
void fillHits(edm::PCaloHitContainer &, const std::string &) override
std::vector< Detector > fineDetectors_
void swap(Association< C > &lhs, Association< C > &rhs)
bool equal(const T &first, const T &second)
virtual void initEvent(const BeginOfEvent *)
std::unordered_map< unsigned int, unsigned int > boundaryCrossingParentMap_
void cleanHitCollection()
T getUntrackedParameter(std::string const &, T const &) const
bool isItFineCalo(const G4VTouchable *touch)
void addEnergyDeposit(double em, double hd)
bool trackExists(unsigned int i) const
bool isFinecaloTrackID() const
static std::string printableDecayChain(const std::vector< unsigned int > &decayChain)
std::unique_ptr< CaloSlaveSD > slave
std::vector< TrackWithHistory * > TrackContainer
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
CaloG4Hit * createNewHit(const G4Step *, const G4Track *)
void storeHit(CaloG4Hit *)
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)
bool hitExists(const G4Step *)
const TrackContainer * trackContainer() const
std::unique_ptr< CaloMeanResponse > meanResponse
std::map< CaloHitID, CaloG4Hit * > hitMap
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)
uint32_t getUnitID() const
CaloG4HitCollection * theHC
CaloSD(const std::string &aSDname, const SensitiveDetectorCatalog &clg, edm::ParameterSet const &p, const SimTrackManager *, float timeSlice=1., bool ignoreTkID=false)
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::vector< std::unique_ptr< CaloG4Hit > > reusehit
const SimTrackManager * m_trackManager
std::string shortreprID(const CaloHitID &ID)
Log< level::Warning, false > LogWarning
void clearHits() override
double getResponseWt(const G4Track *)
bool saveHit(CaloG4Hit *)
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.
unsigned int trackID() const