CMS 3D CMS Logo

StackingAction.cc
Go to the documentation of this file.
6 
8 
9 #include "G4VProcess.hh"
10 #include "G4EmProcessSubType.hh"
11 #include "G4LogicalVolumeStore.hh"
12 #include "G4RegionStore.hh"
13 #include "Randomize.hh"
14 #include "G4SystemOfUnits.hh"
15 #include "G4VSolid.hh"
16 #include "G4TransportationManager.hh"
17 #include "G4GammaGeneralProcess.hh"
18 #include "G4LossTableManager.hh"
19 
21  : trackAction(trka), steppingVerbose(sv) {
22  trackNeutrino = p.getParameter<bool>("TrackNeutrino");
23  killHeavy = p.getParameter<bool>("KillHeavy");
24  killGamma = p.getParameter<bool>("KillGamma");
25  kmaxGamma = p.getParameter<double>("GammaThreshold") * CLHEP::MeV;
26  kmaxIon = p.getParameter<double>("IonThreshold") * CLHEP::MeV;
27  kmaxProton = p.getParameter<double>("ProtonThreshold") * CLHEP::MeV;
28  kmaxNeutron = p.getParameter<double>("NeutronThreshold") * CLHEP::MeV;
29  killDeltaRay = p.getParameter<bool>("KillDeltaRay");
30  limitEnergyForVacuum = p.getParameter<double>("CriticalEnergyForVacuum") * CLHEP::MeV;
31  maxTrackTime = p.getParameter<double>("MaxTrackTime") * ns;
32  maxTrackTimeForward = p.getParameter<double>("MaxTrackTimeForward") * ns;
33  maxZCentralCMS = p.getParameter<double>("MaxZCentralCMS") * CLHEP::m;
34  maxTrackTimes = p.getParameter<std::vector<double> >("MaxTrackTimes");
35  maxTimeNames = p.getParameter<std::vector<std::string> >("MaxTimeNames");
36  deadRegionNames = p.getParameter<std::vector<std::string> >("DeadRegions");
37  savePDandCinAll = p.getUntrackedParameter<bool>("SaveAllPrimaryDecayProductsAndConversions", true);
38  savePDandCinTracker = p.getUntrackedParameter<bool>("SavePrimaryDecayProductsAndConversionsInTracker", false);
39  savePDandCinCalo = p.getUntrackedParameter<bool>("SavePrimaryDecayProductsAndConversionsInCalo", false);
40  savePDandCinMuon = p.getUntrackedParameter<bool>("SavePrimaryDecayProductsAndConversionsInMuon", false);
41  saveFirstSecondary = p.getUntrackedParameter<bool>("SaveFirstLevelSecondary", false);
42 
43  gRusRoEnerLim = p.getParameter<double>("RusRoGammaEnergyLimit") * CLHEP::MeV;
44  nRusRoEnerLim = p.getParameter<double>("RusRoNeutronEnergyLimit") * CLHEP::MeV;
45 
46  gRusRoEcal = p.getParameter<double>("RusRoEcalGamma");
47  gRusRoHcal = p.getParameter<double>("RusRoHcalGamma");
48  gRusRoMuonIron = p.getParameter<double>("RusRoMuonIronGamma");
49  gRusRoPreShower = p.getParameter<double>("RusRoPreShowerGamma");
50  gRusRoCastor = p.getParameter<double>("RusRoCastorGamma");
51  gRusRoWorld = p.getParameter<double>("RusRoWorldGamma");
52 
53  nRusRoEcal = p.getParameter<double>("RusRoEcalNeutron");
54  nRusRoHcal = p.getParameter<double>("RusRoHcalNeutron");
55  nRusRoMuonIron = p.getParameter<double>("RusRoMuonIronNeutron");
56  nRusRoPreShower = p.getParameter<double>("RusRoPreShowerNeutron");
57  nRusRoCastor = p.getParameter<double>("RusRoCastorNeutron");
58  nRusRoWorld = p.getParameter<double>("RusRoWorldNeutron");
59 
60  if (gRusRoEnerLim > 0.0 && (gRusRoEcal < 1.0 || gRusRoHcal < 1.0 || gRusRoMuonIron < 1.0 || gRusRoPreShower < 1.0 ||
61  gRusRoCastor < 1.0 || gRusRoWorld < 1.0)) {
62  gRRactive = true;
63  }
64  if (nRusRoEnerLim > 0.0 && (nRusRoEcal < 1.0 || nRusRoHcal < 1.0 || nRusRoMuonIron < 1.0 || nRusRoPreShower < 1.0 ||
65  nRusRoCastor < 1.0 || nRusRoWorld < 1.0)) {
66  nRRactive = true;
67  }
68 
69  if (p.exists("TestKillingOptions")) {
70  killInCalo = (p.getParameter<edm::ParameterSet>("TestKillingOptions")).getParameter<bool>("KillInCalo");
71  killInCaloEfH = (p.getParameter<edm::ParameterSet>("TestKillingOptions")).getParameter<bool>("KillInCaloEfH");
72  edm::LogWarning("SimG4CoreApplication")
73  << " *** Activating special test killing options in StackingAction \n"
74  << " *** Kill secondaries in Calorimetetrs volume = " << killInCalo << "\n"
75  << " *** Kill electromagnetic secondaries from hadrons in Calorimeters volume= " << killInCaloEfH;
76  }
77 
78  initPointer();
79 
80  edm::LogVerbatim("SimG4CoreApplication")
81  << "StackingAction initiated with"
82  << " flag for saving decay products in "
83  << " Tracker: " << savePDandCinTracker << " in Calo: " << savePDandCinCalo << " in Muon: " << savePDandCinMuon
84  << " everywhere: " << savePDandCinAll << "\n saveFirstSecondary"
85  << ": " << saveFirstSecondary << " Tracking neutrino flag: " << trackNeutrino
86  << " Kill Delta Ray flag: " << killDeltaRay << " Kill hadrons/ions flag: " << killHeavy
87  << " MaxZCentralCMS = " << maxZCentralCMS / CLHEP::m << " m"
88  << " MaxTrackTimeForward = " << maxTrackTimeForward / CLHEP::ns << " ns";
89 
90  if (killHeavy) {
91  edm::LogVerbatim("SimG4CoreApplication") << "StackingAction kill protons below " << kmaxProton / CLHEP::MeV
92  << " MeV, neutrons below " << kmaxNeutron / CLHEP::MeV << " MeV and ions"
93  << " below " << kmaxIon / CLHEP::MeV << " MeV";
94  }
96 
97  edm::LogVerbatim("SimG4CoreApplication") << "StackingAction kill tracks with "
98  << "time larger than " << maxTrackTime / CLHEP::ns << " ns ";
99  numberTimes = maxTimeNames.size();
100  if (0 < numberTimes) {
101  for (unsigned int i = 0; i < numberTimes; ++i) {
102  edm::LogVerbatim("SimG4CoreApplication")
103  << " MaxTrackTime for " << maxTimeNames[i] << " is " << maxTrackTimes[i] << " ns ";
104  maxTrackTimes[i] *= CLHEP::ns;
105  }
106  }
107  if (limitEnergyForVacuum > 0.0) {
108  edm::LogVerbatim("SimG4CoreApplication")
109  << "StackingAction LowDensity regions - kill if E < " << limitEnergyForVacuum / CLHEP::MeV << " MeV";
110  printRegions(lowdensRegions, "LowDensity");
111  }
112  if (deadRegions.size() > 0.0) {
113  edm::LogVerbatim("SimG4CoreApplication") << "StackingAction Dead regions - kill all secondaries ";
114  printRegions(deadRegions, "Dead");
115  }
116  if (gRRactive) {
117  edm::LogVerbatim("SimG4CoreApplication")
118  << "StackingAction: "
119  << "Russian Roulette for gamma Elimit(MeV)= " << gRusRoEnerLim / CLHEP::MeV << "\n"
120  << " ECAL Prob= " << gRusRoEcal << "\n"
121  << " HCAL Prob= " << gRusRoHcal << "\n"
122  << " MuonIron Prob= " << gRusRoMuonIron << "\n"
123  << " PreShower Prob= " << gRusRoPreShower << "\n"
124  << " CASTOR Prob= " << gRusRoCastor << "\n"
125  << " World Prob= " << gRusRoWorld;
126  }
127  if (nRRactive) {
128  edm::LogVerbatim("SimG4CoreApplication")
129  << "StackingAction: "
130  << "Russian Roulette for neutron Elimit(MeV)= " << nRusRoEnerLim / CLHEP::MeV << "\n"
131  << " ECAL Prob= " << nRusRoEcal << "\n"
132  << " HCAL Prob= " << nRusRoHcal << "\n"
133  << " MuonIron Prob= " << nRusRoMuonIron << "\n"
134  << " PreShower Prob= " << nRusRoPreShower << "\n"
135  << " CASTOR Prob= " << nRusRoCastor << "\n"
136  << " World Prob= " << nRusRoWorld;
137  }
138 
139  if (savePDandCinTracker) {
140  edm::LogVerbatim("SimG4CoreApplication") << "StackingAction Tracker regions: ";
141  printRegions(trackerRegions, "Tracker");
142  }
143  if (savePDandCinCalo) {
144  edm::LogVerbatim("SimG4CoreApplication") << "StackingAction Calo regions: ";
145  printRegions(caloRegions, "Calo");
146  }
147  if (savePDandCinMuon) {
148  edm::LogVerbatim("SimG4CoreApplication") << "StackingAction Muon regions: ";
149  printRegions(muonRegions, "Muon");
150  }
151  worldSolid = G4TransportationManager::GetTransportationManager()
152  ->GetNavigatorForTracking()
153  ->GetWorldVolume()
154  ->GetLogicalVolume()
155  ->GetSolid();
156 }
157 
158 G4ClassificationOfNewTrack StackingAction::ClassifyNewTrack(const G4Track* aTrack) {
159  // G4 interface part
160  G4ClassificationOfNewTrack classification = fUrgent;
161  const int pdg = aTrack->GetDefinition()->GetPDGEncoding();
162  const int abspdg = std::abs(pdg);
163  auto track = const_cast<G4Track*>(aTrack);
164  const G4VProcess* creatorProc = aTrack->GetCreatorProcess();
165 
166  if (creatorProc == nullptr && aTrack->GetParentID() != 0) {
167  edm::LogWarning("StackingAction::ClassifyNewTrack")
168  << " TrackID=" << aTrack->GetTrackID() << " ParentID=" << aTrack->GetParentID() << " "
169  << aTrack->GetDefinition()->GetParticleName() << " Ekin(MeV)=" << aTrack->GetKineticEnergy();
170  }
171  if (aTrack->GetKineticEnergy() < 0.0) {
172  edm::LogWarning("StackingAction::ClassifyNewTrack")
173  << " TrackID=" << aTrack->GetTrackID() << " ParentID=" << aTrack->GetParentID() << " "
174  << aTrack->GetDefinition()->GetParticleName() << " Ekin(MeV)=" << aTrack->GetKineticEnergy() << " creator "
175  << creatorProc->GetProcessName();
176  }
177  // primary
178  if (creatorProc == nullptr || aTrack->GetParentID() == 0) {
179  if (!trackNeutrino && (abspdg == 12 || abspdg == 14 || abspdg == 16 || abspdg == 18)) {
180  classification = fKill;
181  } else if (worldSolid->Inside(aTrack->GetPosition()) == kOutside) {
182  classification = fKill;
183  } else {
185  }
186  } else {
187  // secondary
188  const G4Region* reg = aTrack->GetVolume()->GetLogicalVolume()->GetRegion();
189  const double time = aTrack->GetGlobalTime();
190 
191  // definetly killed tracks
192  if (aTrack->GetTrackStatus() == fStopAndKill) {
193  classification = fKill;
194  } else if (!trackNeutrino && (abspdg == 12 || abspdg == 14 || abspdg == 16 || abspdg == 18)) {
195  classification = fKill;
196 
197  } else if (std::abs(aTrack->GetPosition().z()) >= maxZCentralCMS) {
198  // very forward secondary
199  if (time > maxTrackTimeForward) {
200  classification = fKill;
201  } else {
202  const G4Track* mother = trackAction->geant4Track();
203  MCTruthUtil::secondary(track, *mother, 0);
204  }
205 
206  } else if (isItOutOfTimeWindow(reg, time)) {
207  // time window check
208  classification = fKill;
209 
210  } else {
211  // potentially good for tracking
212  const double ke = aTrack->GetKineticEnergy();
213  G4int subType = (nullptr != creatorProc) ? creatorProc->GetProcessSubType() : 0;
214 
215  LogDebug("SimG4CoreApplication") << "##StackingAction:Classify Track " << aTrack->GetTrackID() << " Parent "
216  << aTrack->GetParentID() << " " << aTrack->GetDefinition()->GetParticleName()
217  << " Ekin(MeV)=" << ke / CLHEP::MeV << " subType=" << subType << " ";
218 
219  // kill tracks in specific regions
220  if (isThisRegion(reg, deadRegions)) {
221  classification = fKill;
222  }
223  if (classification != fKill && ke <= limitEnergyForVacuum && isThisRegion(reg, lowdensRegions)) {
224  classification = fKill;
225 
226  } else if (classification != fKill) {
227  // very low-energy gamma
228  if (pdg == 22 && killGamma && ke < kmaxGamma) {
229  classification = fKill;
230  }
231 
232  // specific track killing - not for production
233  if (killExtra && classification != fKill) {
234  if (killHeavy && classification != fKill) {
235  if (((pdg / 1000000000 == 1) && (((pdg / 10000) % 100) > 0) && (((pdg / 10) % 100) > 0) &&
236  (ke < kmaxIon)) ||
237  ((pdg == 2212) && (ke < kmaxProton)) || ((pdg == 2112) && (ke < kmaxNeutron))) {
238  classification = fKill;
239  }
240  }
241 
242  if (killDeltaRay && classification != fKill && subType == fIonisation) {
243  classification = fKill;
244  }
245  if (killInCalo && classification != fKill && isThisRegion(reg, caloRegions)) {
246  classification = fKill;
247  }
248  if (killInCaloEfH && classification != fKill) {
249  int pdgMother = std::abs(trackAction->geant4Track()->GetDefinition()->GetPDGEncoding());
250  if ((pdg == 22 || abspdg == 11) && pdgMother != 11 && pdgMother != 22 && isThisRegion(reg, caloRegions)) {
251  classification = fKill;
252  }
253  }
254  }
255 
256  // Russian roulette && MC truth
257  if (classification != fKill) {
258  const G4Track* mother = trackAction->geant4Track();
259  int flag = 0;
260  if (savePDandCinAll) {
261  flag = isItPrimaryDecayProductOrConversion(subType, *mother);
262  } else {
266  flag = isItPrimaryDecayProductOrConversion(subType, *mother);
267  }
268  }
269  if (saveFirstSecondary && 0 == flag) {
270  flag = isItFromPrimary(*mother, flag);
271  }
272 
273  // Russian roulette
274  if (2112 == pdg || 22 == pdg) {
275  double currentWeight = aTrack->GetWeight();
276 
277  if (1.0 >= currentWeight) {
278  double prob = 1.0;
279  double elim = 0.0;
280 
281  // neutron
282  if (nRRactive && pdg == 2112) {
283  elim = nRusRoEnerLim;
284  if (reg == regionEcal) {
285  prob = nRusRoEcal;
286  } else if (reg == regionHcal) {
287  prob = nRusRoHcal;
288  } else if (reg == regionMuonIron) {
290  } else if (reg == regionPreShower) {
292  } else if (reg == regionCastor) {
293  prob = nRusRoCastor;
294  } else if (reg == regionWorld) {
295  prob = nRusRoWorld;
296  }
297 
298  // gamma
299  } else if (gRRactive && pdg == 22) {
300  elim = gRusRoEnerLim;
301  if (reg == regionEcal || reg == regionPreShower) {
302  if (rrApplicable(aTrack, *mother)) {
303  if (reg == regionEcal) {
304  prob = gRusRoEcal;
305  } else {
307  }
308  }
309  } else {
310  if (reg == regionHcal) {
311  prob = gRusRoHcal;
312  } else if (reg == regionMuonIron) {
314  } else if (reg == regionCastor) {
315  prob = gRusRoCastor;
316  } else if (reg == regionWorld) {
317  prob = gRusRoWorld;
318  }
319  }
320  }
321  if (prob < 1.0 && aTrack->GetKineticEnergy() < elim) {
322  if (G4UniformRand() < prob) {
323  track->SetWeight(currentWeight / prob);
324  } else {
325  classification = fKill;
326  }
327  }
328  }
329  }
330  if (classification != fKill) {
331  MCTruthUtil::secondary(track, *mother, flag);
332  }
333  LogDebug("SimG4CoreApplication")
334  << "StackingAction:Classify Track " << aTrack->GetTrackID() << " Parent " << aTrack->GetParentID()
335  << " Type " << aTrack->GetDefinition()->GetParticleName() << " Ekin=" << ke / CLHEP::MeV
336  << " MeV from process subType=" << subType << " as " << classification << " Flag: " << flag;
337  }
338  }
339  }
340  }
341  if (nullptr != steppingVerbose) {
342  steppingVerbose->stackFilled(aTrack, (classification == fKill));
343  }
344  return classification;
345 }
346 
348 
350 
352  // prepare region vector
353  const unsigned int num = maxTimeNames.size();
354  maxTimeRegions.resize(num, nullptr);
355 
356  // Russian roulette
357  const std::vector<G4Region*>* rs = G4RegionStore::GetInstance();
358 
359  for (auto& reg : *rs) {
360  const G4String& rname = reg->GetName();
361  if ((gRusRoEcal < 1.0 || nRusRoEcal < 1.0) && rname == "EcalRegion") {
362  regionEcal = reg;
363  }
364  if ((gRusRoHcal < 1.0 || nRusRoHcal < 1.0) && rname == "HcalRegion") {
365  regionHcal = reg;
366  }
367  if ((gRusRoMuonIron < 1.0 || nRusRoMuonIron < 1.0) && rname == "MuonIron") {
368  regionMuonIron = reg;
369  }
370  if ((gRusRoPreShower < 1.0 || nRusRoPreShower < 1.0) && rname == "PreshowerRegion") {
371  regionPreShower = reg;
372  }
373  if ((gRusRoCastor < 1.0 || nRusRoCastor < 1.0) && rname == "CastorRegion") {
374  regionCastor = reg;
375  }
376  if ((gRusRoWorld < 1.0 || nRusRoWorld < 1.0) && rname == "DefaultRegionForTheWorld") {
377  regionWorld = reg;
378  }
379 
380  // time limits
381  for (unsigned int i = 0; i < num; ++i) {
382  if (rname == (G4String)(maxTimeNames[i])) {
383  maxTimeRegions[i] = reg;
384  break;
385  }
386  }
387  //
388  if (savePDandCinTracker &&
389  (rname == "BeamPipe" || rname == "BeamPipeVacuum" || rname == "TrackerPixelSensRegion" ||
390  rname == "TrackerPixelDeadRegion" || rname == "TrackerDeadRegion" || rname == "TrackerSensRegion" ||
391  rname == "FastTimerRegionBTL" || rname == "FastTimerRegionETL" || rname == "FastTimerRegionSensBTL" ||
392  rname == "FastTimerRegionSensETL")) {
393  trackerRegions.push_back(reg);
394  }
395  if (savePDandCinCalo && (rname == "HcalRegion" || rname == "EcalRegion" || rname == "PreshowerSensRegion" ||
396  rname == "PreshowerRegion" || rname == "APDRegion" || rname == "HGCalRegion")) {
397  caloRegions.push_back(reg);
398  }
399  if (savePDandCinMuon && (rname == "MuonChamber" || rname == "MuonSensitive_RPC" || rname == "MuonIron" ||
400  rname == "Muon" || rname == "MuonSensitive_DT-CSC")) {
401  muonRegions.push_back(reg);
402  }
403  if (rname == "BeamPipeOutside" || rname == "BeamPipeVacuum") {
404  lowdensRegions.push_back(reg);
405  }
406  for (auto& dead : deadRegionNames) {
407  if (rname == (G4String)(dead)) {
408  deadRegions.push_back(reg);
409  }
410  }
411  }
412 }
413 
414 bool StackingAction::isThisRegion(const G4Region* reg, std::vector<const G4Region*>& regions) const {
415  bool flag = false;
416  for (auto& region : regions) {
417  if (reg == region) {
418  flag = true;
419  break;
420  }
421  }
422  return flag;
423 }
424 
425 int StackingAction::isItPrimaryDecayProductOrConversion(const int stype, const G4Track& mother) const {
426  int flag = 0;
427  auto motherInfo = static_cast<const TrackInformation*>(mother.GetUserInformation());
428  // Check whether mother is a primary
429  if (motherInfo->isPrimary()) {
430  if (stype == fDecay) {
431  flag = 1;
432  } else if (stype == fGammaConversion) {
433  flag = 2;
434  }
435  }
436  return flag;
437 }
438 
439 bool StackingAction::rrApplicable(const G4Track* aTrack, const G4Track& mother) const {
440  auto motherInfo = static_cast<const TrackInformation*>(mother.GetUserInformation());
441 
442  // Check whether mother is gamma, e+, e-
443  const int genID = motherInfo->genParticlePID();
444  return (22 != genID && 11 != std::abs(genID));
445 }
446 
447 int StackingAction::isItFromPrimary(const G4Track& mother, int flagIn) const {
448  int flag = flagIn;
449  if (flag != 1) {
450  auto ptr = static_cast<const TrackInformation*>(mother.GetUserInformation());
451  if (ptr->isPrimary()) {
452  flag = 3;
453  }
454  }
455  return flag;
456 }
457 
458 bool StackingAction::isItOutOfTimeWindow(const G4Region* reg, const double& t) const {
459  double tofM = maxTrackTime;
460  for (unsigned int i = 0; i < numberTimes; ++i) {
461  if (reg == maxTimeRegions[i]) {
462  tofM = maxTrackTimes[i];
463  break;
464  }
465  }
466  return (t > tofM);
467 }
468 
469 void StackingAction::printRegions(const std::vector<const G4Region*>& reg, const std::string& word) const {
470  for (unsigned int i = 0; i < reg.size(); ++i) {
471  edm::LogVerbatim("SimG4CoreApplication")
472  << " StackingAction: " << word << "Region " << i << ". " << reg[i]->GetName();
473  }
474 }
double nRusRoPreShower
Log< level::Info, true > LogVerbatim
G4ClassificationOfNewTrack ClassifyNewTrack(const G4Track *aTrack) final
StackingAction(const TrackingAction *, const edm::ParameterSet &ps, const CMSSteppingVerbose *)
std::vector< const G4Region * > lowdensRegions
double maxZCentralCMS
void PrepareNewEvent() override
std::vector< double > maxTrackTimes
bool rrApplicable(const G4Track *, const G4Track &) const
static void secondary(G4Track *aSecondary, const G4Track &mother, int)
Definition: MCTruthUtil.cc:17
double gRusRoPreShower
double nRusRoEnerLim
const G4Region * regionCastor
const G4Region * regionMuonIron
const G4Track * geant4Track() const
int isItFromPrimary(const G4Track &, int) const
std::vector< const G4Region * > deadRegions
const CMSSteppingVerbose * steppingVerbose
uint64_t word
std::vector< const G4Region * > muonRegions
std::vector< std::string > maxTimeNames
void NewStage() override
const G4Region * regionEcal
unsigned int numberTimes
void printRegions(const std::vector< const G4Region *> &reg, const std::string &word) const
double nRusRoMuonIron
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
G4VSolid * worldSolid
bool isItOutOfTimeWindow(const G4Region *, const double &) const
void stackFilled(const G4Track *, bool isKilled) const
int genParticlePID() const
bool isThisRegion(const G4Region *, std::vector< const G4Region *> &) const
bool savePDandCinTracker
static void primary(G4Track *aPrimary)
Definition: MCTruthUtil.cc:7
std::vector< std::string > deadRegionNames
double gRusRoEnerLim
const G4Region * regionHcal
std::vector< const G4Region * > maxTimeRegions
double maxTrackTimeForward
const G4String rname[NREG]
const G4Region * regionPreShower
const TrackingAction * trackAction
Log< level::Warning, false > LogWarning
double gRusRoMuonIron
std::vector< const G4Region * > trackerRegions
int isItPrimaryDecayProductOrConversion(const int subtype, const G4Track &) const
#define LogDebug(id)
std::vector< const G4Region * > caloRegions
double limitEnergyForVacuum
const G4Region * regionWorld