00001
00002 #include "CalRecon/CalClustersAlg.h"
00003
00004
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
00045
00046
00047
00048
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
00061
00062
00063 gamma1 = Gamma(alpha,x);
00064 x += dx;
00065
00066
00067 gamma2 = Gamma(alpha,x);
00068
00069
00070 result = par[0]*(gamma2 - gamma1);
00071
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
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
00141
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
00152
00153
00154
00155
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)
00203
00204 {
00205 cl->setFitEnergy(0);
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
00224 float vstrt[5];
00225 float stp[5];
00226 float bmin[5];
00227 float bmax[5];
00228
00229
00230 double eTotal_GeV = eTotal / 1000;
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 vstrt[0] = eTotal_GeV;
00241 vstrt[1] = 2.65 * exp(0.15*log(eTotal_GeV));
00242 vstrt[2] = 1.8f;
00243 vstrt[3] = 2.29 * exp(-0.031*log(eTotal_GeV));
00244
00245 stp[0] = 0.1f;
00246 stp[1] = 0.1f;
00247 stp[2] = 0.02f;
00248 stp[3] = 0.2f;
00249
00250
00251 bmin[0] = 0.5*eTotal_GeV;
00252 bmin[1] = 0.5;
00253 bmin[2] = -5;
00254 bmin[3] = 0.;
00255
00256
00257 bmax[0] = 5 * eTotal_GeV;
00258 bmax[1] = 15;
00259 bmax[2] = 10;
00260 bmax[3] = 10;
00261
00262
00263 double arglist[10];
00264 int ierflg = 0;
00265
00266
00267 arglist[0] = -1;
00268 minuit->mnexcm("SET PRI", arglist ,1,ierflg);
00269
00270
00271 minuit->mnexcm("SET NOW", arglist ,1,ierflg);
00272
00273 arglist[0] = 1;
00274 minuit->mnexcm("SET ERR", arglist ,1,ierflg);
00275
00276
00277
00278 arglist[0] = 2;
00279 minuit->mnexcm("SET STR", arglist ,1,ierflg);
00280
00281
00282
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
00290
00291 arglist[0] = 2;
00292 minuit->mnexcm("FIX ", arglist ,1,ierflg);
00293
00294
00295 arglist[0] = 4;
00296 minuit->mnexcm("FIX ", arglist ,1,ierflg);
00297
00298
00299
00300 arglist[0]=500;
00301 arglist[1]=1;
00302 minuit->mnexcm("MIGRAD",arglist,2,ierflg);
00303
00304
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
00312 double edm,errdef;
00313 int nvpar,nparx,icstat;
00314 minuit->mnstat(ki2,edm,errdef,nvpar,nparx,icstat);
00315
00316
00317 cl->setFitEnergy(1000*fit_energy);
00318 cl->setProfChisq(ki2);
00319 cl->setCsiStart(fit_start);
00320 cl->setCsiAlpha(fit_alpha);
00321 cl->setCsiLambda(fit_lambda);
00322
00323
00324
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
00344 double cov_xz = 0;
00345 double cov_yz = 0;
00346 double mx=0;
00347 double my=0;
00348 double mz1=0;
00349 double mz2=0;
00350 double norm1=0;
00351 double norm2=0;
00352 double var_z1=0;
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
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
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
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
00457 minuit = new Midnight(5);
00458
00459
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
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
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;
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
00530 }
00531 else
00532 {
00533
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
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;
00576
00577 ene += eneLog;
00578 pCluster += ptmp;
00579 }
00580
00581
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
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
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
00634 Vector caldir = Fit_Direction(posrel,rmsLayer,nLayers);
00635
00636
00637
00638 if(!rectkr) slope = caldir.z();
00639
00640
00641
00642
00643
00644
00645
00646
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
00657 double eleak = Leak(ene,eneLayer[nLayers-1])+ene;
00658
00659
00660 eleak = Leak(eleak,eneLayer[nLayers-1])+ene;
00661
00662
00663 cl->setEneLeak(eleak);
00664
00665
00666 g_elayer.resize(nLayers);
00667 for ( i =0;i<nLayers;i++)
00668 {
00669
00670 g_elayer[i] = eneLayer[i]/1000.;
00671 }
00672 nbins = nLayers;
00673
00674
00675
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
00705 delete minuit;
00706
00707
00708
00709
00710 return sc;
00711 }
00712
00713
00714
00715