CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/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 
00014 #include<algorithm>
00015 
00016 //#define DebugLog
00017 
00018 StackingAction::StackingAction(const edm::ParameterSet & p) {
00019 
00020   trackNeutrino  = p.getParameter<bool>("TrackNeutrino");
00021   killHeavy      = p.getParameter<bool>("KillHeavy");
00022   kmaxIon        = p.getParameter<double>("IonThreshold")*MeV;
00023   kmaxProton     = p.getParameter<double>("ProtonThreshold")*MeV;
00024   kmaxNeutron    = p.getParameter<double>("NeutronThreshold")*MeV;
00025   killDeltaRay   = p.getParameter<bool>("KillDeltaRay");
00026   maxTrackTime   = p.getParameter<double>("MaxTrackTime")*ns;
00027   maxTrackTimes  = p.getParameter<std::vector<double> >("MaxTrackTimes");
00028   maxTimeNames   = p.getParameter<std::vector<std::string> >("MaxTimeNames");
00029   savePDandCinTracker = p.getUntrackedParameter<bool>("SavePrimaryDecayProductsAndConversionsInTracker",false);
00030   savePDandCinCalo    = p.getUntrackedParameter<bool>("SavePrimaryDecayProductsAndConversionsInCalo",false);
00031   savePDandCinMuon    = p.getUntrackedParameter<bool>("SavePrimaryDecayProductsAndConversionsInMuon",false);
00032   saveFirstSecondary  = p.getUntrackedParameter<bool>("SaveFirstLevelSecondary",false);
00033 
00034   edm::LogInfo("SimG4CoreApplication") << "StackingAction initiated with"
00035                                        << " flag for saving decay products in "
00036                                        << " Tracker: " << savePDandCinTracker
00037                                        << " in Calo: " << savePDandCinCalo
00038                                        << " in Muon: " << savePDandCinMuon
00039                                        << "\n               saveFirstSecondary"
00040                                        << ": " << saveFirstSecondary
00041                                        << " Flag for tracking neutrino: "
00042                                        << trackNeutrino << " Killing Flag "
00043                                        << killHeavy << " protons below " 
00044                                        << kmaxProton <<" MeV, neutrons below "
00045                                        << kmaxNeutron << " MeV and ions"
00046                                        << " below " << kmaxIon << " MeV\n"
00047                                        << "               kill tracks with "
00048                                        << "time larger than " << maxTrackTime
00049                                        << " ns and kill Delta Ray flag set to "
00050                                        << killDeltaRay;
00051   for (unsigned int i=0; i<maxTrackTimes.size(); i++) {
00052     maxTrackTimes[i] *= ns;
00053     edm::LogInfo("SimG4CoreApplication") << "StackingAction::MaxTrackTime for "
00054                                          << maxTimeNames[i] << " is " 
00055                                          << maxTrackTimes[i];
00056   }
00057   initPointer();
00058 }
00059 
00060 StackingAction::~StackingAction() {}
00061 
00062 G4ClassificationOfNewTrack StackingAction::ClassifyNewTrack(const G4Track * aTrack) {
00063 
00064   // G4 interface part
00065   G4ClassificationOfNewTrack classification = fUrgent;
00066   int flag = 0;
00067 
00068   NewTrackAction newTA;
00069   if (aTrack->GetCreatorProcess()==0 || aTrack->GetParentID()==0) {
00070     newTA.primary(aTrack);
00071   } else if (aTrack->GetTouchable() == 0) {
00072     edm::LogError("SimG4CoreApplication")
00073       << "StackingAction: no touchable for track " << aTrack->GetTrackID()
00074       << " from " << aTrack->GetParentID()
00075       << " with PDG code " << aTrack->GetDefinition()->GetParticleName();
00076     classification = fKill;
00077   } else {
00078     const G4Track * mother = CurrentG4Track::track();
00079     if ((savePDandCinTracker && isThisVolume(aTrack->GetTouchable(),tracker))||
00080         (savePDandCinCalo && isThisVolume(aTrack->GetTouchable(),calo)) ||
00081         (savePDandCinMuon && isThisVolume(aTrack->GetTouchable(),muon)))
00082       flag = isItPrimaryDecayProductOrConversion(aTrack, *mother);
00083     if (saveFirstSecondary) flag = isItFromPrimary(*mother, flag);
00084     newTA.secondary(aTrack, *mother, flag);
00085 
00086     if (aTrack->GetTrackStatus() == fStopAndKill) classification = fKill;
00087     if (killHeavy) {
00088       int    pdg = aTrack->GetDefinition()->GetPDGEncoding();
00089       double ke  = aTrack->GetKineticEnergy()/MeV;
00090       if (((pdg/1000000000 == 1) && (((pdg/10000)%100) > 0) && 
00091            (((pdg/10)%100) > 0) && (ke<kmaxIon)) || 
00092           ((pdg == 2212) && (ke < kmaxProton)) ||
00093           ((pdg == 2112) && (ke < kmaxNeutron))) classification = fKill;
00094     }
00095     if (!trackNeutrino) {
00096       int    pdg = std::abs(aTrack->GetDefinition()->GetPDGEncoding());
00097       if (pdg == 12 || pdg == 14 || pdg == 16 || pdg == 18) 
00098         classification = fKill;
00099     }
00100     if (isItLongLived(aTrack)) classification = fKill;
00101     if (killDeltaRay) {
00102       if (aTrack->GetCreatorProcess()->GetProcessType() == fElectromagnetic &&
00103           aTrack->GetCreatorProcess()->GetProcessSubType() == fIonisation)
00104         classification = fKill;
00105     }
00106 #ifdef DebugLog
00107     LogDebug("SimG4CoreApplication") << "StackingAction:Classify Track "
00108                                      << aTrack->GetTrackID() << " Parent " 
00109                                      << aTrack->GetParentID() << " Type "
00110                                      << aTrack->GetDefinition()->GetParticleName() 
00111                                      << " K.E. " << aTrack->GetKineticEnergy()/MeV
00112                                      << " MeV from process/subprocess " 
00113                                      << aTrack->GetCreatorProcess()->GetProcessType() << "|"
00114                                      << aTrack->GetCreatorProcess()->GetProcessSubType()
00115                                      << " as " << classification << " Flag " << flag;
00116 #endif
00117   }
00118   return classification;
00119 }
00120 
00121 void StackingAction::NewStage() {}
00122 
00123 void StackingAction::PrepareNewEvent() {}
00124 
00125 void StackingAction::initPointer() {
00126 
00127   const G4LogicalVolumeStore * lvs = G4LogicalVolumeStore::GetInstance();
00128   if (lvs) {
00129     std::vector<G4LogicalVolume*>::const_iterator lvcite;
00130     for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
00131       if (savePDandCinTracker) {
00132         if (strcmp("Tracker",(*lvcite)->GetName().c_str()) == 0) tracker.push_back(*lvcite);
00133         if (strcmp("BEAM",(*lvcite)->GetName().substr(0,4).c_str()) == 0) tracker.push_back(*lvcite);
00134       }
00135       if (savePDandCinCalo) {
00136         if (strcmp("CALO",(*lvcite)->GetName().c_str()) == 0) calo.push_back(*lvcite);
00137         if (strcmp("VCAL",(*lvcite)->GetName().c_str()) == 0) calo.push_back(*lvcite);
00138       }
00139       if (savePDandCinMuon) {
00140         if (strcmp("MUON",(*lvcite)->GetName().c_str()) == 0) muon.push_back(*lvcite);
00141       }
00142     }
00143     edm::LogInfo("SimG4CoreApplication") << "# of LV for Tracker " 
00144                                          << tracker.size() << " for Calo "
00145                                          << calo.size() << " for Muon "
00146                                          << muon.size();
00147     for (unsigned int i=0; i<tracker.size(); ++i)
00148       edm::LogInfo("SimG4CoreApplication") << "Tracker vol " << i << " name "
00149                                            << tracker[i]->GetName();
00150     for (unsigned int i=0; i<calo.size(); ++i)
00151       edm::LogInfo("SimG4CoreApplication") << "Calorimeter vol " <<i <<" name "
00152                                            << calo[i]->GetName();
00153     for (unsigned int i=0; i<muon.size(); ++i)
00154       edm::LogInfo("SimG4CoreApplication") << "Muon vol " << i << " name "
00155                                            << muon[i]->GetName();
00156   }
00157 
00158   const G4RegionStore * rs = G4RegionStore::GetInstance();
00159   unsigned int num = maxTimeNames.size();
00160   if (num > 0) {
00161     std::vector<double> tofs;
00162     if (rs) {
00163       std::vector<G4Region*>::const_iterator rcite;
00164       for (rcite = rs->begin(); rcite != rs->end(); rcite++) {
00165         for (unsigned int i=0; i<num; i++) {
00166           if ((*rcite)->GetName() == (G4String)(maxTimeNames[i])) {
00167             maxTimeRegions.push_back(*rcite);
00168             tofs.push_back(maxTrackTimes[i]);
00169             break;
00170           }
00171         }
00172         if (tofs.size() == num) break;
00173       }
00174     }
00175     for (unsigned int i=0; i<tofs.size(); i++) {
00176       maxTrackTimes[i] = tofs[i];
00177       G4String name = "Unknown";
00178       if (maxTimeRegions[i]) name = maxTimeRegions[i]->GetName();
00179       edm::LogInfo("SimG4CoreApplication") << name << " with pointer " 
00180                                            << maxTimeRegions[i]<<" KE cut off "
00181                                            << maxTrackTimes[i];
00182     }
00183   }
00184 
00185 }
00186 
00187 bool StackingAction::isThisVolume(const G4VTouchable* touch, 
00188                                   std::vector<G4LogicalVolume*> & lvs) const {
00189 
00190   bool flag = false;
00191   if (lvs.size() > 0 && touch !=0) {
00192     int level = ((touch->GetHistoryDepth())+1);
00193     if (level >= 3) {
00194       unsigned int  ii = (unsigned int)(level - 3);
00195       flag    = (std::count(lvs.begin(),lvs.end(),(touch->GetVolume(ii)->GetLogicalVolume())) != 0);
00196     }
00197   }
00198   return flag;
00199 }
00200 
00201 int StackingAction::isItPrimaryDecayProductOrConversion(const G4Track * aTrack,
00202                                                         const G4Track & mother) const {
00203 
00204   int flag = 0;
00205   TrackInformationExtractor extractor;
00206   const TrackInformation & motherInfo(extractor(mother));
00207   // Check whether mother is a primary
00208   if (motherInfo.isPrimary()) {
00209     if (aTrack->GetCreatorProcess()->GetProcessType() == fDecay) flag = 1;
00210     else if (aTrack->GetCreatorProcess()->GetProcessType() == fElectromagnetic &&
00211              aTrack->GetCreatorProcess()->GetProcessSubType() == fGammaConversion) flag = 2;
00212   }
00213   return flag;
00214 }
00215 
00216 int StackingAction::isItFromPrimary(const G4Track & mother, int flagIn) const {
00217 
00218   int flag = flagIn;
00219   if (flag != 1) {
00220     TrackInformationExtractor extractor;
00221     const TrackInformation & motherInfo(extractor(mother));
00222     if (motherInfo.isPrimary()) flag = 3;
00223   }
00224   return flag;
00225 }
00226 
00227 bool StackingAction::isItLongLived(const G4Track * aTrack) const {
00228 
00229   bool   flag = false;
00230   double time = (aTrack->GetGlobalTime())/nanosecond;
00231   double tofM = maxTrackTime;
00232   if (maxTimeRegions.size() > 0) {
00233     G4Region* reg = aTrack->GetTouchable()->GetVolume(0)->GetLogicalVolume()->GetRegion();
00234     for (unsigned int i=0; i<maxTimeRegions.size(); i++) {
00235       if (reg == maxTimeRegions[i]) {
00236         tofM = maxTrackTimes[i];
00237         break;
00238       }
00239     }
00240   }
00241   if (time > tofM) flag = true;
00242   return flag;
00243 }