StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
tpxFCF.cxx
1 /*
2  This code is property of Brookhaven National Laboratory, USA.
3  Authored by Tonko Ljubicic.
4 
5  No modifications are to be made without the express consent of
6  the author.
7 
8  Version 6.00 6/18/2007 Brand new TPX version
9 */
10 
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 
15 #include <rtsLog.h>
16 #include <I386/i386Lib.h>
17 
18 #include <TPC/rowlen.h>
19 
20 #include "tpxGain.h"
21 #include "tpxFCF.h"
22 
23 #include <DAQ_READER/daq_dta_structs.h>
24 
25 #define likely(x) __builtin_expect((x),1)
26 #define unlikely(x) __builtin_expect((x),0)
27 
28 char *tpxFCF::fcf_flags(u_char flags)
29 {
30  static char c_flags[32] ;
31 
32  c_flags[0] = 0 ; // empty string...
33 
34  if(flags & FCF_IN_DOUBLE) strcat(c_flags,"?") ; // can't be
35 
36  if(flags & FCF_DEAD_EDGE) strcat(c_flags,"D") ;
37  if(flags & FCF_BROKEN_EDGE) strcat(c_flags,"B") ;
38  if(flags & FCF_ROW_EDGE) strcat(c_flags,"E") ;
39 
40  if(flags & FCF_BIG_CHARGE) strcat(c_flags,"c") ;
41  if(flags & FCF_DOUBLE_T) strcat(c_flags,"!") ; // can't be
42  if(flags & FCF_MERGED) strcat(c_flags,"m") ;
43  if(flags & FCF_ONEPAD) strcat(c_flags,"1") ;
44 
45  if(c_flags[0] == 0) strcpy(c_flags,"0") ;
46 
47  return c_flags ;
48 }
49 
50 
51 int tpxFCF::afterburner(int cou, daq_cld *store[])
52 {
53  int merged ;
54 
55  if(likely(cou == 0)) return 0 ; // most cases like this...
56 
57  //printf("Start afterburner: cou %d\n",cou) ;
58 
59  merged = 0 ;
60 
61  for(int i=0;i<cou;i++) {
62  daq_cld *l = store[i] ; // left guy
63  int merge_ix = -1 ;
64 
65 
66 
67  if(l->charge == 0) continue ; // already merged
68  if(l->flags & FCF_BROKEN_EDGE) ;
69  else continue ;
70 
71  int type = 0 ;
72 
73  for(int j=0;j<cou;j++) {
74  int ok = 0 ;
75 
76 
77  if(j<=i) continue ;
78 
79  daq_cld *r = store[j] ; // right guy
80 
81  if(r->charge == 0) continue ; // already merged!
82  if(r->flags & FCF_BROKEN_EDGE) ;
83  else continue ;
84 
85  if(r->p1==13) { // right
86  if(l->p2 != 12) continue ;
87  type = 1 ;
88  }
89  else if(r->p2==12) {
90  if(l->p1 != 13) continue ;
91  type = 2 ;
92  }
93  else if(r->p1==131) {
94  if(l->p2 != 130) continue ;
95  type = 3 ;
96  }
97  else if(r->p2==130) {
98  if(l->p1 != 131) continue ;
99  type = 4 ;
100  }
101  else { // can happen if one was deconvoluted...
102  continue ;
103  type = 5 ;
104  }
105 
106  if((r->t1 >= l->t1) && (r->t1 <= l->t2)) ok = 1 ;
107  if((r->t2 >= l->t1) && (r->t2 <= l->t2)) ok = 1 ;
108 
109  if(ok==0) continue ;
110 
111  merge_ix = j ;
112  break ;
113 
114 
115 
116  }
117 
118  if(merge_ix < 0) { // no merge -- let it go...
119 
120  }
121  else {
122  // merge...
123  merged++ ;
124 
125  // merge
126  daq_cld *r = store[merge_ix] ;
127  double charge = l->charge + r->charge ;
128 
129  /*
130  printf("can merge %d: L%d: [%d:%d] %f, f 0x%02X, R%d: [%d:%d] %f f 0x%02X\n",
131  type,
132  i,l->p1,l->p2,l->tb,l->flags,
133  merge_ix,r->p1,r->p2,r->tb,r->flags) ;
134  */
135 
136  l->tb = (l->tb * l->charge + r->tb * r->charge) / charge ;
137  l->pad = (l->pad * l->charge + r->pad * r->charge) / charge ;
138 
139  if(r->t1 < l->t1) l->t1 = r->t1 ;
140  if(r->t2 > l->t2) l->t2 = r->t2 ;
141 
142  if(r->p1 < l->p1) l->p1 = r->p1 ;
143  if(r->p2 > l->p2) l->p2 = r->p2 ;
144 
145  l->flags |= r->flags ; // merge flags
146  l->flags &= ~FCF_ONEPAD ; // remove onepad, by dedfinition.
147 
148  // bug fixed...
149  if(charge > (double)0x7FFF) {
150 
151  int ch = (int) (charge+1) ; // roundoff
152 
153  ch /= 1024 ; // do what FCF does...
154 
155  l->charge = (u_short) ch * 1024 ; // do what decoder does...
156  l->flags |= FCF_BIG_CHARGE ;
157  }
158  else {
159  l->charge = (u_short) charge ;
160  }
161 
162  l->flags &= ~FCF_BROKEN_EDGE ;
163 
164  // and kill the right guy!
165  r->flags |= FCF_DEAD_EDGE ;
166  r->charge = 0 ;
167  }
168 
169 
170 
171  }
172 
173  // cleanup flags
174  for(int i=0;i<cou;i++) {
175  daq_cld *l = store[i] ; // left guy
176 
177 // printf("AfterB: %2d: P [%d:%d], T [%d:%d], flags %d, charge %d\n",i,l->p1,l->p2,l->t1,l->t2,l->flags,l->charge) ;
178 
179  if(l->flags & (FCF_ONEPAD | FCF_DEAD_EDGE | FCF_ROW_EDGE)) { // is this is still on, kill it with dead edge
180  l->flags |= FCF_DEAD_EDGE ;
181  l->charge = 0 ;
182  }
183  else {
184  l->flags &= ~FCF_BROKEN_EDGE ; // remove this flag since we ran the afterburner
185  }
186 
187  }
188 
189  return merged ;
190 }
191 
192 int tpxFCF::fcf_decode(u_int *p_buff, daq_cld *dc, u_short version)
193 {
194  double p, t ;
195  int p1,p2,t1,t2,cha,fla ;
196  u_int p_tmp, t_tmp ;
197 
198  // pad
199  p_tmp = *p_buff & 0xFFFF ;
200 
201  // time
202  t_tmp = *p_buff >> 16 ;
203 
204 
205  if(version==FCF_V_FY08) { // had a bug in FY08...
206  p = (double)(p_tmp & 0x3FFF) / 32.0 ;
207  t = (double)(t_tmp & 0x7FFF) / 32.0 ;
208  }
209  else {
210  p = (double)(p_tmp & 0x3FFF) / 64.0 ;
211  t = (double)(t_tmp & 0x7FFF) / 64.0 ;
212  }
213 
214  fla = 0 ;
215  if(p_tmp & 0x8000) fla |= FCF_MERGED ;
216  if(p_tmp & 0x4000) fla |= FCF_DEAD_EDGE ;
217  if(t_tmp & 0x8000) fla |= FCF_ONEPAD ;
218 
219 
220  p_buff++ ; // advance to next word
221  cha = *p_buff >> 16 ;
222 
223  if(cha >= 0x8000) { // special case of very large charge...
224 //printf("1: Big cha: 0x%08X %d; %f %f\n",cha,cha,p,t) ;
225 
226  fla |= FCF_BIG_CHARGE ;
227  cha = (cha & 0x7FFF) * 1024 ;
228 // if(cha == 0) cha = 0x8000; // exaclty, but can't be I think...
229 
230 //printf("2: Big cha: 0x%08X %d\n",cha,cha) ;
231 
232  // quasi fix of the very large problem...
233  if(cha > 0xFFFF) cha = 0xFFFF ; // because the daq_cld structure has charge as a short... damn...
234 
235  }
236 
237  p_tmp = *p_buff & 0xFFFF ; // reuse p_tmp
238 
239  if(p_tmp & 0x8000) fla |= FCF_ROW_EDGE ;
240  if(p_tmp & 0x4000) fla |= FCF_BROKEN_EDGE ;
241 
242  t1 = p_tmp & 0xF ;
243  t2 = (p_tmp >> 4) & 0xF ;
244 
245 
246  p1 = (p_tmp >> 8) & 0x7 ;
247  p2 = (p_tmp >> 11) & 0x7 ;
248 
249 
250  t1 = (int)t - t1 ;
251  t2 = (int)t + t2 ;
252 
253 
254  p1 = (int)p - p1 ;
255  p2 = (int)p + p2 ;
256 
257  dc->t1 = t1 ;
258  dc->t2 = t2 ;
259  dc->p1 = p1 ;
260  dc->p2 = p2 ;
261  dc->charge = cha ; // this is a problem for BIG_CHARGE... it will strip the upper bits... unsolved.
262  dc->flags = fla ;
263  dc->pad = p ;
264  dc->tb = t ;
265 
266 
267  return 2 ; // 2 u_ints used
268 
269 }
270 
271 int tpxFCF::fcf_decode(u_int *p_buff, daq_sim_cld *sdc, u_short version)
272 {
273  int skip = fcf_decode(p_buff,&(sdc->cld), version) ;
274 
275  sdc->track_id = 0 ;
276  sdc->quality = 0 ;
277 
278 
279  p_buff += skip ;
280 
281 
282  sdc->quality = (*p_buff) >> 16 ;
283  sdc->track_id = (*p_buff) & 0xFFFF ;
284 
285 
286  //LOG(TERR,"Q %d, T %d",sdc->quality, sdc->track_id) ;
287 
288  // took one int so...
289  skip++ ;
290 
291 
292  return skip ;
293 }
294 
295 
296 tpxFCF::s_static_storage *tpxFCF::gain_storage[24][256] ;
297 
298 
299 
300 tpxFCF::tpxFCF()
301 {
302  rbs = 0 ;
303  sector = 0 ;
304  modes = 0 ;
305 
306  rdo = 0 ;
307  fcf_style = 0 ;
308  memset(working_storage,0,sizeof(working_storage)) ;
309 
310  cl_marker = 0 ;
311  my_id = -1 ;
312 
313  run_compatibility = 9 ; // run 9
314  do_cuts = 2 ; // 1 means always, 2 means don't cut edges (for i.e. pulser run), 0 means don't...
315  ch_min = 10 ;
316 
317  row_count = 45 ; // default for our usual TPC
318  tpx_rowlen = tpc_rowlen ; // default for out usual TPC
319  tpx_padplane = 0 ; // original padplane
320 
321  memset(row_ix,0xFF,sizeof(row_ix)) ;
322  storage = 0 ;
323 
324 
325  read_version = 0 ;
326  do_version = FCF_V_FY09 ;
327 
328  return ;
329 }
330 
331 
332 tpxFCF::~tpxFCF()
333 {
334  if(storage) {
335  free(storage) ;
336  storage = 0 ;
337  }
338 
339  for(int s=0;s<24;s++) {
340  for(int r=0;r<256;r++) {
341  if(working_storage[s][r]) {
342  free(working_storage[s][r]) ;
343  working_storage[s][r] = 0 ;
344  }
345  if(gain_storage[s][r]) {
346  free(gain_storage[s][r]) ;
347  gain_storage[s][r] = 0;
348  }
349  }
350  }
351 
352  return ;
353 }
354 
355 /*
356  Called once at startup to allocate the static storage
357 */
358 void tpxFCF::config2(int sec1, int rdo1, int mode, int rows, unsigned char *rowlen)
359 {
360  int rdo0 = rdo1 - 1 ;
361  int sec0 = sec1 - 1 ;
362 
363  //temporary
364  sector = sec1 ;
365 
366  modes = mode ;
367 
368  if((rowlen==0) || (rows<=0)) {
369  tpx_rowlen = tpc_rowlen ;
370  row_count = 45 ; // force override
371  tpx_padplane = 0 ; // original
372  }
373  else {
374  tpx_rowlen = rowlen ;
375  row_count = rows ;
376  tpx_padplane = 1 ; // new padplane
377  }
378 
379 
380  int tot_count = 0 ;
381 
382  for(int a=0;a<256;a++) {
383  for(int ch=0;ch<16;ch++) {
384  int pad, row ;
385 
386  tpx_from_altro(rdo0,a,ch,row,pad) ;
387 
388  if(row > 250) continue ; // not in this RDO...
389  if(row == 0) continue ; // will nix row 0 as well...
390 
391  int bytes = tpx_rowlen[row] * sizeof(s_static_storage) ;
392 
393 
394  if(gain_storage[sec0][row]) ;
395  else {
396 
397 
398  gain_storage[sec0][row] = (s_static_storage *)valloc(bytes) ;
399  //and clear
400  memset(gain_storage[sec0][row],0, bytes) ;
401 
402  tot_count += tpx_rowlen[row] ;
403 
404  }
405 
406 
407 
408  s_static_storage *ss = get_static(row,pad) ;
409 
410  ss->f = FCF_NEED_PAD | FCF_ONEPAD ;
411  ss->g = 1.0 ;
412  ss->t0 = 0.0 ;
413  }
414  }
415 
416  LOG(TERR,"config2: S%2d, RDO %d: %d pads",sec1,rdo1,tot_count) ;
417 }
418 
419 
420 void tpxFCF::config(u_int mask, int mode, int rows, unsigned char *rowlen)
421 {
422  rbs = mask ;
423  modes = mode ;
424 
425  int r ;
426  int row, pad ;
427  int a, ch ;
428 
429  memset(row_ix,0,sizeof(row_ix)) ;
430 
431  if((rowlen==0) || (rows<=0)) {
432  tpx_rowlen = tpc_rowlen ;
433  row_count = 45 ; // force override
434  tpx_padplane = 0 ; // original
435  }
436  else {
437  tpx_rowlen = rowlen ;
438  row_count = rows ;
439  tpx_padplane = 1 ; // new padplane
440  }
441 
442 
443  //LOG(WARN,"calling config: mask 0x%X, mode %d, rows %3d",mask,mode,row_count) ;
444 
445  // There is some amount of acrobatics involved so
446  // bear with me...
447 
448  if(tpx_padplane) { // some new padplane
449  for(row=1;row<=row_count;row++) row_ix[row] = 1 ;
450  }
451  else { // original TPC padplane
452  // First, we figure out which rows are needed from the RB mask
453  for(r=0;r<6;r++) { // hell, let's assume 32 RDOs per sector...
454  if(rbs & (1<<r)) {
455  for(a=0;a<256;a++) {
456  for(ch=0;ch<16;ch++) {
457  tpx_from_altro(r,a,ch,row,pad) ;
458 
459  if(row > 250) continue ; // not in this RDO...
460  if(row == 0) continue ; // will nix row 0 as well...
461  row_ix[row] = 1 ; // mark as needed...
462  }
463  }
464  }
465  }
466  }
467 
468  // get the count of pads needed assuming _whole_ rows!
469  int tot_count = 0 ;
470  for(row=0;row<=row_count;row++) {
471  if(row_ix[row]) {
472  tot_count += tpx_rowlen[row] ; // allocate whole rows!
473  }
474  }
475 
476  LOG(NOTE,"fcfconfig: RDO mask 0x%03X: allocated %d pads (%d bytes)",rbs,tot_count,tot_count * sizeof(struct stage1)) ;
477 
478  // allocate storage
479  if(storage) {
480  LOG(WARN,"Whoa! Storage already allocated!") ;
481  free(storage) ;
482  }
483 
484  storage = (struct stage1 *) valloc(tot_count * sizeof(struct stage1)) ;
485 
486  LOG(NOTE,"FCF for mask 0x%02X: alloced %d bytes for %d tot_count X %d; cleared gains",mask,
487  tot_count * sizeof(struct stage1),
488  tot_count,
489  sizeof(struct stage1)) ;
490 
491  // clear storage
492  memset(storage,0,tot_count * sizeof(struct stage1)) ;
493 
494 
495 
496  // re-create offsets which we use in the row+pad navigation
497  tot_count = 0 ; // re use...
498  for(row=0;row<=row_count;row++) {
499  if(row_ix[row] == 0) {
500  row_ix[row] = -1 ; // nix!
501  continue ;
502  }
503 
504  row_ix[row] = tot_count ;
505 
506  tot_count += tpx_rowlen[row] ;
507  }
508 
509  // OK -- we have the storage and the navigation via get_stage1(row,pad) ready.
510  // Now let's get the per-pad flags ready:
511 
512  if(tpx_padplane) {
513  for(row=1;row<=row_count;row++) {
514  for(pad=1;pad<=tpx_rowlen[row];pad++) {
515  get_stage1(row,pad)->f = FCF_NEED_PAD | FCF_ONEPAD ;
516  get_stage1(row,pad)->g = 1.0 ;
517  get_stage1(row,pad)->t0 = 0.0 ;
518  }
519  }
520  }
521  else {
522  // Mark pads which are there as present...
523  for(r=0;r<6;r++) {
524  if(rbs & (1<<r)) {
525  for(a=0;a<256;a++) {
526  for(ch=0;ch<16;ch++) {
527  tpx_from_altro(r,a,ch,row,pad) ;
528 
529  if(row > 250) continue ;
530  if(row == 0) continue ;
531 
532  get_stage1(row, pad)->f = FCF_NEED_PAD | FCF_ONEPAD ;
533  get_stage1(row, pad)->g = 1.0 ;
534  get_stage1(row, pad)->t0 = 0.0 ;
535 
536  }
537  }
538  }
539  }
540  }
541 
542  return ;
543 }
544 
545 /*
546  This might me reapplied...
547 */
548 void tpxFCF::apply_gains2(tpxGain *gain)
549 {
550 // gains = gain ;
551 
552  if(tpx_padplane) gain = 0 ; // force it!
553 
554  if(gain == 0) {
555  LOG(WARN,"Sector %2d, gains NULL",sector) ;
556  }
557  else {
558  LOG(NOTE,"Applying gains to sector %d [%p ?]",sector,gain) ;
559  }
560 
561  // clear all flags but the existing higher ones
562  for(int s=0;s<24;s++) {
563  for(int r=0;r<256;r++) {
564  if(gain_storage[s][r] == 0) continue ;
565 
566  sector = s+1 ;
567  rdo = r+1 ;
568 
569  for(int row=1;row<=row_count;row++) {
570  for(int pad=1;pad<=tpx_rowlen[row];pad++) {
571  s_static_storage *ss = get_static(row,pad) ;
572 
573  if(ss==0) continue ;
574 
575  ss->f &= 0xFF00 ;
576  }
577  }
578  }
579  }
580 
581 
582  for(int s=0;s<24;s++) {
583  for(int r=0;r<256;r++) {
584  if(gain_storage[s][r] == 0) continue ;
585 
586  sector = s+1 ;
587  rdo = r+1 ;
588 
589  for(int row=1;row<=row_count;row++) {
590  for(int pad=1;pad<=tpx_rowlen[row];pad++) {
591  s_static_storage *ss = get_static(row,pad) ;
592  int kill = 0 ;
593 
594  if(ss==0) continue ;
595 
596  if(gain) {
597  ss->g = gain->get_gains(sector,row,pad)->g ;
598  ss->t0 = gain->get_gains(sector,row,pad)->t0 ;
599  }
600  else {
601  ss->g = 1.0 ;
602  ss->t0 = 0.0 ;
603  }
604 
605  int fl = 0 ;
606 
607  if(tpx_fy16_map==0) {
608  if(!(ss->f & FCF_NEED_PAD)) { // not in this RDO i.e. row 8 is split between RDO1 and RDO2
609  fl |= FCF_BROKEN_EDGE ;
610  LOG(TERR,"Broken edge in RDO %d: RP %d:%d",rdo,row,pad) ;
611  }
612  }
613 
614  if(ss->g < 0.001) {
615  fl |= FCF_DEAD_EDGE ;
616  kill |= FCF_KILLED_PAD ; // this pad is really dead!!!
617  }
618 
619  if(fl) { // apply the above flags to adjecant pads as well
620  if(pad>1) {
621  get_static(row,pad-1)->f |= fl ;
622  }
623  if(pad < tpx_rowlen[row]) {
624  get_static(row,pad+1)->f |= fl ;
625  }
626  }
627 
628  // marks the first and last pad as "edge"
629  if((pad==1) || (pad==tpx_rowlen[row])) {
630  fl |= FCF_ROW_EDGE ;
631  }
632 
633  ss->f |= fl | FCF_ONEPAD | kill ;
634 
635  //if(row<=13) {
636  // LOG(WARN,"S %d:%d, RP %d:%d is 0x%X",sector,rdo,row,pad,ss->f) ;
637  //}
638 
639  }
640  }
641  }
642  }
643 
644  return ;
645 }
646 
647 /*
648  This might me reapplied...
649 */
650 void tpxFCF::apply_gains(int sec, tpxGain *gain)
651 {
652  sector = sec ;
653  gain = gain ;
654 
655  int row, pad ;
656 
657  if(tpx_padplane) gain = 0 ; // force it!
658 
659  LOG(WARN,"apply_gains, sec %d",sec) ;
660 
661  if(gain == 0) {
662  LOG(WARN,"Sector %2d, gains NULL",sector) ;
663  }
664  else {
665  LOG(NOTE,"Applying gains to sector %d [%p ?]",sector,gain) ;
666  }
667 
668  // clear all flags but the existing ones
669  for(row=1;row<=row_count;row++) {
670  if(row_ix[row] < 0) continue ;
671 
672  for(pad=1;pad <= tpx_rowlen[row]; pad++) {
673 
674  get_stage1(row, pad)->f &= 0xFF00 ; // clear, keeping upper bits intact...
675  }
676  }
677 
678 
679  // put gains & flags
680  for(row=1;row<=row_count;row++) {
681  if(row_ix[row] < 0) continue ;
682 
683  for(pad=1;pad<=tpx_rowlen[row];pad++) {
684  stage1 *s = get_stage1(row, pad) ;
685 
686  if(gain) {
687  s->g = gain->get_gains(sector,row,pad)->g ;
688  s->t0 = gain->get_gains(sector,row,pad)->t0 ;
689  }
690  else {
691  s->g = 1.0 ;
692  s->t0 = 0.0 ;
693  }
694 
695  u_int fl = 0 ;
696 
697  if(!(s->f & FCF_NEED_PAD)) { // not really here; missing in the RDO...
698  //LOG(WARN,"Applying broken edge to row:pad %d:%d",row,pad) ;
699  fl |= FCF_BROKEN_EDGE ;
700  }
701 
702  if(s->g == 0.0) { // dead
703  fl |= FCF_DEAD_EDGE ;
704  }
705 
706 
707  // for these we must mark adjacent pads!
708  if(fl) {
709  if(pad>1) {
710  get_stage1(row,pad-1)->f |= fl ; // bad_edge
711  }
712  if(pad < tpx_rowlen[row]) {
713  get_stage1(row,pad+1)->f |= fl ; // bad_edge ;
714  }
715 
716  }
717 
718  // marks the first and last pad as "edge"
719  if((pad==1) || (pad==tpx_rowlen[row])) {
720  fl |= FCF_ROW_EDGE ;
721  }
722 
723  s->f |= fl | FCF_ONEPAD ;
724 
725  LOG(DBG,"FCF gains: row %2d, pad %3d: gain %f, flags 0x%04X",row,pad,s->g,s->f) ;
726 
727  }
728 
729 
730  }
731 
732 
733  return ;
734 }
735 
736 void tpxFCF::start_evt2(int sec1, int rdo1)
737 {
738  cl_marker = 10000 ; // used to mark unique clusters sector...
739 
740 // LOG(TERR,"start_evt2: START: %d %d",sec1,rdo1) ;
741 
742  sector = sec1 ;
743  rdo = rdo1 ;
744 
745 
746  for(int r=1;r<=row_count;r++) {
747  if(gain_storage[sector-1][r] == 0) continue ; //this is an optimization thing...
748 
749  for(int p=1;p<=tpx_rowlen[r];p++) {
750  struct stage1 *w ;
751  w = get_working(r, p) ;
752  if(unlikely(w==0)) {
753  LOG(ERR,"[%d] S%02d:%d: no row pad %d:%d???",my_id,sector,rdo,r,p) ;
754  }
755  else {
756  //LOG(TERR,"[%d] S%02d:%d: got rp %d:%d",my_id,sector,rdo,r,p) ;
757  w->count = 0 ;
758  }
759  }
760  }
761 
762 // LOG(TERR,"start_evt2: END: %d %d",sec1,rdo1) ;
763 
764  return ;
765 }
766 
767 
768 void tpxFCF::start_evt()
769 {
770  cl_marker = 10000 ; // used to mark unique clusters sector...
771 
772 
773  for(int r=1;r<=row_count;r++) {
774  if(row_ix[r] < 0) continue ;
775 
776  for(int p=1;p<=tpx_rowlen[r];p++) {
777  struct stage1 *o ;
778  o = get_stage1(r, p) ;
779  if(unlikely(o==0)) {
780  LOG(ERR,"No row pad %d:%d???",r,p) ;
781  }
782  else {
783  o->count = 0 ;
784  }
785  }
786  }
787 
788 
789  return ;
790 }
791 
792 
793 
794 int tpxFCF::do_pad(tpx_altro_struct *a, daq_sim_adc_tb *sim_adc)
795 {
796  struct stage1 *s ;
797 
798  if(unlikely(a->row > 250)) return 0 ;
799  if(unlikely(a->row == 0)) return 0 ;
800  if(unlikely(a->pad > tpx_rowlen[a->row])) return 0 ;
801 
802  if(fcf_style) {
803  s = get_working(a->row,a->pad) ;
804  }
805  else {
806  s = get_stage1(a->row, a->pad) ;
807 
808 
809  }
810 
811  if(unlikely(s==0)) {
812  LOG(ERR,"[%d] Whoa -- no row:pad %d:%d???",my_id,a->row,a->pad) ;
813  return 0 ;
814  }
815 
816  s->count = 0 ;
817 
818  if(unlikely(a->count<=1)) return 0 ; // no point....
819 
820 
821  // HACK put in on Mar 6th, 2009 to suppress those
822  // long strips (>=415 tb) of unknown nature (to that date).
823  // After run 10065096.
824  // Tonko.
825  // Actually, I will leave this cut in and lower to 400
826 
827  if(unlikely(a->count >= 400)) {
828  //LOG(WARN,"count %d on r:p %d:%d",a->count,a->row,a->pad) ;
829  return 0 ;
830  }
831 
832  u_int flags ;
833  u_int orig_flags ;
834 
835  if(fcf_style) {
836  struct s_static_storage *ss ;
837 
838  ss = get_static(a->row,a->pad) ;
839  if(unlikely(ss->g <= 0.001)) {
840  //LOG(WARN,"Killed %d:%d",a->row,a->pad) ;
841  return 0 ;
842  }
843 
844  orig_flags = flags = ss->f & 0xFF ;
845  }
846  else {
847  // kill, by hand, the pad which has 0.0 gain just to avoid confusion
848  // when the gains i.e. in Offline are misapplied
849  if(unlikely(s->g <= 0.001)) {
850  //LOG(WARN,"Killed %d:%d",a->row,a->pad) ;
851  return 0 ;
852  }
853 
854  orig_flags = flags = s->f & 0xFF ;
855  }
856 
857 
858 // if(a->row <= 13) {
859 // LOG(TERR,"Doing %d:%d %d",a->row,a->pad,a->count) ;
860 // }
861 
862  u_int t_ave, charge ;
863  u_int tb_start ;
864  u_int last_falling, last_adc ;
865 
866  u_int tb_prev ;
867  int new_cluster ;
868 
869  struct tpxFCF_cl *cl, *cl_max ;
870 
871 
872  cl = s->cl ; // start...
873  cl_max = &(s->cl[FCF_MAX_CL]) ; // end of cl sentinel...
874 
875 
876  u_int max_adc = 0 ;
877 
878  last_falling = last_adc = 0 ;
879  t_ave = charge = 0 ;
880 
881  tb_prev = tb_start = a->tb[0] ;
882 
883  new_cluster = 0 ;
884 
885 
886  // start the loop over raw pixels in this pad...
887  for(int i=0;likely( i < a->count );i++) {
888  u_int adc, tb ;
889 
890 
891  adc = a->adc[i] ;
892  tb = a->tb[i] ;
893 
894 // printf("........looking at %d %d %d %d\n",a->row,a->pad,tb,adc) ;
895 
896  if(unlikely( adc <= 1 )) { // possible due to ALTROs way of sticking sequences...
897  continue ;
898  }
899 
900  if(unlikely( tb < (tb_prev - 1) )) { // end of previous sequence
901  new_cluster |= FCF_ONEPAD ;
902  }
903 
904  if(unlikely( last_falling )) {
905  if(unlikely( last_falling > FCF_MIN_WIDTH )) {
906  if(unlikely( adc > (last_adc + FCF_ADC_NOISE) )) {
907  flags |= FCF_DOUBLE_T ;
908  new_cluster |= FCF_DOUBLE_T ;
909 
910  }
911  }
912  else {
913  last_falling++ ;
914  }
915 
916  }
917  else {
918  if(unlikely( (adc + FCF_ADC_NOISE) < last_adc )) {
919  last_falling = 1 ;
920  }
921  }
922 
923 
924  if(unlikely( new_cluster )) {
925  if(likely(max_adc >= FCF_ADC_MIN)) {
926  cl->t_ave = t_ave ;
927  cl->charge = charge ;
928 
929  cl->t1 = tb_prev; // put previous; t1 is the lower value
930  cl->t2 = tb_start ;
931 
932  cl->flags = flags ;
933 
934 
935  cl++ ;
936 
937  // protect storage!
938  if(unlikely( cl >= cl_max )) goto pad_done ; // to many!
939  }
940 
941  // prepare for new one...
942  if(unlikely( new_cluster & FCF_DOUBLE_T )) ;
943 // else flags = s->f & 0xFF ;
944  else flags = orig_flags & 0xFF ;
945 
946  t_ave = charge = 0 ;
947  tb_start = tb ;
948  last_falling = 0 ;
949  max_adc = 0 ;
950 
951  new_cluster = 0 ;
952  }
953 
954 
955  if(unlikely( adc > max_adc )) {
956  max_adc = adc ;
957  }
958 
959  last_adc = adc ;
960  tb_prev = tb ;
961 
962  t_ave += adc * tb ;
963  charge += adc ;
964 
965 
966  } // scan over the sequence
967 
968  // finish off the rest...
969  if(likely(max_adc >= FCF_ADC_MIN)) {
970  cl->t1 = tb_prev ; // t1 is the lower value
971  cl->t2 = tb_start ;
972 
973  cl->flags = flags ;
974 
975  cl->charge = charge ;
976  cl->t_ave = t_ave ;
977 
978  cl++ ;
979  }
980 
981  // goto target...
982  pad_done: ;
983 
984 
985  s->count = cl - s->cl ; // count of 1d clusters
986 
987 
988  if(unlikely( s->count == 0 )) {
989  //LOG(DBG,"No 1D clusters?") ;
990  }
991  else {
992  if(unlikely( s->count >= FCF_MAX_CL )) {
993  LOG(NOTE,"Row %d:%d, %d clusters [max!]",a->row,a->pad,s->count) ;
994  }
995  else {
996  //LOG(DBG,"Row %d:%d, %d clusters",a->row,a->pad,s->count) ;
997  }
998  }
999 
1000 #ifdef FCF_DEBUG
1001  // debugging dump
1002  cl = s->cl ;
1003  for(int j=0;j<s->count;j++) {
1004  LOG(DBG,"C: %d:%d\t %3d %3d, ch %5d, fl 0x%X",a->row,a->pad,cl->t1,cl->t2,cl->charge,cl->flags) ;
1005  cl++ ;
1006  }
1007 
1008 #endif
1009 
1010  if(unlikely(sim_adc && modes)) { // FCF_ANNOTATION for simulated data!
1011  cl = s->cl ;
1012 
1013  for(int j=0;j<s->count;j++) {
1014 
1015  int t_lo = cl->t1 ;
1016  int t_hi = cl->t2 ;
1017  int adc_min = 0 ;
1018 
1019  cl->track_id = 0 ;
1020  cl->quality = 0 ;
1021 
1022  u_int adc_sum = 0 ;
1023  u_int t_sum = 0 ;
1024 
1025  // position this clusters sim data...
1026  int i_min = 0xFFFFFF ;
1027  cl->sim = 0 ;
1028  cl->sim_length = 0 ;
1029  for(int i=0;i<a->count;i++) {
1030  if((a->tb[i] >= t_lo) && (a->tb[i]<=t_hi)) { // belong to this sequence
1031  if(i < i_min) i_min = i ; // need the smallest I
1032  cl->sim_length++ ;
1033 
1034  // in case of non-geant data, overwrite the track ids with the current marker...
1035  if(sim_adc[i].track_id == 0xFFFF) {
1036  modes |= 2 ; // heuristic to set the correct mode
1037  sim_adc[i].track_id = cl_marker ;
1038  }
1039  }
1040  }
1041  cl->sim = sim_adc + i_min ; // this is where the sim data starts...
1042 
1043 
1044  // get thr track id from the pixel with the maximum ADC
1045  for(int i=0;i<a->count;i++) {
1046  if((a->tb[i] >= t_lo) && (a->tb[i]<=t_hi)) { // belong to this sequence
1047  adc_sum += a->adc[i] ;
1048 
1049  if(a->adc[i] >= adc_min) {
1050  adc_min = a->adc[i] ; // bug before Oct 09!
1051  cl->track_id = sim_adc[i].track_id ;
1052  }
1053  }
1054  }
1055 
1056  // sum the pixels whic belong to this track id only
1057  for(int i=0;i<a->count;i++) {
1058  if((a->tb[i] >= t_lo) && (a->tb[i]<=t_hi)) { // belong to this sequence
1059 
1060  if(cl->track_id == sim_adc[i].track_id) {
1061  t_sum += a->adc[i] ;
1062  }
1063  }
1064  }
1065 
1066  if(adc_sum) {
1067  cl->quality = (t_sum * 100) / adc_sum ;
1068 
1069  }
1070  else {
1071  cl->quality = 0 ;
1072  }
1073 
1074 
1075  //LOG(TERR,"%d: track id %d, qua %d",cl_marker,cl->track_id, cl->quality) ;
1076 
1077  cl_marker++ ;
1078  cl++ ;
1079 
1080  }
1081 
1082  }
1083 
1084 
1085  return s->count ; // returns count...
1086 }
1087 
1088 
1089 int tpxFCF::stage2(u_int *outbuff, int max_bytes)
1090 {
1091  int r, p, c ;
1092  struct stage1 *old1, *cur1 ;
1093 
1094 
1095  tpxFCF_cl *old, *cur, *old_end, *cur_end ;
1096 
1097  loc_buff = outbuff ; // copy over
1098 
1099 
1100  for(r=1;r<=row_count;r++) {
1101  if(fcf_style) {
1102  if(gain_storage[sector-1][r] == 0) continue ;
1103  }
1104  else {
1105  if(row_ix[r] < 0) continue ;
1106  }
1107 
1108 
1109  cur_row = r ;
1110  //if(cur_row == 0) {
1111  // LOG(WARN,"Can;t be -- row 0; row_ix %d",row_ix[r]) ;
1112  //}
1113 
1114  int bytes_so_far = (loc_buff - outbuff)*4 ;
1115  if(bytes_so_far > (max_bytes-1024)) {
1116  LOG(WARN,"row %d: approaching limit: is %d, max %d",cur_row,bytes_so_far,max_bytes) ;
1117  }
1118 
1119 
1120  u_int *row_cache = loc_buff++ ; // remember where the row goes...
1121  u_int *clust_count_cache = loc_buff++ ; // remember where the cluster count goes...
1122 
1123 
1124  cur_row_clusters = 0 ;
1125 
1126  //LOG(TERR,"[%d S%02d:%d] going into row %d",my_id,sector,rdo,r) ;
1127 
1128  // scan from first pad to one before the last...
1129  for(p=1;p<tpx_rowlen[r];p++) {
1130 
1131  if(fcf_style) {
1132  struct s_static_storage *old_ss, *cur_ss ;
1133 
1134  old1 = get_working(r,p) ;
1135 
1136  if(old1->count == 0) continue ;
1137 
1138  cur1 = get_working(r,p+1) ;
1139 
1140  old_ss = get_static(r,p) ;
1141  cur_ss = get_static(r,p+1) ;
1142 
1143  //LOG(TERR,"%p %p %p %p",old1,cur1,old_ss,cur_ss) ;
1144 
1145  old1->g = old_ss->g ;
1146  old1->t0 = old_ss->t0 ;
1147  //old1->f = 0 ;
1148 
1149  cur1->g = cur_ss->g ;
1150  cur1->t0 = cur_ss->t0 ;
1151  //cur1->f = 0 ;
1152 
1153 
1154 
1155  }
1156  else {
1157  old1 = get_stage1(r,p) ;
1158  cur1 = get_stage1(r,p+1) ;
1159  }
1160 
1161  //if(r<=13) LOG(TERR,"[%d] rp %d:%d : gain %f, t0 %f, flags 0x%X",my_id,r,p,old1->g,old1->t0,old1->f) ;
1162 
1163  old = old1->cl ;
1164  cur = cur1->cl ;
1165 
1166  //LOG(DBG,"row %d: pad %d:%d, pad++ %d:%d",r,p,old1->count,p+1,cur1->count) ;
1167 
1168  //LOG(DBG,"RP %d:%d at 0x%08X, next at 0x%08X",r,p,old1,cur1) ;
1169 
1170  // counters
1171  //if(old1->count) LOG(DBG,"pad %d: count %d",p,old1->count) ;
1172 
1173  //end sentinel
1174  cur_end = cur + cur1->count ;
1175  old_end = old + old1->count ;
1176 
1177 
1178  while(old<old_end) { // loop over old
1179  int merge ;
1180 
1181  merge = 0 ;
1182 
1183 
1184  // loop over next, called "cur"
1185  while(likely(cur<cur_end)) {
1186 
1187  //LOG(DBG,"Row %d: old pad %d[%d]: %d..%d 0x%X, new %d..%d 0x%X [%d]",r,p,old_end-old,
1188  // old->t1,old->t2,old->flags,cur->t1,cur->t2,cur->flags,cur_end-cur) ;
1189 
1190  // every "new" sequence MUST be one_pad!
1191  if(cur->flags & FCF_ONEPAD) ;
1192  else {
1193  LOG(WARN,"Can;t be without ONEPAD %d:%d 0x%X?! %d..%d",r,p+1,cur->flags,cur->p1,cur->p2) ;
1194  }
1195 
1196  //LOG(DBG,"p %d: %d %d",p,old->t1,cur->t2) ;
1197 
1198 
1199  if(unlikely((old->t1 - cur->t2) >= 1)) {
1200  // the old guy is left behind and thus
1201  // we can only dump it oiut at this point
1202  merge = 2 ;
1203 
1204  // keep the current guy
1205 
1206  break ; // this dumps the old guy
1207  }
1208  else if(unlikely((cur->t1 - old->t2) > 1)) {
1209  // don't use the new guy ever again...
1210 
1211  cur++ ;
1212  continue ;
1213  }
1214  else { // we are merging here into cur for sure!
1215 
1216  // it only depends to see if we just merge and blow "old"
1217  // or
1218  // merge part of "old" and dump "old"
1219  //LOG(DBG,"Merge") ;
1220 
1221  // move to double and gain correct!
1222  if(unlikely(cur->flags & FCF_IN_DOUBLE)) {
1223 
1224  }
1225  else {
1226  cur->flags |= FCF_IN_DOUBLE ;
1227 
1228  cur->f_charge = cur->charge * cur1->g ;
1229  cur->scharge = cur->f_charge ;
1230 
1231  cur->f_t_ave = cur->t_ave * cur1->g ;
1232  //BUG in FY10!!!
1233  //cur->f_t_ave += cur1->g * cur1->t0 ;
1234  cur->f_t_ave += cur->f_charge * cur1->t0 ;
1235  cur->p1 = p+1 ;
1236  cur->p_ave = (p+1) * cur->f_charge ;
1237 
1238  // Added in FY12
1239  cur->t_min = cur->t1 ;
1240  cur->t_max = cur->t2 ;
1241 
1242  }
1243 
1244 
1245  // also correct the charge if the old guy is still no corrected -- first pad in a sequence
1246  if(likely(old->flags & FCF_IN_DOUBLE)) {
1247 
1248  }
1249  else {
1250  // correct charge here
1251  old->flags |= FCF_IN_DOUBLE ;
1252 
1253  old->f_charge = old->charge * old1->g ;
1254  old->scharge = old->f_charge ;
1255 
1256  old->f_t_ave = old->t_ave * old1->g ;
1257  //BUG in FY10!!!
1258  //old->f_t_ave += old1->g * old1->t0 ;
1259  old->f_t_ave += old->f_charge * old1->t0 ;
1260 
1261  old->t_min = old->t1 ;
1262  old->t_max = old->t2 ;
1263 
1264  old->p1 = p ;
1265  old->p_ave = p * old->f_charge ;
1266  }
1267 
1268 
1269 
1270  if(unlikely(old->flags & FCF_FALLING)) {
1271 
1272  if(unlikely(old->flags & FCF_ONEPAD)) {
1273  LOG(ERR,"Can't be on a merge!") ;
1274  }
1275  if(unlikely(!(old->flags & FCF_IN_DOUBLE))) {
1276  LOG(ERR,"Can't be on a merge!!!") ;
1277  }
1278 
1279 
1280  if(unlikely(cur->scharge > (old->scharge + FCF_MIN_ADC_PAD_C))) {
1281 
1282  // we are splitting here!
1283  double sc_tmp, sc_p_tmp ;
1284 
1285  // take half of old scharge
1286 
1287  sc_tmp = old->scharge * 0.5 ;
1288  sc_p_tmp = sc_tmp * (p+1) ;
1289 
1290 
1291  cur->flags |= FCF_DOUBLE_PAD ;
1292  cur->f_charge += sc_tmp ;
1293  cur->p_ave += sc_p_tmp ;
1294  cur->f_t_ave += ((cur->t1 + cur->t2) * sc_tmp) * 0.5 ;
1295 
1296 
1297  old->flags |= FCF_DOUBLE_PAD ;
1298  old->f_charge -= sc_tmp ;
1299  old->p_ave -= sc_p_tmp ;
1300  old->f_t_ave -= ((old->t1 + old->t2) * sc_tmp) * 0.5 ;
1301 
1302 
1303  //LOG(DBG,"Split!") ;
1304 
1305 
1306 
1307  cur++ ; // don't use the new guy again...
1308  merge = 3 ;
1309  break ; // this dumps the old guy, or does it?
1310  }
1311 
1312  cur->flags |= FCF_FALLING ;
1313  }
1314  else {
1315  if(unlikely(cur->scharge < (old->scharge - FCF_MIN_ADC_PAD_C))) {
1316  cur->flags |= FCF_FALLING ;
1317  }
1318  }
1319 
1320  // merge!
1321  merge = 1 ;
1322 
1323  //LOG(DBG,"Typical merge") ;
1324 
1325  // sanity check: the new 1d-clusters can only be
1326  // "fresh" i.e. 1pad wide...
1327  if(unlikely(!(cur->flags & FCF_ONEPAD))) {
1328  LOG(ERR,"Can;t be -- here I can have only ONEPADS!!") ;
1329  }
1330  if(unlikely(!(cur->flags & FCF_IN_DOUBLE))) {
1331  LOG(ERR,"Can't be -- I must be in double here!") ;
1332 
1333  }
1334 
1335 
1336  cur->flags |= old->flags ;
1337  cur->flags &= ~FCF_ONEPAD ;
1338 
1339  if(unlikely(modes)) { // merge annotated stuff
1340  double qua ;
1341 
1342  if(cur->track_id == old->track_id) {
1343  qua = cur->quality * cur->f_charge + old->quality * old->f_charge ;
1344  }
1345  else if(cur->f_charge < old->f_charge) {
1346  cur->track_id = old->track_id ;
1347 
1348  qua = old->quality * old->f_charge ;
1349 
1350  }
1351  else {
1352  qua = cur->quality * cur->f_charge ;
1353  }
1354  if (cur->f_charge + old->f_charge > 0)
1355  qua /= (cur->f_charge + old->f_charge) ;
1356  else qua = 0;
1357  cur->quality = (u_int )qua ;
1358 
1359  // need to know what to do here when we
1360  if(modes & 2) { // local annotation back to track id!
1361  cur->track_id = old->track_id ;
1362  for(int i=0;i<cur->sim_length;i++) {
1363  cur->sim[i].track_id = old->track_id ;
1364  }
1365  }
1366  }
1367 
1368 
1369 
1370  cur->f_charge += old->f_charge ;
1371  cur->f_t_ave += old->f_t_ave ;
1372  cur->p_ave += old->p_ave ;
1373  cur->p1 = old->p1 ;
1374 
1375 
1376  if(cur->t1 > old->t_min) {
1377  cur->t_min = old->t_min ;
1378  }
1379  else {
1380  cur->t_min = cur->t1 ;
1381  }
1382 
1383  if(cur->t2 < old->t_max) {
1384  cur->t_max = old->t_max ;
1385  }
1386  else {
1387  cur->t_max = cur->t2 ;
1388  }
1389 
1390 
1391 
1392  cur++ ; // don't use the new guy again...
1393  break ;
1394  }
1395  } // end of loop over new....
1396 
1397 
1398  //LOG(DBG,"Merge %d:%d = merge %d, t1..t2 %d:%d",r,p,merge,old->t1,old->t2) ;
1399 
1400 
1401  switch(merge) {
1402  case 1 :
1403  // this is a real merge so keep the old guy...
1404  break ;
1405  default :
1406  if(old->flags & FCF_ONEPAD) {
1407  if(merge==3) {
1408  LOG(ERR,"Can;t be!") ;
1409  }
1410  // will dump for onepad
1411  old->p2 = p ;
1412  //old->p1 = 201 ; was in FY11
1413  old->p1 = p ;
1414  dump(old,r) ;
1415  }
1416  else {
1417  // dump OLD!
1418  old->p2 = p ;
1419  dump(old,r) ;
1420  }
1421 
1422  break ;
1423  }
1424 
1425  old++ ;
1426 
1427  } // end of loop over old...
1428 
1429 
1430 
1431  } // loop over pads; until one before the last
1432 
1433  // dump the last pad; p is at row->pad_stop
1434  if(fcf_style) {
1435  old1 = get_working(r,p) ;
1436  }
1437  else {
1438  old1 = get_stage1(r,p) ;
1439  }
1440 
1441  old = old1->cl ;
1442 
1443  //LOG(DBG,"end of row %d: pad %d, leftower count %d",r,p,old1->count) ;
1444  //if(old1->count) {
1445  // LOG(DBG,"Leftover at row %d:%d, %d",r,p,old1->count) ;
1446  //}
1447 
1448  for(c=0;c<old1->count;c++) { // loop over old
1449 
1450  old->p2 = p ;
1451  dump(old,r);
1452 
1453  old++ ;
1454  }
1455 
1456 
1457  // end of row. We either enter the count in the header or go back 1 int...
1458 // LOG(TERR,"[%d] row %d, clusters %d",my_id,r,cur_row_clusters) ;
1459 
1460  if(cur_row_clusters) {
1461  *row_cache = (do_version<<16) | r ;
1462  *clust_count_cache = cur_row_clusters ;
1463  //LOG(DBG,"In row %2d: found %d clusters",r,cur_row_clusters) ;
1464  }
1465  else {
1466  loc_buff -= 2 ; // go back, nothing found!
1467  }
1468 
1469  } // loop over rows...
1470 
1471 // LOG(TERR,"[%d] returning %d",loc_buff-(u_int *)outbuff) ;
1472 
1473  return loc_buff - (u_int *)outbuff ; // return number of ints stored!
1474 }
1475 
1476 
1477 void tpxFCF::dump(tpxFCF_cl *cl, int row)
1478 {
1479  u_int fla = cl->flags ;
1480  u_int tmp_p, tmp_fl ;
1481  u_int pad_c ;
1482  int time_c ; // time_c can go negative due to T0 corrections!
1483  double dp, dt ;
1484  u_int p1, p2 ;
1485  int div_fact ;
1486 
1487 
1488 //LOG(TERR,"[%d] Dump: fl 0x%X: p %d,%d, t %d,%d",my_id,fla,cl->p1,cl->p2,cl->t1,cl->t2) ;
1489 
1490  switch(run_compatibility) {
1491  case 9 : //FY09 // THIS WAS IN RUN09, right or wrong!
1492 
1493  // first set of pre-cuts
1494  if(likely(do_cuts)) {
1495  if(unlikely(fla & FCF_BROKEN_EDGE)) ; // pass hits on row 8 even when dead because of the afterburner!
1496  else if((do_cuts == 1) && (fla & (FCF_ROW_EDGE | FCF_DEAD_EDGE))) return ; // kill clusters touching the edge or a dead pad
1497  }
1498 
1499 
1500  // next we will kill one pad wide clusters but not the ones close to the padplane (MWPC studies)!
1501  if((fla & FCF_ONEPAD) && (cl->t1 < 15)) { // for any hit below the trigger, we pass -- for MWPC studies!
1502  if((cl->t2 - cl->t1)<=1) return ; // I won't pass hits with less than 2 timebins
1503  if(cl->t2 > 30) return ; // too long, noise
1504 
1505 
1506  //LOG(INFO,"dt %.1f: row %d: %d %d %d %d : %d %f 0x%X",dt,cur_row,cl->p1,cl->p2,cl->t1,cl->t2,cl->charge,cl->f_charge,cl->flags) ;
1507  return ; // still
1508  }
1509  else if(likely(do_cuts)) {
1510 
1511  if(fla & FCF_BROKEN_EDGE) { // always pass!
1512  ;
1513  }
1514  else if(fla & FCF_ONEPAD) return ;
1515  else if((cl->t_max - cl->t_min) <= 2) return ; // kill if the cluster length in time is small
1516 
1517  }
1518 
1519 
1520 
1521  //now, I can have ONEPAD hits here:
1522  // 1) because of the low timebin, MWPC studies
1523  // 2) because of row 8 aka BROKEN_EDGE
1524 
1525  if(!(fla & FCF_IN_DOUBLE)) { // the values were not turned to double
1526  if(fla & FCF_ONEPAD) { // this is the only valid case
1527  cl->p1 = cl->p2 ; // adjust the start pad...
1528 
1529 
1530 
1531  // I don't have the gain corrections here yet (in FY09) so I use a 1.0!
1532  cl->f_charge = (float)cl->charge * 1.0 ;
1533  cl->p_ave = cl->p1 * cl->f_charge ;
1534  cl->f_t_ave = (float)cl->t_ave * 1.0 ;
1535 
1536  }
1537  else {
1538  LOG(WARN,"WTF? not double: row %d: %d-%d, %d-%d (%d-%d): charge %d (%.3f): 0x%X",cur_row,cl->p1,cl->p2,cl->t1,cl->t2,cl->t_min,cl->t_max,cl->charge,cl->f_charge,cl->flags) ;
1539  return ;
1540  }
1541  }
1542 
1543  if(cl->f_charge < 1.0) {
1544  if(!(fla & FCF_DEAD_EDGE)) LOG(WARN,"WTF? no charge: row %d: %d-%d, %d-%d (%d-%d): charge %d (%.3f): 0x%X",cur_row,cl->p1,cl->p2,cl->t1,cl->t2,cl->t_min,cl->t_max,cl->charge,cl->f_charge,cl->flags) ;
1545  return ;
1546  }
1547 
1548  break ;
1549  default :
1550  // run 10 ;
1551  if(unlikely(fla & FCF_BROKEN_EDGE)) goto keep ; // always keep
1552 
1553  if(unlikely(do_cuts == 0)) goto keep ; // obviously always keep
1554 
1555  if(likely(do_cuts != 2)) { // junk them unless do_cuts is 2
1556  if(fla & (FCF_DEAD_EDGE | FCF_ROW_EDGE)) return ; // never keep!
1557  }
1558 
1559  if(likely(fla & FCF_IN_DOUBLE)) {
1560  if((cl->t_max - cl->t_min)<=2) return ; // kill if TB width <= 3
1561  if(cl->f_charge < 10.0) return ; // kill small charge
1562  }
1563  else {
1564 
1565  if(likely(fla & FCF_ONEPAD)) ;
1566  else {
1567  LOG(WARN,"WTF? not onebad but not in double!?") ;
1568  }
1569 
1570  if((cl->t2 - cl->t1)<=2) return ;
1571  if(cl->charge < 10) return ;
1572 
1573 
1574  }
1575 
1576  keep:;
1577 
1578  if(likely(fla & FCF_IN_DOUBLE)) ;
1579  else {
1580  struct stage1 ggg, *gain ;
1581 
1582  if(likely(fla & FCF_ONEPAD)) ;
1583  else {
1584  LOG(WARN,"WTF? not onebad but not in double!?") ;
1585  }
1586 
1587 // printf("ONEPAD: %d %d %d %d %d\n",cl->p1,cl->p2,cl->t1,cl->t2,fla) ;
1588 
1589 
1590 
1591  if(fcf_style) {
1592  gain = &ggg ;
1593 
1594  gain->g = get_static(row, cl->p2)->g ;
1595  gain->t0 = get_static(row, cl->p2)->t0 ;
1596 
1597 
1598  }
1599  else {
1600  gain = get_stage1(row, cl->p2) ;
1601  }
1602 
1603  cl->p1 = cl->p2 ;
1604 
1605  cl->f_charge = cl->charge * gain->g ;
1606  // don't need scharge
1607 
1608  cl->f_t_ave = cl->t_ave * gain->g ;
1609  // BUG in FY10!!!
1610  //cl->f_t_ave += gain->g * gain->t0 ;
1611  cl->f_t_ave += cl->f_charge * gain->t0 ;
1612 
1613  cl->p_ave = cl->p2 * cl->f_charge ;
1614 
1615  cl->t_min = cl->t1 ;
1616  cl->t_max = cl->t2 ;
1617 
1618  }
1619 
1620  if(do_cuts==1 && run_compatibility >= 22) { // ADDED in FY22, pp500
1621  // kill ONEDPAD unless they fall before the trigger
1622  if((cl->t_max > 20) && (fla & FCF_ONEPAD)) return ;
1623  }
1624  }
1625 
1626 
1627 
1628  int cha = (int) (cl->f_charge + 0.5) ; // integerized version; 0.5 is for correct roundoff
1629 
1630  // clear the FALLING flag
1631  fla &= (~FCF_FALLING) ;
1632 
1633  dt = cl->f_t_ave / cl->f_charge ;
1634  dp = cl->p_ave / cl->f_charge ;
1635 
1636 
1637  if(do_version == FCF_V_FY08) {
1638  div_fact = 32 ;
1639  }
1640  else {
1641  div_fact = 64 ;
1642  //LOG(DBG,"Using div fact %d",div_fact) ;
1643  }
1644 
1645  // we dump an integerized version ("fixed point")
1646  time_c = (u_int) (dt * div_fact + 0.5) ; // 0.5 for correct roundoff
1647  pad_c = (u_int) (dp * div_fact + 0.5) ;
1648 
1649  // get pad extents
1650  tmp_p = pad_c / div_fact ;
1651 
1652  p1 = tmp_p - cl->p1 ;
1653  p2 = cl->p2 - tmp_p ;
1654 
1655  if(p1 > 7) p1 = 7 ;
1656  if(p2 > 7) p2 = 7 ;
1657 
1658  tmp_fl = (p1 << 8) | (p2 << 11) ;
1659 
1660 
1661  // get timebin extents
1662  tmp_p = time_c / div_fact ;
1663 
1664  p1 = tmp_p - cl->t_min ;
1665  p2 = cl->t_max - tmp_p ;
1666 
1667  if(p1 > 15) p1 = 15 ;
1668  if(p2 > 15) p2 = 15 ;
1669 
1670 
1671  tmp_fl |= (p2 << 4) | p1 ;
1672 
1673 
1674  if(fla & FCF_ONEPAD) time_c |= 0x8000 ;
1675 
1676  if(fla & (FCF_DOUBLE_T | FCF_DOUBLE_PAD)) pad_c |= 0x8000 ;
1677  if(fla & FCF_DEAD_EDGE) pad_c |= 0x4000 ;
1678 
1679  if(fla & FCF_ROW_EDGE) tmp_fl |= 0x8000 ;
1680  if(fla & FCF_BROKEN_EDGE) tmp_fl |= 0x4000 ;
1681 
1682  if(cha > 0x7FFF) cha = 0x8000 | (cha/1024) ;
1683 
1684  // watchout for ordering!
1685  *loc_buff++ = (time_c << 16) | pad_c ;
1686  *loc_buff++ = (cha << 16) | tmp_fl ;
1687 
1688 
1689  if(modes) { // FCF Annotation
1690  *loc_buff++ = (cl->quality << 16) | cl->track_id ;
1691  }
1692 
1693 
1694  cur_row_clusters++ ;
1695 
1696 
1697  return ;
1698 }