Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTAGHHit_factory_Calib.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DTAGHHit_factory_Calib.cc
4 // Created: Wed Aug 3 12:55:19 EDT 2016
5 // Creator: nsparks (on Linux cua2.jlab.org 3.10.0-327.22.2.el7.x86_64 x86_64)
6 //
7 
8 
9 #include <iostream>
10 #include <iomanip>
11 #include <limits>
12 using namespace std;
13 
14 #include "DTAGHHit_factory_Calib.h"
15 #include "DTAGHDigiHit.h"
16 #include "DTAGHTDCDigiHit.h"
17 #include "TTAB/DTTabUtilities.h"
18 #include <DAQ/Df250PulseIntegral.h>
19 #include <DAQ/Df250PulsePedestal.h>
20 
21 using namespace jana;
22 
27 
28 //------------------
29 // init
30 //------------------
32 {
33  // set default config. parameters
34  DELTA_T_ADC_TDC_MAX = 10.0; // ns
35  gPARMS->SetDefaultParameter("TAGHHit:DELTA_T_ADC_TDC_MAX", DELTA_T_ADC_TDC_MAX,
36  "Maximum difference in ns between a (calibrated) fADC time and"
37  " F1TDC time for them to be matched in a single hit");
38  ADC_THRESHOLD = 200.0; // ADC counts
39  gPARMS->SetDefaultParameter("TAGHHit:ADC_THRESHOLD",ADC_THRESHOLD,
40  "pulse height threshold");
41 
42  CHECK_FADC_ERRORS = true;
43  gPARMS->SetDefaultParameter("TAGHHit:CHECK_FADC_ERRORS", CHECK_FADC_ERRORS, "Set to 1 to reject hits with fADC250 errors, ser to 0 to keep these hits");
44 
45  // initialize calibration constants
46  fadc_a_scale = 0;
47  fadc_t_scale = 0;
48  t_base = 0;
49  t_tdc_base=0;
50 
51  // calibration constants stored by counter index
52  for (int counter = 0; counter <= TAGH_MAX_COUNTER; ++counter) {
53  fadc_gains[counter] = 0;
54  fadc_pedestals[counter] = 0;
55  fadc_time_offsets[counter] = 0;
57  counter_quality[counter] = 0;
58  }
59 
60  return NOERROR;
61 }
62 
63 //------------------
64 // brun
65 //------------------
66 jerror_t DTAGHHit_factory_Calib::brun(jana::JEventLoop *eventLoop, int32_t runnumber)
67 {
68  // Only print messages for one thread whenever run number change
69  static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;
70  static set<int> runs_announced;
71  pthread_mutex_lock(&print_mutex);
72  bool print_messages = false;
73  if(runs_announced.find(runnumber) == runs_announced.end()){
74  print_messages = true;
75  runs_announced.insert(runnumber);
76  }
77  pthread_mutex_unlock(&print_mutex);
78 
79  /// set the base conversion scales
80  fadc_a_scale = 1.1; // pixels per count
81  fadc_t_scale = 0.0625; // ns per count
82  t_base = 0.; // ns
83 
84  if(print_messages) jout << "In DTAGHHit_factory, loading constants..." << std::endl;
85 
86  // load base time offset
87  map<string,double> base_time_offset;
88  if (eventLoop->GetCalib("/PHOTON_BEAM/hodoscope/base_time_offset",base_time_offset))
89  jout << "Error loading /PHOTON_BEAM/hodoscope/base_time_offset !" << endl;
90  if (base_time_offset.find("TAGH_BASE_TIME_OFFSET") != base_time_offset.end())
91  t_base = base_time_offset["TAGH_BASE_TIME_OFFSET"];
92  else
93  jerr << "Unable to get TAGH_BASE_TIME_OFFSET from /PHOTON_BEAM/hodoscope/base_time_offset !" << endl;
94 
95  if (base_time_offset.find("TAGH_TDC_BASE_TIME_OFFSET") != base_time_offset.end())
96  t_tdc_base = base_time_offset["TAGH_TDC_BASE_TIME_OFFSET"];
97  else
98  jerr << "Unable to get TAGH_TDC_BASE_TIME_OFFSET from /PHOTON_BEAM/hodoscope/base_time_offset !" << endl;
99 
100  if (load_ccdb_constants("fadc_gains", "gain", fadc_gains) &&
101  load_ccdb_constants("fadc_pedestals", "pedestal", fadc_pedestals) &&
102  load_ccdb_constants("fadc_time_offsets", "offset", fadc_time_offsets) &&
103  load_ccdb_constants("tdc_time_offsets", "offset", tdc_time_offsets) &&
104  load_ccdb_constants("counter_quality", "code", counter_quality) &&
105  load_ccdb_constants("tdc_timewalk", "c0", tdc_twalk_c0) &&
106  load_ccdb_constants("tdc_timewalk", "c1", tdc_twalk_c1) &&
107  load_ccdb_constants("tdc_timewalk", "c2", tdc_twalk_c2) &&
108  load_ccdb_constants("tdc_timewalk", "c3", tdc_twalk_c3))
109  {
110  return NOERROR;
111  }
112  return UNRECOVERABLE_ERROR;
113 }
114 
115 //------------------
116 // evnt
117 //------------------
118 jerror_t DTAGHHit_factory_Calib::evnt(JEventLoop *loop, uint64_t eventnumber)
119 {
120  /// Generate DTAGHHit object for each DTAGHDigiHit object.
121  /// This is where the first set of calibration constants
122  /// is applied to convert from digitzed units into natural
123  /// units.
124  ///
125  /// Note that this code does NOT get called for simulated
126  /// data in HDDM format. The HDDM event source will copy
127  /// the precalibrated values directly into the _data vector.
128 
129  // extract the TAGH geometry
130  vector<const DTAGHGeometry*> taghGeomVect;
131  eventLoop->Get( taghGeomVect );
132  if (taghGeomVect.size() < 1)
133  return OBJECT_NOT_AVAILABLE;
134  const DTAGHGeometry& taghGeom = *(taghGeomVect[0]);
135 
136  const DTTabUtilities* locTTabUtilities = nullptr;
137  loop->GetSingle(locTTabUtilities);
138 
139  // First loop over all TAGHDigiHits and make DTAGHHits out of them
140  vector<const DTAGHDigiHit*> digihits;
141  loop->Get(digihits);
142  for (unsigned int i=0; i < digihits.size(); i++) {
143  const DTAGHDigiHit *digihit = digihits[i];
144  int counter = digihit->counter_id;
145 
146  // throw away hits from bad or noisy counters
147  int quality = counter_quality[counter];
148  if (quality == k_counter_bad || quality == k_counter_noisy)
149  continue;
150 
151  // Throw away hits with firmware errors (post-summer 2016 firmware)
152  if(CHECK_FADC_ERRORS && !locTTabUtilities->CheckFADC250_NoErrors(digihit->QF))
153  continue;
154 
155  // Get pedestal, prefer associated event pedestal if it exists,
156  // otherwise, use the average pedestal from CCDB
157  double pedestal = fadc_pedestals[counter];
158  double nsamples_integral = (double)digihit->nsamples_integral;
159  double nsamples_pedestal = (double)digihit->nsamples_pedestal;
160 
161  // nsamples_pedestal should always be positive for valid data - err on the side of caution for now
162  if(nsamples_pedestal == 0) {
163  jerr << "DTAGHDigiHit with nsamples_pedestal == 0 ! Event = " << eventnumber << endl;
164  continue;
165  }
166 
167  // digihit->pedestal is the sum of "nsamples_pedestal" samples
168  // Calculate the average pedestal per sample
169  if ( (digihit->pedestal>0) && locTTabUtilities->CheckFADC250_PedestalOK(digihit->QF) ) {
170  pedestal = (double)digihit->pedestal/nsamples_pedestal;
171  }
172 
173  // Subtract pedestal from pulse peak
174  if (digihit->pulse_time == 0 || digihit->pedestal == 0 || digihit->pulse_peak == 0) continue;
175  double pulse_peak = digihit->pulse_peak - pedestal;
176 
177  // Subtract pedestal from pulse integral
178  double A = digihit->pulse_integral;
179  A -= pedestal*nsamples_integral;
180 
181  // Pulse height cut
182  if (pulse_peak < ADC_THRESHOLD) continue;
183 
184  DTAGHHit *hit = new DTAGHHit;
185  hit->counter_id = counter;
186  double Elow = taghGeom.getElow(counter);
187  double Ehigh = taghGeom.getEhigh(counter);
188  hit->E = (Elow + Ehigh)/2;
189 
190  // Apply calibration constants
191  double T = digihit->pulse_time;
192  hit->integral = A;
193  hit->pulse_peak = pulse_peak;
194  hit->npe_fadc = A * fadc_a_scale * fadc_gains[counter];
195  hit->time_fadc = T * fadc_t_scale - fadc_time_offsets[counter] + t_base;
196  hit->time_tdc = numeric_limits<double>::quiet_NaN();
197  hit->t = hit->time_fadc;
198  hit->has_fADC = true;
199  hit->has_TDC = false;
200  hit->is_double = false;
201 
202  hit->AddAssociatedObject(digihit);
203  _data.push_back(hit);
204  }
205 
206  // Next, loop over TDC hits, matching them to the existing fADC hits
207  // where possible and updating their time information. If no match is
208  // found, then create a new hit with just the TDC info.
209  vector<const DTAGHTDCDigiHit*> tdcdigihits;
210  loop->Get(tdcdigihits);
211  for (unsigned int i=0; i < tdcdigihits.size(); i++) {
212  const DTAGHTDCDigiHit *digihit = tdcdigihits[i];
213 
214  // Apply calibration constants here
215  int counter = digihit->counter_id;
216  double T = locTTabUtilities->Convert_DigiTimeToNs_F1TDC(digihit) - tdc_time_offsets[counter] + t_tdc_base;
217 
218  // Look for existing hits to see if there is a match
219  // or create new one if there is no match
220  DTAGHHit *hit = nullptr;
221  for (unsigned int j=0; j < _data.size(); ++j) {
222  if (_data[j]->counter_id == counter &&
223  fabs(T - _data[j]->time_fadc) < DELTA_T_ADC_TDC_MAX)
224  {
225  hit = _data[j];
226  }
227  }
228  if (hit == nullptr) {
229  hit = new DTAGHHit;
230  hit->counter_id = counter;
231  double Elow = taghGeom.getElow(counter);
232  double Ehigh = taghGeom.getEhigh(counter);
233  hit->E = (Elow + Ehigh)/2;
234  hit->time_fadc = numeric_limits<double>::quiet_NaN();
235  hit->integral = numeric_limits<double>::quiet_NaN();
236  hit->pulse_peak = numeric_limits<double>::quiet_NaN();
237  hit->npe_fadc = numeric_limits<double>::quiet_NaN();
238  hit->has_fADC = false;
239  hit->is_double = false;
240  _data.push_back(hit);
241  }
242  hit->time_tdc = T;
243  hit->has_TDC = true;
244  // apply time-walk corrections
245  double c0 = tdc_twalk_c0[counter]; double c1 = tdc_twalk_c1[counter];
246  double c2 = tdc_twalk_c2[counter]; double c3 = tdc_twalk_c3[counter];
247  double P = hit->pulse_peak;
248  if (P > 0.0) {
249  T -= (P <= c3 || c3 <= 0.0) ? c0 + c1/pow(P,c2) : c0 + c1*(1.0+c2)/pow(c3,c2) - c1*c2*P/pow(c3,1.0+c2);
250  }
251  hit->t = T;
252  hit->AddAssociatedObject(digihit);
253  }
254  return NOERROR;
255 }
256 
257 //------------------
258 // erun
259 //------------------
261 {
262  return NOERROR;
263 }
264 
265 //------------------
266 // fini
267 //------------------
269 {
270  return NOERROR;
271 }
272 
273 //---------------------
274 // load_ccdb_constants
275 //---------------------
277  std::string table_name,
278  std::string column_name,
279  double result[TAGH_MAX_COUNTER+1])
280 {
281  std::vector< std::map<std::string, double> > table;
282  std::string ccdb_key = "/PHOTON_BEAM/hodoscope/" + table_name;
283  if (eventLoop->GetCalib(ccdb_key, table))
284  {
285  jout << "Error loading " << ccdb_key << " from ccdb!" << std::endl;
286  return false;
287  }
288  for (unsigned int i=0; i < table.size(); ++i) {
289  int counter = (table[i])["id"];
290  result[counter] = (table[i])[column_name];
291  }
292  return true;
293 }
double t
Definition: DTAGHHit.h:19
double E
Definition: DTAGHHit.h:18
int counter_id
counter id 1-274
Definition: DTAGHDigiHit.h:18
double Convert_DigiTimeToNs_F1TDC(const JObject *locTDCDigiHit) const
Double_t c0[2][NMODULES]
Definition: tw_corr.C:67
double npe_fadc
Definition: DTAGHHit.h:25
double getElow(unsigned int counter) const
jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber)
Called every event.
bool CheckFADC250_NoErrors(uint32_t QF) const
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.
#define TAGH_MAX_COUNTER
Definition: DTAGHGeometry.h:18
bool is_double
Definition: DTAGHHit.h:26
char string[256]
bool has_TDC
Definition: DTAGHHit.h:26
uint32_t QF
Quality Factor from FPGA algorithms.
Definition: DTAGHDigiHit.h:22
int counter_id
counter id 1-274
Double_t c1[2][NMODULES]
Definition: tw_corr.C:68
jerror_t fini(void)
Called after last event of last event source has been processed.
double counter
Definition: FitGains.C:151
Double_t c2[2][NMODULES]
Definition: tw_corr.C:69
int counter_id
Definition: DTAGHHit.h:20
double time_tdc
Definition: DTAGHHit.h:23
uint32_t pulse_integral
identified pulse integral as returned by FPGA algorithm
Definition: DTAGHDigiHit.h:19
uint32_t pulse_time
identified pulse time as returned by FPGA algorithm
Definition: DTAGHDigiHit.h:20
bool load_ccdb_constants(std::string table_name, std::string column_name, double table[TAGH_MAX_COUNTER+1])
double getEhigh(unsigned int counter) const
bool CheckFADC250_PedestalOK(uint32_t QF) const
vector< double > tdc_time_offsets
bool has_fADC
Definition: DTAGHHit.h:26
static TH1I * pedestal[nChan]
double time_fadc
Definition: DTAGHHit.h:24
double integral
Definition: DTAGHHit.h:21
uint32_t pedestal
pedestal info used by FPGA (if any)
Definition: DTAGHDigiHit.h:21
jerror_t erun(void)
Called everytime run number changes, provided brun has been called.
double pulse_peak
Definition: DTAGHHit.h:22
static const int k_counter_noisy
TCanvas * c3
uint32_t nsamples_pedestal
number of samples used in pedestal
Definition: DTAGHDigiHit.h:24
jerror_t init(void)
Called once at program start.
uint32_t pulse_peak
maximum sample in pulse
Definition: DTAGHDigiHit.h:25
uint32_t nsamples_integral
number of samples used in integral
Definition: DTAGHDigiHit.h:23