CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/SimG4CMS/ShowerLibraryProducer/src/CastorShowerLibraryMaker.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     ShowerLibraryProducer
00004 // Class  :     CastorShowerLibraryMaker
00005 //
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author: P. Katsas
00010 //         Created: 02/2007 
00011 //
00012 // Adapted by W. Carvalho , 02/2009
00013 //
00015 #include "FWCore/Utilities/interface/EDMException.h"
00016 #include "FWCore/Utilities/interface/Exception.h"
00017 #include "SimG4Core/Notification/interface/SimG4Exception.h"
00018 #include "SimG4CMS/Calo/interface/CaloG4Hit.h"
00019 #include "SimG4CMS/Calo/interface/CaloG4HitCollection.h"
00020 #include "DataFormats/Math/interface/Point3D.h"
00021 
00022 #include "SimG4CMS/ShowerLibraryProducer/interface/CastorShowerLibraryMaker.h"
00023 #include "SimG4CMS/Forward/interface/CastorNumberingScheme.h"
00024 
00025 #include "SimDataFormats/CaloHit/interface/CastorShowerEvent.h"
00026 
00027 #include "TFile.h"
00028 #include <cmath>
00029 #include <iostream>
00030 #include <sstream>
00031 #include <iomanip>
00032 #include <stdlib.h>
00033 
00034 CastorShowerLibraryMaker::CastorShowerLibraryMaker(const edm::ParameterSet &p) : 
00035                              NPGParticle(0),DoHadSL(false),DoEmSL(false),DeActivatePhysicsProcess(false),
00036                              emShower(NULL) , hadShower(NULL) {
00037 
00038   MapOfSecondaries.clear();
00039   hadInfo = NULL;
00040   emInfo  = NULL;
00041   edm::ParameterSet p_SLM   = p.getParameter<edm::ParameterSet>("CastorShowerLibraryMaker");
00042   verbosity                 = p_SLM.getParameter<int>("Verbosity");
00043   eventNtFileName           = p_SLM.getParameter<std::string>("EventNtupleFileName");
00044   hadSLHolder.nEvtPerBinPhi = p_SLM.getParameter<int>("nhadEvents");
00045   emSLHolder.nEvtPerBinPhi  = p_SLM.getParameter<int>("nemEvents");
00046   hadSLHolder.SLEnergyBins  = p_SLM.getParameter<std::vector<double> >("SLhadEnergyBins");
00047   hadSLHolder.SLEtaBins     = p_SLM.getParameter<std::vector<double> >("SLhadEtaBins");
00048   hadSLHolder.SLPhiBins     = p_SLM.getParameter<std::vector<double> >("SLhadPhiBins");
00049   emSLHolder.SLEnergyBins   = p_SLM.getParameter<std::vector<double> >("SLemEnergyBins");
00050   emSLHolder.SLEtaBins      = p_SLM.getParameter<std::vector<double> >("SLemEtaBins");
00051   emSLHolder.SLPhiBins      = p_SLM.getParameter<std::vector<double> >("SLemPhiBins");
00052   PGParticleIDs             = p_SLM.getParameter<std::vector<int> >("PartID");
00053   DeActivatePhysicsProcess  = p_SLM.getParameter<bool>("DeActivatePhysicsProcess");
00054   MaxPhi                    = p_SLM.getParameter<double>("SLMaxPhi");
00055   MaxEta                    = p_SLM.getParameter<double>("SLMaxEta");
00056 //
00057   NPGParticle               = PGParticleIDs.size(); 
00058   for(unsigned int i=0;i<PGParticleIDs.size();i++) {
00059      switch (int(fabs(PGParticleIDs.at(i)))) {
00060         case 11:
00061         case 22:
00062                DoEmSL = true;
00063                break;
00064         default:
00065                DoHadSL = true;
00066      }
00067   }
00068   hadSLHolder.nEvtPerBinEta = (hadSLHolder.nEvtPerBinPhi)*(hadSLHolder.SLPhiBins.size());
00069   hadSLHolder.nEvtPerBinE   = (hadSLHolder.nEvtPerBinEta)*(hadSLHolder.SLEtaBins.size());
00070   emSLHolder.nEvtPerBinEta = (emSLHolder.nEvtPerBinPhi)*(emSLHolder.SLPhiBins.size());
00071   emSLHolder.nEvtPerBinE   = (emSLHolder.nEvtPerBinEta)*(emSLHolder.SLEtaBins.size());
00072 
00073   std::cout << "============================================================================"<<std::endl;
00074   std::cout << "CastorShowerLibraryMaker:: Initialized as observer" << std::endl;
00075   std::cout << " Event Ntuple will be created" << std::endl;
00076   std::cout << " Event Ntuple file: " << eventNtFileName << std::endl;
00077   std::cout << " Number of Hadronic events in E   bins: " << hadSLHolder.nEvtPerBinE << std::endl;
00078   std::cout << " Number of Hadronic events in Eta bins: " << hadSLHolder.nEvtPerBinEta << std::endl;
00079   std::cout << " Number of Hadronic events in Phi bins: " << hadSLHolder.nEvtPerBinPhi << std::endl;
00080   std::cout << " Number of Electromag. events in E   bins: " << emSLHolder.nEvtPerBinE << std::endl;
00081   std::cout << " Number of Electromag. events in Eta bins: " << emSLHolder.nEvtPerBinEta << std::endl;
00082   std::cout << " Number of Electromag. events in Phi bins: " << emSLHolder.nEvtPerBinPhi << std::endl;
00083   std::cout << "============================================================================"<<std::endl;
00084   std::cout << std::endl;
00085 
00086   // Initializing the SL collections
00087   InitSLHolder(hadSLHolder);
00088   InitSLHolder(emSLHolder);
00089 }
00090 void CastorShowerLibraryMaker::InitSLHolder(ShowerLib& showerholder)
00091 {
00092   int nBinsE,nBinsEta,nBinsPhi,nEvtPerBinPhi;
00093   nBinsE      = showerholder.SLEnergyBins.size();
00094   nBinsEta    = showerholder.SLEtaBins.size();
00095   nBinsPhi    = showerholder.SLPhiBins.size();
00096   nEvtPerBinPhi=showerholder.nEvtPerBinPhi;
00097 //
00098 // Info
00099 //
00100   showerholder.SLInfo.Energy.setNEvts(nEvtPerBinPhi*nBinsPhi*nBinsEta*nBinsE);
00101   showerholder.SLInfo.Energy.setNEvtPerBin(nEvtPerBinPhi*nBinsPhi*nBinsEta);
00102   showerholder.SLInfo.Energy.setNBins(nBinsE);
00103   showerholder.SLInfo.Energy.setBin(showerholder.SLEnergyBins);
00104 //
00105   showerholder.SLInfo.Eta.setNEvts(nEvtPerBinPhi*nBinsPhi*nBinsEta);
00106   showerholder.SLInfo.Eta.setNEvtPerBin(nEvtPerBinPhi*nBinsPhi);
00107   showerholder.SLInfo.Eta.setNBins(nBinsEta);
00108   showerholder.SLInfo.Eta.setBin(showerholder.SLEtaBins);
00109 //
00110   showerholder.SLInfo.Phi.setNEvts(nEvtPerBinPhi*nBinsPhi);
00111   showerholder.SLInfo.Phi.setNEvtPerBin(nEvtPerBinPhi);
00112   showerholder.SLInfo.Phi.setNBins(nBinsPhi);
00113   showerholder.SLInfo.Phi.setBin(showerholder.SLPhiBins);
00114 //
00115 // Shower
00116   showerholder.SLCollection.assign(nBinsE,std::vector<std::vector<std::vector<CastorShowerEvent> > >());
00117   showerholder.nEvtInBinE.assign(nBinsE,0);
00118   showerholder.nEvtInBinEta.assign(nBinsE,std::vector<int>(0));
00119   showerholder.nEvtInBinPhi.assign(nBinsE,std::vector<std::vector<int> >());
00120   for(int i=0;i<nBinsE;i++) {
00121      showerholder.SLCollection.at(i).assign(nBinsEta,std::vector<std::vector<CastorShowerEvent> >());
00122      showerholder.nEvtInBinEta.at(i).assign(nBinsEta,0);
00123      showerholder.nEvtInBinPhi.at(i).assign(nBinsEta,std::vector<int>(0));
00124      for(int j=0;j<nBinsEta;j++) {
00125         showerholder.SLCollection.at(i).at(j).assign(nBinsPhi,std::vector<CastorShowerEvent>());
00126         showerholder.nEvtInBinPhi.at(i).at(j).assign(nBinsPhi,0);
00127         for(int k=0;k<nBinsPhi;k++) 
00128            showerholder.SLCollection.at(i).at(j).at(k).assign(nEvtPerBinPhi,CastorShowerEvent());
00129      }
00130   }
00131 }
00132 
00133 //===============================================================================================
00134 
00135 CastorShowerLibraryMaker::~CastorShowerLibraryMaker() {
00136 
00137   Finish();
00138 
00139   std::cout << "CastorShowerLibraryMaker: End of process" << std::endl;
00140 
00141 }
00142 
00143 //=================================================================== per EVENT
00144 void CastorShowerLibraryMaker::update(const BeginOfJob * job) {
00145 
00146   std::cout << " CastorShowerLibraryMaker::Starting new job " << std::endl;
00147 }
00148 
00149 //==================================================================== per RUN
00150 void CastorShowerLibraryMaker::update(const BeginOfRun * run) {
00151 
00152   std::cout << std::endl << "CastorShowerLibraryMaker: Starting Run"<< std::endl; 
00153 
00154   std::cout << "CastorShowerLibraryMaker: output event root file created" << std::endl;
00155 
00156   TString eventfilename = eventNtFileName;
00157   theFile = new TFile(eventfilename,"RECREATE");
00158   theTree = new TTree("CastorCherenkovPhotons", "Cherenkov Photons");
00159 
00160   Int_t split = 1;
00161   Int_t bsize = 64000;
00162   emInfo      = new CastorShowerLibraryInfo();
00163   emShower    = new CastorShowerEvent();
00164   hadInfo     = new CastorShowerLibraryInfo();
00165   hadShower   = new CastorShowerEvent();
00166   // Create Branchs
00167   theTree->Branch("emShowerLibInfo.", "CastorShowerLibraryInfo", &emInfo, bsize, split);
00168   theTree->Branch("emParticles.", "CastorShowerEvent", &emShower, bsize, split);
00169   theTree->Branch("hadShowerLibInfo.", "CastorShowerLibraryInfo", &hadInfo, bsize, split);
00170   theTree->Branch("hadParticles.", "CastorShowerEvent", &hadShower, bsize, split);
00171 
00172 // set the Info for electromagnetic shower
00173 // set the energy bins info
00174   emInfo->Energy.setNEvts(emSLHolder.nEvtPerBinE*emSLHolder.SLEnergyBins.size());
00175   emInfo->Energy.setNBins(emSLHolder.SLEnergyBins.size());
00176   emInfo->Energy.setNEvtPerBin(emSLHolder.nEvtPerBinE);
00177   emInfo->Energy.setBin(emSLHolder.SLEnergyBins);
00178 // set the eta bins info
00179   emInfo->Eta.setNEvts(emSLHolder.nEvtPerBinEta*emSLHolder.SLEtaBins.size());
00180   emInfo->Eta.setNBins(emSLHolder.SLEtaBins.size());
00181   emInfo->Eta.setNEvtPerBin(emSLHolder.nEvtPerBinEta);
00182   emInfo->Eta.setBin(emSLHolder.SLEtaBins);
00183 // set the eta bins info
00184   emInfo->Phi.setNEvts(emSLHolder.nEvtPerBinPhi*emSLHolder.SLPhiBins.size());
00185   emInfo->Phi.setNBins(emSLHolder.SLPhiBins.size());
00186   emInfo->Phi.setNEvtPerBin(emSLHolder.nEvtPerBinPhi);
00187   emInfo->Phi.setBin(emSLHolder.SLPhiBins);
00188 // The same for the hadronic shower
00189 // set the energy bins info
00190   hadInfo->Energy.setNEvts(hadSLHolder.nEvtPerBinE*hadSLHolder.SLEnergyBins.size());
00191   hadInfo->Energy.setNBins(hadSLHolder.SLEnergyBins.size());
00192   hadInfo->Energy.setNEvtPerBin(hadSLHolder.nEvtPerBinE);
00193   hadInfo->Energy.setBin(hadSLHolder.SLEnergyBins);
00194 // set the eta bins info
00195   hadInfo->Eta.setNEvts(hadSLHolder.nEvtPerBinEta*hadSLHolder.SLEtaBins.size());
00196   hadInfo->Eta.setNBins(hadSLHolder.SLEtaBins.size());
00197   hadInfo->Eta.setNEvtPerBin(hadSLHolder.nEvtPerBinEta);
00198   hadInfo->Eta.setBin(hadSLHolder.SLEtaBins);
00199 // set the eta bins info
00200   hadInfo->Phi.setNEvts(hadSLHolder.nEvtPerBinPhi*hadSLHolder.SLPhiBins.size());
00201   hadInfo->Phi.setNBins(hadSLHolder.SLPhiBins.size());
00202   hadInfo->Phi.setNEvtPerBin(hadSLHolder.nEvtPerBinPhi);
00203   hadInfo->Phi.setBin(hadSLHolder.SLPhiBins);
00204   // int flag = theTree->GetBranch("CastorShowerLibInfo")->Fill();
00205   // Loop on all leaves of this branch to fill Basket buffer.
00206   // The function returns the number of bytes committed to the memory basket.
00207   // If a write error occurs, the number of bytes returned is -1.
00208   // If no data are written, because e.g. the branch is disabled,
00209   // the number of bytes returned is 0.
00210   // if(flag==-1) {
00211   //    edm::LogInfo("CastorAnalyzer") << " WARNING: Error writing to Branch \"CastorShowerLibInfo\" \n" ; 
00212   // } else 
00213   // if(flag==0) {
00214   //    edm::LogInfo("CastorAnalyzer") << " WARNING: No data written to Branch \"CastorShowerLibInfo\" \n" ; 
00215   // }
00216 
00217   // Initialize "accounting" variables
00218 
00219   eventIndex = 0;
00220 
00221 }
00222 
00223 //=================================================================== per EVENT
00224 void CastorShowerLibraryMaker::update(const BeginOfEvent * evt) {
00225 
00226   eventIndex++;
00227   stepIndex = 0;
00228   InsideCastor = false;
00229   PrimaryMomentum.clear();
00230   PrimaryPosition.clear();
00231   int NAccepted =0;
00232 // reset the pointers to the shower objects
00233   SLShowerptr = NULL;
00234   MapOfSecondaries.clear();
00235   thePrims.clear();
00236   G4EventManager *e_mgr = G4EventManager::GetEventManager();
00237   if (IsSLReady()) {
00238       printSLstatus(-1,-1,-1);
00239       update((EndOfRun*)NULL);
00240       return;
00241   }
00242 
00243   thePrims = GetPrimary((*evt)());
00244   for(unsigned int i=0;i<thePrims.size();i++) {
00245      G4PrimaryParticle* thePrim = thePrims.at(i);
00246      int particleType = thePrim->GetPDGcode();
00247 
00248      std::string SLType("");
00249      if (particleType==11) {
00250         SLShowerptr = &emSLHolder;
00251         SLType = "Electromagnetic";
00252      }
00253      else {
00254         SLShowerptr = &hadSLHolder;
00255         SLType = "Hadronic";
00256      }
00257      double px=0., py=0., pz=0., pInit = 0., eta = 0., phi = 0.;
00258      GetKinematics(thePrim,px,py,pz,pInit,eta,phi);
00259      int ebin = FindEnergyBin(pInit);
00260      int etabin= FindEtaBin(eta);
00261      int phibin = FindPhiBin(phi);
00262      if (verbosity)
00263         std::cout << "\n========================================================================"
00264                   << "\nBeginOfEvent: E   : " << pInit <<"\t  bin : " << ebin
00265                   << "\n              Eta : " << eta   <<"\t  bin : " << etabin
00266                   << "\n              Phi : " << phi   <<"\t  bin : " << phibin
00267                   << "\n========================================================================"
00268                   << std::endl;
00269 
00270      if (ebin<0||etabin<0||phibin<0) continue;
00271      bool accept=false;
00272      if (!(SLacceptEvent(ebin,etabin,phibin))) {
00273 /*
00274 // To increase the chance of a particle arriving at CASTOR inside a not full bin,
00275 // check if there is available phase space in the neighboring bins
00276         unsigned int ebin_min = std::max(0,ebin-3);
00277         unsigned int eta_bin_min = std::max(0,etabin-2);
00278         unsigned int eta_bin_max = std::min(etabin,etabin+2);
00279         unsigned int phi_bin_min = std::max(0,phibin-2);
00280         unsigned int phi_bin_max = std::min(phibin,phibin+2);
00281         for(unsigned int i_ebin=ebin_min;i_ebin<=(unsigned int)ebin;i_ebin++) {
00282            for (unsigned int i_etabin=eta_bin_min;i_etabin<=eta_bin_max;i_etabin++) {
00283                for (unsigned int i_phibin=phi_bin_min;i_phibin<=phi_bin_max;i_phibin++) {
00284                    if (SLacceptEvent((int)i_ebin,(int)i_etabin,(int)i_phibin)) {accept=true;break;}
00285                }
00286                if (accept) break;
00287            }
00288            if (accept) break;
00289         }
00290 */
00291         if (!accept) edm::LogInfo("CastorShowerLibraryMaker") << "Event not accepted for ebin="
00292              << ebin<<",etabin="<<etabin<<",phibin="<<phibin<<std::endl;
00293      }
00294      else {
00295         accept=true;
00296      }
00297      if (accept) NAccepted++;
00298   }
00299   
00300   if (NAccepted==0) {
00301      const_cast<G4Event*>((*evt)())->SetEventAborted();
00302      const_cast<G4Event*>((*evt)())->KeepTheEvent((G4bool)false);
00303      e_mgr->AbortCurrentEvent();
00304   }
00305   SLShowerptr=NULL;
00306 //
00307   std::cout << "CastorShowerLibraryMaker: Processing Event Number: " << eventIndex << std::endl;
00308 }
00309 
00310 //=================================================================== per STEP
00311 void CastorShowerLibraryMaker::update(const G4Step * aStep) {
00312    static int CurrentPrimary = 0;
00313    G4Track *trk = aStep->GetTrack();
00314    if (trk->GetCurrentStepNumber()==1) {
00315       if (trk->GetParentID()==0) {
00316          CurrentPrimary = (int)trk->GetDynamicParticle()->GetPDGcode();
00317          if (CurrentPrimary==0) 
00318              SimG4Exception("CastorShowerLibraryMaker::update(G4Step) -> Primary particle undefined");
00319          InsideCastor=false;
00320 // Deactivate the physics process
00321          if (DeActivatePhysicsProcess) {
00322             G4ProcessManager *p_mgr = trk->GetDefinition()->GetProcessManager();
00323             G4ProcessVector *pvec = p_mgr->GetProcessList();
00324             for (int i = 0;i<pvec->size();i++) {
00325                 G4VProcess *proc = (*pvec)(i);
00326                 if (proc->GetProcessName()!="Transportation"&&
00327                     proc->GetProcessName()!="Decay") {
00328                     std::cout << "DeActivating process: " << proc->GetProcessName() << std::endl;
00329                     p_mgr->SetProcessActivation(proc,false);
00330                 }
00331             } 
00332          }
00333 // move track to z of CASTOR
00334          G4ThreeVector pos;
00335          pos.setZ(-14390);
00336          double t = abs((pos.z()-trk->GetPosition().z()))/trk->GetVelocity();
00337          double r = (pos.z()-trk->GetPosition().z())/trk->GetMomentum().cosTheta();
00338          pos.setX(r*sin(trk->GetMomentum().theta())*cos(trk->GetMomentum().phi())+trk->GetPosition().x());
00339          pos.setY(r*sin(trk->GetMomentum().theta())*sin(trk->GetMomentum().phi())+trk->GetPosition().y());
00340          trk->SetPosition(pos);
00341          trk->SetGlobalTime(trk->GetGlobalTime()+t);
00342          trk->AddTrackLength(r);
00343       }
00344       else if (!InsideCastor) {
00345          std::cout<<"CastorShowerLibraryMaker::update(G4Step) -> Killing spurious track" << std::endl;
00346          trk->SetTrackStatus(fKillTrackAndSecondaries);
00347          return;
00348       }
00349       MapOfSecondaries[CurrentPrimary].insert((int)trk->GetTrackID());
00350    }
00351 // Checks if primary already inside CASTOR
00352    std::string CurVolume = trk->GetVolume()->GetName();
00353    if (!InsideCastor&&(
00354        //CurVolume=="C3EF"||CurVolume=="C4EF"||CurVolume=="CAEL"||
00355        //CurVolume=="CAHL"||CurVolume=="C3HF"||CurVolume=="C4HF")) {
00356        //CurVolume=="CastorB"||
00357        CurVolume=="CAST")) {
00358        //CurVolume=="CAIR")) {
00359        InsideCastor=true;
00360 // Activate the physics process
00361        if (trk->GetParentID()==0&&DeActivatePhysicsProcess) {
00362           G4ProcessManager *p_mgr = trk->GetDefinition()->GetProcessManager();
00363           G4ProcessVector *pvec = p_mgr->GetProcessList();
00364           for (int i = 0;i<pvec->size();i++) {
00365               G4VProcess *proc = (*pvec)(i);
00366               if (proc->GetProcessName()!="Transportation"&&
00367                  proc->GetProcessName()!="Decay") {
00368                  std::cout << "  Activating process: " << proc->GetProcessName() << std::endl;
00369                  p_mgr->SetProcessActivation(proc,true);
00370               }
00371           }
00372        }
00373        //PrimaryMomentum[CurrentPrimary]=aStep->GetPreStepPoint()->GetMomentum();
00374 // check fiducial eta and phi
00375        if (trk->GetMomentum().phi()>MaxPhi||trk->GetMomentum().eta()>MaxEta) {
00376           trk->SetTrackStatus(fKillTrackAndSecondaries);
00377           InsideCastor=false;
00378           return;
00379        }
00380        PrimaryMomentum[CurrentPrimary]=trk->GetMomentum();
00381        PrimaryPosition[CurrentPrimary]=trk->GetPosition();
00382        KillSecondaries(aStep);
00383        return;
00384    } 
00385 // Kill the secondaries if they have been produced before entering castor
00386    if (CurrentPrimary!=0&&trk->GetParentID()==0&&!InsideCastor) {
00387       KillSecondaries(aStep);
00388       if (verbosity) {
00389          double pre_phi = aStep->GetPreStepPoint()->GetMomentum().phi();
00390          double cur_phi = trk->GetMomentum().phi();
00391          if (pre_phi!=cur_phi) {
00392             std::cout << "Primary track phi :  " << pre_phi << " changed in current step: "
00393                       << cur_phi << " by processes:" << std::endl;
00394             const G4VProcess *proc = aStep->GetPreStepPoint()->GetProcessDefinedStep();
00395             std::cout << "           " << proc->GetProcessName()
00396                       << "  In volume " << CurVolume << std::endl;
00397          }
00398       }
00399    }
00400 
00401 //==============================================
00402 /*
00403 */
00404 /*
00405   if(aStep->IsFirstStepInVolume()) { 
00406     edm::LogInfo("CastorShowerLibraryMaker") << "CastorShowerLibraryMaker::update(const G4Step * aStep):"
00407                                              << "\n IsFirstStepInVolume , " 
00408                                              << "time = " << aStep->GetTrack()->GetGlobalTime() ; 
00409   }
00410   stepIndex++;
00411 */
00412 }
00413 
00414 //================= End of EVENT ===============
00415 void CastorShowerLibraryMaker::update(const EndOfEvent * evt) {
00416 
00417 // check if the job is done!
00418   if ((*evt)()->IsAborted()) {
00419      std::cout << "\n========================================================================"
00420                << "\nEndOfEvent: EVENT ABORTED"
00421                << "\n========================================================================"
00422                << std::endl;
00423      return;
00424   }
00425   //DynamicRangeFlatRandomEGunProducer* pgun = edm::DynamicRangeFlatRandomEGunKernel::get_instance();
00426   //std::cout << pgun->EGunMaxE() << std::endl;
00427 /*
00428   std::cout << "Minimum energy in Particle Gun : " << pgun->EGunMinE() << "\n"
00429             << "Maximum energy in Particle Gun : " << pgun->EGunMaxE() << std::endl;
00430 */
00431   if (verbosity) 
00432      std::cout << "CastorShowerLibraryMaker: End of Event: " << eventIndex << std::endl;
00433 // Get the pointer to the primary particle
00434   if (thePrims.size() == 0) {
00435      edm::LogInfo("CastorShowerLibraryMaker") << "No valid primary particle found. Skipping event" << std::endl;
00436      return;
00437   }
00438   // access to the G4 hit collections 
00439   G4HCofThisEvent* allHC = (*evt)()->GetHCofThisEvent();
00440   int CAFIid = G4SDManager::GetSDMpointer()->GetCollectionID("CastorFI");
00441   CaloG4HitCollection* theCAFI = (CaloG4HitCollection*) allHC->GetHC(CAFIid);
00442   if (verbosity) edm::LogInfo("CastorShowerLibraryMaker") << " update(*evt) --> accessed all HC ";
00443   edm::LogInfo("CastorShowerLibraryMaker") << "Found "<<theCAFI->entries() << " hits in G4HitCollection";
00444   if (theCAFI->entries()== 0) {
00445      edm::LogInfo("CastorShowerLibraryMaker") << "\n Empty G4HitCollection";
00446      return;
00447   }
00448 
00449 // Loop over primaries
00450   int NEvtAccepted = 0;
00451   int NHitInEvent  = 0;
00452   for(unsigned int i=0;i<thePrims.size();i++) {
00453      G4PrimaryParticle* thePrim = thePrims.at(i);
00454      if (!thePrim) {
00455         edm::LogInfo("CastorShowerLibraryMaker") << "NULL Pointer to the primary" << std::endl;
00456         continue;
00457      }
00458 // Check primary particle type
00459      int particleType = thePrim->GetPDGcode();
00460 
00461 // set the pointer to the shower collection
00462      std::string SLType("");
00463      if (particleType==11) {
00464         SLShowerptr = &emSLHolder;
00465         SLType = "Electromagnetic";
00466      }
00467      else {
00468         SLShowerptr = &hadSLHolder;
00469         SLType = "Hadronic";
00470      }
00471      edm::LogInfo("CastorShowerLibraryMaker") << "\n Primary (thePrim) trackID is " << thePrim->GetTrackID() << "\n" ;
00472 
00473 // Obtain primary particle's initial momentum (pInit)
00474      double px=0., py=0., pz=0., pInit = 0., eta = 0., phi = 0.;
00475      GetKinematics(particleType,px,py,pz,pInit,eta,phi);
00476 // Check if current event falls into any bin
00477 // first: energy
00478      if (pInit==0) {
00479         edm::LogInfo("CastorShowerLibraryMaker") << "Primary did not hit CASTOR" << std::endl;
00480         continue;
00481      }
00482      int ebin = FindEnergyBin(pInit);
00483      int etabin= FindEtaBin(eta);
00484      int phibin = FindPhiBin(phi);
00485      std::cout << SLType << std::endl;
00486      printSLstatus(ebin,etabin,phibin);
00487      if (!SLacceptEvent(ebin,etabin,phibin)) {
00488         edm::LogInfo("CastorShowerLibraryMaker") << "Event not accepted for ebin="
00489              << ebin<<",etabin="<<etabin<<",phibin="<<phibin
00490              <<"("<< pInit <<","<<eta<<","<<phi<<")" <<std::endl;
00491         continue;
00492      }
00493 //
00494 // event passed. Fill the vector accordingly
00495 //  
00496 // Look for the Hit Collection 
00497      edm::LogInfo("CastorShowerLibraryMaker")
00498         << "\n CastorShowerLibraryMaker::update(EndOfEvent * evt) - event #" 
00499         << (*evt)()->GetEventID() ;
00500 
00501 /*
00502      std::cout << "Number of collections : " << allHC->GetNumberOfCollections() << std::endl;
00503      for(int ii = 0;ii<allHC->GetNumberOfCollections();ii++) 
00504         std::cout << "Name of collection " << ii << " : " << allHC->GetHC(ii)->GetName() << std::endl;
00505 */
00506 
00507      CastorShowerEvent* shower=NULL;
00508      int cur_evt_idx = SLShowerptr->nEvtInBinPhi.at(ebin).at(etabin).at(phibin);
00509      shower = &(SLShowerptr->SLCollection.at(ebin).at(etabin).at(phibin).at(cur_evt_idx));
00510 
00511 // Get Hit information
00512      if (FillShowerEvent(theCAFI,shower,particleType)) { 
00513 //  Primary particle information
00514 /*
00515         edm::LogInfo("CastorShowerLibraryMaker") << "New SL event: Primary = " << particleType
00516              << "; Energy = " << pInit << "; Eta = " << eta << "; Phi = " << phi
00517              << "; Nhits = " << shower->getNhit() << std::endl;
00518 */
00519         shower->setPrimE(pInit);
00520         shower->setPrimEta(eta);
00521         shower->setPrimPhi(phi);
00522         shower->setPrimX(PrimaryPosition[particleType].x());
00523         shower->setPrimY(PrimaryPosition[particleType].y());
00524         shower->setPrimZ(PrimaryPosition[particleType].z());
00525         SLnEvtInBinE(ebin)++;
00526         SLnEvtInBinEta(ebin,etabin)++;
00527         SLnEvtInBinPhi(ebin,etabin,phibin)++;
00528         NHitInEvent+=shower->getNhit();
00529         NEvtAccepted++;
00530       }
00531       else {shower->Clear();}
00532   }
00533 // Check for unassociated energy
00534      
00535   if (NEvtAccepted==int(thePrims.size())&&theCAFI->entries()!=NHitInEvent){
00536      std::cout << "WARNING: Inconsistent Number of Hits -> Hits in collection: "<< theCAFI->entries()
00537           << "   Hits in the showers: " << NHitInEvent << std::endl;
00538      double miss_energy=0;
00539      double tot_energy=0;
00540      GetMissingEnergy(theCAFI,miss_energy,tot_energy);
00541      if (miss_energy>0) {
00542         std::cout << "Total missing energy: " << miss_energy
00543                << " for an incident energy: " << tot_energy
00544                << std::endl;
00545      }
00546   }
00547          
00548 /*
00549   for (int i=emSLHolder.SLEnergyBins.size()-1;i>0;i--) {
00550       if (emSLHolder.nEvtInBinE.at(i)==(int)emSLHolder.nEvtPerBinE) {
00551          std::ostringstream out;
00552          out << emSLHolder.SLEnergyBins.at(i);
00553          cout << "Bin Limit: " << out.str() << std::endl;
00554          setenv("CASTOR_SL_PG_MAXE",out.str().c_str(),1);
00555        }
00556        break;
00557    }
00558 */
00559   //int iEvt = (*evt)()->GetEventID();
00560   //double xint;
00561 /*
00562   if (modf(log10(iEvt),&xint)==0) 
00563     std::cout << " CastorShowerLibraryMaker Event " << iEvt << std::endl;
00564 */
00565   // std::cout << std::endl << "===>>> Done writing user histograms " << std::endl;
00566 }
00567 
00568 //========================= End of RUN ======================
00569 void CastorShowerLibraryMaker::update(const EndOfRun * run)
00570 {
00571 // Fill the tree with the collected objects
00572   if (!IsSLReady()) SimG4Exception("\n\nShower Library  NOT READY.\n\n");
00573 
00574   unsigned int  ibine,ibineta,ibinphi,ievt; // indexes for em shower
00575   unsigned int  jbine,jbineta,jbinphi,jevt;// indexes for had shower
00576 
00577   ibine=ibineta=ibinphi=ievt=jbine=jbineta=jbinphi=jevt=0;
00578 
00579   int  nEvtInTree = 0;
00580   int  nEMevt  = emSLHolder.nEvtPerBinE*emSLHolder.SLEnergyBins.size();
00581   int  nHadevt = hadSLHolder.nEvtPerBinE*hadSLHolder.SLEnergyBins.size();
00582   int  maxEvtInTree=std::max(nEMevt,nHadevt);
00583 
00584   emInfo = &emSLHolder.SLInfo;
00585   hadInfo= &hadSLHolder.SLInfo;
00586 
00587   while(nEvtInTree<maxEvtInTree) {
00588     if (emShower) emShower->Clear();
00589     if (hadShower) hadShower->Clear();
00590     while(ibine<emSLHolder.SLEnergyBins.size()&&nEMevt>0){
00591       emShower = &(emSLHolder.SLCollection.at(ibine).at(ibineta).at(ibinphi).at(ievt));
00592       ievt++;
00593       if (ievt==emSLHolder.nEvtPerBinPhi) {ievt=0;ibinphi++;}
00594       if (ibinphi==emSLHolder.SLPhiBins.size()) {ibinphi=0;ibineta++;}
00595       if (ibineta==emSLHolder.SLEtaBins.size()) {ibineta=0;ibine++;}
00596       break;
00597     }
00598     while(jbine<hadSLHolder.SLEnergyBins.size()&&nHadevt>0){
00599       hadShower = &(hadSLHolder.SLCollection.at(jbine).at(jbineta).at(jbinphi).at(jevt));
00600       jevt++;
00601       if (jevt==hadSLHolder.nEvtPerBinPhi) {jevt=0;jbinphi++;}
00602       if (jbinphi==hadSLHolder.SLPhiBins.size()) {jbinphi=0;jbineta++;}
00603       if (jbineta==hadSLHolder.SLEtaBins.size()) {jbineta=0;jbine++;}
00604       break;
00605     }
00606     theTree->Fill();
00607     nEvtInTree++;
00608     if (nEvtInTree==1) {
00609        theTree->SetBranchStatus("emShowerLibInfo.",0);
00610        theTree->SetBranchStatus("hadShowerLibInfo.",0);
00611     }
00612   }
00613 // check if run is NULL and exit
00614   if (run==NULL) throw SimG4Exception("\n\nNumber of needed trigger events reached in CastorShowerLibraryMaker\n\n");
00615 }
00616 
00617 //============================================================
00618 void CastorShowerLibraryMaker::Finish() {
00619 
00620   // if (doNTcastorevent) {
00621 
00622   theFile->cd();
00623   theTree->Write("",TObject::kOverwrite);
00624   std::cout << "CastorShowerLibraryMaker: Ntuple event written" << std::endl;   
00625   theFile->Close();
00626   std::cout << "CastorShowerLibraryMaker: Event file closed" << std::endl;
00627 
00628   // Delete pointers to objects, now that TTree has been written and TFile closed
00629 //  delete      info; 
00630 //  delete  emShower;
00631 //  delete hadShower;
00632   // }
00633 } 
00634 int CastorShowerLibraryMaker::FindEnergyBin(double energy) {
00635   //
00636   // returns the integer index of the energy bin, taken from SLenergies vector
00637   // returns -1 if ouside valid range
00638   //
00639   if (!SLShowerptr) {
00640      edm::LogInfo("CastorShowerLibraryMaker") << "\n\nFindEnergyBin can be called only after BeginOfEvent\n\n";
00641      throw SimG4Exception("\n\nNULL Pointer to the shower library.\n\n");
00642   }
00643   const std::vector<double>& SLenergies = SLShowerptr->SLEnergyBins;
00644   if (energy >= SLenergies.back()) return SLenergies.size()-1;
00645 
00646   unsigned int i = 0;
00647   for(;i<SLenergies.size()-1;i++) 
00648     if (energy >= SLenergies.at(i) && energy < SLenergies.at(i+1)) return (int)i;
00649 
00650   // now i points to the last but 1 bin
00651   if (energy>=SLenergies.at(i)) return (int)i;
00652   // energy outside bin range
00653   return -1;
00654 }
00655 int CastorShowerLibraryMaker::FindEtaBin(double eta) {
00656   //
00657   // returns the integer index of the eta bin, taken from SLetas vector
00658   // returns -1 if ouside valid range
00659   //
00660   if (!SLShowerptr) {
00661      edm::LogInfo("CastorShowerLibraryMaker") << "\n\nFindEtaBin can be called only after BeginOfEvent\n\n";
00662      throw SimG4Exception("\n\nNULL Pointer to the shower library.\n\n");
00663   }
00664   const std::vector<double>& SLetas = SLShowerptr->SLEtaBins;
00665   if (eta>=SLetas.back()) return SLetas.size()-1;
00666   unsigned int i = 0;
00667   for(;i<SLetas.size()-1;i++)
00668      if (eta >= SLetas.at(i) && eta < SLetas.at(i+1)) return (int)i;
00669   // now i points to the last but 1 bin
00670   if (eta>=SLetas.at(i)) return (int)i;
00671   // eta outside bin range
00672   return -1;
00673 }
00674 int CastorShowerLibraryMaker::FindPhiBin(double phi) {
00675   //
00676   // returns the integer index of the phi bin, taken from SLphis vector
00677   // returns -1 if ouside valid range
00678   //
00679   // needs protection in case phi is outside range -pi,pi
00680   //
00681   if (!SLShowerptr) {
00682      edm::LogInfo("CastorShowerLibraryMaker") << "\n\nFindPhiBin can be called only after BeginOfEvent\n\n";
00683      throw SimG4Exception("\n\nNULL Pointer to the shower library.\n\n");
00684   }
00685   const std::vector<double>& SLphis = SLShowerptr->SLPhiBins;
00686   if (phi>=SLphis.back()) return SLphis.size()-1;
00687   unsigned int i = 0;
00688   for(;i<SLphis.size()-1;i++)
00689      if (phi >= SLphis.at(i) && phi < SLphis.at(i+1)) return (int)i;
00690   // now i points to the last but 1 bin
00691   if (phi>=SLphis.at(i)) return (int)i;
00692   // phi outside bin range
00693   return -1;
00694 }
00695 bool CastorShowerLibraryMaker::IsSLReady()
00696 {
00697 // at this point, the pointer to the shower library should be NULL
00698   if (SLShowerptr) {
00699      edm::LogInfo("CastorShowerLibraryMaker") << "\n\nIsSLReady must be called when a new event starts.\n\n";
00700      throw SimG4Exception("\n\nNOT NULL Pointer to the shower library.\n\n");
00701   }
00702 // it is enough to check if all the energy bin is filled
00703   if (DoEmSL) {
00704      SLShowerptr = &emSLHolder;
00705      for(unsigned int i=0;i<SLShowerptr->SLEnergyBins.size();i++) {
00706         if (!SLisEBinFilled(i)) {
00707            SLShowerptr=NULL;
00708            return false;
00709         }
00710      }
00711   }
00712   if (DoHadSL) {
00713      SLShowerptr = &hadSLHolder;
00714      for(unsigned int i=0;i<SLShowerptr->SLEnergyBins.size();i++) {
00715         if (!SLisEBinFilled(i)) {
00716            SLShowerptr=NULL;
00717            return false;
00718         }
00719      }
00720   }
00721   SLShowerptr=NULL;
00722   return true;
00723 }
00724 void CastorShowerLibraryMaker::GetKinematics(int thePrim,double& px, double& py, double& pz, double& pInit, double& eta, double& phi)
00725 {
00726     if (thePrim==0) return;
00727     if (PrimaryMomentum.find(thePrim)==PrimaryMomentum.end()) return;
00728     px = PrimaryMomentum[thePrim].x()/GeV;
00729     py = PrimaryMomentum[thePrim].y()/GeV;
00730     pz = PrimaryMomentum[thePrim].z()/GeV;
00731     pInit=PrimaryMomentum[thePrim].mag()/GeV;
00732     if (pInit==0) return;
00733     double costheta = pz/pInit;
00734     double theta = acos(std::min(std::max(costheta,double(-1.)),double(1.)));
00735     eta = -log(tan(theta/2.0));
00736     phi = (px==0 && py==0) ? 0 : atan2(py,px); // the recommended way of calculating phi
00737     phi = PrimaryMomentum[thePrim].phi();
00738 }
00739 void CastorShowerLibraryMaker::GetKinematics(G4PrimaryParticle* thePrim,double& px, double& py, double& pz, double& pInit, double& eta, double& phi)
00740 {
00741     px=py=pz=phi=eta=0.0;
00742     if (thePrim==0) return;
00743     px = thePrim->GetMomentum().x()/GeV;
00744     py = thePrim->GetMomentum().y()/GeV;
00745     pz = thePrim->GetMomentum().z()/GeV;
00746     pInit = thePrim->GetMomentum().mag()/GeV;
00747     //pInit = sqrt(pow(px,2.)+pow(py,2.)+pow(pz,2.));
00748     if (pInit==0) return;
00749     double costheta = pz/pInit;
00750     double theta = acos(std::min(std::max(costheta,double(-1.)),double(1.)));
00751     eta = -log(tan(theta/2.0));
00752     phi = (px==0 && py==0) ? 0 : atan2(py,px); // the recommended way of calculating phi
00753     phi = thePrim->GetMomentum().phi();
00754     //if (px!=0) phi=atan(py/px);
00755 }
00756 std::vector<G4PrimaryParticle*> CastorShowerLibraryMaker::GetPrimary(const G4Event * evt)
00757 {
00758   // Find Primary info:
00759   int trackID = 0;
00760   std::vector<G4PrimaryParticle*> thePrims;
00761   G4PrimaryParticle* thePrim = 0;
00762   G4int nvertex = evt->GetNumberOfPrimaryVertex();
00763   edm::LogInfo("CastorShowerLibraryMaker")  << "Event has " << nvertex << " vertex";   
00764   if (nvertex!=1) {
00765      edm::LogInfo("CastorShowerLibraryMaker") << "CastorShowerLibraryMaker::GetPrimary ERROR: no vertex";
00766      return thePrims;
00767   }
00768 
00769   for (int i = 0 ; i<nvertex; i++) {
00770     G4PrimaryVertex* avertex = evt->GetPrimaryVertex(i);
00771     if (avertex == 0) {
00772        edm::LogInfo("CastorShowerLibraryMaker")
00773           << "CastorShowerLibraryMaker::GetPrimary ERROR: pointer to vertex = 0";
00774        continue;
00775     }
00776     unsigned int npart = avertex->GetNumberOfParticle();
00777     if (npart!=NPGParticle) continue;
00778     for (unsigned int j=0;j<npart;j++) {
00779         unsigned int k = 0;
00780         //int test_pID = 0;
00781         trackID = j;
00782         thePrim=avertex->GetPrimary(trackID);
00783         while(k<NPGParticle&&PGParticleIDs.at(k++)!=thePrim->GetPDGcode()){;};
00784         if (k>NPGParticle) continue; // ID not found in the requested particles
00785         thePrims.push_back(thePrim);
00786     }
00787   }
00788   return thePrims;
00789 }
00790 void CastorShowerLibraryMaker::printSLstatus(int ebin,int etabin,int phibin)
00791 {
00792   if (!SLShowerptr) {
00793      edm::LogInfo("CastorShowerLibraryInfo") << "NULL shower pointer. Printing both";
00794      std::cout << "Electromagnetic" << std::endl;
00795      SLShowerptr = &emSLHolder;
00796      this->printSLstatus(ebin,etabin,phibin);
00797      std::cout << "Hadronic" << std::endl;
00798      SLShowerptr = &hadSLHolder;
00799      this->printSLstatus(ebin,etabin,phibin);
00800      SLShowerptr = NULL;
00801      return;
00802   }
00803   int nBinsE  =SLShowerptr->SLEnergyBins.size();
00804   int nBinsEta=SLShowerptr->SLEtaBins.size();
00805   int nBinsPhi=SLShowerptr->SLPhiBins.size();
00806   std::vector<double> SLenergies = SLShowerptr->SLEnergyBins;
00807   for(int n=0;n<11+(nBinsEta*nBinsPhi);n++) std::cout << "=";
00808   std::cout << std::endl;
00809   for(int i=0;i<nBinsE;i++) {
00810      std::cout << "E bin " << std::setw(6) << SLenergies.at(i) << " : ";
00811      for(int j=0;j<nBinsEta;j++) {
00812         for(int k=0;k<nBinsPhi;k++) {
00813            (SLisPhiBinFilled(i,j,k))?std::cout << "1":std::cout << "-";
00814         }
00815         if (j<nBinsEta-1) std::cout << "|";
00816      }
00817      std::cout << " (" << SLnEvtInBinE(i) << " events)";
00818      std::cout << std::endl;
00819      if (ebin!=i) continue;
00820      std::cout << "               ";
00821      for(int j=0;j<nBinsEta;j++) {
00822         for(int k=0;k<nBinsPhi;k++) {
00823            (ebin==i&&etabin==j&&phibin==k)?std::cout <<  "^":std::cout << " ";
00824         }
00825         if (j<nBinsEta-1) std::cout << " ";
00826      }
00827      std::cout << std::endl;
00828   }
00829   for(int n=0;n<11+(nBinsEta*nBinsPhi);n++) std::cout << "=";
00830   std::cout << std::endl;
00831 }
00832 bool CastorShowerLibraryMaker::SLacceptEvent(int ebin, int etabin, int phibin)
00833 {
00834      if (SLShowerptr==NULL) {
00835         edm::LogInfo("CastorShowerLibraryMaker::SLacceptEvent:") << "Error. NULL pointer to CastorShowerEvent";
00836         return false;
00837      }
00838      if (ebin<0||ebin>=int(SLShowerptr->SLEnergyBins.size())) return false;
00839      if (SLisEBinFilled(ebin)) return false;
00840 
00841      if (etabin<0||etabin>=int(SLShowerptr->SLEtaBins.size())) return false;
00842      if (SLisEtaBinFilled(ebin,etabin)) return false;
00843 
00844      if (phibin<0||phibin>=int(SLShowerptr->SLPhiBins.size())) return false;
00845      if (SLisPhiBinFilled(ebin,etabin,phibin)) return false;
00846      return true;
00847 }
00848 bool CastorShowerLibraryMaker::FillShowerEvent(CaloG4HitCollection* theCAFI, CastorShowerEvent* shower,int ipart)
00849 {
00850      unsigned int volumeID=0;
00851      double en_in_fi = 0.;
00852      //double totalEnergy = 0;
00853 
00854      int nentries = theCAFI->entries();
00855 
00856 // Compute Total Energy in CastorFI volume
00857 /*
00858      for(int ihit = 0; ihit < nentries; ihit++) {
00859        CaloG4Hit* aHit = (*theCAFI)[ihit];
00860        totalEnergy += aHit->getEnergyDeposit();
00861      }
00862 */
00863      if (!shower) {
00864         edm::LogInfo("CastorShowerLibraryMaker") << "Error. NULL pointer to CastorShowerEvent";
00865         return false;
00866      }
00867 
00868      CastorNumberingScheme *theCastorNumScheme = new CastorNumberingScheme();
00869 // Hit position
00870      math::XYZPoint entry;
00871      math::XYZPoint position;
00872      int nHits;
00873      nHits=0;
00874      for (int ihit = 0; ihit < nentries; ihit++) {
00875        CaloG4Hit* aHit  = (*theCAFI)[ihit];
00876        int hit_particleID = aHit->getTrackID();
00877        if (MapOfSecondaries[ipart].find(hit_particleID)==MapOfSecondaries[ipart].end()) {
00878           if (verbosity) edm::LogInfo("CastorShowerLibraryMaker")
00879               << "Skipping hit from trackID " << hit_particleID;
00880           continue;
00881        }
00882        volumeID         = aHit->getUnitID();
00883        double hitEnergy = aHit->getEnergyDeposit();
00884        en_in_fi        += aHit->getEnergyDeposit();
00885        float time       = aHit->getTimeSlice();
00886        int zside, sector, zmodule;
00887        theCastorNumScheme->unpackIndex(volumeID, zside, sector,zmodule);
00888        entry    = aHit->getEntry();
00889        position = aHit->getPosition();
00890        if (verbosity) edm::LogInfo("CastorShowerLibraryMaker")
00891           << "\n side , sector , module = " << zside << " , " 
00892           << sector << " , " << zmodule 
00893           << "\n nphotons = " << hitEnergy ; 
00894 
00895        if (verbosity) edm::LogInfo("CastorShowerLibraryMaker")
00896           << "\n packIndex = " 
00897           << theCastorNumScheme->packIndex(zside, sector,zmodule);
00898 
00899        if(verbosity&&time>100.) {
00900          edm::LogInfo("CastorShowerLibraryMaker")
00901             << "\n nentries = " << nentries 
00902             << "\n     time[" << ihit << "] = " << time
00903             << "\n  trackID[" << ihit << "] = " << aHit->getTrackID()
00904             << "\n volumeID[" << ihit << "] = " << volumeID 
00905             << "\n nphotons[" << ihit << "] = " << hitEnergy 
00906             << "\n side, sector, module  = " << zside <<", " << sector<<", " << zmodule
00907             << "\n packIndex " << theCastorNumScheme->packIndex(zside,sector,zmodule)
00908             << "\n X,Y,Z = " << entry.x() << ","<< entry.y() << "," << entry.z();
00909        }
00910        if (verbosity) edm::LogInfo("CastorShowerLibraryMaker") << "\n    Incident Energy = "  
00911                                                 << aHit->getIncidentEnergy() << " \n" ;
00912 
00913 //  CaloG4Hit information 
00914        shower->setDetID(volumeID);
00915        shower->setHitPosition(position);
00916        shower->setNphotons(hitEnergy);
00917        shower->setTime(time);
00918        nHits++;
00919      }
00920 // Write number of hits to CastorShowerEvent instance
00921      if (nHits==0) {
00922         edm::LogInfo("CastorShowerLibraryMaker") << "No hits found for this track (trackID=" << ipart << ")." << std::endl;
00923         if (theCastorNumScheme) delete theCastorNumScheme;
00924         return false;
00925      }
00926      shower->setNhit(nHits);
00927 
00928 // update the event counters
00929      if (theCastorNumScheme) delete theCastorNumScheme;
00930      return true;
00931 }
00932 int& CastorShowerLibraryMaker::SLnEvtInBinE(int ebin)
00933 {
00934    if (!SLShowerptr) {
00935       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLnEvtInBinE can be called only after BeginOfEvent\n\n";
00936       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00937    }
00938    return SLShowerptr->nEvtInBinE.at(ebin);
00939 }
00940 
00941 int& CastorShowerLibraryMaker::SLnEvtInBinEta(int ebin, int etabin)
00942 {
00943    if (!SLShowerptr) {
00944       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLnEvtInBinEta can be called only after BeginOfEvent\n\n";
00945       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00946    }
00947    return SLShowerptr->nEvtInBinEta.at(ebin).at(etabin);
00948 }
00949 
00950 int& CastorShowerLibraryMaker::SLnEvtInBinPhi(int ebin, int etabin, int phibin)
00951 {
00952    if (!SLShowerptr) {
00953       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLnEvtInBinPhi can be called only after BeginOfEvent\n\n";
00954       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00955    }
00956    return SLShowerptr->nEvtInBinPhi.at(ebin).at(etabin).at(phibin);
00957 }
00958 bool CastorShowerLibraryMaker::SLisEBinFilled(int ebin)
00959 {
00960    if (!SLShowerptr) {
00961       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLisEBinFilled can be called only after BeginOfEvent\n\n";
00962       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00963    }
00964    if (SLShowerptr->nEvtInBinE.at(ebin)<(int)SLShowerptr->nEvtPerBinE) return false;
00965    return true;
00966 }
00967 bool CastorShowerLibraryMaker::SLisEtaBinFilled(int ebin,int etabin)
00968 {
00969    if (!SLShowerptr) {
00970       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLisEtaBinFilled can be called only after BeginOfEvent\n\n";
00971       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00972    }
00973    if (SLShowerptr->nEvtInBinEta.at(ebin).at(etabin)<(int)SLShowerptr->nEvtPerBinEta) return false;
00974    return true;
00975 }
00976 bool CastorShowerLibraryMaker::SLisPhiBinFilled(int ebin,int etabin,int phibin)
00977 {
00978    if (!SLShowerptr) {
00979       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLisPhiBinFilled can be called only after BeginOfEvent\n\n";
00980       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00981    }
00982    if (SLShowerptr->nEvtInBinPhi.at(ebin).at(etabin).at(phibin)<(int)SLShowerptr->nEvtPerBinPhi) return false;
00983    return true;
00984 }
00985 void CastorShowerLibraryMaker::KillSecondaries(const G4Step * aStep) {
00986    G4TrackVector *p_sec = const_cast<G4TrackVector*>(aStep->GetSecondary());
00987    for(int i=0;i<int(p_sec->size());i++) {
00988       /*if (verbosity)*/ std::cout << "Killing track ID " << p_sec->at(i)->GetTrackID() << " and its secondaries"
00989           << " Produced by Process " << p_sec->at(i)->GetCreatorProcess()->GetProcessName()
00990           << " in the volume " << aStep->GetTrack()->GetVolume()->GetName()
00991           << std::endl;
00992       p_sec->at(i)->SetTrackStatus(fKillTrackAndSecondaries);
00993    }
00994 }
00995 
00996 void CastorShowerLibraryMaker::GetMissingEnergy(CaloG4HitCollection* theCAFI,double& miss_energy,double& tot_energy){
00997 // Get the total deposited energy and the one from hit not associated to a primary
00998      miss_energy = 0;
00999      tot_energy = 0;
01000      for (int ihit = 0; ihit < theCAFI->entries(); ihit++) {
01001          int id = (*theCAFI)[ihit]->getTrackID();
01002          tot_energy+=(*theCAFI)[ihit]->getEnergyDeposit();
01003          int hit_prim = 0;
01004          for(unsigned int i=0;i<thePrims.size();i++) {
01005             int particleType = thePrims.at(i)->GetPDGcode();
01006             if (MapOfSecondaries[particleType].find(id)!=MapOfSecondaries[particleType].end())
01007                hit_prim = particleType;
01008          }
01009          if (hit_prim==0) {
01010             std::cout << "Track ID " << id << " produced a hit which is not associated with a primary."
01011             << std::endl;
01012             miss_energy+=(*theCAFI)[ihit]->getEnergyDeposit();
01013          }
01014      }
01015 }