00001 #include <stdio.h>
00002 #include <sys/types.h>
00003 #include <math.h>
00004 #include <string.h>
00005 #include <assert.h>
00006
00007 #ifdef __ROOT__
00008
00009 #define LOG(x,a,v1,v2,v3,v4,v5)
00010
00011 #else
00012 #include <rtsLog.h>
00013 #endif
00014
00015 #include <fcfClass.hh>
00016 #include <rts.h>
00017 #include <TPC/padfinder.h>
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 fcfAfterburner::fcfAfterburner()
00033 {
00034 last_n = last_count = last_i = last_stage = 0;
00035
00036 do_merge = do_cuts = 1 ;
00037
00038 verbose = true;
00039
00040
00041 }
00042
00043
00044
00045
00046
00047
00048
00049 void fcfAfterburner::print_hit(char *str, struct fcfHit *h)
00050 {
00051 if(str) {
00052 fprintf(stdout,"%s: ",str) ;
00053 }
00054
00055 fprintf(stdout,"%d %f %f %d %d %d %d %d %d %d %d %d\n",
00056 row,(double)h->pad/64.0+0.5,(double)h->tm/64.0+0.5,h->c,h->f,
00057 h->p1,h->p2,h->t1,h->t2,h->cl_id,h->id_simtrk,h->id_quality) ;
00058
00059 return ;
00060 }
00061
00062
00063
00064
00065
00066
00067 int fcfAfterburner::output(struct fcfHit *hit)
00068 {
00069 int ret ;
00070
00071
00072 if(do_cuts) {
00073 if(hit->f & (FCF_ONEPAD | FCF_ROW_EDGE | FCF_DEAD_EDGE)) ret = 0 ;
00074 else if((hit->t2 - hit->t1) <= 3) ret = 0 ;
00075 else if(hit->t1 == 0) ret = 0 ;
00076 else if(hit->c < 40) ret = 0 ;
00077 else ret = 1 ;
00078 }
00079 else {
00080 ret = 1 ;
00081 }
00082
00083 if(ret) {
00084
00085 }
00086 else {
00087
00088 }
00089
00090 return ret;
00091
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101 void fcfAfterburner::decode(u_int *ptr, struct fcfHit *hit, u_int *sim)
00102 {
00103 u_int pt, cf ;
00104 u_short flags, fl ;
00105 u_short tm, pad ;
00106 u_short p1,p2,t1,t2 ;
00107 u_short charge ;
00108
00109
00110
00111 if(sim) {
00112 struct FcfSimOutput *s = (struct FcfSimOutput *) sim ;
00113
00114
00115
00116 hit->id_simtrk = s->id_simtrk ;
00117 hit->id_quality = s->id_quality ;
00118 hit->cl_id = s->cl_id ;
00119 }
00120 else {
00121
00122 hit->id_simtrk = 0 ;
00123 hit->id_quality = 100 ;
00124 hit->cl_id = -1 ;
00125 }
00126
00127
00128 pt = *ptr++ ;
00129 cf = *ptr++ ;
00130
00131
00132 if(do_swap) {
00133 pt = swap32(pt) ;
00134 cf = swap32(cf) ;
00135 }
00136
00137 tm = (pt >> 16) & 0x7FFF ;
00138 pad = pt & 0x3FFF ;
00139 charge = cf >> 16 ;
00140 fl = cf & 0xFFFF ;
00141
00142 flags = 0 ;
00143 if(pt & 0x8000) flags |= FCF_DOUBLE_PAD ;
00144 if(pt & 0x4000) flags |= FCF_DEAD_EDGE ;
00145 if(pt & (0x8000 << 16)) flags |= FCF_ONEPAD ;
00146 if(fl & 0x8000) flags |= FCF_ROW_EDGE ;
00147 if(fl & 0x4000) flags |= FCF_BROKEN_EDGE ;
00148
00149 t2 = (fl & 0x00F0) >> 4 ;
00150 t1 = fl & 0x000F ;
00151
00152 t2 = (tm >> 6) + t2 ;
00153 t1 = (tm >> 6) - t1 ;
00154
00155 p2 = (fl & 0x3800) >> 11 ;
00156 p1 = (fl & 0x0700) >> 8 ;
00157
00158 p2 = (pad >> 6) + p2 ;
00159 p1 = (pad >> 6) - p1 ;
00160
00161
00162 hit->pad = pad ;
00163 hit->tm = tm ;
00164 hit->c = charge ;
00165 hit->f = flags ;
00166 hit->p1 = p1 ;
00167 hit->p2 = p2 ;
00168 hit->t1 = t1 ;
00169 hit->t2 = t2 ;
00170
00171 return ;
00172 }
00173
00174
00175
00176
00177
00178
00179 int fcfAfterburner::check_merge(struct fcfHit *hit_l, struct fcfHit *hit_r)
00180 {
00181 u_int charge ;
00182 double tm[2] ;
00183
00184 tm[0] = (double)hit_l->tm ;
00185 tm[1] = (double)hit_r->tm ;
00186
00187 if(fabs(tm[0]/64.0-tm[1]/64.0)<2.0) {
00188
00189
00190
00191 charge = hit_r->c + hit_l->c ;
00192 if(charge & 0xFFFF0000) {
00193 LOG(ERR,"Merge: charge too big %d %d",hit_r->c, hit_l->c,0,0,0) ;
00194 hit_l->c = hit_r->c = 0 ;
00195 return 0 ;
00196 }
00197
00198
00199 if(hit_r->id_simtrk != hit_l->id_simtrk) {
00200
00201 if(hit_r->c > hit_l->c) {
00202 hit_l->id_simtrk = hit_r->id_simtrk ;
00203 hit_l->id_quality= short((hit_r->id_quality*hit_r->c/double(charge))+0.5);
00204 } else {
00205 hit_l->id_quality= short((hit_l->id_quality*hit_l->c/double(charge))+0.5);
00206 }
00207
00208 } else {
00209
00210
00211 hit_l->id_quality = (hit_l->id_quality * hit_l->c + hit_r->id_quality * hit_r->c) / charge ;
00212 }
00213
00214
00215 if(hit_r->cl_id != hit_l->cl_id) {
00216 hit_l->cl_id = 0xFFFF ;
00217 }
00218
00219 hit_l->tm = (short)((tm[0]*(double)hit_l->c + tm[1]*(double)hit_r->c)/(double)charge) ;
00220
00221 tm[0] = (double)hit_l->pad ;
00222 tm[1] = (double)hit_r->pad ;
00223 hit_l->pad = (short)((tm[0]*(double)hit_l->c + tm[1]*(double)hit_r->c)/(double)charge) ;
00224
00225 hit_l->c = charge ;
00226 hit_r->c = 0 ;
00227
00228 hit_l->f |= hit_r->f ;
00229 hit_l->f &= ~FCF_ONEPAD ;
00230
00231
00232 hit_l->p2 = hit_r->p2 ;
00233
00234
00235 if(hit_r->t2 > hit_l->t2) hit_l->t2 = hit_r->t2 ;
00236 if(hit_r->t1 < hit_l->t1) hit_l->t1 = hit_r->t1 ;
00237
00238
00239
00240 return 1 ;
00241 }
00242
00243
00244 return 0 ;
00245 }
00246
00247
00248 int fcfAfterburner::burn(u_int *ptr_res[3], u_int *ptr_simu_res[3])
00249 {
00250 u_int i ;
00251
00252 last_i = last_n = last_count = last_stage = 0 ;
00253
00254 ptr = ptr_res ;
00255 ptr_simu = ptr_simu_res ;
00256
00257 for(i=0;i<3;i++) {
00258 if(ptr_res[i]) {
00259 row = *ptr_res[i] ;
00260
00261 if(row < 123) do_swap = 0 ;
00262 else do_swap = 1 ;
00263
00264 break ;
00265 }
00266 }
00267
00268 if(i==3) {
00269 row = 0 ;
00270 return -1 ;
00271 }
00272
00273
00274 row = 123 ;
00275 for(i=0;i<3;i++) {
00276 if(ptr[i]) {
00277 if(row == 123) row = do_swap ? swap32(*ptr[i]) : (*ptr[i]) ;
00278 else if(row != (do_swap ? swap32(*ptr[i]) : (*ptr[i]))) {
00279 row = 0 ;
00280 LOG(ERR,"Corrupted row data pointer %d: is %d expect %d",i,*ptr[i],row,0,0) ;
00281 return -1 ;
00282 }
00283 }
00284 }
00285
00286
00287
00288
00289 edge[0] = padfinder[row-1][0].maxpad ;
00290 edge[1] = padfinder[row-1][1].minpad ;
00291 edge[2] = padfinder[row-1][1].maxpad ;
00292 edge[3] = padfinder[row-1][2].minpad ;
00293
00294 memset(cou_broken,0,sizeof(cou_broken)) ;
00295
00296 return 0 ;
00297 }
00298
00299 int fcfAfterburner::next(fcfHit *h)
00300 {
00301
00302
00303
00304 u_int *res ;
00305 u_int *res_sim ;
00306
00307 if(row == 0) {
00308 return 0 ;
00309 }
00310
00311
00312
00313
00314 switch(last_stage) {
00315 case 0 :
00316 goto stage1 ;
00317 break ;
00318 case 1 :
00319 goto stage2 ;
00320 break ;
00321 case 2 :
00322 goto stage3 ;
00323 break ;
00324 }
00325
00326
00327 stage1: ;
00328 if(last_n >= 3) {
00329 goto stage2 ;
00330 }
00331
00332 res = ptr[last_n] ;
00333 if(ptr_simu) {
00334 res_sim = ptr_simu[last_n] ;
00335 }
00336 else {
00337 res_sim = 0 ;
00338 }
00339
00340 if(res == 0) {
00341 last_n++ ;
00342 last_i = 0 ;
00343 goto stage1;
00344 }
00345
00346 if(last_i == 0) {
00347 u_int irow = *res++ ;
00348 last_count = *res++ ;
00349
00350
00351 if(res_sim) res_sim += 2 ;
00352
00353 if(do_swap) {
00354 irow = swap32(irow) ;
00355 last_count = swap32(last_count) ;
00356 }
00357
00358 if(irow != row) LOG(ERR,"Row %d and row %d in data don't match!!!",row,irow,0,0,0) ;
00359 }
00360 else {
00361 res += 2 + 2*last_i ;
00362 if(res_sim) res_sim += 2 + (sizeof(struct FcfSimOutput)/4)*last_i ;
00363 }
00364
00365 while(last_i < last_count) {
00366
00367 fcfHit hit ;
00368 decode(res,&hit,res_sim) ;
00369
00370 res += 2 ;
00371 if(res_sim) {
00372 res_sim += (sizeof(struct FcfSimOutput)/4) ;
00373 }
00374
00375 last_i++ ;
00376
00377 if(do_merge && (hit.f & FCF_BROKEN_EDGE)) {
00378 int list ;
00379
00380 list = -1 ;
00381
00382 if(hit.p2 == edge[0]) list = 0 ;
00383 else if(hit.p1 == edge[1]) list = 1 ;
00384 else if(hit.p2 == edge[2]) list = 2 ;
00385 else if(hit.p1 == edge[3]) list = 3 ;
00386
00387 if(list >= 0 && cou_broken[list]<kMax_fcfHit) {
00388 memcpy(&(broken[list][cou_broken[list]]),&hit,sizeof(hit)) ;
00389 cou_broken[list]++ ;
00390
00391
00392 }
00393 else {
00394 LOG(DBG,"Row %d: incorrect edges are %d:%d, %f???",row,hit.p1,hit.p2,(double)hit.pad/64.0+0.5,0) ;
00395 LOG(DBG," %d %d %d %d",edge[0],edge[1],edge[2],edge[3],0) ;
00396 }
00397 }
00398 else {
00399 if(output(&hit)) {
00400 memcpy(h,&hit,sizeof(hit)) ;
00401 return 1 ;
00402 }
00403 }
00404 }
00405
00406 last_i = 0 ;
00407 last_n++ ;
00408 goto stage1 ;
00409
00410
00411 stage2: ;
00412 last_stage = 1 ;
00413
00414 if(edge[0] == 0) return 0 ;
00415
00416
00417
00418 int right ;
00419 for(right=0;right<4;right+=2) {
00420 u_int i, j ;
00421 for(i=0;i<cou_broken[right];i++) {
00422 int merged = 0 ;
00423 for(j=0;j<cou_broken[right+1];j++) {
00424 if(broken[right+1][j].c == 0) continue ;
00425
00426
00427 merged = check_merge(&broken[right][i],&broken[right+1][j]) ;
00428 if(merged) break ;
00429 }
00430 }
00431 }
00432
00433
00434
00435 last_i = 0 ;
00436 last_n = 0 ;
00437
00438 stage3: ;
00439 last_stage = 2 ;
00440
00441 if(last_n >= 4) return 0 ;
00442 while(last_i<cou_broken[last_n]) {
00443 if(output(&broken[last_n][last_i])) {
00444 memcpy(h,&broken[last_n][last_i],sizeof(fcfHit)) ;
00445 last_i++ ;
00446 return 1 ;
00447 }
00448 last_i++ ;
00449 }
00450 last_n++ ;
00451 last_i = 0 ;
00452 goto stage3 ;
00453
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 int fcfAfterburner::compare(u_int *p1[3], u_int *p2[3])
00465 {
00466 u_int matched1, count1, count2 ;
00467 u_int match ;
00468 fcfAfterburner after ;
00469 fcfHit h1, h2 ;
00470 static u_char marray[2][10000] ;
00471 int i ;
00472 int ret = 0 ;
00473 int save_merge, save_cuts ;
00474
00475
00476 save_merge = do_merge ;
00477 save_cuts = do_cuts ;
00478
00479
00480
00481
00482 do_merge = do_cuts = 0 ;
00483 after.do_merge = after.do_cuts = 0 ;
00484
00485 memset(marray,0,sizeof(marray)) ;
00486
00487 burn(p1) ;
00488 matched1 = count1 = 0 ;
00489
00490
00491 while(next(&h1)) {
00492
00493 match = 0 ;
00494 after.burn(p2) ;
00495
00496 count2 = 0 ;
00497
00498 while(after.next(&h2)) {
00499
00500 if(marray[1][count2]) {
00501 count2++ ;
00502 continue ;
00503 }
00504
00505 if(memcmp(&h1,&h2,sizeof(h1))==0) {
00506 marray[1][count2] = 1 ;
00507 match = 1 ;
00508 break ;
00509 }
00510 count2++ ;
00511 }
00512
00513 if(match) {
00514
00515 marray[0][count1] = 1 ;
00516 matched1++ ;
00517 }
00518 count1++ ;
00519 }
00520
00521 burn(p1) ;
00522 i = 0 ;
00523 while(next(&h1)) {
00524 if(marray[0][i] == 0) {
00525
00526
00527
00528
00529
00530 {
00531 if(verbose) print_hit("UNMATCHED 1",&h1) ;
00532 ret++;
00533 }
00534 }
00535 i++ ;
00536 }
00537
00538 after.burn(p2) ;
00539 i = 0 ;
00540 while(after.next(&h1)){
00541 if(marray[1][i] == 0) {
00542
00543
00544
00545
00546
00547 {
00548 if(verbose) print_hit("UNMATCHED 2",&h1) ;
00549 ret++;
00550 }
00551 }
00552 i++ ;
00553 }
00554
00555
00556 do_cuts = save_cuts ;
00557 do_merge = save_merge ;
00558 return ret ;
00559 }
00560