Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

CalClustersAlg.cpp

Go to the documentation of this file.
00001 
00002 #include "CalRecon/CalClustersAlg.h"
00003 // #include "Event/dataManager.h"
00004 // #include "Event/messageManager.h"
00005 #include "CalRecon/CsIClusters.h"
00006 #include "CalRecon/CalRecLogs.h"
00007 #include "CalRecon/gamma.h"
00008 #include "CalRecon/Midnight.h"
00009 #include "GaudiKernel/MsgStream.h"
00010 #include "GaudiKernel/AlgFactory.h"
00011 #include "GaudiKernel/IDataProviderSvc.h"
00012 #include "GaudiKernel/SmartDataPtr.h"
00013 #include "GlastSvc/GlastDetSvc/IGlastDetSvc.h"
00014 
00015 
00017 #include "GlastEvent/TopLevel/EventModel.h"
00018 #include "GlastEvent/TopLevel/Event.h"
00019 #include "GaudiKernel/ObjectVector.h"
00020 #include "GlastEvent/data/TdGlastData.h"
00021 
00023 #include "GlastEvent/Recon/ISiRecObjs.h"
00024 
00025 int nbins;  
00026 std::vector<double> g_elayer;  
00027 double slope;   
00028 double logheight; 
00029 double logwidth;  
00030 
00032 
00035 static const AlgFactory<CalClustersAlg>  Factory;
00036 const IAlgFactory& CalClustersAlgFactory = Factory;
00037 
00038 static double gam_prof(double *par, int i)
00039 {
00040         double result =0; 
00041 
00042         double length = ((logheight*i+par[2])/1.85)/slope;
00043 
00044         // Evaluation of the parameters of CsI at this energy   
00045 
00046         //      double alpha = par[1];
00047 
00048         //      double lambda = par[3];
00049 
00050         double alpha = 2.65*exp(0.15*log(par[0]));
00051     double lambda = 2.29*exp(-0.031*log(par[0]));
00052 
00053 
00054         double x=length/lambda;
00055         double dx = logheight / (1.85 *lambda)/slope;
00056         
00057         double gamma1 =0;
00058         double gamma2 = 0;
00059 
00060         // Now we will calculate the gamma incomplete function
00061 
00062         // gamma1 = integration from 0 to x     
00063         gamma1 = Gamma(alpha,x);
00064         x += dx;
00065 
00066         // gamma2 = integration from 0 to x+dx  
00067         gamma2 = Gamma(alpha,x);
00068         
00069         // the result of integration over Xtal pathlength is E*(gamma2 - gamma1)
00070         result = par[0]*(gamma2 - gamma1);
00071 //      std::cout<< result << "\n";
00072         return result;
00073 }
00074 
00075 
00077 
00080 static void fcn(int &npar, double *gin, double &f, double *par, int iflag)
00081 {
00082      int i;
00083         //calculate 'chisquare'
00084    double chisq = 0;
00085    double dlt;
00086    
00087    for (i=0;i<nbins; i++) {
00088      dlt  = (g_elayer[i]-gam_prof(par,i));
00089      if(g_elayer[i]>0.001) chisq += dlt*dlt/g_elayer[i];
00090         }
00091    
00092    f = chisq;
00093 }
00094 
00096 
00133 //################################################
00134 double CalClustersAlg::Leak(double eTotal,double elast)
00135 //################################################
00136 {
00137         if(eTotal<200.) return 0.;
00138         else
00139         {
00140             // Evaluation of energy using correlation method
00141                 // Coefficients fitted using GlastSim.
00142                 double p0 = -1.49 + 1.72*slope;
00143                 double p1 = 0.28 + 0.434 * slope;
00144                 double p2 = -15.16 + 11.55 * slope;
00145                 double p3 = 13.88 - 10.18 * slope;
00146                 double lnE = log(eTotal/1000.);
00147                 double funcoef = (p0 + p1 * lnE )/(1+exp(-p2*(lnE - p3)));
00148 
00149                 double e_leak = funcoef * elast;
00150                 
00151                 // Evaluation of energy using correlation woth last layer
00152         // coefficients fitted using tbsim and valid for ~1GeV<E<~50GeV
00153         //double slope = 1.111 + 0.557*log(eTotal/1000.);
00154                 //double intercept = 210. + 112. * log(eTotal/1000.) *log(eTotal/1000.); 
00155         //double e_leak = slope * elast + intercept;
00156                 return e_leak;
00157         }
00158 }
00159 
00161 
00197 //################################################
00198 void CalClustersAlg::Profile(double eTotal, CsICluster* cl)
00199 //################################################
00200 {
00201 
00202   if( eTotal<2000. || slope == 0) //algorithm is useless under several GeV
00203 
00204         {
00205          cl->setFitEnergy(0);    // Conversion to MeV
00206          cl->setProfChisq(0);
00207          cl->setCsiStart(0);
00208          cl->setCsiAlpha(0);
00209          cl->setCsiLambda(0);
00210         }
00211   else
00212 {
00213   double fit_energy;
00214   double ki2;
00215   double fit_alpha;
00216   double fit_lambda;
00217   double fit_start;
00218   double energy_err;
00219   double alpha_err;
00220   double lambda_err;
00221   double start_err;
00222 
00223   // Vector of step, initial min and max value
00224   float vstrt[5];
00225   float stp[5];
00226   float bmin[5];
00227   float bmax[5];
00228   
00229   // We are working in GeV
00230   double eTotal_GeV = eTotal / 1000;
00231   
00232   // par[0] is energy
00233   // par[1] is alpha
00234   // par[2] is the starting point
00235   // par[3] is lambda
00236   
00237   // Init start values and bounds
00238   
00239   // starting value of each parameter
00240   vstrt[0] = eTotal_GeV;
00241   vstrt[1] = 2.65 * exp(0.15*log(eTotal_GeV));  // parametrisation of alpha
00242   vstrt[2] = 1.8f;                      // eq to 1X0 in CsI
00243   vstrt[3] = 2.29 * exp(-0.031*log(eTotal_GeV));
00244   // step value of each parameter
00245   stp[0] = 0.1f;
00246   stp[1] = 0.1f;
00247   stp[2] = 0.02f;
00248   stp[3] = 0.2f;
00249   
00250   // minimum value of each parameter
00251   bmin[0] = 0.5*eTotal_GeV;
00252   bmin[1] = 0.5;
00253   bmin[2] = -5;
00254   bmin[3] = 0.;
00255 
00256   // maximum value of each parameter
00257   bmax[0] = 5 * eTotal_GeV;
00258   bmax[1] = 15;
00259   bmax[2] = 10;
00260   bmax[3] = 10;
00261 
00262   // Those are the arguments for Minuit
00263   double arglist[10];
00264   int ierflg = 0;
00265 
00266   // Set no output because of tuple output
00267   arglist[0] = -1;
00268   minuit->mnexcm("SET PRI", arglist ,1,ierflg);
00269     
00270   // idem with warnings ( minuit prints warnings when the Hessian matrix is not positive )
00271   minuit->mnexcm("SET NOW", arglist ,1,ierflg);
00272   
00273   arglist[0] = 1;
00274   minuit->mnexcm("SET ERR", arglist ,1,ierflg);
00275   
00276   // defines the strategy used by minuit
00277   // 1 is standard
00278   arglist[0] = 2;
00279   minuit->mnexcm("SET STR", arglist ,1,ierflg);
00280   
00281   
00282   // Defines parameters
00283   
00284   minuit->mnparm(0, "Energy",    vstrt[0], stp[0], bmin[0],bmax[0],ierflg);
00285   minuit->mnparm(1, "Alpha",    vstrt[1], stp[1], bmin[1],bmax[1],ierflg);
00286   minuit->mnparm(2, "Starting point",  vstrt[2], stp[2], bmin[2],bmax[2],ierflg);
00287   minuit->mnparm(3, "Lambda",  vstrt[3], stp[3], bmin[3],bmax[3],ierflg);
00288   
00289   // Fix some parameters
00290   // alpha
00291   arglist[0] = 2;
00292   minuit->mnexcm("FIX ", arglist ,1,ierflg);
00293   
00294   // lambda
00295   arglist[0] = 4;
00296   minuit->mnexcm("FIX ", arglist ,1,ierflg);
00297   
00298   
00299   // Calls Migrad with 500 iterations maximum
00300   arglist[0]=500;
00301   arglist[1]=1;
00302   minuit->mnexcm("MIGRAD",arglist,2,ierflg);
00303   
00304   // Retrieve parameter information 
00305 
00306   minuit->GetParameter( 0, fit_energy,energy_err ); 
00307   minuit->GetParameter( 1, fit_alpha,alpha_err ); 
00308   minuit->GetParameter( 2, fit_start,start_err ); 
00309   minuit->GetParameter( 3, fit_lambda,lambda_err ); 
00310 
00311   // Get chi-square
00312   double edm,errdef;
00313   int nvpar,nparx,icstat;
00314   minuit->mnstat(ki2,edm,errdef,nvpar,nparx,icstat);
00315 
00316   // Fills data
00317   cl->setFitEnergy(1000*fit_energy);    // Conversion to MeV
00318   cl->setProfChisq(ki2);
00319   cl->setCsiStart(fit_start);
00320   cl->setCsiAlpha(fit_alpha);
00321   cl->setCsiLambda(fit_lambda); 
00322 
00323   
00324   // Clear minuit
00325   arglist[0] = 1;
00326   minuit->mnexcm("CLEAR", arglist ,1,ierflg);
00327 
00328  } 
00329 
00330 }
00331 
00333 
00336 //################################################
00337 Vector CalClustersAlg::Fit_Direction(std::vector<Vector> pos,std::vector<Vector> sigma2,int nlayers)
00338 //################################################
00339 {
00340         
00341     MsgStream log(msgSvc(), name());
00342 
00343         // sigma2.z() is useless here no matter its value.
00344         double cov_xz = 0;  // covariance x,z
00345         double cov_yz = 0;  // covariance y,z
00346         double mx=0;        // mean x
00347         double my=0;            // mean y
00348         double mz1=0;           // mean z for x pos
00349         double mz2=0;           // mean z for y pos
00350         double norm1=0;
00351         double norm2=0;
00352         double var_z1=0;                // variance of z        
00353         double var_z2=0;
00354     int nlx=0,nly=0;
00355     Vector nodir(-1000.,-1000.,-1000.);
00356         for(int il=0;il<nlayers;il++)
00357         {
00358 
00359         
00360         // For the moment forget about longitudinal position
00361                 if(il%2==1)
00362                 {
00363                         if (sigma2[il].x()>0.)
00364                         {
00365                 nlx++;
00366                                 double err = 1/sigma2[il].x();
00367                 cov_xz += pos[il].x()*pos[il].z()*err;
00368                                 var_z1 += pos[il].z()*pos[il].z()*err;
00369                                 mx += pos[il].x()*err;
00370                                 mz1 += pos[il].z()*err;
00371                                 norm1 += err;
00372                         }
00373                 }
00374                 else
00375                 {
00376                         if(sigma2[il].y()>0.)
00377                         {
00378 
00379                 nly++;
00380                 double err = 1/sigma2[il].y();
00381                 cov_yz += pos[il].y()*pos[il].z()*err;
00382                                 var_z2 += pos[il].z()*pos[il].z()*err;
00383                                 my += pos[il].y()*err;
00384                                 mz2 += pos[il].z()*err;
00385                                 norm2 += err;
00386                         }
00387                 }
00388         }               
00389 
00390 
00391     if(nlx <2 || nly < 2 )return nodir;
00392 
00393     
00394 
00395     
00396     mx /= norm1;
00397         mz1 /= norm1;
00398         cov_xz /= norm1;
00399         cov_xz -= mx*mx;
00400         var_z1 /= norm1;
00401         var_z1 -= mz1*mz1;
00402     if(var_z1 == 0) return nodir;
00403         double tgthx = cov_xz/var_z1;
00404     
00405 
00406         my /= norm2;
00407         mz2 /= norm2;
00408         cov_yz /= norm2;
00409         cov_yz -= my*my;
00410         var_z2 /= norm2;
00411         var_z2 -= mz2*mz2;
00412 
00413 // Now we have cov(x,z) and var(z) we can deduce slope
00414     if(var_z2 == 0) return nodir;
00415     double tgthy = cov_yz/var_z2;
00416     
00417 
00418         double tgtheta_sqr = tgthx*tgthx+tgthy*tgthy;
00419         double costheta = 1/sqrt(1+tgtheta_sqr);
00420 //    log << MSG::INFO << norm2 << "\t" << norm1  << "\t" << var_z2 << "\t" << var_z1 << endreq;
00421         Vector dir(costheta*tgthx,costheta*tgthy,costheta);
00422         return dir;
00423 }
00424 
00425 
00426 //################################################
00427 CalClustersAlg::CalClustersAlg(const std::string& name, ISvcLocator* pSvcLocator):
00428 //################################################
00429 Algorithm(name, pSvcLocator)
00430 {
00431     declareProperty("callNumber",m_callNumber=0);
00432  
00433 }
00434 
00435 //################################################
00436 StatusCode CalClustersAlg::initialize()
00437 //################################################
00438 {
00439     MsgStream log(msgSvc(), name());
00440     StatusCode sc = StatusCode::SUCCESS;
00441     sc = service("CalGeometrySvc", m_CalGeo);
00442 
00443     if(sc.isFailure())
00444     {
00445         log << MSG::ERROR << "CalGeometrySvc could not be found" <<endreq;
00446         return sc;
00447     }
00448 
00449     setProperties();
00450     log << MSG::INFO << "callNumber = " << m_callNumber << endreq;
00451 
00452     logheight = m_CalGeo->logHeight();
00453         logwidth = m_CalGeo->logWidth();
00454     
00455     
00456     // Minuit object
00457     minuit = new Midnight(5);
00458     
00459     //Sets the function to be minimized
00460     minuit->SetFCN(fcn);
00461     
00462     
00463     g_elayer.clear();
00464     
00465     return sc;
00466 }
00467 
00468 //################################################
00469 StatusCode CalClustersAlg::retrieve()
00470 //################################################
00471 {
00472         
00473     StatusCode sc = StatusCode::SUCCESS;
00474 
00475     MsgStream log(msgSvc(), name());
00476         log << MSG::INFO << "Initialize" << endreq;
00477 
00478         DataObject* pnode=0;
00479 
00480     sc = eventSvc()->retrieveObject( "/Event/CalRecon", pnode );
00481     
00482     if( sc.isFailure() ) {
00483         sc = eventSvc()->registerObject("/Event/CalRecon",new DataObject);
00484         if( sc.isFailure() ) {
00485             
00486             log << MSG::ERROR << "Could not create CalRecon directory" << endreq;
00487             return sc;
00488         }
00489     }
00490     m_CsIClusterList = SmartDataPtr<CsIClusterList> (eventSvc(),"/Event/CalRecon/CsIClusterList");
00491  //   sc = eventSvc()->retrieveObject("/Event/CalRecon/CsIClusterList",m_CsIClusterList);
00492     if (!m_CsIClusterList ){
00493             m_CsIClusterList = 0;
00494             m_CsIClusterList = new CsIClusterList();
00495         sc = eventSvc()->registerObject("/Event/CalRecon/CsIClusterList",m_CsIClusterList);
00496     } else {
00497         m_CsIClusterList->clear();
00498     }
00499 
00500         m_CalRecLogs = SmartDataPtr<CalRecLogs>(eventSvc(),"/Event/CalRecon/CalRecLogs"); 
00501 
00502 
00503 //      sc = eventSvc()->retrieveObject("/Event/CalRecon/CalADCLogs",m_CalRawLogs);
00504         return sc;
00505 }
00506 
00512 //################################################
00513 StatusCode CalClustersAlg::execute()
00514 //################################################
00515 {
00516     MsgStream log(msgSvc(), name());
00517         StatusCode sc = StatusCode::SUCCESS;
00518         sc = retrieve();
00519         const Point p0(0.,0.,0.);
00520 
00521         int rectkr=0;  //is tracker recon OK?
00522         int ngammas;
00523         Point gammaVertex;
00524                 Vector gammaDirection;
00525 
00526     SmartDataPtr<ISiRecObjs> tkrRecData(eventSvc(),"/Event/TkrRecon/SiRecObjs");
00527     if (tkrRecData == 0) {
00528         log << MSG::INFO << "No TKR Reconstruction available " << endreq;
00529        // return sc;
00530         }
00531         else
00532         {
00533                 // First get reconstructed direction from tracker
00534                 ngammas = tkrRecData->numGammas();
00535                 log << MSG::INFO << "number of gammas = " << ngammas << endreq;
00536         
00537   
00538                  if (ngammas > 0) {
00539                         rectkr++;
00540             gammaVertex = tkrRecData->getGammaVertex(0);
00541             gammaDirection = tkrRecData->getGammaDirection(0);
00542                         slope = fabs(gammaDirection.z());
00543                 log << MSG::DEBUG << "gamma direction = " << slope << endreq;
00544 
00545                   } else {
00546                   log << MSG::INFO << "No reconstructed gammas " << endreq;
00547                  }      
00548         }
00549         int nLogs = m_CalRecLogs->num();
00550         double ene = 0;
00551         Vector pCluster(p0);
00552         int nLayers = m_CalGeo->numLayers() * m_CalGeo->numViews();
00553         
00554         std::vector<double> eneLayer(nLayers,0.);
00555         std::vector<Vector> pLayer(nLayers);
00556         std::vector<Vector> rmsLayer(nLayers);
00557 
00558                 
00559         
00560         // Compute barycenter and various moments
00561 
00562         for (int jlog = 0; jlog < nLogs ; jlog++) {
00563                 CalRecLog* recLog = m_CalRecLogs->Log(jlog);
00564 
00565                 double eneLog = recLog->energy();
00566                 Vector pLog = recLog->position() - p0;
00567                 int layer = nLayers-1 - (recLog->layer() * 2 + recLog->view());
00568                 
00569                 eneLayer[layer]+=eneLog;
00570 
00571                 Vector ptmp = eneLog*pLog;
00572                 pLayer[layer] += ptmp;
00573         
00574                 Vector ptmp_sqr(ptmp.x()*pLog.x(),ptmp.y()*pLog.y(),ptmp.z()*pLog.z());
00575                 rmsLayer[layer] += ptmp_sqr;  // Position error is assumed to be 1/sqrt(eneLog)
00576 
00577                 ene  += eneLog;
00578                 pCluster += ptmp;
00579         }
00580 
00581         // Now take the means
00582         if(ene>0.)pCluster *= (1./ene); else pCluster=Vector(-1000., -1000., -1000.);
00583         int i = 0;
00584         for( ;i<nLayers;i++){
00585                         if(eneLayer[i]>0)
00586                         {
00587                                 pLayer[i] *= (1./eneLayer[i]);
00588                                 rmsLayer[i] *= (1./eneLayer[i]);
00589 
00590                                 Vector sqrLayer(pLayer[i].x()*pLayer[i].x(),pLayer[i].y()*pLayer[i].y(),pLayer[i].z()*pLayer[i].z());
00591                                 
00592                                 
00593                                 Vector d; 
00594                                 if(i%2 == 1) d = Vector(logwidth*logwidth/12.,0.,0.);
00595                                 else d = Vector(0.,logwidth*logwidth/12.,0.);
00596 
00597                                 rmsLayer[i] += d-sqrLayer;
00598                                 
00599                         }
00600                         else 
00601                         {
00602                                 pLayer[i]=p0;
00603                                 rmsLayer[i]=p0;
00604                         }
00605         }
00606 
00607 
00608         // Now sum the different rms to have one transverse and one longitudinal rms
00609         double rms_trans=0;
00610         double rms_long=0;
00611         std::vector<Vector> posrel(nLayers);
00612 
00613     
00614     for(int ilayer=0;ilayer<nLayers;ilayer++)
00615         {
00616 
00617     posrel[ilayer]=pLayer[ilayer]-pCluster;
00618 
00619                 // Sum alternatively the rms
00620                 if(ilayer%2)
00621                 {
00622                         rms_trans += rmsLayer[ilayer].y();
00623                         rms_long += rmsLayer[ilayer].x();
00624                 }
00625                 else
00626                 {
00627                         rms_trans += rmsLayer[ilayer].x();
00628                         rms_long += rmsLayer[ilayer].y();
00629                 }
00630         }
00631 
00632 
00633         // Compute direction using the positions and rms per layer
00634         Vector caldir = Fit_Direction(posrel,rmsLayer,nLayers);
00635 
00636 
00637         // if no tracker rec then fill slope
00638         if(!rectkr) slope = caldir.z();
00639 
00640     //slope=1;  // Temporary whilst the algorith appplies to slope=1 showers only.
00641 
00642         // Take square roots of RMS
00643 //      rms_trans = sqrt(rms_trans);
00644 //      rms_long = sqrt(rms_long);
00645 
00646         // Fill CsICluster data
00647         CsICluster* cl = new CsICluster(ene,pCluster+p0);
00648         m_CsIClusterList->add(cl);
00649         cl->setEneLayer(eneLayer);
00650         cl->setPosLayer(pLayer);
00651         cl->setRmsLayer(rmsLayer);
00652         cl->setRmsLong(rms_long);
00653         cl->setRmsTrans(rms_trans);
00654         cl->setDirection(caldir);
00655 
00656         // Leakage correction
00657         double eleak = Leak(ene,eneLayer[nLayers-1])+ene;
00658         
00659         // iteration
00660     eleak = Leak(eleak,eneLayer[nLayers-1])+ene;        
00661 
00662 
00663         cl->setEneLeak(eleak);
00664 
00665         // defines global variable to be used for fcn
00666         g_elayer.resize(nLayers);
00667         for ( i =0;i<nLayers;i++)
00668         {
00669                 // We are working in GeV
00670                 g_elayer[i] = eneLayer[i]/1000.;
00671         }
00672         nbins = nLayers;
00673 //      slope = 1;  // temporary
00674 
00675         // Do profile fitting
00676         Profile(ene,cl);
00677 
00678     if(ngammas>0){
00679         Vector calOffset = (p0+pCluster) - gammaVertex;
00680         double calLongOffset = gammaDirection*calOffset;
00681         double calTransvOffset =sqrt(calOffset.mag2() - calLongOffset*calLongOffset);
00682         cl->setTransvOffset(calTransvOffset);
00683         
00684 
00685 
00686     }
00687 
00688         m_CsIClusterList->writeOut();
00689 
00690         return sc;
00691 }
00692 
00697 //################################################
00698 StatusCode CalClustersAlg::finalize()
00699 //################################################
00700 {
00701         StatusCode sc = StatusCode::SUCCESS;
00702         
00703         
00704         // delete Minuit object
00705   delete minuit;
00706 
00707 
00708 //      m_CsIClusterList->writeOut();
00709 
00710         return sc;
00711 }
00712 
00713 
00714 
00715 

Generated on Thu Nov 29 16:38:48 2001 by doxygen1.2.12 written by Dimitri van Heesch, © 1997-2001