StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
tpxGain.cxx
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <math.h>
5 #include <stdlib.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 #include <time.h>
9 
10 #include <rtsLog.h>
11 #include <daqModes.h>
12 
13 #include <TPC/rowlen.h>
14 
15 #include <TPX/tpx_altro_to_pad.h>
16 
17 #include "tpxCore.h"
18 #include "tpxGain.h"
19 
20 
21 
22 
23 struct tpx_odd_fee_t tpx_odd_fee[256] ;
24 int tpx_odd_fee_count = 0 ;
25 
26 
27 static u_int histo_data[2000] ;
28 static void histo_init()
29 {
30  memset(histo_data,0,sizeof(histo_data)) ;
31 }
32 
33 static void histo_fill(double gain)
34 {
35  int i_gain = (int) gain ;
36 
37  if((i_gain>=0) && (i_gain<2000)) histo_data[i_gain]++ ;
38 
39  return ;
40 }
41 
42 static double histo_peak()
43 {
44  int max_sum, sum ;
45  int start_i = 0;
46  double peak ;
47 
48  max_sum = 0 ;
49  for(int i=0;i<(2000-10);i++) {
50  sum = 0 ;
51  for(int j=0;j<10;j++) {
52  sum += histo_data[i+j] ;
53  }
54  if(sum > max_sum) {
55  max_sum = sum ;
56  start_i = i ;
57  }
58  }
59 
60  sum = 0 ;
61  peak = 0.0 ;
62 
63  for(int i=start_i;i<(start_i+10);i++) {
64  sum += histo_data[i] ;
65  peak += i*histo_data[i] ;
66  }
67 
68 
69  if(sum) {
70  peak /= sum ;
71  peak += 0.5 ; // to unbias it...
72  }
73 
74  return peak ;
75 }
76 
77 
78 
79 tpxGain::tpxGain()
80 {
81  events = 0 ;
82  load_time = 0 ;
83  sector = 0 ; // assume all...
84  c_run = c_date = c_time = 0 ;
85 
86  row_max = 45 ; // normal TPC, not iTPC!
87 
88  // no raw dump
89  raw_gains_fname = 0 ;
90 
91  // mark memory as cleared
92  aux = 0 ;
93  means = 0 ;
94  fee_found = 0 ;
95  memset(gains,0,sizeof(gains)) ;
96 
97  dummy_gain.g = 1.0 ;
98  dummy_gain.t0 = 0.0 ;
99 
100  // bad_fee's are sticky and can only be entered via a file!
101  memset(bad_fee,0,sizeof(bad_fee)) ;
102  tpx_odd_fee_count = 0 ;
103 
104  memset(bad_rdo_mask,0,sizeof(bad_rdo_mask)) ;
105 
106  pulser_ped = TPX_PULSER_PED_START ;
107 
108  pulser_ped_stop = TPX_TCU_LOC_PED_STOP ;
109  pulser_start = TPX_TCU_LOC_START ;
110  pulser_stop = TPX_TCU_LOC_STOP ;
111  pulser_time_0 = TPX_TCU_LOC_TIME_0 ;
112 
113  clock_mode = TPX_CLOCK_TCU_LOC ;
114 
115  return ;
116 }
117 
118 tpxGain::~tpxGain()
119 {
120  free_store() ;
121 
122  return ;
123 }
124 
125 void tpxGain::set_clock_mode(int mode)
126 {
127  clock_mode = mode ;
128 
129  switch(mode) {
130  default:
131  case TPX_CLOCK_TCU_LOC : // default
132  pulser_ped_stop = TPX_TCU_LOC_PED_STOP ;
133  pulser_start = TPX_TCU_LOC_START ;
134  pulser_stop = TPX_TCU_LOC_STOP ;
135  pulser_time_0 = TPX_TCU_LOC_TIME_0 ;
136  break ;
137  case TPX_CLOCK_TCD :
138  pulser_ped_stop = TPX_TCD_PED_STOP ;
139  pulser_start = TPX_TCD_START ;
140  pulser_stop = TPX_TCD_STOP ;
141  pulser_time_0 = TPX_TCD_TIME_0 ;
142  break ;
143  case TPX_CLOCK_TCU_RHIC : // this changes...
144  pulser_ped_stop = TPX_TCU_RHIC_PED_STOP ;
145  pulser_start = TPX_TCU_RHIC_START ; // don;t know yet!
146  pulser_stop = TPX_TCU_RHIC_STOP ;
147  pulser_time_0 = TPX_TCU_RHIC_TIME_0 ;
148  break ;
149  case TPX_CLOCK_NEW_TCD : // new frequency from Oct 2021
150  pulser_ped_stop = TPX_NEW_TCD_PED_STOP ;
151  pulser_start = TPX_NEW_TCD_START ;
152  pulser_stop = TPX_NEW_TCD_STOP ;
153  pulser_time_0 = TPX_NEW_TCD_TIME_0 ;
154  break ;
155 
156  }
157 
158 
159  return ;
160 }
161 
162 
163 void tpxGain::free_store()
164 {
165  if(aux) {
166  free(aux) ;
167  aux = 0 ;
168  }
169 
170  if(means) {
171  free(means) ;
172  means = 0 ;
173  }
174 
175  if(fee_found) {
176  free(fee_found) ;
177  fee_found = 0 ;
178  }
179 
180  for(int i=0;i<24;i++) {
181  if(gains[i]) {
182  free(gains[i]) ;
183  gains[i] = 0 ;
184  }
185  }
186 
187  return ;
188 }
189 
190 /*
191  Initialize calculation at beginning of a run...
192 */
193 void tpxGain::init(int sec)
194 {
195  int bytes ;
196 
197  events = 0 ;
198  load_time = 0 ; // force reload next time if I reinit gains!
199  sector = sec ; // this is the 36
200 
201 
202 
203  bytes = sizeof(struct means) * 24 * 46 ;
204  if(means==0) {
205  means = (struct means *) malloc(bytes) ;
206  }
207  memset(means,0,bytes) ;
208 
209  bytes = sizeof(struct aux) * 24 * 46 * 182 ;
210  if(aux==0) {
211  aux = (struct aux *) malloc(bytes) ;
212  }
213  memset(aux,0,bytes) ;
214 
215  bytes = sizeof(struct fee_found_t) * 25 * 7 ;
216  if(fee_found == 0) {
217  fee_found = (struct fee_found_t *) malloc(bytes) ;
218 
219  }
220  memset(fee_found,0,bytes) ;
221 
222  for(int i=0;i<24;i++) {
223  bytes = sizeof(struct gains) * 46 * 182 ;
224  if(gains[i]==0) {
225  gains[i] = (struct gains *) malloc(bytes) ;
226  }
227  memset(gains[i],0,bytes) ;
228  }
229 
230 
231  memset(tpx_pulser_peak,0,sizeof(tpx_pulser_peak)) ;
232 
233  memset(bad_rdo_mask,0,sizeof(bad_rdo_mask)) ;
234 
235  return ;
236 }
237 
238 
239 /*
240  Called at end of event
241 */
242 void tpxGain::ev_done()
243 {
244  if(events==0) {
245  LOG(WARN,"Using hardcoded tb range: ped at [%3d:%3d], peak at [%3d:%3d], T0 at %f!",pulser_ped, pulser_ped_stop, pulser_start,pulser_stop,pulser_time_0) ;
246  }
247 
248  events++ ;
249  LOG(NOTE,"After event %d",events) ;
250 
251  return ;
252 }
253 
254 /*
255  Called once per event per RDO.
256  I.e. "evbuff" points to the RDO contrib
257 */
258 void tpxGain::accum(char *evbuff, int bytes)
259 {
260  int t ;
261  int i ;
262  u_int *data_end ;
263  int sec ;
264  tpx_rdo_event rdo ;
265  tpx_altro_struct a ;
266  struct gains *gs ;
267  struct aux *as ;
268 
269 
270  t = tpx_get_start(evbuff, bytes/4, &rdo, 0) ;
271 
272  LOG(NOTE,"RDO %d: %d bytes,token %d",rdo.rdo,bytes,t) ;
273 
274  if(t <= 0) return ; // non data event...
275 
276 
277  sec = rdo.sector ;
278  data_end = rdo.data_end ;
279  a.rdo = rdo.rdo - 1 ; // a.rdo counts from 0
280  a.what = TPX_ALTRO_DO_ADC ;
281  a.t = rdo.token ;
282  a.sector = rdo.sector ;
283  a.log_err = 0 ;
284 
285  // got an rdo
286  struct fee_found_t *fee_f = get_fee_found(sec,rdo.rdo) ;
287  fee_f->got_one++ ;
288 
289  LOG(DBG,"gain: evt %d (got_one %d), sector %d, rdo %d",events, fee_f->got_one,rdo.sector, rdo.rdo) ;
290 
291  do {
292 
293  data_end = tpx_scan_to_next(data_end, rdo.data_start, &a) ;
294 
295  fee_f->ch_count[a.id][a.ch]++ ;
296 
297  if((a.row>45) || (a.pad>182)) { // the FEE is not supposed to be in this RDO!
298  LOG(TERR,"Should not be here! row %d, pad %d, aid %3d:%02d",a.row,a.pad, a.id, a.ch) ;
299  continue ;
300  }
301 
302  gs = get_gains(sec,a.row,a.pad) ;
303  as = get_aux(sec,a.row,a.pad) ;
304 
305 
306  double cou, noise ;
307 
308  cou = 0.0 ;
309  noise = 0.0 ;
310 
311 
312  if(a.count) as->cou++ ;
313 
314  for(i=0;i<a.count;i++) {
315  if(a.adc[i] == 0) continue ; // this is possible due to altro packing style...
316 
317  int adc_i = a.adc[i] ;
318  int tb_i = a.tb[i] ;
319 
320  //LOG(TERR,"RDO %d: %d %d, tb %d, adc %d",rdo.rdo,a.row,a.pad,tb_i,adc_i) ;
321 
322  // sum up the main pulser peak...
323  if((tb_i>=pulser_ped) && (tb_i<=pulser_stop)) {
324  as->adc_store[tb_i - pulser_ped] += adc_i ;
325  }
326  else if(tb_i < pulser_ped) { // sum up stuff before the peak
327  noise += adc_i ;
328  cou++ ;
329  }
330  }
331 
332  if(cou) noise /= cou ;
333 
334 
335  if((noise > 40.0) || (cou>20)) {
336  as->noise++ ;
337  }
338 
339  } while(data_end && (data_end > rdo.data_start)) ;
340 
341 
342  return ;
343 
344 }
345 
346 /*
347  When I run from file I don't know
348  about bad FEEs or bad RDOs or no sectors
349  so I need to figure this out from took data
350 
351 */
352 void tpxGain::if_file()
353 {
354  memset(bad_rdo_mask, 0, sizeof(bad_rdo_mask)) ;
355 
356  for(int s=1;s<=24;s++) {
357  for(int r=1;r<=6;r++) {
358  struct fee_found_t *fee_f = get_fee_found(s,r) ;
359 
360  if(fee_f->got_one) {
361  for(int a=0;a<256;a+=2) {
362  int not_bad ;
363 
364  if(tpx_altro_to_fee(r,a)<0) continue ; // not there
365 
366  not_bad = 0 ;
367 
368  for(int w=a;w<(a+2);w++) {
369  for(int c=0;c<16;c++) {
370  if(fee_f->ch_count[w][c]) {
371  not_bad = 1 ;
372  break ;
373  }
374  }
375  if(not_bad) break ;
376  }
377 
378  if(!not_bad) { // no FEE has this channel
379  int c = bad_fee[s][r][0] ;
380 
381  bad_fee[s][r][c+1] = a ;
382  bad_fee[s][r][0]++ ;
383 
384  int fee = tpx_altro_to_fee(r,a) ;
385 
386  LOG(WARN,"Possible bad FEE %3d (ALTRO %3d) on sector %2d, RDO %d",fee,a,s,r) ;
387  LOG(WARN," to tpx_gains.txt: %d %d %d 0.000 0.000",-s,r,fee) ;
388  }
389  }
390  }
391  else {
392  bad_rdo_mask[s] |= (1<<(r-1)) ;
393  LOG(WARN,"Possible masked RDO %d on sector %2d",r,s) ;
394  }
395 
396  }
397 
398 
399  }
400 
401 
402  return ;
403 
404 }
405 
406 
407 /*
408  Called at end of run
409 */
410 void tpxGain::calc()
411 {
412  int s, r, p ;
413  int c ;
414  double g_rms, t0_rms, c_rms ;
415  int t0_mean_count[25] ;
416  double t0_mean[25] ;
417 
418  memset(t0_mean_count,0,sizeof(t0_mean_count)) ;
419  memset(t0_mean,0,sizeof(t0_mean)) ;
420 
421  g_rms = t0_rms = c_rms = 0 ;
422 
423 
424  // HACK! due to my f**** way of doing this I will need to add one to the events here...
425 //? events++ ;
426 
427  LOG(DBG,"gain_calc: doing calculation with %d events",events) ;
428 
429 
430 
431 
432 
433  int s_start, s_stop ;
434 
435  if(sector==0) { // whole TPX!
436  s_start = 1 ;
437  s_stop = 24 ;
438  }
439  else if(sector <= 24) {
440  s_start = sector ;
441  s_stop = sector ;
442  }
443  else {
444  s_start = (sector-24)*2-1 ;
445  s_stop = s_start + 1 ;
446  }
447 
448  char fname[128];
449  FILE *ofile = 0 ;
450  if(raw_gains_fname) {
451  sprintf(fname,"%s_%02d",raw_gains_fname,sector) ;
452  ofile = fopen(fname,"w") ;
453  }
454 
455 
456  for(s=s_start;s<=s_stop;s++) {
457 
458 
459  for(r=1;r<=45;r++) { // I changed this so it skips row 0, i.e. diconnected pads...
460 
461  // sanity check...
462  if(get_means(s,r)->g || get_means(s,r)->t0) {
463  LOG(ERR,"%f %f",get_means(s,r)->g,get_means(s,r)->t0) ;
464  }
465 
466  // calc the mean, where appropriate...
467  for(p=1;p<=tpc_rowlen[r];p++) {
468  c = get_aux(s,r,p)->cou ; // get count of events for this pad...
469 
470  if(!c) { // nothing ever fell on this pad _at_all_
471  get_gains(s,r,p)->g = 0.0 ;
472  get_gains(s,r,p)->t0 = 9.999 ;
473 
474  int aa,cc,rdo ;
475  tpx_to_altro(r,p,rdo,aa,cc) ;
476  rdo-- ; // we want from 0
477  if(bad_rdo_mask[s] & (1<<rdo)) {
478  // kill all the rows & pads in this RDO
479  LOG(WARN,"Masked Sector %d, RDO %d, row %d, pad %d",s,rdo+1,r,p) ;
480  get_gains(s,r,p)->t0 = -9.990 ;
481 
482  }
483 
484  // back to indexing from 1!
485  rdo++ ;
486  int c = bad_fee[s][rdo][0] ;
487 
488  for(int i=0;i<c;i++) {
489  int al=bad_fee[s][rdo][i+1];
490  for(int j=0;j<2;j++) {
491  //LOG(WARN,"Checking ALTRO %3d against %3d, RDO %d, row %d, pad %d",aa,al,rdo,r,p) ;
492  if(aa == (int)al) {
493  //LOG(WARN,"Masked ALTRO %3d, RDO %d, row %d, pad %d",aa,rdo,r,p) ;
494  get_gains(s,r,p)->t0 = -9.900 ;
495  }
496  al++ ;
497  }
498  }
499 
500  }
501  else {
502  int ped_cou = 0 ;
503  double ped = 0.0 ;
504 
505  struct aux *as = get_aux(s,r,p) ;
506 
507  // this is used for the pedestal
508  for(int i=pulser_ped;i<=pulser_ped_stop;i++) {
509  ped += (double) as->adc_store[i-pulser_ped] / (double) c ;
510  ped_cou++ ;
511  }
512 
513  ped /= ped_cou ;
514 
515  double charge, t0 ;
516  charge = t0 = 0.0 ;
517 
518  // and this is the peak
519  for(int i=pulser_start;i<=pulser_stop;i++) {
520  double val = (double) as->adc_store[i-pulser_ped] / (double) c - ped ;
521  charge += val ;
522  t0 += i * val ;
523  }
524 
525 
526  // and fill in the final absolute charge and t0...
527  //LOG(TERR,"RDO %d: %d %d = %f %f",0,r,p,ped,charge) ;
528  //for(int i=pulser_ped;i<=pulser_stop;i++) {
529  // LOG(TERR," %d %d",i,as->adc_store[i-pulser_ped]) ;
530  //}
531 
532  get_gains(s,r,p)->g = charge ; // this might be small or even negative in case the pad is not connected
533 
534  if(charge>1) { // some arbitrary cutoff
535  get_gains(s,r,p)->t0 = t0/charge ;
536  }
537  else {
538  get_gains(s,r,p)->t0 = 0.0 ; // *shrug* what else...
539  get_gains(s,r,p)->g = 0.0 ; // *shrug* what else...
540  }
541 
542 
543  }
544 
545  //LOG(TERR,"S%d: RP %d:%d = %f %f",s,r,p,get_gains(s,r,p)->g,get_gains(s,r,p)->t0) ;
546  }
547 
548  /*
549  Now we need to calculate the mean CHARGE and T0 of a ROW
550 
551  We will skip first and last 3 pads because the gain
552  (calculated with the pulser) is usually wrong.
553 
554  We will also skip any pads which had _any_ to low
555  or to high pulse...
556  */
557 
558  // normalize the odd pulser to 100%
559  for(p=1;p<=tpc_rowlen[r];p++) { // skip first and last 3 pads!
560  struct aux *aux = get_aux(s,r,p) ;
561 
562  if(events) { // normalize to 100%
563  aux->low_pulse = (100 * aux->low_pulse) / events ;
564  aux->high_pulse = (100 * aux->high_pulse) / events ;
565  aux->noise = (100 * aux->noise) / events ;
566  }
567  }
568 
569  histo_init() ;
570 
571  c = 0 ;
572 
573  for(p=1;p<=tpc_rowlen[r];p++) {
574  struct aux *aux = get_aux(s,r,p) ;
575  int fired = aux->cou ;
576 
577 
578  if(fired) ; // do nothing, all is well...
579  else aux->low_pulse = 100 ; // obviously
580 
581  // the gain now has the mean charge, absolute, so let's cut on some
582  // sanitiy numbers here i.e. 100 ...
583  if(get_gains(s,r,p)->g < 100.0) aux->low_pulse = 100 ;
584  if(get_gains(s,r,p)->g > 2000.0) aux->high_pulse = 100 ;
585 
586  // skip obviously bad ones...
587  if((aux->low_pulse > 10) || (aux->noise > 10) || (aux->high_pulse > 10)) {
588  if(r != 0) LOG(NOTE,"ROW %d, pad %d: lo %d, noise %d, hi %d -- skipping",r,p,
589  aux->low_pulse, aux->noise, aux->high_pulse) ;
590  continue ;
591  }
592 
593  // use only _known_ good ones
594  if((p>=4) && (p<=(tpc_rowlen[r]-3))) {
595  histo_fill(get_gains(s,r,p)->g) ;
596  c++ ;
597  }
598  }
599 
600  int accepted_pads_cou = c ;
601 
602  double row_means = histo_peak() ; // rough mean of the charge on this row...
603 
604  /*
605  now, we skip all gains where the gain is not within
606  10% of the mean
607  */
608 
609  c = 0 ;
610  int tot_pads_cou ;
611  int good_pads_cou ;
612 
613  tot_pads_cou = good_pads_cou = 0 ;
614 
615  //LOG(TERR,"S%d, row %d = charge row_mean %f",s,r,row_means) ;
616 
617  for(p=4;p<=(tpc_rowlen[r]-3);p++) {
618  double g = get_gains(s,r,p)->g ;
619  double t0 = get_gains(s,r,p)->t0 ;
620 
621 
622  // skip pads which are outside of the narrow window...
623  if( (g>(row_means*0.9)) && (g<(row_means*1.1))) {
624 
625  if(t0 < -1.0) {
626  LOG(WARN,"TO: %d %d %d = %f %f",s,r,p,g,t0) ;
627  }
628 
629 
630  get_means(s,r)->g += g ;
631  get_means(s,r)->g_rms += g * g ;
632 
633  get_means(s,r)->t0 += get_gains(s,r,p)->t0 ;
634  get_means(s,r)->t0_rms += get_gains(s,r,p)->t0 * get_gains(s,r,p)->t0 ;
635  c++ ;
636  }
637 
638  tot_pads_cou++ ;
639  }
640 
641  good_pads_cou = c ; // remember
642 
643  // now calculate the nicer means...
644  if(c==0) {
645  // no row in the data...
646  get_means(s,r)->t0 = tb_stop ;
647  }
648  else {
649  get_means(s,r)->g /= c ;
650  get_means(s,r)->g_rms /= c ;
651 
652  get_means(s,r)->g_rms = sqrt(get_means(s,r)->g_rms - get_means(s,r)->g * get_means(s,r)->g) ;
653 
654  get_means(s,r)->t0 /= c ;
655  get_means(s,r)->t0_rms /= c ;
656 
657  double tmp = get_means(s,r)->t0_rms - get_means(s,r)->t0 * get_means(s,r)->t0 ;
658  if(tmp < 0.0) {
659  get_means(s,r)->t0_rms = 0.0 ;
660  }
661  else {
662  get_means(s,r)->t0_rms = sqrt(tmp) ;
663  }
664 
665 // LOG(TERR,"Sector %d, row %d: gain %f +- %f, t0 %f +- %f",s,r,
666 // get_means(s,r)->g,get_means(s,r)->g_rms,
667 // get_means(s,r)->t0,get_means(s,r)->t0_rms
668 // ) ;
669  }
670 
671 
672 #if 0
673  /* Dump absolute values here for debugging! */
674  printf("%2d %2d %f %f %f %f\n",s,r,
675  get_means(s,r)->g, get_means(s,r)->g_rms,
676  get_means(s,r)->t0, get_means(s,r)->t0_rms) ;
677 #endif
678 
679  /*
680  Now we apply the per-row normalization of the gain and T0 constants using
681  the previously calculated average gains and T0
682  */
683 
684  for(p=1;p<=tpc_rowlen[r];p++) {
685 
686  if(ofile) fprintf(ofile,"%d %d %d %.3f %.3f ",s,r,p,get_gains(s,r,p)->g,get_gains(s,r,p)->t0) ;
687 
688  if(get_gains(s,r,p)->g>0.0001) {
689  double t0 = get_gains(s,r,p)->t0 ;
690 
691  if(t0<0) {
692  LOG(WARN,"T0 S%d %d %d = %f %f",s,r,p,get_gains(s,r,p)->g,t0) ;
693  }
694 
695 
696  // this is the actual correction...
697  get_gains(s,r,p)->g = get_means(s,r)->g / get_gains(s,r,p)->g ; // relative to row
698 
699 
700 
701 
702  if((p==1) || (p==2) || (p==tpc_rowlen[r]) || (p==(tpc_rowlen[r]-1))) ;
703  else {
704  t0_mean[s] += get_gains(s,r,p)->t0 ;
705  t0_mean_count[s]++ ;
706  }
707 
708 // get_gains(s,r,p)->t0 = pulser_time_0 - get_gains(s,r,p)->t0; // absolute to TPX!
709  }
710 
711  if(ofile) fprintf(ofile,"%.3f %.3f\n",get_gains(s,r,p)->g, get_gains(s,r,p)->t0) ;
712  }
713 
714 
715  if(get_means(s,r)->g != 0.0) {
716  LOG(TERR,"Sector %2d, row %2d: charge %.3f +- %.3f; t0 %.3f +- %.3f; rough mean %.3f; good/acc/all pads %d/%d/%d",
717  s,r,
718  get_means(s,r)->g, get_means(s,r)->g_rms,
719  get_means(s,r)->t0, get_means(s,r)->t0_rms,
720  row_means,good_pads_cou, accepted_pads_cou, tot_pads_cou) ;
721  }
722  else {
723  LOG(WARN,"Sector %2d, row %2d: charge %f +- %f; t0 %f +- %f; rough_mean %.1f; good/acc/all pads %d/%d/%d",
724  s,r,
725  get_means(s,r)->g, get_means(s,r)->g_rms,
726  get_means(s,r)->t0, get_means(s,r)->t0_rms,
727  row_means,good_pads_cou, accepted_pads_cou, tot_pads_cou) ;
728  }
729 
730 
731  // for logging reasons we calc the RMS of the whole TPC but we skip unconnected pads
732  if(get_means(s,r)->g) {
733 
734  //printf("Sector %d, row %d: %f +- %f charge, %f += %f t0 [%d cou]\n",s,r,
735  // get_means(s,r)->g, get_means(s,r)->g_rms,
736  // get_means(s,r)->t0, get_means(s,r)->t0_rms, c) ;
737 
738  g_rms += get_means(s,r)->g_rms ;
739  t0_rms += get_means(s,r)->t0_rms ;
740  c_rms++ ;
741  }
742 
743 
744 
745  } // end of row calc...
746  } // end of sector calc
747 
748 
749 
750  g_rms /= c_rms ;
751  t0_rms /= c_rms ;
752 
753  if(ofile) fclose(ofile) ;
754 
755  double t0_all_mean = 0.0 ;
756  int t0_all_mean_count = 0 ;
757  for(int s=s_start;s<=s_stop;s++) {
758  if(t0_mean_count[s]) {
759  t0_mean[s] /= (double) t0_mean_count[s] ;
760  if(s!=16) {
761  t0_all_mean += t0_mean[s] ;
762  t0_all_mean_count++ ;
763  }
764  LOG(TERR,"Sector %d: t0_mean %f, count was %d",s,t0_mean[s],t0_mean_count[s]) ;
765  }
766  }
767 
768  // for sector 16 specially in case we are running online!!!
769  if((s_start==16) && (s_stop==16)) {
770  LOG(WARN,"Sector 16 -- special case") ;
771  t0_all_mean += t0_mean[16] ;
772  t0_all_mean_count = 1 ;
773  }
774 
775  if(t0_all_mean_count) t0_all_mean /= (double) t0_all_mean_count ;
776 
777 
778  // re-do T0 with this new mean!
779  for(int s=s_start;s<=s_stop;s++) {
780  for(int r=1;r<=45;r++) {
781  for(int p=1;p<=tpc_rowlen[r];p++) {
782  double t0 = get_gains(s,r,p)->t0 ;
783 
784  if(get_gains(s,r,p)->g) {
785  get_gains(s,r,p)->t0 = t0_all_mean - t0 ;
786  }
787 
788  }
789  }
790  }
791 
792  LOG(TERR,"gain_calc: sectors [%d:%d]: %d events used: Mean RMS: %f gain; T0 %f +- %f, diff from canonical %f",
793  s_start,s_stop,
794  events,
795  g_rms,
796  t0_all_mean, t0_rms,
797  pulser_time_0-t0_all_mean) ;
798 
799 
800  return ;
801 }
802 
803 void tpxGain::do_default(int sec)
804 {
805  int s, r, p ;
806 
807 
808  // zap and create defaults in case the file is missing!
809  memset(bad_fee,0,sizeof(bad_fee)) ;
810  tpx_odd_fee_count = 0 ;
811 
812  if(sec) {
813  if(gains[sec-1] == 0) {
814  gains[sec-1] = (struct gains *) malloc(sizeof(struct gains) * 46 * 182) ;
815  }
816  }
817  else {
818  for(int i=0;i<24;i++) {
819  if(gains[i] == 0) {
820  gains[i] = (struct gains *) malloc(sizeof(struct gains) * 46 * 182) ;
821  }
822  }
823  }
824 
825  // create defaults!
826  for(s=1;s<=24;s++) {
827  if(gains[s-1]) {
828  memset(gains[s-1],0,sizeof(struct gains) * 46 * 182) ;
829  }
830  else {
831  continue ;
832  }
833 
834  for(r=1;r<=45;r++) {
835  for(p=1;p<=tpc_rowlen[r];p++) {
836  set_gains(s,r,p,1.0,0.0) ; // we'll set the gains to 1.0 only for valid pads...
837  }
838  }
839  }
840 
841 
842  return ;
843 }
844 
845 int tpxGain::from_file(const char *fname, int sec)
846 {
847  FILE *f ;
848  int s, r, p ;
849  float g, t0 ;
850  struct stat buff ;
851 
852  // try file...
853  sector = sec ;
854 
855  f = fopen(fname,"r") ;
856 
857  if(f==0) {
858  LOG(WARN,"from_file: error in fopen \"%s\" [%s]",fname,strerror(errno)) ;
859  do_default(sector) ;
860  return -1 ; // assume hange...
861  }
862 
863 
864 
865  stat(fname, &buff) ;
866 
867  LOG(DBG,"After stat %s %d %d",fname,buff.st_mtime,load_time) ;
868 
869  if(load_time < buff.st_mtime) {
870  LOG(DBG,"Will reload...") ;
871  LOG(INFO,"Reloading \"%s\"",fname) ;
872  }
873  else {
874  LOG(DBG,"Wont relaod") ;
875  LOG(INFO,"Keeping cached copy of gains...") ;
876  fclose(f) ;
877  return 0 ; // no change
878  }
879 
880 
881 
882  // we don't know yet what those values were...
883  c_run = 0 ;
884  c_date = 0 ;
885  c_time = 0 ;
886 
887  u_int f_date, f_time ;
888 
889  struct tm tm ;
890  localtime_r(&buff.st_mtime, &tm) ;
891 
892  f_date = (tm.tm_year+1900) * 10000 + (tm.tm_mon+1) * 100 + tm.tm_mday ;
893  f_time = tm.tm_hour * 10000 + tm.tm_min * 100 + tm.tm_sec ;
894 
895  //LOG(DBG,"What?") ;
896 
897  load_time = time(NULL) ;
898  do_default(sector) ; // zap to all 1...
899 
900  LOG(TERR,"reading gains from \"%s\" for sector %d...",fname, sector) ;
901 
902 
903 
904  while(!feof(f)) {
905  char str[1024] ;
906 
907  if(fgets(str,sizeof(str)-1,f)==0) continue ;
908 
909  if(strlen(str)==0) continue ; // empty
910 
911  if((str[0]=='#') || (str[0]=='/')) { // comment
912  char *cix ;
913  if((cix = strstr(str,"Run "))) {
914  sscanf(cix+4,"%u",&c_run) ;
915  }
916  else if((cix = strstr(str,"Date "))) {
917  sscanf(cix+5,"%u",&c_date) ;
918  }
919  else if((cix = strstr(str,"Time "))) {
920  sscanf(cix+5,"%u",&c_time) ;
921  }
922  else {
923  continue ; // comment
924  }
925  }
926 
927  int ret = sscanf(str,"%d %d %d %f %f\n",&s,&r,&p,&g,&t0) ;
928 
929  if(ret != 5) continue ;
930 
931 
932  if(s < 0) { // special case! the whole TPC-FEE in "pad" is bad
933  s *= -1 ;
934 
935  if(sector && (s != sector)) continue ;
936 
937  int altro ;
938 
939  // counter is in location 0!
940  int c = bad_fee[s][r][0] ;
941 
942  // the TPC_FEE is in the file as "pad"
943 
944  // move to ALTRO_ID
945  altro = (p<<1) & 0xFF ;
946  bad_fee[s][r][c+1] = altro ;
947 
948  bad_fee[s][r][0]++ ; // increment count of bad FEEs...
949 
950  // do the same for the global
951  c = tpx_odd_fee_count ;
952  tpx_odd_fee[c].sector = s ;
953  tpx_odd_fee[c].rdo = r ;
954  tpx_odd_fee[c].status = 2 ; // mark bad
955  tpx_odd_fee[c].tpc_fee_padplane = p ;
956  tpx_odd_fee[c].altro_id_padplane = altro ;
957 
958  tpx_odd_fee_count++ ;
959 
960  LOG(INFO,"Bad FEE %d: sector %2d, RB %d, ALTRO %3d (TPC-FEE %3d)",bad_fee[s][r][0],s,r,altro,p) ;
961 
962  continue ;
963  }
964 
965 
966  if(sector && (s != sector)) continue ;
967 
968  set_gains(s,r,p,g,t0) ;
969 
970  }
971  fclose(f) ;
972 
973  if(tpx_is_stgc) goto skip_per_pad ;
974 
975  // now kill the pads where we had the bad fees!
976  for(s=1;s<=24;s++) {
977 
978  if(sector && (s != sector)) continue ;
979 
980  for(r=1;r<=6;r++) {
981 
982  for(u_int c=0;c<bad_fee[s][r][0];c++) {
983  int fee ;
984 
985  fee = bad_fee[s][r][c+1] ;
986 
987  for(int i=0;i<2;i++) { // kill both ALTROs...
988  for(int ch=0;ch<16;ch++) { // ...all channels..
989  int row, pad ;
990 
991  tpx_from_altro(r-1,fee+i,ch, row, pad) ;
992 
993  if(row>45) {
994  LOG(ERR,"What %d: %d %d %d????",row,r,fee+i,ch) ;
995  continue ;
996  }
997 
998  set_gains(s,row,pad,0.0,-9.900) ; // t0 9.900 signifies the whole FEE was killed...
999 
1000 
1001  LOG(DBG,"Killing rp %d:%d for bad FEE %3d in sector %2d",row,pad,fee,s) ;
1002  }
1003  }
1004 
1005  }
1006  }
1007  }
1008 
1009  skip_per_pad:;
1010 
1011  LOG(TERR,"Gains read: run %08u, date %08u [%08u], time %06u [%06u]",c_run,c_date,f_date,c_time,f_time) ;
1012  return 1 ; // changed!
1013 }
1014 
1015 
1016 int tpxGain::to_file(const char *fname)
1017 {
1018 
1019  FILE *f ;
1020  int s, r, p ;
1021 
1022  time_t tim = time(NULL) ;
1023 
1024  if(strcmp(fname,"stdout")==0) f = stdout ;
1025  else {
1026  f = fopen(fname,"w") ;
1027  }
1028 
1029  if(f==0) {
1030  LOG(ERR,"gains: fopen \"%s\" [%s]",fname,strerror(errno)) ;
1031  return -1 ;
1032  }
1033 
1034 
1035 
1036  int s_start, s_stop ;
1037  if(sector>0) {
1038  s_start = sector ;
1039  s_stop = sector ;
1040  }
1041  else {
1042  s_start = 1 ;
1043  s_stop = 24 ;
1044  }
1045 
1046 
1047  struct tm tm ;
1048  localtime_r(&tim, &tm) ;
1049 
1050  c_date = (tm.tm_year+1900) * 10000 + (tm.tm_mon+1) * 100 + tm.tm_mday ;
1051  c_time = tm.tm_hour * 10000 + tm.tm_min * 100 + tm.tm_sec ;
1052 
1053  LOG(TERR,"gains: writing to file \"%s\" for sectors %d..%d: run %u, date %u, time %u",fname,
1054  s_start,s_stop,
1055  c_run, c_date, c_time) ;
1056 
1057  fprintf(f,"# $Id: tpxGain.cxx,v 1.37 2022/09/23 19:55:47 jml Exp $\n") ; // CVS id!
1058  fprintf(f,"# Run %u\n",c_run) ;
1059 
1060  for(s=s_start;s<=s_stop;s++) {
1061 
1062  if(bad_rdo_mask[s]) {
1063  LOG(WARN,"Sector %02d: bad rdo mask 0x%02X",s,bad_rdo_mask[s]) ;
1064  }
1065 
1066 
1067  for(r=1;r<=45;r++) {
1068  for(p=1;p<=tpc_rowlen[r];p++) {
1069  float t0 = get_gains(s,r,p)->t0 ;
1070  float gg = get_gains(s,r,p)->g ;
1071 
1072  fprintf(f,"%d %d %d %.3f %6.3f",s,r,p,
1073  gg,
1074  t0) ;
1075 
1076  if(t0 < -9.9) {
1077  fprintf(f," # RDO missing\n") ;
1078  }
1079  else if(t0 < -9.0) {
1080  fprintf(f," # FEE missing\n") ;
1081  }
1082  else {
1083  fprintf(f,"\n") ;
1084  }
1085  }
1086  }
1087  }
1088 
1089  // dump at the end!
1090  fprintf(f,"# Date %u\n",c_date) ;
1091  fprintf(f,"# Time %u\n",c_time) ;
1092 
1093  if(f != stdout) fclose(f) ;
1094 
1095  LOG(TERR,"gains: written.") ;
1096 
1097  return 0 ;
1098 }
1099 
1100 void tpxGain::compare(char *fname, int mysec)
1101 {
1102  FILE *f ;
1103  int s, r, p ;
1104  float g, t0 ;
1105  double dg_mean, dg_rms ;
1106  double dt_mean, dt_rms ;
1107  int dg_count ;
1108 
1109  int both, old_only, new_only ;
1110 
1111  old_only = new_only = both = 0 ;
1112 
1113  f = fopen(fname,"r") ;
1114 
1115  if(f==0) {
1116  LOG(ERR,"from_file: error in fopen \"%s\" [%s]",fname,strerror(errno)) ;
1117  return ;
1118  }
1119 
1120  dg_mean = dg_rms = dt_mean = dt_rms = 0.0 ;
1121  dg_count = 0 ;
1122 
1123 
1124  char (*f_bad)[46][183] = (char (*)[46][183]) malloc(25*46*183) ;
1125 
1126  if(f_bad == 0) {
1127  LOG(ERR,"Malloc failed? Wha? [%s]",strerror(errno)) ;
1128  fclose(f) ;
1129  return ;
1130  }
1131 
1132  // read in the canonical gain file
1133  while(!feof(f)) {
1134  char str[1024] ;
1135 
1136  if(fgets(str,sizeof(str)-1,f)==0) continue ;
1137 
1138  if(strlen(str)==0) continue ; // empty
1139  if((str[0]=='#') || (str[0]=='/')) continue ; // comment
1140 
1141 
1142  int ret = sscanf(str,"%d %d %d %f %f\n",&s,&r,&p,&g,&t0) ;
1143 
1144  if(ret != 5) continue ;
1145  if(s < 0) continue ;
1146 
1147  if(mysec && (s != mysec)) continue ; // only look at my sectors
1148 
1149  if(r==0) continue ; // skip unphysical channels
1150 
1151 // printf("got %d %d %d %f %f\n",s,r,p,g,t0) ;
1152 
1153  // skip edge pads, they are always a hassle
1154  if((p==1) || (p==2)) continue ;
1155  if((p==tpc_rowlen[r]) || (p==(tpc_rowlen[r]-1))) continue ;
1156 
1157  if(g==0.0) f_bad[s][r][p] = 1 ;
1158  else f_bad[s][r][p] = 0 ;
1159  }
1160 
1161  fclose(f) ;
1162 
1163  for(int s=1;s<=24;s++) {
1164  if(mysec && (s != mysec)) continue ;
1165 
1166  for(int r=1;r<=45;r++) {
1167  for(int p=1;p<=tpc_rowlen[r];p++) {
1168 
1169  // skip edge pads, they are always a hassle
1170  if((p==1) || (p==2)) continue ;
1171  if((p==tpc_rowlen[r]) || (p==(tpc_rowlen[r]-1))) continue ;
1172 
1173  //printf("New bad %d %d %d %f, old %d\n",s,r,p,get_gains(s,r,p)->t0,f_bad[s][r][p]) ;
1174 
1175  if(f_bad[s][r][p]) { // bad in old file
1176  if(get_gains(s,r,p)->g == 0.0) both++ ;
1177  else old_only++ ;
1178  }
1179  else { // good in old file
1180 
1181  // here I need to differentiate between bad FEEs and masked RDOs!
1182  if(get_gains(s,r,p)->g == 0.0) {
1183  if(get_gains(s,r,p)->t0 < -9.0) {
1184  LOG(DBG,"FEE/RDO was marked as bad (%d,%d,%d) -- skipping",s,r,p) ;
1185  }
1186  else {
1187 
1188  new_only++ ;
1189  }
1190  }
1191  else { // both OK
1192  double dg = get_gains(s,r,p)->g / g ;
1193  double dt0 = get_gains(s,r,p)->t0 - t0 ;
1194 
1195  dg_mean += dg ;
1196  dg_rms += dg * dg ;
1197 
1198  dt_mean += dt0 ;
1199  dt_rms += dt0 * dt0 ;
1200 
1201  dg_count++ ;
1202  }
1203  }
1204  }
1205  }
1206  }
1207 
1208 
1209  free(f_bad) ;
1210 
1211 // printf("dg_count %d\n",dg_count) ;
1212 
1213  if(dg_count) {
1214  dg_mean /= (double) dg_count ;
1215  dg_rms /= (double) dg_count ;
1216  dt_mean /= (double) dg_count ;
1217  dt_rms /= (double) dg_count ;
1218 
1219  dg_rms = sqrt(dg_rms - dg_mean * dg_mean) ;
1220  dt_rms = sqrt(dt_rms - dt_mean * dt_mean) ;
1221  }
1222 
1223  int max_allowed = 2 ;
1224  if(mysec == 0) { // whole TPC, I will allow more
1225  max_allowed *= 24 ;
1226  }
1227 
1228  if(new_only>max_allowed) {
1229  LOG(ERR, "gain_compare to %s: sector %d: seems to have new bad pads: both %3d, new_only %3d, old_only %d",
1230  fname,
1231  mysec,both,new_only,old_only) ;
1232  }
1233  else {
1234  LOG(INFO,"gain_compare to %s: sector %d: both %3d, new_only %3d, old_only %d",
1235  fname,mysec,both,new_only,old_only) ;
1236  }
1237 
1238 // LOG(INFO,"gain_compare: sector %d: gain %f +- %f, T0 %f +- %f",mysec,dg_mean, dg_rms, dt_mean, dt_rms) ;
1239 
1240  return ;
1241 }
1242 
1243 int tpxGain::summarize(char *fname, FILE *log, int gain_mode)
1244 {
1245  int s, r, a ;
1246  char reason[1024] ;
1247  u_int good, bad ;
1248  FILE *ofile ;
1249  int notes = 0 ;
1250 
1251  good = bad = 0 ;
1252  reason[0] = 0 ; // empty string...
1253 
1254  if(fname==0) ofile = 0 ;
1255  else if(strcmp(fname,"stdout")==0) ofile = stdout ;
1256  else {
1257  ofile = fopen(fname,"w") ;
1258  if(ofile==0) {
1259  getcwd(reason,100) ;
1260  LOG(ERR,"summarize: error in fopen %s\"%s\" [%s] ",reason,fname,strerror(errno)) ;
1261  return notes ;
1262  }
1263  }
1264 
1265  LOG(TERR,"fname %s, logfile %p, gain_mode %d",fname,log,gain_mode) ;
1266 
1267 
1268  int s_start, s_stop ;
1269  if(sector) {
1270  s_start = s_stop = sector ;
1271  }
1272  else {
1273  s_start = 1 ;
1274  s_stop = 24 ;
1275  }
1276 
1277  // check fee sanity here!
1278 
1279  for(s=s_start;s<=s_stop;s++) {
1280 // LOG(TERR,"Doing sector %d",s) ;
1281 
1282  for(r=1;r<=6;r++) { // RB
1283  struct fee_found_t *fee_f = get_fee_found(s,r) ;
1284 
1285  if(fee_f == 0) {
1286  LOG(ERR,"FEE %d,%d -- not found",s,r) ;
1287  }
1288 
1289  if(fee_f->got_one == 0) continue ;
1290 
1291  if(events != (int)fee_f->got_one) {
1292  LOG(WARN,"Run had sector %d, RB %d: expect %u events, got %u",s,r,events,fee_f->got_one) ;
1293  }
1294  else {
1295  LOG(NOTE,"Run had sector %d, RB %d: expect %u events, got %u",s,r,events,fee_f->got_one) ;
1296  }
1297 
1298  for(int i=0;i<36;i++) {
1299  int fee = tpx_rdo_fees(r,i) ;
1300  if(fee == 255) continue ;
1301 
1302 // LOG(TERR,"%d %d %d %d",s,r,i,fee) ;
1303 
1304  for(int fch=0;fch<32;fch++) { // FEE channel! [0..15] are on the upper row, [16..31] on the lower
1305 
1306  int ch = tpx_old_to_new_ch[fch] ;
1307 
1308  if(ch > 15) {
1309  ch -= 16 ;
1310  a = ((fee << 1) | 1) & 0xFF ;
1311  }
1312  else {
1313  a = (fee << 1) & 0xFF ;
1314  }
1315 
1316  int err = 0 ;
1317 
1318 // LOG(TERR,"%d %d %d %d: %d %d",s,r,i,fee,a,ch) ;
1319 
1320  int seen = fee_f->ch_count[a][ch] ;
1321 
1322 
1323  int row, pad ;
1324 
1325  tpx_from_altro(r-1,a,ch,row,pad) ;
1326 
1327  //int row = tpx_altro_to_pad[r-1][a][ch].row ;
1328  //int pad = tpx_altro_to_pad[r-1][a][ch].pad ;
1329 
1330 
1331  //LOG(TERR,"RP %d %d",row,pad) ;
1332 
1333  double g = get_gains(s,row,pad)->g ;
1334  double t0 = get_gains(s,row,pad)->t0 ;
1335 
1336  struct aux *aux = get_aux(s,row,pad) ;
1337 
1338  reason[0] = 0 ;
1339 
1340  if(seen != events) {
1341 
1342  if(seen == 0) {
1343  err = 3 ;
1344  sprintf(reason+strlen(reason),"[Bad - Missing]") ;
1345  }
1346  else {
1347  if(seen>events) {
1348  err = 3 ;
1349  sprintf(reason+strlen(reason),"[Bad - Flaky readout: seen %d times in %d events]",seen,events) ;
1350  }
1351  }
1352 
1353  }
1354 
1355 
1356  int bad_t0, bad_gain, bad_noise, bad_low ;
1357  bad_t0 = bad_gain = bad_noise = bad_low = 0 ;
1358 
1359  if(row != 0) { // only for physically connected rows!
1360 
1361  if((g<0.9) || (g>1.1)) {
1362  bad_gain = 1 ;
1363 
1364 
1365  // first & last pads are usually bad
1366  if((pad<=2) || (pad>=(tpc_rowlen[row]-1))) {
1367  if(err<1) err = 1 ;
1368  }
1369  else {
1370  if(err<2) err = 2 ;
1371  }
1372  }
1373 
1374  if((t0<-0.40) || (t0>0.40)) {
1375  bad_t0 = 1 ;
1376 
1377 
1378  // first and last are usually bad...
1379  if((pad<=2) || (pad>=(tpc_rowlen[row]-1))) {
1380  if(err<1) err = 1 ;
1381  }
1382  else {
1383  if(err<2) err = 2 ;
1384  }
1385  }
1386 
1387 
1388  if(aux->noise > 10) {
1389  bad_noise = aux->noise ;
1390 
1391  // first & last pads are usually bad
1392  if((pad<=2) || (pad>=(tpc_rowlen[row]-1))) {
1393  if(err<1) err = 1 ;
1394  }
1395  else {
1396  if(err<2) err = 2 ;
1397  }
1398  }
1399 
1400  if(aux->low_pulse > 1) {
1401  bad_low = aux->low_pulse ;
1402 
1403  // first & last pads are usually bad
1404  if((pad<=2) || (pad>=(tpc_rowlen[row]-1))) {
1405  if(err<1) err = 1 ;
1406  }
1407  else {
1408  if(err<2) err = 2 ;
1409  }
1410  }
1411 
1412  }
1413 
1414 
1415  // new as of Jun 11, 08:
1416  // override fch to be J1 pin number as given to Tonko by Bob!
1417  u_char j1 = tpx_altro_to_j1[a&1][ch] ;
1418 
1419  if(err > 1) {
1420  if(row && bad_gain) sprintf(reason+strlen(reason),"[Bad gain %.1f]",g) ;
1421  if(row && bad_t0) sprintf(reason+strlen(reason),"[Bad t0 %.1f]",t0) ;
1422  if(row && bad_noise) {
1423  if(gain_mode != GAIN_MODE_CORRECTED) {
1424  sprintf(reason+strlen(reason),"[Bad noise %d%%]",bad_noise) ;
1425  }
1426  else {
1427  sprintf(reason+strlen(reason),"[JUST NOISE %d%%]",bad_noise) ;
1428  }
1429  }
1430  if(row && bad_low) sprintf(reason+strlen(reason),"[Bad low %d%%]",bad_low) ;
1431 
1432 
1433 
1434  notes++ ;
1435  if(log) {
1436  if(gain_mode != GAIN_MODE_CORRECTED) {
1437  fprintf(log,"%2d %d %3d %2d %3d %2d %2d %3d %.3f %6.3f %d %s\n",s,r,fee,j1,a,ch,row,pad,
1438  g,t0,err,reason) ;
1439  }
1440  else if(row && bad_noise) {
1441  fprintf(log,"%2d %d %3d %2d %3d %2d %2d %3d %.3f %6.3f %d %s\n",s,r,fee,j1,a,ch,row,pad,
1442  g,t0,err,reason) ;
1443  }
1444  }
1445  }
1446 
1447  if(gain_mode != GAIN_MODE_CORRECTED) {
1448  if((err>1) || bad_gain || bad_t0 || bad_noise || bad_low) { // this now includes edge pads!
1449  g = 0.0 ; // mark real bad
1450  get_gains(s,row,pad)->g = 0.0 ; // need it later for comparison...
1451  }
1452 
1453  if(ofile) fprintf(ofile,"%2d %d %3d %2d %3d %2d %2d %3d %.3f %6.3f %d %s\n",s,r,fee,j1,a,ch,row,pad,
1454  g,t0,err,reason) ;
1455  }
1456  else {
1457  if(bad_noise) {
1458 
1459 
1460  g = 0.0 ; // mark real bad
1461  t0 = 0.0 ;
1462  get_gains(s,row,pad)->g = 0.0 ; // need it later for comparison...
1463  get_gains(s,row,pad)->t0 = 0.0 ; // need it later for comparison...
1464 
1465  if(ofile) {
1466  fprintf(ofile,"%2d %d %3d %2d %3d %2d %2d %3d %.3f %6.3f %d %s\n",s,r,fee,j1,a,ch,row,pad,
1467  g,t0,err,reason) ;
1468  fprintf(ofile,"%d %d %d 0.000 0.000 # ONLY NOISY\n",s,row,pad) ;
1469  }
1470  }
1471  else {
1472 
1473  get_gains(s,row,pad)->g = 1.0 ; // need it later for comparison...
1474  get_gains(s,row,pad)->t0 = -10.0 ; // need it later for comparison...
1475  }
1476 
1477  }
1478  fee_f->ch_count[a][ch] *= -1 ; // mark as seen and done!
1479  }
1480  }
1481 
1482  for(a=0;a<256;a++) {
1483  for(int ch=0;ch<16;ch++) {
1484  u_char j1 = tpx_altro_to_j1[a&1][ch] ;
1485  if(fee_f->ch_count[a][ch] > 0) {
1486  int fee = tpx_altro_to_fee(r,a) ;
1487  notes++ ;
1488  if(log) {
1489  fprintf(log,"%2d %d %3d %2d %3d %2d %2d %3d %.3f %6.3f %d %s\n",s,r,fee,j1,a,ch,-1,-1,
1490  0.0,0.0,3,"[Bad - Spurious channel]") ;
1491 
1492  }
1493  if(ofile) fprintf(ofile,"%2d %d %3d %2d %3d %2d %2d %3d %.3f %6.3f %d %s\n",s,r,fee,j1,a,ch,-1,-1,
1494  0.0,0.0,3,"[Bad - Spurious channel]") ;
1495  }
1496  }
1497  }
1498 
1499  if(ofile) fflush(ofile) ;
1500 
1501  }
1502  }
1503 
1504  if(ofile && (ofile != stdout)) fclose(ofile) ;
1505 
1506  return notes ;
1507 }
1508