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
00058
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
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
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
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
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
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
00278
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
00319 const G4ThreeVector& pos = mCurrentStepPoint->GetPosition();
00320 const G4ThreeVector mom = mCurrentStepPoint->GetMomentum();
00321
00322
00323 SimProcess proc;
00324 if(g4track->GetParentID()==0){
00325
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
00349 mCurrentHistory->addPrimaryTrack(track);
00350 } else {
00351
00352
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
00366 return mVertexRule->select(this);
00367 }
00368
00369 bool HistorianStepAction::IsInterestingTrack(const G4Track*)
00370 {
00371
00372 return mTrackRule->select(this);
00373 }
00374
00375
00376 void HistorianStepAction::UserSteppingAction(const G4Step* g4step)
00377 {
00383
00384
00385 mHistoryKeeper->GetCurrentHistory(mCurrentHistory);
00386 assert(mCurrentHistory);
00387
00389
00390
00391 G4Track* g4track = g4step->GetTrack();
00395 if( g4track->GetGlobalTime()> 3e16 ) {
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
00421 if(idflag==true)
00422 {
00423
00424 if(material->GetName()=="/dd/Materials/Rock"||material->GetName()=="/dd/Materials/Air")
00425 {
00426
00427 if(particle->GetPDGCharge()!=0)
00428 {
00429 EnergyCut=500.0;
00430 }
00431 else
00432 {
00433 EnergyCut=30.0;
00434 }
00435 }
00436 else if(material->GetName()=="/dd/Materials/OwsWater"||material->GetName()=="/dd/Materials/IwsWater")
00437 {
00438
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
00452
00453 }
00454 if(g4track->GetKineticEnergy()/MeV<EnergyCut)
00455 {
00456
00457
00458 g4track->SetTrackStatus(fStopAndKill);
00459 idflag=false;
00460 }
00461 }
00463
00465
00467
00468 if(g4track->GetCurrentStepNumber() == 1) {
00469
00470
00471 QueriableStepAction::Reset(g4step,g4track,g4step->GetPreStepPoint());
00472
00473
00474 int id = g4track->GetTrackID();
00475 SimTrackReference ref = mCurrentHistory->track(id);
00476 SimTrack* track = ref.track();
00477
00478 if(track==0) {
00479
00480 if(g4track->GetParentID()==0) {
00481
00482
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
00495 SimTrackReference parentTrack = getAncestorTrack();
00496 SimVertexReference parentVertex = getAncestorVertex();
00497
00498
00499 ref = SimTrackReference(parentTrack.track(),parentTrack.indirection()+1);
00500 mCurrentHistory->addTrackRef(g4track->GetTrackID(),ref);
00501 }
00502
00503
00504
00505 if(! ref.isDirect()) {
00506
00507
00508 ref.track()->incrementUnrecordedDescendants(pdgFromG4Track(g4track));
00509 }
00510
00511
00512
00513 }
00514
00516
00518
00519
00520 QueriableStepAction::Reset(g4step,g4track,g4step->GetPostStepPoint());
00521
00522 mCurrentTrackRef = mCurrentHistory->track(g4track->GetTrackID());
00523 if(!mCurrentTrackRef.track()) {
00524
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
00533 if(mCurrentTrackRef.isDirect()){
00534
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
00545 mCurrentHistory->addVertex(vertex);
00546
00547 mCurrentTrackRef.track()->addVertex(vertex);
00548 }
00549 }
00550
00551
00552 int pdg = pdgFromG4Track(g4track);
00553
00554
00555 SimVertexReference curVertexRef(mCurrentTrackRef.track()->vertices().back(),mCurrentTrackRef.indirection());
00556
00557 assert(fpSteppingManager);
00558 assert(fpSteppingManager->GetStep() == g4step);
00559
00560
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