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 "G4PhysicalConstants.hh" 26 #include <CLHEP/Units/SystemOfUnits.h> 42 G4VGFlashSensitiveDetector(),
44 m_trackManager(manager),
45 ignoreTrackID(ignoreTkID),
49 nHC_ = (newcollName.empty()) ? 1 : 2;
50 for (
int k = 0;
k < 2; ++
k) {
55 bool dd4hep =
p.getParameter<
bool>(
"g4GeometryDD4hepSource");
56 int addlevel =
dd4hep ? 1 : 0;
60 std::vector<double> eminHits = m_CaloSD.
getParameter<std::vector<double>>(
"EminHits");
61 std::vector<double> tmaxHits = m_CaloSD.
getParameter<std::vector<double>>(
"TmaxHits");
64 std::vector<double> eminHitX = m_CaloSD.
getParameter<std::vector<double>>(
"EminHitsDepth");
74 double beamZ = m_CaloSD.
getParameter<
double>(
"BeamPosition") * CLHEP::cm;
75 correctT = beamZ / CLHEP::c_light / CLHEP::nanosecond;
78 std::vector<std::string> fineNames = m_CaloSD.
getParameter<std::vector<std::string>>(
"FineCaloNames");
79 std::vector<int> fineLevels = m_CaloSD.
getParameter<std::vector<int>>(
"FineCaloLevels");
80 std::vector<int> useFines = m_CaloSD.
getParameter<std::vector<int>>(
"UseFineCalo");
81 for (
auto&
level : fineLevels)
84 SetVerboseLevel(verbn);
85 for (
int k = 0;
k < 2; ++
k)
87 for (
unsigned int k = 0;
k <
hcn_.size(); ++
k) {
89 if (
k < eminHits.size())
91 if (
k < eminHitX.size())
93 if (
k < tmaxHits.size())
104 slave[0] = std::make_unique<CaloSlaveSD>(
name);
105 slave[1].reset(
nullptr);
107 for (
int k = 0;
k < 2; ++
k) {
120 for (
int k = 0;
k < 2; ++
k) {
125 <<
" GeV\n Use of HitID Map " <<
useMap <<
"\n Check last " 126 <<
nCheckedHits[0] <<
" before saving the hit\n Correct TOF globally by " 128 <<
tmaxHit <<
" ns and if energy is above " <<
eminHit / CLHEP::MeV
129 <<
" MeV (for depth 0) or " <<
eminHitD / CLHEP::MeV
130 <<
" MeV (for nonzero depths);\n Time Slice Unit " <<
timeSlice 132 <<
"\nBeam Position " << beamZ / CLHEP::cm <<
" cm";
137 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Have a possibility of " << fineNames.size() <<
" fine calorimeters of which " 138 << useFines.size() <<
" are selected";
139 for (
unsigned int k = 0;
k < fineNames.size(); ++
k)
140 edm::LogVerbatim(
"CaloSim") <<
"[" <<
k <<
"] " << fineNames[
k] <<
" at " << fineLevels[
k];
141 std::ostringstream st1;
142 for (
unsigned int k = 0;
k < useFines.size(); ++
k)
143 st1 <<
" [" <<
k <<
"] " << useFines[
k] <<
":" << fineNames[useFines[
k]];
145 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
146 std::vector<G4LogicalVolume*>::const_iterator lvcite;
147 for (
unsigned int i = 0;
i < useFines.size();
i++) {
148 G4LogicalVolume* lv =
nullptr;
149 G4String
name =
static_cast<G4String
>(fineNames[useFines[
i]]);
150 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
161 detector.level = fineLevels[useFines[
i]];
170 <<
" pointer to LV: " <<
detector.lv;
178 for (
unsigned int k = 0;
k <
hcn_.size(); ++
k) {
186 slave[1] = std::make_unique<CaloSlaveSD>(
name);
200 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" ID= " << aStep->GetTrack()->GetTrackID()
201 <<
" prID= " << aStep->GetTrack()->GetParentID()
202 <<
" Eprestep= " << aStep->GetPreStepPoint()->GetKineticEnergy()
203 <<
" step= " << aStep->GetStepLength() <<
" Edep= " << aStep->GetTotalEnergyDeposit();
215 (aStep->GetTrack())->SetTrackStatus(fStopAndKill);
216 if (0 < aStep->GetNumberOfSecondariesInCurrentStep()) {
217 auto tv = aStep->GetSecondaryInCurrentStep();
218 auto vol = aStep->GetPreStepPoint()->GetPhysicalVolume();
219 for (
auto& tk : *tv) {
220 if (tk->GetVolume() == vol) {
221 const_cast<G4Track*
>(tk)->SetTrackStatus(fStopAndKill);
231 if (aStep->GetTotalEnergyDeposit() <= 0.0) {
237 auto const theTrack = aStep->GetTrack();
240 double time = theTrack->GetGlobalTime() / CLHEP::nanosecond;
246 const G4TouchableHistory* touch =
static_cast<const G4TouchableHistory*
>(theTrack->GetTouchable());
248 <<
" currUnit= " <<
currentID[0].
unitID() <<
" Detector: " << GetName()
249 <<
" trackID= " << theTrack->GetTrackID() <<
" " 250 << theTrack->GetDefinition()->GetParticleName()
251 <<
"\n Edep= " << aStep->GetTotalEnergyDeposit()
252 <<
" PV: " << touch->GetVolume(0)->GetName()
253 <<
" PVid= " << touch->GetReplicaNumber(0) <<
" MVid= " << touch->GetReplicaNumber(1);
273 const G4TouchableHistory* touch =
static_cast<const G4TouchableHistory*
>(theTrack->GetTouchable());
274 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::" << GetName() <<
" PV:" << touch->GetVolume(0)->GetName()
275 <<
" PVid=" << touch->GetReplicaNumber(0) <<
" MVid=" << touch->GetReplicaNumber(1)
277 <<
edepositHAD <<
" ID=" << theTrack->GetTrackID() <<
" pID=" << theTrack->GetParentID()
278 <<
" E=" << theTrack->GetKineticEnergy() <<
" S=" << aStep->GetStepLength() <<
"\n " 279 << theTrack->GetDefinition()->GetParticleName() <<
" primaryID= " << primaryID
297 const G4Track*
track = aSpot->GetOriginatorTrack()->GetPrimaryTrack();
299 double edep = aSpot->GetEnergySpot()->GetEnergy();
305 G4StepPoint* fFakePreStepPoint = fFakeStep.GetPreStepPoint();
306 G4StepPoint* fFakePostStepPoint = fFakeStep.GetPostStepPoint();
307 fFakePreStepPoint->SetPosition(aSpot->GetPosition());
308 fFakePostStepPoint->SetPosition(aSpot->GetPosition());
310 G4TouchableHandle fTouchableHandle = aSpot->GetTouchableHandle();
311 fFakePreStepPoint->SetTouchableHandle(fTouchableHandle);
312 fFakeStep.SetTotalEnergyDeposit(edep);
330 double time =
track->GetGlobalTime() / CLHEP::nanosecond;
342 posGlobal = aSpot->GetEnergySpot()->GetPosition();
371 int level = ((touch->GetHistoryDepth()) + 1);
375 G4LogicalVolume* lv = touch->GetVolume(
ii)->GetLogicalVolume();
378 std::string name1 = (lv ==
nullptr) ?
"Unknown" : lv->GetName();
394 for (
int k = 0;
k <
nHC_; ++
k) {
419 for (
int k = 0;
k <
nHC_; ++
k) {
421 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: EndofEvent entered for container " <<
k <<
" with no entries";
423 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: EndofEvent entered for container " <<
k <<
" with " <<
theHC[
k]->entries()
434 for (
int k = 0;
k <
nHC_; ++
k) {
443 for (
int k = 0;
k <
nHC_; ++
k) {
445 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Tries to transfer " <<
slave[
k].get()->hits().size() <<
" hits for " 446 <<
slave[
k].get()->name() <<
" " << hname;
456 return touch->GetHistory()->GetTopTransform().TransformPoint(global);
460 return touch->GetHistory()->GetTopTransform().Inverse().TransformPoint(
local);
481 posGlobal = aStep->GetPreStepPoint()->GetPosition();
505 int maxhit =
nhits - 1;
507 for (
int j = maxhit;
j > minhit; --
j) {
529 std::stringstream
ss;
530 for (
long unsigned int i = 0;
i < decayChain.size();
i++) {
540 std::stringstream
ss;
541 ss << GetName() <<
"/" <<
ID.unitID() <<
"/trk" <<
ID.trackID() <<
"/d" <<
ID.depth() <<
"/time" <<
ID.timeSliceID();
542 if (
ID.isFinecaloTrackID())
555 unsigned int id =
track->GetTrackID();
560 edm::LogVerbatim(
"DoFineCalo") <<
"Track " <<
id <<
" parent already cached: " <<
it->second;
567 edm::LogVerbatim(
"DoFineCalo") <<
"Track " <<
id <<
" crosses boundary itself";
574 std::vector<unsigned int> decayChain{
id};
576 edm::LogVerbatim(
"DoFineCalo") <<
"Track " <<
id <<
": Traversing history to find boundary-crossing parent";
578 unsigned int parentID =
track->GetParentID();
582 <<
"Hit end of parentage for track " <<
id <<
" without finding a boundary-crossing parent";
588 <<
" boundary-crossing parent already cached: " <<
it->second;
591 for (
auto ancestorID : decayChain)
595 decayChain.push_back(parentID);
596 while (parentID !=
it->second) {
598 decayChain.push_back(parentID);
609 decayChain.push_back(parentID);
611 for (
auto ancestorID : decayChain)
614 edm::LogVerbatim(
"DoFineCalo") <<
" Found boundary-crossing ancestor " << parentID <<
" for track " <<
id 620 decayChain.push_back(parentID);
632 <<
" " << theTrack->GetDefinition()->GetParticleName()
633 <<
" E(GeV)= " << theTrack->GetKineticEnergy() / CLHEP::GeV
634 <<
" parentID= " << theTrack->GetParentID() <<
"\n Ein= " <<
incidentEnergy 662 <<
" isItFineCalo(post)=" <<
isItFineCalo(aStep->GetPostStepPoint()->GetTouchable())
663 <<
" isItFineCalo(pre)=" <<
isItFineCalo(aStep->GetPreStepPoint()->GetTouchable());
670 }
else if (
currentID[
k].trackID() == theTrack->GetTrackID()) {
671 etrack = theTrack->GetKineticEnergy();
686 if (trkh !=
nullptr) {
716 auto const preStepPoint = aStep->GetPreStepPoint();
721 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::resetForNewPrimary for " << GetName()
722 <<
" ID= " << aStep->GetTrack()->GetTrackID() <<
" Ein= " <<
incidentEnergy / CLHEP::GeV
730 double charge = aStep->GetPreStepPoint()->GetCharge();
731 double length = aStep->GetStepLength();
733 if (
charge != 0. && length > 0.) {
734 double density = aStep->GetPreStepPoint()->GetMaterial()->GetDensity();
735 double dedx = aStep->GetTotalEnergyDeposit() / length;
737 double c = birk2 * rkb * rkb;
740 weight = 1. / (1. + rkb * dedx +
c * dedx * dedx);
742 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::getAttenuation in " << aStep->GetPreStepPoint()->GetMaterial()->GetName()
743 <<
" Charge " <<
charge <<
" dE/dx " << dedx <<
" Birk Const " << rkb <<
", " <<
c 744 <<
" Weight = " <<
weight <<
" dE " << aStep->GetTotalEnergyDeposit();
754 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Dispatched BeginOfEvent for " << GetName() <<
" !";
761 int id = (*trk)()->GetTrackID();
763 int lastTrackID = -1;
766 if (
id == lastTrackID) {
768 if (!trksForThisEvent->empty()) {
773 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: get track " <<
id <<
" from Container of size " 774 << trksForThisEvent->size() <<
" with ID " << trkH->
trackID();
783 for (
int k = 0;
k <
nHC_; ++
k) {
798 int hc_entries =
theHC[
k]->entries();
799 for (
int i = 0;
i < hc_entries; ++
i) {
817 ee += (*
theHC[
k])[
i]->getIncidentEnergy();
823 double norm = (
count > 0) ? 1.0 /
count : 0.0;
837 <<
" hits not passing cuts\n EmeanEM= " << eEM <<
" ErmsEM= " << eEM2
838 <<
"\n EmeanHAD= " << eHAD <<
" ErmsHAD= " << eHAD2 <<
" TimeMean= " <<
tt 839 <<
" E0mean= " << ee <<
" Zglob= " << zglob <<
" Zloc= " << zloc <<
" ";
850 for (
int k = 0;
k <
nHC_; ++
k) {
855 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: Clears hit vector for " << GetName()
856 <<
" and initialise slave: " <<
slave[
k].get()->name();
858 slave[
k].get()->Initialize();
884 primaryID = aTrack->GetTrackID();
886 edm::LogWarning(
"CaloSim") <<
"CaloSD: Problem with primaryID **** set by force to TkID **** " << primaryID;
893 auto const theTrack = aStep->GetTrack();
896 if (primaryID <= 0) {
897 primaryID = theTrack->GetTrackID();
909 <<
" trackID= " << aStep->GetTrack()->GetTrackID() <<
" primaryID= " << primaryID;
920 if (
hit->getDepth() > 0)
923 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::filterHit(..) Depth " <<
hit->getDepth() <<
" Emin = " << emin <<
" (" 964 throw cms::Exception(
"Unknown",
"CaloSD") <<
"m_trackManager not set, needed for finecalo!";
967 <<
"Error on hit " <<
shortreprID(aHit) <<
": Parent track not in track manager";
969 aHit->
getEM() / CLHEP::GeV,
994 slave[
k].get()->processHits(
1002 <<
" by SimTrackManager Status " <<
ok;
1007 << aHit->
getDepth() <<
" due to " << tkID <<
" in time " <<
time <<
" of energy " 1008 << aHit->
getEM() / CLHEP::GeV <<
" GeV (EM) and " << aHit->
getHadr() / CLHEP::GeV
1018 primary = (*trk)()->GetTrackID();
1033 for (
int k = 0;
k <
nHC_; ++
k)
1034 if (
theHC[
k]->entries() > 0)
1042 for (
int k = 0;
k <
nHC_; ++
k) {
1043 std::vector<CaloG4Hit*>* theCollection =
theHC[
k]->GetVector();
1053 std::vector<CaloG4Hit*> hitvec;
1055 hitvec.swap(*theCollection);
1058 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: sort hits in buffer starting from " 1060 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
1061 if (hitvec[
i] ==
nullptr)
1070 for (
unsigned int j =
i + 1;
j < hitvec.size() &&
equal(hitvec[
i], hitvec[
j]); ++
j) {
1073 (*hitvec[
i]).addEnergyDeposit(*hitvec[
j]);
1074 (*hitvec[
j]).setEM(0.);
1075 (*hitvec[
j]).setHadr(0.);
1077 hitvec[
j] =
nullptr;
1082 edm::LogVerbatim(
"CaloSim") <<
"CaloSD: cleanHitCollection merge the hits in buffer ";
1083 for (
unsigned int i = 0;
i < hitvec.size(); ++
i) {
1084 if (hitvec[
i] ==
nullptr)
1091 hitvec.erase(std::stable_partition(
1095 edm::LogVerbatim(
"CaloSim") <<
"CaloSD::cleanHitCollection: remove the merged hits in buffer, new size = " 1098 hitvec.swap(*theCollection);
1104 <<
" Size of reusehit= " <<
reusehit[
k].size()
1105 <<
"\n starting hit selection from index = " <<
cleanIndex[
k];
1109 for (
unsigned int i =
cleanIndex[
k];
i < theCollection->size(); ++
i) {
1125 reusehit[
k].emplace_back((*theCollection)[
i]);
1126 (*theCollection)[
i] =
nullptr;
1133 <<
" Number of added hit = " << addhit;
1138 for (
int ii = addhit - 1;
ii >= 0; --
ii) {
1146 theCollection->erase(
1147 std::stable_partition(
1148 theCollection->begin() +
cleanIndex[
k], theCollection->end(), [](
CaloG4Hit*
p) {
return p !=
nullptr; }),
1149 theCollection->end());
1152 theHC[
k]->PrintAllHits();
1161 int level = ((touch->GetHistoryDepth()) + 1);
1162 std::ostringstream st1;
1163 st1 <<
level <<
" Levels:";
1167 G4VPhysicalVolume*
pv = touch->GetVolume(
i);
1169 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::string nameMatterLV(const std::string &name, bool dd4hep)
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.