CMS 3D CMS Logo

/data/git/CMSSW_5_3_11_patch5/src/FastSimulation/ShowerDevelopment/src/EMShower.cc

Go to the documentation of this file.
00001 //FAMOS Headers
00002 #include "FastSimulation/ShowerDevelopment/interface/EMShower.h"
00003 #include "FastSimulation/CaloHitMakers/interface/EcalHitMaker.h"
00004 #include "FastSimulation/CaloHitMakers/interface/PreshowerHitMaker.h"
00005 #include "FastSimulation/CaloHitMakers/interface/HcalHitMaker.h"
00006 
00007 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00008 #include "FastSimulation/Utilities/interface/GammaFunctionGenerator.h"
00009 
00010 #include "DQMServices/Core/interface/DQMStore.h"
00011 #include "DQMServices/Core/interface/MonitorElement.h"
00012 
00013 
00014 #include <cmath>
00015 
00016 //#include "FastSimulation/Utilities/interface/Histos.h"
00017 
00018 using std::vector;
00019 
00020 
00021 EMShower::EMShower(const RandomEngine* engine,
00022                    GammaFunctionGenerator* gamma,
00023                    EMECALShowerParametrization* const myParam, 
00024                    vector<const RawParticle*>* const myPart, 
00025                    DQMStore * const dbeIn,
00026                    EcalHitMaker * const myGrid,
00027                    PreshowerHitMaker * const myPresh,
00028                    bool bFixedLength)
00029                          
00030   : theParam(myParam), 
00031     thePart(myPart), 
00032     theGrid(myGrid),
00033     thePreshower(myPresh),
00034     random(engine),
00035     myGammaGenerator(gamma),
00036     bFixedLength_(bFixedLength)
00037 { 
00038 
00039   // Get the Famos Histos pointer
00040   //  myHistos = Histos::instance();
00041   //  myGammaGenerator = GammaFunctionGenerator::instance();
00042   stepsCalculated=false;
00043   hasPreshower = myPresh!=NULL;
00044   theECAL = myParam->ecalProperties();
00045   theHCAL = myParam->hcalProperties();
00046   theLayer1 = myParam->layer1Properties();
00047   theLayer2 = myParam->layer2Properties();
00048 
00049   
00050   double fotos = theECAL->photoStatistics() 
00051                * theECAL->lightCollectionEfficiency();
00052 
00053   dbe = dbeIn;
00054 
00055   nPart = thePart->size();
00056   totalEnergy = 0.;
00057   globalMaximum = 0.;
00058   double meanDepth=0.;
00059   // Initialize the shower parameters for each particle
00060 
00061   if (dbe) {
00062     dbe->cd();             
00063     if (!dbe->get("EMShower/NumberOfParticles")) {}//std::cout << "NOT FOUND IN Shower.cc" << std::endl;}
00064         else {
00065           dbe->get("EMShower/NumberOfParticles")->Fill(nPart);
00066         }
00067     }
00068 
00069 
00070   for ( unsigned int i=0; i<nPart; ++i ) {
00071     //    std::cout << " AAA " << *(*thePart)[i] << std::endl;
00072     // The particle and the shower energy
00073     Etot.push_back(0.);
00074     E.push_back(((*thePart)[i])->e());
00075     totalEnergy+=E[i];
00076     
00077 
00078 
00079     if (dbe) {
00080         dbe->cd();             
00081         if (!dbe->get("EMShower/ParticlesEnergy")) {}//std::cout << "NOT FOUND IN Shower.cc" << std::endl;}
00082         else {
00083           dbe->get("EMShower/ParticlesEnergy")->Fill(log10(E[i]));
00084         }
00085     }
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093     double lny = std::log ( E[i] / theECAL->criticalEnergy() );
00094 
00095     // Average and Sigma for T and alpha
00096     double theMeanT        = myParam->meanT(lny);
00097     double theMeanAlpha    = myParam->meanAlpha(lny);
00098     double theMeanLnT      = myParam->meanLnT(lny);
00099     double theMeanLnAlpha  = myParam->meanLnAlpha(lny);
00100     double theSigmaLnT     = myParam->sigmaLnT(lny);
00101     double theSigmaLnAlpha = myParam->sigmaLnAlpha(lny);
00102 
00103     // The correlation matrix
00104     double theCorrelation = myParam->correlationAlphaT(lny);
00105     double rhop = std::sqrt( (1.+theCorrelation)/2. );
00106     double rhom = std::sqrt( (1.-theCorrelation)/2. );
00107 
00108     // The number of spots in ECAL / HCAL
00109     theNumberOfSpots.push_back(myParam->nSpots(E[i]));
00110     //    theNumberOfSpots.push_back(myParam->nSpots(E[i])*spotFraction);
00111     //theNumberOfSpots = random->poissonShoot(myParam->nSpots(myPart->e()));
00112 
00113     // Photo-statistics
00114     photos.push_back(E[i] * fotos);
00115     
00116     // The longitudinal shower development parameters
00117     // Fluctuations of alpha, T and beta
00118     double z1=0.;
00119     double z2=0.;
00120     double aa=0.;
00121 
00122     // Protect against too large fluctuations (a < 1) for small energies
00123     while ( aa <= 1. ) {
00124       z1 = random->gaussShoot(0.,1.);
00125       z2 = random->gaussShoot(0.,1.);
00126       aa = std::exp(theMeanLnAlpha + theSigmaLnAlpha * (z1*rhop-z2*rhom));
00127     }
00128 
00129     a.push_back(aa);
00130     T.push_back(std::exp(theMeanLnT + theSigmaLnT * (z1*rhop+z2*rhom)));
00131     b.push_back((a[i]-1.)/T[i]);
00132     maximumOfShower.push_back((a[i]-1.)/b[i]);
00133     globalMaximum += maximumOfShower[i]*E[i];
00134     meanDepth += a[i]/b[i]*E[i];
00135     //    std::cout << " Adding max " << maximumOfShower[i] << " " << E[i] << " " <<maximumOfShower[i]*E[i] << std::endl; 
00136     //    std::cout << std::setw(8) << std::setprecision(5) << " a /b " << a[i] << " " << b[i] << std::endl;
00137     Ti.push_back(
00138                  a[i]/b[i] * (std::exp(theMeanLnAlpha)-1.) / std::exp(theMeanLnAlpha));
00139   
00140     // The parameters for the number of energy spots
00141     TSpot.push_back(theParam->meanTSpot(theMeanT));
00142     aSpot.push_back(theParam->meanAlphaSpot(theMeanAlpha));
00143     bSpot.push_back((aSpot[i]-1.)/TSpot[i]);
00144     //    myHistos->fill("h7000",a[i]);
00145     //    myHistos->fill("h7002",E[i],a[i]);
00146   }
00147 //  std::cout << " PS1 : " << myGrid->ps1TotalX0()
00148 //         << " PS2 : " << myGrid->ps2TotalX0()
00149 //         << " ECAL : " << myGrid->ecalTotalX0()
00150 //         << " HCAL : " << myGrid->hcalTotalX0() 
00151 //         << " Offset : " << myGrid->x0DepthOffset()
00152 //         << std::endl;
00153 
00154  globalMaximum/=totalEnergy;
00155  meanDepth/=totalEnergy;
00156  // std::cout << " Total Energy " << totalEnergy << " Global max " << globalMaximum << std::endl;
00157 }
00158 
00159 void EMShower::prepareSteps()
00160 {
00161   //  TimeMe theT("EMShower::compute");
00162   
00163   // Determine the longitudinal intervals
00164   //  std::cout << " EMShower compute" << std::endl;
00165   double dt;
00166   double radlen;
00167   int stps;
00168   int first_Ecal_step=0;
00169   int last_Ecal_step=0;
00170 
00171   // The maximum is in principe 8 (with 5X0 steps in the ECAL)
00172   steps.reserve(24);
00173 
00174   /*  
00175   std::cout << " PS1 : " << theGrid->ps1TotalX0()
00176             << " PS2 : " << theGrid->ps2TotalX0()
00177             << " PS2 and ECAL : " << theGrid->ps2eeTotalX0()
00178             << " ECAL : " << theGrid->ecalTotalX0()
00179             << " HCAL : " << theGrid->hcalTotalX0() 
00180             << " Offset : " << theGrid->x0DepthOffset()
00181             << std::endl;
00182   */
00183   
00184   radlen = -theGrid->x0DepthOffset();
00185   
00186   // Preshower Layer 1
00187   radlen += theGrid->ps1TotalX0();
00188   if ( radlen > 0. ) {
00189     steps.push_back(Step(0,radlen));
00190     radlen = 0.;
00191   }
00192   
00193   // Preshower Layer 2
00194   radlen += theGrid->ps2TotalX0();
00195   if ( radlen > 0. ) {
00196     steps.push_back(Step(1,radlen));
00197     radlen = 0.;
00198   }
00199   
00200   // add a step between preshower and ee
00201   radlen += theGrid->ps2eeTotalX0();
00202   if ( radlen > 0.) {
00203     steps.push_back(Step(5,radlen));
00204     radlen = 0.;  
00205   }
00206   
00207   // ECAL
00208   radlen += theGrid->ecalTotalX0();
00209 
00210   if ( radlen > 0. ) {
00211 
00212     if (!bFixedLength_){
00213       stps=(int)((radlen+2.5)/5.);
00214       //    stps=(int)((radlen+.5)/1.);
00215       if ( stps == 0 ) stps = 1;
00216       dt = radlen/(double)stps;
00217       Step step(2,dt);
00218       first_Ecal_step=steps.size();
00219       for ( int ist=0; ist<stps; ++ist )
00220         steps.push_back(step);
00221       last_Ecal_step=steps.size()-1;
00222       radlen = 0.;
00223     } else {
00224       dt = 1.0;
00225       stps = static_cast<int>(radlen); 
00226       if (stps == 0) stps = 1;
00227       Step step(2,dt);
00228       first_Ecal_step=steps.size();
00229       for ( int ist=0; ist<stps; ++ist ) steps.push_back(step);
00230       dt = radlen-stps;
00231       if (dt>0) {
00232         Step stepLast (2,dt);
00233         steps.push_back(stepLast);
00234       }
00235       last_Ecal_step=steps.size()-1;
00236       //      std::cout << "radlen = "  << radlen << " stps = " << stps << " dt = " << dt << std::endl;
00237       radlen = 0.;
00238 
00239     }
00240   } 
00241 
00242   // I should had a gap here ! 
00243  
00244  // HCAL 
00245  radlen += theGrid->hcalTotalX0();
00246  if ( radlen > 0. ) {
00247    double dtFrontHcal=theGrid->totalX0()-theGrid->hcalTotalX0();
00248    // One single step for the full HCAL
00249    if(dtFrontHcal<30.) 
00250      {
00251        dt=30.-dtFrontHcal;
00252        Step step(3,dt);
00253        steps.push_back(step);
00254      }
00255  } 
00256 
00257  nSteps=steps.size();
00258  if(nSteps==0) return;
00259  double ESliceTot=0.;
00260  double MeanDepth=0.;
00261  depositedEnergy.resize(nSteps);
00262  meanDepth.resize(nSteps);
00263  double t=0.;
00264 
00265  int offset=0;
00266  for(unsigned iStep=0;iStep<nSteps;++iStep)
00267    {
00268      ESliceTot=0.;
00269      MeanDepth=0.;
00270      double realTotalEnergy=0;
00271      dt=steps[iStep].second;
00272      t+=dt;
00273      for ( unsigned int i=0; i<nPart; ++i ) {
00274        depositedEnergy[iStep].push_back(deposit(t,a[i],b[i],dt));     
00275        ESliceTot +=depositedEnergy[iStep][i];
00276        MeanDepth += deposit(t,a[i]+1.,b[i],dt)/b[i]*a[i];
00277        realTotalEnergy+=depositedEnergy[iStep][i]*E[i];
00278      }
00279 
00280      if( ESliceTot > 0. )  // can happen for the shower tails; this depth will be skipped anyway
00281        MeanDepth/=ESliceTot;
00282      else
00283        MeanDepth=t-dt;
00284 
00285      meanDepth[iStep]=MeanDepth;
00286      if(realTotalEnergy<0.001)
00287        {
00288          offset-=1;
00289        }
00290    }
00291 
00292  innerDepth=meanDepth[first_Ecal_step];
00293  if(last_Ecal_step+offset>=0)
00294    outerDepth=meanDepth[last_Ecal_step+offset];
00295  else
00296    outerDepth=innerDepth;
00297 
00298  stepsCalculated=true;
00299 }
00300 
00301 void
00302 EMShower::compute() {
00303 
00304   double t = 0.;
00305   double dt = 0.;
00306   if(!stepsCalculated) prepareSteps();
00307 
00308   // Prepare the grids in EcalHitMaker
00309   // theGrid->setInnerAndOuterDepth(innerDepth,outerDepth);
00310   float pstot=0.;
00311   float ps2tot=0.;
00312   float ps1tot=0.;
00313   bool status=false; 
00314   //  double E1 = 0.;  // Energy layer 1
00315   //  double E2 = 0.;  // Energy layer 2
00316   //  double n1 = 0.;  // #mips layer 1
00317   //  double n2 = 0.;  // #mips layer 2
00318   //  double E9 = 0.;  // Energy ECAL
00319 
00320   // Loop over all segments for the longitudinal development
00321   double totECalc = 0;
00322   
00323 
00324 
00325   for (unsigned iStep=0; iStep<nSteps; ++iStep ) {
00326     
00327     // The length of the shower in this segment
00328     dt = steps[iStep].second;
00329 
00330     //    std::cout << " Detector " << steps[iStep].first << " t " << t << " " << dt << std::endl;
00331 
00332     // The elapsed length
00333     t += dt;
00334     
00335     // In what detector are we ?
00336     unsigned detector=steps[iStep].first;
00337        
00338     bool presh1 = detector==0;
00339     bool presh2 = detector==1;
00340     bool ecal = detector==2;
00341     bool hcal = detector==3;
00342     bool vfcal = detector==4;
00343     bool gap = detector==5;
00344 
00345     // Temporary. Will be removed 
00346     if ( theHCAL==NULL) hcal=false;
00347 
00348     // Keep only ECAL for now
00349     if ( vfcal ) continue;
00350 
00351     // Nothing to do in the gap
00352     if( gap ) continue;
00353 
00354     //    cout << " t = " << t << endl;
00355     // Build the grid of crystals at this ECAL depth
00356     // Actually, it might be useful to check if this grid is empty or not. 
00357     // If it is empty (because no crystal at this depth), it is of no use 
00358     // (and time consuming) to generate the spots
00359     
00360 
00361    // middle of the step
00362     double tt = t-0.5*dt; 
00363 
00364     double realTotalEnergy=0.;
00365     for ( unsigned int i=0; i<nPart; ++i ) {
00366       realTotalEnergy += depositedEnergy[iStep][i]*E[i];
00367     }
00368 
00369 //    std::cout << " Step " << tt << std::endl;
00370 //    std::cout << "ecal " << ecal << " hcal "  << hcal <<std::endl;
00371 
00372     // If the amount of energy is greater than 1 MeV, make a new grid
00373     // otherwise put in the previous one.    
00374     bool usePreviousGrid=(realTotalEnergy<0.001);   
00375 
00376     // If the amount of energy is greater than 1 MeV, make a new grid
00377     // otherwise put in the previous one.    
00378 
00379     // If less than 1 kEV. Just skip
00380     if(iStep>2&&realTotalEnergy<0.000001) continue;
00381 
00382     if (ecal && !usePreviousGrid) 
00383       {
00384         status=theGrid->getPads(meanDepth[iStep]);
00385       }
00386     if (hcal) 
00387       {
00388         status=theHcalHitMaker->setDepth(tt);
00389       }
00390     if((ecal || hcal) && !status) continue;
00391     
00392     bool detailedShowerTail=false;
00393     // check if a detailed treatment of the rear leakage should be applied
00394     if(ecal && !usePreviousGrid) 
00395       {
00396         detailedShowerTail=(t-dt > theGrid->getX0back());
00397       }
00398     
00399     // The particles of the shower are processed in parallel
00400     for ( unsigned int i=0; i<nPart; ++i ) {
00401 
00402       //      double Edepo=deposit(t,a[i],b[i],dt);
00403 
00404      //  integration of the shower profile between t-dt and t
00405       double dE = (!hcal)? depositedEnergy[iStep][i]:1.-deposit(a[i],b[i],t-dt);
00406 
00407       totECalc +=dE;
00408       
00409       if (dbe && fabs(dt-1.)< 1e-5 && ecal) {
00410         dbe->cd();             
00411         if (!dbe->get("EMShower/LongitudinalShape")) {}//std::cout << "NOT FOUND IN Shower.cc" << std::endl;}
00412         else {
00413           double dx = 1.;
00414           // dE is aready in relative units from 0 to 1
00415           dbe->get("EMShower/LongitudinalShape")->Fill(t, dE/dx);
00416         }
00417         //(dbe->get("TransverseShape"))->Fill(ri,log10(1./1000.*eSpot/0.2));
00418 
00419       }
00420 
00421 
00422 
00423        // no need to do the full machinery if there is ~nothing to distribute)
00424       if(dE*E[i]<0.000001) continue;
00425 
00426       if(detailedShowerTail)
00427         {
00428           myGammaGenerator->setParameters(floor(a[i]+0.5),b[i],t-dt);
00429         }
00430       
00431       // The number of energy spots (or mips)
00432       double nS = 0;
00433       
00434       // ECAL case : Account for photostatistics and long'al non-uniformity
00435       if (ecal) {
00436 
00437         dE = random->poissonShoot(dE*photos[i])/photos[i];
00438         double z0 = random->gaussShoot(0.,1.);
00439         dE *= 1. + z0*theECAL->lightCollectionUniformity();
00440 
00441         // Expected spot number
00442         nS = ( theNumberOfSpots[i] * gam(bSpot[i]*tt,aSpot[i]) 
00443                                    * bSpot[i] * dt 
00444                                    / tgamma(aSpot[i]) );
00445         
00446       // Preshower : Expected number of mips + fluctuation
00447       }
00448       else if ( hcal ) {
00449 
00450         nS = ( theNumberOfSpots[i] * gam(bSpot[i]*tt,aSpot[i]) 
00451                * bSpot[i] * dt 
00452                / tgamma(aSpot[i]))* theHCAL->spotFraction();
00453         double nSo = nS ;
00454         nS = random->poissonShoot(nS);
00455         // 'Quick and dirty' fix (but this line should be better removed):
00456         if( nSo > 0. && nS/nSo < 10.) dE *= nS/nSo;
00457 
00458 //      if(true)
00459 //        {
00460 //          std::cout << " theHCAL->spotFraction = " <<theHCAL->spotFraction() <<std::endl;
00461 //          std::cout << " nSpot Ecal : " << nSo/theHCAL->spotFraction() << " Final " << nS << std::endl;
00462 //        }
00463       }
00464       else if ( presh1 ) {
00465         
00466         nS = random->poissonShoot(dE*E[i]*theLayer1->mipsPerGeV());
00467         //      std::cout << " dE *E[i] (1)" << dE*E[i] << " " << dE*E[i]*theLayer1->mipsPerGeV() << "  "<< nS << std::endl;
00468         pstot+=dE*E[i];
00469         ps1tot+=dE*E[i];
00470         dE = nS/(E[i]*theLayer1->mipsPerGeV());
00471 
00472         //        E1 += dE*E[i]; 
00473         //      n1 += nS; 
00474         //      if (presh2) { E2 += SpotEnergy; ++n2; }
00475       
00476       } else if ( presh2 ) {
00477         
00478         nS = random->poissonShoot(dE*E[i]*theLayer2->mipsPerGeV());
00479         //      std::cout << " dE *E[i] (2) " << dE*E[i] << " " << dE*E[i]*theLayer2->mipsPerGeV() << "  "<< nS << std::endl;
00480         pstot+=dE*E[i];
00481         ps2tot+=dE*E[i];
00482         dE = nS/(E[i]*theLayer2->mipsPerGeV());
00483 
00484         //        E2 += dE*E[i]; 
00485         //      n2 += nS; 
00486         
00487       }
00488 
00489       //    myHistos->fill("h100",t,dE);
00490       
00491       // The lateral development parameters  
00492  
00493       // Energy of the spots
00494       double eSpot = (nS>0.) ? dE/nS : 0.;
00495       double SpotEnergy=eSpot*E[i];
00496 
00497       if(hasPreshower&&(presh1||presh2)) thePreshower->setSpotEnergy(0.00009);
00498       if(hcal) 
00499         {
00500           SpotEnergy*=theHCAL->hOverPi();
00501           theHcalHitMaker->setSpotEnergy(SpotEnergy);
00502         }
00503       // Poissonian fluctuations for the number of spots
00504       //    int nSpot = random->poissonShoot(nS);
00505       int nSpot = (int)(nS+0.5);
00506       
00507       
00508       // Fig. 11 (right) *** Does not match.
00509       //    myHistos->fill("h101",t,(double)nSpot/theNumberOfSpots);
00510       
00511       //double taui = t/T;
00512       double taui = tt/Ti[i];
00513       double proba = theParam->p(taui,E[i]);
00514       double theRC = theParam->rC(taui,E[i]);
00515       double theRT = theParam->rT(taui,E[i]);
00516       
00517       // Fig. 10
00518       //    myHistos->fill("h300",taui,theRC);
00519       //    myHistos->fill("h301",taui,theRT);
00520       //    myHistos->fill("h302",taui,proba);
00521       
00522          double dSpotsCore = 
00523         random->gaussShoot(proba*nSpot,std::sqrt(proba*(1.-proba)*nSpot));
00524       
00525       if(dSpotsCore<0) dSpotsCore=0;
00526       
00527       unsigned nSpots_core = (unsigned)(dSpotsCore+0.5);
00528       unsigned nSpots_tail = ((unsigned)nSpot>nSpots_core) ? nSpot-nSpots_core : 0;
00529       
00530       for(unsigned icomp=0;icomp<2;++icomp)
00531         {         
00532           
00533           double theR=(icomp==0) ? theRC : theRT ;    
00534           unsigned ncompspots=(icomp==0) ? nSpots_core : nSpots_tail;
00535           
00536           RadialInterval radInterval(theR,ncompspots,SpotEnergy,random);
00537           if(ecal)
00538             {
00539               if(icomp==0)
00540                 {
00541                   setIntervals(icomp,radInterval);
00542                 }
00543               else
00544                 {
00545                   setIntervals(icomp,radInterval);
00546                 }
00547             }
00548           else
00549             {
00550               radInterval.addInterval(100.,1.);// 100% of the spots
00551             }
00552           
00553           radInterval.compute();
00554            // irad = 0 : central circle; irad=1 : outside
00555 
00556            unsigned nrad=radInterval.nIntervals();
00557 
00558            for(unsigned irad=0;irad<nrad;++irad)
00559              {
00560                double spote=radInterval.getSpotEnergy(irad);
00561                if(ecal) theGrid->setSpotEnergy(spote);
00562                if(hcal) theHcalHitMaker->setSpotEnergy(spote);
00563                unsigned nradspots=radInterval.getNumberOfSpots(irad);
00564                double umin=radInterval.getUmin(irad);
00565                double umax=radInterval.getUmax(irad);
00566                // Go for the lateral development
00567                //              std::cout << "Couche " << iStep << " irad = " << irad << " Ene = " << E[i] << " eSpot = " << eSpot << " spote = " << spote << " nSpot = " << nS << std::endl;
00568 
00569                for ( unsigned  ispot=0; ispot<nradspots; ++ispot ) 
00570                  {
00571                    double z3=random->flatShoot(umin,umax);
00572                    double ri=theR * std::sqrt(z3/(1.-z3)) ;
00573 
00574 
00575 
00576                    //Fig. 12
00577                    /*
00578                    if ( 2. < t && t < 3. ) 
00579                      dbe->fill("h401",ri,1./1000.*eSpot/dE/0.2);
00580                    if ( 6. < t && t < 7. ) 
00581                      dbe->fill("h402",ri,1./1000.*eSpot/dE/0.2);
00582                    if ( 19. < t && t < 20. ) 
00583                      dbe->fill("h403",ri,1./1000.*eSpot/dE/0.2);
00584                    */
00585                    // Fig. 13 (top)
00586                    if (dbe && fabs(dt-1.)< 1e-5 && ecal) {
00587                      dbe->cd();             
00588                      if (!dbe->get("EMShower/TransverseShape")) {}//std::cout << "NOT FOUND IN Shower.cc" << std::endl;}
00589                      else {
00590                        double drho = 0.1;
00591                        double dx = 1;
00592                        // spote is a real energy we have to normalise it by E[i] which is the energy of the particle i
00593                        dbe->get("EMShower/TransverseShape")->Fill(ri,1/E[i]*spote/drho);
00594                        dbe->get("EMShower/ShapeRhoZ")->Fill(ri, t, 1/E[i]*spote/(drho*dx));
00595                      }
00596                    } else {
00597                      //              std::cout << "dt =  " << dt << " length = " << t << std::endl;  
00598                    }
00599                
00600 
00601                    // Generate phi
00602                    double phi = 2.*M_PI*random->flatShoot();
00603                    
00604                    // Add the hit in the crystal
00605                    //   if( ecal ) theGrid->addHit(ri*theECAL->moliereRadius(),phi);
00606                    // Now the *moliereRadius is done in EcalHitMaker
00607                    if ( ecal )
00608                      {
00609                        if(detailedShowerTail) 
00610                          {
00611                            //                      std::cout << "About to call addHitDepth " << std::endl;
00612                            double depth;
00613                            do
00614                              {
00615                                depth=myGammaGenerator->shoot();
00616                              }
00617                            while(depth>t);
00618                            theGrid->addHitDepth(ri,phi,depth);
00619                            //                      std::cout << " Done " << std::endl;
00620                          }
00621                        else
00622                          theGrid->addHit(ri,phi);
00623                      }
00624                    else if (hasPreshower&&presh1) thePreshower->addHit(ri,phi,1);
00625                    else if (hasPreshower&&presh2) thePreshower->addHit(ri,phi,2);
00626                    else if (hcal) 
00627                      {
00628                        //                      std::cout << " About to add a spot in the HCAL" << status << std::endl;
00629                        theHcalHitMaker->addHit(ri,phi);
00630                        //                      std::cout << " Added a spot in the HCAL" << status << std::endl;
00631                      }
00632                    //   if (ecal) E9 += SpotEnergy;
00633                    //   if (presh1) { E1 += SpotEnergy; ++n1; }
00634                    //   if (presh2) { E2 += SpotEnergy; ++n2; }
00635 
00636                    Etot[i] += spote;
00637                  }
00638              }
00639         }
00640       //      std::cout << " Done with the step " << std::endl;
00641       // The shower!
00642       //myHistos->fill("h500",theSpot.z(),theSpot.perp());
00643     }
00644     //    std::cout << " nPart " << nPart << std::endl;
00645   }
00646   //  std::cout << " Finshed the step loop " << std::endl;
00647   //  myHistos->fill("h500",E1+0.7*E2,E9);
00648   //  myHistos->fill("h501",n1+0.7*n2,E9);
00649   //  myHistos->fill("h400",n1);
00650   //  myHistos->fill("h401",n2);
00651   //  myHistos->fill("h402",E9+E1+0.7*E2);
00652   //  if(!standalone)theGrid->printGrid();
00653   double Etotal=0.;
00654   for(unsigned i=0;i<nPart;++i)
00655     {
00656       //      myHistos->fill("h10",Etot[i]);
00657       Etotal+=Etot[i];
00658     }
00659 
00660   //  std::cout << "Etotal = " << Etotal << " nPart = "<< nPart << std::endl; 
00661   //  std::cout << "totECalc = " << totECalc << std::endl;
00662 
00663   //  myHistos->fill("h20",Etotal);
00664   //  if(thePreshower)
00665   //    std::cout << " PS " << thePreshower->layer1Calibrated() << " " << thePreshower->layer2Calibrated() << " " << thePreshower->totalCalibrated() << " " << ps1tot << " " <<ps2tot << " " << pstot << std::endl;
00666 }
00667 
00668 
00669 double
00670 EMShower::gam(double x, double a) const {
00671   // A stupid gamma function
00672   return std::pow(x,a-1.)*std::exp(-x);
00673 }
00674 
00675 //double 
00676 //EMShower::deposit(double t, double a, double b, double dt) {
00677 //
00678 //  // The number of integration steps (about 1 / X0)
00679 //  int numberOfSteps = (int)dt+1;
00680 //
00681 //  // The size if the integration step
00682 //  double integrationstep = dt/(double)numberOfSteps;
00683 //
00684 //  // Half this size
00685 //  double halfis = 0.5*integrationstep;
00686 //
00687 //  double dE = 0.;
00688 //  
00689 //  for(double tt=t-dt+halfis;tt<t;tt+=integrationstep) {
00690 //
00691 //    // Simpson integration over each of these steps
00692 //    dE +=   gam(b*(tt-halfis),a) 
00693 //       + 4.*gam(b* tt        ,a)
00694 //       +    gam(b*(tt+halfis),a);
00695 //
00696 //  }
00697 //
00698 //  // Normalization
00699 //  dE *= b*integrationstep/tgamma(a)/6.;
00700 //
00701 //  // There we go.
00702 //  return dE;
00703 //}
00704 
00705 double
00706 EMShower::deposit(double t, double a, double b, double dt) {
00707   myIncompleteGamma.a().setValue(a);
00708   double b1=b*(t-dt);
00709   double b2=b*t;
00710   double result = 0.;  
00711   double rb1=(b1!=0.) ? myIncompleteGamma(b1) : 0.;
00712   double rb2=(b2!=0.) ?  myIncompleteGamma(b2) : 0.;
00713   result = (rb2-rb1);
00714   return result;
00715 }
00716 
00717 
00718 void EMShower::setIntervals(unsigned icomp,  RadialInterval& rad)
00719 {
00720   //  std::cout << " Got the pointer " << std::endl;
00721   const std::vector<double>& myValues((icomp)?theParam->getTailIntervals():theParam->getCoreIntervals());
00722   //  std::cout << " Got the vector " << myValues.size () << std::endl;
00723   unsigned nvals=myValues.size()/2;
00724   for(unsigned iv=0;iv<nvals;++iv)
00725     {
00726       //      std::cout << myValues[2*iv] << " " <<  myValues[2*iv+1] <<std::endl;
00727       rad.addInterval(myValues[2*iv],myValues[2*iv+1]);
00728     } 
00729 } 
00730 
00731 void EMShower::setPreshower(PreshowerHitMaker * const myPresh)
00732 {
00733   if(myPresh!=NULL)
00734     {
00735       thePreshower = myPresh;
00736       hasPreshower=true;
00737     }
00738 }
00739 
00740 
00741 void EMShower::setHcal(HcalHitMaker * const myHcal)
00742 {
00743   theHcalHitMaker = myHcal;
00744 }
00745 
00746 double
00747 EMShower::deposit( double a, double b, double t) {
00748   //  std::cout << " Deposit " << std::endl;
00749   myIncompleteGamma.a().setValue(a);
00750   double b2=b*t;
00751   double result = 0.;
00752   if(fabs(b2) < 1.e-9 ) b2 = 1.e-9;
00753   result=myIncompleteGamma(b2);
00754   //  std::cout << " deposit t = " << t  << " "  << result <<std::endl;
00755   return result;
00756 
00757 }