Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTOFHit_factory.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DTOFHit_factory.cc
4 // Created: Wed Aug 7 09:30:17 EDT 2013
5 // Creator: davidl (on Darwin harriet.jlab.org 11.4.2 i386)
6 //
7 
8 
9 #include <iostream>
10 #include <iomanip>
11 #include <cmath>
12 #include <vector>
13 #include <limits>
14 
15 #include <TMath.h>
16 
17 using namespace std;
18 
19 #include <TOF/DTOFDigiHit.h>
20 #include <TOF/DTOFTDCDigiHit.h>
21 #include "DTOFHit_factory.h"
22 #include <DAQ/Df250PulseIntegral.h>
23 #include <DAQ/Df250Config.h>
24 #include <DAQ/DCODAROCInfo.h>
25 
26 using namespace jana;
27 
28 static bool COSMIC_DATA = false;
29 
30 int TOF_DEBUG = 0;
31 
32 //------------------
33 // init
34 //------------------
35 jerror_t DTOFHit_factory::init(void)
36 {
37 
38  gPARMS->SetDefaultParameter("TOF:DEBUG_TOF_HITS", TOF_DEBUG,
39  "Generate DEBUG output");
40 
41  USE_NEWAMP_4WALKCORR = 1;
42  gPARMS->SetDefaultParameter("TOF:USE_NEWAMP_4WALKCORR", USE_NEWAMP_4WALKCORR,
43  "Use Signal Amplitude for NEW walk correction with two fit functions");
44  USE_AMP_4WALKCORR = 0;
45  gPARMS->SetDefaultParameter("TOF:USE_AMP_4WALKCORR", USE_AMP_4WALKCORR,
46  "Use Signal Amplitude for walk correction rather than Integral");
47 
48  USE_NEW_4WALKCORR = 0;
49  gPARMS->SetDefaultParameter("TOF:USE_NEW_4WALKCORR", USE_NEW_4WALKCORR,
50  "Use NEW walk correction function with 4 parameters");
51 
52  DELTA_T_ADC_TDC_MAX = 20.0; // ns
53  // DELTA_T_ADC_TDC_MAX = 30.0; // ns, value based on the studies from cosmic events
54  gPARMS->SetDefaultParameter("TOF:DELTA_T_ADC_TDC_MAX", DELTA_T_ADC_TDC_MAX,
55  "Maximum difference in ns between a (calibrated) fADC time and F1TDC time for them to be matched in a single hit");
56 
57  int analyze_cosmic_data = 0;
58  gPARMS->SetDefaultParameter("TOF:COSMIC_DATA", analyze_cosmic_data,
59  "Special settings for analysing cosmic data");
60  if(analyze_cosmic_data > 0)
61  COSMIC_DATA = true;
62 
63  CHECK_FADC_ERRORS = true;
64  gPARMS->SetDefaultParameter("TOF:CHECK_FADC_ERRORS", CHECK_FADC_ERRORS, "Set to 1 to reject hits with fADC250 errors, ser to 0 to keep these hits");
65 
66 
67  /// Set basic conversion constants
68  a_scale = 0.2/5.2E5;
69  t_scale = 0.0625; // 62.5 ps/count
70  t_base = 0.; // ns
71  t_base_tdc = 0.; // ns
72 
73  if(COSMIC_DATA)
74  // Hardcoding of 110 taken from cosmics events
75  tdc_adc_time_offset = 110.;
76  else
77  tdc_adc_time_offset = 0.;
78 
79  // default values, will override from DTOFGeometry
80  TOF_NUM_PLANES = 2;
81  TOF_NUM_BARS = 44;
82 
83  return NOERROR;
84 }
85 
86 //------------------
87 // brun
88 //------------------
89 jerror_t DTOFHit_factory::brun(jana::JEventLoop *eventLoop, int32_t runnumber)
90 {
91  // Only print messages for one thread whenever run number change
92  static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;
93  static set<int> runs_announced;
94  pthread_mutex_lock(&print_mutex);
95  bool print_messages = false;
96  if(runs_announced.find(runnumber) == runs_announced.end()){
97  print_messages = true;
98  runs_announced.insert(runnumber);
99  }
100  pthread_mutex_unlock(&print_mutex);
101 
102  // read in geometry information
103  vector<const DTOFGeometry*> tofGeomVect;
104  eventLoop->Get( tofGeomVect );
105  if(tofGeomVect.size()<1) return OBJECT_NOT_AVAILABLE;
106  const DTOFGeometry& tofGeom = *(tofGeomVect[0]);
107 
108  TOF_NUM_PLANES = tofGeom.Get_NPlanes();
109  TOF_NUM_BARS = tofGeom.Get_NBars();
110 
111  /// Read in calibration constants
112  vector<double> raw_adc_pedestals;
113  vector<double> raw_adc_gains;
114  vector<double> raw_adc_offsets;
115  vector<double> raw_tdc_offsets;
116  vector<double> raw_adc2E;
117 
118  if(print_messages) jout << "In DTOFHit_factory, loading constants..." << endl;
119 
120  // load timing cut values
121  vector<double> time_cut_values;
122  if(eventLoop->GetCalib("/TOF/HitTimeCut", time_cut_values)){
123  jout << "Error loading /TOF/HitTimeCut SET DEFUALT to 0 and 100!" << endl;
124  TimeCenterCut = 0.;
125  TimeWidthCut = 100.;
126  } else {
127  double loli = time_cut_values[0];
128  double hili = time_cut_values[1];
129  TimeCenterCut = hili - (hili-loli)/2.;
130  TimeWidthCut = (hili-loli)/2.;
131  //jout<<"TOF Timing Cuts for PRUNING: "<<TimeCenterCut<<" +/- "<<TimeWidthCut<<endl;
132  }
133 
134  // load scale factors
135  map<string,double> scale_factors;
136  if(eventLoop->GetCalib("/TOF/digi_scales", scale_factors))
137  jout << "Error loading /TOF/digi_scales !" << endl;
138  if( scale_factors.find("TOF_ADC_ASCALE") != scale_factors.end() ) {
139  ; //a_scale = scale_factors["TOF_ADC_ASCALE"];
140  } else {
141  jerr << "Unable to get TOF_ADC_ASCALE from /TOF/digi_scales !" << endl;
142  }
143  if( scale_factors.find("TOF_ADC_TSCALE") != scale_factors.end() ) {
144  ; //t_scale = scale_factors["TOF_ADC_TSCALE"];
145  } else {
146  jerr << "Unable to get TOF_ADC_TSCALE from /TOF/digi_scales !" << endl;
147  }
148 
149  // load base time offset
150  map<string,double> base_time_offset;
151  if (eventLoop->GetCalib("/TOF/base_time_offset",base_time_offset))
152  jout << "Error loading /TOF/base_time_offset !" << endl;
153  if (base_time_offset.find("TOF_BASE_TIME_OFFSET") != base_time_offset.end())
154  t_base = base_time_offset["TOF_BASE_TIME_OFFSET"];
155  else
156  jerr << "Unable to get TOF_BASE_TIME_OFFSET from /TOF/base_time_offset !" << endl;
157 
158  if (base_time_offset.find("TOF_TDC_BASE_TIME_OFFSET") != base_time_offset.end())
159  t_base_tdc = base_time_offset["TOF_TDC_BASE_TIME_OFFSET"];
160  else
161  jerr << "Unable to get TOF_TDC_BASE_TIME_OFFSET from /TOF/base_time_offset !" << endl;
162 
163  // load constant tables
164  if(eventLoop->GetCalib("TOF/pedestals", raw_adc_pedestals))
165  jout << "Error loading /TOF/pedestals !" << endl;
166  if(eventLoop->GetCalib("TOF/gains", raw_adc_gains))
167  jout << "Error loading /TOF/gains !" << endl;
168  if(eventLoop->GetCalib("TOF/adc_timing_offsets", raw_adc_offsets))
169  jout << "Error loading /TOF/adc_timing_offsets !" << endl;
170 
171  if (USE_NEWAMP_4WALKCORR){
172 
173  if(eventLoop->GetCalib("TOF/timing_offsets_NEWAMP", raw_tdc_offsets)){
174 
175  jout<<"\033[1;31m"; // red text";
176  jout<< "Error loading /TOF/timing_offsets_NEWAMP !\033[0m" << endl;
177 
178  USE_NEWAMP_4WALKCORR = 0;
179  jout << "\033[1;31m"; // red text again";
180  jout << "Try to resort back to old calibration table /TOF/timing_offsets !\033[0m" << endl;
181  if(eventLoop->GetCalib("TOF/timing_offsets", raw_tdc_offsets)){
182  jout << "Error loading /TOF/timing_offsets !" << endl;
183  } else {
184  jout<<"OK Found!"<<endl;
185  }
186  if(eventLoop->GetCalib("TOF/timewalk_parms", timewalk_parameters))
187  jout << "Error loading /TOF/timewalk_parms !" << endl;
188 
189  } else { // timing offsets for NEWAMP exist, get also the walk parameters
190 
191  if(eventLoop->GetCalib("TOF/timewalk_parms_NEWAMP", timewalk_parameters_NEWAMP))
192  jout << "Error loading /TOF/timewalk_parms_NEWAMP !" << endl;
193 
194  }
195 
196 
197  } else if (USE_AMP_4WALKCORR){
198  if(eventLoop->GetCalib("TOF/timewalk_parms_AMP", timewalk_parameters_AMP))
199  jout << "Error loading /TOF/timewalk_parms_AMP !" << endl;
200  if(eventLoop->GetCalib("TOF/timing_offsets", raw_tdc_offsets))
201  jout << "Error loading /TOF/timing_offsets !" << endl;
202  } else if (USE_NEW_4WALKCORR){
203  if(eventLoop->GetCalib("TOF/timewalk_parms_NEW", timewalk_parameters_NEW))
204  jout << "Error loading /TOF/timewalk_parms_NEW !" << endl;
205  if(eventLoop->GetCalib("TOF/timing_offsets", raw_tdc_offsets))
206  jout << "Error loading /TOF/timing_offsets !" << endl;
207  } else {
208  if(eventLoop->GetCalib("TOF/timewalk_parms", timewalk_parameters))
209  jout << "Error loading /TOF/timewalk_parms !" << endl;
210  if(eventLoop->GetCalib("TOF/timing_offsets", raw_tdc_offsets))
211  jout << "Error loading /TOF/timing_offsets !" << endl;
212  }
213 
214 
215  FillCalibTable(adc_pedestals, raw_adc_pedestals, tofGeom);
216  FillCalibTable(adc_gains, raw_adc_gains, tofGeom);
217  FillCalibTable(adc_time_offsets, raw_adc_offsets, tofGeom);
218  FillCalibTable(tdc_time_offsets, raw_tdc_offsets, tofGeom);
219 
220 
221  if(eventLoop->GetCalib("TOF/adc2E", raw_adc2E))
222  jout << "Error loading /TOF/adc2E !" << endl;
223 
224  // make sure we have one entry per channel
225  adc2E.resize(TOF_NUM_PLANES*TOF_NUM_BARS*2);
226  for (unsigned int n=0; n<raw_adc2E.size(); n++){
227  adc2E[n] = raw_adc2E[n];
228  }
229 
230  /*
231  CheckCalibTable(adc_pedestals,"/TOF/pedestals");
232  CheckCalibTable(adc_gains,"/TOF/gains");
233  CheckCalibTable(adc_time_offsets,"/TOF/adc_timing_offsets");
234  CheckCalibTable(tdc_time_offsets,"/TOF/timing_offsets");
235  */
236 
237  return NOERROR;
238 }
239 
240 //------------------
241 // evnt
242 //------------------
243 jerror_t DTOFHit_factory::evnt(JEventLoop *loop, uint64_t eventnumber)
244 {
245  /// Generate DTOFHit object for each DTOFDigiHit object.
246  /// This is where the first set of calibration constants
247  /// is applied to convert from digitzed units into natural
248  /// units.
249  ///
250  /// Note that this code does NOT get called for simulated
251  /// data in HDDM format. The HDDM event source will copy
252  /// the precalibrated values directly into the _data vector.
253 
254  const DTTabUtilities* locTTabUtilities = NULL;
255  loop->GetSingle(locTTabUtilities);
256 
257  // First, make hits out of all fADC250 hits
258  vector<const DTOFDigiHit*> digihits;
259  loop->Get(digihits);
260  for(unsigned int i=0; i<digihits.size(); i++){
261  const DTOFDigiHit *digihit = digihits[i];
262 
263  // Error checking for pre-Fall 2016 firmware
264  if(digihit->datasource == 1) {
265  // There is a slight difference between Mode 7 and 8 data
266  // The following condition signals an error state in the flash algorithm
267  // Do not make hits out of these
268  const Df250PulsePedestal* PPobj = NULL;
269  digihit->GetSingle(PPobj);
270  if (PPobj != NULL) {
271  if (PPobj->pedestal == 0 || PPobj->pulse_peak == 0) continue;
272  } else
273  continue;
274 
275  //if (digihit->pulse_time == 0) continue; // Should already be caught
276  }
277 
278  if(CHECK_FADC_ERRORS && !locTTabUtilities->CheckFADC250_NoErrors(digihit->QF)){
279 
280  if (TOF_DEBUG){
281  vector <const Df250PulseData *> pulses;
282  digihit->Get(pulses);
283  const Df250PulseData *p = pulses[0];
284 
285  cout<<"1: "<<eventnumber<<" P/B/E "<<digihit->plane<<"/"<<digihit->bar<<"/"<<digihit->end
286  <<" :::> I/Ped/P/T "<<digihit->pulse_integral<<"/"<<digihit->pedestal<<"/"<<digihit->pulse_peak<<"/"<<digihit->pulse_time
287  <<" QF: 0x"<<hex<<digihit->QF<<dec
288  <<" roc/slot/chan "<<p->rocid<<"/"<<p->slot<<"/"<<p->channel
289  << endl;
290  }
291 
292  //continue;
293 
294  }
295  // Initialize pedestal to one found in CCDB, but override it
296  // with one found in event if is available (?)
297  // For now, only keep events with a correct pedestal
298  double pedestal = GetConstant(adc_pedestals, digihit); // get mean pedestal from DB in case we need it
299  double nsamples_integral = digihit->nsamples_integral;
300  double nsamples_pedestal = digihit->nsamples_pedestal;
301 
302  // nsamples_pedestal should always be positive for valid data - err on the side of caution for now
303  if(nsamples_pedestal == 0) {
304  jerr << "DTOFDigiHit with nsamples_pedestal == 0 ! Event = " << eventnumber << endl;
305  continue;
306  }
307 
308  double pedestal4Amp = pedestal;
309  int AlreadyDone = 0;
310  if( (digihit->pedestal>0) && locTTabUtilities->CheckFADC250_PedestalOK(digihit->QF) ) {
311  pedestal = digihit->pedestal * (double)(nsamples_integral)/(double)(nsamples_pedestal); // overwrite pedestal
312  } else {
313 
314  if (TOF_DEBUG){
315  vector <const Df250PulseData *> pulses;
316  digihit->Get(pulses);
317  const Df250PulseData *p = pulses[0];
318 
319  cout<<"2: "<<eventnumber<<" P/B/E "<<digihit->plane<<"/"<<digihit->bar<<"/"<<digihit->end
320  <<" :::> I/Ped/P/T "<<digihit->pulse_integral<<"/"<<digihit->pedestal<<"/"<<digihit->pulse_peak<<"/"<<digihit->pulse_time
321  <<" QF: 0x"<<hex<<digihit->QF<<dec
322  <<" roc/slot/chan "<<p->rocid<<"/"<<p->slot<<"/"<<p->channel
323  << endl;
324 
325  }
326 
327  pedestal *= (double)(nsamples_integral);
328  pedestal4Amp *= (double)nsamples_pedestal;
329  AlreadyDone = 1;
330  //continue;
331  }
332 
333  if ((digihit->pulse_peak == 0) && (!AlreadyDone)){
334  pedestal = pedestal4Amp * (double)(nsamples_integral);
335  pedestal4Amp *= (double)nsamples_pedestal;
336  }
337 
338  // Apply calibration constants here
339  double A = (double)digihit->pulse_integral;
340  double T = (double)digihit->pulse_time;
341  T = t_scale * T - GetConstant(adc_time_offsets, digihit) + t_base;
342  double dA = A - pedestal;
343 
344  if (dA<0) {
345 
346  if (TOF_DEBUG){
347 
348  vector <const Df250PulseData *> pulses;
349  digihit->Get(pulses);
350  const Df250PulseData *p = pulses[0];
351 
352  cout<<"3: "<<eventnumber<<" "<<dA<<" "<<digihit->plane<<" "<<digihit->bar<<" "<<digihit->end
353  <<" :::> "<<digihit->pulse_integral<<" "<<digihit->pedestal<<" "<<digihit->pulse_peak<<" "<<digihit->pulse_time
354  <<" roc/slot/chan "<<p->rocid<<"/"<<p->slot<<"/"<<p->channel
355  << endl;
356 
357  }
358  // ok if Integral is below zero this is a good hint that we can not use this hit!
359  continue;
360  }
361  // apply Time cut to prune out of time hits
362  if (TMath::Abs(T-TimeCenterCut)> TimeWidthCut ) continue;
363 
364  DTOFHit *hit = new DTOFHit;
365  hit->plane = digihit->plane;
366  hit->bar = digihit->bar;
367  hit->end = digihit->end;
368  hit->dE=dA; // this will be scaled to energy units later
369  hit->Amp = (float)digihit->pulse_peak - pedestal4Amp/(float)nsamples_pedestal;
370 
371  if (hit->Amp<1){ // this happens if pulse_peak is reported as zero, resort to use scaled Integral value
372  hit->Amp = dA*0.163;
373  }
374 
375  if(COSMIC_DATA)
376  hit->dE = (A - 55*pedestal); // value of 55 is taken from (NSB,NSA)=(10,45) in the confg file
377 
378  hit->t_TDC=numeric_limits<double>::quiet_NaN();
379  hit->t_fADC=T;
380  hit->t = hit->t_fADC; // set initial time to the ADC time, in case there's no matching TDC hit
381 
382  hit->has_fADC=true;
383  hit->has_TDC=false;
384 
385  /*
386  cout << "TOF ADC hit = (" << hit->plane << "," << hit->bar << "," << hit->end << ") "
387  << t_scale << " " << T << " "
388  << GetConstant(adc_time_offsets, digihit) << " "
389  << t_scale*GetConstant(adc_time_offsets, digihit) << " " << hit->t << endl;
390  */
391 
392  hit->AddAssociatedObject(digihit);
393 
394  _data.push_back(hit);
395  }
396 
397  //Get the TDC hits
398  vector<const DTOFTDCDigiHit*> tdcdigihits;
399  loop->Get(tdcdigihits);
400 
401  // Next, loop over TDC hits, matching them to the
402  // existing fADC hits where possible and updating
403  // their time information. If no match is found, then
404  // create a new hit with just the TDC info.
405  for(unsigned int i=0; i<tdcdigihits.size(); i++)
406  {
407  const DTOFTDCDigiHit *digihit = tdcdigihits[i];
408 
409  // Apply calibration constants here
410  double T = locTTabUtilities->Convert_DigiTimeToNs_CAEN1290TDC(digihit);
411  T += t_base_tdc - GetConstant(tdc_time_offsets, digihit) + tdc_adc_time_offset;
412 
413  // do not consider Time hits away from coincidence peak Note: This cut should be wide for uncalibrated data!!!!!
414  if (TMath::Abs(T-TimeCenterCut)> TimeWidthCut ) continue;
415 
416  /*
417  cout << "TOF TDC hit = (" << digihit->plane << "," << digihit->bar << "," << digihit->end << ") "
418  << T << " " << GetConstant(tdc_time_offsets, digihit) << endl;
419  */
420 
421  // Look for existing hits to see if there is a match
422  // or create new one if there is no match
423  DTOFHit *hit = FindMatch(digihit->plane, digihit->bar, digihit->end, T);
424  //DTOFHit *hit = FindMatch(digihit->plane, hit->bar, hit->end, T);
425  if(!hit){
426  continue; // Do not use unmatched TDC hits
427  /*
428  hit = new DTOFHit;
429  hit->plane = digihit->plane;
430  hit->bar = digihit->bar;
431  hit->end = digihit->end;
432  hit->dE = 0.0;
433  hit->Amp = 0.0;
434  hit->t_fADC=numeric_limits<double>::quiet_NaN();
435  hit->has_fADC=false;
436 
437  _data.push_back(hit);
438  */
439  } else if (hit->has_TDC) { // this tof ADC hit has already a matching TDC, make new tof ADC hit
440  DTOFHit *newhit = new DTOFHit;
441  newhit->plane = hit->plane;
442  newhit->bar = hit->bar;
443  newhit->end = hit->end;
444  newhit->dE = hit->dE;
445  newhit->Amp = hit->Amp;
446  newhit->t_fADC = hit->t_fADC;
447  newhit->has_fADC = hit->has_fADC;
448  newhit->t_TDC=numeric_limits<double>::quiet_NaN();
449  newhit->t = hit->t_fADC; // set initial time to the ADC time, in case there's no matching TDC hit
450  newhit->has_TDC=false;
451  newhit->AddAssociatedObject(digihit);
452  _data.push_back(newhit);
453  hit = newhit;
454  }
455  hit->has_TDC=true;
456  hit->t_TDC=T;
457 
458  if (hit->dE>0.){
459 
460  // time walk correction
461  // Note at this point the dE value is still in ADC units
462  double tcorr = 0.;
463  if (USE_AMP_4WALKCORR) {
464  // use amplitude instead of integral
465  tcorr = CalcWalkCorrAmplitude(hit);
466 
467  } else if (USE_NEW_4WALKCORR) {
468  // new functional form with 4 parameter but still using integral
469  tcorr = CalcWalkCorrNEW(hit);
470 
471  } else if (USE_NEWAMP_4WALKCORR) {
472  // new functional form with 2 functions and 4 parameter using amplitude
473  tcorr = CalcWalkCorrNEWAMP(hit);
474 
475  } else {
476  // use integral
477  tcorr = CalcWalkCorrIntegral(hit);
478 
479  }
480 
481  T -= tcorr;
482  }
483  hit->t=T;
484 
485  hit->AddAssociatedObject(digihit);
486  }
487 
488  // Apply calibration constants to convert pulse integrals to energy units
489  for (unsigned int i=0;i<_data.size();i++){
490  int id=2*TOF_NUM_BARS*_data[i]->plane + TOF_NUM_BARS*_data[i]->end + _data[i]->bar-1;
491  _data[i]->dE *= adc2E[id];
492  //cout<<id<<" "<< adc2E[id]<<" "<<_data[i]->dE<<endl;
493  }
494 
495  return NOERROR;
496 }
497 
498 //------------------
499 // FindMatch
500 //------------------
501 DTOFHit* DTOFHit_factory::FindMatch(int plane, int bar, int end, double T)
502 {
503  DTOFHit* best_match = NULL;
504 
505  // Loop over existing hits (from fADC) and look for a match
506  // in both the sector and the time.
507  for(unsigned int i=0; i<_data.size(); i++){
508  DTOFHit *hit = _data[i];
509 
510  if(!isfinite(hit->t_fADC)) continue; // only match to fADC hits, not bachelor TDC hits
511  if(hit->plane != plane) continue;
512  if(hit->bar != bar) continue;
513  if(hit->end != end) continue;
514 
515  //double delta_T = fabs(hit->t - T);
516  double delta_T = fabs(T - hit->t);
517  if(delta_T > DELTA_T_ADC_TDC_MAX) continue;
518 
519  // if there are multiple hits, pick the one that is closest in time
520  if(best_match != NULL) {
521  if(delta_T < fabs(best_match->t - T))
522  best_match = hit;
523  } else {
524  best_match = hit;
525  }
526 
527  }
528 
529  return best_match;
530 }
531 
532 //------------------
533 // erun
534 //------------------
535 jerror_t DTOFHit_factory::erun(void)
536 {
537  return NOERROR;
538 }
539 
540 //------------------
541 // fini
542 //------------------
543 jerror_t DTOFHit_factory::fini(void)
544 {
545  return NOERROR;
546 }
547 
548 
549 //------------------
550 // FillCalibTable
551 //------------------
552 void DTOFHit_factory::FillCalibTable(tof_digi_constants_t &table, vector<double> &raw_table,
553  const DTOFGeometry &tofGeom)
554 {
555  char str[256];
556  int channel = 0;
557 
558  // reset the table before filling it
559  table.clear();
560 
561  for(int plane=0; plane<tofGeom.Get_NPlanes(); plane++) {
562  int plane_index=2*tofGeom.Get_NBars()*plane;
563  table.push_back( vector< pair<double,double> >(tofGeom.Get_NBars()) );
564  for(int bar=0; bar<tofGeom.Get_NBars(); bar++) {
565  table[plane][bar]
566  = pair<double,double>(raw_table[plane_index+bar],
567  raw_table[plane_index+tofGeom.Get_NBars()+bar]);
568  channel+=2;
569  }
570  }
571 
572  // check to make sure that we loaded enough channels
573  if(channel != TOF_MAX_CHANNELS) {
574  sprintf(str, "Not enough channels for TOF table! channel=%d (should be %d)",
575  channel, TOF_MAX_CHANNELS);
576  cerr << str << endl;
577  throw JException(str);
578  }
579 }
580 
581 
582 //------------------------------------
583 // GetConstant
584 // Allow a few different interfaces
585 // NOTE: LoadGeometry() must be called before calling these functions
586 //
587 // TOF Geometry as defined in the Translation Table:
588 // plane = 0-1
589 // bar = 1-44
590 // end = 0-1
591 // Note the different counting schemes used
592 //------------------------------------
593 const double DTOFHit_factory::GetConstant( const tof_digi_constants_t &the_table,
594  const int in_plane, const int in_bar, const int in_end) const
595 {
596  char str[256];
597 
598  if( (in_plane < 0) || (in_plane > TOF_NUM_PLANES)) {
599  sprintf(str, "Bad module # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", in_plane, TOF_NUM_PLANES);
600  cerr << str << endl;
601  throw JException(str);
602  }
603  if( (in_bar <= 0) || (in_bar > TOF_NUM_BARS)) {
604  sprintf(str, "Bad layer # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", in_bar, TOF_NUM_BARS);
605  cerr << str << endl;
606  throw JException(str);
607  }
608  if( (in_end != 0) && (in_end != 1) ) {
609  sprintf(str, "Bad end # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 0-1", in_end);
610  cerr << str << endl;
611  throw JException(str);
612  }
613 
614  // we have two ends, indexed as 0/1
615  // could be north/south or up/down depending on the bar orientation
616  if(in_end == 0) {
617  return the_table[in_plane][in_bar].first;
618  } else {
619  return the_table[in_plane][in_bar].second;
620  }
621 }
622 
623 const double DTOFHit_factory::GetConstant( const tof_digi_constants_t &the_table,
624  const DTOFHit *in_hit) const
625 {
626  char str[256];
627 
628  if( (in_hit->plane < 0) || (in_hit->plane > TOF_NUM_PLANES)) {
629  sprintf(str, "Bad module # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", in_hit->plane, TOF_NUM_PLANES);
630  cerr << str << endl;
631  throw JException(str);
632  }
633  if( (in_hit->bar <= 0) || (in_hit->bar > TOF_NUM_BARS)) {
634  sprintf(str, "Bad layer # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", in_hit->bar, TOF_NUM_BARS);
635  cerr << str << endl;
636  throw JException(str);
637  }
638  if( (in_hit->end != 0) && (in_hit->end != 1) ) {
639  sprintf(str, "Bad end # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 0-1", in_hit->end);
640  cerr << str << endl;
641  throw JException(str);
642  }
643 
644  // we have two ends, indexed as 0/1
645  // could be north/south or up/down depending on the bar orientation
646  if(in_hit->end == 0) {
647  return the_table[in_hit->plane][in_hit->bar-1].first;
648  } else {
649  return the_table[in_hit->plane][in_hit->bar-1].second;
650  }
651 }
652 
653 const double DTOFHit_factory::GetConstant( const tof_digi_constants_t &the_table,
654  const DTOFDigiHit *in_digihit) const
655 {
656  char str[256];
657 
658  if( (in_digihit->plane < 0) || (in_digihit->plane > TOF_NUM_PLANES)) {
659  sprintf(str, "Bad module # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", in_digihit->plane, TOF_NUM_PLANES);
660  cerr << str << endl;
661  throw JException(str);
662  }
663  if( (in_digihit->bar <= 0) || (in_digihit->bar > TOF_NUM_BARS)) {
664  sprintf(str, "Bad layer # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", in_digihit->bar, TOF_NUM_BARS);
665  cerr << str << endl;
666  throw JException(str);
667  }
668  if( (in_digihit->end != 0) && (in_digihit->end != 1) ) {
669  sprintf(str, "Bad end # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 0-1", in_digihit->end);
670  cerr << str << endl;
671  throw JException(str);
672  }
673 
674  // we have two ends, indexed as 0/1
675  // could be north/south or up/down depending on the bar orientation
676  if(in_digihit->end == 0) {
677  return the_table[in_digihit->plane][in_digihit->bar-1].first;
678  } else {
679  return the_table[in_digihit->plane][in_digihit->bar-1].second;
680  }
681 }
682 
683 const double DTOFHit_factory::GetConstant( const tof_digi_constants_t &the_table,
684  const DTOFTDCDigiHit *in_digihit) const
685 {
686  char str[256];
687 
688  if( (in_digihit->plane < 0) || (in_digihit->plane > TOF_NUM_PLANES)) {
689  sprintf(str, "Bad module # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", in_digihit->plane, TOF_NUM_PLANES);
690  cerr << str << endl;
691  throw JException(str);
692  }
693  if( (in_digihit->bar <= 0) || (in_digihit->bar > TOF_NUM_BARS)) {
694  sprintf(str, "Bad layer # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", in_digihit->bar, TOF_NUM_BARS);
695  cerr << str << endl;
696  throw JException(str);
697  }
698  if( (in_digihit->end != 0) && (in_digihit->end != 1) ) {
699  sprintf(str, "Bad end # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 0-1", in_digihit->end);
700  cerr << str << endl;
701  throw JException(str);
702  }
703 
704  // we have two ends, indexed as 0/1
705  // could be north/south or up/down depending on the bar orientation
706  if(in_digihit->end == 0) {
707  return the_table[in_digihit->plane][in_digihit->bar-1].first;
708  } else {
709  return the_table[in_digihit->plane][in_digihit->bar-1].second;
710  }
711 }
712 
713 /*
714  const double DTOFHit_factory::GetConstant( const tof_digi_constants_t &the_table,
715  const DTranslationTable *ttab,
716  const int in_rocid, const int in_slot, const int in_channel) const {
717 
718  char str[256];
719 
720  DTranslationTable::csc_t daq_index = { in_rocid, in_slot, in_channel };
721  DTranslationTable::DChannelInfo channel_info = ttab->GetDetectorIndex(daq_index);
722 
723  if( (channel_info.tof.plane <= 0)
724  || (channel_info.tof.plane > static_cast<unsigned int>(TOF_NUM_PLANES))) {
725  sprintf(str, "Bad plane # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", channel_info.tof.plane, TOF_NUM_PLANES);
726  cerr << str << endl;
727  throw JException(str);
728  }
729  if( (channel_info.tof.bar <= 0)
730  || (channel_info.tof.bar > static_cast<unsigned int>(TOF_NUM_BARS))) {
731  sprintf(str, "Bad bar # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 1-%d", channel_info.tof.bar, TOF_NUM_BARS);
732  cerr << str << endl;
733  throw JException(str);
734  }
735  if( (channel_info.tof.end != 0) && (channel_info.tof.end != 1) ) {
736  sprintf(str, "Bad end # requested in DTOFHit_factory::GetConstant()! requested=%d , should be 0-1", channel_info.tof.end);
737  cerr << str << endl;
738  throw JException(str);
739  }
740 
741  int the_cell = DTOFGeometry::cellId(channel_info.tof.module,
742  channel_info.tof.layer,
743  channel_info.tof.sector);
744 
745  if(channel_info.tof.end == DTOFGeometry::kUpstream) {
746 // handle the upstream end
747 return the_table.at(the_cell).first;
748 } else {
749 // handle the downstream end
750 return the_table.at(the_cell).second;
751 }
752 }
753 */
755  int id=2*TOF_NUM_BARS*hit->plane+TOF_NUM_BARS*hit->end+hit->bar-1;
756  double A=hit->dE;
757  double C0=timewalk_parameters[id][1];
758  double C1=timewalk_parameters[id][1];
759  double C2=timewalk_parameters[id][2];
760  double A0=timewalk_parameters[id][3];
761 
762  double a1 = C0 + C1*pow(A,C2);
763  double a2 = C0 + C1*pow(A0,C2);
764 
765  float corr = a1 - a2;
766 
767  //cout<<id<<" "<<A<<" "<<a1<<" "<<a2<<" "<<corr<<endl;
768 
769  return corr;
770 
771 
772 }
773 
774 
776 
777  int id=2*TOF_NUM_BARS*hit->plane+TOF_NUM_BARS*hit->end+hit->bar-1;
778  double A = hit->Amp;
779  double C0 = timewalk_parameters_AMP[id][0];
780  double C1 = timewalk_parameters_AMP[id][1];
781  double C2 = timewalk_parameters_AMP[id][2];
782  double C3 = timewalk_parameters_AMP[id][3];
783 
784  double hookx = timewalk_parameters_AMP[id][4];
785  double refx = timewalk_parameters_AMP[id][5];
786  double val_at_ref = C0 + C1*pow(refx,C2);
787  double val_at_hook = C0 + C1*pow(hookx,C2);
788  double slope = (val_at_hook - C3)/hookx;
789  if (refx>hookx){
790  val_at_ref = slope * refx + C3;
791  }
792  double val_at_A = C0 + C1*pow(A,C2);
793  if (A>hookx){
794  val_at_A = slope * A + C3;
795  }
796 
797  float corr = val_at_A - val_at_ref;
798 
799  //cout<<id<<" "<<val_at_A<<" "<<val_at_ref<<" "<<corr<<endl;
800 
801  return corr;
802 
803 }
804 
805 
807 
808  int id=2*TOF_NUM_BARS*hit->plane+TOF_NUM_BARS*hit->end+hit->bar-1;
809  double ADC=hit->dE;
810 
811  if (ADC<1.){
812  return 0;
813  }
814 
815  double A = timewalk_parameters_NEW[id][0];
816  double B = timewalk_parameters_NEW[id][1];
817  double C = timewalk_parameters_NEW[id][2];
818  double D = timewalk_parameters_NEW[id][3];
819  double ADCREF = timewalk_parameters_NEW[id][4];
820 
821  if (ADC>20000.){
822  ADC = 20000.;
823  }
824  double a1 = A + B*pow(ADC,-0.5) + C*pow(ADC,-0.33) + D*pow(ADC,-0.2);
825  double a2 = A + B*pow(ADCREF,-0.5) + C*pow(ADCREF,-0.33) + D*pow(ADCREF,-0.2);
826 
827 
828  float corr = a1 - a2;
829 
830  //cout<<id<<" "<<a1<<" "<<a2<<" "<<corr<<endl;
831 
832  return corr;
833 
834 }
835 
837 
838  int id=2*TOF_NUM_BARS*hit->plane+TOF_NUM_BARS*hit->end+hit->bar-1;
839  double ADC=hit->Amp;
840  if (ADC<50.){
841  return 0;
842  }
843  double loc = timewalk_parameters_NEWAMP[id][8];
844  int offset = 0;
845  if (ADC>loc){
846  offset = 4;
847  }
848  double A = timewalk_parameters_NEWAMP[id][0+offset];
849  double B = timewalk_parameters_NEWAMP[id][1+offset];
850  double C = timewalk_parameters_NEWAMP[id][2+offset];
851  double D = timewalk_parameters_NEWAMP[id][3+offset];
852 
853  double ADCREF = timewalk_parameters_NEWAMP[id][9];
854  double A2 = timewalk_parameters_NEWAMP[id][4];
855  double B2 = timewalk_parameters_NEWAMP[id][5];
856  double C2 = timewalk_parameters_NEWAMP[id][6];
857  double D2 = timewalk_parameters_NEWAMP[id][7];
858 
859  double a1 = A + B*pow(ADC,-0.5) + C*pow(ADC,-0.33) + D*pow(ADC,-0.2);
860  double a2 = A2 + B2*pow(ADCREF,-0.5) + C2*pow(ADCREF,-0.33) + D2*pow(ADCREF,-0.2);
861 
862  if (ADC>4095){
863  a1 += 0.6; // overflow hits are off by about 0.6ns to the regular curve.
864  }
865 
866  float corr = a1 - a2;
867 
868  //cout<<id<<" "<<ADC<<" "<<a1<<" "<<a2<<" "<<corr<<endl;
869 
870  return corr;
871 
872 }
873 
jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber)
vector< vector< pair< double, double > > > tof_digi_constants_t
#define A0
Definition: src/md5.cpp:22
bool CheckFADC250_NoErrors(uint32_t QF) const
int end
Definition: DTOFHit.h:23
DTOFHit * FindMatch(int plane, int bar, int end, double T)
char str[256]
uint32_t pedestal
pedestal info used by FPGA (if any)
Definition: DTOFDigiHit.h:23
int plane
Definition: DTOFHit.h:21
static bool COSMIC_DATA
bool has_fADC
Definition: DTOFHit.h:29
sprintf(text,"Post KinFit Cut")
#define C0
Definition: src/md5.cpp:24
double Convert_DigiTimeToNs_CAEN1290TDC(const JObject *locTDCDigiHit) const
uint32_t nsamples_integral
number of samples used in integral
Definition: DTOFDigiHit.h:25
float t
Definition: DTOFHit.h:28
int bar
bar number
uint32_t pulse_peak
from Pulse Pedestal Data word
int Get_NPlanes() const
Definition: DTOFGeometry.h:29
jerror_t erun(void)
int Get_NBars() const
Definition: DTOFGeometry.h:33
float t_TDC
Definition: DTOFHit.h:27
jerror_t init(void)
float Amp
Definition: DTOFHit.h:25
double CalcWalkCorrAmplitude(DTOFHit *hit)
int TOF_DEBUG
void FillCalibTable(tof_digi_constants_t &table, vector< double > &raw_table, const DTOFGeometry &tofGeom)
uint32_t nsamples_pedestal
number of samples used in pedestal
Definition: DTOFDigiHit.h:26
jerror_t fini(void)
bool has_TDC
Definition: DTOFHit.h:30
float t_fADC
Definition: DTOFHit.h:26
bool CheckFADC250_PedestalOK(uint32_t QF) const
vector< double > tdc_time_offsets
int end
left/right 0/1 or North/South 0/1
uint32_t channel
Definition: DDAQAddress.h:34
int bar
Definition: DTOFHit.h:22
static TH1I * pedestal[nChan]
double CalcWalkCorrNEWAMP(DTOFHit *hit)
uint32_t rocid
Definition: DDAQAddress.h:32
uint32_t pulse_time
identified pulse time as returned by FPGA algorithm
Definition: DTOFDigiHit.h:22
uint32_t pedestal
from Pulse Pedestal Data word
File: DTOFHit.h Created: Tue Jan 18 16:15:26 EST 2011 Creator: B. Zihlmann Purpose: Container class t...
Definition: DTOFHit.h:16
uint32_t pulse_peak
maximum sample in pulse
Definition: DTOFDigiHit.h:27
uint32_t QF
Quality Factor from FPGA algorithms.
Definition: DTOFDigiHit.h:24
int plane
plane (0: vertical, 1: horizontal)
double CalcWalkCorrNEW(DTOFHit *hit)
vector< double > adc_time_offsets
float dE
Definition: DTOFHit.h:24
const double GetConstant(const tof_digi_constants_t &the_table, const int in_plane, const int in_bar, const int in_end) const
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
uint32_t datasource
0=window raw data, 1=old(pre-Fall16) firmware, 2=Df250PulseData
Definition: DTOFDigiHit.h:29
double CalcWalkCorrIntegral(DTOFHit *hit)
uint32_t slot
Definition: DDAQAddress.h:33
uint32_t pulse_integral
identified pulse integral as returned by FPGA algorithm
Definition: DTOFDigiHit.h:21