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