Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTAGMHit_factory_Calib.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DTAGMHit_factory_Calib.cc
4 // Created: Sat Aug 2 12:23:43 EDT 2014
5 // Creator: jonesrt (on Linux gluex.phys.uconn.edu)
6 //
7 
8 
9 #include <iostream>
10 #include <iomanip>
11 using namespace std;
12 
13 #include "DTAGMDigiHit.h"
14 #include "DTAGMTDCDigiHit.h"
15 #include "DTAGMGeometry.h"
16 #include "DTAGMHit_factory_Calib.h"
17 #include <DAQ/Df250PulseIntegral.h>
18 #include <DAQ/Df250PulsePedestal.h>
19 #include <DAQ/Df250Config.h>
20 
21 using namespace jana;
22 
26 
27 //------------------
28 // init
29 //------------------
31 {
32  DELTA_T_ADC_TDC_MAX = 10.0; // ns
33  USE_ADC = 0;
34  CUT_FACTOR = 1;
35  gPARMS->SetDefaultParameter("TAGMHit: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  gPARMS->SetDefaultParameter("TAGMHit:CUT_FACTOR", CUT_FACTOR, "TAGM pulse integral cut factor, 0 = no cut");
39  gPARMS->SetDefaultParameter("TAGMHit:USE_ADC", USE_ADC, "Use ADC times in TAGM");
40 
41  CHECK_FADC_ERRORS = true;
42  gPARMS->SetDefaultParameter("TAGMHit:CHECK_FADC_ERRORS", CHECK_FADC_ERRORS, "Set to 1 to reject hits with fADC250 errors, ser to 0 to keep these hits");
43 
44  // initialize calibration constants
45  fadc_a_scale = 0;
46  fadc_t_scale = 0;
47  t_base = 0;
48  t_tdc_base=0;
49 
50  // calibration constants stored in row, column format
51  for (int row = 0; row <= TAGM_MAX_ROW; ++row) {
52  for (int col = 0; col <= TAGM_MAX_COLUMN; ++col) {
53  fadc_gains[row][col] = 0;
54  fadc_pedestals[row][col] = 0;
55  fadc_time_offsets[row][col] = 0;
56  tdc_time_offsets[row][col] = 0;
57  fiber_quality[row][col] = 0;
58  }
59  }
60 
61  return NOERROR;
62 }
63 
64 //------------------
65 // brun
66 //------------------
67 jerror_t DTAGMHit_factory_Calib::brun(jana::JEventLoop *eventLoop, int32_t runnumber)
68 {
69  // Only print messages for one thread whenever run number change
70  static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;
71  static set<int> runs_announced;
72  pthread_mutex_lock(&print_mutex);
73  bool print_messages = false;
74  if(runs_announced.find(runnumber) == runs_announced.end()){
75  print_messages = true;
76  runs_announced.insert(runnumber);
77  }
78  pthread_mutex_unlock(&print_mutex);
79 
80  /// set the base conversion scales
81  fadc_a_scale = 1.1; // pixels per count
82  fadc_t_scale = 0.0625; // ns per count
83  t_base = 0.; // ns
84 
85  pthread_mutex_unlock(&print_mutex);
86  if(print_messages) jout << "In DTAGMHit_factory_Calib, loading constants..." << std::endl;
87 
88  // load base time offset
89  map<string,double> base_time_offset;
90  if (eventLoop->GetCalib("/PHOTON_BEAM/microscope/base_time_offset",base_time_offset))
91  jout << "Error loading /PHOTON_BEAM/microscope/base_time_offset !" << endl;
92  if (base_time_offset.find("TAGM_BASE_TIME_OFFSET") != base_time_offset.end())
93  t_base = base_time_offset["TAGM_BASE_TIME_OFFSET"];
94  else
95  jerr << "Unable to get TAGM_BASE_TIME_OFFSET from /PHOTON_BEAM/microscope/base_time_offset !" << endl;
96  if (base_time_offset.find("TAGM_TDC_BASE_TIME_OFFSET") != base_time_offset.end())
97  t_tdc_base = base_time_offset["TAGM_TDC_BASE_TIME_OFFSET"];
98  else
99  jerr << "Unable to get TAGM_TDC_BASE_TIME_OFFSET from /PHOTON_BEAM/microscope/base_time_offset !" << endl;
100 
101  if (load_ccdb_constants("fadc_gains", "gain", fadc_gains) &&
102  load_ccdb_constants("fadc_pedestals", "pedestal", fadc_pedestals) &&
103  load_ccdb_constants("fadc_time_offsets", "offset", fadc_time_offsets) &&
104  load_ccdb_constants("tdc_time_offsets", "offset", tdc_time_offsets) &&
105  load_ccdb_constants("fiber_quality", "code", fiber_quality) &&
106  load_ccdb_constants("tdc_timewalk_corrections", "c0", tw_c0) &&
107  load_ccdb_constants("tdc_timewalk_corrections", "c1", tw_c1) &&
108  load_ccdb_constants("tdc_timewalk_corrections", "c2", tw_c2) &&
109  load_ccdb_constants("tdc_timewalk_corrections", "threshold", tw_c3) &&
110  load_ccdb_constants("tdc_timewalk_corrections", "reference", ref) &&
111  load_ccdb_constants("integral_cuts", "integral", int_cuts))
112  {
113  return NOERROR;
114  }
115  return UNRECOVERABLE_ERROR;
116 }
117 
118 //------------------
119 // evnt
120 //------------------
121 jerror_t DTAGMHit_factory_Calib::evnt(JEventLoop *loop, uint64_t eventnumber)
122 {
123  /// Generate DTAGMHit object for each DTAGMDigiHit object.
124  /// This is where the first set of calibration constants
125  /// is applied to convert from digitzed units into natural
126  /// units.
127  ///
128  /// Note that this code does NOT get called for simulated
129  /// data in HDDM format. The HDDM event source will copy
130  /// the precalibrated values directly into the _data vector.
131 
132  // extract the TAGM geometry
133  vector<const DTAGMGeometry*> tagmGeomVect;
134  eventLoop->Get( tagmGeomVect );
135  if (tagmGeomVect.size() < 1)
136  return OBJECT_NOT_AVAILABLE;
137  const DTAGMGeometry& tagmGeom = *(tagmGeomVect[0]);
138 
139  const DTTabUtilities* locTTabUtilities = nullptr;
140  loop->GetSingle(locTTabUtilities);
141 
142  // First loop over all TAGMDigiHits and make DTAGMHits out of them
143  vector<const DTAGMDigiHit*> digihits;
144  loop->Get(digihits);
145  for (unsigned int i=0; i < digihits.size(); i++) {
146  const DTAGMDigiHit *digihit = digihits[i];
147 
148  // Throw away hits with firmware errors (post-summer 2016 firmware)
149  if(CHECK_FADC_ERRORS && !locTTabUtilities->CheckFADC250_NoErrors(digihit->QF))
150  continue;
151 
152  // Get pedestal, prefer associated event pedestal if it exists,
153  // otherwise, use the average pedestal from CCDB
154  double pedestal = fadc_pedestals[digihit->row][digihit->column];
155  double nsamples_integral = (double)digihit->nsamples_integral;
156  double nsamples_pedestal = (double)digihit->nsamples_pedestal;
157 
158  // nsamples_pedestal should always be positive for valid data - err on the side of caution for now
159  if(nsamples_pedestal == 0) {
160  jerr << "DTAGMDigiHit with nsamples_pedestal == 0 ! Event = " << eventnumber << endl;
161  continue;
162  }
163 
164  // digihit->pedestal is the sum of "nsamples_pedestal" samples
165  // Calculate the average pedestal per sample
166  if ( (digihit->pedestal>0) && locTTabUtilities->CheckFADC250_PedestalOK(digihit->QF) ) {
167  pedestal = (double)digihit->pedestal/nsamples_pedestal;
168  }
169 
170  // Subtract pedestal from pulse peak
171  if (digihit->pulse_time == 0 || digihit->pedestal == 0 || digihit->pulse_peak == 0) continue;
172  double pulse_peak = digihit->pulse_peak - pedestal;
173 
174  // throw away hits from bad or noisy fibers
175  int quality = fiber_quality[digihit->row][digihit->column];
176  if (quality == k_fiber_bad || quality == k_fiber_noisy)
177  continue;
178 
179  // Apply calibration constants
180  double A = digihit->pulse_integral;
181  double T = digihit->pulse_time;
182  A -= pedestal*nsamples_integral;
183  int row = digihit->row;
184  int column = digihit->column;
185  if (A < CUT_FACTOR*int_cuts[row][column]) continue;
186 
187  DTAGMHit *hit = new DTAGMHit;
188  hit->row = row;
189  hit->column = column;
190  double Elow = tagmGeom.getElow(column);
191  double Ehigh = tagmGeom.getEhigh(column);
192  hit->E = (Elow + Ehigh)/2;
193 
194  hit->integral = A;
195  hit->pulse_peak = pulse_peak;
196  hit->npix_fadc = A * fadc_a_scale * fadc_gains[row][column];
197  hit->time_fadc = T * fadc_t_scale - fadc_time_offsets[row][column] + t_base;
198  hit->t=hit->time_fadc;
199  hit->has_TDC=false;
200  hit->has_fADC=true;
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 DTAGMTDCDigiHit*> tdcdigihits;
210  loop->Get(tdcdigihits);
211  for (unsigned int i=0; i < tdcdigihits.size(); i++) {
212  const DTAGMTDCDigiHit *digihit = tdcdigihits[i];
213 
214  // Apply calibration constants here
215  int row = digihit->row;
216  int column = digihit->column;
217  double T = locTTabUtilities->Convert_DigiTimeToNs_F1TDC(digihit) - tdc_time_offsets[row][column] + t_tdc_base;
218 
219  // Look for existing hits to see if there is a match
220  // or create new one if there is no match
221  DTAGMHit *hit = nullptr;
222  for (unsigned int j=0; j < _data.size(); ++j) {
223  if (_data[j]->row == row && _data[j]->column == column &&
224  fabs(T - _data[j]->time_fadc) < DELTA_T_ADC_TDC_MAX)
225  {
226  hit = _data[j];
227  }
228  }
229  if (hit == nullptr) {
230  hit = new DTAGMHit;
231  hit->row = row;
232  hit->column = column;
233  double Elow = tagmGeom.getElow(column);
234  double Ehigh = tagmGeom.getEhigh(column);
235  hit->E = (Elow + Ehigh)/2;
236  hit->time_fadc = 0;
237  hit->npix_fadc = 0;
238  hit->integral = 0;
239  hit->pulse_peak = 0;
240  hit->has_fADC=false;
241  _data.push_back(hit);
242  }
243  hit->time_tdc=T;
244  hit->has_TDC=true;
245 
246  // apply time-walk corrections
247  double P = hit->pulse_peak;
248  double c0 = tw_c0[row][column];
249  double c1 = tw_c1[row][column];
250  double c2 = tw_c2[row][column];
251  //double TH = thresh[row][column];
252  double c3 = tw_c3[row][column];
253  double t0 = ref[row][column];
254  //pp_0 = TH*pow((pp_0-c0)/c1,1/c2);
255  if (P > 0) {
256  //T -= c1*(pow(P/TH,c2)-pow(pp_0/TH,c2));
257  T -= c1*pow(1/(P+c3),c2) - (t0 - c0);
258  }
259 
260  // Optionally only use ADC times
261  if (USE_ADC && hit->has_fADC) hit->t = hit->time_fadc;
262  else hit->t = T;
263 
264  hit->AddAssociatedObject(digihit);
265  }
266 
267  return NOERROR;
268 }
269 
270 //------------------
271 // erun
272 //------------------
274 {
275  return NOERROR;
276 }
277 
278 //------------------
279 // fini
280 //------------------
282 {
283  return NOERROR;
284 }
285 
286 //---------------------
287 // load_ccdb_constants
288 //---------------------
290  std::string table_name,
291  std::string column_name,
292  double result[TAGM_MAX_ROW+1][TAGM_MAX_COLUMN+1])
293 {
294  std::vector< std::map<std::string, double> > table;
295  std::string ccdb_key = "/PHOTON_BEAM/microscope/" + table_name;
296  if (eventLoop->GetCalib(ccdb_key, table))
297  {
298  jout << "Error loading " << ccdb_key << " from ccdb!" << std::endl;
299  return false;
300  }
301  for (unsigned int i=0; i < table.size(); ++i) {
302  int row = (table[i])["row"];
303  int col = (table[i])["column"];
304  result[row][col] = (table[i])[column_name];
305  }
306  return true;
307 }
double Convert_DigiTimeToNs_F1TDC(const JObject *locTDCDigiHit) const
Double_t c0[2][NMODULES]
Definition: tw_corr.C:67
double E
Definition: DTAGMHit.h:18
uint32_t pulse_time
identified pulse time as returned by FPGA algorithm
Definition: DTAGMDigiHit.h:21
bool CheckFADC250_NoErrors(uint32_t QF) const
int column
column number 1-102
jerror_t fini(void)
Called after last event of last event source has been processed.
#define TAGM_MAX_COLUMN
Definition: DTAGMGeometry.h:19
char string[256]
int row
Definition: DTAGMHit.h:20
double time_fadc
Definition: DTAGMHit.h:25
double t
Definition: DTAGMHit.h:19
Double_t c1[2][NMODULES]
Definition: tw_corr.C:68
double getEhigh(unsigned int column) const
Double_t c2[2][NMODULES]
Definition: tw_corr.C:69
bool has_fADC
Definition: DTAGMHit.h:27
uint32_t pulse_peak
maximum sample in pulse
Definition: DTAGMDigiHit.h:26
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.
bool has_TDC
Definition: DTAGMHit.h:27
uint32_t pedestal
pedestal info used by FPGA (if any)
Definition: DTAGMDigiHit.h:22
uint32_t QF
Quality Factor from FPGA algorithms.
Definition: DTAGMDigiHit.h:23
uint32_t pulse_integral
identified pulse integral as returned by FPGA algorithm
Definition: DTAGMDigiHit.h:20
double npix_fadc
Definition: DTAGMHit.h:26
double getElow(unsigned int column) const
double pulse_peak
Definition: DTAGMHit.h:23
bool CheckFADC250_PedestalOK(uint32_t QF) const
bool load_ccdb_constants(std::string table_name, std::string column_name, double table[TAGM_MAX_ROW+1][TAGM_MAX_COLUMN+1])
vector< double > tdc_time_offsets
double integral
Definition: DTAGMHit.h:22
jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber)
Called every event.
#define TAGM_MAX_ROW
Definition: DTAGMGeometry.h:18
static TH1I * pedestal[nChan]
uint32_t nsamples_integral
number of samples used in integral
Definition: DTAGMDigiHit.h:24
int column
Definition: DTAGMHit.h:21
TCanvas * c3
int row
row number 1-5
jerror_t erun(void)
Called everytime run number changes, if brun has been called.
double time_tdc
Definition: DTAGMHit.h:24
uint32_t nsamples_pedestal
number of samples used in pedestal
Definition: DTAGMDigiHit.h:25
jerror_t init(void)
Called once at program start.