| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

HistorianStepAction.cc

Go to the documentation of this file.
00001 #include "HistorianStepAction.h"
00002 #include "G4ToHistoryUtensils.h"
00003 #include "G4HistoryUserTrackInfo.h"
00004 #include "HistorianCustomRules.h"
00005 
00006 #include "Event/SimProcess.h"
00007 #include "Event/SimVertex.h"
00008 #include "Event/SimTrack.h"
00009 #include "Event/SimParticleHistory.h"
00010 
00011 #include "G4TouchableHistory.hh"
00012 #include "G4TouchableHandle.hh"
00013 #include "G4Step.hh"
00014 #include "G4StepPoint.hh"
00015 #include "G4SteppingManager.hh"
00016 #include "G4MaterialPropertiesTable.hh"
00017 
00018 #include "RuleParser/Rules.h"
00019 #include "RuleParser/CreateRules.h"
00020 #include "RuleParser/PrescaleRule.h"
00021 
00022 #include "G4DataHelpers/G4DhPrimaryParticleInformation.h"
00023 #include "G4DataHelpers/ITouchableToDetectorElement.h"
00024 #include "G4DataHelpers/IHistoryKeeper.h"
00025 
00026 #include "GaudiKernel/DataObject.h"
00027 #include "GaudiKernel/DeclareFactoryEntries.h"
00028 
00029 #include <vector>
00030 
00031 
00032 DECLARE_TOOL_FACTORY(HistorianStepAction);
00033 
00034 using namespace DayaBay;
00035 
00036 HistorianStepAction::HistorianStepAction ( 
00037   const std::string& type   , 
00038   const std::string& name   , 
00039   const IInterface*  parent ) 
00040   : QueriableStepAction( type, name, parent )
00041   , mHistoryKeeper(0)
00042   , mTrackRule(0)
00043   , mVertexRule(0)
00044 { 
00045   declareProperty("TrackSelection",m_TrackSelection = "none");
00046   declareProperty("VertexSelection",m_VertexSelection = "none");
00047   declareProperty("UseFastMuEnergyCut",m_UseFastMuEnergyCut = false);
00048 }
00049 
00050 StatusCode HistorianStepAction::initialize() 
00051 {
00052   info() << "HistorianStepAction::initialize()" << endreq;
00053 
00054   StatusCode sc = QueriableStepAction::initialize();
00055   if (sc.isFailure()) return sc;
00056   
00057   // Set up default search path for detector elements. Note that this throws away PMT-specific information.
00058   // Also, change the default search path:
00059   m_DetectorElementSearchPath.clear();
00060   m_DetectorElementSearchPath.push_back("/dd/Structure/DayaBay");
00061   m_DetectorElementSearchPath.push_back("/dd/Structure/Sites");
00062   m_DetectorElementSearchPath.push_back("/dd/Structure/Pool");
00063   m_DetectorElementSearchPath.push_back("/dd/Structure/AD");
00064   m_DetectorElementSearchPath.push_back("/dd/Structure/RPC");
00065   
00066   sc = service("HistoryKeeper",mHistoryKeeper,true);
00067   if (sc.isFailure()) return sc;
00068   
00069 
00071   // Build the selection rules.
00072   
00073   using namespace RuleParser;
00074   using std::string;
00075     
00077   ParameterList tplist;
00078   QueriableStepAction::GetTrackParameterList(tplist);
00079   tplist.add<double>(kPar_ParentPdg,"ParentPdg","AncestorPdg","Ancestor");
00080   tplist.add<double>(kPar_ParentIndirection,"ParentIndirection","AncestorIndirection");
00081   tplist.add<double>(kPar_GrandParentPdg,"GrandParentPdg","GrandParent");
00082   tplist.add<double>(kPar_GrandParentIndirection,"GrandParentIndirection");
00083 
00084 
00086   ParameterList vplist;
00087   QueriableStepAction::GetVertexParameterList(vplist);
00088   vplist.add<double>(kPar_ParentPdg,"ParentPdg","AncestorPdg","Ancestor");
00089   vplist.add<double>(kPar_ParentIndirection,"ParentIndirection","AncestorIndirection");
00090   vplist.add<double>(kPar_GrandParentPdg,"GrandParentPdg","GrandParent");
00091   vplist.add<double>(kPar_GrandParentIndirection,"GrandParentIndirection");
00092   
00093   vplist.add<double>(kPar_distanceFromLastVertex,"distanceFromLastVertex");
00094   vplist.add<double>(kPar_timeSinceLastVertex,"TimeSinceLastVertex");
00095   vplist.add<double>(kPar_energyLossSinceLastVertex,"EnergyLostSinceLastVertex");
00096   vplist.add<double>(kPar_angleFromLastVertex,"AngleFromLastVertex");
00097                                                      
00098                                                      
00099   bool result;
00100   result = RuleParser::CreateRules(m_TrackSelection,tplist,mTrackRule);
00101   
00102   if(mTrackRule==0 || result==false) {
00103     err() << "Failed to interpret selection string: " << m_TrackSelection << endreq;
00104     return StatusCode::FAILURE;
00105   } else {
00106     info() << "Configured with track selection:  " << mTrackRule->name() << endreq;
00107   }
00108   
00109 
00110   result = RuleParser::CreateRules(m_VertexSelection,vplist,mVertexRule);
00111   
00112   if(mVertexRule==0 || result==false) {
00113     err() << "Failed to interpret selection string: " << m_VertexSelection << endreq;
00114     return StatusCode::FAILURE;
00115   } else {
00116     info() << "Configured with vertex selection: " << mVertexRule->name() << endreq;
00117   }
00118   
00119 
00120   return StatusCode::SUCCESS; 
00121 }
00122 
00123 StatusCode HistorianStepAction::finalize() 
00124 {
00125   return  QueriableStepAction::finalize();
00126 }
00127 
00129 // Callback functions for the RuleParser mechanism.
00130 
00131 
00132 void  HistorianStepAction::queryParam(int id,double& output) const
00133 {
00134   SimTrackReference ref;
00135   G4StepPoint* postPoint = mCurrentStep->GetPostStepPoint();
00136   const SimVertex* v = 0;
00137   Gaudi::XYZPoint pos;
00138   Gaudi::XYZVector dPos;
00139   
00140   switch(id) {
00141     case kPar_ParentPdg:
00142       ref = getAncestorTrack();
00143       if(ref.track()) output = ref.track()->particle();
00144       else output = 0;
00145       break;
00146       
00147     case kPar_ParentIndirection:
00148       output = getAncestorTrack().indirection();
00149       break;
00150 
00151     case kPar_GrandParentPdg:
00152       output = 0;
00153       ref = getAncestorTrack();
00154       if(ref.track()) ref = ref.track()->ancestorTrack();
00155       if(ref.track()) output = ref.track()->particle();
00156       break;
00157     
00158     case kPar_GrandParentIndirection:
00159       output = -999;
00160       ref = getAncestorTrack();
00161       if(ref.track()) output = ref.track()->ancestorTrack().indirection();
00162       break;
00163 
00164     // Special history stuff.
00165     case kPar_distanceFromLastVertex:      
00166     case kPar_timeSinceLastVertex:
00167     case kPar_energyLossSinceLastVertex:
00168     case kPar_angleFromLastVertex:
00169       assert(mCurrentTrackRef.track());
00170       assert(mCurrentTrackRef.track()->vertices().size());
00171       v = mCurrentTrackRef.track()->vertices().back();
00172 
00173       switch(id) {
00174         case kPar_distanceFromLastVertex:
00175           pos = Gaudi::XYZPoint(postPoint->GetPosition().x()
00176                                 ,postPoint->GetPosition().y()
00177                                 ,postPoint->GetPosition().z());
00178           dPos = pos - v->position();
00179           output = dPos.R();
00180           return;
00181         case kPar_timeSinceLastVertex:
00182           output = postPoint->GetGlobalTime() - v->time();
00183           return;
00184         case kPar_energyLossSinceLastVertex:
00185           output = postPoint->GetTotalEnergy() - v->totalEnergy();
00186           return;
00187         case kPar_angleFromLastVertex:
00188           output = ( postPoint->GetMomentumDirection().x() * v->momentum().x()
00189                    + postPoint->GetMomentumDirection().y() * v->momentum().y()
00190                    + postPoint->GetMomentumDirection().z() * v->momentum().z() )
00191                    / (v->momentum().R());
00192           output = acos(output)*CLHEP::radian;
00193           return;
00194       }
00195       break;
00196 
00197     default:
00198       QueriableStepAction::queryParam(id,output);
00199   }
00200   verbose() << " id " << id << " output " << output << endreq;
00201 
00202 }
00203 
00204 void  HistorianStepAction::queryParam(int id,std::string& output) const
00205 {
00206   QueriableStepAction::queryParam(id,output);
00207   verbose() << " id " << id << " output " << output << endreq;
00208 
00209 }
00210 
00211 
00212 SimTrackReference HistorianStepAction::getAncestorTrack() const
00213 {
00214   const G4HistoryUserTrackInfo* info = getUserTrackInfo();
00215   if(!info) {
00216     err() << "Found track id " << mCurrentTrack->GetTrackID() << " with no user info. Shouldn't happen." << endreq;
00217     err() << "(Are you running with both the HistorianTrackAction AND the HistorianStepAction?)" << endreq;
00218     assert(info);    
00219   }
00220   return info->track();
00221 }
00222 
00223 SimVertexReference HistorianStepAction::getAncestorVertex() const
00224 {
00225   const G4HistoryUserTrackInfo* info = getUserTrackInfo();
00226   if(!info) {
00227     err() << "Found track id " << mCurrentTrack->GetTrackID() << " with no user info. Shouldn't happen." << endreq;
00228     err() << "(Are you running with both the HistorianTrackAction AND the HistorianStepAction?)" << endreq;
00229     assert(info);    
00230   }
00231   
00232   return info->vertex();
00233 }
00234 
00235 
00237 // Function to fill out the vertex.
00238 
00239 StatusCode HistorianStepAction::CreateVertex(SimVertex* &vertex,
00240                                            const SimTrackReference& parent)
00241 { 
00248      
00249   const G4ThreeVector& pos = mCurrentStepPoint->GetPosition();
00250   const G4ThreeVector mom = mCurrentStepPoint->GetMomentum();
00251 
00252   vertex = new SimVertex(
00253                       parent,
00254                       getProcess(),
00255                       mCurrentStepPoint->GetGlobalTime(),
00256                       Gaudi::XYZPoint(pos.x(),pos.y(),pos.z()),
00257                       mCurrentStepPoint->GetTotalEnergy(),
00258                       Gaudi::XYZVector(mom.x(),mom.y(),mom.z())
00259                      );
00260 
00261   return StatusCode::SUCCESS;
00262 }
00263 
00265 // Function to fill out the track.
00266 
00267 
00268 StatusCode HistorianStepAction::CreateTrack(const G4Track* g4track,SimTrack* &track)
00269 {
00270   SimTrackReference parentTrack;
00271   SimVertexReference parentVertex;
00272   int parentPdg = 0;
00273  
00274   const HepMC::GenParticle*  genPart = 0;
00275 
00276   if(g4track->GetParentID()==0){
00277     //info() << "Building primary particle" << endreq;
00278     // Primary track is a special case.
00279     parentTrack = SimTrackReference(0,0);
00280     parentVertex= SimVertexReference(0,0);
00281 
00282     const G4DhPrimaryParticleInformation* primaryinfo = 
00283         dynamic_cast<const G4DhPrimaryParticleInformation*>(
00284              g4track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation() );
00285      if(primaryinfo) {
00286        genPart  = primaryinfo->GetHepParticle();      
00287      }
00288 
00289   } else {
00290     const G4HistoryUserTrackInfo* userinfo = getUserTrackInfo();
00291     if(userinfo) {
00292       parentTrack = userinfo->track();
00293       parentVertex = userinfo->vertex();
00294       parentPdg = userinfo->parentPdg();
00295     } else {
00296       err() << "Found track id " << mCurrentTrack->GetTrackID() << " with no user info. Shouldn't happen." << endreq;
00297       err() << "(Are you running with both the HistorianTrackAction AND the HistorianStepAction?)" << endreq;
00298       assert(userinfo);    
00299     }
00300     genPart = parentTrack.track()->primaryParticle();
00301   }
00302 
00303   int pdg = pdgFromG4Track(g4track);
00304   if(pdg == 0 ) {
00305     warning() << "Found particle with zero pdg code. Geant claims this particle is: " 
00306               << g4track->GetDefinition()->GetParticleName() << endreq;
00307   }
00308  
00309   track = new SimTrack();
00310   track->setTrackId(g4track->GetTrackID());
00311   track->setParentParticle(parentPdg);
00312   track->setAncestorTrack(parentTrack);
00313   track->setAncestorVertex(parentVertex);
00314   track->setPrimaryParticle(genPart);
00315   track->setParticle(pdg);
00316     
00318   // Create the start vertex.
00319   const G4ThreeVector& pos = mCurrentStepPoint->GetPosition();
00320   const G4ThreeVector mom = mCurrentStepPoint->GetMomentum();
00321 
00322   // Figure out the process.
00323   SimProcess proc;
00324   if(g4track->GetParentID()==0){
00325     // This is a primary.
00326     proc = SimProcess(SimProcess::kPrimaryVertex,"");
00327   } else {
00328     if(mCurrentTrack->GetCreatorProcess())
00329       proc = SimProcess(SimProcess::kParticleStart,mCurrentTrack->GetCreatorProcess()->GetProcessName());
00330     else
00331       proc = SimProcess(SimProcess::kParticleStart,"");
00332   }
00333 
00334   SimVertex* vertex = new SimVertex(
00335                        SimTrackReference(track,0),
00336                        proc,
00337                        mCurrentStepPoint->GetGlobalTime(),
00338                        Gaudi::XYZPoint(pos.x(),pos.y(),pos.z()),
00339                        mCurrentStepPoint->GetTotalEnergy(),
00340                        Gaudi::XYZVector(mom.x(),mom.y(),mom.z())
00341                       );
00342     
00343   track->addVertex(vertex);
00344   mCurrentHistory->addTrack(track);
00345   mCurrentHistory->addTrackRef(g4track->GetTrackID(),SimTrackReference(track,0));
00346   mCurrentHistory->addVertex(vertex);
00347   if(g4track->GetParentID()==0){ 
00348     // This is a primary.
00349     mCurrentHistory->addPrimaryTrack(track);
00350   } else {
00351     // This track is not a primary, so try to link from our parent vertex to us.
00352     // Invert the parent-vertex indirection to find out the parentVertex->this track reference.
00353     SimTrackReference downref(track,parentVertex.indirection());
00354     if(!parentVertex.vertex())
00355       err() << "SimTrack being created, but no Parent vertex is stored. This shouldn't happen." << endreq;
00356     else
00357       parentVertex.vertex()->addSecondary(downref);
00358   }  
00359   return StatusCode::SUCCESS;
00360 }
00361 
00362 
00363 bool HistorianStepAction::IsInterestingVertex(const G4Step*)
00364 {
00365   // All the magic is done by the RuleParser system, and the Rules it has procuded:
00366   return mVertexRule->select(this);
00367 }
00368 
00369 bool HistorianStepAction::IsInterestingTrack(const G4Track*)
00370 {
00371   // All the magic is done by the RuleParser system, and the Rules it has procuded:
00372   return mTrackRule->select(this);
00373 }
00374 
00375 
00376 void HistorianStepAction::UserSteppingAction(const G4Step* g4step)
00377 {
00383   
00384   // Reset temporary things:
00385   mHistoryKeeper->GetCurrentHistory(mCurrentHistory);
00386   assert(mCurrentHistory);
00387  
00389   //Add the fast muon simulation energy cut for different particle, intend to increase the simulation speed. By Haoqi Jan,27, 2011.
00390   
00391   G4Track* g4track = g4step->GetTrack();
00395   if( g4track->GetGlobalTime()> 3e16 )  {  //3e16 /* a year */
00396     G4HistoryUserTrackInfo* userinfo = dynamic_cast<G4HistoryUserTrackInfo*>
00397       ( g4track->GetUserInformation() );
00398     int parentPdg = 0;
00399     if(userinfo) {
00400       parentPdg = userinfo->parentPdg();
00401     }
00402     warning()<<"A 1 year old track orignated by particle "<<parentPdg<<endreq;
00403   }
00405 
00406   G4int trackId = g4track ->GetTrackID();
00407   G4StepPoint* thePrePoint;
00408   G4VPhysicalVolume* physV;
00409   G4Material* material;
00410   G4ParticleDefinition* particle = g4track->GetDefinition();
00411   G4String pname = particle->GetParticleName();
00412   G4ProcessVector* processVector; 
00413   thePrePoint = g4step->GetPreStepPoint();
00414   physV = thePrePoint->GetPhysicalVolume();
00415   material = physV->GetLogicalVolume()->GetMaterial(); 
00416   G4double EnergyCut;
00417  
00418 if(g4track->GetCurrentStepNumber()==1&&m_UseFastMuEnergyCut==true)
00419   { idflag=true;}
00420  //G4cout<<"FastMuCut ="<<m_UseFastMuEnergyCut <<G4endl;
00421   if(idflag==true)
00422     {
00423        
00424       if(material->GetName()=="/dd/Materials/Rock"||material->GetName()=="/dd/Materials/Air")
00425       {  
00426        //  G4cout<<"Rock or air aterial Name ="<<material->GetName()<<G4endl;
00427          if(particle->GetPDGCharge()!=0)
00428          {
00429             EnergyCut=500.0;
00430          }
00431          else
00432          {
00433             EnergyCut=30.0; 
00434          }
00435       }//rock
00436       else if(material->GetName()=="/dd/Materials/OwsWater"||material->GetName()=="/dd/Materials/IwsWater")
00437       {
00438          // G4cout<<"Ows or IWs aterial Name ="<<material->GetName()<<G4endl;
00439          if(particle->GetPDGCharge()!=0)
00440          {
00441             EnergyCut=50.0;
00442          }
00443          else
00444          {
00445             EnergyCut=3.0;   
00446           }
00447        }
00448        else 
00449        {
00450         EnergyCut=0.;
00451      //    if(material->GetName()=="/dd/Materials/LiquidScintillator"||material->GetName()=="/dd/Materials/GdDopedLS") G4cout<<"Material ="<<material->GetName()<<G4endl;
00452 
00453         }//material
00454       if(g4track->GetKineticEnergy()/MeV<EnergyCut)
00455       {
00456           
00457           //aTrack->SetKineticEnergy(0.00001/MeV);
00458           g4track->SetTrackStatus(fStopAndKill);
00459           idflag=false;
00460       }
00461    }//idflag
00463   
00465   // First, do things related to SimTracks.
00467 
00468   if(g4track->GetCurrentStepNumber() == 1) {
00469     // This is the first time we've seen this track. 
00470     // The interesting point is the first one, the track initial vertex.
00471     QueriableStepAction::Reset(g4step,g4track,g4step->GetPreStepPoint());
00472 
00473     // Does a SimTrack already exist for this G4track?
00474     int id = g4track->GetTrackID();
00475     SimTrackReference ref = mCurrentHistory->track(id);
00476     SimTrack* track = ref.track();
00477 
00478     if(track==0) { // There is no track or reference.
00479       // Maybe we need to make one. Is it a primary track?
00480       if(g4track->GetParentID()==0) {
00481         // This is a primary track, so this action is responsible for starting it.
00482         // Create the SimTrack
00483         CreateTrack(g4track,track);
00484         ref = SimTrackReference(track,0);
00485       } else {
00486         if(IsInterestingTrack(g4track)) {
00487           CreateTrack(g4track,track);        
00488           ref = SimTrackReference(track,0);
00489         }
00490       }
00491     }
00492 
00493     if(ref.track()==0) {
00494       // OK, there is still no valid reference. Let's build an indirect one.
00495       SimTrackReference  parentTrack = getAncestorTrack();
00496       SimVertexReference parentVertex = getAncestorVertex();
00497 
00498        // Increment indirection.
00499        ref = SimTrackReference(parentTrack.track(),parentTrack.indirection()+1);
00500        mCurrentHistory->addTrackRef(g4track->GetTrackID(),ref);
00501      }
00502 
00503 
00504     // currentTrack should now be set correctly, one way or another
00505     if(! ref.isDirect()) {
00506       // The reference is indirect, meaning we aren't recording the current one.
00507       // So, instead, we want to store some 'missing' information.
00508       ref.track()->incrementUnrecordedDescendants(pdgFromG4Track(g4track));
00509     }
00510 
00511     // The current track reference, for convenience.
00512     //mCurrentHistory->setCurrentTrack(ref);
00513   }
00514   
00516   // Second, do things related to SimVertex.
00518   
00519   // The point of interest is the post-step if we're looking at the step/vertex
00520   QueriableStepAction::Reset(g4step,g4track,g4step->GetPostStepPoint());
00521   
00522   mCurrentTrackRef = mCurrentHistory->track(g4track->GetTrackID());
00523   if(!mCurrentTrackRef.track()) {
00524     // This is an error and shouldn't happen.
00525     err() << "Somehow we got a bad track reference on track id " 
00526           << g4track->GetTrackID() << endreq;
00527     err() << " This shouldn't happen - everything should have a parent." << endreq;
00528     assert(0);
00529   }
00530   
00531 
00532   // Is the current track getting recorded?
00533   if(mCurrentTrackRef.isDirect()){
00534     // Yes. Is this interaction interesting on it's own?
00535     if(IsInterestingVertex(g4step)) {
00536       verbose() << " InterestingVertex. Track in " << g4step->GetTrack()->GetVolume()->GetName() 
00537               << " particle " << g4step->GetTrack()->GetDefinition()->GetParticleName()
00538               << " G4TrackID "<< g4step->GetTrack()->GetTrackID()
00539               << " current step# " << g4step->GetTrack()->GetCurrentStepNumber()
00540               << " step length(mm) " << g4step->GetTrack()->GetStepLength()/mm
00541               << endreq;
00542       SimVertex* vertex = 0;
00543       CreateVertex(vertex,mCurrentTrackRef);
00544       // Give ownership to History.
00545       mCurrentHistory->addVertex(vertex); 
00546       // We have a recorded track and recorded vertex. So, add the vertex.
00547       mCurrentTrackRef.track()->addVertex(vertex);
00548     }
00549   }
00550 
00551   // Get current PDG code.
00552   int pdg = pdgFromG4Track(g4track);
00553   
00554   // Get the current best reference to a vertex
00555   SimVertexReference curVertexRef(mCurrentTrackRef.track()->vertices().back(),mCurrentTrackRef.indirection());
00556 
00557   assert(fpSteppingManager);
00558   assert(fpSteppingManager->GetStep() == g4step);
00559   
00560   // Loop over secondaries, push information forward.
00561   int nSecAtRest = fpSteppingManager->GetfN2ndariesAtRestDoIt();
00562   int nSecAlong  = fpSteppingManager->GetfN2ndariesAlongStepDoIt();
00563   int nSecPost   = fpSteppingManager->GetfN2ndariesPostStepDoIt();
00564   int nSecTotal  = nSecAtRest+nSecAlong+nSecPost;
00565   G4TrackVector* secVec = fpSteppingManager->GetfSecondary();
00566 
00567   size_t end = (*secVec).size();
00568   size_t start = end-nSecTotal;
00569   for(size_t itrack=start; itrack < end; itrack++)
00570   {
00571     G4Track* g4track = (*secVec)[itrack];
00572     G4HistoryUserTrackInfo* user
00573       = new G4HistoryUserTrackInfo(curVertexRef,mCurrentTrackRef,pdg);
00574     if(g4track->GetUserInformation()) {
00575       warning() << "Already found user info!  itrack=" << itrack
00576         << " out of " << (*secVec).size() << endreq;
00577     } else {
00578       g4track->SetUserInformation(user);
00579     }
00580   }
00581 
00582 }
00583 
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 20:54:53 2011 for Historian by doxygen 1.4.7