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
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
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
00111 G4ClassificationOfNewTrack classification = fUrgent;
00112 int flag = 0;
00113
00114 NewTrackAction newTA;
00115 if (aTrack->GetCreatorProcess()==0 || aTrack->GetParentID()==0) {
00116
00117
00118
00119
00120
00121
00122
00123
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
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
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
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