CMS 3D CMS Logo

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