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 }
00204
00205 }
00206
00207
00208 hit_l->id_quality = (hit_l->id_quality * hit_l->c + hit_r->id_quality * hit_r->c) / charge ;
00209
00210
00211
00212 if(hit_r->cl_id != hit_l->cl_id) {
00213 hit_l->cl_id = 0xFFFF ;
00214 }
00215
00216 hit_l->tm = (short)((tm[0]*(double)hit_l->c + tm[1]*(double)hit_r->c)/(double)charge) ;
00217
00218 tm[0] = (double)hit_l->pad ;
00219 tm[1] = (double)hit_r->pad ;
00220 hit_l->pad = (short)((tm[0]*(double)hit_l->c + tm[1]*(double)hit_r->c)/(double)charge) ;
00221
00222 hit_l->c = charge ;
00223 hit_r->c = 0 ;
00224
00225 hit_l->f |= hit_r->f ;
00226 hit_l->f &= ~FCF_ONEPAD ;
00227
00228
00229 hit_l->p2 = hit_r->p2 ;
00230
00231
00232 if(hit_r->t2 > hit_l->t2) hit_l->t2 = hit_r->t2 ;
00233 if(hit_r->t1 < hit_l->t1) hit_l->t1 = hit_r->t1 ;
00234
00235
00236
00237 return 1 ;
00238 }
00239
00240
00241 return 0 ;
00242 }
00243
00244
00245 int fcfAfterburner::burn(u_int *ptr_res[3], u_int *ptr_simu_res[3])
00246 {
00247 u_int i ;
00248
00249 last_i = last_n = last_count = last_stage = 0 ;
00250
00251 ptr = ptr_res ;
00252 ptr_simu = ptr_simu_res ;
00253
00254 for(i=0;i<3;i++) {
00255 if(ptr_res[i]) {
00256 row = *ptr_res[i] ;
00257
00258 if(row < 123) do_swap = 0 ;
00259 else do_swap = 1 ;
00260
00261 break ;
00262 }
00263 }
00264
00265 if(i==3) {
00266 row = 0 ;
00267 return -1 ;
00268 }
00269
00270
00271 row = 123 ;
00272 for(i=0;i<3;i++) {
00273 if(ptr[i]) {
00274 if(row == 123) row = do_swap ? swap32(*ptr[i]) : (*ptr[i]) ;
00275 else if(row != (do_swap ? swap32(*ptr[i]) : (*ptr[i]))) {
00276 row = 0 ;
00277 LOG(ERR,"Corrupted row data pointer %d: is %d expect %d",i,*ptr[i],row,0,0) ;
00278 return -1 ;
00279 }
00280 }
00281 }
00282
00283
00284
00285
00286 edge[0] = padfinder[row-1][0].maxpad ;
00287 edge[1] = padfinder[row-1][1].minpad ;
00288 edge[2] = padfinder[row-1][1].maxpad ;
00289 edge[3] = padfinder[row-1][2].minpad ;
00290
00291 memset(cou_broken,0,sizeof(cou_broken)) ;
00292
00293 return 0 ;
00294 }
00295
00296 int fcfAfterburner::next(fcfHit *h)
00297 {
00298
00299
00300
00301 u_int *res ;
00302 u_int *res_sim ;
00303
00304 if(row == 0) {
00305 return 0 ;
00306 }
00307
00308
00309
00310
00311 switch(last_stage) {
00312 case 0 :
00313 goto stage1 ;
00314 break ;
00315 case 1 :
00316 goto stage2 ;
00317 break ;
00318 case 2 :
00319 goto stage3 ;
00320 break ;
00321 }
00322
00323
00324 stage1: ;
00325 if(last_n >= 3) {
00326 goto stage2 ;
00327 }
00328
00329 res = ptr[last_n] ;
00330 if(ptr_simu) {
00331 res_sim = ptr_simu[last_n] ;
00332 }
00333 else {
00334 res_sim = 0 ;
00335 }
00336
00337 if(res == 0) {
00338 last_n++ ;
00339 last_i = 0 ;
00340 goto stage1;
00341 }
00342
00343 if(last_i == 0) {
00344 u_int irow = *res++ ;
00345 last_count = *res++ ;
00346
00347
00348 if(res_sim) res_sim += 2 ;
00349
00350 if(do_swap) {
00351 irow = swap32(irow) ;
00352 last_count = swap32(last_count) ;
00353 }
00354
00355 if(irow != row) LOG(ERR,"Row %d and row %d in data don't match!!!",row,irow,0,0,0) ;
00356 }
00357 else {
00358 res += 2 + 2*last_i ;
00359 if(res_sim) res_sim += 2 + (sizeof(struct FcfSimOutput)/4)*last_i ;
00360 }
00361
00362 while(last_i < last_count) {
00363
00364 fcfHit hit ;
00365 decode(res,&hit,res_sim) ;
00366
00367 res += 2 ;
00368 if(res_sim) {
00369 res_sim += (sizeof(struct FcfSimOutput)/4) ;
00370 }
00371
00372 last_i++ ;
00373
00374 if(do_merge && (hit.f & FCF_BROKEN_EDGE)) {
00375 int list ;
00376
00377 list = -1 ;
00378
00379 if(hit.p2 == edge[0]) list = 0 ;
00380 else if(hit.p1 == edge[1]) list = 1 ;
00381 else if(hit.p2 == edge[2]) list = 2 ;
00382 else if(hit.p1 == edge[3]) list = 3 ;
00383
00384 if(list >= 0 && cou_broken[list]<kMax_fcfHit) {
00385 memcpy(&(broken[list][cou_broken[list]]),&hit,sizeof(hit)) ;
00386 cou_broken[list]++ ;
00387
00388
00389 }
00390 else {
00391 LOG(DBG,"Row %d: incorrect edges are %d:%d, %f???",row,hit.p1,hit.p2,(double)hit.pad/64.0+0.5,0) ;
00392 LOG(DBG," %d %d %d %d",edge[0],edge[1],edge[2],edge[3],0) ;
00393 }
00394 }
00395 else {
00396 if(output(&hit)) {
00397 memcpy(h,&hit,sizeof(hit)) ;
00398 return 1 ;
00399 }
00400 }
00401 }
00402
00403 last_i = 0 ;
00404 last_n++ ;
00405 goto stage1 ;
00406
00407
00408 stage2: ;
00409 last_stage = 1 ;
00410
00411 if(edge[0] == 0) return 0 ;
00412
00413
00414
00415 int right ;
00416 for(right=0;right<4;right+=2) {
00417 u_int i, j ;
00418 for(i=0;i<cou_broken[right];i++) {
00419 int merged = 0 ;
00420 for(j=0;j<cou_broken[right+1];j++) {
00421 if(broken[right+1][j].c == 0) continue ;
00422
00423
00424 merged = check_merge(&broken[right][i],&broken[right+1][j]) ;
00425 if(merged) break ;
00426 }
00427 }
00428 }
00429
00430
00431
00432 last_i = 0 ;
00433 last_n = 0 ;
00434
00435 stage3: ;
00436 last_stage = 2 ;
00437
00438 if(last_n >= 4) return 0 ;
00439 while(last_i<cou_broken[last_n]) {
00440 if(output(&broken[last_n][last_i])) {
00441 memcpy(h,&broken[last_n][last_i],sizeof(fcfHit)) ;
00442 last_i++ ;
00443 return 1 ;
00444 }
00445 last_i++ ;
00446 }
00447 last_n++ ;
00448 last_i = 0 ;
00449 goto stage3 ;
00450
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 int fcfAfterburner::compare(u_int *p1[3], u_int *p2[3])
00462 {
00463 u_int matched1, count1, count2 ;
00464 u_int match ;
00465 fcfAfterburner after ;
00466 fcfHit h1, h2 ;
00467 static u_char marray[2][10000] ;
00468 int i ;
00469 int ret = 0 ;
00470 int save_merge, save_cuts ;
00471
00472
00473 save_merge = do_merge ;
00474 save_cuts = do_cuts ;
00475
00476
00477
00478
00479 do_merge = do_cuts = 0 ;
00480 after.do_merge = after.do_cuts = 0 ;
00481
00482 memset(marray,0,sizeof(marray)) ;
00483
00484 burn(p1) ;
00485 matched1 = count1 = 0 ;
00486
00487
00488 while(next(&h1)) {
00489
00490 match = 0 ;
00491 after.burn(p2) ;
00492
00493 count2 = 0 ;
00494
00495 while(after.next(&h2)) {
00496
00497 if(marray[1][count2]) {
00498 count2++ ;
00499 continue ;
00500 }
00501
00502 if(memcmp(&h1,&h2,sizeof(h1))==0) {
00503 marray[1][count2] = 1 ;
00504 match = 1 ;
00505 break ;
00506 }
00507 count2++ ;
00508 }
00509
00510 if(match) {
00511
00512 marray[0][count1] = 1 ;
00513 matched1++ ;
00514 }
00515 count1++ ;
00516 }
00517
00518 burn(p1) ;
00519 i = 0 ;
00520 while(next(&h1)) {
00521 if(marray[0][i] == 0) {
00522
00523
00524
00525
00526
00527 {
00528 if(verbose) print_hit("UNMATCHED 1",&h1) ;
00529 ret++;
00530 }
00531 }
00532 i++ ;
00533 }
00534
00535 after.burn(p2) ;
00536 i = 0 ;
00537 while(after.next(&h1)){
00538 if(marray[1][i] == 0) {
00539
00540
00541
00542
00543
00544 {
00545 if(verbose) print_hit("UNMATCHED 2",&h1) ;
00546 ret++;
00547 }
00548 }
00549 i++ ;
00550 }
00551
00552
00553 do_cuts = save_cuts ;
00554 do_merge = save_merge ;
00555 return ret ;
00556 }
00557