CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/SimG4CMS/ShowerLibraryProducer/src/CastorShowerLibraryMaker.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Forward
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 
00016 #include "SimG4Core/Notification/interface/SimG4Exception.h"
00017 #include "SimG4CMS/Calo/interface/CaloG4Hit.h"
00018 #include "SimG4CMS/Calo/interface/CaloG4HitCollection.h"
00019 #include "DataFormats/Math/interface/Point3D.h"
00020 
00021 #include "SimG4CMS/ShowerLibraryProducer/interface/CastorShowerLibraryMaker.h"
00022 #include "SimG4CMS/Forward/interface/CastorNumberingScheme.h"
00023 
00024 #include "SimDataFormats/CaloHit/interface/CastorShowerEvent.h"
00025 
00026 #include "TFile.h"
00027 #include <cmath>
00028 #include <iostream>
00029 #include <iomanip>
00030 
00031 CastorShowerLibraryMaker::CastorShowerLibraryMaker(const edm::ParameterSet &p) : 
00032                              NPGParticle(0),DoHadSL(false),DoEmSL(false),
00033                              emShower(NULL) , hadShower(NULL) {
00034 
00035   MapOfSecondaries.clear();
00036   hadInfo = NULL;
00037   emInfo  = NULL;
00038   edm::ParameterSet p_SLM   = p.getParameter<edm::ParameterSet>("CastorShowerLibraryMaker");
00039   verbosity                 = p_SLM.getParameter<int>("Verbosity");
00040   eventNtFileName           = p_SLM.getParameter<std::string>("EventNtupleFileName");
00041   hadSLHolder.nEvtPerBinPhi = p_SLM.getParameter<int>("nhadEvents");
00042   emSLHolder.nEvtPerBinPhi  = p_SLM.getParameter<int>("nemEvents");
00043   hadSLHolder.SLEnergyBins  = p_SLM.getParameter<std::vector<double> >("SLhadEnergyBins");
00044   hadSLHolder.SLEtaBins     = p_SLM.getParameter<std::vector<double> >("SLhadEtaBins");
00045   hadSLHolder.SLPhiBins     = p_SLM.getParameter<std::vector<double> >("SLhadPhiBins");
00046   emSLHolder.SLEnergyBins   = p_SLM.getParameter<std::vector<double> >("SLemEnergyBins");
00047   emSLHolder.SLEtaBins      = p_SLM.getParameter<std::vector<double> >("SLemEtaBins");
00048   emSLHolder.SLPhiBins      = p_SLM.getParameter<std::vector<double> >("SLemPhiBins");
00049   PGParticleIDs             = p_SLM.getParameter<std::vector<int> >("PartID");
00050   NPGParticle               = PGParticleIDs.size(); 
00051 //
00052   for(unsigned int i=0;i<PGParticleIDs.size();i++) {
00053      switch (int(fabs(PGParticleIDs.at(i)))) {
00054         case 11:
00055         case 22:
00056                DoEmSL = true;
00057                break;
00058         default:
00059                DoHadSL = true;
00060      }
00061   }
00062   hadSLHolder.nEvtPerBinEta = (hadSLHolder.nEvtPerBinPhi)*(hadSLHolder.SLPhiBins.size());
00063   hadSLHolder.nEvtPerBinE   = (hadSLHolder.nEvtPerBinEta)*(hadSLHolder.SLEtaBins.size());
00064   emSLHolder.nEvtPerBinEta = (emSLHolder.nEvtPerBinPhi)*(emSLHolder.SLPhiBins.size());
00065   emSLHolder.nEvtPerBinE   = (emSLHolder.nEvtPerBinEta)*(emSLHolder.SLEtaBins.size());
00066 
00067   std::cout << "============================================================================"<<std::endl;
00068   std::cout << "CastorShowerLibraryMaker:: Initialized as observer" << std::endl;
00069   std::cout << " Event Ntuple will be created" << std::endl;
00070   std::cout << " Event Ntuple file: " << eventNtFileName << std::endl;
00071   std::cout << " Number of Hadronic events in E   bins: " << hadSLHolder.nEvtPerBinE << std::endl;
00072   std::cout << " Number of Hadronic events in Eta bins: " << hadSLHolder.nEvtPerBinEta << std::endl;
00073   std::cout << " Number of Hadronic events in Phi bins: " << hadSLHolder.nEvtPerBinPhi << std::endl;
00074   std::cout << " Number of Electromag. events in E   bins: " << emSLHolder.nEvtPerBinE << std::endl;
00075   std::cout << " Number of Electromag. events in Eta bins: " << emSLHolder.nEvtPerBinEta << std::endl;
00076   std::cout << " Number of Electromag. events in Phi bins: " << emSLHolder.nEvtPerBinPhi << std::endl;
00077   std::cout << "============================================================================"<<std::endl;
00078   std::cout << std::endl;
00079 
00080   // Initializing the SL collections
00081   InitSLHolder(hadSLHolder);
00082   InitSLHolder(emSLHolder);
00083 }
00084 void CastorShowerLibraryMaker::InitSLHolder(ShowerLib& showerholder)
00085 {
00086   int nBinsE,nBinsEta,nBinsPhi,nEvtPerBinPhi;
00087   nBinsE      = showerholder.SLEnergyBins.size();
00088   nBinsEta    = showerholder.SLEtaBins.size();
00089   nBinsPhi    = showerholder.SLPhiBins.size();
00090   nEvtPerBinPhi=showerholder.nEvtPerBinPhi;
00091 //
00092 // Info
00093 //
00094   showerholder.SLInfo.Energy.setNEvts(nEvtPerBinPhi*nBinsPhi*nBinsEta*nBinsE);
00095   showerholder.SLInfo.Energy.setNEvtPerBin(nEvtPerBinPhi*nBinsPhi*nBinsEta);
00096   showerholder.SLInfo.Energy.setNBins(nBinsE);
00097   showerholder.SLInfo.Energy.setBin(showerholder.SLEnergyBins);
00098 //
00099   showerholder.SLInfo.Eta.setNEvts(nEvtPerBinPhi*nBinsPhi*nBinsEta);
00100   showerholder.SLInfo.Eta.setNEvtPerBin(nEvtPerBinPhi*nBinsPhi);
00101   showerholder.SLInfo.Eta.setNBins(nBinsEta);
00102   showerholder.SLInfo.Eta.setBin(showerholder.SLEtaBins);
00103 //
00104   showerholder.SLInfo.Phi.setNEvts(nEvtPerBinPhi*nBinsPhi);
00105   showerholder.SLInfo.Phi.setNEvtPerBin(nEvtPerBinPhi);
00106   showerholder.SLInfo.Phi.setNBins(nBinsPhi);
00107   showerholder.SLInfo.Phi.setBin(showerholder.SLPhiBins);
00108 //
00109 // Shower
00110   showerholder.SLCollection.assign(nBinsE,std::vector<std::vector<std::vector<CastorShowerEvent> > >());
00111   showerholder.nEvtInBinE.assign(nBinsE,0);
00112   showerholder.nEvtInBinEta.assign(nBinsE,std::vector<int>(0));
00113   showerholder.nEvtInBinPhi.assign(nBinsE,std::vector<std::vector<int> >());
00114   for(int i=0;i<nBinsE;i++) {
00115      showerholder.SLCollection.at(i).assign(nBinsEta,std::vector<std::vector<CastorShowerEvent> >());
00116      showerholder.nEvtInBinEta.at(i).assign(nBinsEta,0);
00117      showerholder.nEvtInBinPhi.at(i).assign(nBinsEta,std::vector<int>(0));
00118      for(int j=0;j<nBinsEta;j++) {
00119         showerholder.SLCollection.at(i).at(j).assign(nBinsPhi,std::vector<CastorShowerEvent>());
00120         showerholder.nEvtInBinPhi.at(i).at(j).assign(nBinsPhi,0);
00121         for(int k=0;k<nBinsPhi;k++) 
00122            showerholder.SLCollection.at(i).at(j).at(k).assign(nEvtPerBinPhi,CastorShowerEvent());
00123      }
00124   }
00125 }
00126 
00127 //===============================================================================================
00128 
00129 CastorShowerLibraryMaker::~CastorShowerLibraryMaker() {
00130 
00131   Finish();
00132 
00133   std::cout << "CastorShowerLibraryMaker: End of process" << std::endl;
00134 
00135 }
00136 
00137 //=================================================================== per EVENT
00138 void CastorShowerLibraryMaker::update(const BeginOfJob * job) {
00139 
00140   std::cout << " CastorShowerLibraryMaker::Starting new job " << std::endl;
00141 }
00142 
00143 //==================================================================== per RUN
00144 void CastorShowerLibraryMaker::update(const BeginOfRun * run) {
00145 
00146   std::cout << std::endl << "CastorShowerLibraryMaker: Starting Run"<< std::endl; 
00147 
00148   std::cout << "CastorShowerLibraryMaker: output event root file created" << std::endl;
00149 
00150   TString eventfilename = eventNtFileName;
00151   theFile = new TFile(eventfilename,"RECREATE");
00152   theTree = new TTree("CastorCherenkovPhotons", "Cherenkov Photons");
00153 
00154   Int_t split = 1;
00155   Int_t bsize = 64000;
00156   emInfo      = new CastorShowerLibraryInfo();
00157   emShower    = new CastorShowerEvent();
00158   hadInfo     = new CastorShowerLibraryInfo();
00159   hadShower   = new CastorShowerEvent();
00160   // Create Branchs
00161   theTree->Branch("emShowerLibInfo.", "CastorShowerLibraryInfo", &emInfo, bsize, split);
00162   theTree->Branch("emParticles.", "CastorShowerEvent", &emShower, bsize, split);
00163   theTree->Branch("hadShowerLibInfo.", "CastorShowerLibraryInfo", &hadInfo, bsize, split);
00164   theTree->Branch("hadParticles.", "CastorShowerEvent", &hadShower, bsize, split);
00165 
00166 // set the Info for electromagnetic shower
00167 // set the energy bins info
00168   emInfo->Energy.setNEvts(emSLHolder.nEvtPerBinE*emSLHolder.SLEnergyBins.size());
00169   emInfo->Energy.setNBins(emSLHolder.SLEnergyBins.size());
00170   emInfo->Energy.setNEvtPerBin(emSLHolder.nEvtPerBinE);
00171   emInfo->Energy.setBin(emSLHolder.SLEnergyBins);
00172 // set the eta bins info
00173   emInfo->Eta.setNEvts(emSLHolder.nEvtPerBinEta*emSLHolder.SLEtaBins.size());
00174   emInfo->Eta.setNBins(emSLHolder.SLEtaBins.size());
00175   emInfo->Eta.setNEvtPerBin(emSLHolder.nEvtPerBinEta);
00176   emInfo->Eta.setBin(emSLHolder.SLEtaBins);
00177 // set the eta bins info
00178   emInfo->Phi.setNEvts(emSLHolder.nEvtPerBinPhi*emSLHolder.SLPhiBins.size());
00179   emInfo->Phi.setNBins(emSLHolder.SLPhiBins.size());
00180   emInfo->Phi.setNEvtPerBin(emSLHolder.nEvtPerBinPhi);
00181   emInfo->Phi.setBin(emSLHolder.SLPhiBins);
00182 // The same for the hadronic shower
00183 // set the energy bins info
00184   hadInfo->Energy.setNEvts(hadSLHolder.nEvtPerBinE*hadSLHolder.SLEnergyBins.size());
00185   hadInfo->Energy.setNBins(hadSLHolder.SLEnergyBins.size());
00186   hadInfo->Energy.setNEvtPerBin(hadSLHolder.nEvtPerBinE);
00187   hadInfo->Energy.setBin(hadSLHolder.SLEnergyBins);
00188 // set the eta bins info
00189   hadInfo->Eta.setNEvts(hadSLHolder.nEvtPerBinEta*hadSLHolder.SLEtaBins.size());
00190   hadInfo->Eta.setNBins(hadSLHolder.SLEtaBins.size());
00191   hadInfo->Eta.setNEvtPerBin(hadSLHolder.nEvtPerBinEta);
00192   hadInfo->Eta.setBin(hadSLHolder.SLEtaBins);
00193 // set the eta bins info
00194   hadInfo->Phi.setNEvts(hadSLHolder.nEvtPerBinPhi*hadSLHolder.SLPhiBins.size());
00195   hadInfo->Phi.setNBins(hadSLHolder.SLPhiBins.size());
00196   hadInfo->Phi.setNEvtPerBin(hadSLHolder.nEvtPerBinPhi);
00197   hadInfo->Phi.setBin(hadSLHolder.SLPhiBins);
00198   // int flag = theTree->GetBranch("CastorShowerLibInfo")->Fill();
00199   // Loop on all leaves of this branch to fill Basket buffer.
00200   // The function returns the number of bytes committed to the memory basket.
00201   // If a write error occurs, the number of bytes returned is -1.
00202   // If no data are written, because e.g. the branch is disabled,
00203   // the number of bytes returned is 0.
00204   // if(flag==-1) {
00205   //    edm::LogInfo("CastorAnalyzer") << " WARNING: Error writing to Branch \"CastorShowerLibInfo\" \n" ; 
00206   // } else 
00207   // if(flag==0) {
00208   //    edm::LogInfo("CastorAnalyzer") << " WARNING: No data written to Branch \"CastorShowerLibInfo\" \n" ; 
00209   // }
00210 
00211   // Initialize "accounting" variables
00212 
00213   eventIndex = 0;
00214 
00215 }
00216 
00217 //=================================================================== per EVENT
00218 void CastorShowerLibraryMaker::update(const BeginOfEvent * evt) {
00219 
00220   eventIndex++;
00221   stepIndex = 0;
00222 // reset the pointers to the shower objects
00223   SLShowerptr = NULL;
00224   MapOfSecondaries.clear();
00225 //
00226   std::cout << "CastorShowerLibraryMaker: Processing Event Number: " << eventIndex << std::endl;
00227 }
00228 
00229 //=================================================================== per STEP
00230 void CastorShowerLibraryMaker::update(const G4Step * aStep) {
00231    static int CurrentPrimary = 0;
00232    G4Track *trk = aStep->GetTrack();
00233    if (trk->GetCurrentStepNumber()==1) {
00234       if (trk->GetParentID()==0) CurrentPrimary = trk->GetDynamicParticle()->GetPDGcode();
00235       if (CurrentPrimary==0) 
00236          SimG4Exception("CastorShowerLibraryMaker::update(G4Step) -> Primary particle undefined");
00237       MapOfSecondaries[CurrentPrimary].insert((int)trk->GetTrackID());
00238    }
00239 /*
00240   if(aStep->IsFirstStepInVolume()) { 
00241     edm::LogInfo("CastorShowerLibraryMaker") << "CastorShowerLibraryMaker::update(const G4Step * aStep):"
00242                                              << "\n IsFirstStepInVolume , " 
00243                                              << "time = " << aStep->GetTrack()->GetGlobalTime() ; 
00244   }
00245   stepIndex++;
00246 */
00247 }
00248 
00249 //================= End of EVENT ===============
00250 void CastorShowerLibraryMaker::update(const EndOfEvent * evt) {
00251 
00252 // check if the job is done!
00253   if (IsSLReady()) update((EndOfRun*)NULL);
00254 
00255   std::cout << "CastorShowerLibraryMaker: End of Event: " << eventIndex << std::endl;
00256 // Get the pointer to the primary particle
00257   std::vector<G4PrimaryParticle*> thePrims = GetPrimary(evt);
00258   if (thePrims.size() == 0) {
00259      edm::LogInfo("CastorShowerLibraryMaker") << "No valid primary particle found. Skipping event" << std::endl;
00260      return;
00261   }
00262 
00263 // Loop over primaries
00264   for(unsigned int i=0;i<thePrims.size();i++) {
00265      G4PrimaryParticle* thePrim = thePrims.at(i);
00266      if (!thePrim) {
00267         edm::LogInfo("CastorShowerLibraryMaker") << "NULL Pointer to the primary" << std::endl;
00268         continue;
00269      }
00270 // Check primary particle type
00271      int particleType = thePrim->GetPDGcode();
00272 
00273 // set the pointer to the shower collection
00274      std::string SLType("");
00275      if (particleType==11) {
00276         SLShowerptr = &emSLHolder;
00277         SLType = "Electromagnetic";
00278      }
00279      else {
00280         SLShowerptr = &hadSLHolder;
00281         SLType = "Hadronic";
00282      }
00283 
00284 // Obtain primary particle's initial momentum (pInit)
00285      double px=0., py=0., pz=0., pInit = 0., eta = 0., phi = 0.;
00286 
00287      GetKinematics(thePrim,px,py,pz,pInit,eta,phi);
00288      edm::LogInfo("CastorShowerLibraryMaker") << "\n Primary (thePrim) trackID is " << thePrim->GetTrackID() << "\n" ;
00289 
00290 // Check if current event falls into any bin
00291 // first: energy
00292      int ebin = FindEnergyBin(pInit);
00293      int etabin= FindEtaBin(eta);
00294      int phibin = FindPhiBin(phi);
00295      std::cout << SLType << std::endl;
00296      printSLstatus(ebin,etabin,phibin);
00297      if (!SLacceptEvent(ebin,etabin,phibin)) {
00298         edm::LogInfo("CastorShowerLibraryMaker") << "Event not accepted for ebin="
00299              << ebin<<",etabin="<<etabin<<",phibin="<<phibin<<std::endl;
00300         continue;
00301      }
00302 //
00303 // event passed. Fill the vector accordingly
00304 //  
00305 // Look for the Hit Collection 
00306      edm::LogInfo("CastorShowerLibraryMaker")
00307         << "\n CastorShowerLibraryMaker::update(EndOfEvent * evt) - event #" 
00308         << (*evt)()->GetEventID() ;
00309 
00310   // access to the G4 hit collections 
00311      G4HCofThisEvent* allHC = (*evt)()->GetHCofThisEvent();
00312 /*
00313      std::cout << "Number of collections : " << allHC->GetNumberOfCollections() << std::endl;
00314      for(int ii = 0;ii<allHC->GetNumberOfCollections();ii++) 
00315         std::cout << "Name of collection " << ii << " : " << allHC->GetHC(ii)->GetName() << std::endl;
00316 */
00317      edm::LogInfo("CastorShowerLibraryMaker") << " update(*evt) --> accessed all HC ";
00318 
00319      CastorShowerEvent* shower=NULL;
00320      int cur_evt_idx = SLShowerptr->nEvtInBinPhi.at(ebin).at(etabin).at(phibin);
00321      shower = &(SLShowerptr->SLCollection.at(ebin).at(etabin).at(phibin).at(cur_evt_idx));
00322 
00323 // Get Hit information
00324      if (FillShowerEvent(allHC,shower,particleType)) { 
00325 //  Primary particle information
00326         shower->setPrimE(pInit);
00327         shower->setPrimEta(eta);
00328         shower->setPrimPhi(phi);
00329         //shower->setPrimX(entry.x());
00330         //shower->setPrimY(entry.y());
00331         //shower->setPrimZ(entry.z());
00332         SLnEvtInBinE(ebin)++;
00333         SLnEvtInBinEta(ebin,etabin)++;
00334         SLnEvtInBinPhi(ebin,etabin,phibin)++;
00335       }
00336   }
00337 
00338   //int iEvt = (*evt)()->GetEventID();
00339   //double xint;
00340 /*
00341   if (modf(log10(iEvt),&xint)==0) 
00342     std::cout << " CastorShowerLibraryMaker Event " << iEvt << std::endl;
00343 */
00344   // std::cout << std::endl << "===>>> Done writing user histograms " << std::endl;
00345 }
00346 
00347 //========================= End of RUN ======================
00348 void CastorShowerLibraryMaker::update(const EndOfRun * run)
00349 {
00350 // Fill the tree with the collected objects
00351   if (!IsSLReady()) SimG4Exception("\n\nShower Library  NOT READY.\n\n");
00352 
00353   unsigned int  ibine,ibineta,ibinphi,ievt; // indexes for em shower
00354   unsigned int  jbine,jbineta,jbinphi,jevt;// indexes for had shower
00355 
00356   ibine=ibineta=ibinphi=ievt=jbine=jbineta=jbinphi=jevt=0;
00357 
00358   int  nEvtInTree = 0;
00359   int  maxEvtInTree=std::max(hadSLHolder.nEvtPerBinE*hadSLHolder.SLEnergyBins.size(),
00360                              emSLHolder.nEvtPerBinE*emSLHolder.SLEnergyBins.size());
00361 
00362   emInfo = &emSLHolder.SLInfo;
00363   hadInfo= &hadSLHolder.SLInfo;
00364 
00365   while(nEvtInTree<maxEvtInTree) {
00366     if (emShower) emShower->Clear();
00367     if (hadShower) hadShower->Clear();
00368     while(ibine<emSLHolder.SLEnergyBins.size()){
00369       emShower = &(emSLHolder.SLCollection.at(ibine).at(ibineta).at(ibinphi).at(ievt));
00370       ievt++;
00371       if (ievt==emSLHolder.nEvtPerBinPhi) {ievt=0;ibinphi++;}
00372       if (ibinphi==emSLHolder.SLPhiBins.size()) {ibinphi=0;ibineta++;}
00373       if (ibineta==emSLHolder.SLEtaBins.size()) {ibineta=0;ibine++;}
00374       break;
00375     }
00376     while(jbine<hadSLHolder.SLEnergyBins.size()){
00377       hadShower = &(hadSLHolder.SLCollection.at(jbine).at(jbineta).at(jbinphi).at(jevt));
00378       jevt++;
00379       if (jevt==hadSLHolder.nEvtPerBinPhi) {jevt=0;jbinphi++;}
00380       if (jbinphi==hadSLHolder.SLPhiBins.size()) {jbinphi=0;jbineta++;}
00381       if (jbineta==hadSLHolder.SLEtaBins.size()) {jbineta=0;jbine++;}
00382       break;
00383     }
00384     theTree->Fill();
00385     nEvtInTree++;
00386     if (nEvtInTree==1) {
00387        theTree->SetBranchStatus("emShowerLibInfo.",0);
00388        theTree->SetBranchStatus("hadShowerLibInfo.",0);
00389     }
00390   }
00391 // check if run is NULL and exit
00392   if (run==NULL) throw SimG4Exception("\n\nNumber of needed trigger events reached in CastorShowerLibraryMaker\n\n");
00393 }
00394 
00395 //============================================================
00396 void CastorShowerLibraryMaker::Finish() {
00397 
00398   // if (doNTcastorevent) {
00399 
00400   theFile->cd();
00401   theTree->Write("",TObject::kOverwrite);
00402   std::cout << "CastorShowerLibraryMaker: Ntuple event written" << std::endl;   
00403   theFile->Close();
00404   std::cout << "CastorShowerLibraryMaker: Event file closed" << std::endl;
00405 
00406   // Delete pointers to objects, now that TTree has been written and TFile closed
00407 //  delete      info; 
00408 //  delete  emShower;
00409 //  delete hadShower;
00410   // }
00411 } 
00412 int CastorShowerLibraryMaker::FindEnergyBin(double energy) {
00413   //
00414   // returns the integer index of the energy bin, taken from SLenergies vector
00415   // returns -1 if ouside valid range
00416   //
00417   if (!SLShowerptr) {
00418      edm::LogInfo("CastorShowerLibraryMaker") << "\n\nFindEnergyBin can be called only after BeginOfEvent\n\n";
00419      throw SimG4Exception("\n\nNULL Pointer to the shower library.\n\n");
00420   }
00421   const std::vector<double>& SLenergies = SLShowerptr->SLEnergyBins;
00422   if (energy >= SLenergies.back()) return SLenergies.size()-1;
00423 
00424   unsigned int i = 0;
00425   for(;i<SLenergies.size()-1;i++) 
00426     if (energy >= SLenergies.at(i) && energy < SLenergies.at(i+1)) return (int)i;
00427 
00428   // now i points to the last but 1 bin
00429   if (energy>=SLenergies.at(i)) return (int)i;
00430   // energy outside bin range
00431   return -1;
00432 }
00433 int CastorShowerLibraryMaker::FindEtaBin(double eta) {
00434   //
00435   // returns the integer index of the eta bin, taken from SLetas vector
00436   // returns -1 if ouside valid range
00437   //
00438   if (!SLShowerptr) {
00439      edm::LogInfo("CastorShowerLibraryMaker") << "\n\nFindEtaBin can be called only after BeginOfEvent\n\n";
00440      throw SimG4Exception("\n\nNULL Pointer to the shower library.\n\n");
00441   }
00442   const std::vector<double>& SLetas = SLShowerptr->SLEtaBins;
00443   if (eta>=SLetas.back()) return SLetas.size()-1;
00444   unsigned int i = 0;
00445   for(;i<SLetas.size()-1;i++)
00446      if (eta >= SLetas.at(i) && eta < SLetas.at(i+1)) return (int)i;
00447   // now i points to the last but 1 bin
00448   if (eta>=SLetas.at(i)) return (int)i;
00449   // eta outside bin range
00450   return -1;
00451 }
00452 int CastorShowerLibraryMaker::FindPhiBin(double phi) {
00453   //
00454   // returns the integer index of the phi bin, taken from SLphis vector
00455   // returns -1 if ouside valid range
00456   //
00457   // needs protection in case phi is outside range -pi,pi
00458   //
00459   if (!SLShowerptr) {
00460      edm::LogInfo("CastorShowerLibraryMaker") << "\n\nFindPhiBin can be called only after BeginOfEvent\n\n";
00461      throw SimG4Exception("\n\nNULL Pointer to the shower library.\n\n");
00462   }
00463   const std::vector<double>& SLphis = SLShowerptr->SLPhiBins;
00464   if (phi>=SLphis.back()) return SLphis.size()-1;
00465   unsigned int i = 0;
00466   for(;i<SLphis.size()-1;i++)
00467      if (phi >= SLphis.at(i) && phi < SLphis.at(i+1)) return (int)i;
00468   // now i points to the last but 1 bin
00469   if (phi>=SLphis.at(i)) return (int)i;
00470   // phi outside bin range
00471   return -1;
00472 }
00473 bool CastorShowerLibraryMaker::IsSLReady()
00474 {
00475 // at this point, the pointer to the shower library should be NULL
00476   if (SLShowerptr) {
00477      edm::LogInfo("CastorShowerLibraryMaker") << "\n\nIsSLReady must be called when a new event starts.\n\n";
00478      throw SimG4Exception("\n\nNOT NULL Pointer to the shower library.\n\n");
00479   }
00480 // it is enough to check if all the energy bin is filled
00481   if (DoEmSL) {
00482      SLShowerptr = &emSLHolder;
00483      for(unsigned int i=0;i<SLShowerptr->SLEnergyBins.size();i++) {
00484         if (!SLisEBinFilled(i)) {
00485            SLShowerptr=NULL;
00486            return false;
00487         }
00488      }
00489   }
00490   if (DoHadSL) {
00491      SLShowerptr = &hadSLHolder;
00492      for(unsigned int i=0;i<SLShowerptr->SLEnergyBins.size();i++) {
00493         if (!SLisEBinFilled(i)) {
00494            SLShowerptr=NULL;
00495            return false;
00496         }
00497      }
00498   }
00499   SLShowerptr=NULL;
00500   return true;
00501 }
00502 void CastorShowerLibraryMaker::GetKinematics(G4PrimaryParticle* thePrim,double& px, double& py, double& pz, double& pInit, double& eta, double& phi)
00503 {
00504     px=py=pz=phi=eta=0.0;
00505     if (thePrim==0) return;
00506     px = thePrim->GetPx()/GeV;
00507     py = thePrim->GetPy()/GeV;
00508     pz = thePrim->GetPz()/GeV;
00509     pInit = sqrt(pow(px,2.)+pow(py,2.)+pow(pz,2.));
00510     if (pInit==0) {
00511       std::cout << "CastorShowerLibraryMaker::GetKinematics: ERROR: primary has p=0 " << std::endl;
00512       return;
00513     }
00514     double costheta = pz/pInit;
00515     double theta = acos(std::min(std::max(costheta,double(-1.)),double(1.)));
00516     eta = -log(tan(theta/2.0));
00517     phi = (px==0 && py==0) ? 0 : atan2(py,px); // the recommended way of calculating phi
00518     //if (px!=0) phi=atan(py/px);
00519 }
00520 std::vector<G4PrimaryParticle*> CastorShowerLibraryMaker::GetPrimary(const EndOfEvent * evt)
00521 {
00522   // Find Primary info:
00523   int trackID = 0;
00524   std::vector<G4PrimaryParticle*> thePrims;
00525   G4PrimaryParticle* thePrim = 0;
00526   G4int nvertex = (*evt)()->GetNumberOfPrimaryVertex();
00527   edm::LogInfo("CastorShowerLibraryMaker")  << "Event has " << nvertex << " vertex";   
00528   if (nvertex!=1) {
00529      edm::LogInfo("CastorShowerLibraryMaker") << "CastorShowerLibraryMaker::GetPrimary ERROR: no vertex";
00530      return thePrims;
00531   }
00532 
00533   for (int i = 0 ; i<nvertex; i++) {
00534     G4PrimaryVertex* avertex = (*evt)()->GetPrimaryVertex(i);
00535     if (avertex == 0) {
00536        edm::LogInfo("CastorShowerLibraryMaker")
00537           << "CastorShowerLibraryMaker::GetPrimary ERROR: pointer to vertex = 0";
00538        continue;
00539     }
00540     unsigned int npart = avertex->GetNumberOfParticle();
00541     if (npart!=NPGParticle) continue;
00542     for (unsigned int j=0;j<npart;j++) {
00543         unsigned int k = 0;
00544         //int test_pID = 0;
00545         trackID = j;
00546         thePrim=avertex->GetPrimary(trackID);
00547         while(k<NPGParticle&&PGParticleIDs.at(k++)!=thePrim->GetPDGcode()){;};
00548         if (k>NPGParticle) continue; // ID not found in the requested particles
00549         thePrims.push_back(thePrim);
00550     }
00551   }
00552   return thePrims;
00553 }
00554 void CastorShowerLibraryMaker::printSLstatus(int ebin,int etabin,int phibin)
00555 {
00556   int nBinsE  =SLShowerptr->SLEnergyBins.size();
00557   int nBinsEta=SLShowerptr->SLEtaBins.size();
00558   int nBinsPhi=SLShowerptr->SLPhiBins.size();
00559   std::vector<double> SLenergies = SLShowerptr->SLEnergyBins;
00560   for(int n=0;n<11+(nBinsEta*nBinsPhi);n++) std::cout << "=";
00561   std::cout << std::endl;
00562   for(int i=0;i<nBinsE;i++) {
00563      std::cout << "E bin " << SLenergies.at(i) << " : ";
00564      for(int j=0;j<nBinsEta;j++) {
00565         for(int k=0;k<nBinsPhi;k++) {
00566            (SLisPhiBinFilled(i,j,k))?std::cout << "1":std::cout << "-";
00567         }
00568         if (j<nBinsEta-1) std::cout << "|";
00569      }
00570      std::cout << " (" << SLnEvtInBinE(i) << " events)";
00571      std::cout << std::endl;
00572      if (ebin!=i) continue;
00573      std::cout << "          ";
00574      for(int j=0;j<nBinsEta;j++) {
00575         for(int k=0;k<nBinsPhi;k++) {
00576            (ebin==i&&etabin==j&&phibin==k)?std::cout <<  "^":std::cout << " ";
00577         }
00578         if (j<nBinsEta-1) std::cout << " ";
00579      }
00580      std::cout << std::endl;
00581   }
00582   for(int n=0;n<11+(nBinsEta*nBinsPhi);n++) std::cout << "=";
00583   std::cout << std::endl;
00584 }
00585 bool CastorShowerLibraryMaker::SLacceptEvent(int ebin, int etabin, int phibin)
00586 {
00587      if (ebin<0) return false;
00588      if (SLisEBinFilled(ebin)) return false;
00589 
00590      if (etabin<0) return false;
00591      if (SLisEtaBinFilled(ebin,etabin)) return false;
00592 
00593      if (phibin<0) return false;
00594      if (SLisPhiBinFilled(ebin,etabin,phibin)) return false;
00595      return true;
00596 }
00597 bool CastorShowerLibraryMaker::FillShowerEvent(G4HCofThisEvent* allHC, CastorShowerEvent* shower,int ipart)
00598 {
00599   //   int CAFIid = G4SDManager::GetSDMpointer()->GetCollectionID("CastorPL"); // Trick to get CASTPL
00600      int CAFIid = G4SDManager::GetSDMpointer()->GetCollectionID("CastorFI");
00601 
00602      CaloG4HitCollection* theCAFI = (CaloG4HitCollection*) allHC->GetHC(CAFIid);
00603 
00604      CastorNumberingScheme *theCastorNumScheme = new CastorNumberingScheme();
00605 
00606      unsigned int volumeID=0;
00607      double en_in_fi = 0.;
00608      //double totalEnergy = 0;
00609 
00610      int nentries = theCAFI->entries();
00611      edm::LogInfo("CastorShowerLibraryMaker") << "Found "<<nentries << " hits in G4HitCollection";
00612      if (nentries == 0) {
00613        edm::LogInfo("CastorShowerLibraryMaker") << "\n Empty G4HitCollection";
00614        return false;
00615      }
00616 
00617 // Compute Total Energy in CastorFI volume
00618 /*
00619      for(int ihit = 0; ihit < nentries; ihit++) {
00620        CaloG4Hit* aHit = (*theCAFI)[ihit];
00621        totalEnergy += aHit->getEnergyDeposit();
00622      }
00623 */
00624      if (!shower) {
00625         edm::LogInfo("CastorShowerLibraryMaker") << "Error. NULL pointer to CastorShowerEvent";
00626         return false;
00627      }
00628 
00629 // Hit position
00630      math::XYZPoint entry;
00631      math::XYZPoint position;
00632      int nHits;
00633      nHits=0;
00634      for (int ihit = 0; ihit < nentries; ihit++) {
00635        CaloG4Hit* aHit  = (*theCAFI)[ihit];
00636        int hit_particleID = aHit->getTrackID();
00637        if (MapOfSecondaries[ipart].find(hit_particleID)==MapOfSecondaries[ipart].end()) {
00638           if (verbosity) edm::LogInfo("CastorShowerLibraryMaker") << "Skipping hit from trackID " << hit_particleID;
00639           continue;
00640        }
00641        volumeID         = aHit->getUnitID();
00642        double hitEnergy = aHit->getEnergyDeposit();
00643        en_in_fi        += aHit->getEnergyDeposit();
00644        float time       = aHit->getTimeSlice();
00645        int zside, sector, zmodule;
00646        theCastorNumScheme->unpackIndex(volumeID, zside, sector,zmodule);
00647        entry    = aHit->getEntry();
00648        position = aHit->getPosition();
00649        if (verbosity) edm::LogInfo("CastorShowerLibraryMaker")
00650           << "\n side , sector , module = " << zside << " , " 
00651           << sector << " , " << zmodule 
00652           << "\n nphotons = " << hitEnergy ; 
00653 
00654        if (verbosity) edm::LogInfo("CastorShowerLibraryMaker")
00655           << "\n packIndex = " 
00656           << theCastorNumScheme->packIndex(zside, sector,zmodule);
00657 
00658        if(time>100.) {
00659          edm::LogInfo("CastorShowerLibraryMaker")
00660             << "\n nentries = " << nentries 
00661             << "\n     time[" << ihit << "] = " << time
00662             << "\n  trackID[" << ihit << "] = " << aHit->getTrackID()
00663             << "\n volumeID[" << ihit << "] = " << volumeID 
00664             << "\n nphotons[" << ihit << "] = " << hitEnergy 
00665             << "\n side, sector, module  = " << zside <<", " << sector<<", " << zmodule
00666             << "\n packIndex " << theCastorNumScheme->packIndex(zside,sector,zmodule)
00667             << "\n X,Y,Z = " << entry.x() << ","<< entry.y() << "," << entry.z();
00668        }
00669        if(nHits==0) {
00670 /*
00671          edm::LogInfo("CastorShowerLibraryMaker")
00672             << "\n    entry(x,y,z) = (" << entry.x() << "," 
00673             << entry.y() << "," << entry.z() << ") \n" 
00674             << "\n    entry(eta,phi,z) = (" << entry.eta() << "," 
00675             << entry.phi() << "," << entry.z() << ") \n" 
00676             << "\n    eta , phi = "  
00677             << eta << " , " << phi << " \n" ;
00678 */
00679           shower->setPrimX(entry.x());
00680           shower->setPrimY(entry.y());
00681           shower->setPrimZ(entry.z());
00682        }
00683        if (verbosity) edm::LogInfo("CastorShowerLibraryMaker") << "\n    Incident Energy = "  
00684                                                 << aHit->getIncidentEnergy() << " \n" ;
00685 
00686 
00687 //  CaloG4Hit information 
00688        shower->setDetID(volumeID);
00689        shower->setHitPosition(position);
00690        shower->setNphotons(hitEnergy);
00691        shower->setTime(time);
00692        nHits++;
00693      }
00694 // Write number of hits to CastorShowerEvent instance
00695      if (nHits==0) {
00696         edm::LogInfo("CastorShowerLibraryMaker") << "No hits found for this track (trackID=" << ipart << ")." << std::endl;
00697         return false;
00698      }
00699      shower->setNhit(nHits);
00700 
00701      edm::LogInfo("CastorShowerLibraryMaker") << "Filling the SL vector with new element ("<<nHits<<" hits)";
00702 // update the event counters
00703      return true;
00704 }
00705 int& CastorShowerLibraryMaker::SLnEvtInBinE(int ebin)
00706 {
00707    if (!SLShowerptr) {
00708       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLnEvtInBinE can be called only after BeginOfEvent\n\n";
00709       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00710    }
00711    return SLShowerptr->nEvtInBinE.at(ebin);
00712 }
00713 
00714 int& CastorShowerLibraryMaker::SLnEvtInBinEta(int ebin, int etabin)
00715 {
00716    if (!SLShowerptr) {
00717       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLnEvtInBinEta can be called only after BeginOfEvent\n\n";
00718       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00719    }
00720    return SLShowerptr->nEvtInBinEta.at(ebin).at(etabin);
00721 }
00722 
00723 int& CastorShowerLibraryMaker::SLnEvtInBinPhi(int ebin, int etabin, int phibin)
00724 {
00725    if (!SLShowerptr) {
00726       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLnEvtInBinPhi can be called only after BeginOfEvent\n\n";
00727       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00728    }
00729    return SLShowerptr->nEvtInBinPhi.at(ebin).at(etabin).at(phibin);
00730 }
00731 bool CastorShowerLibraryMaker::SLisEBinFilled(int ebin)
00732 {
00733    if (!SLShowerptr) {
00734       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLisEBinFilled can be called only after BeginOfEvent\n\n";
00735       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00736    }
00737    if (SLShowerptr->nEvtInBinE.at(ebin)<(int)SLShowerptr->nEvtPerBinE) return false;
00738    return true;
00739 }
00740 bool CastorShowerLibraryMaker::SLisEtaBinFilled(int ebin,int etabin)
00741 {
00742    if (!SLShowerptr) {
00743       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLisEtaBinFilled can be called only after BeginOfEvent\n\n";
00744       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00745    }
00746    if (SLShowerptr->nEvtInBinEta.at(ebin).at(etabin)<(int)SLShowerptr->nEvtPerBinEta) return false;
00747    return true;
00748 }
00749 bool CastorShowerLibraryMaker::SLisPhiBinFilled(int ebin,int etabin,int phibin)
00750 {
00751    if (!SLShowerptr) {
00752       edm::LogInfo("CastorShowerLibraryMaker") << "\n\nSLisPhiBinFilled can be called only after BeginOfEvent\n\n";
00753       throw SimG4Exception("\n\nNULL Pointer to the shower library.");
00754    }
00755    if (SLShowerptr->nEvtInBinPhi.at(ebin).at(etabin).at(phibin)<(int)SLShowerptr->nEvtPerBinPhi) return false;
00756    return true;
00757 }