CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/SimG4Core/Application/src/StackingAction.cc

Go to the documentation of this file.
00001 #include "SimG4Core/Application/interface/StackingAction.h"
00002 #include "SimG4Core/Notification/interface/CurrentG4Track.h"
00003 #include "SimG4Core/Notification/interface/NewTrackAction.h"
00004 #include "SimG4Core/Notification/interface/TrackInformation.h"
00005 #include "SimG4Core/Notification/interface/TrackInformationExtractor.h"
00006 
00007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00008 
00009 #include "G4VProcess.hh"
00010 #include "G4EmProcessSubType.hh"
00011 #include "G4LogicalVolumeStore.hh"
00012 #include "G4RegionStore.hh"
00013 #include "Randomize.hh"
00014 
00015 #include<algorithm>
00016 
00017 //#define DebugLog
00018 
00019 StackingAction::StackingAction(const edm::ParameterSet & p) {
00020 
00021   trackNeutrino  = p.getParameter<bool>("TrackNeutrino");
00022   killHeavy      = p.getParameter<bool>("KillHeavy");
00023   kmaxIon        = p.getParameter<double>("IonThreshold")*MeV;
00024   kmaxProton     = p.getParameter<double>("ProtonThreshold")*MeV;
00025   kmaxNeutron    = p.getParameter<double>("NeutronThreshold")*MeV;
00026   killDeltaRay   = p.getParameter<bool>("KillDeltaRay");
00027   maxTrackTime   = p.getParameter<double>("MaxTrackTime")*ns;
00028   maxTrackTimes  = p.getParameter<std::vector<double> >("MaxTrackTimes");
00029   for(unsigned int i=0; i<maxTrackTimes.size(); ++i) { maxTrackTimes[i] *= ns; }
00030   maxTimeNames   = p.getParameter<std::vector<std::string> >("MaxTimeNames");
00031   savePDandCinTracker = p.getUntrackedParameter<bool>("SavePrimaryDecayProductsAndConversionsInTracker",false);
00032   savePDandCinCalo    = p.getUntrackedParameter<bool>("SavePrimaryDecayProductsAndConversionsInCalo",false);
00033   savePDandCinMuon    = p.getUntrackedParameter<bool>("SavePrimaryDecayProductsAndConversionsInMuon",false);
00034   saveFirstSecondary  = p.getUntrackedParameter<bool>("SaveFirstLevelSecondary",false);
00035   killInCalo = false;
00036   killInCaloEfH = false;
00037 
00038   // Russian Roulette
00039   nRusRoEcal = p.getParameter<double>("RusRoEcalNeutron");
00040   nRusRoHcal = p.getParameter<double>("RusRoHcalNeutron");
00041   nRusRoEcalLim = p.getParameter<double>("RusRoEcalNeutronLimit")*MeV;
00042   nRusRoHcalLim = p.getParameter<double>("RusRoHcalNeutronLimit")*MeV;
00043   pRusRoEcal = p.getParameter<double>("RusRoEcalProton");
00044   pRusRoHcal = p.getParameter<double>("RusRoHcalProton");
00045   pRusRoEcalLim = p.getParameter<double>("RusRoEcalProtonLimit")*MeV;
00046   pRusRoHcalLim = p.getParameter<double>("RusRoHcalProtonLimit")*MeV;
00047   regionEcal = 0;
00048   regionHcal = 0;
00049 
00050   if ( p.exists("TestKillingOptions") ) {
00051 
00052     killInCalo = (p.getParameter<edm::ParameterSet>("TestKillingOptions")).getParameter<bool>("KillInCalo");
00053     killInCaloEfH = (p.getParameter<edm::ParameterSet>("TestKillingOptions")).getParameter<bool>("KillInCaloEfH");
00054     edm::LogWarning("SimG4CoreApplication") << " *** Activating special test killing options in StackingAction \n"
00055                                             << " *** Kill secondaries in Calorimetetrs volume = " << killInCalo << "\n"
00056                                             << " *** Kill electromagnetic secondaries from hadrons in Calorimeters volume = " << killInCaloEfH;
00057 
00058   }
00059 
00060   edm::LogInfo("SimG4CoreApplication") << "StackingAction initiated with"
00061                                        << " flag for saving decay products in "
00062                                        << " Tracker: " << savePDandCinTracker
00063                                        << " in Calo: " << savePDandCinCalo
00064                                        << " in Muon: " << savePDandCinMuon
00065                                        << "\n               saveFirstSecondary"
00066                                        << ": " << saveFirstSecondary
00067                                        << " Flag for tracking neutrino: "
00068                                        << trackNeutrino << " Killing Flag "
00069                                        << killHeavy << " protons below " 
00070                                        << kmaxProton <<" MeV, neutrons below "
00071                                        << kmaxNeutron << " MeV and ions"
00072                                        << " below " << kmaxIon << " MeV\n"
00073                                        << "               kill tracks with "
00074                                        << "time larger than " << maxTrackTime
00075                                        << " ns and kill Delta Ray flag set to "
00076                                        << killDeltaRay;
00077   for (unsigned int i=0; i<maxTrackTimes.size(); i++) {
00078     maxTrackTimes[i] *= ns;
00079     edm::LogInfo("SimG4CoreApplication") << "StackingAction::MaxTrackTime for "
00080                                          << maxTimeNames[i] << " is " 
00081                                          << maxTrackTimes[i];
00082   }
00083   if(nRusRoEcal < 1.0 || nRusRoHcal < 1.0) {
00084     edm::LogInfo("SimG4CoreApplication") << "StackingAction: "
00085                                          << "Russian Roulette for neutron in ECAL Prob= " 
00086                                          << nRusRoEcal << "  Elimit(MeV)= "
00087                                          << nRusRoEcalLim << "\n"
00088                                          << "                "
00089                                          << "Russian Roulette for neutron in HCAL Prob= " 
00090                                          << nRusRoHcal << "  Elimit(MeV)= "
00091                                          << nRusRoHcalLim;
00092   }
00093   if(pRusRoEcal < 1.0 || pRusRoHcal < 1.0) {
00094     edm::LogInfo("SimG4CoreApplication") << "StackingAction: "
00095                                          << "Russian Roulette for proton in ECAL Prob= " 
00096                                          << pRusRoEcal << "  Elimit(MeV)= "
00097                                          << pRusRoEcalLim << "\n"
00098                                          << "                "
00099                                          << "Russian Roulette for proton in HCAL Prob= " 
00100                                          << pRusRoHcal << "  Elimit(MeV)= "
00101                                          << pRusRoHcalLim;
00102   }
00103   initPointer();
00104 }
00105 
00106 StackingAction::~StackingAction() {}
00107 
00108 G4ClassificationOfNewTrack StackingAction::ClassifyNewTrack(const G4Track * aTrack) {
00109 
00110   // G4 interface part
00111   G4ClassificationOfNewTrack classification = fUrgent;
00112   int flag = 0;
00113 
00114   NewTrackAction newTA;
00115   if (aTrack->GetCreatorProcess()==0 || aTrack->GetParentID()==0) {
00116     /*
00117     std::cout << "StackingAction: primary weight= " 
00118               << aTrack->GetWeight() << " "
00119               << aTrack->GetDefinition()->GetParticleName()
00120               << " " << aTrack->GetKineticEnergy()
00121               << " Id=" << aTrack->GetTrackID()
00122               << "  trackInfo " << aTrack->GetUserInformation() 
00123               << std::endl;
00124     */
00125     newTA.primary(aTrack);
00126     if (!trackNeutrino) {
00127       int pdg = std::abs(aTrack->GetDefinition()->GetPDGEncoding());
00128       if (pdg == 12 || pdg == 14 || pdg == 16 || pdg == 18) {
00129         classification = fKill;
00130       }
00131     }
00132   } else if (aTrack->GetTouchable() == 0) {
00133     edm::LogError("SimG4CoreApplication")
00134       << "StackingAction: no touchable for track " << aTrack->GetTrackID()
00135       << " from " << aTrack->GetParentID()
00136       << " with PDG code " << aTrack->GetDefinition()->GetParticleName();
00137     classification = fKill;
00138   } else {
00139     const G4Track * mother = CurrentG4Track::track();
00140     if ((savePDandCinTracker && isThisVolume(aTrack->GetTouchable(),tracker))||
00141         (savePDandCinCalo && isThisVolume(aTrack->GetTouchable(),calo)) ||
00142         (savePDandCinMuon && isThisVolume(aTrack->GetTouchable(),muon)))
00143       flag = isItPrimaryDecayProductOrConversion(aTrack, *mother);
00144     if (saveFirstSecondary) flag = isItFromPrimary(*mother, flag);
00145     newTA.secondary(aTrack, *mother, flag);
00146 
00147     if (aTrack->GetTrackStatus() == fStopAndKill) classification = fKill;
00148     if (killHeavy && classification != fKill) {
00149       int    pdg = aTrack->GetDefinition()->GetPDGEncoding();
00150       double ke  = aTrack->GetKineticEnergy()/MeV;
00151       if (((pdg/1000000000 == 1) && (((pdg/10000)%100) > 0) && 
00152            (((pdg/10)%100) > 0) && (ke<kmaxIon)) || 
00153           ((pdg == 2212) && (ke < kmaxProton)) ||
00154           ((pdg == 2112) && (ke < kmaxNeutron))) classification = fKill;
00155     }
00156     if (!trackNeutrino  && classification != fKill) {
00157       int    pdg = std::abs(aTrack->GetDefinition()->GetPDGEncoding());
00158       if (pdg == 12 || pdg == 14 || pdg == 16 || pdg == 18) 
00159         classification = fKill;
00160     }
00161     if (isItLongLived(aTrack)) classification = fKill;
00162     if (killDeltaRay) {
00163       if (aTrack->GetCreatorProcess()->GetProcessType() == fElectromagnetic &&
00164           aTrack->GetCreatorProcess()->GetProcessSubType() == fIonisation)
00165         classification = fKill;
00166     }
00167     if (killInCalo && classification != fKill) {
00168       if ( isThisVolume(aTrack->GetTouchable(),calo)) { 
00169         classification = fKill; 
00170       }
00171     }
00172     if (killInCaloEfH && classification != fKill) {
00173       int    pdg = aTrack->GetDefinition()->GetPDGEncoding();
00174       int    pdgMother = mother->GetDefinition()->GetPDGEncoding();
00175       if ( (pdg == 22 || std::abs(pdg) == 11) && 
00176            (std::abs(pdgMother) < 11 || std::abs(pdgMother) > 17) && 
00177            pdgMother != 22  ) {
00178         if ( isThisVolume(aTrack->GetTouchable(),calo)) { 
00179           classification = fKill; 
00180         }
00181       }
00182     }
00183     double currentWeight = aTrack->GetWeight();
00184     if((regionEcal || regionHcal) && classification != fKill
00185        && 1.0 >= currentWeight) {
00186       int    pdg = aTrack->GetDefinition()->GetPDGEncoding();
00187       if(2112 == pdg || 2212 == pdg) {
00188         G4Region* reg = aTrack->GetVolume()->GetLogicalVolume()->GetRegion();
00189         double prob = 1.0;
00190         double elim = 0.0;
00191         if(reg == regionEcal) {
00192           if(2112 == pdg) {
00193             prob = nRusRoEcal;
00194             elim = nRusRoEcalLim;
00195           } else {
00196             prob = pRusRoEcal;
00197             elim = pRusRoEcalLim;
00198           }
00199         } else if(reg == regionHcal) {
00200           if(2112 == pdg) {
00201             prob = nRusRoHcal;
00202             elim = nRusRoHcalLim;
00203           } else {
00204             prob = pRusRoHcal;
00205             elim = pRusRoHcalLim;
00206           }
00207         }
00208         if(prob < 1.0 && aTrack->GetKineticEnergy() < elim) {
00209           if(G4UniformRand() < prob) {
00210             const_cast<G4Track*>(aTrack)->SetWeight(currentWeight/prob);
00211           } else {
00212             classification = fKill;
00213           }
00214         }
00215       }  
00216     }
00217   /*
00218   double wt2 = aTrack->GetWeight();
00219   if(wt2 != 1.0) { 
00220     G4Region* reg = aTrack->GetVolume()->GetLogicalVolume()->GetRegion();
00221     std::cout << "StackingAction: weight= " << wt2 << " "
00222               << aTrack->GetDefinition()->GetParticleName()
00223               << " " << aTrack->GetKineticEnergy()
00224               << " Id=" << aTrack->GetTrackID()
00225               << " IdP=" << aTrack->GetParentID();
00226     const G4VProcess* pr = aTrack->GetCreatorProcess();
00227     if(pr) std::cout << " from  " << pr->GetProcessName();
00228     if(reg) std::cout << " in  " << reg->GetName()
00229                       << "  trackInfo " << aTrack->GetUserInformation(); 
00230     std::cout << std::endl;
00231   }
00232   */
00233 #ifdef DebugLog
00234     LogDebug("SimG4CoreApplication") << "StackingAction:Classify Track "
00235                                      << aTrack->GetTrackID() << " Parent " 
00236                                      << aTrack->GetParentID() << " Type "
00237                                      << aTrack->GetDefinition()->GetParticleName() 
00238                                      << " K.E. " << aTrack->GetKineticEnergy()/MeV
00239                                      << " MeV from process/subprocess " 
00240                                      << aTrack->GetCreatorProcess()->GetProcessType() << "|"
00241                                      << aTrack->GetCreatorProcess()->GetProcessSubType()
00242                                      << " as " << classification << " Flag " << flag;
00243 #endif
00244   }
00245   return classification;
00246 }
00247 
00248 void StackingAction::NewStage() {}
00249 
00250 void StackingAction::PrepareNewEvent() {}
00251 
00252 void StackingAction::initPointer() {
00253 
00254   const G4LogicalVolumeStore * lvs = G4LogicalVolumeStore::GetInstance();
00255   if (lvs) {
00256     std::vector<G4LogicalVolume*>::const_iterator lvcite;
00257     for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
00258       if (savePDandCinTracker) {
00259         if (strcmp("Tracker",(*lvcite)->GetName().c_str()) == 0) tracker.push_back(*lvcite);
00260         if (strcmp("BEAM",(*lvcite)->GetName().substr(0,4).c_str()) == 0) tracker.push_back(*lvcite);
00261       }
00262       if (savePDandCinCalo || killInCalo || killInCaloEfH ) {
00263         if (strcmp("CALO",(*lvcite)->GetName().c_str()) == 0) calo.push_back(*lvcite);
00264         if (strcmp("VCAL",(*lvcite)->GetName().c_str()) == 0) calo.push_back(*lvcite);
00265       }
00266       if (savePDandCinMuon) {
00267         if (strcmp("MUON",(*lvcite)->GetName().c_str()) == 0) muon.push_back(*lvcite);
00268       }
00269     }
00270     edm::LogInfo("SimG4CoreApplication") << "# of LV for Tracker " 
00271                                          << tracker.size() << " for Calo "
00272                                          << calo.size() << " for Muon "
00273                                          << muon.size();
00274     for (unsigned int i=0; i<tracker.size(); ++i)
00275       edm::LogInfo("SimG4CoreApplication") << "Tracker vol " << i << " name "
00276                                            << tracker[i]->GetName();
00277     for (unsigned int i=0; i<calo.size(); ++i)
00278       edm::LogInfo("SimG4CoreApplication") << "Calorimeter vol " <<i <<" name "
00279                                            << calo[i]->GetName();
00280     for (unsigned int i=0; i<muon.size(); ++i)
00281       edm::LogInfo("SimG4CoreApplication") << "Muon vol " << i << " name "
00282                                            << muon[i]->GetName();
00283   }
00284 
00285   const G4RegionStore * rs = G4RegionStore::GetInstance();
00286   unsigned int num = maxTimeNames.size();
00287   if (num > 0) {
00288     std::vector<double> tofs;
00289     if (rs) {
00290       std::vector<G4Region*>::const_iterator rcite;
00291       for (rcite = rs->begin(); rcite != rs->end(); rcite++) {
00292         if ((nRusRoEcal < 1.0 || pRusRoEcal < 1.0) && 
00293             (*rcite)->GetName() == "EcalRegion") {  regionEcal = (*rcite); }
00294         if ((nRusRoHcal < 1.0 || pRusRoHcal < 1.0) && 
00295             (*rcite)->GetName() == "HcalRegion") {  regionHcal = (*rcite); }
00296         for (unsigned int i=0; i<num; i++) {
00297           if ((*rcite)->GetName() == (G4String)(maxTimeNames[i])) {
00298             maxTimeRegions.push_back(*rcite);
00299             tofs.push_back(maxTrackTimes[i]);
00300             break;
00301           }
00302         }
00303         if (tofs.size() == num) break;
00304       }
00305     }
00306     for (unsigned int i=0; i<tofs.size(); i++) {
00307       maxTrackTimes[i] = tofs[i];
00308       G4String name = "Unknown";
00309       if (maxTimeRegions[i]) name = maxTimeRegions[i]->GetName();
00310       edm::LogInfo("SimG4CoreApplication") << name << " with pointer " 
00311                                            << maxTimeRegions[i]<<" KE cut off "
00312                                            << maxTrackTimes[i];
00313     }
00314   }
00315 }
00316 
00317 bool StackingAction::isThisVolume(const G4VTouchable* touch, 
00318                                   std::vector<G4LogicalVolume*> & lvs) const {
00319 
00320   bool flag = false;
00321   if (lvs.size() > 0 && touch !=0) {
00322     int level = ((touch->GetHistoryDepth())+1);
00323     if (level >= 3) {
00324       unsigned int  ii = (unsigned int)(level - 3);
00325       flag    = (std::count(lvs.begin(),lvs.end(),(touch->GetVolume(ii)->GetLogicalVolume())) != 0);
00326     }
00327   }
00328   return flag;
00329 }
00330 
00331 int StackingAction::isItPrimaryDecayProductOrConversion(const G4Track * aTrack,
00332                                                         const G4Track & mother) const {
00333 
00334   int flag = 0;
00335   TrackInformationExtractor extractor;
00336   const TrackInformation & motherInfo(extractor(mother));
00337   // Check whether mother is a primary
00338   if (motherInfo.isPrimary()) {
00339     if (aTrack->GetCreatorProcess()->GetProcessType() == fDecay) flag = 1;
00340     else if (aTrack->GetCreatorProcess()->GetProcessType() == fElectromagnetic &&
00341              aTrack->GetCreatorProcess()->GetProcessSubType() == fGammaConversion) flag = 2;
00342   }
00343   return flag;
00344 }
00345 
00346 int StackingAction::isItFromPrimary(const G4Track & mother, int flagIn) const {
00347 
00348   int flag = flagIn;
00349   if (flag != 1) {
00350     TrackInformationExtractor extractor;
00351     const TrackInformation & motherInfo(extractor(mother));
00352     if (motherInfo.isPrimary()) flag = 3;
00353   }
00354   return flag;
00355 }
00356 
00357 bool StackingAction::isItLongLived(const G4Track * aTrack) const {
00358 
00359   bool   flag = false;
00360   double time = (aTrack->GetGlobalTime())/nanosecond;
00361   double tofM = maxTrackTime;
00362   if (maxTimeRegions.size() > 0) {
00363     G4Region* reg = aTrack->GetTouchable()->GetVolume(0)->GetLogicalVolume()->GetRegion();
00364     for (unsigned int i=0; i<maxTimeRegions.size(); i++) {
00365       if (reg == maxTimeRegions[i]) {
00366         tofM = maxTrackTimes[i];
00367         break;
00368       }
00369     }
00370   }
00371   if (time > tofM) flag = true;
00372   return flag;
00373 }
00374 
00375