CMS 3D CMS Logo

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