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