00001
00002
00003
00004
00005
00006
00007 #include "EmcGlSectorRec.h"
00008 #include "EmcCluster.h"
00009
00010
00011
00012
00013 float EmcGlSectorRec::fgEpar00 = 0.010;
00014 float EmcGlSectorRec::fgEpar0 = 0.01;
00015 float EmcGlSectorRec::fgEpar1 = 0.035;
00016 float EmcGlSectorRec::fgEpar2 = -0.035;
00017
00018 float EmcGlSectorRec::fgEpar3 = 0.;
00019 float EmcGlSectorRec::fgEpar4 = 1.0;
00020
00021 float EmcGlSectorRec::fSin4T = 0.;
00022
00023 float EmcGlSectorRec::fgConfLevel=0.01;
00024
00025
00026 float const EmcGlSectorRec::fgSigEcorr0=2.25e-02;
00027 float const EmcGlSectorRec::fgSigEcorr1=1.43e-02;
00028 float const EmcGlSectorRec::fgSigAcorr0=7.20815e-02;
00029 float const EmcGlSectorRec::fgSigAcorr1=-3.22703e-01;
00030
00031
00032 float const EmcGlSectorRec::fgCutEcorr0=2.1e-02;
00033 float const EmcGlSectorRec::fgCutEcorr1=0.009;
00034
00035
00036 float const EmcGlSectorRec::fgCoorPar00=0.1584384;
00037 float const EmcGlSectorRec::fgCoorPar01=0.1125;
00038 float const EmcGlSectorRec::fgCoorPar02=4.89856;
00039 float const EmcGlSectorRec::fgCoorPar03=2.42169e-01;
00040 float const EmcGlSectorRec::fgCoorPar10=0.4777;
00041 float const EmcGlSectorRec::fgCoorPar11=4.87463;
00042 float const EmcGlSectorRec::fgCoorPar12=1.23336e-01;
00043 float const EmcGlSectorRec::fgCoorPar20=3.28647;
00044 float const EmcGlSectorRec::fgCoorPar21=6.30741e-01;
00045
00046
00047
00048 void
00049 EmcGlSectorRec::Gamma(int nh, EmcModule* phit, float* pchi, float* pchi0,
00050 float* pe1, float* px1, float* py1, float* pe2,
00051 float* px2, float* py2, int &ndf)
00052 {
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 float e1, x1, y1, e2, x2, y2;
00065 float chi, chi0, chisave;
00066 int dof;
00067 float d2, xm2;
00068 const float zTG=100;
00069 const float xmcut=0.0015;
00070
00071 *pe1=0;
00072 *px1=0;
00073 *py1=0;
00074 *pe2=0;
00075 *px2=0;
00076 *py2=0;
00077
00078 if(nh<=0) return;
00079
00080 Mom1(nh, phit, &e1, &x1, &y1);
00081 *pe1=e1;
00082
00083 if( e1 <= 0 ) return;
00084
00085 SetProfileParameters(0, e1, x1, y1);
00086
00087 chisave = *pchi;
00088 chi = *pchi;
00089
00090
00091 chi0 = ClusterChisq(nh, phit, e1, x1, y1, ndf);
00092 dof = ndf;
00093
00094
00095 if( dof < 1 ) dof=1;
00096 chi = chi0/dof;
00097
00098 *pchi0 = chi;
00099 *pchi = chi;
00100 *px1 = x1;
00101 *py1 = y1;
00102
00103 if( e1 <= fgMinShowerEnergy ) return;
00104
00105 if( chi > chisave ) {
00106 TwoGamma(nh,phit,&chi,&e1,&x1,&y1,&e2,&x2,&y2);
00107 if( e2 > 0 ) {
00108 d2 = ((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))/zTG/zTG;
00109 xm2 = e1*e2*d2;
00110 if( xm2 > 0 ) xm2 = sqrt(xm2);
00111 if( xm2 > xmcut && e1 > fgMinShowerEnergy && e2 > fgMinShowerEnergy) {
00112 *pe1 = e1;
00113 *px1 = x1;
00114 *py1 = y1;
00115 *pe2 = e2;
00116 *px2 = x2;
00117 *py2 = y2;
00118 *pchi = chi;
00119 }
00120 }
00121 }
00122 }
00123
00124 float
00125 EmcGlSectorRec::Chi2Limit(int ndf)
00126 {
00127
00128
00129 if(ndf<1) return 0.;
00130 float chi2 = fgChi2Level[EmcCluster::min(ndf,50)-1];
00131 return chi2;
00132
00133 }
00134
00135 float
00136 EmcGlSectorRec::Chi2Correct(float chi2, int ndf)
00137 {
00138
00139 if(ndf<1) return 0.;
00140 return chi2;
00141
00142 }
00143
00144 void
00145 EmcGlSectorRec::SetProfileParameters(int sectorID, float energy,
00146 float x, float y)
00147 {
00148
00149
00150
00151
00152
00153 float vx, vy, vz;
00154 float xVert, yVert, zVert;
00155
00156 if(sectorID>=0){
00157
00158
00159 GlobalToSector(fVx, fVy, fVz, &xVert, &yVert, &zVert);
00160 vz = -zVert;
00161 vy = y*fModSizey - yVert;
00162 vx = x*fModSizex - xVert;
00163
00164 fSinTy=vy/sqrt(vy*vy+vz*vz);
00165 fSinTx=vx/sqrt(vx*vx+vz*vz);
00166
00167 fSin4T = fabs((2*fSinTy-fSinTx)*(fSinTy-2*fSinTx)*(fSinTy-fSinTx)*(fSinTy-fSinTx));
00168
00169
00170 fTheta=180.0/ M_PI * asin(sqrt(vx*vx+vy*vy)/sqrt(vx*vx+vy*vy+vz*vz));
00171 fPhi=180.0/ M_PI * (M_PI + atan2(vy, vx));
00172
00173 #if 0
00174 cerr<<"Before 2nd pass"<<endl;
00175 cerr<<"fTheta="<<fTheta<<" ";
00176 cerr<<"fPhi="<<fPhi<<endl;
00177 cerr<<"fVx="<<fVx<<" fVy="<<fVy<<" fVz="<<fVz<<endl;
00178 cerr<<"xVert="<<xVert<<" yVert="<<yVert<<" zVert="<<zVert<<endl;
00179 cerr<<" y="<<y*fModSizey<<" x="<<x*fModSizex<<endl;
00180 cerr<<endl;
00181 #endif
00182
00183
00184
00185
00186
00187
00188
00189 y*=fModSizey;
00190 x*=fModSizex;
00191 float xcorr, ycorr;
00192 CorrectPosition(energy, x, y, &xcorr, &ycorr, false);
00193
00194
00195 vy = ycorr-yVert;
00196 vx = xcorr-xVert;
00197
00198 fSinTy=vy/sqrt(vy*vy+vz*vz);
00199 fSinTx=vx/sqrt(vx*vx+vz*vz);
00200
00201
00202 fTheta=180.0/ M_PI * asin(sqrt(vx*vx+vy*vy)/sqrt(vx*vx+vy*vy+vz*vz));
00203 fPhi=180.0/ M_PI * (M_PI + atan2(vy, vx));
00204
00205 #if 0
00206 cerr<<"After 2nd pass"<<endl;
00207 cerr<<"fTheta="<<fTheta<<" ";
00208 cerr<<"fPhi="<<fPhi<<endl;
00209 cerr<<"fVx="<<fVx<<" fVy="<<fVy<<" fVz="<<fVz<<endl;
00210 cerr<<"xVert="<<xVert<<" yVert="<<yVert<<" zVert="<<zVert<<endl;
00211 cerr<<" y="<<y*fModSizey<<" x="<<x*fModSizex<<endl;
00212 cerr<<endl;
00213 #endif
00214 }
00215
00216
00217 fShift=ShiftFunc(energy, fTheta);
00218 fExc1=Sigma1Func(energy, fTheta);
00219 fExc2=Sigma2Func(energy, fTheta);
00220
00221
00222 fShapePars[0]=AFunc(energy, fTheta, fPhi);
00223 fShapePars[1]=CFunc(energy, fTheta, fPhi);
00224 fShapePars[2]=DFunc(energy, fTheta, fPhi);
00225 fShapePars[3]=SFunc(energy, fTheta, fPhi);
00226
00227
00228 fSpecThr=fgCutEcorr0+fgCutEcorr1*energy;
00229 fThrCorr=0;
00230 }
00231
00232 float
00233 EmcGlSectorRec::PredictEnergy (float deltaz, float deltay, float energy)
00234 {
00235
00236
00237
00238
00239 if(energy>0) SetProfileParameters(-1, energy, 0., 0.);
00240
00241
00242 Rotate(fPhi, deltaz, deltay);
00243
00244
00245 deltaz-=fShift;
00246 if(deltaz<0.0) deltaz*=fExc1;
00247 else deltaz*=fExc2;
00248
00249
00250 float rCG=sqrt(deltaz*deltaz+deltay*deltay);
00251
00252
00253 float predicted=ShapeFunc(&rCG, fShapePars)+fThrCorr;
00254
00255 return predicted;
00256 }
00257
00258 float EmcGlSectorRec::ClusterChisq(int nh, EmcModule* phit, float e, float x,
00259 float y, int &ndf)
00260
00261 {
00262
00263 float chi=0;
00264 int nhout = 0;
00265 int ixy, ix, iy;
00266 float et, a, d;
00267
00268 for( int in=0; in<nh; in++ ) {
00269 et = phit[in].amp;
00270 if( et/e > 0.004 ) {
00271 ixy = phit[in].ich;
00272 iy = ixy/fNx;
00273 ix = ixy - iy*fNx;
00274 a = PredictEnergy(x-ix, y-iy, -1);
00275 d = fgEpar00*fgEpar00 + e*(fgEpar1*a + fgEpar2*a*a + fgEpar3*a*a*a) +
00276 e*e*fgEpar4*a*(1-a)*fSin4T + e*e*fgEpar0*fgEpar0;
00277 d += 0.30*0.30*e*e*a*a*(1-a);
00278
00279 a *= e;
00280 chi += (et-a)*(et-a)/d;
00281 nhout++;
00282 }
00283 }
00284
00285 ndf=nhout;
00286 return chi;
00287
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 void
00415 EmcGlSectorRec::CorrectEnergy (float Energy, float x, float y,
00416 float* Ecorr)
00417 {
00418
00419
00420
00421
00422
00423
00424
00425 static float par_1 = -0.012043;
00426 static float par_2 = 0.077908;
00427 float xm,ym;
00428 float sin_theta;
00429 float theta_deg;
00430 float corr_factor_ang;
00431
00432
00433
00434 static float par_a = 1.0386;
00435 static float par_b = -0.041423;
00436 static float par_c = 0.006064;
00437 float log_e;
00438 float corr_factor_nonl;
00439
00440
00441
00442
00443
00444
00445
00446 xm = x;
00447 ym = y;
00448
00449
00450
00451 GetImpactAngle(xm,ym,&sin_theta);
00452 theta_deg = 180.0/ M_PI * asin(sin_theta);
00453
00454
00455
00456 corr_factor_ang = par_1*exp(theta_deg*par_2)+1-par_1;
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 Energy = Energy/corr_factor_ang;
00471
00472
00473
00474
00475
00476
00477
00478
00479 log_e = log(Energy);
00480
00481
00482
00483 corr_factor_nonl = par_a + par_b*(log_e)+par_c*(log_e*log_e);
00484
00485
00486
00487 *Ecorr = corr_factor_nonl*Energy;
00488 }
00489
00490
00491 void
00492 EmcGlSectorRec::CorrectECore (float Ecore, float x, float y,
00493 float* Ecorr)
00494 {
00495
00496
00497
00498
00499
00500 *Ecorr = Ecore;
00501 }
00502
00503
00504 void
00505 EmcGlSectorRec::CorrectPosition (float energy, float zcg, float ycg,
00506 float* zcgcorr, float* ycgcorr,
00507 bool callSetPar)
00508 {
00509
00510
00511
00512
00513
00514
00515
00516
00517 float spar[3];
00518
00519 if(callSetPar)
00520 SetProfileParameters( 0, energy, zcg/GetModSizex(), ycg/GetModSizey() );
00521
00522
00523 zcg/=GetModSizex();
00524 spar[0]=fgCoorPar00+fgCoorPar01*fabs(fSinTx)+
00525 (fgCoorPar02+fgCoorPar03*energy)*fSinTx*fSinTx;
00526 spar[0]*=copysign(1., fSinTx);
00527 spar[1]=fgCoorPar10*fabs(fSinTx)+
00528 (fgCoorPar11+fgCoorPar12*energy)*fSinTx*fSinTx;
00529 spar[1]*=copysign(1., fSinTx);
00530 spar[2]=(fgCoorPar20+fgCoorPar21*log(energy))*fSinTx;
00531
00532 #if 0
00533
00534
00535
00536
00537 spar[0]=1.28090;
00538 spar[0]*=copysign(1., fSinTx);
00539 spar[1]=1.07773;
00540 spar[1]*=copysign(1., fSinTx);
00541 spar[2]=1.65389;
00542 spar[2]*=copysign(1., fSinTx);
00543 #endif
00544
00545 *zcgcorr=InvScurveFunc(zcg, spar)*GetModSizex();
00546
00547
00548 ycg/=GetModSizey();
00549 spar[0]=fgCoorPar00+fgCoorPar01*fabs(fSinTy)+
00550 (fgCoorPar02+fgCoorPar03*energy)*fSinTy*fSinTy;
00551 spar[0]*=copysign(1., fSinTy);
00552 spar[1]=fgCoorPar10*fabs(fSinTy)+
00553 (fgCoorPar11+fgCoorPar12*energy)*fSinTy*fSinTy;
00554 spar[1]*=copysign(1., fSinTy);
00555 spar[2]=(fgCoorPar20+fgCoorPar21*log(energy))*fSinTy;
00556 *ycgcorr=InvScurveFunc(ycg, spar)*GetModSizey();
00557 }
00558
00559 void
00560 EmcGlSectorRec::CalculateErrors (float e, float x, float y, float* pde,
00561 float* pdx, float* pdy, float* pdz)
00562 {
00563
00564
00565
00566
00567
00568
00569 *pde = 999.999;
00570 *pdx = 999.999;
00571 *pdy = 999.999;
00572 *pdz = 999.999;
00573 }
00574
00575 void
00576 EmcGlSectorRec::TwoGamma (int nmod, EmcModule *modules, float *pchi,
00577 float *pe1, float *pz1, float *py1,
00578 float *pe2, float *pz2, float *py2)
00579 {
00580
00581
00582 float e0, z0, y0, zz, yy, zy;
00583
00584 *pe2=0.;
00585 *pz2=0.;
00586 *py2=0.;
00587
00588 Momenta(nmod, modules, &e0, &z0, &y0, &zz, &yy, &zy);
00589
00590 *pe1=e0;
00591 *pz1=z0;
00592 *py1=y0;
00593 }
00594
00595 float
00596 EmcGlSectorRec::ShiftFunc (float energy, float angle)
00597 {
00598
00599
00600
00601 const float par0=-6.06226e+00;
00602 const float par1=-3.49026e-01;
00603
00604 return (par0+par1*log(energy))*(1.0-cos(angle* M_PI /180.0));
00605 }
00606
00607 float
00608 EmcGlSectorRec::Sigma1Func (float energy, float angle)
00609 {
00610
00611
00612
00613 const float par0=-1.75549e-02;
00614 const float par1=-1.35630e-03;
00615
00616 return 1.0+(par0+par1*log(energy))*angle;
00617 }
00618
00619 float
00620 EmcGlSectorRec::Sigma2Func (float energy, float angle)
00621 {
00622
00623
00624
00625 const float par0=-2.33139e-02;
00626 const float par1=-2.79326e-03;
00627
00628 return 1.0+(par0+par1*log(energy))*angle;
00629
00630 }
00631
00632 float
00633 EmcGlSectorRec::ShapeFunc (float *x, float *par)
00634 {
00635
00636
00637
00638 float rad=fabs(x[0]);
00639 float value;
00640
00641 float expr1=exp(-::pow(rad, 1.95)/par[1]);
00642
00643 float d=par[2];
00644 float s=par[3];
00645 float expr2=d*exp(-rad/s);
00646 value=par[0]*EmcCluster::max(expr1,expr2);
00647
00648 return value;
00649 }
00650
00651 float
00652 EmcGlSectorRec::AFunc (float energy, float angle, float phi)
00653 {
00654
00655
00656
00657
00658
00659 const float Ap0p0p0=-3.81425e+00;
00660 const float Ap0p0p1=-1.94749e+00;
00661
00662 float Ap0p0=Ap0p0p0+Ap0p0p1*log(energy);
00663
00664 const float Ap0p1p0=4.62982e+00;
00665 const float Ap0p1p1=1.94482e+00;
00666
00667 float Ap0p1=Ap0p1p0+Ap0p1p1*log(energy);
00668
00669 float Ap0=Ap0p0+Ap0p1*cos(angle* M_PI/180.0);
00670
00671
00672 const float Ap1p0p0=2.65696e-05;
00673 const float Ap1p0p1=5.56524e-05;
00674
00675 float Ap1p0=Ap1p0p0+Ap1p0p1*log(energy);
00676
00677 float Ap1=exp(Ap1p0*::pow(angle, 2.5))-1.0;
00678
00679
00680 const float Ap2p0p0=1.90663e+01;
00681 const float Ap2p0p1=-2.96820e-02;
00682
00683 float Ap2p0=Ap2p0p0+Ap2p0p1*log(energy);
00684
00685 const float Ap2p1p0=1.51973e-04;
00686 const float Ap2p1p1=1.20920e-04;
00687
00688 float Ap2p1=Ap2p1p0+Ap2p1p1*log(energy);
00689
00690 float Ap2=Ap2p0+exp(Ap2p1*angle*angle*angle);
00691
00692
00693 float A[3]={Ap0, Ap1, Ap2};
00694
00695 return PeriodicFunc(&phi, A);
00696
00697 }
00698
00699 float
00700 EmcGlSectorRec::CFunc (float energy, float angle, float phi)
00701 {
00702
00703
00704
00705
00706 #if 0
00707 const float cp0=3.28956e-01;
00708 const float cp1=-1.08942e-02;
00709
00710 float c=cp0+cp1*log(energy);
00711 #endif
00712
00713 const float cp0p0=-4.13339e-03;
00714 const float cp0p1=-6.24275e-03;
00715
00716 float cp0=cp0p0+cp0p1*log(energy);
00717
00718 float c=0.34+cp0*::pow(angle, 0.3);
00719
00720 return c;
00721
00722 }
00723
00724 float
00725 EmcGlSectorRec::DFunc (float energy, float angle, float phi)
00726 {
00727
00728
00729
00730
00731 const float dp0=1.35528e-01;
00732 const float dp1=-2.43148e-02;
00733
00734 float d=dp0+dp1*log(energy);
00735
00736 return d;
00737
00738 }
00739
00740 float
00741 EmcGlSectorRec::SFunc (float energy, float angle, float phi)
00742 {
00743
00744
00745
00746
00747 const float sp0=5.21967e-01;
00748 const float sp1=2.66467e-02;
00749
00750 float s=sp0+sp1*log(energy);
00751
00752 return s;
00753
00754 }
00755
00756 float
00757 EmcGlSectorRec::PeriodicFunc (float *x, float *par)
00758 {
00759
00760
00761 float mean;
00762 float var=x[0];
00763
00764 const float a=45.0;
00765
00766 if(var!=0.0) mean=a*(fabs(var)/var)*((1+2*abs(int((var-0.00001)/(2*a)))));
00767 else mean=a;
00768
00769 return par[0]+par[1]*exp(-0.5*(var-mean)*(var-mean)/(par[2]*par[2]));
00770
00771 }
00772
00773 float
00774 EmcGlSectorRec::InvScurveFunc (float cog, float *par)
00775 {
00776
00777
00778 float b=par[0];
00779 float d=par[1];
00780 float D=par[2];
00781
00782 cog-=d;
00783 float translation=cog>0.? int(cog+0.5): int(cog-0.5);
00784 float xinc=translation+
00785 asinh(2.*(cog-translation)*sinh(0.5/b))*b-D+d;
00786
00787 return xinc;
00788
00789 }
00790
00791 void
00792 EmcGlSectorRec::Rotate (float phi, float &deltaRow, float &deltaCol)
00793 {
00794
00795
00796 float alpha=phi * M_PI / 180.0;
00797 float sina=sin(alpha);
00798 float cosa=cos(alpha);
00799
00800 float xprime=deltaRow;
00801 float yprime=deltaCol;
00802
00803 deltaRow=xprime*cosa+yprime*sina;
00804 deltaCol=-xprime*sina+yprime*cosa;
00805
00806 }
00807
00808 float
00809 EmcGlSectorRec::CalcSigma (float predicted, float totSignal, float theta)
00810 {
00811
00812
00813
00814 float sigmaSq;
00815
00816
00817
00818 const float pisaCorr=2.;
00819
00820 sigmaSq=totSignal*fabs(predicted*(0.9-predicted));
00821
00822
00823 sigmaSq*=(pisaCorr*fgSigEcorr0+fgSigEcorr1*totSignal);
00824
00825
00826 sigmaSq*=1.0+(fgSigAcorr0*exp(fgSigAcorr1*totSignal))*theta;
00827
00828 return sigmaSq;
00829
00830 }
00831
00832 void
00833 EmcGlSectorRec::getTowerPos(int ix, int iy,
00834 float &x, float & y)
00835 {
00836 x = fModSizex * ix+int(ix/6)*0.15;
00837 y = fModSizey * iy+int(iy/6)*0.163;
00838 }
00839
00841 void
00842 EmcGlSectorRec::TowersToSector(float xT, float yT,
00843 float & xS, float & yS)
00844 {
00845 int x = int(xT);
00846 float dx = xT - x;
00847 int y = int(yT);
00848 float dy = yT - y;
00849 xS = fModSizex*x + int(xT/6)*0.15 + fModSizex*dx;
00850 yS = fModSizey*y + int(yT/6)*0.163 + fModSizey*dy;
00851 }
00852
00854 void
00855 EmcGlSectorRec::TowersToSector(int xT, int yT,
00856 float & xS, float & yS)
00857 {
00858 xS = fModSizex*xT + int(xT/6)*0.15;
00859 yS = fModSizey*yT + int(yT/6)*0.163;
00860 }
00861
00863 void
00864 EmcGlSectorRec::SectorToTowers(float xS, float yS,
00865 int & xT, int & yT)
00866 {
00867
00868 xT = int(((xS-int(xS/24.612)*24.612)+2.0385)/fModSizex) + 6*int(xS/24.612);
00869 yT = int(((yS-int(yS/16.471)*16.471)+2.0385)/fModSizey) + 4*int(yS/16.471);
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882