CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/FastSimulation/Calorimetry/src/CalorimetryManager.cc

Go to the documentation of this file.
00001 //Framework headers 
00002 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 
00005 // Fast Simulation headers
00006 #include "FastSimulation/Calorimetry/interface/CalorimetryManager.h"
00007 #include "FastSimulation/Event/interface/FSimEvent.h"
00008 #include "FastSimulation/Event/interface/FSimTrack.h"
00009 #include "FastSimulation/ShowerDevelopment/interface/EMECALShowerParametrization.h"
00010 #include "FastSimulation/ShowerDevelopment/interface/EMShower.h"
00011 #include "FastSimulation/ShowerDevelopment/interface/HDShowerParametrization.h"
00012 #include "FastSimulation/ShowerDevelopment/interface/HDShower.h"
00013 #include "FastSimulation/ShowerDevelopment/interface/HFShower.h"
00014 #include "FastSimulation/ShowerDevelopment/interface/HDRShower.h"
00015 #include "FastSimulation/ShowerDevelopment/interface/HSParameters.h"
00016 #include "FastSimulation/CaloGeometryTools/interface/CaloGeometryHelper.h"
00017 #include "FastSimulation/CaloHitMakers/interface/EcalHitMaker.h"
00018 #include "FastSimulation/CaloHitMakers/interface/HcalHitMaker.h"
00019 #include "FastSimulation/CaloHitMakers/interface/PreshowerHitMaker.h"
00020 //#include "FastSimulation/Utilities/interface/Histos.h"
00021 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00022 #include "FastSimulation/Utilities/interface/GammaFunctionGenerator.h"
00023 #include "FastSimulation/Utilities/interface/LandauFluctuationGenerator.h"
00024 #include "DataFormats/HcalDetId/interface/HcalSubdetector.h"
00025 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"  
00026 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
00027 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00028 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00029 #include "FastSimulation/Event/interface/FSimTrackEqual.h"
00030 // New headers for Muon Mip Simulation
00031 #include "FastSimulation/MaterialEffects/interface/MaterialEffects.h"
00032 #include "FastSimulation/MaterialEffects/interface/EnergyLossSimulator.h"
00033 // Muon Brem
00034 #include "FastSimulation/MaterialEffects/interface/MuonBremsstrahlungSimulator.h"
00035 
00036 //Gflash Hadronic Model
00037 #include "SimGeneral/GFlash/interface/GflashHadronShowerProfile.h"
00038 #include "SimGeneral/GFlash/interface/GflashPiKShowerProfile.h"
00039 #include "SimGeneral/GFlash/interface/GflashProtonShowerProfile.h"
00040 #include "SimGeneral/GFlash/interface/GflashAntiProtonShowerProfile.h"
00041 #include "SimGeneral/GFlash/interface/GflashTrajectoryPoint.h"
00042 #include "SimGeneral/GFlash/interface/GflashHit.h"
00043 #include "SimGeneral/GFlash/interface/Gflash3Vector.h"
00044 // STL headers 
00045 #include <vector>
00046 #include <iostream>
00047 
00048 //CMSSW headers 
00049 #include "DataFormats/DetId/interface/DetId.h"
00050 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
00051 //#include "DataFormats/EcalDetId/interface/EcalDetId.h"
00052 
00053 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00054 
00055 using namespace edm;
00056 
00057 typedef math::XYZVector XYZVector;
00058 typedef math::XYZVector XYZPoint;
00059 
00060 std::vector<std::pair<int,float> > CalorimetryManager::myZero_ = std::vector<std::pair<int,float> >
00061 (1,std::pair<int,float>(0,0.));
00062 
00063 CalorimetryManager::CalorimetryManager() : 
00064   myCalorimeter_(0),
00065   myHistos(0),
00066   random(0),initialized_(false)
00067 {;}
00068 
00069 CalorimetryManager::CalorimetryManager(FSimEvent * aSimEvent, 
00070                                        const edm::ParameterSet& fastCalo,
00071                                        const edm::ParameterSet& fastMuECAL,
00072                                        const edm::ParameterSet& fastMuHCAL,
00073                                        const edm::ParameterSet& parGflash,
00074                                        const RandomEngine* engine)
00075   : 
00076   mySimEvent(aSimEvent), 
00077   random(engine),initialized_(false),
00078   theMuonEcalEffects(0), theMuonHcalEffects (0)
00079 
00080 {
00081 
00082   aLandauGenerator = new LandauFluctuationGenerator(random);
00083   aGammaGenerator = new GammaFunctionGenerator(random);
00084 
00085   //Gflash
00086   theProfile = new GflashHadronShowerProfile(parGflash);
00087   thePiKProfile = new GflashPiKShowerProfile(parGflash);
00088   theProtonProfile = new GflashProtonShowerProfile(parGflash);
00089   theAntiProtonProfile = new GflashAntiProtonShowerProfile(parGflash);
00090 
00091   readParameters(fastCalo);
00092 
00093 //  EBMapping_.resize(62000,myZero_);
00094 //  EEMapping_.resize(20000,myZero_);
00095 //  HMapping_.resize(10000,myZero_);
00096   EBMapping_.resize(62000);
00097   EEMapping_.resize(20000);
00098   HMapping_.resize(10000);
00099   theDetIds_.resize(10000);
00100 
00101   unsigned s=(unfoldedMode_)?5:1;
00102   for(unsigned ic=0;ic<62000;++ic)
00103     {
00104       EBMapping_[ic].reserve(s);
00105       if(ic<20000)
00106         EEMapping_[ic].reserve(s);
00107       if(ic<10000)
00108         HMapping_[ic].reserve(s);
00109     }
00110   
00111 
00112 
00113   myHistos = 0; 
00114 #ifdef FAMOSDEBUG
00115   myHistos = Histos::instance();
00116   myHistos->book("h10",140,-3.5,3.5,100,-0.5,99.5);
00117   myHistos->book("h20",150,0,150.,100,-0.5,99.5);
00118   myHistos->book("h100",140,-3.5,3.5,100,0,0.1);
00119   myHistos->book("h110",140,-3.5,3.5,100,0,10.);
00120   myHistos->book("h120",200,-5.,5.,100,0,0.5);
00121 
00122   myHistos->book("h200",300,0,3.,100,0.,35.);
00123   myHistos->book("h210",720,-M_PI,M_PI,100,0,35.);
00124   myHistos->book("h212",720,-M_PI,M_PI,100,0,35.);
00125 
00126   myHistos->bookByNumber("h30",0,7,300,-3.,3.,100,0.,35.);
00127   myHistos->book("h310",75,-3.,3.,"");
00128   myHistos->book("h400",100,-10.,10.,100,0.,35.);
00129   myHistos->book("h410",720,-M_PI,M_PI);
00130 #endif
00131   myCalorimeter_ = 
00132     new CaloGeometryHelper(fastCalo);
00133   myHDResponse_ = 
00134     new HCALResponse(fastCalo.getParameter<edm::ParameterSet>("HCALResponse"),
00135                      random);
00136   myHSParameters_ = 
00137     new HSParameters(fastCalo.getParameter<edm::ParameterSet>("HSParameters"));
00138 
00139   // Material Effects for Muons in ECAL (only EnergyLoss implemented so far)
00140 
00141   if ( fastMuECAL.getParameter<bool>("PairProduction") || 
00142        fastMuECAL.getParameter<bool>("Bremsstrahlung") ||
00143        fastMuECAL.getParameter<bool>("MuonBremsstrahlung") ||
00144        fastMuECAL.getParameter<bool>("EnergyLoss") || 
00145        fastMuECAL.getParameter<bool>("MultipleScattering") )
00146     theMuonEcalEffects = new MaterialEffects(fastMuECAL,random);
00147 
00148   // Material Effects for Muons in HCAL (only EnergyLoss implemented so far)
00149 
00150   if ( fastMuHCAL.getParameter<bool>("PairProduction") || 
00151        fastMuHCAL.getParameter<bool>("Bremsstrahlung") ||
00152        fastMuHCAL.getParameter<bool>("MuonBremsstrahlung") ||
00153        fastMuHCAL.getParameter<bool>("EnergyLoss") || 
00154        fastMuHCAL.getParameter<bool>("MultipleScattering") )
00155     theMuonHcalEffects = new MaterialEffects(fastMuHCAL,random);
00156 
00157 }
00158 
00159 void CalorimetryManager::clean()
00160 {
00161   unsigned size=firedCellsEB_.size();
00162   for(unsigned ic=0;ic<size;++ic)
00163     {
00164       EBMapping_[firedCellsEB_[ic]].clear();
00165     }
00166   firedCellsEB_.clear();
00167 
00168   size=firedCellsEE_.size();
00169   for(unsigned ic=0;ic<size;++ic)
00170     {
00171       EEMapping_[firedCellsEE_[ic]].clear();
00172     }
00173   firedCellsEE_.clear();
00174   
00175   size=firedCellsHCAL_.size();
00176   for(unsigned ic=0;ic<size;++ic)
00177     {
00178       HMapping_[firedCellsHCAL_[ic]].clear();
00179     }
00180   firedCellsHCAL_.clear();
00181 
00182   ESMapping_.clear();
00183   muonSimTracks.clear();
00184 }
00185 
00186 CalorimetryManager::~CalorimetryManager()
00187 {
00188 #ifdef FAMOSDEBUG
00189   myHistos->put("Famos.root");
00190 #endif
00191   if(myCalorimeter_) delete myCalorimeter_;
00192   if(myHDResponse_) delete myHDResponse_;
00193 
00194   if ( theMuonEcalEffects ) delete theMuonEcalEffects;
00195   if ( theMuonHcalEffects ) delete theMuonHcalEffects;
00196 
00197   if ( theProfile ) delete theProfile;
00198 }
00199 
00200 void CalorimetryManager::reconstruct()
00201 {
00202   if(evtsToDebug_.size())
00203     {
00204       std::vector<unsigned int>::const_iterator itcheck=find(evtsToDebug_.begin(),evtsToDebug_.end(),mySimEvent->id().event());
00205       debug_=(itcheck!=evtsToDebug_.end());
00206       if(debug_)
00207         mySimEvent->print();
00208     }
00209   // Clear the content of the calorimeters 
00210   if(!initialized_)
00211     {
00212       const CaloSubdetectorGeometry* geom=myCalorimeter_->getHcalGeometry();
00213       for(int subdetn=1;subdetn<=4;++subdetn)
00214         {
00215           const std::vector<DetId>& ids(geom->getValidDetIds(DetId::Hcal,subdetn));  
00216           for (std::vector<DetId>::const_iterator i=ids.begin(); i!=ids.end(); i++) 
00217             {
00218               HcalDetId myDetId(*i);
00219               unsigned hi=myDetId.hashed_index();
00220               theDetIds_[hi]=myDetId;
00221             }
00222         }
00223       
00224       // Check if the preshower is really available
00225       if(simulatePreshower_ && !myCalorimeter_->preshowerPresent())
00226         {
00227           std::cout << " WARNING " << std::endl;
00228           std::cout << " The preshower simulation has been turned on; but no preshower geometry is available " << std::endl;
00229           std::cout << " Disabling the preshower simulation " << std::endl;
00230           simulatePreshower_ = false;
00231         }
00232 
00233       initialized_=true;
00234     }
00235   clean();
00236 
00237   LogInfo("FastCalorimetry") << "Reconstructing " << (int) mySimEvent->nTracks() << " tracks." << std::endl;
00238   for( int fsimi=0; fsimi < (int) mySimEvent->nTracks() ; ++fsimi) {
00239 
00240     FSimTrack& myTrack = mySimEvent->track(fsimi);
00241 
00242     int pid = abs(myTrack.type());
00243 
00244     if (debug_) {
00245       LogDebug("FastCalorimetry") << " ===> pid = "  << pid << std::endl;      
00246     }
00247     
00248     
00249     // Check that the particle hasn't decayed
00250     if(myTrack.noEndVertex()) {
00251       // Simulate energy smearing for photon and electrons
00252       if ( pid == 11 || pid == 22 ) {
00253           
00254           
00255            if ( myTrack.onEcal() ) 
00256             EMShowerSimulation(myTrack);
00257           else if ( myTrack.onVFcal() )
00258             reconstructHCAL(myTrack);
00259            
00260       } // electron or photon
00261       else if (pid==13)
00262         {
00263           MuonMipSimulation(myTrack);
00264         }
00265       // Simulate energy smearing for hadrons (i.e., everything 
00266       // but muons... and SUSY particles that deserve a special 
00267       // treatment.
00268       else if ( pid < 1000000 ) {
00269         if ( myTrack.onHcal() || myTrack.onVFcal() ) {    
00270           if(optionHDSim_ == 0 )  reconstructHCAL(myTrack);
00271           else HDShowerSimulation(myTrack);
00272         }
00273       } // pid < 1000000 
00274     } // myTrack.noEndVertex()
00275   } // particle loop
00276   //  LogInfo("FastCalorimetry") << " Number of  hits (barrel)" << EBMapping_.size() << std::endl;
00277   //  LogInfo("FastCalorimetry") << " Number of  hits (Hcal)" << HMapping_.size() << std::endl;
00278   //  std::cout << " Nombre de hit (endcap)" << EEMapping_.size() << std::endl;
00279 
00280 } // reconstruct
00281 
00282 // Simulation of electromagnetic showers in PS, ECAL, HCAL 
00283 void CalorimetryManager::EMShowerSimulation(const FSimTrack& myTrack) {
00284   std::vector<const RawParticle*> thePart;
00285   double X0depth;
00286   if (debug_) {
00287     LogDebug("FastCalorimetry") << " EMShowerSimulation "  <<myTrack << std::endl;      
00288   }
00289   
00290   //  std::cout << " Simulating " << myTrack << std::endl;
00291 
00292   // The Particle at ECAL entrance
00293   //  std::cout << " Before ecalEntrance " << std::endl;
00294   myPart = myTrack.ecalEntrance(); 
00295 
00296   // protection against infinite loop.  
00297   if ( myTrack.type() == 22 && myPart.e()<0.055) return; 
00298 
00299 
00300   // Barrel or Endcap ?
00301   int onEcal = myTrack.onEcal();
00302   int onHcal = myTrack.onHcal();
00303   int onLayer1 = myTrack.onLayer1();
00304   int onLayer2 = myTrack.onLayer2();
00305 
00306   // The entrance in ECAL
00307   XYZPoint ecalentrance = myPart.vertex().Vect();
00308   
00309   //  std::cout << " Ecal entrance " << ecalentrance << std::endl;
00310   
00311   // The preshower
00312   PreshowerHitMaker * myPreshower = NULL ;
00313   if(simulatePreshower_ && (onLayer1 || onLayer2))
00314     {
00315       XYZPoint layer1entrance,layer2entrance;
00316       XYZVector dir1,dir2;
00317       if(onLayer1) 
00318         {
00319           layer1entrance = XYZPoint(myTrack.layer1Entrance().vertex().Vect());
00320           dir1 = XYZVector(myTrack.layer1Entrance().Vect().Unit());
00321         }
00322       if(onLayer2) 
00323         {
00324           layer2entrance = XYZPoint(myTrack.layer2Entrance().vertex().Vect());
00325           dir2 = XYZVector(myTrack.layer2Entrance().Vect().Unit());
00326         }
00327       //      std::cout << " Layer1entrance " << layer1entrance << std::endl;
00328       //      std::cout << " Layer2entrance " << layer2entrance << std::endl;
00329       myPreshower = new PreshowerHitMaker(myCalorimeter_,
00330                                           layer1entrance,
00331                                           dir1,
00332                                           layer2entrance,
00333                                           dir2,
00334                                           aLandauGenerator);
00335       myPreshower->setMipEnergy(mipValues_[0],mipValues_[1]);
00336     }
00337 
00338   // The ECAL Properties
00339   EMECALShowerParametrization 
00340     showerparam(myCalorimeter_->ecalProperties(onEcal), 
00341                 myCalorimeter_->hcalProperties(onHcal), 
00342                 myCalorimeter_->layer1Properties(onLayer1), 
00343                 myCalorimeter_->layer2Properties(onLayer2),
00344                 theCoreIntervals_,
00345                 theTailIntervals_,
00346                 RCFactor_,
00347                 RTFactor_);
00348 
00349   // Photons : create an e+e- pair
00350   if ( myTrack.type() == 22 ) {
00351     
00352     // Depth for the first e+e- pair creation (in X0)
00353     X0depth = -log(random->flatShoot()) * (9./7.);
00354     
00355     // Initialization
00356     double eMass = 0.000510998902; 
00357     double xe=0;
00358     double xm=eMass/myPart.e();
00359     double weight = 0.;
00360     
00361     // Generate electron energy between emass and eGamma-emass
00362     do {
00363       xe = random->flatShoot()*(1.-2.*xm) + xm;
00364       weight = 1. - 4./3.*xe*(1.-xe);
00365     } while ( weight < random->flatShoot() );
00366     
00367     // Protection agains infinite loop in Famos Shower
00368     if ( myPart.e()*xe < 0.055 || myPart.e()*(1.-xe) < 0.055 ) {
00369       
00370       if ( myPart.e() > 0.055 ) thePart.push_back(&myPart);
00371       
00372     } else {      
00373       
00374       myElec = (myPart) * xe;
00375       myPosi = (myPart) * (1.-xe);
00376       myElec.setVertex(myPart.vertex());
00377       myPosi.setVertex(myPart.vertex());
00378       thePart.push_back(&myElec);
00379       thePart.push_back(&myPosi);
00380     }
00381   // Electrons
00382   } else {  
00383     
00384     X0depth = 0.;
00385     if ( myPart.e() > 0.055 ) thePart.push_back(&myPart);
00386     
00387   } 
00388   
00389   // After the different protections, this shouldn't happen. 
00390   if(thePart.size()==0) 
00391     { 
00392       if(myPreshower==NULL) return; 
00393       delete myPreshower; 
00394       return; 
00395     } 
00396 
00397   // find the most energetic particle
00398   double maxEnergy=-1.;
00399   for(unsigned ip=0;ip < thePart.size();++ip)
00400     if(thePart[ip]->e() > maxEnergy) maxEnergy = thePart[ip]->e();
00401   
00402   // Initialize the Grid in ECAL
00403   int size = gridSize_;
00404   if(maxEnergy>100) size=11;
00405 //  if ( maxEnergy < threshold5x5 ) size = 5;
00406 //  if ( maxEnergy < threshold3x3 ) size = 3;
00407 
00408 
00409   EMShower theShower(random,aGammaGenerator,&showerparam,&thePart);
00410 
00411   double maxShower = theShower.getMaximumOfShower();
00412   if (maxShower > 20.) maxShower = 2.; // simple pivot-searching protection 
00413 
00414   double depth((X0depth + maxShower) * 
00415                myCalorimeter_->ecalProperties(onEcal)->radLenIncm());
00416   XYZPoint meanShower = ecalentrance + myPart.Vect().Unit()*depth;
00417   
00418   //  if(onEcal!=1) return ; 
00419 
00420   // The closest crystal
00421   DetId pivot(myCalorimeter_->getClosestCell(meanShower, true, onEcal==1));
00422 
00423   if(pivot.subdetId() == 0) {   // further protection against avbsence of pivot
00424     edm::LogWarning("CalorimetryManager") <<  "Pivot for egamma  e = "  << myTrack.hcalEntrance().e() << " is not found at depth " << depth << " and meanShower coordinates = " << meanShower << std::endl; 
00425     return;
00426   }
00427   
00428   EcalHitMaker myGrid(myCalorimeter_,ecalentrance,pivot,onEcal,size,0,random);
00429   //                                             ^^^^
00430   //                                         for EM showers
00431   myGrid.setPulledPadSurvivalProbability(pulledPadSurvivalProbability_);
00432   myGrid.setCrackPadSurvivalProbability(crackPadSurvivalProbability_);
00433   myGrid.setRadiusFactor(radiusFactor_);
00434  //maximumdepth dependence of the radiusfactorbehindpreshower
00435  // adjusted by Shilpi Jain (Mar-Apr 2010)
00436   if(onLayer1 || onLayer2)
00437     {
00438       float b               = radiusPreshowerCorrections_[0];
00439       float a               = radiusFactor_*( 1.+radiusPreshowerCorrections_[1]*radiusPreshowerCorrections_[0] );
00440       float maxdepth        = X0depth+theShower.getMaximumOfShower();
00441       float newRadiusFactor = radiusFactor_;
00442       if(myPart.e()<=250.)
00443         {
00444           newRadiusFactor = a/(1.+b*maxdepth); 
00445         }
00446       myGrid.setRadiusFactor(newRadiusFactor);
00447     }
00448   else // otherwise use the normal radius factor
00449     {
00450       myGrid.setRadiusFactor(radiusFactor_);
00451     }
00452   myGrid.setPreshowerPresent(simulatePreshower_);
00453   
00454   // The shower simulation
00455   myGrid.setTrackParameters(myPart.Vect().Unit(),X0depth,myTrack);
00456 
00457 //  std::cout << " PS ECAL GAP HCAL X0 " << myGrid.ps1TotalX0()+myGrid.ps2TotalX0() << " " << myGrid.ecalTotalX0();
00458 //  std::cout << " " << myGrid.ecalHcalGapTotalX0() << " " << myGrid.hcalTotalX0() << std::endl;
00459 //  std::cout << " PS ECAL GAP HCAL L0 " << myGrid.ps1TotalL0()+myGrid.ps2TotalL0() << " " << myGrid.ecalTotalL0();
00460 //   std::cout << " " << myGrid.ecalHcalGapTotalL0() << " " << myGrid.hcalTotalL0() << std::endl;
00461 //   std::cout << "ECAL-HCAL " << myTrack.momentum().eta() << " " <<  myGrid.ecalHcalGapTotalL0() << std::endl;
00462 //
00463 //  std::cout << " Grid created " << std::endl;
00464   if(myPreshower) theShower.setPreshower(myPreshower);
00465   
00466   HcalHitMaker myHcalHitMaker(myGrid,(unsigned)0); 
00467 
00468   theShower.setGrid(&myGrid);
00469   theShower.setHcal(&myHcalHitMaker);
00470   //  std:: cout << " About to compute " << std::endl;
00471   theShower.compute();
00472   //  std::cout << " Coming back from compute" << std::endl;
00473   //myHistos->fill("h502", myPart->eta(),myGrid.totalX0());
00474   
00475   // Save the hits !
00476   std::map<uint32_t,float>::const_iterator mapitr;
00477   std::map<uint32_t,float>::const_iterator endmapitr=myGrid.getHits().end();
00478   for(mapitr=myGrid.getHits().begin();mapitr!=endmapitr;++mapitr)
00479     {
00480       if(onEcal==1)
00481         {
00482           updateMap(EBDetId(mapitr->first).hashedIndex(), mapitr->second,myTrack.id(),EBMapping_,firedCellsEB_);
00483         }
00484             
00485       else if(onEcal==2)
00486         updateMap(EEDetId(mapitr->first).hashedIndex(), mapitr->second,myTrack.id(),EEMapping_,firedCellsEE_);
00487       //      std::cout << " Adding " <<mapitr->first << " " << mapitr->second <<std::endl; 
00488     }
00489 
00490   // Now fill the HCAL hits
00491   endmapitr=myHcalHitMaker.getHits().end();
00492   for(mapitr=myHcalHitMaker.getHits().begin();mapitr!=endmapitr;++mapitr)
00493     {
00494       updateMap(HcalDetId(mapitr->first).hashed_index(),mapitr->second,myTrack.id(),HMapping_,firedCellsHCAL_);
00495       //      std::cout << " Adding " <<mapitr->first << " " << mapitr->second <<std::endl; 
00496     }
00497 
00498   // delete the preshower
00499   if(myPreshower!=0)
00500     {
00501       endmapitr=myPreshower->getHits().end();
00502       for(mapitr=myPreshower->getHits().begin();mapitr!=endmapitr;++mapitr)
00503         {
00504           updateMap(mapitr->first,mapitr->second,myTrack.id(),ESMapping_);
00505           //      std::cout << " Adding " <<mapitr->first << " " << mapitr->second <<std::endl; 
00506         }
00507       delete myPreshower;
00508     }
00509   //  std::cout << " Deleting myPreshower " << std::endl;
00510   
00511 }
00512 
00513 
00514 
00515 // Simulation of electromagnetic showers in VFCAL
00516 void CalorimetryManager::reconstructECAL(const FSimTrack& track) {
00517   if(debug_) {
00518     XYZTLorentzVector moment = track.momentum();
00519     std::cout << "FASTEnergyReconstructor::reconstructECAL - " << std::endl
00520          << "  eta " << moment.eta() << std::endl
00521          << "  phi " << moment.phi() << std::endl
00522          << "   et " << moment.Et()  << std::endl;
00523   }
00524   
00525   int hit; 
00526   
00527   bool central=track.onEcal()==1;
00528   
00529   //Reconstruct only electrons and photons. 
00530 
00531   //deal with different conventions
00532   // ParticlePropagator 1 <-> Barrel
00533   //                    2 <-> EC
00534   // whereas for Artur(this code):
00535   //                    0 <-> Barrel
00536   //                    1 <-> EC
00537   //                    2 <-> VF
00538   XYZTLorentzVector trackPosition;
00539   if( track.onEcal() ) {
00540     hit=track.onEcal()-1;
00541     trackPosition=track.ecalEntrance().vertex();
00542   } else {
00543     hit=2;
00544     trackPosition=track.vfcalEntrance().vertex();
00545   }
00546   
00547   double pathEta   = trackPosition.eta();
00548   double pathPhi   = trackPosition.phi();       
00549   double EGen      = track.ecalEntrance().e();
00550   
00551 
00552   double e=0.;
00553   double sigma=0.;
00554   // if full simulation and in HF, but without showering anyway...
00555   if(hit == 2 && optionHDSim_ == 2 ) { 
00556     std::pair<double,double> response =
00557       myHDResponse_->responseHCAL(0, EGen, pathEta, 0); // last par.= 0 = e/gamma 
00558     e     = response.first;
00559     sigma = response.second;
00560   }
00561 
00562   double emeas = 0.;
00563   
00564   if(sigma>0.)
00565     emeas = random->gaussShoot(e,sigma);
00566   
00567 
00568   if(debug_)
00569     std::cout << "FASTEnergyReconstructor::reconstructECAL : " 
00570          << "  on-calo  eta, phi  = " << pathEta << " " << pathPhi << std::endl 
00571          << "  Egen  = " << EGen << std::endl 
00572          << "  Eres  = " << e << std::endl 
00573          << " sigma  = " << sigma << std::endl 
00574          << "  Emeas = " << emeas << std::endl; 
00575 
00576 
00577   if(debug_)
00578     std::cout << "FASTEnergyReconstructor::reconstructECAL : " 
00579          << " Track position - " << trackPosition.Vect() 
00580          << "   bool central - " << central
00581          << "   hit - " << hit   << std::endl;  
00582 
00583   DetId detid;  
00584   if( hit==2 ) 
00585       detid = myCalorimeter_->getClosestCell(trackPosition.Vect(),false,central);
00586   // Check that the detid is HCAL forward
00587   HcalDetId hdetid(detid);
00588   if(!hdetid.subdetId()!=HcalForward) return;
00589 
00590   if(debug_)
00591     std::cout << "FASTEnergyReconstructor::reconstructECAL : " 
00592               << " CellID - " <<  detid.rawId() << std::endl;
00593 
00594   if( hit != 2  || emeas > 0.) 
00595     if(!detid.null()) 
00596       {
00597         updateMap(hdetid.hashed_index(),emeas,track.id(),HMapping_,firedCellsHCAL_);
00598       }
00599 
00600 }
00601 
00602 
00603 void CalorimetryManager::reconstructHCAL(const FSimTrack& myTrack)
00604 {
00605   int hit;
00606   int pid = abs(myTrack.type());
00607   if (debug_) {
00608     LogDebug("FastCalorimetry") << " reconstructHCAL "  << myTrack << std::endl;      
00609   }
00610 
00611   //  FSimTrack myTrack = mySimEvent.track(fsimi);
00612 
00613   //  int pid=abs(myTrack.type());
00614   //  std::cout << "reconstructHCAL " << std::endl;
00615   
00616   XYZTLorentzVector trackPosition;
00617   if (myTrack.onHcal()) {
00618     trackPosition=myTrack.hcalEntrance().vertex();
00619     hit = myTrack.onHcal()-1;
00620   } else {
00621     trackPosition=myTrack.vfcalEntrance().vertex();
00622     hit = 2;
00623   }
00624 
00625   double pathEta   = trackPosition.eta();
00626   double pathPhi   = trackPosition.phi();       
00627   //  double pathTheta = trackPosition.theta();
00628 
00629   double EGen  = myTrack.hcalEntrance().e();
00630   double e     = 0.;
00631   double sigma = 0.;
00632   double emeas = 0.;
00633 
00634   if(pid == 13) { 
00635     //    std::cout << " We should not be here " << std::endl;
00636     std::pair<double,double> response =
00637       myHDResponse_->responseHCAL(0, EGen, pathEta, 2); // 2=muon 
00638     emeas  = response.first;
00639     if(debug_)
00640       LogDebug("FastCalorimetry") << "CalorimetryManager::reconstructHCAL - MUON !!!" << std::endl;
00641   }
00642   else if( pid == 22 || pid == 11)
00643     {
00644       
00645       std::pair<double,double> response =
00646         myHDResponse_->responseHCAL(0, EGen, pathEta, 0); // last par. = 0 = e/gamma
00647       e     = response.first;              //
00648       sigma = response.second;             //
00649       emeas = random->gaussShoot(e,sigma); //
00650 
00651       //  cout <<  "CalorimetryManager::reconstructHCAL - e/gamma !!!" << std::endl;
00652       if(debug_)
00653         LogDebug("FastCalorimetry") << "CalorimetryManager::reconstructHCAL - e/gamma !!!" << std::endl;
00654     }
00655     else {
00656       e     = myHDResponse_->getHCALEnergyResponse(EGen,hit);
00657       sigma = myHDResponse_->getHCALEnergyResolution(EGen, hit);
00658       
00659       emeas = random->gaussShoot(e,sigma);  
00660     }
00661     
00662 
00663   if(debug_)
00664     LogDebug("FastCalorimetry") << "CalorimetryManager::reconstructHCAL - on-calo "   
00665                                 << "  eta = " << pathEta 
00666                                 << "  phi = " << pathPhi 
00667                                 << "  Egen = " << EGen 
00668                                 << "  Eres = " << e 
00669                                 << "  sigma = " << sigma 
00670                                 << "  Emeas = " << emeas << std::endl;
00671 
00672   if(emeas > 0.) {  
00673     DetId cell = myCalorimeter_->getClosestCell(trackPosition.Vect(),false,false);
00674     updateMap(HcalDetId(cell).hashed_index(), emeas, myTrack.id(),HMapping_,firedCellsHCAL_);
00675   }
00676 }
00677 
00678 void CalorimetryManager::HDShowerSimulation(const FSimTrack& myTrack)
00679 {
00680   //  TimeMe t(" FASTEnergyReconstructor::HDShower");
00681   XYZTLorentzVector moment = myTrack.momentum();
00682   
00683   if(debug_)
00684     LogDebug("FastCalorimetry") 
00685       << "CalorimetryManager::HDShowerSimulation - track param."
00686       << std::endl
00687       << "  eta = " << moment.eta() << std::endl
00688       << "  phi = " << moment.phi() << std::endl
00689       << "   et = " << moment.Et()  << std::endl
00690       << "   e  = " << myTrack.hcalEntrance().e() << std::endl;
00691 
00692   if (debug_) {
00693       LogDebug("FastCalorimetry") << " HDShowerSimulation "  << myTrack << std::endl;      
00694     }
00695 
00696 
00697   int hit;
00698   //  int pid = abs(myTrack.type());
00699 
00700   XYZTLorentzVector trackPosition;
00701   if ( myTrack.onEcal() ) {
00702     trackPosition=myTrack.ecalEntrance().vertex();
00703     hit = myTrack.onEcal()-1;                               //
00704     myPart = myTrack.ecalEntrance();
00705   } else if ( myTrack.onVFcal()) {
00706     trackPosition=myTrack.vfcalEntrance().vertex();
00707     hit = 2;
00708     myPart = myTrack.vfcalEntrance();
00709   }
00710   else
00711     {
00712       LogDebug("FastCalorimetry") << " The particle is not in the acceptance " << std::endl;
00713       return;
00714     }
00715 
00716   // int onHCAL = hit + 1; - specially for myCalorimeter->hcalProperties(onHCAL)
00717   // (below) to get VFcal properties ...
00718   int onHCAL = hit + 1;
00719   int onECAL = myTrack.onEcal();
00720   
00721   double pathEta   = trackPosition.eta();
00722   double pathPhi   = trackPosition.phi();       
00723   //  double pathTheta = trackPosition.theta();
00724 
00725   double eint  = moment.e();
00726   double eGen  = myTrack.hcalEntrance().e();
00727   double e     = 0.;
00728   double sigma = 0.;
00729 
00730   double emeas = 0.;  
00731   
00732   //===========================================================================
00733   if(eGen > 0.) {  
00734 
00735     // ECAL and HCAL properties to get
00736     HDShowerParametrization 
00737       theHDShowerparam(myCalorimeter_->ecalProperties(onECAL),
00738                        myCalorimeter_->hcalProperties(onHCAL),
00739                        myHSParameters_);
00740     
00741     //Making ECAL Grid (and segments calculation)
00742     XYZPoint caloentrance;
00743     XYZVector direction;
00744     if(myTrack.onEcal()) 
00745       { 
00746         caloentrance = myTrack.ecalEntrance().vertex().Vect();
00747         direction = myTrack.ecalEntrance().Vect().Unit();
00748       }
00749     else if(myTrack.onHcal())
00750       {
00751         caloentrance = myTrack.hcalEntrance().vertex().Vect();
00752         direction = myTrack.hcalEntrance().Vect().Unit();
00753       }
00754     else
00755       {
00756         caloentrance = myTrack.vfcalEntrance().vertex().Vect();
00757         direction = myTrack.vfcalEntrance().Vect().Unit();
00758       }
00759 
00760   if(debug_)
00761     LogDebug("FastCalorimetry") 
00762       << "CalorimetryManager::HDShowerSimulation - on-calo 1 "
00763       << std::endl
00764       << "  onEcal    = " <<  myTrack.onEcal()  << std::endl
00765       << "  onHcal    = " <<  myTrack.onHcal()  << std::endl
00766       << "  onVFcal   = " <<  myTrack.onVFcal() << std::endl
00767       << "  position  = " << caloentrance << std::endl;
00768 
00769 
00770     DetId pivot;
00771     if(myTrack.onEcal())
00772       {
00773         pivot=myCalorimeter_->getClosestCell(caloentrance,
00774                                              true, myTrack.onEcal()==1);
00775       }
00776     else if(myTrack.onHcal())
00777       {
00778         //      std::cout << " CalorimetryManager onHcal " <<  myTrack.onHcal() << " caloentrance" << caloentrance  << std::endl;
00779         pivot=myCalorimeter_->getClosestCell(caloentrance,                                           
00780                                             false, false);
00781       }
00782 
00783     EcalHitMaker myGrid(myCalorimeter_,caloentrance,pivot,
00784                         pivot.null()? 0 : myTrack.onEcal(),hdGridSize_,1,
00785                         random);
00786     // 1=HAD shower
00787 
00788     myGrid.setTrackParameters(direction,0,myTrack);
00789     // Build the FAMOS HCAL 
00790     HcalHitMaker myHcalHitMaker(myGrid,(unsigned)1); 
00791     
00792     // Shower simulation
00793     bool status = false;
00794     int  mip = 2;
00795     // Use HFShower for HF
00796     if ( !myTrack.onEcal() && !myTrack.onHcal() ) {
00797       //      std::cout << "CalorimetryManager::HDShowerSimulation(): track entrance = "
00798       //                << myTrack.vfcalEntrance().vertex().X() << " "
00799       //                << myTrack.vfcalEntrance().vertex().Y() << " "
00800       //                << myTrack.vfcalEntrance().vertex().Z() << " "
00801       //                << " , Energy (Gen/Scale) = " << eGen << " " << e << std::endl;
00802 
00803       // Warning : We give here the particle energy with the response
00804       //           but without the resolution/gaussian smearing
00805       //           For HF, the resolution is due to the PE statistic
00806 
00807       HFShower theShower(random,
00808                          &theHDShowerparam,
00809                          &myGrid,
00810                          &myHcalHitMaker,
00811                          onECAL,
00812                          eGen);
00813                          //                      eGen);
00814                          //                      e); // PV Warning : temporarly set the energy to the generated E
00815 
00816       status = theShower.compute();
00817     } else { 
00818       if(hdSimMethod_ == 0) {
00819         HDShower theShower(random,
00820                            &theHDShowerparam,
00821                            &myGrid,
00822                            &myHcalHitMaker,
00823                            onECAL,
00824                            eGen);
00825         status = theShower.compute();
00826         mip    = theShower.getmip();
00827       }
00828       else if (hdSimMethod_ == 1) {
00829         HDRShower theShower(random,
00830                             &theHDShowerparam,
00831                             &myGrid,
00832                             &myHcalHitMaker,
00833                             onECAL,
00834                             eGen);
00835         status = theShower.computeShower();
00836         mip = 2;
00837       }
00838       else if (hdSimMethod_ == 2 ) {
00839         //        std::cout << "Using GflashHadronShowerProfile hdSimMethod_ == 2" << std::endl;
00840 
00841         //dynamically loading a corresponding profile by the particle type
00842         int particleType = myTrack.type();
00843         theProfile = thePiKProfile;
00844         if(particleType == -2212) theProfile = theAntiProtonProfile;
00845         else if(particleType == 2212) theProfile = theProtonProfile;
00846 
00847         //input variables for GflashHadronShowerProfile
00848         int showerType = 99 + myTrack.onEcal();
00849         double globalTime = 150.0; // a temporary reference hit time in nanosecond
00850         float charge = (float)(myTrack.charge());
00851         Gflash3Vector gfpos(trackPosition.X(),trackPosition.Y(),trackPosition.Z());
00852         Gflash3Vector gfmom(moment.X(),moment.Y(),moment.Z());
00853 
00854         theProfile->initialize(showerType,eGen,globalTime,charge,gfpos,gfmom);
00855         theProfile->loadParameters();
00856         theProfile->hadronicParameterization();
00857 
00858         //make hits
00859         std::vector<GflashHit>& gflashHitList = theProfile->getGflashHitList();
00860         std::vector<GflashHit>::const_iterator spotIter    = gflashHitList.begin();
00861         std::vector<GflashHit>::const_iterator spotIterEnd = gflashHitList.end();
00862 
00863         Gflash::CalorimeterNumber whichCalor = Gflash::kNULL;
00864         bool result;
00865 
00866         for( ; spotIter != spotIterEnd; spotIter++){
00867 
00868           double pathLength = theProfile->getGflashShowino()->getPathLengthAtShower()
00869             + (30*100/eGen)*(spotIter->getTime() - globalTime);
00870 
00871           double currentDepth = std::max(0.0,pathLength - theProfile->getGflashShowino()->getPathLengthOnEcal());
00872 
00873           //find the the showino position at the currentDepth
00874           GflashTrajectoryPoint trajectoryPoint;
00875           theProfile->getGflashShowino()->getHelix()->getGflashTrajectoryPoint(trajectoryPoint,pathLength);
00876           Gflash3Vector positionAtCurrentDepth = trajectoryPoint.getPosition();
00877           //find radial distrance
00878           Gflash3Vector lateralDisplacement = positionAtCurrentDepth - spotIter->getPosition()/CLHEP::cm;
00879           double rShower = lateralDisplacement.r();
00880           double azimuthalAngle = lateralDisplacement.phi();
00881 
00882           whichCalor = Gflash::getCalorimeterNumber(positionAtCurrentDepth);
00883 
00884           if(whichCalor==Gflash::kESPM || whichCalor==Gflash::kENCA) {
00885             bool statusPad = myGrid.getPads(currentDepth,true);
00886             if(!statusPad) continue;
00887             myGrid.setSpotEnergy(1.2*spotIter->getEnergy()/CLHEP::GeV);
00888             result = myGrid.addHit(rShower/Gflash::intLength[Gflash::kESPM],azimuthalAngle,0);
00889           }
00890           else if(whichCalor==Gflash::kHB || whichCalor==Gflash::kHE) {
00891             bool setHDdepth = myHcalHitMaker.setDepth(currentDepth,true);
00892             if(!setHDdepth) continue;
00893             myHcalHitMaker.setSpotEnergy(1.4*spotIter->getEnergy()/CLHEP::GeV);
00894             result = myHcalHitMaker.addHit(rShower/Gflash::intLength[Gflash::kHB],azimuthalAngle,0);
00895           }
00896         }
00897         status = true;
00898       }
00899       else {
00900         edm::LogInfo("FastSimulationCalorimetry") << " SimMethod " << hdSimMethod_ <<" is NOT available ";
00901       }
00902     }
00903 
00904 
00905     if(status) {
00906 
00907       // Here to switch between simple formulae and parameterized response
00908       if(optionHDSim_ == 1) {
00909         e     = myHDResponse_->getHCALEnergyResponse  (eGen, hit);
00910         sigma = myHDResponse_->getHCALEnergyResolution(eGen, hit);
00911       }
00912       else { // optionHDsim == 2
00913         std::pair<double,double> response =
00914           myHDResponse_->responseHCAL(mip, eGen, pathEta, 1); // 1=hadron
00915         e     = response.first;
00916         sigma = response.second;
00917       }
00918       
00919       emeas = random->gaussShoot(e,sigma);      
00920       double correction = emeas / eGen;
00921       
00922       // RespCorrP factors (ECAL and HCAL separately) calculation
00923       respCorr(eint);     
00924 
00925       if(debug_)
00926         LogDebug("FastCalorimetry") 
00927           << "CalorimetryManager::HDShowerSimulation - on-calo 2" << std::endl
00928           << "   eta  = " << pathEta << std::endl
00929           << "   phi  = " << pathPhi << std::endl
00930           << "  Egen  = " << eGen << std::endl
00931           << "  Eres  = " << e << std::endl
00932           << " sigma  = " << sigma << std::endl
00933           << " Emeas  = " << emeas << std::endl
00934           << "  corr  = " << correction << std::endl
00935           << "   mip  = " << mip << std::endl;
00936       
00937       
00938       // was map<unsigned,double> but CaloHitMaker uses float
00939       std::map<unsigned,float>::const_iterator mapitr;
00940       std::map<unsigned,float>::const_iterator endmapitr;
00941       if(myTrack.onEcal() > 0) {
00942         // Save ECAL hits 
00943         endmapitr=myGrid.getHits().end();
00944         for(mapitr=myGrid.getHits().begin(); mapitr!=endmapitr; ++mapitr) {
00945           double energy = mapitr->second;
00946           energy *= correction;              // RESCALING 
00947           energy *= ecorr;
00948 
00949           if(energy > 0.000001) { 
00950             if(onECAL==1)
00951                 updateMap(EBDetId(mapitr->first).hashedIndex(),energy,myTrack.id(),EBMapping_,firedCellsEB_);
00952 
00953             else if(onECAL==2)
00954               updateMap(EEDetId(mapitr->first).hashedIndex(),energy,myTrack.id(),EEMapping_,firedCellsEE_);
00955 
00956             if(debug_)
00957               LogDebug("FastCalorimetry") << " ECAL cell " << mapitr->first << " added,  E = " 
00958                    << energy << std::endl;  
00959           }
00960         }
00961       }
00962       
00963       // Save HCAL hits
00964       endmapitr=myHcalHitMaker.getHits().end();
00965       for(mapitr=myHcalHitMaker.getHits().begin(); mapitr!=endmapitr; ++mapitr) {
00966         double energy = mapitr->second;
00967         energy *= correction;               // RESCALING 
00968         energy *= hcorr;
00969 
00970         updateMap(HcalDetId(mapitr->first).hashed_index(),energy,myTrack.id(),HMapping_,firedCellsHCAL_);
00971         if(debug_)
00972           LogDebug("FastCalorimetry") << " HCAL cell "  
00973                << mapitr->first << " added    E = " 
00974                << mapitr->second << std::endl;  
00975       }
00976     }      
00977     else {  // shower simulation failed  
00978 //      std::cout << " Shower simulation failed " << trackPosition.Vect() << std::endl;
00979 //      std::cout << " The FSimTrack " << myTrack << std::endl;
00980 //      std::cout << " HF entrance on VFcal" << myTrack.onVFcal() << std::endl;
00981 //      std::cout << " trackPosition.eta() " << trackPosition.eta() << std::endl;
00982       if(myTrack.onHcal() || myTrack.onVFcal())
00983         {
00984           DetId cell = myCalorimeter_->getClosestCell(trackPosition.Vect(),false,false);
00985           updateMap(HcalDetId(cell).hashed_index(),emeas,myTrack.id(),HMapping_,firedCellsHCAL_);
00986           if(debug_)
00987             LogDebug("FastCalorimetry") << " HCAL simple cell "   
00988                                         << cell.rawId() << " added    E = " 
00989                                         << emeas << std::endl;  
00990         }
00991     }
00992 
00993   } // e > 0. ...
00994 
00995   if(debug_)
00996     LogDebug("FastCalorimetry") << std::endl << " FASTEnergyReconstructor::HDShowerSimulation  finished "
00997          << std::endl;
00998 }
00999 
01000 
01001 void CalorimetryManager::MuonMipSimulation(const FSimTrack& myTrack)
01002 {
01003   //  TimeMe t(" FASTEnergyReconstructor::HDShower");
01004   XYZTLorentzVector moment = myTrack.momentum();
01005 
01006   // Backward compatibility behaviour
01007   if(!theMuonHcalEffects) 
01008     {
01009       if(myTrack.onHcal() || myTrack.onVFcal() ) 
01010         reconstructHCAL(myTrack);
01011 
01012       return;
01013     }
01014 
01015   if(debug_)
01016     LogDebug("FastCalorimetry") << "CalorimetryManager::MuonMipSimulation - track param."
01017          << std::endl
01018          << "  eta = " << moment.eta() << std::endl
01019          << "  phi = " << moment.phi() << std::endl
01020          << "   et = " << moment.Et()  << std::endl;
01021 
01022   int hit;
01023   //  int pid = abs(myTrack.type());
01024 
01025   XYZTLorentzVector trackPosition;
01026   if ( myTrack.onEcal() ) {
01027     trackPosition=myTrack.ecalEntrance().vertex();
01028     hit = myTrack.onEcal()-1;                               //
01029     myPart = myTrack.ecalEntrance();
01030   } else if ( myTrack.onVFcal()) {
01031     trackPosition=myTrack.vfcalEntrance().vertex();
01032     hit = 2;
01033     myPart = myTrack.vfcalEntrance();
01034   }
01035   else
01036     {
01037       LogDebug("FastCalorimetry") << " The particle is not in the acceptance " << std::endl;
01038       return;
01039     }
01040 
01041   // int onHCAL = hit + 1; - specially for myCalorimeter->hcalProperties(onHCAL)
01042   // (below) to get VFcal properties ...
01043   // not needed ? 
01044   //  int onHCAL = hit + 1; 
01045   int onECAL = myTrack.onEcal();
01046   
01047   //  double pathEta   = trackPosition.eta();
01048   //  double pathPhi   = trackPosition.phi();   
01049   //  double pathTheta = trackPosition.theta();
01050   
01051   //===========================================================================
01052 
01053   // ECAL and HCAL properties to get
01054       
01055   //Making ECAL Grid (and segments calculation)
01056   XYZPoint caloentrance;
01057   XYZVector direction;
01058   if(myTrack.onEcal()) 
01059     {   
01060       caloentrance = myTrack.ecalEntrance().vertex().Vect();
01061       direction = myTrack.ecalEntrance().Vect().Unit();
01062     }
01063   else if(myTrack.onHcal())
01064     {
01065       caloentrance = myTrack.hcalEntrance().vertex().Vect();
01066       direction = myTrack.hcalEntrance().Vect().Unit();
01067     }
01068   else
01069     {
01070       caloentrance = myTrack.vfcalEntrance().vertex().Vect();
01071       direction = myTrack.vfcalEntrance().Vect().Unit();
01072     }
01073   
01074   DetId pivot;
01075   if(myTrack.onEcal())
01076     {
01077       pivot=myCalorimeter_->getClosestCell(caloentrance,
01078                                            true, myTrack.onEcal()==1);
01079     }
01080   else if(myTrack.onHcal())
01081     {
01082       //        std::cout << " CalorimetryManager onHcal " <<  myTrack.onHcal() << " caloentrance" << caloentrance  << std::endl;
01083       pivot=myCalorimeter_->getClosestCell(caloentrance,                                             
01084                                            false, false);
01085     }
01086   
01087   EcalHitMaker myGrid(myCalorimeter_,caloentrance,pivot,
01088                       pivot.null()? 0 : myTrack.onEcal(),hdGridSize_,0,
01089                       random);
01090   // 0 =EM shower -> Unit = X0
01091   
01092   myGrid.setTrackParameters(direction,0,myTrack);
01093   
01094   // Now get the path in the Preshower, ECAL and HCAL along a straight line extrapolation 
01095   // but only those in the ECAL are used 
01096  
01097   const std::vector<CaloSegment>& segments=myGrid.getSegments();
01098   unsigned nsegments=segments.size();
01099   
01100   int ifirstHcal=-1;
01101   int ilastEcal=-1;
01102   EnergyLossSimulator* energyLossECAL = 0;
01103  //New muon brem effect  in Calorimetry 16th Jan 2011 (Sandro Fonseca de Souza and Andre Sznajder UERJ/Brazil)
01104   MuonBremsstrahlungSimulator* muonBremECAL = 0;
01105  
01106   if (theMuonEcalEffects) energyLossECAL = theMuonEcalEffects->energyLossSimulator();
01107   // Muon brem in ECAL
01108   if (theMuonEcalEffects) muonBremECAL = theMuonEcalEffects->muonBremsstrahlungSimulator();
01109 
01110   for(unsigned iseg=0;iseg<nsegments&&ifirstHcal<0;++iseg)
01111     {
01112       
01113       // in the ECAL, there are two types of segments: PbWO4 and GAP
01114       float segmentSizeinX0=segments[iseg].X0length();
01115 
01116       // Martijn - insert your computations here
01117       float energy=0.0;
01118       if (segmentSizeinX0>0.001 && segments[iseg].material()==CaloSegment::PbWO4 ) {
01119         // The energy loss simulator
01120         float charge = (float)(myTrack.charge());
01121         ParticlePropagator theMuon(moment,trackPosition,charge,0);
01122         theMuon.setID(-(int)charge*13);
01123         if ( energyLossECAL ) { 
01124           energyLossECAL->updateState(theMuon, segmentSizeinX0);
01125           energy = energyLossECAL->deltaMom().E();
01126           moment -= energyLossECAL->deltaMom();
01127         }
01128       } 
01129       // that's all for ECAL, Florian
01130       // Save the hit only if it is a crystal
01131       if(segments[iseg].material()==CaloSegment::PbWO4)
01132         {
01133           myGrid.getPads(segments[iseg].sX0Entrance()+segmentSizeinX0*0.5);
01134           myGrid.setSpotEnergy(energy);
01135           myGrid.addHit(0.,0.);
01136           ilastEcal=iseg;
01137         }
01138       // Check for end of loop:
01139       if(segments[iseg].material()==CaloSegment::HCAL)
01140         {
01141           ifirstHcal=iseg;
01142         }
01143     }
01144   
01145   // Position of Ecal Exit
01146   math::XYZVector ecalExit;
01147   if(ilastEcal>=0)
01148     math::XYZVector ecalExit=segments[ilastEcal].exit();
01149   
01150   // Position of HCAL entrance
01151   math::XYZVector hcalEntrance;
01152   if(ifirstHcal>=0)
01153     hcalEntrance=segments[ifirstHcal].entrance();
01154 
01155   // dummy HCAL exit, just to test the FSimTrack saving mechanism
01156   math::XYZVector hcalExit;
01157   if(ifirstHcal>=0)
01158     hcalExit=segments[ifirstHcal].exit();
01159 
01160 
01161   // Build the FAMOS HCAL 
01162   HcalHitMaker myHcalHitMaker(myGrid,(unsigned)2);     
01163   // float mipenergy=0.1;
01164   // Create the helix with the stepping helix propagator
01165   // to add a hit, just do
01166   //  myHcalHitMaker.setSpotEnergy(mipenergy);
01167   // myHcalHitMaker.addHit(hcalEntrance);
01171   int ilastHcal=-1;
01172   float mipenergy=0.0;
01173   EnergyLossSimulator* energyLossHCAL = 0;
01174   // Implementation of Muon Brem Effect in HCAL (Sandro Fonseca de Souza and Andre Sznajder UERJ/Brazil)
01175   //Date 01/16/2011
01176   MuonBremsstrahlungSimulator* muonBremHCAL = 0;
01177  
01178   if (theMuonHcalEffects) energyLossHCAL = theMuonHcalEffects->energyLossSimulator();
01179   // Muon Brem effect
01180   if (theMuonHcalEffects) muonBremHCAL = theMuonHcalEffects->muonBremsstrahlungSimulator(); 
01181  
01182   if(ifirstHcal>0 && energyLossHCAL){
01183     for(unsigned iseg=ifirstHcal;iseg<nsegments;++iseg)
01184       {
01185         float segmentSizeinX0=segments[iseg].X0length();
01186         if (segmentSizeinX0>0.001 && segments[iseg].material()==CaloSegment::HCAL ) {
01187           // The energy loss simulator
01188           float charge = (float)(myTrack.charge());
01189           ParticlePropagator theMuon(moment,trackPosition,charge,0);
01190           theMuon.setID(-(int)charge*13);
01191           energyLossHCAL->updateState(theMuon, segmentSizeinX0);
01192           mipenergy = energyLossHCAL->deltaMom().E();
01193           moment -= energyLossHCAL->deltaMom();
01194           myHcalHitMaker.setSpotEnergy(mipenergy);
01195           myHcalHitMaker.addHit(segments[iseg].entrance());
01196         } 
01197         if(segments[iseg].material()==CaloSegment::HCAL)
01198           {
01199             ilastHcal=iseg;
01200           }
01201       }
01202   }
01203   if(ilastHcal>=0) // Update hcalExit position from 'dummy' HCAL entrance to 'staight line' HCAL exit
01204     hcalExit=segments[ilastHcal].exit();
01205 
01210   //
01211 
01212 
01213 
01214   // Copy the muon SimTrack (Only for Energy loss)
01215   FSimTrack muonTrack(myTrack);
01216   if(energyLossHCAL) {
01217     muonTrack.setTkPosition(hcalExit);
01218     muonTrack.setTkMomentum(moment);
01219   } else if(energyLossECAL) {
01220     muonTrack.setTkPosition(ecalExit);
01221     muonTrack.setTkMomentum(moment);
01222   } // else just leave tracker surface position and momentum...  
01223 
01224   muonSimTracks.push_back(muonTrack);
01225 
01226 
01227   // no need to change below this line
01228   std::map<unsigned,float>::const_iterator mapitr;
01229   std::map<unsigned,float>::const_iterator endmapitr;
01230   if(myTrack.onEcal() > 0) {
01231     // Save ECAL hits 
01232     endmapitr=myGrid.getHits().end();
01233     for(mapitr=myGrid.getHits().begin(); mapitr!=endmapitr; ++mapitr) {
01234       double energy = mapitr->second;
01235       if(onECAL==1)
01236         {
01237           updateMap(EBDetId(mapitr->first).hashedIndex(),energy,myTrack.id(),EBMapping_,firedCellsEB_);
01238         }      
01239       else if(onECAL==2)
01240         {
01241           updateMap(EEDetId(mapitr->first).hashedIndex(),energy,myTrack.id(),EEMapping_,firedCellsEE_);
01242         }
01243       
01244       if(debug_)
01245         LogDebug("FastCalorimetry") << " ECAL cell " << mapitr->first << " added,  E = " 
01246                                     << energy << std::endl;  
01247     }
01248   }
01249       
01250   // Save HCAL hits
01251   endmapitr=myHcalHitMaker.getHits().end();
01252   for(mapitr=myHcalHitMaker.getHits().begin(); mapitr!=endmapitr; ++mapitr) {
01253     double energy = mapitr->second;
01254     {
01255       updateMap(HcalDetId(mapitr->first).hashed_index(),energy,myTrack.id(),HMapping_,firedCellsHCAL_);
01256     }
01257     if(debug_)
01258       LogDebug("FastCalorimetry") << " HCAL cell "  
01259                                   << mapitr->first << " added    E = " 
01260                                   << mapitr->second << std::endl;  
01261   }
01262   
01263   if(debug_)
01264     LogDebug("FastCalorimetry") << std::endl << " FASTEnergyReconstructor::MipShowerSimulation  finished "
01265          << std::endl;
01266 }
01267 
01268 
01269 void CalorimetryManager::readParameters(const edm::ParameterSet& fastCalo) {
01270 
01271   edm::ParameterSet ECALparameters = fastCalo.getParameter<edm::ParameterSet>("ECAL");
01272 
01273   evtsToDebug_ = fastCalo.getUntrackedParameter<std::vector<unsigned int> >("EvtsToDebug",std::vector<unsigned>());
01274   debug_ = fastCalo.getUntrackedParameter<bool>("Debug");
01275 
01276   gridSize_ = ECALparameters.getParameter<int>("GridSize");
01277   spotFraction_ = ECALparameters.getParameter<double>("SpotFraction");
01278   pulledPadSurvivalProbability_ = ECALparameters.getParameter<double>("FrontLeakageProbability");
01279   crackPadSurvivalProbability_ = ECALparameters.getParameter<double>("GapLossProbability");
01280   theCoreIntervals_ = ECALparameters.getParameter<std::vector<double> >("CoreIntervals");
01281   theTailIntervals_ = ECALparameters.getParameter<std::vector<double> >("TailIntervals");
01282   
01283   RCFactor_ = ECALparameters.getParameter<double>("RCFactor");
01284   RTFactor_ = ECALparameters.getParameter<double>("RTFactor");
01285   radiusFactor_ = ECALparameters.getParameter<double>("RadiusFactor");
01286   radiusPreshowerCorrections_ = ECALparameters.getParameter<std::vector<double> >("RadiusPreshowerCorrections");
01287   mipValues_ = ECALparameters.getParameter<std::vector<double> >("MipsinGeV");
01288   simulatePreshower_ = ECALparameters.getParameter<bool>("SimulatePreshower");
01289 
01290   if(gridSize_ <1) gridSize_= 7;
01291   if(pulledPadSurvivalProbability_ <0. || pulledPadSurvivalProbability_>1 ) pulledPadSurvivalProbability_= 1.;
01292   if(crackPadSurvivalProbability_ <0. || crackPadSurvivalProbability_>1 ) crackPadSurvivalProbability_= 0.9;
01293   
01294   LogInfo("FastCalorimetry") << " Fast ECAL simulation parameters " << std::endl;
01295   LogInfo("FastCalorimetry") << " =============================== " << std::endl;
01296   if(simulatePreshower_)
01297     LogInfo("FastCalorimetry") << " The preshower is present " << std::endl;
01298   else
01299     LogInfo("FastCalorimetry") << " The preshower is NOT present " << std::endl;
01300   LogInfo("FastCalorimetry") << " Grid Size : " << gridSize_  << std::endl; 
01301   if(spotFraction_>0.) 
01302     LogInfo("FastCalorimetry") << " Spot Fraction : " << spotFraction_ << std::endl;
01303   else
01304     {
01305       LogInfo("FastCalorimetry") << " Core of the shower " << std::endl;
01306       for(unsigned ir=0; ir < theCoreIntervals_.size()/2;++ir)
01307         {
01308           LogInfo("FastCalorimetry") << " r < " << theCoreIntervals_[ir*2] << " R_M : " << theCoreIntervals_[ir*2+1] << "        ";
01309         }
01310       LogInfo("FastCalorimetry") << std::endl;
01311         
01312       LogInfo("FastCalorimetry") << " Tail of the shower " << std::endl;
01313       for(unsigned ir=0; ir < theTailIntervals_.size()/2;++ir)
01314         {
01315           LogInfo("FastCalorimetry") << " r < " << theTailIntervals_[ir*2] << " R_M : " << theTailIntervals_[ir*2+1] << "        ";
01316         }
01317       LogInfo("FastCalotimetry") << "Radius correction factor " << radiusFactor_ << std::endl;
01318       LogInfo("FastCalorimetry") << std::endl;
01319       if(mipValues_.size()>2)   {
01320         LogInfo("FastCalorimetry") << "Improper number of parameters for the preshower ; using 95keV" << std::endl;
01321         mipValues_.clear();
01322         mipValues_.resize(2,0.000095);
01323         }
01324     }
01325 
01326   LogInfo("FastCalorimetry") << " FrontLeakageProbability : " << pulledPadSurvivalProbability_ << std::endl;
01327   LogInfo("FastCalorimetry") << " GapLossProbability : " << crackPadSurvivalProbability_ << std::endl;
01328 
01329   
01330   // RespCorrP: p (momentum), ECAL and HCAL corrections = f(p)
01331   edm::ParameterSet CalorimeterParam = fastCalo.getParameter<edm::ParameterSet>("CalorimeterProperties");
01332 
01333   rsp = CalorimeterParam.getParameter<std::vector<double> >("RespCorrP");
01334    LogInfo("FastCalorimetry") << " RespCorrP (rsp) size " << rsp.size() << std::endl;
01335 
01336   if( rsp.size()%3 !=0 )  {
01337     LogInfo("FastCalorimetry") 
01338       << " RespCorrP size is wrong -> no corrections applied !!!" 
01339       << std::endl;
01340 
01341       p_knots.push_back(14000.);
01342       k_e.push_back    (1.);
01343       k_h.push_back    (1.);
01344   }
01345   else {
01346     for(unsigned i = 0; i < rsp.size(); i += 3) { 
01347      LogInfo("FastCalorimetry") << "i = " << i/3 << "   p = " << rsp [i] 
01348                                 << "   k_e(p) = " << rsp[i+1] 
01349                                 << "   k_e(p) = " << rsp[i+2] << std::endl; 
01350       
01351       p_knots.push_back(rsp[i]);
01352       k_e.push_back    (rsp[i+1]);
01353       k_h.push_back    (rsp[i+2]); 
01354     }
01355   }  
01356  
01357 
01358   //FR
01359   edm::ParameterSet HCALparameters = fastCalo.getParameter<edm::ParameterSet>("HCAL");
01360   optionHDSim_ = HCALparameters.getParameter<int>("SimOption");
01361   hdGridSize_  = HCALparameters.getParameter<int>("GridSize");
01362   hdSimMethod_ = HCALparameters.getParameter<int>("SimMethod");
01363   //RF
01364 
01365   unfoldedMode_ = fastCalo.getUntrackedParameter<bool>("UnfoldedMode",false);
01366 }
01367 
01368 
01369 void CalorimetryManager::updateMap(uint32_t cellid,float energy,int id,std::map<uint32_t,std::vector<std::pair<int,float> > > & mymap)
01370 {
01371   //  std::cout << " updateMap " << std::endl;
01372   std::map<unsigned,std::vector<std::pair<int,float> > >::iterator cellitr;
01373   cellitr = mymap.find(cellid);
01374   if(!unfoldedMode_) id=0;
01375   if( cellitr==mymap.end())
01376     {      
01377       std::vector<std::pair<int,float> > myElement;
01378       myElement.push_back(std::pair<int,float> (id,energy));
01379       mymap[cellid]=myElement;
01380     }
01381   else
01382     {
01383       if(!unfoldedMode_)
01384         {
01385           cellitr->second[0].second+=energy;
01386         }
01387       else
01388         cellitr->second.push_back(std::pair<int,float>(id,energy));
01389     }
01390 }
01391 
01392 void CalorimetryManager::updateMap(int hi,float energy,int tid,std::vector<std::vector<std::pair<int,float> > > & mymap, std::vector<int>& firedCells)
01393 {
01394   // Standard case first : one entry per cell 
01395   if(!unfoldedMode_)
01396     {
01397       // if new entry, update the list 
01398       if(mymap[hi].size()==0)
01399         {
01400           firedCells.push_back(hi);
01401           mymap[hi].push_back(std::pair<int,float>(0,energy));
01402         }
01403       else
01404         mymap[hi][0].second+=energy;
01405     }
01406   else
01407     {
01408       //      std::cout << "update map " << mymap[hi].size() << " " << hi << std::setw(8) << std::setprecision(6) <<  energy ;
01409       //      std::cout << " " << mymap[hi][0].second << std::endl;
01410       // the minimal size is always 1 ; in this case, no push_back 
01411       if(mymap[hi].size()==0)
01412         {
01413           //      if(tid==0) std::cout << " Shit ! " << std::endl;
01414           firedCells.push_back(hi);
01415         }
01416 
01417       mymap[hi].push_back(std::pair<int,float>(tid,energy));
01418     }
01419   
01420 }
01421 
01422 
01423 void CalorimetryManager::respCorr(double p) {
01424 
01425   int sizeP = p_knots.size();
01426 
01427   if(sizeP <= 1) {
01428     ecorr = 1.;
01429     hcorr = 1.;
01430   }
01431   else {
01432     int ip = -1;    
01433     for (int i = 0; i < sizeP; i++) { 
01434       if (p < p_knots[i]) { ip = i; break;}
01435     }
01436     if (ip == 0) {
01437       ecorr = k_e[0];
01438       hcorr = k_h[0];
01439     }
01440     else {
01441       if(ip == -1) {
01442         ecorr = k_e[sizeP-1];
01443         hcorr = k_h[sizeP-1];
01444       } 
01445       else {
01446         double x1 =  p_knots[ip-1];
01447         double x2 =  p_knots[ip];
01448         double y1 =  k_e[ip-1];
01449         double y2 =  k_e[ip];
01450         
01451         if(x1 == x2) {
01452           //        std::cout << " equal p_knots values!!! " << std::endl;
01453         }       
01454       
01455         ecorr = (y1 + (y2 - y1) * (p - x1)/(x2 - x1));
01456         
01457         y1 =  k_h[ip-1];
01458         y2 =  k_h[ip];
01459         hcorr = (y1 + (y2 - y1) * (p - x1)/(x2 - x1)); 
01460         
01461       }
01462     }
01463   }
01464 
01465   if(debug_)
01466     LogDebug("FastCalorimetry") << " p, ecorr, hcorr = " << p << " "  
01467                                 << ecorr << "  " << hcorr << std::endl;
01468         
01469 }
01470 
01471 
01472 void CalorimetryManager::loadFromEcalBarrel(edm::PCaloHitContainer & c) const
01473 { 
01474   unsigned size=firedCellsEB_.size();
01475   //  float sum=0.;
01476   for(unsigned ic=0;ic<size;++ic)
01477     {
01478       int hi=firedCellsEB_[ic];
01479       if(!unfoldedMode_)
01480         {
01481           c.push_back(PCaloHit(EBDetId::unhashIndex(hi),EBMapping_[hi][0].second,0.,0));
01482           //      std::cout << "Adding " << hi << " " << EBDetId::unhashIndex(hi) << " " ;
01483           //      std::cout << EBMapping_[hi][0].second << " " << EBMapping_[hi][0].first << std::endl;
01484         }
01485       else
01486         {
01487           unsigned npart=EBMapping_[hi].size();
01488           for(unsigned ip=0;ip<npart;++ip)
01489             {
01490               c.push_back(PCaloHit(EBDetId::unhashIndex(hi),EBMapping_[hi][ip].second,0.,
01491                                    EBMapping_[hi][ip].first));
01492 
01493             }
01494         }
01495         
01496       //      sum+=cellit->second;
01497     }
01498   
01499 //  for(unsigned ic=0;ic<61200;++ic) 
01500 //    { 
01501 //      EBDetId myCell(EBDetId::unhashIndex(ic)); 
01502 //      if(!myCell.null()) 
01503 //        { 
01504 //        float total=0.;
01505 //        for(unsigned id=0;id<EBMapping_[ic].size();++id)
01506 //          total+=EBMapping_[ic][id].second;
01507 //        if(EBMapping_[ic].size()>0)
01508 //          std::cout << "Adding " << ic << " " << myCell << " " << std::setprecision(8) <<total << std::endl; 
01509 //        } 
01510 //    } 
01511 
01512 
01513   //  std::cout << " SUM : " << sum << std::endl;
01514   //  std::cout << " Added " <<c.size() << " hits " <<std::endl;
01515 }
01516 
01517 
01518 void CalorimetryManager::loadFromEcalEndcap(edm::PCaloHitContainer & c) const
01519 {
01520   unsigned size=firedCellsEE_.size();
01521   //  float sum=0.;
01522   for(unsigned ic=0;ic<size;++ic)
01523     {
01524       int hi=firedCellsEE_[ic];
01525       if(!unfoldedMode_)
01526         c.push_back(PCaloHit(EEDetId::unhashIndex(hi),EEMapping_[hi][0].second,0.,0));
01527       else
01528         {
01529           unsigned npart=EEMapping_[hi].size();
01530           for(unsigned ip=0;ip<npart;++ip)
01531             c.push_back(PCaloHit(EEDetId::unhashIndex(hi),EEMapping_[hi][ip].second,0.,
01532                                  EEMapping_[hi][ip].first));
01533         }
01534         
01535       //      sum+=cellit->second;
01536     }
01537   //  std::cout << " SUM : " << sum << std::endl;
01538   //  std::cout << " Added " <<c.size() << " hits " <<std::endl;
01539 }
01540 
01541 void CalorimetryManager::loadFromHcal(edm::PCaloHitContainer & c) const
01542 {
01543   unsigned size=firedCellsHCAL_.size();
01544   //  float sum=0.;
01545   for(unsigned ic=0;ic<size;++ic)
01546     {
01547       int hi=firedCellsHCAL_[ic];
01548       if(!unfoldedMode_)
01549         c.push_back(PCaloHit(theDetIds_[hi],HMapping_[hi][0].second,0.,0));
01550       else
01551         {
01552           unsigned npart=HMapping_[hi].size();
01553           for(unsigned ip=0;ip<npart;++ip)
01554             c.push_back(PCaloHit(theDetIds_[hi],HMapping_[hi][ip].second,0.,
01555                                  HMapping_[hi][ip].first));
01556         }
01557         
01558       //      sum+=cellit->second;
01559     }
01560   //  std::cout << " SUM : " << sum << std::endl;
01561   //  std::cout << " Added " <<c.size() << " hits " <<std::endl;
01562 }
01563 
01564 void CalorimetryManager::loadFromPreshower(edm::PCaloHitContainer & c) const
01565 {
01566   std::map<uint32_t,std::vector<std::pair< int,float> > >::const_iterator cellit;
01567   std::map<uint32_t,std::vector<std::pair <int,float> > >::const_iterator preshEnd=ESMapping_.end();
01568   
01569   for(cellit=ESMapping_.begin();cellit!=preshEnd;++cellit)
01570     {
01571       if(!unfoldedMode_)        
01572         c.push_back(PCaloHit(cellit->first,cellit->second[0].second,0.,0));
01573       else
01574         {
01575           unsigned npart=cellit->second.size();
01576           for(unsigned ip=0;ip<npart;++ip)
01577             {
01578               c.push_back(PCaloHit(cellit->first,cellit->second[ip].second,0.,cellit->second[ip].first));
01579             }
01580         }
01581     }
01582 }
01583 
01584 
01585 // The main danger in this method is to screw up to relationships between particles
01586 // So, the muon FSimTracks created by FSimEvent.cc are simply to be updated 
01587 void CalorimetryManager::loadMuonSimTracks(edm::SimTrackContainer &muons) const
01588 {
01589   unsigned size=muons.size();
01590   for(unsigned i=0; i<size;++i)
01591     {
01592       int id=muons[i].trackId();
01593       if(abs(muons[i].type())!=13) continue;
01594       // identify the corresponding muon in the local collection
01595 
01596       std::vector<FSimTrack>::const_iterator itcheck=find_if(muonSimTracks.begin(),muonSimTracks.end(),FSimTrackEqual(id));
01597       if(itcheck!=muonSimTracks.end())
01598         {
01599           muons[i].setTkPosition(itcheck->trackerSurfacePosition());
01600           muons[i].setTkMomentum(itcheck->trackerSurfaceMomentum());
01601 //        std::cout << " Found the SimTrack " << std::endl;
01602 //        std::cout << *itcheck << std::endl;
01603 //        std::cout << "SimTrack Id "<< id << " " << muons[i] << " " << std::endl;
01604         }
01605 //      else
01606 //      {
01607 //        std::cout << " Calorimetery Manager : this should really not happen " << std::endl;
01608 //        std::cout << " Was looking for " << id << " " << muons[i] << std::endl;
01609 //        for(unsigned i=0;i<muonSimTracks.size();++i)
01610 //          std::cout << muonSimTracks[i] << std::endl;
01611 //      }
01612     }
01613 
01614 }
01615