CMS 3D CMS Logo

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