Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

PTSimModule.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // PTSimModule
00004 //
00005 // PTSimModule is a JobControl Module for use with simulating particle
00006 // transport through the MINOS detectors.
00007 //
00008 // S. Kasahara 05/04
00010 
00011 #include <cassert>
00012 //#include "/usr/include/google/profiler.h"
00013 
00014 #include <TClonesArray.h>
00015 #include <TVirtualMC.h>
00016 #include <TMCProcess.h>
00017 #include <TPDGCode.h>
00018 #include <TDatabasePDG.h>
00019 
00020 #include "MessageService/MsgService.h"
00021 #include "JobControl/JobCommand.h"
00022 #include "JobControl/JobCModuleRegistry.h"
00023 #include "ParticleTransportSim/PTSim.h"
00024 #include "ParticleTransportSim/PTSimModule.h"
00025 #include "ParticleTransportSim/PTSimApplication.h"
00026 #include "ParticleTransportSim/PTSimStack.h"
00027 #include "MCApplication/MCApplication.h"
00028 #include "Util/LoadMinosPDG.h"
00029 #include "Util/UtilString.h"
00030 #include "Record/SimSnarlRecord.h"
00031 #include "MinosObjectMap/MomNavigator.h"
00032 
00033 ClassImp(PTSimModule)
00034 
00035 //   Definition of static data members
00036 //   *********************************
00037 
00038 CVSID("$Id: PTSimModule.cxx,v 1.56 2009/06/22 03:51:01 kasahara Exp $");
00039 
00040 JOBMODULE(PTSimModule, "PTSimModule",
00041           "A module for running the particle transport simulation.");
00042 
00043 //_____________________________________________________________________________
00044 PTSimModule::PTSimModule(): fMCConfig("<null>"),fDecayConfig("<null>"),
00045                             fMCAppUser(0),fRandomSeed(0) {
00046   // Default constructor
00047 
00048   LoadMinosPDG(); // Load PDG database w/MINOS specific particles
00049   
00050   fStopwatch.Reset();
00051   fStopwatch.Stop();
00052   
00053 
00054   // The application must be instantiated before the mc implementation
00055   fMCAppUser = new PTSimApplication("PTSimApplication","Minos MC Application");
00056   if ( !fMCAppUser ) {
00057     MSG("PTSim",Msg::kFatal) << "No MC application instance." << endl;
00058     abort();
00059   }
00060 
00061 
00062 }
00063 
00064 //_____________________________________________________________________________
00065 PTSimModule::~PTSimModule() {
00066    // Destructor
00067 
00068   MSG("PTSim",Msg::kDebug) << "PTSimModule dtor @ " << this << endl;
00069   
00070   if ( fMCAppUser ) delete fMCAppUser; fMCAppUser = 0;
00071 
00072   // Clear contents of MCApplication because MCApplication singleton
00073   // destruction is out of order with G4 singleton destruction
00074   MCApplication& mcapp = const_cast<MCApplication&>(MCApplication::Instance());
00075   mcapp.Clear();
00076   
00077 }
00078 
00079 //_____________________________________________________________________________
00080 const Registry& PTSimModule::DefaultConfig() const {
00081   //
00082   // Purpose: Method to return default configuration.
00083   // 
00084   // Arguments: none.
00085   //
00086   // Return: Registry containing default configuration
00087   //
00088 
00089   MSG("PTSim",Msg::kDebug) << "Loading default config" << endl;
00090 
00091   static Registry r; 
00092   std::string name = this->JobCModule::GetName();
00093   name += ".config.default";
00094   r.SetName(name.c_str());
00095 
00096   r.UnLockValues();
00097   r.Set("MCConfig","<null>");
00098   r.Set("DecayConfig","<null>");  // or PTSim_DecayConfig.C
00099   r.Set("StdHepSelectMask",PTSim::kMomentum);
00100   // stdhep select mask default is to save
00101   // all tracks above momentum threshold (StdHepThr) 
00102   r.Set("StdHepThr",0.15);// default p(GeV/c) thresh applied to stdhep trks
00103   // if user has selected mode to save secondaries resulting in energy
00104   // deposition hit, StdHepHitThr determines threshold above which to
00105   // store
00106   r.Set("StdHepHitThr",0.001);// default E(GeV) hit threshold
00107   // flag used to determine if selected secondary siblings are to be saved 
00108   // (0 => false, 1 => true, 2 (default) => true and save siblings of direct 
00109   // ancestors as well if StdHepSaveAncestor true)
00110   r.Set("StdHepSaveSibling",2);// default is to save selected secondary sibs
00111                                // and sibs of ancestors
00112   r.Set("StdHepSaveAncestor",1);// default is to save selected secondary ances
00113   r.Set("RandomSeed",fRandomSeed);  // optional random seed supplied by user
00114   r.Set("RkVLevel",0);  // default is to impose no rock veto cuts
00115   r.Set("RkVMinDist",2.); // default minimum distance at which veto cut applies
00116   // safety factor multiplied in front of E/(dE/dX)_min when determining max 
00117   // distance particle will travel 
00118   r.Set("RkVFactor",1.25); 
00119   r.Set("UseLinearStep",false); // bad idea to set true, but useful for validation against gminos
00120 
00121   r.LockValues();
00122 
00123   // Set defaults for storing secondaries
00124   // Always store secondary muons, regardless of production mechanism or 
00125   // momentum
00126   PTSimStack* stack = fMCAppUser -> GetStack();
00127   if ( !stack ) {
00128     MSG("PTSim",Msg::kFatal) << "No stack!" << endl;
00129     abort();
00130   }
00131 
00132   // Always store muons at production
00133   stack -> SetStdHepThrByType(0.,kPNoProcess,-13);
00134   stack -> SetStdHepThrByType(0.,kPNoProcess,+13);
00135   // Always store secondaries produced by muon decay, regardless of type
00136   stack -> SetStdHepThrByType(0.,kPDecay,kRootino,-13);
00137   stack -> SetStdHepThrByType(0.,kPDecay,kRootino,+13);
00138 
00139 
00140   return r;
00141 }
00142 
00143 
00144 //_____________________________________________________________________________
00145 void PTSimModule::Config(const Registry& r) {
00146   //
00147   // Purpose: Configure the module given a registry.
00148   //
00149   // Arguments: Registry to use to configure the module.
00150   //
00151   // Return: none.
00152   //
00153 
00154   MSG("PTSim",Msg::kDebug) << "Config PTSimModule with r=" << r << endl;
00155   
00156   Int_t tmpi;
00157   Double_t tmpd;
00158   const Char_t* tmpc;
00159   if ( r.Get("MCConfig",tmpc) ) fMCConfig = tmpc;
00160   if ( r.Get("DecayConfig",tmpc) ) fDecayConfig = tmpc;
00161 
00162   PTSimStack* stack = fMCAppUser -> GetStack();
00163   if ( r.Get("StdHepThr",tmpd) ) stack -> SetStdHepThr(tmpd);
00164   if ( r.Get("StdHepHitThr",tmpd) ) stack -> SetStdHepHitThr(tmpd);
00165   if ( r.Get("StdHepSelectMask",tmpi) ) stack -> SetStdHepSelectMask(tmpi);
00166   if ( r.Get("StdHepSaveSibling",tmpi) ) stack -> SetStdHepSaveSibling(tmpi);
00167   if ( r.Get("StdHepSaveAncestor",tmpi) ) stack -> SetStdHepSaveAncestor(tmpi);
00168   if ( r.Get("RandomSeed",tmpi) ) fRandomSeed = tmpi;
00169   if ( r.Get("RkVLevel",tmpi) ) fMCAppUser -> SetRkVLevel(tmpi);
00170   if ( r.Get("RkVMinDist",tmpd) ) fMCAppUser -> SetRkVMinDistInCM(tmpd*100.);
00171   if ( r.Get("RkVFactor",tmpd) ) fMCAppUser -> SetRkVFactor(tmpd);
00172   if ( r.Get("UseLinearStep",tmpi) ) fMCAppUser -> UseLinearStep(tmpi);
00173   
00174 }
00175 
00176 //_____________________________________________________________________________
00177 void PTSimModule::BeginJob() {
00178   //
00179   //  Purpose:  Called once at the beginning of the job to
00180   //            handle job module initialization.
00181   //
00182   //  Arguments: none.
00183   //  
00184   //  Return: status.
00185   // 
00186 
00187    MSG("PTSim",Msg::kDebug) << "PTSimModule::BeginJob" << endl;
00188 
00189    // mc implementation initialization is saved until first event
00190    // since vldc is required for geometry construction
00191    
00192 }
00193 
00194 //_____________________________________________________________________________
00195 void PTSimModule::EndJob() {
00196   //
00197   //  Purpose:  Called once at the end of the job to handle job
00198   //            module validation.
00199   //
00200   //  Arguments: none.
00201   //  
00202   //  Return: status.
00203   // 
00204 
00205    MSG("PTSim",Msg::kDebug) << "PTSimModule::EndJob" << endl;
00206 
00207    //ProfilerStop();
00208    
00209    fStopwatch.Stop();
00210    Int_t nSnarl = 0;
00211    Int_t nEvent = 0;
00212    if ( fMCAppUser ) {
00213      nSnarl = fMCAppUser -> GetNSnarls();
00214      nEvent = fMCAppUser -> GetNEvents();
00215    }
00216    
00217    MSG("PTSim",Msg::kInfo) << "PTSimModule::EndJob, Time(sec), Real "
00218                            << fStopwatch.RealTime() << ", CPU "
00219                            << fStopwatch.CpuTime() << " # snarls/events " 
00220                            << nSnarl << "/" << nEvent <<  endl;
00221    
00222 }
00223 
00224 //_____________________________________________________________________________
00225 void PTSimModule::HandleCommand(JobCommand* cmd) {
00226   // Used to handle commands that don't work Config
00227   //
00228   
00229   if ( !cmd->HaveCmd() ) return;
00230   string s = cmd->PopCmd();
00231   if ( s == "StdHepThrByType" ) {
00232     UtilIstHEP::EProdMethod prodmethod = UtilIstHEP::kMNoProcess;
00233     Int_t pdgId = kRootino;
00234     Int_t parentId = kRootino;
00235     double thresh = 0.;
00236     if ( cmd->HaveOpt() ) {
00237       thresh = cmd->PopFloatOpt();
00238 
00239       if ( cmd->HaveOpt() ) {
00240         int prodmethodint = cmd -> PopIntOpt();
00241         if ( prodmethodint < 0 || prodmethodint >= UtilIstHEP::kNProdMethod ){
00242           MSG("PTSim",Msg::kWarning) 
00243           << "StdHepThrByType called w/invalid UtilIstHEP::EProdMethod "
00244           << prodmethodint << ". Ignored." << endl;
00245           return;
00246         }
00247         else prodmethod = (UtilIstHEP::EProdMethod)(prodmethodint);
00248 
00249         if ( cmd->HaveOpt() ) {
00250           pdgId = cmd -> PopIntOpt();
00251           if ( cmd->HaveOpt() ) parentId = cmd -> PopIntOpt();
00252         }
00253       }
00254       else {
00255         MSG("PTSim",Msg::kWarning)
00256           << "StdHepThrByType called w/no production method. Ignored." 
00257           << endl;
00258         return;
00259       }  
00260     }
00261     else {
00262       MSG("PTSim",Msg::kWarning)
00263         << "StdHepThrByType called w/no momentum threshold. Ignored."
00264         << endl;
00265       return;
00266     }
00267     
00268     // Particle Name
00269     std::string particlename = " for particles of type ";
00270     if ( pdgId != kRootino ) {
00271       particlename += UtilString::ToString<int>(pdgId) + "/";
00272       const TDatabasePDG& dbpdg = *(TDatabasePDG::Instance());
00273       particlename += "???";
00274       if ( dbpdg.GetParticle(pdgId) ) particlename 
00275                        += dbpdg.GetParticle(pdgId)->GetName();
00276     }
00277     else particlename = "";
00278 
00279     std::string parentname = " for particles w/parent type ";
00280     if ( !particlename.empty() ) parentname = " and parent type ";
00281     if ( parentId != kRootino ) {
00282       parentname += UtilString::ToString<int>(parentId) + "/";
00283       const TDatabasePDG& dbpdg = *(TDatabasePDG::Instance());
00284       parentname += "???";
00285       if ( dbpdg.GetParticle(parentId) ) parentname 
00286                        += dbpdg.GetParticle(parentId)->GetName();
00287     }
00288     else parentname = "";
00289     
00290     if ( prodmethod == UtilIstHEP::kMNoProcess ) {
00291       MSG("PTSim",Msg::kInfo) << "PTSimModule StdHepThrByType " 
00292                               << "configured to " << thresh << "(GeV/c)"
00293                               << particlename.c_str()
00294                               << parentname.c_str()
00295                               << endl;
00296     }
00297     else {
00298       std::string prodmethodname = " for particles produced by ";
00299       if ( !parentname.empty() || !particlename.empty() ) 
00300         prodmethodname = " and produced by ";
00301       MSG("PTSim",Msg::kInfo) << "PTSimModule StdHepThrByType " 
00302                               << "configured to " << thresh << "(GeV/c)"
00303                               << particlename.c_str()
00304                               << parentname.c_str()
00305                               << prodmethodname.c_str() << prodmethod 
00306                               << "/" << UtilIstHEP::AsString(prodmethod) 
00307                               << endl;
00308     }
00309     
00310     PTSimStack* stack = fMCAppUser -> GetStack();
00311     TMCProcess tmcprocess = UtilIstHEP::GetTMCProcess(prodmethod);
00312     stack -> SetStdHepThrByType(thresh,tmcprocess,pdgId,parentId);
00313     return;
00314   }
00315   else if ( s == "StdHepSave" ) {
00316 
00317     std::vector<int> snarllist;
00318     MsgStream& msgDebug = MSGSTREAM("PTSim",Msg::kDebug);
00319     msgDebug << "StdHepSave ";
00320 
00321     bool isrange = false;
00322     Int_t nsnarl = 0;
00323     while ( cmd->HaveOpt() ) {
00324       Int_t snarlno = cmd->PopIntOpt();
00325       msgDebug << snarlno << " ";
00326       snarllist.push_back(TMath::Abs(snarlno));
00327       nsnarl++;
00328       if ( snarlno < 0 ) isrange = true;
00329     }
00330     msgDebug << endl;
00331     if ( isrange && nsnarl != 2 ) {
00332       MSG("PTSim",Msg::kWarning)
00333         << "StdHepSave by range requires two arguments. Ignored." << endl;
00334       snarllist.clear();
00335       isrange = false;
00336     }
00337     
00338     PTSimStack* stack = fMCAppUser -> GetStack();
00339     stack -> SetStdHepSave(snarllist,isrange);
00340 
00341     return;
00342   }
00343 
00344   // Errors fall through to here
00345   MSG("PTSim",Msg::kError) << "Illegal command: " << s.c_str() << endl;
00346   
00347 }
00348 
00349 //_____________________________________________________________________________
00350 JobCResult PTSimModule::Reco(MomNavigator *mom) {
00351   //
00352   //  Purpose:  Run the requested mc implementation.
00353   //
00354   //  Arguments: mom.
00355   //  
00356   //  Return: status.
00357   // 
00358 
00359   JobCResult result(JobCResult::kPassed);  
00360   MSG("PTSim",Msg::kDebug) << "PTSimModule::Reco" << endl;
00361 
00362   // Check that mom exists.
00363   assert(mom);
00364 
00365   SimSnarlRecord* record 
00366   = dynamic_cast<SimSnarlRecord*>(mom->GetFragment("SimSnarlRecord"));
00367   if ( !record ) {
00368     MSG("PTSim",Msg::kError) << "No SimSnarlRecord in Mom." << endl;
00369     result.SetWarning().SetFailed();
00370     return result;
00371   }
00372   
00373   RecJobHistory& jobhist 
00374               = const_cast<RecJobHistory&>(record->GetJobHistory());
00375   jobhist.CreateJobRecord(RecJobHistory::kPTSim);
00376   
00377   const SimSnarlHeader* header= record->GetSimSnarlHeader();
00378 
00379   MCApplication& mcapp = const_cast<MCApplication&>(MCApplication::Instance());
00380   const VldContext& vldc = *(record -> GetVldContext());
00381   if ( !(mcapp.GetMC() ) ) {
00382     // VldContext will be used to construct appropriate geometry only once
00383     mcapp.InitMC(fMCConfig.c_str(),vldc,fDecayConfig.c_str());
00384     //ProfilerStart("ptsimprofile");
00385   }
00386   mcapp.InitSnarl(vldc);
00387   
00388   // Tell the MCApplication Instance about the current User application
00389   mcapp.SetUserApplication(fMCAppUser);
00390   
00391   // Extract StdHep array from record
00392   // Particle stack will be initialized using StdHep array contents.
00393   // The particles in this stack represent the initial interaction state 
00394   // particles + secondaries generated during gminos tracking if a reroot 
00395   // file is used as input
00396   TClonesArray* stdheparray = dynamic_cast<TClonesArray*>(const_cast<TObject*>
00397     (record -> FindComponent("TClonesArray","StdHep")));
00398  
00399   if ( !stdheparray || stdheparray->GetEntriesFast() == 0 ) {
00400     MSG("PTSim",Msg::kWarning) 
00401     << "No StdHep TClonesArray in SimSnarlRecord or is empty." << endl;
00402     return JobCResult::kError;
00403   } 
00404 
00405   // Extract NeuKinList array from record
00406   // If present, this will be used to determine the number of events
00407   // in the snarl, which may be more than 1.
00408   const TClonesArray* neukinarray = dynamic_cast<const TClonesArray*>
00409     (record -> FindComponent("TClonesArray","NeuKinList"));
00410   Int_t nevent = 1;
00411   if ( neukinarray && neukinarray->GetEntriesFast() != 0 ) 
00412                                 nevent = neukinarray->GetEntriesFast();
00413 
00414   // Initialize output DigiScintHit stack, results from tracking will
00415   // be stored here.
00416   TClonesArray* hitarray = dynamic_cast<TClonesArray*>(const_cast<TObject*>
00417     (record -> FindComponent("TClonesArray","DigiScintHits")));
00418   if ( hitarray ) hitarray -> Clear("C");
00419   else {
00420     hitarray = new TClonesArray("DigiScintHit");
00421     hitarray -> SetName("DigiScintHits");
00422     record -> AdoptComponent(hitarray);
00423   }
00424 
00425   // Set random number seeds for this event(snarl) according to the
00426   // run/snarl number with an optional user specified random seed thrown
00427   // in as in N. Tagg's DigiPEtoRawDigitModule.
00428   Int_t run = header -> GetRun();
00429   Int_t snarl = header -> GetSnarl();
00430   Int_t seed = run+snarl+fRandomSeed;
00431   MSG("PTSim",Msg::kDebug) << "Random number seed for run,snarl("
00432        << run << "," << snarl << ") = " << seed << endl;
00433   mcapp.GetRandom() -> SetSeed(seed);
00434   
00435   fMCAppUser -> SetHitArray(hitarray); // pass the place to store the hits
00436   // Prime snarl using snarl number, contents of stdheparray, and nevent
00437   fMCAppUser -> InitSnarl(snarl,stdheparray,nevent); 
00438 
00439   fStopwatch.Start(false);
00440   // Monte carlo generation takes place here
00441   gMC -> ProcessRun(nevent);
00442   fStopwatch.Stop();
00443 
00444   return result;
00445 
00446 }
00447 
00448 
00449 
00450 
00451 
00452 
00453 

Generated on Mon Nov 23 05:28:06 2009 for loon by  doxygen 1.3.9.1