00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 #include <math.h>
00082 #include <stdio.h>
00083 #include "cluster.h"
00084
00085
00086
00087
00088
00089
00090 #define MinPeakEnergy 0.08
00091
00092
00093 #define MinShowerEnergy 0.1
00094
00095
00096 #define MaxLen 1000
00097
00098
00099 #define MaxNofPeaks 10
00100
00101
00102 #define PeakIter 6
00103
00104
00105 #define Emin 0.002
00106
00107
00108 #define chisq 3.
00109
00110
00111 float epar00 = 0.005;
00112 float epar0 = 0.0014;
00113 float epar1 = 0.03;
00114 float epar2 = -0.03;
00115 float epar3 = 0.;
00116 float epar4 = 4.0;
00117
00118
00119 #define XABSURD -999999.
00120 #define YABSURD -999999.
00121
00122 int EMCzSize = 72;
00123 int EMCySize = 36;
00124 float Tower_zSize = 5.535;
00125 float Tower_ySize = 5.535;
00126
00127 float xVertex=0, yVertex=0, zVertex=0;
00128 float xSector=500, ySector=-97, zSector=-196;
00129 float normx=1, normy=0, normz=0;
00130
00131
00132 float Chi2Level[50]={
00133 6.634899, 4.605171, 3.780564, 3.318915, 3.017103,
00134 2.801872, 2.639259, 2.511249, 2.407341, 2.320967,
00135 2.247720, 2.184744, 2.129863, 2.081515, 2.038526,
00136 1.999994, 1.965214, 1.933627, 1.904781, 1.878311,
00137 1.853912, 1.831334, 1.810365, 1.790825, 1.772564,
00138 1.755449, 1.739367, 1.724222, 1.709926, 1.696406,
00139 1.683593, 1.671430, 1.659864, 1.648850, 1.638344,
00140 1.628311, 1.618716, 1.609528, 1.600721, 1.592268,
00141 1.584148, 1.576338, 1.568822, 1.561579, 1.554596,
00142 1.547856, 1.541346, 1.535055, 1.528968, 1.523077 };
00143
00144
00145 float Chi2Level1[50]={
00146 6.634899, 4.605171, 3.780564, 3.318915, 3.017103,
00147 2.801872, 2.639259, 2.511249, 2.407341, 2.320967,
00148 2.247720, 2.184744, 2.129863, 2.081515, 2.038526,
00149 1.999994, 1.965214, 1.933627, 1.904781, 1.878311,
00150 1.853912, 1.831334, 1.810365, 1.790825, 1.772564,
00151 1.755449, 1.739367, 1.724222, 1.709926, 1.696406,
00152 1.683593, 1.671430, 1.659864, 1.648850, 1.638344,
00153 1.628311, 1.618716, 1.609528, 1.600721, 1.592268,
00154 1.584148, 1.576338, 1.568822, 1.561579, 1.554596,
00155 1.547856, 1.541346, 1.535055, 1.528968, 1.523077 };
00156
00157
00158 float Chi2Level2[50]={
00159 5.411895, 3.912024, 3.278443, 2.916812, 2.677547,
00160 2.505458, 2.374582, 2.271008, 2.186567, 2.116065,
00161 2.056169, 2.004491, 1.959343, 1.919481, 1.883964,
00162 1.852072, 1.823237, 1.797008, 1.773021, 1.750981,
00163 1.730640, 1.711795, 1.694274, 1.677931, 1.662643,
00164 1.648301, 1.634814, 1.622101, 1.610093, 1.598727,
00165 1.587948, 1.577709, 1.567968, 1.558684, 1.549824,
00166 1.541357, 1.533256, 1.525494, 1.518051, 1.510903,
00167 1.504033, 1.497424, 1.491059, 1.484924, 1.479006,
00168 1.473292, 1.467771, 1.462433, 1.457267, 1.452265 };
00169
00170 float sin4a, sinax, sinay;
00171 float ppar1, ppar2, ppar3, ppar4, pShiftx, pShifty;
00172
00173 #define max(a,b) ((a) > (b) ? (a) : (b))
00174 #define min(a,b) ((a) < (b) ? (a) : (b))
00175 #define ABS(x) ((x) < 0 ? -(x) : (x))
00176 #define lowint(x) ((x) < 0 ? int(x-1) : int(x))
00177 #define asinht(x) (log((x)+sqrt((x)*(x)+1)))
00178 #define sinht(x) ((exp(x)-exp(-(x)))/2.)
00179
00180 int Hit_NCompare( const void*, const void* );
00181 int Hit_ACompare( const void*, const void* );
00182 void CopyVector( int*, int*, int );
00183 void CopyVector( hit*, hit*, int );
00184 void ZeroVector( int*, int );
00185 void ZeroVector( float*, int );
00186 void ZeroVector( hit*, int );
00187 void ResizeVector( int* , int, int );
00188 void CorrectPosition( float, float, float, float*, float* );
00189 void CalculateErrors( float e, float x, float y, float* pde, float* pdx, float* pdy, float* pdz);
00190 void GlobalToSector( float, float, float, float*, float*, float* );
00191 void SectorToGlobal( float xsec, float ysec, float zsec, float* px, float* py, float* pz );
00192 void SectorToGlobalErr( float dxsec, float dysec, float dzsec, float* pdx, float* pdy, float* pdz );
00193 void gamma(int, hit*, float*, float*, float*, float*, float*, float*, float*, float*);
00194 void twogamma(int, hit*, float*, float*, float*, float*, float*, float*, float*);
00195 void mom1(int, hit*, float*, float*, float*);
00196 void momenta(int, hit*, float*, float*, float*, float*, float*, float* );
00197 void c3to5(float, float, float, float, float, float, float*, float*, float*, float*, float*, float*);
00198 void SetProfileParameters(int, float, float, float);
00199 float ClusterChisq(int, hit*, float, float, float);
00200 float Chi2Limit( int ND );
00201
00202 void emshower::GetCorrPos( float* px, float* py )
00203
00204 {
00205 CorrectPosition( energy, xcg, ycg, px, py );
00206 }
00207
00208 void emshower::GetGlobalPos( float* px, float* py, float* pz )
00209
00210 {
00211 float xc, yc;
00212
00213 GetCorrPos( &xc, &yc );
00214
00215 SectorToGlobal( 0, yc, xc, px, py, pz );
00216 }
00217
00218 void cluster::GetCorrPos( float* px, float* py )
00219
00220 {
00221 float e, x, y, xx, yy, xy;
00222
00223 e = GetTotalEnergy();
00224 GetMoments( &x, &y, &xx, &xy, &yy );
00225 CorrectPosition( e, x, y, px, py );
00226 }
00227
00228 void cluster::GetGlobalPos( float* px, float* py, float* pz )
00229
00230 {
00231 float xc, yc;
00232
00233 GetCorrPos( &xc, &yc );
00234
00235 SectorToGlobal( 0, yc, xc, px, py, pz );
00236 }
00237
00238 float cluster::GetTowerEnergy( int ich )
00239
00240 {
00241 list<hit>::iterator ph;
00242 if( HitList.empty() ) return 0;
00243 ph = HitList.begin();
00244 while( ph != HitList.end() ) {
00245 if( (*ph).ich == ich ) return (*ph).amp;
00246 ph++;
00247 }
00248 return 0;
00249 }
00250
00251 float cluster::GetTowerToF( int ich )
00252
00253 {
00254 list<hit>::iterator ph;
00255 if( HitList.empty() ) return 0;
00256 ph = HitList.begin();
00257 while( ph != HitList.end() ) {
00258 if( (*ph).ich == ich ) return (*ph).tof;
00259 ph++;
00260 }
00261 return 0;
00262 }
00263
00264 float cluster::GetTotalEnergy()
00265
00266 {
00267 list<hit>::iterator ph;
00268 float et=0;
00269 if( HitList.empty() ) return 0;
00270 ph = HitList.begin();
00271 while( ph != HitList.end() ) {
00272 et += (*ph).amp;
00273 ph++;
00274 }
00275 return et;
00276 }
00277
00278 float cluster::GetE9( int ich )
00279
00280 {
00281 int i, ic, ixc, ix0, ichmax, ichmin, nhit;
00282 float e;
00283 hit *hlist, *vv;
00284 list<hit>::iterator ph;
00285
00286 e=0;
00287
00288 nhit = HitList.size();
00289
00290 if( nhit <= 0 ) return e;
00291
00292 hlist = new hit[nhit];
00293
00294 ph = HitList.begin();
00295 vv = hlist;
00296 while( ph != HitList.end() ) *vv++ = *ph++;
00297
00298 qsort( hlist, nhit, sizeof(hit), Hit_NCompare );
00299
00300 ichmax = ich + EMCzSize + 1;
00301 ichmin = ich - EMCzSize - 1;
00302 ix0 = ich - ich/EMCzSize*EMCzSize;
00303
00304 for( i=0; i<nhit; i++ )
00305 if( hlist[i].ich >= ichmin ) break;
00306 while( (i < nhit) && ( (ic=hlist[i].ich) <= ichmax) ) {
00307 ixc = ic - ic/EMCzSize*EMCzSize;
00308 if( abs(ixc-ix0) <= 1 ) e += hlist[i].amp;
00309 i++;
00310 }
00311
00312 delete hlist;
00313 return e;
00314 }
00315
00316 hit cluster::GetImpactTower()
00317
00318 {
00319 float x, y;
00320 int ix, iy, ich;
00321 hit ht;
00322
00323 GetCorrPos( &x, &y );
00324 ix = lowint(x/Tower_zSize + 0.5);
00325 iy = lowint(y/Tower_ySize + 0.5);
00326 if( ix < 0 || ix > EMCzSize-1 || iy < 0 || iy > EMCySize-1 ) {
00327 printf("????? EmcClusterChi2: Something wrong in GetImpactTower: (x,y)=(%f,%f) (ix,iy)=(%d,%d) \n", x, y, ix, iy);
00328 ht.ich = -1;
00329 ht.amp = 0;
00330 ht.tof = 0;
00331 return ht;
00332 }
00333 else {
00334 ich = iy*EMCzSize + ix;
00335 ht.ich = ich;
00336 ht.amp = GetTowerEnergy( ich );
00337 ht.tof = GetTowerToF( ich );
00338
00339 return ht;
00340 }
00341 }
00342
00343 hit cluster::GetMaxTower()
00344
00345 {
00346 list<hit>::iterator ph;
00347 float emax=0;
00348 hit ht;
00349
00350 ht.ich = -1;
00351 ht.amp = 0;
00352 ht.tof = 0;
00353 if( HitList.empty() ) return ht;
00354
00355 ph = HitList.begin();
00356 while( ph != HitList.end() ) {
00357 if( (*ph).amp > emax ) { emax = (*ph).amp; ht = *ph; }
00358 ph++;
00359 }
00360 return ht;
00361 }
00362
00363 void cluster::GetHits(hit* phit, int n)
00364
00365 {
00366 int nhit;
00367 hit *hlist, *vv;
00368 list<hit>::iterator ph;
00369 list<hit> hl;
00370
00371 ZeroVector( phit, n );
00372 nhit = HitList.size();
00373
00374 if( nhit <= 0 ) return;
00375
00376 hlist = new hit[nhit];
00377
00378 ph = HitList.begin();
00379 vv = hlist;
00380 while( ph != HitList.end() ) *vv++ = *ph++;
00381
00382 qsort( hlist, nhit, sizeof(hit), Hit_ACompare );
00383 for( int i=0; i<min(nhit,n); i++ ) phit[i]=hlist[i];
00384 delete hlist;
00385 }
00386
00387 void cluster::GetMoments( float* px, float* py, float* pxx, float* pxy, float* pyy )
00388
00389 {
00390 list<hit>::iterator ph;
00391 float e, x, y, xx, yy, xy;
00392 int nhit;
00393 hit *phit, *p;
00394
00395 *px = XABSURD; *py = YABSURD;
00396 *pxx = 0; *pxy = 0; *pyy = 0;
00397 nhit=HitList.size();
00398 if( nhit <= 0 ) return;
00399
00400 phit = new hit[nhit];
00401 ph = HitList.begin();
00402 p=phit;
00403 while( ph != HitList.end() ) {
00404 p->ich = (*ph).ich;
00405 p->amp = (*ph).amp;
00406 ph++;
00407 p++;
00408 }
00409 momenta( nhit, phit, &e, &x, &y, &xx, &yy, &xy );
00410 *px = x*Tower_zSize;
00411 *py = y*Tower_ySize;
00412 *pxx = xx*Tower_zSize*Tower_zSize;
00413 *pxy = xy*Tower_zSize*Tower_ySize;
00414 *pyy = yy*Tower_ySize*Tower_ySize;
00415
00416 delete phit;
00417 }
00418
00419 void cluster::GetErrors( float* pde, float* pdx, float* pdy, float* pdz)
00420
00421 {
00422 float e, x, y;
00423
00424 e = GetTotalEnergy();
00425 GetCorrPos( &x, &y );
00426 CalculateErrors( e, x, y, pde, pdx, pdy, pdz);
00427 }
00428
00429 void emshower::GetErrors( float* pde, float* pdx, float* pdy, float* pdz)
00430
00431 {
00432 float e, x, y;
00433
00434 e = GetTotalEnergy();
00435 GetCorrPos( &x, &y );
00436 CalculateErrors( e, x, y, pde, pdx, pdy, pdz);
00437 }
00438
00439 void cluster::GetChar( float* pe,
00440 float* pxcg, float* pycg,
00441 float* pxc, float* pyc,
00442 float* pxg, float* pyg, float* pzg,
00443 float* pxx, float* pxy, float* pyy,
00444 float* pde, float* pdx, float* pdy, float* pdz )
00445
00446
00447 {
00448 *pe = GetTotalEnergy();
00449 GetMoments( pxcg, pycg, pxx, pxy, pyy );
00450 CorrectPosition( *pe, *pxcg, *pycg, pxc, pyc );
00451 SectorToGlobal( 0, *pyc, *pxc, pxg, pyg, pzg );
00452 CalculateErrors( *pe, *pxc, *pyc, pde, pdx, pdy, pdz);
00453 }
00454
00455 void peakarea::GetChar( float* pe,
00456 float* pxcg, float* pycg,
00457 float* pxcgmin, float* pycgmin,
00458 float* pxc, float* pyc,
00459 float* pxg, float* pyg, float* pzg,
00460 float* pxx, float* pxy, float* pyy,
00461 float* pchi,
00462 float* pde, float* pdx, float* pdy, float* pdz )
00463
00464
00465 {
00466 float chi, chi0, chicorr;
00467 float e1, x1, y1, e2, x2, y2;
00468 int nh;
00469 hit *phit, *vv;
00470 list<hit>::iterator ph;
00471 list<hit> hl;
00472
00473 *pe = 0;
00474 hl = HitList;
00475 nh = hl.size();
00476 if( nh <= 0 ) return;
00477
00478 phit = new hit[nh];
00479
00480 ph = hl.begin();
00481 vv = phit;
00482 while( ph != hl.end() ) *vv++ = *ph++;
00483
00484 chi = chisq*1000;
00485 gamma(nh,phit,&chi,&chi0,&e1,&x1,&y1,&e2,&x2,&y2);
00486 chicorr = Chi2Correct(chi0,nh);
00487
00488 *pchi = chi0;
00489
00490 *pxcgmin = x1*Tower_zSize;
00491 *pycgmin = y1*Tower_ySize;
00492
00493 *pe = GetTotalEnergy();
00494 GetMoments( pxcg, pycg, pxx, pxy, pyy );
00495
00496 CorrectPosition( *pe, *pxcgmin, *pycgmin, pxc, pyc );
00497 SectorToGlobal( 0, *pyc, *pxc, pxg, pyg, pzg );
00498 CalculateErrors( *pe, *pxc, *pyc, pde, pdx, pdy, pdz);
00499
00500 delete phit;
00501 }
00502
00503
00504 void emshower::GetChar( float* pe,
00505 float* pxcg, float* pycg,
00506 float* pxc, float* pyc,
00507 float* pxg, float* pyg, float* pzg,
00508 float* pchi,
00509 float* pde, float* pdx, float* pdy, float* pdz )
00510
00511
00512 {
00513 *pe = GetTotalEnergy();
00514 GetCG( pxcg, pycg );
00515 CorrectPosition( *pe, *pxcg, *pycg, pxc, pyc );
00516 SectorToGlobal( 0, *pyc, *pxc, pxg, pyg, pzg );
00517 CalculateErrors( *pe, *pxc, *pyc, pde, pdx, pdy, pdz);
00518 *pchi = GetChi2();
00519 }
00520
00521
00522 float peakarea::GetChi2()
00523
00524
00525 {
00526 float chi, chi0, chicorr;
00527 float e1, x1, y1, e2, x2, y2;
00528 int nh;
00529 hit *phit, *vv;
00530 list<hit>::iterator ph;
00531 list<hit> hl;
00532
00533 hl = HitList;
00534 nh = hl.size();
00535 if( nh <= 0 ) return 0;
00536
00537 phit = new hit[nh];
00538
00539 ph = hl.begin();
00540 vv = phit;
00541 while( ph != hl.end() ) *vv++ = *ph++;
00542
00543 chi = chisq*1000;
00544 gamma(nh,phit,&chi,&chi0,&e1,&x1,&y1,&e2,&x2,&y2);
00545
00546 chicorr = Chi2Correct(chi0,nh);
00547
00548
00549 delete phit;
00550 return chi0;
00551 }
00552
00553 void peakarea::GetCGmin( float* px, float* py )
00554
00555 {
00556 float chi, chi0;
00557 float e1, x1, y1, e2, x2, y2;
00558 int nh;
00559 hit *phit, *vv;
00560 list<hit>::iterator ph;
00561 list<hit> hl;
00562
00563 *px = XABSURD;
00564 *py = YABSURD;
00565 hl = HitList;
00566 nh = hl.size();
00567 if( nh <= 0 ) return;
00568
00569 phit = new hit[nh];
00570
00571 ph = hl.begin();
00572 vv = phit;
00573 while( ph != hl.end() ) *vv++ = *ph++;
00574
00575 chi = chisq*1000;
00576 gamma(nh,phit,&chi,&chi0,&e1,&x1,&y1,&e2,&x2,&y2);
00577 *px = x1*Tower_zSize;
00578 *py = y1*Tower_ySize;
00579
00580 delete phit;
00581 }
00582
00583 int peakarea::GetGammas( emshower* ShList)
00584
00585
00586
00587
00588
00589
00590
00591
00592 {
00593 float chi, chi0, e1, x1, y1, e2, x2, y2, chicorr;
00594 int nh, ig;
00595 hit *phit, *vv;
00596 emshower sh1, sh2;
00597 list<hit>::iterator ph;
00598 list<hit> hl;
00599
00600
00601
00602 hl = HitList;
00603 nh = hl.size();
00604 if( nh <= 0 ) return 0;
00605
00606 phit = new hit[nh];
00607
00608 ph = hl.begin();
00609 vv = phit;
00610 while( ph != hl.end() ) *vv++ = *ph++;
00611
00612
00613 chi=Chi2Limit(nh);
00614 gamma(nh,phit,&chi,&chi0,&e1,&x1,&y1,&e2,&x2,&y2);
00615
00616 chicorr = Chi2Correct(chi,nh);
00617
00618 if( e1 > 0 )
00619 sh1.ReInitialize( e1, x1*Tower_zSize, y1*Tower_ySize, chi );
00620 else
00621 sh1.ReInitialize( 0, XABSURD, YABSURD, 0 );
00622
00623 if( e2 > 0 )
00624 sh2.ReInitialize( e2, x2*Tower_zSize, y2*Tower_ySize, chi );
00625 else
00626 sh2.ReInitialize( 0, XABSURD, YABSURD, 0 );
00627
00628 if( e2 > e1 ) {
00629 sh1.ReInitialize( e2, x2*Tower_zSize, y2*Tower_ySize, chi );
00630 sh2.ReInitialize( e1, x1*Tower_zSize, y1*Tower_ySize, chi );
00631 }
00632
00633 ig = 0;
00634 if( e1>0 ) {
00635 ShList[ig++]=sh1;
00636 if( e2>0 ) {
00637 ShList[ig++]=sh2;
00638 }
00639 }
00640
00641 delete phit;
00642 return ig;
00643 }
00644
00645 int cluster::GetPeaks( peakarea* PkList, hit* ppeaks )
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 {
00660 int npk, ipk, nhit;
00661 int ixypk, ixpk, iypk, in, nh, ic;
00662 int ixy, ix, iy, nn;
00663 int ig, ng, igmpk1[MaxNofPeaks], igmpk2[MaxNofPeaks];
00664 int PeakCh[MaxNofPeaks];
00665 float epk[MaxNofPeaks*2], xpk[MaxNofPeaks*2], ypk[MaxNofPeaks*2];
00666 float ratio, eg, dx, dy, a, chi, chi0;
00667 float *Energy[MaxNofPeaks], *totEnergy, *tmpEnergy;
00668 hit *ip;
00669 hit *phit, *hlist, *vv;
00670 peakarea peak;
00671 list<hit>::iterator ph;
00672 list<hit> hl;
00673
00674
00675 nhit = HitList.size();
00676
00677 if( nhit <= 0 ) return 0;
00678
00679 hlist = new hit[nhit];
00680
00681 ph = HitList.begin();
00682 vv = hlist;
00683 while( ph != HitList.end() ) *vv++ = *ph++;
00684
00685 qsort( hlist, nhit, sizeof(hit), Hit_NCompare );
00686
00687
00688
00689 npk=0;
00690 for( ic=0; ic<nhit; ic++ ) {
00691 float amp = hlist[ic].amp;
00692 if( amp > MinPeakEnergy ) {
00693 int ich = hlist[ic].ich;
00694 int ichmax = ich + EMCzSize + 1;
00695 int ichmin = ich - EMCzSize - 1;
00696 int ixc = ich - ich/EMCzSize*EMCzSize;
00697 int in = ic + 1;
00698 while( (in < nhit) && (hlist[in].ich <= ichmax) ) {
00699 int ix = hlist[in].ich - hlist[in].ich/EMCzSize*EMCzSize;
00700 if( (abs(ixc-ix) <= 1) && (hlist[in].amp >= amp) ) goto new_ic;
00701 in++;
00702 }
00703 in = ic - 1;
00704 while( (in >= 0) && (hlist[in].ich >= ichmin) ) {
00705 int ix = hlist[in].ich - hlist[in].ich/EMCzSize*EMCzSize;
00706 if( (abs(ixc-ix) <= 1) && (hlist[in].amp > amp) ) goto new_ic;
00707 in--;
00708 }
00709 if( npk >= MaxNofPeaks ) { delete hlist; return -1; }
00710 PeakCh[npk]=ic;
00711
00712 npk++;
00713 }
00714 new_ic: continue;
00715 }
00716
00717 if( npk <= 0 ) { delete hlist; return 0; }
00718 if( npk == 1 ) {
00719 *ppeaks = hlist[PeakCh[0]];
00720 hl.erase( hl.begin(), hl.end() );
00721 for( int ich=0; ich<nhit; ich++ ) hl.push_back(hlist[ich]);
00722 peak.ReInitialize(hl);
00723
00724 PkList[0]=peak;
00725 delete hlist;
00726 return 1;
00727 }
00728
00729 for( ipk=0; ipk<npk; ipk++ ) { Energy[ipk] = new float[nhit]; }
00730 totEnergy = new float[nhit];
00731 tmpEnergy = new float[nhit];
00732
00733
00734
00735 ratio = 1.;
00736 for( int iter=0; iter<PeakIter; iter++ ) {
00737 ZeroVector( tmpEnergy, nhit );
00738 for( ipk=0; ipk<npk; ipk++ ) {
00739
00740 ic = PeakCh[ipk];
00741 if( iter > 0 ) ratio = Energy[ipk][ic]/totEnergy[ic];
00742 eg = hlist[ic].amp * ratio;
00743 ixypk = hlist[ic].ich;
00744 iypk = ixypk/EMCzSize;
00745 ixpk = ixypk - iypk*EMCzSize;
00746 epk[ipk] = eg;
00747 xpk[ipk] = eg * ixpk;
00748 ypk[ipk] = eg * iypk;
00749
00750 if( ic < nhit-1 ){
00751 for( in=ic+1; in<nhit; in++ ) {
00752 ixy = hlist[in].ich;
00753 iy = ixy/EMCzSize;
00754 ix = ixy - iy*EMCzSize;
00755 if( (ixy-ixypk) > EMCzSize+1 ) break;
00756 if( abs(ix-ixpk) <= 1 ) {
00757 if( iter > 0 ) ratio = Energy[ipk][in]/totEnergy[in];
00758 eg = hlist[in].amp * ratio;
00759 epk[ipk] += eg;
00760 xpk[ipk] += eg*ix;
00761 ypk[ipk] += eg*iy;
00762 }
00763 }
00764 }
00765
00766 if( ic >= 1 ){
00767 for( in=ic-1; in >= 0; in-- ) {
00768 ixy = hlist[in].ich;
00769 iy = ixy/EMCzSize;
00770 ix = ixy - iy*EMCzSize;
00771 if( (ixypk-ixy) > EMCzSize+1 ) break;
00772 if( abs(ix-ixpk) <= 1 ) {
00773 if( iter > 0 ) ratio = Energy[ipk][in]/totEnergy[in];
00774 eg = hlist[in].amp * ratio;
00775 epk[ipk] += eg;
00776 xpk[ipk] += eg*ix;
00777 ypk[ipk] += eg*iy;
00778 }
00779 }
00780 }
00781
00782 xpk[ipk] = xpk[ipk]/epk[ipk];
00783 ypk[ipk] = ypk[ipk]/epk[ipk];
00784 SetProfileParameters(0, epk[ipk], xpk[ipk], ypk[ipk]);
00785 for( in=0; in<nhit; in++ ) {
00786 ixy = hlist[in].ich;
00787 iy = ixy/EMCzSize;
00788 ix = ixy - iy*EMCzSize;
00789 dx = xpk[ipk]-ix;
00790 dy = ypk[ipk]-iy;
00791 a = 0;
00792 if( ABS(dx) < 2.5 && ABS(dy) < 2.5 ) a = epk[ipk]*EMCcell(dx, dy, -1);
00793 Energy[ipk][in] = a;
00794 tmpEnergy[in] += a;
00795 }
00796
00797 }
00798
00799 for( in=0; in<nhit; in++ ) totEnergy[in] = max(0.000001,tmpEnergy[in]);
00800
00801 }
00802
00803 phit = new hit[nhit];
00804
00805 ng=0;
00806 for( ipk=0; ipk<npk; ipk++ ) {
00807 nh=0;
00808 for( in=0; in<nhit; in++ ) {
00809 if( tmpEnergy[in] > 0 ) {
00810 ixy = hlist[in].ich;
00811 a = hlist[in].amp * Energy[ipk][in]/tmpEnergy[in];
00812 if( a > Emin ) {
00813 phit[nh].ich=ixy;
00814 phit[nh].amp=a;
00815 phit[nh].tof= hlist[in].tof;
00816 nh++;
00817 }
00818 }
00819 }
00820 if( nh>0 ) {
00821
00822 chi=Chi2Limit(nh)*10;
00823 gamma(nh,phit,&chi,&chi0,&epk[ng],&xpk[ng],&ypk[ng],&epk[ng+1],&xpk[ng+1],&ypk[ng+1]);
00824 igmpk1[ipk]=ng;
00825 igmpk2[ipk]=ng;
00826 if( epk[ng+1]>0 ) { ng++; igmpk2[ipk]=ng;}
00827 ng++;
00828 }
00829 }
00830
00831 ZeroVector( tmpEnergy, nhit );
00832 for( ipk=0; ipk<npk; ipk++ ) {
00833 ig=igmpk1[ipk];
00834 SetProfileParameters(0, epk[ig], xpk[ig], ypk[ig]);
00835 for( in=0; in<nhit; in++ ) {
00836 Energy[ipk][in]=0;
00837 for(ig=igmpk1[ipk]; ig<=igmpk2[ipk]; ig++){
00838 ixy = hlist[in].ich;
00839 iy = ixy/EMCzSize;
00840 ix = ixy - iy*EMCzSize;
00841 dx = xpk[ig]-ix;
00842 dy = ypk[ig]-iy;
00843 a = epk[ig]*EMCcell(dx, dy, epk[ig]);
00844 Energy[ipk][in] += a;
00845 tmpEnergy[in] += a;
00846 }
00847 }
00848 }
00849
00850 ip = ppeaks;
00851 nn=0;
00852 for( ipk=0; ipk<npk; ipk++ ) {
00853 nh=0;
00854 for( in=0; in<nhit; in++ ) {
00855 if( tmpEnergy[in] > 0 ) {
00856 ixy = hlist[in].ich;
00857 a = hlist[in].amp * Energy[ipk][in]/tmpEnergy[in];
00858 if( a > Emin ) {
00859 phit[nh].ich=ixy;
00860 phit[nh].amp=a;
00861 phit[nh].tof=hlist[in].tof;
00862 nh++;
00863 }
00864 }
00865 }
00866 if( nh>0 ) {
00867 *ip++ = hlist[PeakCh[ipk]];
00868 hl.erase( hl.begin(), hl.end() );
00869 for( in=0; in<nh; in++ ) hl.push_back(phit[in]);
00870 peak.ReInitialize(hl);
00871
00872 PkList[nn++]=peak;
00873 }
00874 }
00875
00876 delete phit;
00877 delete hlist;
00878 for( ipk=0; ipk<npk; ipk++ ) delete Energy[ipk];
00879 delete totEnergy;
00880 delete tmpEnergy;
00881
00882
00883 return nn;
00884 }
00885
00886 void gamma(int nh, hit* phit, float* pchi, float* pchi0, float* pe1, float* px1, float* py1, float* pe2, float* px2, float* py2)
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897 {
00898 float e1, x1, y1, e2, x2, y2;
00899 float chi, chi0, chi00, chisq0, chisave;
00900 float chir, chil, chiu, chid;
00901 int dof;
00902 float x0, y0, d2, xm2;
00903 float stepx, stepy, parx, pary;
00904 const float dxy=0.06;
00905 const float stepmin=0.01;
00906 const float zTG=100;
00907 const float xmcut=0.0015;
00908
00909 *pe1=0;
00910 *px1=0;
00911 *py1=0;
00912 *pe2=0;
00913 *px2=0;
00914 *py2=0;
00915 if( nh <= 0 ) return;
00916 mom1(nh,phit,&e1,&x1,&y1);
00917 *pe1=e1;
00918 if( e1 <= 0 ) return;
00919
00920 SetProfileParameters(0, e1,x1,y1);
00921 chisave = *pchi;
00922 chi = *pchi;
00923 chi0 = ClusterChisq(nh,phit,e1,x1,y1);
00924
00925 chisq0 = chi0;
00926
00927 dof = nh;
00928 if( dof < 1 ) dof=1;
00929 chi = chisq0/dof;
00930 x0 = x1;
00931 y0 = y1;
00932 for(;;){
00933 chir = ClusterChisq(nh,phit,e1,x0+dxy,y0);
00934 chil = ClusterChisq(nh,phit,e1,x0-dxy,y0);
00935 chiu = ClusterChisq(nh,phit,e1,x0,y0+dxy);
00936 chid = ClusterChisq(nh,phit,e1,x0,y0-dxy);
00937
00938 if( (chi0 > chir) || (chi0 > chil) ) {
00939 stepx = dxy;
00940 if( chir > chil ) stepx = -stepx;
00941 }
00942 else {
00943 stepx = 0;
00944 parx = chir+chil-2*chi0;
00945 if( parx > 0 ) stepx = -dxy*(chir-chil)/2/parx;
00946 }
00947
00948 if( (chi0 > chiu) || (chi0 > chid) ) {
00949 stepy = dxy;
00950 if( chiu > chid ) stepy = -stepy;
00951 }
00952 else {
00953 stepy = 0;
00954 pary = chiu+chid-2*chi0;
00955 if( pary > 0 ) stepy = -dxy*(chiu-chid)/2/pary;
00956 }
00957 if( (ABS(stepx) < stepmin) && (ABS(stepy) < stepmin) ) break;
00958 chi00 = ClusterChisq(nh,phit,e1,x0+stepx,y0+stepy);
00959 if( chi00 >= chi0 ) break;
00960 chi0 = chi00;
00961 x0 += stepx;
00962 y0 += stepy;
00963 }
00964 if( chi0 < chisq0 ) {
00965 x1 = x0;
00966 y1 = y0;
00967 chi = chi0/dof;
00968 }
00969
00970 *pchi0 = chi;
00971 *pchi = chi;
00972 *px1 = x1;
00973 *py1 = y1;
00974
00975 if( chi > chisave ) {
00976 twogamma(nh,phit,&chi,&e1,&x1,&y1,&e2,&x2,&y2);
00977 if( e2 > 0 ) {
00978 d2 = ((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))/zTG/zTG;
00979 xm2 = e1*e2*d2;
00980 if( xm2 > 0 ) xm2 = sqrt(xm2);
00981 if( xm2 > xmcut && e1 > MinShowerEnergy && e2 > MinShowerEnergy) {
00982 *pe1 = e1;
00983 *px1 = x1;
00984 *py1 = y1;
00985 *pe2 = e2;
00986 *px2 = x2;
00987 *py2 = y2;
00988 *pchi = chi;
00989 }
00990 }
00991 }
00992
00993 }
00994
00995 void twogamma(int nh, hit* phit, float* pchi, float* pe1, float* px1, float* py1, float* pe2, float* px2, float* py2)
00996 {
00997 float e0, x0, y0, xx, yy, yx;
00998 float dxy, rsg2, rsq;
00999 float dxc, dyc, r, epsc;
01000 int ix, iy, ixy, in, iter, dof;
01001 float step, cosi, chisq2, u;
01002 float e1c, x1c, y1c, e2c, x2c, y2c;
01003 float eps0, eps1, eps2, chisqc, ex;
01004 float dx1, dy1, dx2, dy2, a0, d;
01005 float dchi, dchi0, dd, dchida, gr, a1, a2;
01006 float gre, grx, gry, grec, grxc, gryc, grc, gx1, gx2, gy1, gy2;
01007 float scal, dx0, dy0;
01008 const float epsmax=0.9999;
01009 const float stpmin=0.025;
01010 const float delch=2;
01011
01012 momenta(nh,phit,&e0,&x0,&y0,&xx,&yy,&yx);
01013 *pe2 = 0;
01014 *px2 = 0;
01015 *py2 = 0;
01016 if( nh <= 0 ) return;
01017
01018 dxy = xx-yy;
01019 rsg2 = dxy*dxy + 4*yx*yx;
01020 if( rsg2 < 1e-20 ) rsg2 = 1e-20;
01021 rsq = sqrt(rsg2);
01022 dxc = -sqrt((rsq+dxy)*2);
01023 dyc = sqrt((rsq-dxy)*2);
01024 if( yx >= 0 ) dyc = -dyc;
01025 r = sqrt(dxc*dxc + dyc*dyc);
01026 epsc = 0;
01027 for( in=0; in<nh; in++ ) {
01028 ixy = phit[in].ich;
01029 iy = ixy/EMCzSize;
01030 ix = ixy - iy*EMCzSize;
01031 u = (ix-x0)*dxc/r + (iy-y0)*dyc/r;
01032 epsc -= phit[in].amp * u * ABS(u);
01033 }
01034 epsc /= (e0*rsq);
01035 if( epsc > 0.8 ) epsc = 0.8;
01036 if( epsc < -0.8 ) epsc =-0.8;
01037 dxc /= sqrt(1-epsc*epsc);
01038 dyc /= sqrt(1-epsc*epsc);
01039
01040 step = 0.1;
01041 cosi = 0;
01042 chisq2 = 1.e35;
01043 for( iter=0; iter<100; iter++)
01044 {
01045 c3to5(e0,x0,y0,epsc,dxc,dyc,&e1c,&x1c,&y1c,&e2c,&x2c,&y2c);
01046 eps1 = (1+epsc)/2;
01047 eps2 = (1-epsc)/2;
01048 chisqc = 0;
01049 for( in=0; in<nh; in++ ) {
01050 ex = phit[in].amp;
01051 ixy = phit[in].ich;
01052 iy = ixy/EMCzSize;
01053 ix = ixy - iy*EMCzSize;
01054 dx1 = x1c - ix;
01055 dy1 = y1c - iy;
01056 dx2 = x2c - ix;
01057 dy2 = y2c - iy;
01058 a0 = e1c*EMCcell(dx1, dy1, e1c) + e2c*EMCcell(dx2, dy2, e2c);
01059 d = epar00*epar00 + e0*( epar1*a0/e0 + epar2*a0*a0/e0/e0 +epar3*a0*a0*a0/e0/e0/e0 ) + e0*sqrt(e0)*epar4*a0/e0*(1-a0/e0)*sin4a + e0*e0*epar0*epar0;
01060 chisqc += (a0-ex)*(a0-ex)/d;
01061 }
01062 if( chisqc >= chisq2 ) {
01063 if( iter > 0 ) {
01064 dchi = chisqc-chisq2;
01065 dchi0 = gr*step;
01066 step /= (2*sqrt(1+dchi/dchi0));
01067 }
01068 step /= 2;
01069 }
01070 else {
01071
01072 grec = 0;
01073 grxc = 0;
01074 gryc = 0;
01075 for( in=0; in<nh; in++ ) {
01076 ex = phit[in].amp;
01077 ixy = phit[in].ich;
01078 iy = ixy/EMCzSize;
01079 ix = ixy - iy*EMCzSize;
01080 dx1 = x1c - ix;
01081 dy1 = y1c - iy;
01082 dx2 = x2c - ix;
01083 dy2 = y2c - iy;
01084 a1 = e1c*EMCcell(dx1,dy1,e1c);
01085 a2 = e2c*EMCcell(dx2,dy2,e2c);
01086 a0 = a1 + a2;
01087 d = epar00*epar00 + e0*( epar1*a0/e0 + epar2*a0*a0/e0/e0 +epar3*a0*a0*a0/e0/e0/e0 ) + e0*sqrt(e0)*epar4*a0/e0*(1-a0/e0)*sin4a + e0*e0*epar0*epar0;
01088 dd = (a0-ex)/d;
01089 dchida = dd*( 2 - dd*(epar1 + 2*epar2*a0/e0 + 3*epar3*a0*a0/e0/e0 + e0*sqrt(e0)*epar4*sin4a*(1-2*a0/e0) + 2*epar0*epar0*a0) );
01090 gx1 = ( e1c*EMCcell(x1c+0.05-ix,dy1,e1c) - a1 )*20;
01091 gx2 = ( e2c*EMCcell(x2c+0.05-ix,dy2,e2c) - a2 )*20;
01092 gy1 = ( e1c*EMCcell(dx1, y1c+0.05-iy,e1c) - a1 )*20;
01093 gy2 = ( e2c*EMCcell(dx2, y2c+0.05-iy,e2c) - a2 )*20;
01094 grec += (dchida*((a1/e1c-a2/e2c)*e0 - (gx1+gx2)*dxc -(gy1+gy2)*dyc)/2);
01095 grxc += (dchida*(gx1*eps2-gx2*eps1));
01096 gryc += (dchida*(gy1*eps2-gy2*eps1));
01097 }
01098 grc = sqrt(grec*grec + grxc*grxc + gryc*gryc);
01099 if( grc < 1e-10 ) grc = 1e-10;
01100 if( iter > 0 ) {
01101 cosi = (gre*grec + grx*grxc + gry*gryc ) / (gr*grc);
01102 scal = ABS(gr/grc - cosi);
01103 if( scal < 0.1 ) scal = 0.1;
01104 step /= scal;
01105 }
01106 chisq2 = chisqc;
01107 eps0 = epsc;
01108 dx0 = dxc;
01109 dy0 = dyc;
01110 gre = grec;
01111 grx = grxc;
01112 gry = gryc;
01113 gr = grc;
01114 }
01115 epsc = eps0 - step*gre/gr;
01116 while( ABS(epsc) >= epsmax ) {
01117 step /= 2;
01118 epsc = eps0 - step*gre/gr;
01119 }
01120 dxc = dx0 - step*grx/gr;
01121 dyc = dy0 - step*gry/gr;
01122 if( step*gr < stpmin ) break;
01123 }
01124
01125 if( (*pchi)*nh-chisq2 < delch ) return;
01126
01127 dof = nh;
01128 if( dof < 1 ) dof = 1;
01129 *pchi = chisq2/dof;
01130 c3to5(e0,x0,y0,eps0,dx0,dy0,pe1,px1,py1,pe2,px2,py2);
01131 }
01132
01133 float ClusterChisq(int nh, hit* phit, float e, float x, float y)
01134 {
01135 float chi=0;
01136 int ixy, ix, iy;
01137 float et, a, d;
01138
01139 for( int in=0; in<nh; in++ ) {
01140 ixy = phit[in].ich;
01141 iy = ixy/EMCzSize;
01142 ix = ixy - iy*EMCzSize;
01143 et = phit[in].amp;
01144 a = EMCcell(x-ix, y-iy, -1);
01145 d = epar00*epar00 + e*(epar1*a + epar2*a*a + epar3*a*a*a) +
01146 e*sqrt(e)*epar4*a*(1-a)*sin4a + e*e*epar0*epar0;
01147 a *= e;
01148 chi += (et-a)*(et-a)/d;
01149
01150 }
01151 return chi;
01152 }
01153
01154 void mom1(int nh, hit* phit, float* pe, float* px, float* py)
01155
01156 {
01157 float a, xw, yw, e;
01158 int ix, iy;
01159 hit* p;
01160
01161 *pe=0;
01162 *px=0;
01163 *py=0;
01164 if( nh <= 0 ) return;
01165 p=phit;
01166 xw=0;
01167 yw=0;
01168 e=0;
01169 for( int i=0; i<nh; i++ ) {
01170 a = p->amp;
01171 iy = p->ich / EMCzSize;
01172 ix = p->ich - iy*EMCzSize;
01173 e += a;
01174 xw += ix*a;
01175 yw += iy*a;
01176 p++;
01177 }
01178 *pe = e;
01179 if( e <= 0 ) return;
01180 *px = xw/e;
01181 *py = yw/e;
01182 }
01183
01184 void momenta(int nh, hit* phit, float* pe, float* px, float* py, float* pxx, float* pyy, float* pyx )
01185
01186 {
01187 float a, x, y, e, xx, yy, yx;
01188 int ix, iy, i;
01189 hit* p;
01190
01191 *pe=0;
01192 *px=0;
01193 *py=0;
01194 *pxx=0;
01195 *pyy=0;
01196 *pyx=0;
01197 if( nh <= 0 ) return;
01198
01199 p=phit;
01200 x=0;
01201 y=0;
01202 e=0;
01203 xx=0;
01204 yy=0;
01205 yx=0;
01206 for( i=0; i<nh; i++ ) {
01207 a = p->amp;
01208 iy = p->ich / EMCzSize;
01209 ix = p->ich - iy*EMCzSize;
01210 e += a;
01211 x += ix*a;
01212 y += iy*a;
01213 xx += a*ix*ix;
01214 yy += a*iy*iy;
01215 yx += a*ix*iy;
01216 p++;
01217 }
01218 *pe = e;
01219 if( e <= 0 ) return;
01220 x /= e;
01221 y /= e;
01222 xx = xx/e - x*x;
01223 yy = yy/e - y*y;
01224 yx = yx/e - y*x;
01225
01226 *px = x;
01227 *py = y;
01228 *pxx = xx;
01229 *pyy = yy;
01230 *pyx = yx;
01231 }
01232
01233 void c3to5(float e0, float x0, float y0, float eps, float dx, float dy, float* pe1, float* px1, float* py1, float* pe2, float* px2, float* py2)
01234
01235
01236 {
01237 *pe1 = e0*(1+eps)/2;
01238 *pe2 = e0 - *pe1;
01239 *px1 = x0 + dx*(1-eps)/2;
01240 *py1 = y0 + dy*(1-eps)/2;
01241 *px2 = x0 - dx*(1+eps)/2;
01242 *py2 = y0 - dy*(1+eps)/2;
01243 }
01244
01245 void SetProfileParameters( int sec, float Energy, float z, float y )
01246
01247
01248
01249
01250
01251
01252 {
01253 float t;
01254 static float sin2ax, sin2ay, sin2a, lgE;
01255 float vx, vy, vz;
01256 float xVert, yVert, zVert;
01257 int sign;
01258
01259 if( sec >= 0 ) {
01260
01261 GlobalToSector( xVertex, yVertex, zVertex, &xVert, &yVert, &zVert );
01262 vx = xVert;
01263
01264
01265
01266 vy = y*Tower_ySize - yVert;
01267 vz = z*Tower_zSize - zVert;
01268
01269 sinax = vz/sqrt(vz*vz+vx*vx);
01270 sinay = vy/sqrt(vy*vy+vx*vx);
01271 if( ABS(sinax) > 0.5 || ABS(sinay) > 0.5 )
01272 printf("!!!!! mEmcClusterChi2: Something strange in SetProfileParameters: sinax=%f sinay=%f\n",sinax, sinay);
01273
01274
01275 t = (vz*vz+vy*vy)/(vz*vz+vy*vy+vx*vx);
01276 sin2a=t;
01277 sin4a=t*t;
01278 sin2ax=sinax*sinax;
01279 sin2ay=sinay*sinay;
01280 }
01281
01282 if( Energy <= 1.e-10 ) lgE=0;
01283 else lgE=log(Energy);
01284
01285 ppar1=0.59-(1.45+0.13*lgE)*sin2a;
01286 ppar2=0.265+(0.80+0.32*lgE)*sin2a;
01287 ppar3=0.25+(0.45-0.036*lgE)*sin2a;
01288 ppar4=0.42;
01289
01290 if( sinax > 0 ) sign = 1;
01291 else sign = -1;
01292 pShiftx = (1.05+0.12*lgE) * sin2ax * sign;
01293
01294
01295 if( sinay > 0 ) sign = 1;
01296 else sign = -1;
01297 pShifty = (1.05+0.12*lgE) * sin2ay * sign;
01298
01299 }
01300
01301
01302 float EMCcell( float xc, float yc, float en )
01303
01304
01305
01306
01307
01308
01309 {
01310 float dx, dy, r1, r2, r3, e;
01311
01312 if( en > 0 ) SetProfileParameters(-1,en,xc,yc);
01313 dx=ABS(xc-pShiftx);
01314 dy=ABS(yc-pShifty);
01315 e=0;
01316 r2=dx*dx+dy*dy;
01317 r1=sqrt(r2);
01318 r3=r2*r1;
01319 e=ppar1*exp(-r3/ppar2)+ppar3*exp(-r1/ppar4);
01320
01321 return e;
01322 }
01323
01324
01325 int Find_Clusters( list<hit> hlist, list<cluster>* pClList)
01326
01327
01328
01329 {
01330 int nhit, nCl;
01331
01332
01333 int LenCl[MaxLen];
01334 int next, ib, ie, ia, iab, iae, last, LastCl, leng, ich;
01335 hit *vv;
01336 hit *vhit, *vt;
01337 cluster Clt;
01338 list<hit>::iterator ph;
01339 list<hit> hl;
01340
01341 (*pClList).erase( (*pClList).begin(), (*pClList).end() );
01342 nhit = hlist.size();
01343
01344 if( nhit <= 0 ) return 0;
01345 if( nhit == 1 ) {
01346 Clt.ReInitialize( hlist );
01347 pClList->push_back(Clt);
01348 return 1;
01349 }
01350
01351 vt = new hit[nhit];
01352 vhit = new hit[nhit];
01353
01354 ph = hlist.begin();
01355 vv = vhit;
01356 while( ph != hlist.end() ) *vv++ = *ph++;
01357
01358 qsort( vhit, nhit, sizeof(hit), Hit_NCompare );
01359
01360 nCl=0;
01361 next = 0;
01362 for( ich=1; ich<nhit+1; ich++ ){
01363 if( ich<nhit ) ia=vhit[ich].ich;
01364 if( (ia-vhit[ich-1].ich > 1) || (ich >= nhit) ||
01365
01366 (ia-ia/EMCzSize*EMCzSize == 0) ){
01367 ib=next;
01368 ie=ich-1;
01369 next=ich;
01370 if( nCl >= MaxLen ) {
01371 return -1;
01372
01373
01374 }
01375 nCl++;
01376 LenCl[nCl-1]=next-ib;
01377 if( nCl > 1 ) {
01378
01379 iab=vhit[ib].ich;
01380 iae=vhit[ie].ich;
01381 last=ib-1;
01382 LastCl=nCl-2;
01383 for( int iCl=LastCl; iCl>=0; iCl-- ){
01384 leng=LenCl[iCl];
01385 #ifdef GLUE_CLUSTER_CORNER
01386
01387
01388 if( (iab-vhit[last].ich > EMCzSize+1) ||
01389
01390 ( (iab-vhit[last].ich == EMCzSize+1) &&
01391 (iab-iab/EMCzSize*EMCzSize == 0) ) ) goto new_ich;
01392 for( int ichc=last; ichc >= last-leng+1; ichc-- ) {
01393
01394 if( (iab-vhit[ichc].ich > EMCzSize+1) ||
01395
01396 ( (iab-vhit[ichc].ich == EMCzSize+1) &&
01397 (iab-iab/EMCzSize*EMCzSize == 0) ) ) goto new_icl;
01398
01399 if( (iae-vhit[ichc].ich >= EMCzSize-1) &&
01400
01401 ( (iae-vhit[ichc].ich != EMCzSize-1) ||
01402 ((iae+1)-(iae+1)/EMCzSize*EMCzSize != 0) ) ) {
01403
01404 #else
01405
01406 if( iab-vhit[last].ich > EMCzSize ) goto new_ich;
01407 for( int ichc=last; ichc >= last-leng+1; ichc-- ) {
01408 if( iab-vhit[ichc].ich > EMCzSize ) goto new_icl;
01409 if( iae-vhit[ichc].ich >= EMCzSize ) {
01410
01411 #endif
01412
01413 CopyVector( &vhit[last+1-leng], vt, leng );
01414 CopyVector( &vhit[last+1], &vhit[last+1-leng], ib-1-last );
01415 CopyVector( vt, &vhit[ib-leng], leng );
01416 for( int i=iCl; i<nCl-2; i++ ) LenCl[i]=LenCl[i+1];
01417 ib -= leng;
01418 LenCl[nCl-2]=LenCl[nCl-1]+leng;
01419 nCl--;
01420 goto new_icl;
01421 }
01422 }
01423 new_icl: last=last-leng;
01424 }
01425 }
01426 }
01427 new_ich: continue;
01428 }
01429
01430
01431 if( nCl > 0 ) {
01432 ib=0;
01433 for( int iCl=0; iCl<nCl; iCl++ ) {
01434 leng=LenCl[iCl];
01435 hl.erase( hl.begin(), hl.end() );
01436 for( ich=0; ich<leng; ich++ ) hl.push_back(vhit[ib+ich]);
01437 Clt.ReInitialize(hl);
01438 ib += LenCl[iCl];
01439 pClList->push_back(Clt);
01440 }
01441 }
01442
01443 delete vhit;
01444 delete vt;
01445
01446 return nCl;
01447 }
01448
01449
01450 void SetGeometry( SecGeom sg, float* Vertex )
01451
01452
01453
01454
01455 {
01456
01457
01458
01459 EMCzSize = sg.nz;
01460 EMCySize = sg.ny;
01461
01462
01463
01464 Tower_zSize = sg.Tower_zSize;
01465 Tower_ySize = sg.Tower_ySize;
01466
01467
01468
01469 xVertex = Vertex[0];
01470 yVertex = Vertex[1];
01471 zVertex = Vertex[2];
01472
01473
01474
01475
01476
01477
01478 xSector = sg.xyz0[0];
01479 ySector = sg.xyz0[1];
01480 zSector = sg.xyz0[2];
01481
01482
01483
01484
01485
01486
01487 normx = sg.nxyz[0];
01488 normy = sg.nxyz[1];
01489 normz = sg.nxyz[2];
01490
01491
01492
01493 }
01494
01495 void GlobalToSector( float xgl, float ygl, float zgl, float* px, float* py, float* pz )
01496 {
01497 float x, y, z;
01498
01499 x = xgl-xSector;
01500 y = ygl-ySector;
01501 z = zgl-zSector;
01502 *px = normx*x + normy*y;
01503 *py = -normy*x + normx*y;
01504 *pz = z;
01505 }
01506
01507 void SectorToGlobal( float xsec, float ysec, float zsec, float* px, float* py, float* pz )
01508 {
01509 *px = normx*xsec - normy*ysec + xSector;
01510 *py = normy*xsec + normx*ysec + ySector;
01511 *pz = zsec + zSector;
01512 }
01513
01514 void SectorToGlobalErr( float dxsec, float dysec, float dzsec, float* pdx, float* pdy, float* pdz )
01515 {
01516 *pdx = sqrt( normx*normx*dxsec*dxsec + normy*normy*dysec*dysec );
01517 *pdy = sqrt( normy*normy*dxsec*dxsec + normx*normx*dysec*dysec );
01518 *pdz = dzsec;
01519 }
01520
01521 void CalculateErrors( float e, float x, float y, float* pde, float* pdx, float* pdy, float* pdz)
01522
01523
01524
01525
01526
01527 {
01528 float de, dy, dz, dxg, dyg, dzg;
01529 static float ae = 0.076, be = 0.022;
01530 static float a = 0.57, b = 0.155, d = 1.6;
01531
01532
01533 static float dx = 0.1;
01534
01535
01536 de = sqrt( ae*ae*e + be*be*e*e );
01537 dz = a/sqrt(e) + b;
01538 dy = dz;
01539 dz = sqrt( dz*dz + d*d*sinax*sinax );
01540 dy = sqrt( dy*dy + d*d*sinay*sinay );
01541
01542 SectorToGlobalErr( dx, dy, dz, &dxg, &dyg, &dzg );
01543
01544 *pde = de;
01545 *pdx = dxg;
01546 *pdy = dyg;
01547 *pdz = dzg;
01548 }
01549
01550 void CorrectPosition( float Energy, float x, float y, float* pxc, float* pyc )
01551
01552
01553
01554
01555
01556
01557
01558 {
01559 float xShift, yShift, xZero, yZero, bx, by;
01560 float t, x0, y0;
01561 int ix0, iy0;
01562 int signx, signy;
01563
01564 SetProfileParameters( 0, Energy, x/Tower_zSize, y/Tower_ySize );
01565 if( sinax > 0 ) signx = 1;
01566 else signx = -1;
01567 if( sinay > 0 ) signy = 1;
01568 else signy = -1;
01569 t = 1.93+0.383*log(Energy);
01570
01571
01572 xShift = t*sinax;
01573 yShift = t*sinay;
01574 xZero=xShift-(0.417*ABS(sinax)+1.500*sinax*sinax)*signx;
01575 yZero=yShift-(0.417*ABS(sinay)+1.500*sinay*sinay)*signy;
01576 t = 0.98 + 0.98*sqrt(Energy);
01577 bx = 0.16 + t*sinax*sinax;
01578 by = 0.16 + t*sinay*sinay;
01579
01580
01581
01582
01583
01584 x0 = x/Tower_zSize;
01585 x0 = x0 - xShift + xZero;
01586 ix0 = lowint(x0 + 0.5);
01587 if( ABS(x0-ix0) <= 0.5 ) {
01588 x0 = (ix0-xZero)+bx*asinht( 2.*(x0-ix0)*sinht(0.5/bx) );
01589 *pxc = x0*Tower_zSize;
01590 }
01591 else {
01592 *pxc = x - xShift*Tower_zSize;
01593 printf("????? mEmcClusterChi2: Something wrong in CorrectPosition: x=%f dx=%f\n", x, x0-ix0);
01594 }
01595
01596 y0 = y/Tower_ySize;
01597 y0 = y0 - yShift + yZero;
01598 iy0 = lowint(y0 + 0.5);
01599 if( ABS(y0-iy0) <= 0.5 ) {
01600 y0 = (iy0-yZero)+by*asinht( 2.*(y0-iy0)*sinht(0.5/by) );
01601 *pyc = y0*Tower_ySize;
01602 }
01603 else {
01604 *pyc = y - yShift*Tower_ySize;
01605 printf("????? mEmcClusterChi2: Something wrong in CorrectPosition: y=%f dy=%f\n", y, y0-iy0);
01606 }
01607
01608 }
01609
01610
01611
01612 int Hit_NCompare( const void* h1, const void* h2 )
01613 {
01614 return ( ((hit*)h1)->ich - ((hit*)h2)->ich );
01615 }
01616
01617 int Hit_ACompare( const void* h1, const void* h2 )
01618 {
01619 float amp1 = ((hit*)h1)->amp;
01620 float amp2 = ((hit*)h2)->amp;
01621 return (amp1<amp2) ? 1: (amp1>amp2) ? -1 : 0;
01622 }
01623
01624 void ZeroVector( int* v, int N )
01625 {
01626 int* p = v;
01627 for( int i=0; i < N; i++ ) *p++ = 0;
01628 }
01629
01630 void ZeroVector( float* v, int N )
01631 {
01632 float* p = v;
01633 for( int i=0; i < N; i++ ) *p++ = 0;
01634 }
01635
01636 void ZeroVector( hit* v, int N )
01637 {
01638 for( int i=0; i < N; i++ ) { v[i].ich=0; v[i].amp=0; v[i].tof=0; }
01639 }
01640
01641 void ResizeVector( int* Vector, int OldSize, int NewSize )
01642 {
01643 int* vsave;
01644
01645 if( OldSize <= 0 ) { Vector = new int[NewSize]; return; }
01646 vsave = new int[OldSize];
01647 CopyVector( Vector, vsave, OldSize );
01648 delete Vector;
01649 Vector = new int[NewSize];
01650 if( NewSize > OldSize ) CopyVector( vsave, Vector, OldSize );
01651 else CopyVector( vsave, Vector, NewSize );
01652 delete vsave;
01653 return;
01654 }
01655
01656 void CopyVector( int* from, int* to, int N )
01657 {
01658 if( N <= 0 ) return;
01659 for( int i=0; i<N; i++ ) to[i]=from[i];
01660 }
01661
01662 void CopyVector( hit* from, hit* to, int N )
01663 {
01664 if( N <= 0 ) return;
01665 for( int i=0; i<N; i++ ) to[i]=from[i];
01666 }
01667
01668 void SetChi2Limit( int limit )
01669
01670
01671
01672
01673
01674
01675 {
01676 int i;
01677
01678 switch ( limit ) {
01679 case 0:
01680 for( i=0; i<50; i++ ) Chi2Level[i]=9999.;
01681 break;
01682 case 1:
01683 for( i=0; i<50; i++ ) Chi2Level[i]=Chi2Level1[i];
01684 break;
01685 case 2:
01686 for( i=0; i<50; i++ ) Chi2Level[i]=Chi2Level2[i];
01687 break;
01688 default:
01689 for( i=0; i<50; i++ ) Chi2Level[i]=Chi2Level1[i];
01690 break;
01691 }
01692 }
01693
01694
01695 float Chi2Limit( int ND )
01696
01697 {
01698 float rn, a, b, chi2;
01699
01700 if( ND < 1 ) return 9999.;
01701
01702 chi2 = Chi2Level[min(ND,50)-1];
01703 if( chi2 > 100 ) return 9999.;
01704
01705 rn = ND;
01706 b = 0.072*sqrt(rn);
01707 a = 6.21/(sqrt(rn)+4.7);
01708
01709 return chi2*a/(1.-chi2*b);
01710 }
01711
01712
01713 float Chi2Correct( float Chi2, int ND )
01714
01715 {
01716 float rn, a, b, c;
01717
01718 if( ND < 1 ) return 9999.;
01719
01720 rn = ND;
01721 b = 0.072*sqrt(rn);
01722 a = 6.21/(sqrt(rn)+4.7);
01723 c = a + b*Chi2;
01724 if( c < 1 ) c=1;
01725
01726 return Chi2/c;
01727 }
01728
01729 void SetThreshold( float Thresh )
01730 {
01731 epar0 = Thresh*0.07;
01732 epar00 = max( Thresh/3, 0.005 );
01733 }
01734
01735
01736
01737
01738
01739
01740
01741