StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
fstPed.cxx
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <math.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <time.h>
8 #include <unistd.h>
9 
10 #include <rtsLog.h>
11 #include <daqModes.h>
12 #include <rtsSystems.h>
13 
14 #include <DAQ_READER/daq_dta.h>
15 
16 #include "fgtPed.h" // for some defines
17 #include "fstPed.h"
18 
19 
20 // real time in useconds
21 static u_int t_mark()
22 {
23  timespec ts ;
24 
25  clock_gettime(CLOCK_MONOTONIC,&ts) ;
26 
27  return (u_int)(ts.tv_sec*1000000+ts.tv_nsec/1000) ;
28 }
29 
30 // returns microseconds; good enough
31 static u_int t_delta(u_int mark)
32 {
33  return (unsigned int)((t_mark() - mark)) ;
34 }
35 
36 
37 char fstPed::cmnGroup[24][128] ;
38 
39 
40 
41 
42 int fstPed::load_group(const char *fname)
43 {
44  if(fname==0) fname = "/RTS/conf/fst/cmnGroup.txt" ;
45 
46  memset(cmnGroup,0xFF,sizeof(cmnGroup)) ; // set to -1
47 
48  FILE *f = fopen(fname,"r") ;
49  if(f==0) {
50  LOG(ERR,"Group file %s [%s]",fname,strerror(errno)) ;
51  return -1 ;
52  }
53 
54  while(!feof(f)) {
55  char buff[32] ;
56  int apv, ch, grp ;
57 
58  if(fgets(buff,sizeof(buff),f)==0) continue ;
59 
60  int ret = sscanf(buff,"%d %d %d",&apv,&ch,&grp) ;
61  if(ret != 3) continue ;
62 
63  cmnGroup[apv][ch] = grp ; // is negative if it doesn't exist!
64  }
65  fclose(f) ;
66 
67 // for(int i=0;i<24;i++) {
68 // LOG(TERR,"cmnGroup: APV %d, ch 0: %d",i,cmnGroup[i][0]) ;
69 // }
70 
71  LOG(INFO,"cmnGroup %s loaded.",fname) ;
72 
73  return 0 ;
74 
75 
76 }
77 
78 fstPed::fstPed(int rts)
79 {
80  valid = 0 ;
81  rb_mask = 0 ;
82 
83  memset(fgt_stat,0,sizeof(fgt_stat)) ;
84 
85 
86  k_seq = 0 ;
87  n_sigma = 0.0 ;
88 
89 
90  tb_cou_xpect = -1 ;
91  tb_cou_ped = -1 ;
92 
93  memset(ch_status,0,sizeof(ch_status)) ;
94 
95  evts_for_rms = 500 ;
96  evts_for_cmn = 500 ;
97 
98  for(int r=0;r<6;r++) {
99  for(int ar=0;ar<6;ar++) {
100  for(int ap=0;ap<24;ap++) {
101  for(int c=0;c<128;c++) {
102  ch_status[r][ar][ap][c] = FGT_CH_STAT_SHOULD ;
103  }}}
104 
105  }
106  rb_mask = 0x3F ; // this will depend
107 
108  for(int t=0;t<8;t++) { // for 8 threads!
109  fgt_rdr[t] = new daq_fgt(0) ;
110  }
111 
112  // reasomable defaults
113  nSigmaCut = 3.0 ;
114 
115  nPedsCut1 = 3.5 ;
116  nPedsTbs1 = 1 ;
117 
118  nPedsCut2 = 2.5 ;
119  nPedsTbs2 = 2 ;
120 
121  nSeedsCut = 4.0 ;
122  nSeedsTbs = 2 ;
123 
124  return ;
125 }
126 
127 
128 
129 int fstPed::run_stop()
130 {
131  for(int r=0;r<FGT_RDO_COU;r++) {
132  if(rb_mask & (1<<r)) ;
133  else continue ;
134 
135  int evts = fgt_stat[r].evts ;
136 
137  if(fgt_stat[r].err) {
138  LOG(WARN,"RDO %d: %d errors in %d events [but this is questionable]",r+1,fgt_stat[r].err,evts) ;
139  }
140 
141  for(int arm=0;arm<FGT_ARM_COU;arm++) {
142  if(fgt_stat[r].arm_mask & (1<<arm)) ;
143  else continue ;
144 
145  for(int apv=0;apv<FGT_APV_COU;apv++) {
146  int errs = fgt_stat[r].err_apv[arm][apv] ;
147  int cou = fgt_stat[r].cou_apv[arm][apv] ;
148 
149  if(errs || (cou && (cou!=evts))) {
150  LOG(ERR,"RDO %d: ARM %d, APV %2d: %d errors, in %d/%d events",
151  r+1,arm,apv,errs,cou,evts) ;
152  }
153  }
154  }
155  }
156 
157  return 0 ;
158 }
159 
160 
161 void fstPed::init(int active_rbs)
162 {
163  memset(fgt_stat,0,sizeof(fgt_stat)) ;
164 
165  rb_mask = active_rbs ;
166 
167 }
168 
169 
170 int fstPed::do_zs(char *src, int in_bytes, char *dst, int rdo1, int id)
171 {
172 // int ks = k_seq ;
173  int dumped_cou = 0 ;
174 // int all_cou = 0 ;
175 
176  u_int mark = t_mark() ;
177 
178  short *d16 = (short *) dst ;
179  u_int *d32 = (u_int *)dst ;
180 
181  fgt_stat[rdo1-1].evts++ ;
182 // int evt = fgt_stat[rdo1-1].evts ;
183 
184  daq_dta *dd = fgt_rdr[id]->handle_adc(sector, rdo1, src) ;
185 
186 
187  // create meta
188  apv_meta_zs_t meta_zs ;
189  apv_meta_t *meta = (apv_meta_t *) dd->meta ;
190 
191  memset(&meta_zs,0,sizeof(meta_zs)) ;
192 
193  int t_xpect = tb_cou_ped ;
194 
195  int max_tb = -1 ;
196 
197  total_charge = 0 ;
198 
199  for(int arm=0;arm<FST_ARM_COU;arm++) {
200  for(int apv=0;apv<FGT_APV_COU;apv++) {
201  if(meta->arc[rdo1].arm[arm].apv[apv].present) {
202  int err = 0 ;
203 
204  meta_zs.status[arm][apv] |= 1 ;
205 
206  int t_cou = meta->arc[rdo1].arm[arm].apv[apv].ntim ;
207 
208  if(t_cou != t_xpect) {
209  if(fgt_stat[rdo1-1].err < 12) {
210  LOG(WARN,"wrong tb_cou %d(expect %d): ARC %d, ARM %d, APV %d",t_cou,t_xpect,rdo1,arm,apv) ;
211  }
212  fgt_stat[rdo1-1].err++ ;
213  err |= 2 ;
214  }
215 
216  if(t_cou > max_tb) max_tb = t_cou ;
217 
218 
219  if(err) {
220  meta_zs.status[arm][apv] |= err ;
221  }
222  }
223 
224  if(meta->arc[rdo1].arm[arm].apv[apv].error || meta->arc[rdo1].arm[arm].error) {
225  meta_zs.status[arm][apv] |= 4 ; // error ;
226  }
227 
228  if(meta_zs.status[arm][apv] & 1) {
229  fgt_stat[rdo1-1].cou_apv[arm][apv]++ ;
230  }
231 
232  if(meta_zs.status[arm][apv] & 0xFE) {
233  fgt_stat[rdo1-1].err_apv[arm][apv]++ ;
234  }
235 
236  switch(meta_zs.status[arm][apv]) {
237  case 0 : // not present
238  case 1 : // present
239  case 3 : // present but wrong tb
240  break ;
241  default :
242  if(fgt_stat[rdo1-1].err < 100) {
243  LOG(ERR,"ARC %d, ARM %d, APV %d: meta_zs 0x%X",rdo1,arm,apv,meta_zs.status[arm][apv]) ;
244  }
245  fgt_stat[rdo1-1].err++ ;
246  break ;
247  }
248 
249  }}
250 
251  // cut data!
252  if(max_tb > tb_cou_ped) max_tb = tb_cou_ped ; // FORCED!
253 
254  meta_zs.tb_cou = max_tb ;
255 
256  // roundoff to a 16 bit word...
257  int meta_bytes = sizeof(meta_zs) ;
258  while(meta_bytes % 2) meta_bytes++ ;
259 
260  *d32++ = 0xFEEDBEEF ; // signature
261 
262 // int do_ped_sub = 0 ; // non ped-sub
263 
264 // do_ped_sub = 1 ;
265  *d32++ = META_PED_ZS_VERSION ; // zs _AND_ ped subtracted
266 
267  u_int *dta_bytes = d32++ ; // reserve space
268  *d32++ = meta_bytes ;
269 
270  memcpy(d32,&meta_zs,meta_bytes) ;
271  d16 = (short *)d32 + meta_bytes/2 ;
272 
273  while(dd && dd->iterate()) {
274  int arc, arm, apv ;
275 
276  arc = dd->rdo ;
277  arm = dd->sec ;
278  apv = dd->pad ;
279 
280 // printf("**** ARC %d, ARM %d, APV %d: entries %d\n",
281 // arc,arm,apv,dd->ncontent) ;
282 
283  fgt_adc_t *f = (fgt_adc_t *) dd->Void ;
284 
285  struct peds_t *p = &(peds[arc-1]) ;
286 
287 // int i_save = -1 ;
288 // int cou = 0 ;
289 // int dump = 0 ;
290 // int thr = 0 ;
291 // int ch = -1 ;
292 // int cou_tb = 0 ;
293 
294  *d16++ = 0xAB00 | arc ;
295  *d16++ = (arm << 8) | apv ;
296 
297 
298  struct grp_t {
299  double mean ;
300  int cou ;
301  } grp[4][9] ;
302 
303  memset(grp,0,sizeof(grp)) ;
304  int bad_group = 0 ;
305 
306  u_short dta[128][9] ; // cache
307 
308 
309  //u_int mark = t_mark() ;
310 
311  // first pass, accumulate for the CMN
312  for(u_int i=0;i<dd->ncontent;i++) {
313  int ch = f[i].ch ;
314 
315  int g = cmnGroup[apv][ch] ;
316  if(g<0) continue ;
317 
318 
319  int tb = f[i].tb ;
320 
321  // if the timebin of the data is larger than the timebin of
322  // the available pedestals/thresholds -- silently drop!!!
323 
324  if(tb >= max_tb) continue ;
325 
326  int adc = f[i].adc ;
327 
328 
329 
330  double mean = p->ped[arm][apv][ch][tb] ;
331  double rms = p->rms[arm][apv][ch][tb] ;
332 
333 
334 // printf(" ch %d, tb %d: mean %f, rms %f: adc = %d\n",ch,tb,mean,rms,adc) ;
335 
336  dta[ch][tb] = adc ;
337 
338  if(adc < (mean+nSigmaCut*rms)) {
339  grp[g][tb].mean += adc - mean ;
340  grp[g][tb].cou++ ;
341  }
342 
343  }
344 
345  //mark = t_delta(mark) ;
346  //printf("pass1 %u\n",mark) ;
347  //mark = t_mark() ;
348 
349  // second pass: calculate CMN
350  for(int g=0;g<4;g++) {
351  for(int tb=0;tb<9;tb++) {
352  if(grp[g][tb].cou) grp[g][tb].mean /= grp[g][tb].cou ;
353  else {
354  bad_group ++ ; // and now what????
355  grp[g][tb].mean = 10000000.0 ;
356  }
357  }}
358 
359  //mark = t_delta(mark) ;
360  //printf("pass2 %u\n",mark) ;
361  //mark = t_mark() ;
362 
363  // 3rd pass do the hits pass
364  for(int ch=0;ch<128;ch++) {
365  int g = cmnGroup[apv][ch] ;
366  if(g<0) continue ;
367 
368  int tb_cou[3] ;
369  double d[9] ;
370 
371  tb_cou[0] = tb_cou[1] = tb_cou[2] = 0 ;
372 
373  int t_cou = 0 ;
374  int pass = 0 ;
375 
376  for(int tb=0;tb<9;tb++) {
377  if(tb>=max_tb) continue ;
378 
379  if(grp[g][tb].mean > 10000.0) {
380  pass |= 8 ;
381  break ;
382  }
383  }
384 
385  for(int tb=0;tb<9;tb++) {
386  double dd ;
387 
388  if(tb >= max_tb) continue ;
389 
390  t_cou++ ;
391 
392  double cmn_mean = grp[g][tb].mean ;
393  double mean = p->ped[arm][apv][ch][tb] ;
394  double cmn_rms = p->cmn_rms[arm][apv][ch][tb] ;
395 
396  if(pass) { // NOTE: special ERROR case!!!
397  dd = dta[ch][tb] - mean ;
398  }
399  else {
400  dd = dta[ch][tb] - mean - cmn_mean ;
401  }
402 
403 
404  if(dd > nSeedsCut*cmn_rms) tb_cou[0]++ ;
405  if(dd > nPedsCut1*cmn_rms) tb_cou[1]++ ;
406  if(dd > nPedsCut2*cmn_rms) tb_cou[2]++ ;
407 
408  d[tb] = dd ;
409  }
410 
411 
412  if(tb_cou[0]>=nSeedsTbs) pass |= 1 ;
413  if(tb_cou[1]>=nPedsTbs1) pass |= 2 ;
414  if(tb_cou[2]>=nPedsTbs2) pass |= 4 ;
415 
416  // dump out
417  if(pass) {
418  *d16++ = (t_cou<<8)|ch ;
419  dumped_cou++ ;
420 
421  for(int tb=0;tb<t_cou;tb++) {
422  int id ;
423 
424  if(d[tb]<0) id = 0 ;
425  else id = ((int)(d[tb]+0.5))&0xFFF ; // roundoff ;
426 
427  *d16++ = (pass<<12)|id ;
428  }
429  }
430  }
431 
432  //mark = t_delta(mark) ;
433  //printf("pass3 %u\n",mark) ;
434  //mark = t_mark() ;
435 
436 // if(bad_group >10) { // this happens often!
437 // LOG(WARN,"%d: EVT %d: ARM %d, APV %d: %d bad CMN",rdo1,evt,arm,apv,bad_group) ;
438 // }
439  }
440 
441 
442 
443  *d16++ = dumped_cou ;
444 
445 
446  int out_bytes = (char *)d16 - (char *)dst ;
447 
448  *dta_bytes = out_bytes ;
449 
450  // make sure we are on a 32bit boundary!
451  while(out_bytes % 4) {
452  *d16++ = 0xBABA ;
453  out_bytes += 2 ;
454  }
455 
456  //LOG(TERR,"ARC %d: dumped %d/%d, %d bytes",rdo1,dumped_cou,all_cou,out_bytes) ;
457 
458 // printf("RDO: %d us\n",t_delta(mark)) ;
459 
460  return out_bytes ;
461 }
462 
463 
464 /*
465  Called per event, per RDO. evbbuff is the raw RDO contribuition.
466  rdo counts from 1.
467 */
468 void fstPed::accum(char *evbuff, int bytes, int rdo1)
469 {
470  int do_cmn = 0 ;
471  int rdo = rdo1 - 1 ; // since rdo1 is from 1
472 
473 
474 
475  fgt_stat[rdo].evts++ ;
476 
477  int evt = fgt_stat[rdo].evts ;
478 
479  if(fgt_stat[rdo].evts < evts_for_rms) do_cmn = 0 ;
480  else if(fgt_stat[rdo].evts==evts_for_rms) do_cmn = 1 ; // CALC
481  else do_cmn = 2 ;
482 
483  // skip first few events!
484 // if(fgt_stat[rdo].evts <= 3) {
485 // return ;
486 // }
487 
488  if(fgt_stat[rdo].evts > 0xFF00) return ; // don't allow more than 16bits worth...
489 
490  struct peds_t *p = peds + rdo ;
491 
492  daq_dta *dd = 0 ;
493  dd = fgt_rdr[rdo1-1]->handle_adc(sector,rdo1, evbuff) ;
494 
495 
496  int t_xpect = tb_cou_xpect ;
497 
498  char need[FST_ARM_COU][FGT_APV_COU] ;
499  memset(need,0,sizeof(need)) ;
500 
501  if(dd && dd->meta) {
502  apv_meta_t *meta = (apv_meta_t *)dd->meta ;
503 
504  for(int arm=0;arm<FST_ARM_COU;arm++) {
505  for(int apv=0;apv<FGT_APV_COU;apv++) {
506  if(meta->arc[rdo1].arm[arm].apv[apv].present == 0) continue ;
507 
508  if(meta->arc[rdo1].arm[arm].apv[apv].ntim != t_xpect) {
509  if(fgt_stat[rdo1-1].err <= 10) {
510  LOG(WARN,"evt %d: RDO %d, ARM %d, APV %d: ntim %d, expect %d??",fgt_stat[rdo].evts,rdo1,arm,apv,meta->arc[rdo1].arm[arm].apv[apv].ntim,t_xpect) ;
511  if(fgt_stat[rdo1-1].err==10) {
512  LOG(WARN,"evt %d: RDO %d: NO more warnings",fgt_stat[rdo].evts,rdo1) ;
513  }
514  }
515  fgt_stat[rdo1-1].err++ ;
516  }
517 
518  need[arm][apv] |= 1 ;
519 
520  if(meta->arc[rdo1].arm[arm].apv[apv].apv_id != apv) {
521  LOG(ERR,"RDO %d, ARM %d, APV %d: %d",rdo1,arm,apv,meta->arc[rdo1].arm[arm].apv[apv].apv_id) ;
522  need[arm][apv] |= 2 ; // error
523  }
524 
525 
526  }
527  }
528  }
529 
530  if(do_cmn==1) {
531  LOG(INFO,"%d: calculating pedestals at event %d",rdo1,fgt_stat[rdo].evts) ;
532  }
533 
534  struct fst_grp_t {
535  double mean ;
536  int cou ;
537  } fst_grp[4][9] ;
538 
539  u_short grp_dta[128][9] ;
540 
541  memset(fst_grp,0,sizeof(fst_grp)) ;
542 
543  int good_cmn = 0 ;
544 
545  while(dd && dd->iterate()) {
546  if(dd->rdo != rdo1) continue ;
547 
548  int arm = dd->sec ;
549  int apv = dd->pad ;
550 
551  fgt_adc_t *f = (fgt_adc_t *) dd->Void ;
552 
553  need[arm][apv] |= 4 ;
554 
555  //if(do_cmn==2) {
556  // LOG(TERR,"%d: evt %d: cmd1: arm %d, apv %d",rdo1,evt,arm,apv) ;
557  //}
558 
559 
560  int for_cmn = 0 ;
561 
562  if(do_cmn==2) memset(fst_grp,0,sizeof(fst_grp)) ;
563 
564  for(u_int i=0;i<dd->ncontent;i++) {
565  int adc ;
566  int ch ;
567  int tb ;
568 
569  ch = f[i].ch ;
570  adc = f[i].adc ;
571  tb = f[i].tb ;
572 
573 
574  if(do_cmn==0) {
575  p->ped[arm][apv][ch][tb] += adc ;
576  p->rms[arm][apv][ch][tb] += (adc * adc) ;
577  p->cou[arm][apv][ch][tb]++ ;
578 
579  //if(arm==0 && apv==0 && ch==0 && tb==0) {
580  // LOG(TERR,"do_cmn=0 %d",adc) ;
581  //}
582 
583  }
584  else if(do_cmn==1) {
585  int cou = p->cou[arm][apv][ch][tb] ;
586  double mean, rms ;
587 
588  if(cou==0) {
589  mean = -1.0 ;
590  rms = 0.0 ;
591  }
592  else {
593  mean = p->ped[arm][apv][ch][tb] / cou ;
594  rms = p->rms[arm][apv][ch][tb] / cou ;
595 
596  rms = sqrt(rms-mean*mean) ;
597  }
598 
599  p->ped[arm][apv][ch][tb] = mean ;
600  p->rms[arm][apv][ch][tb] = rms ;
601 
602  //if(arm==0 && apv==0 && ch==0 && tb==0) { // executes twice!!!
603  // LOG(TERR," PED mean %f, rms %f",mean,rms) ;
604  //}
605 
606 
607  //printf("%d %d %d %d %d = %f %f\n",rdo1,arm,apv,ch,tb,mean,rms) ;
608 
609  p->cou[arm][apv][ch][tb] = 0 ; // restart for next step
610  }
611  else {
612  int g = cmnGroup[apv][ch] ;
613  if(g<0) continue ;
614 
615  double mean = p->ped[arm][apv][ch][tb] ;
616  double rms = p->rms[arm][apv][ch][tb] ;
617 
618  grp_dta[ch][tb] = adc ; // cache data so we don't need to pass again
619 
620  //printf("%d %d %d %d %d = %f %f; %d\n",rdo1,arm,apv,ch,tb,mean,rms,adc) ;
621 
622  if(mean<0.0) continue ;
623 
624  if(adc < (mean+nSigmaCut*rms)) {
625  for_cmn++ ;
626  fst_grp[g][tb].mean += adc - mean ;
627  fst_grp[g][tb].cou++ ;
628  }
629 
630  }
631 
632 
633  }
634 
635  if(do_cmn==2) {
636  if(for_cmn < 10) LOG(WARN,"%d: evt %d: ARM %d, APV %d: for cmn %d",rdo1,evt,arm,apv,for_cmn) ;
637 
638  //int good = 0 ;
639 
640  for(int g=0;g<4;g++) {
641  for(int tb=0;tb<9;tb++) {
642  if(fst_grp[g][tb].cou) fst_grp[g][tb].mean /= fst_grp[g][tb].cou ;
643  else {
644  //LOG(WARN,"%d: evt %d: ARM %d, APV %d, cmn_group %d, tb %d not there?",rdo1,evt,arm,apv,g,tb) ;
645  fst_grp[g][tb].mean = 1000000.0 ;
646  }
647  }}
648 
649  for(int ch=0;ch<128;ch++) {
650  int g = cmnGroup[apv][ch] ;
651 
652  if(g<0) continue ;
653 
654  for(int tb=0;tb<9;tb++) {
655  int d = grp_dta[ch][tb] ;
656 
657  double g_mean = fst_grp[g][tb].mean ;
658 
659  if(g_mean > 1024) continue ;
660 
661  double mean = p->ped[arm][apv][ch][tb] ;
662  double rms = p->rms[arm][apv][ch][tb] ;
663 
664  if(mean<0.0) continue ;
665 
666  //if(arm==0 && apv==0 && ch==0 && tb==0) {
667  // LOG(TERR," mean %f, rms %f, g_mean %f: adc %d",mean,rms,g_mean,d) ;
668  //}
669 
670  if(d < (mean+nSigmaCut*rms)) {
671  p->cmn_ped[arm][apv][ch][tb] += d-mean-g_mean ;
672  p->cmn_rms[arm][apv][ch][tb] += (d-mean-g_mean)*(d-mean-g_mean) ;
673  p->cou[arm][apv][ch][tb]++ ;
674  good_cmn++ ;
675  }
676  }
677  }
678 
679  //if(good < 10) LOG(WARN,"%d: EVT %d: ARM %d, APV %d: good CMN %d",rdo1,evt,arm,apv,good) ;
680  }
681 
682  }
683 
684  if(do_cmn==2 && good_cmn<40000) LOG(WARN,"%d: evt %d: good_cmn %d",rdo1,evt,good_cmn) ;
685 
686  // the following is just an error dump...
687  for(int arm=0;arm<FST_ARM_COU;arm++) {
688  for(int apv=0;apv<FGT_APV_COU;apv++) {
689  if(need[arm][apv] == 0) continue ;
690 
691  switch(need[arm][apv]) {
692  case 1 : // missing in data; will capture the error later
693  case 5 : // all OK
694  break ;
695  default :
696  LOG(ERR,"ARC %d, ARM %d, APV %d: need is 0x%X",rdo1,arm,apv,need[arm][apv]) ;
697  }
698 
699  }
700  }
701 
702 
703  return ;
704 
705 }
706 
707 
708 
709 double fstPed::do_thresh(double ns, int k, int do_log)
710 {
711  // suspect
712  // tb_cou set in from_cache
713 
714 
715 
716  n_sigma = ns ;
717  k_seq = k ;
718 
719 
720  LOG(INFO,"do_thresh: n-sigma %f, k-seq %d",n_sigma, k_seq) ;
721 
722 
723  for(int r=0;r<FGT_RDO_COU;r++) {
724  struct peds_t *p = peds + r ;
725 
726  for(int arm=0;arm<FST_ARM_COU;arm++) {
727  for(int apv=0;apv<FGT_APV_COU;apv++) {
728  for(int c=0;c<FGT_CH_COU;c++) {
729 
730  if(ch_status[r][arm][apv][c] & FGT_CH_STAT_SHOULD) ;
731  else continue ;
732 
733 
734  double ped = 0.0 ;
735  double rms = 0.0 ;
736  int cou = 0 ;
737 
738  for(int t=0;t<tb_cou_ped;t++) {
739  double pp = p->ped[arm][apv][c][t] ;
740  double rm = p->rms[arm][apv][c][t] ;
741 
742  if(rm < 0.0) continue ; // should be here but not found in data, damn...
743 
744  ped += pp ;
745  rms += rm ;
746  cou++ ;
747  }
748 
749  if(cou == 0) { // channel should have been present but it wasn't in the pedestal file...
751  continue ;
752  }
753 
754  ped /= cou ;
755  rms /= cou ;
756 
758 
759  }
760  }
761  }
762  }
763 
764  // kill bad
765  int b_all_all = 0 ;
766  int b_bad_all = 0 ;
767 
768  for(int r=0;r<FGT_RDO_COU;r++) {
769 // struct peds_t *p = peds + r ;
770 
771  if(rb_mask & (1<<r)) ;
772  else continue ;
773 
774  int b_ped_0 = 0 ;
775  int b_bad = 0 ;
776  int b_masked = 0 ;
777  int b_misconfigured = 0 ;
778  int b_all = 0 ;
779  int b_unknown = 0 ;
780 
781  int err = 0 ;
782 
783  for(int arm=0;arm<3;arm++) {
784  for(int apv=0;apv<FGT_APV_COU;apv++) {
785  for(int c=0;c<FGT_CH_COU;c++) {
786  if(ch_status[r][arm][apv][c] & FGT_CH_STAT_SHOULD) ;
787  else {
789  continue ;
790  }
791 
792 // if(cmnGroup[apv][c]<0) continue ;
793 
794  b_all++ ;
795 
796  // kill any channel marked odd!
797  if(ch_status[r][arm][apv][c] & 0xFE) {
799  b_bad_all++ ;
800  }
806 
807  if(ch_status[r][arm][apv][c] & FGT_CH_STAT_NO_CONFIG) {
808  b_masked++ ;
809  }
810  if(ch_status[r][arm][apv][c] & FGT_CH_STAT_NO_RESPONSE) {
811  b_misconfigured++ ;
812  err = 1 ;
813  }
814  if(ch_status[r][arm][apv][c] & FGT_CH_STAT_BAD) {
815  b_bad++ ;
816  err = 1 ;
817  }
818  if(ch_status[r][arm][apv][c] & FGT_CH_STAT_PED_UNKNOWN) {
819  b_ped_0++ ;
820  err = 1 ;
821  }
822 
823 
824 
825  }}}
826 
827  b_all_all += b_all ;
828 
829  if(err) {
830  LOG(WARN,"ARC %d: masked %d, misconfigd %d, bad %d, bad ped %d, unknown %d of %d all",
831  r+1,b_masked,b_misconfigured,b_bad,b_ped_0,b_unknown,b_all) ;
832 
833  }
834  else {
835  LOG(WARN,"ARC %d: masked %d, misconfigd %d, bad %d, bad ped %d, unknown %d of %d all",
836  r+1,b_masked,b_misconfigured,b_bad,b_ped_0,b_unknown,b_all) ;
837  }
838 
839  }
840 
841  double perc = (double)b_bad_all/(double)b_all_all ;
842  perc *= 100.0 ;
843 
844  return perc ;
845 
846 }
847 
848 void fstPed::calc()
849 {
850 
851  const int MIN_EVENTS = 1000 ;
852 
853 
854  LOG(NOTE,"Calculating pedestals") ;
855 
856  tb_cou_ped = -1 ;
857 
858  int bad = 0 ;
859 
860 
861 
862  for(int r=0;r<FGT_RDO_COU;r++) {
863  if(rb_mask & (1<<r)) ;
864  else continue ;
865 
866 
867 
868  struct peds_t *ped = peds + r ;
869 
870  for(int arm=0;arm<FST_ARM_COU;arm++) {
871  for(int apv=0;apv<FGT_APV_COU;apv++) {
872  for(int ch=0;ch<FGT_CH_COU;ch++) {
873 
874 
875 
876  for(int t=0;t<tb_cou_xpect;t++) {
877  int cou = ped->cou[arm][apv][ch][t] ;
878 
879  if(cou == 0) { // never seen in the data!
880  ped->cmn_ped[arm][apv][ch][t] = -1.0 ;
881  ped->cmn_rms[arm][apv][ch][t] = 0 ;
882  }
883  else {
884  double pp, rr ;
885 
886 
887  pp = ped->cmn_ped[arm][apv][ch][t] / cou ;
888  rr = ped->cmn_rms[arm][apv][ch][t] / cou ;
889 
890 
891  // due to roundoff I can have super small negative numbers
892  if(rr < (pp*pp)) rr = 0.0 ;
893  else rr = sqrt(rr - pp*pp) ;
894 
895  ped->cmn_ped[arm][apv][ch][t] = pp ;
896  ped->cmn_rms[arm][apv][ch][t] = rr ;
897 
898  if(t > tb_cou_ped) tb_cou_ped = t ;
899 
900 // LOG(TERR,"RDO %d, ARM %d, APV %d, CH %d, TB %d: %f +- %f, cou %d",
901 // r,arm,apv,ch,t,pp,rr,ped->cou[arm][apv][ch][t]) ;
902  }
903  }
904  }
905 
906  }
907  }
908  }
909 
910  tb_cou_ped++ ; // need to increment...
911 
912 
913  int not_enough = 0 ;
914  for(int r=0;r<FGT_RDO_COU;r++) {
915  if(rb_mask & (1<<r)) ;
916  else continue ;
917 
918  if(fgt_stat[r].evts < MIN_EVENTS) {
919  not_enough = 1 ;
920  }
921  }
922 
923 
924 
925  LOG(TERR,"Pedestals calculated. tb_count %d, RDO counts: %u",tb_cou_ped,fgt_stat[0].evts) ;
926  valid = 1 ; // assume all OK...
927 
928  if(not_enough) valid = 0 ;
929 
930 
931  if(!valid) {
932  LOG(ERR,"FGT pedestals not good: APVs bad %d, events %d",bad,fgt_stat[0].evts) ;
933  }
934 
935  return ;
936 }
937 
938 
939 int fstPed::to_evb(char *buff)
940 {
941  int r, arm, apv, c, t ;
942  u_short *dta = (u_short *) buff ;
943 
944 
945  if(!valid) {
946  // log error but continue...
947  LOG(ERR,"ped::to_evb peds are bad: valid %d",valid) ;
948  }
949 
950  LOG(NOTE,"Preparing pedestals for later EVB...") ;
951 
952  *dta++ = 0xBEEF ; // signature
953  *dta++ = 0x0002 ; // version: 2 for FST!
954  *dta++ = FGT_ARM_COU ; // ARM
955  *dta++ = FGT_APV_COU ;
956  *dta++ = FGT_CH_COU ; // channel count
957  *dta++ = tb_cou_ped ; // timebin count
958 
959 
960  for(r=0;r<FGT_RDO_COU;r++) {
961  if(rb_mask && (1<<r)) ;
962  else continue ;
963 
964  struct peds_t *ped = peds + r ;
965 
966  *dta++ = r+1 ; // ARC, from 1
967  u_short *apv_cou = dta++ ;
968  *apv_cou = 0 ;
969 
970  // need to dump the apv_meta_zs_t bank!!!
971 
972  for(arm=0;arm<FST_ARM_COU;arm++) {
973  for(apv=0;apv<FGT_APV_COU;apv++) {
974 
975  if(cmnGroup[apv][0]<0) continue ;
976 
977  *dta++ = arm ;
978  *dta++ = apv ;
979  (*apv_cou)++ ;
980 
981  for(c=0;c<FGT_CH_COU;c++) {
982  for(t=0;t<tb_cou_ped;t++) {
983 
984  u_short pp ;
985 
986  pp = (u_short)(ped->ped[arm][apv][c][t]*16.0 + 0.5) ;
987  *dta++ = pp;
988 
989  pp = (u_short)(ped->rms[arm][apv][c][t]*16.0 + 0.5) ;
990  *dta++ = pp ;
991 
992  pp = (u_short)(ped->cmn_rms[arm][apv][c][t]*16.0 + 0.5) ;
993  *dta++ = pp ;
994 
995  }
996  }
997  }
998  }
999 
1000  }
1001 
1002  LOG(TERR,"Pedestals prepared for later EVB, %d bytes",(char *)dta-buff) ;
1003 
1004  return ((char *)dta-buff) ;
1005 }
1006 
1007 void fstPed::clear()
1008 {
1009  memset(peds,0,sizeof(peds)) ;
1010 }
1011 
1012 void fstPed::clear_from_cache()
1013 {
1014  return ;
1015 #if 0
1016  for(int r=0;r<FGT_RDO_COU;r++) {
1017  struct peds_t *p = peds_from_cache + r ;
1018 
1019  for(int arm=0;arm<FST_ARM_COU;arm++) {
1020  for(int apv=0;apv<FGT_APV_COU;apv++) {
1021  for(int c=0;c<FGT_CH_COU;c++) {
1022  for(int t=0;t<FST_TB_COU;t++) {
1023  p->ped[arm][apv][c][t] = 0.0 ;
1024  p->rms[arm][apv][c][t] = -2.0 ;
1025  p->cmn_rms[arm][apv][c][t] = -2.0 ;
1026  p->cou[arm][apv][c][t] = 0 ;
1027  }
1029  }
1030  }
1031  }
1032  }
1033 
1034 #endif
1035 
1036 }
1037 
1038 int fstPed::from_cache(char *fname)
1039 {
1040  FILE *f ;
1041  const char *fn ;
1042  char file[64] ;
1043 
1044  tb_cou_ped = - 1;
1045 
1046  clear() ;
1047  clear_from_cache() ;
1048 
1049 
1050  if(fname) {
1051  fn = fname ;
1052  }
1053  else {
1054  sprintf(file,"/RTScache/fst_s%d_pedestals.txt",sector) ;
1055  fn = file ;
1056  }
1057 
1058  f = fopen(fn,"r") ;
1059  if(f==0) {
1060  LOG(U_TONKO,"ped::from_cache can't open input file \"%s\" [%s]",fn,strerror(errno)) ;
1061  return -1 ;
1062  }
1063 
1064 
1065  LOG(INFO,"Loading pedestals from cache \"%s\"...",fn) ;
1066 
1067 
1068 
1069  while(!feof(f)) {
1070  int r, arm, apv, ch, tb ;
1071  float pp, rr, cmn_rms ;
1072  char buff[256] ;
1073 
1074  if(fgets(buff,sizeof(buff),f) == 0) continue ;
1075 
1076  switch(buff[0]) {
1077  case '#' :
1078  case '!' :
1079  case '*' :
1080  case '/' :
1081  case '.' :
1082  continue ;
1083  }
1084 
1085 
1086  int ret = sscanf(buff,"%d %d %d %d %d %f %f %f",&r,&arm,&apv,&ch,&tb,&pp,&rr,&cmn_rms) ;
1087  if(ret != 8) continue ;
1088 
1089 
1090  struct peds_t *ped = peds + (r-1) ;
1091 
1092  ped->ped[arm][apv][ch][tb] = pp ;
1093  ped->rms[arm][apv][ch][tb] = rr ;
1094  ped->cmn_rms[arm][apv][ch][tb] = cmn_rms ;
1095 #if 0
1096  struct peds_t *ped_fc = peds_from_cache + (r-1) ;
1097 
1098  ped_fc->ped[arm][apv][ch][tb] = pp ;
1099  ped_fc->rms[arm][apv][ch][tb] = rr ;
1100  ped_fc->cmn_rms[arm][apv][ch][tb] = cmn_rms ;
1101 #endif
1102  if(tb > tb_cou_ped) {
1103  tb_cou_ped = tb ;
1104  }
1105 
1106 
1107  if(tb==0) {
1108  if(pp<=0.0 || rr<=0.0) {
1109  ch_status[r-1][arm][apv][ch] |= FGT_CH_STAT_PED_UNKNOWN ;
1110  }
1111  }
1112  }
1113 
1114  fclose(f) ;
1115 
1116  tb_cou_ped++ ; // to get to the ntimbins
1117 
1118  if(tb_cou_ped != tb_cou_xpect) {
1119  LOG(ERR,"Pedestals loaded from cache \"%s\" but have %d timebins != expect %d!",fn,
1120  tb_cou_ped,tb_cou_xpect) ;
1121  }
1122  else {
1123  LOG(INFO,"Pedestals loaded from cache \"%s\", %d timebins OK",fn,tb_cou_ped) ;
1124  }
1125 
1126  valid = 1 ;
1127 
1128  return valid ;
1129 }
1130 
1131 int fstPed::to_cache(char *fname, u_int run, int dont_cache)
1132 {
1133  FILE *f ;
1134  char f_fname[128] ;
1135 
1136  int bad = 0 ;
1137  for(int r=0;r<FGT_RDO_COU;r++) {
1138  if(rb_mask & (1<<r)) ;
1139  else continue ;
1140 
1141 
1142  if(fgt_stat[r].evts < 1000) {
1143  LOG(ERR,"%d: not enough events %d",r+1,fgt_stat[r].evts) ;
1144  bad = 1 ;
1145  }
1146  }
1147 
1148  if(bad || dont_cache || !valid) bad = 1 ;
1149 
1150  if(bad) {
1151  LOG(ERR,"ped::to_cache peds are bad: valid %d %d %d-- caching anyway...",bad,dont_cache,valid) ;
1152  //LOG(CAUTION,"Pedestals are not valid -- not caching!") ;
1153  }
1154 
1155  if(fname) {
1156  strcpy(f_fname,fname) ;
1157  }
1158  else {
1159  sprintf(f_fname,"/RTScache/fst_s%d_pedestals_%08u_%s.txt",sector,run,bad?"BAD":"GOOD") ;
1160  }
1161 
1162 
1163  f = fopen(f_fname,"w") ;
1164  if(f==0) {
1165  LOG(ERR,"ped::to_cache can't open output file \"%s\" [%s]",f_fname,strerror(errno)) ;
1166  return -1 ;
1167  }
1168 
1169 
1170  if(tb_cou_ped != tb_cou_xpect) {
1171  LOG(ERR,"Writing pedestals to cache \"%s\" [valid %d] but data has %d timebins != expect %d!",f_fname,valid,
1172  tb_cou_ped,tb_cou_xpect) ;
1173  }
1174  else {
1175  LOG(INFO,"Writing pedestals to cache \"%s\" [valid %d], ntimebins %d",f_fname,valid,tb_cou_ped) ;
1176  }
1177 
1178  time_t tim = time(0) ;
1179  fprintf(f,"# Detector FST%d\n",sector) ;
1180  fprintf(f,"# Run %08u\n",run) ;
1181  fprintf(f,"# Date %s",ctime(&tim)) ;
1182  fprintf(f,"# Timebins %d\n",tb_cou_ped) ;
1183  fprintf(f,"\n") ;
1184 
1185 
1186  for(int r=0;r<FGT_RDO_COU;r++) {
1187  if(rb_mask & (1<<r)) ;
1188  else continue ;
1189 
1190 
1191  struct peds_t *ped = peds + r ;
1192 
1193  for(int arm=0;arm<3;arm++) {
1194  for(int apv=0;apv<FGT_APV_COU;apv++) {
1195  for(int c=0;c<FGT_CH_COU;c++) {
1196 
1197  // dump only the ones which need to exist!
1198  if(ch_status[r][arm][apv][c] & FGT_CH_STAT_SHOULD) ;
1199  else continue ;
1200 
1201  if(cmnGroup[apv][c]<0) continue ;
1202 
1203  for(int t=0;t<tb_cou_ped;t++) {
1204 
1205  fprintf(f,"%d %d %2d %3d %2d %7.3f %.3f %.3f\n",r+1,arm,apv,c,t,
1206  ped->ped[arm][apv][c][t],
1207  ped->rms[arm][apv][c][t],
1208  ped->cmn_rms[arm][apv][c][t]) ;
1209  }
1210  }
1211  }
1212  }
1213  }
1214 
1215  fclose(f) ;
1216 
1217  if(fname) {
1218  strcpy(f_fname,fname) ;
1219  }
1220  else {
1221  sprintf(f_fname,"/RTScache/fst_s%d_pedestals_cmn_%08u_%s.txt",sector,run,bad?"BAD":"GOOD") ;
1222  }
1223 
1224 
1225  f = fopen(f_fname,"w") ;
1226  if(f==0) {
1227  LOG(ERR,"ped::to_cache can't open output file \"%s\" [%s]",f_fname,strerror(errno)) ;
1228  return -1 ;
1229  }
1230 
1231 
1232  if(tb_cou_ped != tb_cou_xpect) {
1233  LOG(ERR,"Writing pedestals to cache \"%s\" [valid %d] but data has %d timebins != expect %d!",f_fname,valid,
1234  tb_cou_ped,tb_cou_xpect) ;
1235  }
1236  else {
1237  LOG(INFO,"Writing pedestals to cache \"%s\" [valid %d], ntimebins %d",f_fname,valid,tb_cou_ped) ;
1238  }
1239 
1240  tim = time(0) ;
1241  fprintf(f,"# Detector FST%d\n",sector) ;
1242  fprintf(f,"# Run %08u\n",run) ;
1243  fprintf(f,"# Date %s",ctime(&tim)) ;
1244  fprintf(f,"# Timebins %d\n",tb_cou_ped) ;
1245  fprintf(f,"\n") ;
1246 
1247 
1248  for(int r=0;r<FGT_RDO_COU;r++) {
1249  if(rb_mask & (1<<r)) ;
1250  else continue ;
1251 
1252 
1253  struct peds_t *ped = peds + r ;
1254 
1255  for(int arm=0;arm<3;arm++) {
1256  for(int apv=0;apv<FGT_APV_COU;apv++) {
1257  for(int c=0;c<FGT_CH_COU;c++) {
1258 
1259  // dump only the ones which need to exist!
1260  if(ch_status[r][arm][apv][c] & FGT_CH_STAT_SHOULD) ;
1261  else continue ;
1262 
1263  if(cmnGroup[apv][c]<0) continue ;
1264 
1265  for(int t=0;t<tb_cou_ped;t++) {
1266 
1267  fprintf(f,"%d %d %2d %3d %2d %7.3f %.3f\n",r+1,arm,apv,c,t,
1268  ped->cmn_ped[arm][apv][c][t],
1269  ped->cmn_rms[arm][apv][c][t]) ;
1270  }
1271  }
1272  }
1273  }
1274  }
1275 
1276  fclose(f) ;
1277 
1278 
1279 
1280 
1281  if(bad || dont_cache || !valid) {
1282  LOG(CAUTION,"Pedestals NOT cached for run %08u",run) ;
1283  LOG(ERR,"Pedestals NOT cached for run %08u: %d:%d:0x%X!",run,bad,valid,dont_cache) ;
1284  return 0 ;
1285  }
1286 
1287 
1288  sprintf(f_fname,"/RTScache/fst_s%d_pedestals.txt",sector) ;
1289  f = fopen(f_fname,"w") ;
1290  if(f==0) {
1291  LOG(ERR,"ped::to_cache can't open output file \"%s\" [%s]",f_fname,strerror(errno)) ;
1292  return -1 ;
1293  }
1294 
1295  fprintf(f,"# Detector FST%d\n",sector) ;
1296  fprintf(f,"# Run %08u\n",run) ;
1297  fprintf(f,"# Date %s",ctime(&tim)) ;
1298  fprintf(f,"# Timebins %d\n",tb_cou_ped) ;
1299  fprintf(f,"\n") ;
1300 
1301  int all_cou = 0 ;
1302  int non_cached_cou = 0 ;
1303 
1304  for(int r=0;r<FGT_RDO_COU;r++) {
1305  if(rb_mask & (1<<r)) ;
1306  else continue ;
1307 
1308 
1309  struct peds_t *ped = peds + r ;
1310 
1311  for(int arm=0;arm<3;arm++) {
1312  for(int apv=0;apv<FGT_APV_COU;apv++) {
1313 
1314 
1315  for(int c=0;c<FGT_CH_COU;c++) {
1316 
1317  // dump only the ones which need to exist!
1318  if(ch_status[r][arm][apv][c] & FGT_CH_STAT_SHOULD) ;
1319  else continue ;
1320 
1321  if(cmnGroup[apv][c]<0) continue ;
1322 
1323  struct peds_t *use_ped = ped ;
1324 
1325  all_cou++ ;
1326 #if 0
1327  // use just he lower bits of status!!!
1328  if((ch_status[r][arm][apv][c] & 0x0E) || (ped->cou[arm][apv][c]==0)) {
1329  //use_ped = peds_from_cache ; Major bug before Aug 2014!!! All peds_from_cache were taken from RDO1
1330  //FIXED in Aug 2014:
1331  use_ped = peds_from_cache + r ;
1332  non_cached_cou++ ;
1333  }
1334  else {
1335  use_ped = ped ;
1336  }
1337 #endif
1338  for(int t=0;t<tb_cou_ped;t++) {
1339 
1340  fprintf(f,"%d %d %2d %3d %2d %7.3f %.3f %.3f\n",r+1,arm,apv,c,t,
1341  use_ped->ped[arm][apv][c][t],
1342  use_ped->rms[arm][apv][c][t],
1343  use_ped->cmn_rms[arm][apv][c][t]) ;
1344  }
1345  }
1346  }
1347  }
1348  }
1349 
1350  fclose(f) ;
1351 
1352 #if 0
1353  {
1354  char cmd[128] ;
1355 
1356  sprintf(cmd,"/bin/cp /RTScache/pedestals.txt /RTScache/%s_pedestals_%08u_loaded.txt","fst",run) ;
1357  system(cmd) ;
1358  }
1359 #endif
1360 
1361  double perc = 100.0 * (double)non_cached_cou / (double)all_cou ;
1362  if(perc > 10.0) {
1363  LOG(U_TONKO,"Pedestals cached for run %08u: skipped %d/%d (%d%%) channels.",run,non_cached_cou,all_cou,(int)perc) ;
1364  }
1365  else {
1366  LOG(TERR,"Pedestals cached for run %08u: skipped %d/%d channels.",run,non_cached_cou,all_cou) ;
1367  }
1368 
1369  return 1 ;
1370 }
1371 
1372 
1373 
1374 int fstPed::bad_from_cache(char *fname)
1375 {
1376  FILE *f ;
1377  const char *fn ;
1378 
1379  int b_cou = 0 ;
1380 
1381 
1382  // trivial load from disk...
1383  if(fname) {
1384  fn = fname ;
1385  f = fopen(fname,"r") ;
1386  }
1387  else {
1388  fn = "/RTS/conf/fst/fst_bad_channels.txt" ;
1389  f = fopen(fn,"r") ;
1390  }
1391 
1392  if(f==0) {
1393  LOG(ERR,"ped::bad_from_cache can't open input file \"%s\" [%s]",fn,strerror(errno)) ;
1394  return -1 ;
1395  }
1396 
1397 
1398  LOG(NOTE,"Loading bad from cache \"%s\"...",fn) ;
1399 
1400 
1401 
1402  while(!feof(f)) {
1403  int r, arm, apv, ch ;
1404  char buff[256] ;
1405 
1406  if(fgets(buff,sizeof(buff),f) == 0) continue ;
1407 
1408  switch(buff[0]) {
1409  case '#' :
1410  case '!' :
1411  case '*' :
1412  case '/' :
1413  case '.' :
1414  continue ;
1415  }
1416 
1417 
1418  int ret = sscanf(buff,"%d %d %d %d",&r,&arm,&apv,&ch) ;
1419  if(ret != 4) continue ;
1420  //check for negative 0!
1421 
1422  char ca[4][16] ;
1423  char n[4] ;
1424  memset(n,0,sizeof(n)) ;
1425  sscanf(buff,"%s %s %s %s",ca[0],ca[1],ca[2],ca[3]) ;
1426  for(int i=0;i<4;i++) {
1427  int dummy ;
1428  if(sscanf(ca[i],"%d",&dummy)!=1) continue ;
1429  if(dummy==0) {
1430  if(index(ca[i],'-')) n[i] = '-' ;
1431  else n[i] = '+' ;
1432  }
1433  else {
1434  if(dummy<0) n[i] = '-' ;
1435  else n[i] = '+' ;
1436  }
1437  }
1438 
1439  if(r<0) r *= -1 ;
1440  if(arm < 0) arm *= -1 ;
1441  if(apv < 0) apv *= -1 ;
1442  if(ch < 0) ch *= -1 ;
1443 
1444 
1445 
1446  if(n[1]=='-') { //nix ARM
1447  for(int a=0;a<FGT_APV_COU;a++) {
1448  for(int c=0;c<FGT_CH_COU;c++) {
1449  ch_status[r-1][arm][a][c] |= FGT_CH_STAT_BAD ;
1450  }
1451  }
1452  }
1453  else if(n[2]=='-') { //nix APV
1454  for(int c=0;c<FGT_CH_COU;c++) {
1455  ch_status[r-1][arm][apv][c] |= FGT_CH_STAT_BAD ;
1456  }
1457  }
1458  else {
1459  ch_status[r-1][arm][apv][ch] |= FGT_CH_STAT_BAD ;
1460  }
1461 
1462 
1463  }
1464 
1465  fclose(f) ;
1466 
1467  for(int r=0;r<FGT_RDO_COU;r++) {
1468  for(int m=0;m<FST_ARM_COU;m++) {
1469  for(int a=0;a<FGT_APV_COU;a++) {
1470  for(int c=0;c<FGT_CH_COU;c++) {
1471  if(ch_status[r][m][a][c] & FGT_CH_STAT_BAD) b_cou++ ;
1472  }
1473  }
1474  }
1475  }
1476 
1477  LOG(INFO,"Loaded %d bad channels from \"%s\"",b_cou,fn) ;
1478 
1479  return b_cou ;
1480 }