CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/SimG4Core/Application/src/SteppingAction.cc

Go to the documentation of this file.
00001 #include "SimG4Core/Application/interface/SteppingAction.h"
00002 #include "SimG4Core/Application/interface/EventAction.h"
00003 
00004 #include "G4LogicalVolumeStore.hh"
00005 #include "G4ParticleTable.hh"
00006 #include "G4PhysicalVolumeStore.hh"
00007 #include "G4RegionStore.hh"
00008 #include "G4Track.hh"
00009 #include "G4UnitsTable.hh"
00010 
00011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00012 
00013 SteppingAction::SteppingAction(EventAction* e,const edm::ParameterSet & p) 
00014   : eventAction_(e), initialized(false), tracker(0), calo(0) {
00015 
00016   killBeamPipe = (p.getParameter<bool>("KillBeamPipe"));
00017   theCriticalEnergyForVacuum = (p.getParameter<double>("CriticalEnergyForVacuum")*MeV);
00018   theCriticalDensity = (p.getParameter<double>("CriticalDensity")*g/cm3);
00019   maxTrackTime  = (p.getParameter<double>("MaxTrackTime")*ns);
00020   maxTrackTimes = (p.getParameter<std::vector<double> >("MaxTrackTimes"));
00021   maxTimeNames  = (p.getParameter<std::vector<std::string> >("MaxTimeNames"));
00022   ekinMins      = (p.getParameter<std::vector<double> >("EkinThresholds"));
00023   ekinNames     = (p.getParameter<std::vector<std::string> >("EkinNames"));
00024   ekinParticles = (p.getParameter<std::vector<std::string> >("EkinParticles"));
00025   verbose       = (p.getUntrackedParameter<int>("Verbosity",0));
00026 
00027   edm::LogInfo("SimG4CoreApplication") << "SteppingAction:: KillBeamPipe = "
00028                                        << killBeamPipe << " CriticalDensity = "
00029                                        << theCriticalDensity << " g/cc;"
00030                                        << " CriticalEnergyForVacuum = "
00031                                        << theCriticalEnergyForVacuum << " Mev;"
00032                                        << " MaxTrackTime = " << maxTrackTime 
00033                                        << " ns";
00034   for (unsigned int i=0; i<maxTrackTimes.size(); i++) {
00035     maxTrackTimes[i] *= ns;
00036     edm::LogInfo("SimG4CoreApplication") << "SteppingAction::MaxTrackTime for "
00037                                          << maxTimeNames[i] << " is " 
00038                                          << maxTrackTimes[i];
00039   }
00040   edm::LogInfo("SimG4CoreApplication") << "SteppingAction::Kill following "
00041                                        << ekinParticles.size() 
00042                                        << " particles in " << ekinNames.size()
00043                                        << " volumes";
00044   for (unsigned int i=0; i<ekinParticles.size(); i++) {
00045     ekinMins[i] *= GeV;
00046     edm::LogInfo("SimG4CoreApplication") << "SteppingAction::Particle " << i
00047                                          << " " << ekinParticles[i]
00048                                          << " (Threshold = " << ekinMins[i]
00049                                          << " MeV)";
00050   }
00051   for (unsigned int i=0; i<ekinNames.size(); i++) 
00052     edm::LogInfo("SimG4CoreApplication") << "SteppingAction::Volume[" << i
00053                                          << "] = " << ekinNames[i];
00054 }
00055 
00056 SteppingAction::~SteppingAction() {}
00057 
00058 void SteppingAction::UserSteppingAction(const G4Step * aStep) {
00059   if (!initialized) initialized = initPointer();
00060   m_g4StepSignal(aStep);
00061 
00062   if (killBeamPipe) {
00063     catchLowEnergyInVacuumHere(aStep);
00064     catchLowEnergyInVacuumNext(aStep);
00065   }
00066 
00067   if (aStep->GetPostStepPoint()->GetPhysicalVolume() != 0) {
00068     bool ok = catchLongLived(aStep);
00069     if (ok) ok = catchLongLived(aStep);
00070 
00071     ok = (isThisVolume(aStep->GetPreStepPoint()->GetTouchable(),tracker)&&
00072           isThisVolume(aStep->GetPostStepPoint()->GetTouchable(),calo));
00073     if (ok) {
00074 
00075       math::XYZVectorD pos((aStep->GetPreStepPoint()->GetPosition()).x(),
00076                            (aStep->GetPreStepPoint()->GetPosition()).y(),
00077                            (aStep->GetPreStepPoint()->GetPosition()).z());
00078       
00079       math::XYZTLorentzVectorD mom((aStep->GetPreStepPoint()->GetMomentum()).x(),
00080                                    (aStep->GetPreStepPoint()->GetMomentum()).y(),
00081                                    (aStep->GetPreStepPoint()->GetMomentum()).z(),
00082                                    aStep->GetPreStepPoint()->GetTotalEnergy());
00083       
00084       uint32_t id = aStep->GetTrack()->GetTrackID();
00085       
00086       std::pair<math::XYZVectorD,math::XYZTLorentzVectorD> p(pos,mom);
00087       eventAction_->addTkCaloStateInfo(id,p);
00088     }
00089   }
00090 }
00091 
00092 void SteppingAction::catchLowEnergyInVacuumHere(const G4Step * aStep) {
00093   G4Track * theTrack = aStep->GetTrack();
00094   double theKenergy = theTrack->GetKineticEnergy();
00095   if (theTrack->GetVolume()!=0) {
00096     double density = theTrack->GetVolume()->GetLogicalVolume()->GetMaterial()->GetDensity();
00097     if (theKenergy <= theCriticalEnergyForVacuum && theKenergy > 0.0 &&
00098         density <= theCriticalDensity && theTrack->GetDefinition()->GetPDGCharge() != 0 &&
00099         theTrack->GetTrackStatus() != fStopAndKill) {
00100       if (verbose>1)
00101         edm::LogInfo("SimG4CoreApplication") 
00102           <<   " SteppingAction: LoopCatchSteppingAction:catchLowEnergyInVacuumHere: "
00103           << " Track from " << theTrack->GetDefinition()->GetParticleName()
00104           << " of kinetic energy " << theKenergy/MeV << " MeV "
00105           << " killed in " << theTrack->GetVolume()->GetLogicalVolume()->GetName()
00106           << " of density " << density/(g/cm3) << " g/cm3" ;
00107       theTrack->SetTrackStatus(fStopAndKill);
00108     }
00109   }
00110 }
00111 
00112 void SteppingAction::catchLowEnergyInVacuumNext(const G4Step * aStep) {
00113   G4Track * theTrack = aStep->GetTrack();
00114   double theKenergy = theTrack->GetKineticEnergy();
00115   if (theTrack->GetNextVolume()) {
00116     double density = theTrack->GetNextVolume()->GetLogicalVolume()->GetMaterial()->GetDensity();
00117     if (theKenergy <=  theCriticalEnergyForVacuum && theKenergy > 0.0 &&
00118         density <= theCriticalDensity && theTrack->GetDefinition()->GetPDGCharge() != 0 &&
00119         theTrack->GetTrackStatus() != fStopAndKill) {
00120       if (verbose>1)
00121         edm::LogInfo("SimG4CoreApplication") 
00122           << " SteppingAction: LoopCatchSteppingAction::catchLowEnergyInVacuumNext: "
00123           << " Track from " << theTrack->GetDefinition()->GetParticleName()
00124           << " of kinetic energy " << theKenergy/MeV << " MeV "
00125           << " stopped in " << theTrack->GetVolume()->GetLogicalVolume()->GetName()
00126           << " before going into "<< theTrack->GetNextVolume()->GetLogicalVolume()->GetName()
00127           << " of density " << density/(g/cm3) << " g/cm3" ;
00128       theTrack->SetTrackStatus(fStopButAlive);
00129     }
00130   }
00131 }
00132 
00133 bool SteppingAction::catchLongLived(const G4Step * aStep) {
00134 
00135   bool flag   = true;
00136   double time = (aStep->GetPostStepPoint()->GetGlobalTime())/nanosecond;
00137   double tofM = maxTrackTime;
00138   if (maxTimeRegions.size() > 0) {
00139     G4Region* reg = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetRegion();
00140     for (unsigned int i=0; i<maxTimeRegions.size(); i++) {
00141       if (reg == maxTimeRegions[i]) {
00142         tofM = maxTrackTimes[i];
00143         break;
00144       }
00145     }
00146   }
00147   if (time > tofM) {
00148     killTrack(aStep);
00149     flag = false;
00150   }
00151   return flag;
00152 }
00153 
00154 bool SteppingAction::killLowEnergy(const G4Step * aStep) {
00155 
00156   bool ok = true;
00157   if (ekinVolumes.size() > 0) {
00158     bool flag = false;
00159     G4LogicalVolume* lv = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume();
00160     for (unsigned int i=0; i<ekinVolumes.size(); i++) {
00161       if (lv == ekinVolumes[i]) {
00162         flag = true;
00163         break;
00164       }
00165     }
00166     if (flag) {
00167       G4Track * track = aStep->GetTrack();
00168       double    ekin  = track->GetKineticEnergy();
00169       double    ekinM = 0;
00170       int       pCode = track->GetDefinition()->GetPDGEncoding();
00171       for (unsigned int i=0; i<ekinPDG.size(); i++) {
00172         if (pCode == ekinPDG[i]) {
00173           ekinM = ekinMins[i];
00174           break;
00175         }
00176       }
00177       if (ekin > ekinM) {
00178         killTrack(aStep);
00179         ok = false;
00180       }
00181     }
00182   }
00183   return ok;
00184 }
00185   
00186 bool SteppingAction::initPointer() {
00187 
00188   bool flag = true;
00189   const G4PhysicalVolumeStore * pvs = G4PhysicalVolumeStore::GetInstance();
00190   if (pvs) {
00191     std::vector<G4VPhysicalVolume*>::const_iterator pvcite;
00192     for (pvcite = pvs->begin(); pvcite != pvs->end(); pvcite++) {
00193       if ((*pvcite)->GetName() == "Tracker") tracker = (*pvcite);
00194       if ((*pvcite)->GetName() == "CALO")    calo    = (*pvcite);
00195       if (tracker && calo) break;
00196     }
00197     edm::LogInfo("SimG4CoreApplication") << "Pointer for Tracker " << tracker
00198                                          << " and for Calo " << calo;
00199     if (tracker) LogDebug("SimG4CoreApplication") << "Tracker vol name "
00200                                                   << tracker->GetName();
00201     if (calo)    LogDebug("SimG4CoreApplication") << "Calorimeter vol name "
00202                                                   << calo->GetName();
00203   } else {
00204     flag = false;
00205   }
00206 
00207   const G4LogicalVolumeStore * lvs = G4LogicalVolumeStore::GetInstance();
00208   unsigned int num = ekinNames.size();
00209   if (num > 0) {
00210     if (lvs) {
00211       std::vector<G4LogicalVolume*>::const_iterator lvcite;
00212       for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
00213         for (unsigned int i=0; i<num; i++) {
00214           if ((*lvcite)->GetName() == (G4String)(ekinNames[i])) {
00215             ekinVolumes.push_back(*lvcite);
00216             break;
00217           }
00218         }
00219         if (ekinVolumes.size() == num) break;
00220       }
00221     }
00222     if (ekinVolumes.size() != num) flag = false;
00223     for (unsigned int i=0; i<ekinVolumes.size(); i++) {
00224       edm::LogInfo("SimG4CoreApplication") << ekinVolumes[i]->GetName()
00225                                            <<" with pointer " <<ekinVolumes[i];
00226     }
00227   }
00228 
00229   G4ParticleTable * theParticleTable = G4ParticleTable::GetParticleTable();
00230   G4String particleName;
00231   for (unsigned int i=0; i<ekinParticles.size(); i++) {
00232     int pdg = theParticleTable->FindParticle(particleName=ekinParticles[i])->GetPDGEncoding();
00233     ekinPDG.push_back(pdg);
00234     edm::LogInfo("SimG4CoreApplication") << "Particle " << ekinParticles[i]
00235                                          << " with code " << ekinPDG[i]
00236                                          << " and KE cut off " << ekinMins[i];
00237   }
00238   if (!flag) edm::LogInfo("SimG4CoreApplication") << "SteppingAction fails to"
00239                                                   << " initialize some the "
00240                                                   << "LV pointers correctly";
00241 
00242   const G4RegionStore * rs = G4RegionStore::GetInstance();
00243   num = maxTimeNames.size();
00244   if (num > 0) {
00245     std::vector<double> tofs;
00246     if (rs) {
00247       std::vector<G4Region*>::const_iterator rcite;
00248       for (rcite = rs->begin(); rcite != rs->end(); rcite++) {
00249         for (unsigned int i=0; i<num; i++) {
00250           if ((*rcite)->GetName() == (G4String)(maxTimeNames[i])) {
00251             maxTimeRegions.push_back(*rcite);
00252             tofs.push_back(maxTrackTimes[i]);
00253             break;
00254           }
00255         }
00256         if (tofs.size() == num) break;
00257       }
00258     }
00259     for (unsigned int i=0; i<tofs.size(); i++) {
00260       maxTrackTimes[i] = tofs[i];
00261       G4String name = "Unknown";
00262       if (maxTimeRegions[i]) name = maxTimeRegions[i]->GetName();
00263       edm::LogInfo("SimG4CoreApplication") << name << " with pointer " 
00264                                            << maxTimeRegions[i]<<" KE cut off "
00265                                            << maxTrackTimes[i];
00266     }
00267     if (tofs.size() != num) 
00268       edm::LogInfo("SimG4CoreApplication") << "SteppingAction fails to "
00269                                            << "initialize some the region "
00270                                            << "pointers correctly";
00271   }
00272   return true;
00273 }
00274 
00275 bool SteppingAction::isThisVolume(const G4VTouchable* touch, 
00276                                   G4VPhysicalVolume* pv) {
00277 
00278   int level = ((touch->GetHistoryDepth())+1);
00279   if (level > 0 && level >= 3) {
00280     unsigned int ii = (unsigned int)(level - 3);
00281     return (touch->GetVolume(ii) == pv);
00282   }
00283   return false;
00284 }
00285 
00286 void SteppingAction::killTrack(const G4Step * aStep) {
00287   
00288   aStep->GetTrack()->SetTrackStatus(fStopAndKill);
00289   G4TrackVector tv = *(aStep->GetSecondary());
00290   for (unsigned int kk=0; kk<tv.size(); kk++) {
00291     if (tv[kk]->GetVolume() == aStep->GetPreStepPoint()->GetPhysicalVolume())
00292       tv[kk]->SetTrackStatus(fStopAndKill);
00293   }
00294   LogDebug("SimG4CoreApplication") << "SteppingAction: Kills track " 
00295                                    << aStep->GetTrack()->GetTrackID() << " ("
00296                                    << aStep->GetTrack()->GetDefinition()->GetParticleName()
00297                                    << ") at " << aStep->GetPostStepPoint()->GetGlobalTime()/nanosecond 
00298                                    << " ns in " << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetName()
00299                                    << " from region " << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetRegion()->GetName();
00300 }