CMS 3D CMS Logo

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