Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DCDCHit_factory_Calib.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DCDCHit_factory_Calib.cc
4 // Created: Fri Mar 9 16:57:04 EST 2018
5 // Creator: B. Zihlmann, derived/copyed from DCDCHit_factory.cc
6 //
7 
8 
9 #include <iostream>
10 #include <iomanip>
11 using namespace std;
12 
13 
15 #include <CDC/DCDCDigiHit.h>
16 #include <CDC/DCDCWire.h>
17 #include <DAQ/Df125PulseIntegral.h>
18 #include <DAQ/Df125Config.h>
19 #include <DAQ/Df125CDCPulse.h>
20 
21 using namespace jana;
22 
24 
25 //#define ENABLE_UPSAMPLING
26 
27 //------------------
28 // init
29 //------------------
31 {
32 
33  gPARMS->SetDefaultParameter("CDC:CDC_HIT_THRESHOLD", CDC_HIT_THRESHOLD,
34  "Remove CDC Hits with peak amplitudes smaller than CDC_HIT_THRESHOLD");
35 
36  // default values
37  Nrings = 0;
38  a_scale = 0.;
39  t_scale = 0.;
40  t_base = 0.;
41 
42  // Set default number of number of detector channels
43  maxChannels = 3522;
44 
45  /// set the base conversion scales
46  a_scale = 4.0E3/1.0E2;
47  amp_a_scale = a_scale*28.8;
48  t_scale = 8.0/10.0; // 8 ns/count and integer time is in 1/10th of sample
49  t_base = 0.; // ns
50 
51  return NOERROR;
52 }
53 
54 //------------------
55 // brun
56 //------------------
57 jerror_t DCDCHit_factory_Calib::brun(jana::JEventLoop *eventLoop, int32_t runnumber)
58 {
59  // Only print messages for one thread whenever run number change
60  static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;
61  static set<int> runs_announced;
62  pthread_mutex_lock(&print_mutex);
63  bool print_messages = false;
64  if(runs_announced.find(runnumber) == runs_announced.end()){
65  print_messages = true;
66  runs_announced.insert(runnumber);
67  }
68  pthread_mutex_unlock(&print_mutex);
69 
70  // calculate the number of straws in each ring
71  CalcNstraws(eventLoop, runnumber, Nstraws);
72  Nrings = Nstraws.size();
73 
74  vector<double> raw_gains;
75  vector<double> raw_pedestals;
76  vector<double> raw_time_offsets;
77 
78  if(print_messages) jout << "In DCDCHit_factory, loading constants..." << std::endl;
79 
80  // load scale factors
81  map<string,double> scale_factors;
82  if (eventLoop->GetCalib("/CDC/digi_scales", scale_factors))
83  jout << "Error loading /CDC/digi_scales !" << endl;
84  if (scale_factors.find("CDC_ADC_ASCALE") != scale_factors.end())
85  a_scale = scale_factors["CDC_ADC_ASCALE"];
86  else
87  jerr << "Unable to get CDC_ADC_ASCALE from /CDC/digi_scales !" << endl;
88  amp_a_scale=a_scale*28.8;
89 
90 #ifdef ENABLE_UPSAMPLING
91  //t_scale=1.;
92 #else
93  if (scale_factors.find("CDC_ADC_TSCALE") != scale_factors.end())
94  t_scale = scale_factors["CDC_ADC_TSCALE"];
95  else
96  jerr << "Unable to get CDC_ADC_TSCALE from /CDC/digi_scales !" << endl;
97 #endif
98 
99  // load base time offset
100  map<string,double> base_time_offset;
101  if (eventLoop->GetCalib("/CDC/base_time_offset",base_time_offset))
102  jout << "Error loading /CDC/base_time_offset !" << endl;
103  if (base_time_offset.find("CDC_BASE_TIME_OFFSET") != base_time_offset.end())
104  t_base = base_time_offset["CDC_BASE_TIME_OFFSET"];
105  else
106  jerr << "Unable to get CDC_BASE_TIME_OFFSET from /CDC/base_time_offset !" << endl;
107 
108  // load constant tables
109  if (eventLoop->GetCalib("/CDC/wire_gains", raw_gains))
110  jout << "Error loading /CDC/wire_gains !" << endl;
111  if (eventLoop->GetCalib("/CDC/pedestals", raw_pedestals))
112  jout << "Error loading /CDC/pedestals !" << endl;
113  if (eventLoop->GetCalib("/CDC/timing_offsets", raw_time_offsets))
114  jout << "Error loading /CDC/timing_offsets !" << endl;
115 
116  // fill the tables
117  FillCalibTable(gains, raw_gains, Nstraws);
118  FillCalibTable(pedestals, raw_pedestals, Nstraws);
119  FillCalibTable(time_offsets, raw_time_offsets, Nstraws);
120 
121  // Verify that the right number of rings was read for each set of constants
122  char str[256];
123  if (gains.size() != Nrings) {
124  sprintf(str, "Bad # of rings for CDC gain from CCDB! CCDB=%zu , should be %d", gains.size(), Nrings);
125  std::cerr << str << std::endl;
126  throw JException(str);
127  }
128  if (pedestals.size() != Nrings) {
129  sprintf(str, "Bad # of rings for CDC pedestal from CCDB! CCDB=%zu , should be %d", pedestals.size(), Nrings);
130  std::cerr << str << std::endl;
131  throw JException(str);
132  }
133  if (time_offsets.size() != Nrings) {
134  sprintf(str, "Bad # of rings for CDC time_offset from CCDB!"
135  " CCDB=%zu , should be %d", time_offsets.size(), Nrings);
136  std::cerr << str << std::endl;
137  throw JException(str);
138  }
139 
140  // Verify the right number of straws was read for each ring for each set of constants
141  for (unsigned int i=0; i < Nrings; i++) {
142  if (gains[i].size() != Nstraws[i]) {
143  sprintf(str, "Bad # of straws for CDC gain from CCDB!"
144  " CCDB=%zu , should be %d for ring %d",
145  gains[i].size(), Nstraws[i], i+1);
146  std::cerr << str << std::endl;
147  throw JException(str);
148  }
149  if (pedestals[i].size() != Nstraws[i]) {
150  sprintf(str, "Bad # of straws for CDC pedestal from CCDB!"
151  " CCDB=%zu , should be %d for ring %d",
152  pedestals[i].size(), Nstraws[i], i+1);
153  std::cerr << str << std::endl;
154  throw JException(str);
155  }
156  if (time_offsets[i].size() != Nstraws[i]) {
157  sprintf(str, "Bad # of straws for CDC time_offset from CCDB!"
158  " CCDB=%zu , should be %d for ring %d",
159  time_offsets[i].size(), Nstraws[i], i+1);
160  std::cerr << str << std::endl;
161  throw JException(str);
162  }
163  }
164 
165  return NOERROR;
166 }
167 
168 //------------------
169 // evnt
170 //------------------
171 jerror_t DCDCHit_factory_Calib::evnt(JEventLoop *loop, uint64_t eventnumber)
172 {
173  /// Generate DCDCHit object for each DCDCDigiHit object.
174  /// This is where the first set of calibration constants
175  /// is applied to convert from digitzed units into natural
176  /// units.
177  ///
178  /// Note that this code does NOT get called for simulated
179  /// data in HDDM format. The HDDM event source will copy
180  /// the precalibrated values directly into the _data vector.
181 
182  /// In order to use the new Flash125 data types and maintain compatibility with the old code, what is below is a bit of a mess
183 
184  vector<const DCDCDigiHit*> digihits;
185  loop->Get(digihits);
186  char str[256];
187  for (unsigned int i=0; i < digihits.size(); i++) {
188  const DCDCDigiHit *digihit = digihits[i];
189 
190  //if ( (digihit->QF & 0x1) != 0 ) continue; // Cut bad timing quality factor hits... (should check effect on efficiency)
191 
192  const int &ring = digihit->ring;
193  const int &straw = digihit->straw;
194 
195  // Make sure ring and straw are in valid range
196  if ( (ring < 1) || (ring > (int)Nrings)) {
197  sprintf(str, "DCDCDigiHit ring out of range!"
198  " ring=%d (should be 1-%d)", ring, Nrings);
199  throw JException(str);
200  }
201  if ( (straw < 1) || (straw > (int)Nstraws[ring-1])) {
202  sprintf(str, "DCDCDigiHit straw out of range!"
203  " straw=%d for ring=%d (should be 1-%d)",
204  straw, ring, Nstraws[ring-1]);
205  throw JException(str);
206  }
207 
208  // Grab the pedestal from the digihit since this should be consistent between the old and new formats
209  int raw_ped = digihit->pedestal;
210  int maxamp = digihit->pulse_peak;
211  int nsamples_integral = 0; // actual number computed below using config info
212 
213  // There are a few values from the new data type that are critical for the interpretation of the data
214  uint16_t IBIT = 0; // 2^{IBIT} Scale factor for integral
215  uint16_t ABIT = 0; // 2^{ABIT} Scale factor for amplitude
216  uint16_t PBIT = 0; // 2^{PBIT} Scale factor for pedestal
217  uint16_t NW = 0;
218 
219  // This is the place to make quality cuts on the data.
220  const Df125PulsePedestal* PPobj = NULL;
221  digihit->GetSingle(PPobj);
222  if( PPobj != NULL ) {
223  // Use the old format - mostly handle error conditions
224  // This code will at some point become deprecated in the future...
225  // This applies to the firmware for data taken until the fall of 2015.
226  // Mode 8: Raw data and processed data (except pulse integral).
227  // Mode 7: Processed data only.
228 
229  // This error state is only present in mode 8
230  if (digihit->pulse_time==0.) continue;
231 
232  // There is a slight difference between Mode 7 and 8 data
233  // The following condition signals an error state in the flash algorithm
234  // Do not make hits out of these
235  if (PPobj != NULL){
236  if (PPobj->pedestal == 0 || PPobj->pulse_peak == 0) continue;
237  if (PPobj->pulse_number == 1) continue; // Unintentionally had 2 pulses found in fall 2014 data (0-1 counting issue)
238  }
239 
240  const Df125PulseIntegral* PIobj = NULL;
241  digihit->GetSingle(PIobj);
242  if (PPobj == NULL || PIobj == NULL) continue; // We don't want hits where ANY of the associated information is missing
243 
244  // this amplitude is not set in the translation table for this old data format, so make a (reasonable?) guess
245  maxamp = digihit->pulse_integral / 28.8;
246  } else {
247  // Use the modern (2017+) data versions
248  // Configuration data needed to interpret the hits is stored in the data stream
249  vector<const Df125Config*> configs;
250  digihit->Get(configs);
251  if( configs.empty() ){
252  static int Nwarnings = 0;
253  if(Nwarnings<10){
254  _DBG_ << "NO Df125Config object associated with Df125CDCPulse object!" << endl;
255  Nwarnings++;
256  if(Nwarnings==10) _DBG_ << " --- LAST WARNING!! ---" << endl;
257  }
258  }else{
259  // Set some constants to defaults until they appear correctly in the config words in the future
260  const Df125Config *config = configs[0];
261  IBIT = config->IBIT == 0xffff ? 4 : config->IBIT;
262  ABIT = config->ABIT == 0xffff ? 3 : config->ABIT;
263  PBIT = config->PBIT == 0xffff ? 0 : config->PBIT;
264  NW = config->NW == 0xffff ? 180 : config->NW;
265  }
266 
267  if(NW==0) NW=180; // some data was taken (<=run 4700) where NW was written as 0 to file
268 
269  // The integration window in the CDC should always extend past the end
270  //of the window
271  // Only true after about run 4100
272  nsamples_integral = (NW - (digihit->pulse_time / 10));
273  }
274 
275  // Complete the pedestal subtraction here since we should know the correct number of samples.
276  int scaled_ped = raw_ped << PBIT;
277 
278  if (maxamp > 0) maxamp = maxamp << ABIT;
279  //if (maxamp <= scaled_ped) continue;
280 
281  maxamp = maxamp - scaled_ped;
282 
283  if (maxamp<CDC_HIT_THRESHOLD) {
284  continue;
285  }
286 
287  // Apply calibration constants here
288  double t_raw = double(digihit->pulse_time);
289 
290  // Scale factor to account for gain variation
291  double gain=gains[ring-1][straw-1];
292 
293  // Charge and amplitude
294  double q = a_scale *gain * double((digihit->pulse_integral<<IBIT)
295  - scaled_ped*nsamples_integral);
296  double amp = amp_a_scale*gain*double(maxamp);
297 
298  double t = t_scale * t_raw - time_offsets[ring-1][straw-1] + t_base;
299 
300  DCDCHit *hit = new DCDCHit;
301  hit->ring = ring;
302  hit->straw = straw;
303 
304  // Values for d, itrack, ptype only apply to MC data
305  // note that ring/straw counting starts at 1
306  hit->q = q;
307  hit->amp = amp;
308  hit->t = t;
309  hit->d = 0.0;
310  hit->QF = digihit->QF;
311  hit->itrack = -1;
312  hit->ptype = 0;
313 
314  hit->AddAssociatedObject(digihit);
315 
316  _data.push_back(hit);
317  }
318 
319  return NOERROR;
320 }
321 
322 
323 //------------------
324 // erun
325 //------------------
327 {
328  return NOERROR;
329 }
330 
331 //------------------
332 // fini
333 //------------------
335 {
336  return NOERROR;
337 }
338 
339 //------------------
340 // CalcNstraws
341 //------------------
342 void DCDCHit_factory_Calib::CalcNstraws(jana::JEventLoop *eventLoop, int32_t runnumber, vector<unsigned int> &Nstraws)
343 {
344  DGeometry *dgeom;
345  vector<vector<DCDCWire *> >cdcwires;
346 
347  // Get pointer to DGeometry object
348  DApplication* dapp=dynamic_cast<DApplication*>(eventLoop->GetJApplication());
349  dgeom = dapp->GetDGeometry(runnumber);
350 
351  // Get the CDC wire table from the XML
352  dgeom->GetCDCWires(cdcwires);
353 
354  // Fill array with the number of straws for each layer
355  // Also keep track of the total number of straws, i.e., the total number of detector channels
356  maxChannels = 0;
357  Nstraws.clear();
358  for (unsigned int i=0; i<cdcwires.size(); i++) {
359  Nstraws.push_back( cdcwires[i].size() );
360  maxChannels += cdcwires[i].size();
361  }
362 
363  // clear up all of the wire information
364  for (unsigned int i=0; i<cdcwires.size(); i++) {
365  for (unsigned int j=0; j<cdcwires[i].size(); j++) {
366  delete cdcwires[i][j];
367  }
368  }
369  cdcwires.clear();
370 }
371 
372 
373 //------------------
374 // FillCalibTable
375 //------------------
376 void DCDCHit_factory_Calib::FillCalibTable(vector< vector<double> > &table, vector<double> &raw_table,
377  vector<unsigned int> &Nstraws)
378 {
379  int ring = 0;
380  int straw = 0;
381 
382  // reset table before filling it
383  table.clear();
384  table.resize( Nstraws.size() );
385 
386  for (unsigned int channel=0; channel<raw_table.size(); channel++,straw++) {
387  // make sure that we don't try to load info for channels that don't exist
388  if (channel == maxChannels) break;
389 
390  // if we've hit the end of the ring, move on to the next
391  if (straw == (int)Nstraws[ring]) {
392  ring++;
393  straw = 0;
394  }
395 
396  table[ring].push_back( raw_table[channel] );
397  }
398 
399 }
400 
401 
402 //------------------------------------
403 // GetConstant
404 // Allow a few different interfaces
405 //------------------------------------
407  const int in_ring, const int in_straw) const {
408 
409  char str[256];
410 
411  if ( (in_ring <= 0) || (static_cast<unsigned int>(in_ring) > Nrings)) {
412  sprintf(str, "Bad ring # requested in DCDCHit_factory::GetConstant()!"
413  " requested=%d , should be %ud", in_ring, Nrings);
414  std::cerr << str << std::endl;
415  throw JException(str);
416  }
417  if ( (in_straw <= 0) ||
418  (static_cast<unsigned int>(in_straw) > Nstraws[in_ring]))
419  {
420  sprintf(str, "Bad straw # requested in DCDCHit_factory::GetConstant()!"
421  " requested=%d , should be %ud", in_straw, Nstraws[in_ring]);
422  std::cerr << str << std::endl;
423  throw JException(str);
424  }
425 
426  return the_table[in_ring-1][in_straw-1];
427 }
428 
430  const DCDCDigiHit *in_digihit) const {
431 
432  char str[256];
433 
434  if ( (in_digihit->ring <= 0) ||
435  (static_cast<unsigned int>(in_digihit->ring) > Nrings))
436  {
437  sprintf(str, "Bad ring # requested in DCDCHit_factory::GetConstant()!"
438  " requested=%d , should be %ud", in_digihit->ring, Nrings);
439  std::cerr << str << std::endl;
440  throw JException(str);
441  }
442  if ( (in_digihit->straw <= 0) ||
443  (static_cast<unsigned int>(in_digihit->straw) > Nstraws[in_digihit->ring]))
444  {
445  sprintf(str, "Bad straw # requested in DCDCHit_factory::GetConstant()!"
446  " requested=%d , should be %ud",
447  in_digihit->straw, Nstraws[in_digihit->ring]);
448  std::cerr << str << std::endl;
449  throw JException(str);
450  }
451 
452  return the_table[in_digihit->ring-1][in_digihit->straw-1];
453 }
454 
456  const DCDCHit *in_hit) const {
457 
458  char str[256];
459 
460  if ( (in_hit->ring <= 0) || (static_cast<unsigned int>(in_hit->ring) > Nrings)) {
461  sprintf(str, "Bad ring # requested in DCDCHit_factory::GetConstant()!"
462  " requested=%d , should be %ud", in_hit->ring, Nrings);
463  std::cerr << str << std::endl;
464  throw JException(str);
465  }
466  if ( (in_hit->straw <= 0) ||
467  (static_cast<unsigned int>(in_hit->straw) > Nstraws[in_hit->ring])) {
468  sprintf(str, "Bad straw # requested in DCDCHit_factory::GetConstant()!"
469  " requested=%d , should be %ud",
470  in_hit->straw, Nstraws[in_hit->ring]);
471  std::cerr << str << std::endl;
472  throw JException(str);
473  }
474 
475  return the_table[in_hit->ring-1][in_hit->straw-1];
476 }
477 
DApplication * dapp
int itrack
Definition: DCDCHit.h:25
char str[256]
uint16_t IBIT
Definition: Df125Config.h:44
jerror_t init(void)
Called once at program start.
uint32_t pulse_peak
from Pulse Pedestal Data word
sprintf(text,"Post KinFit Cut")
float amp
Definition: DCDCHit.h:21
jerror_t erun(void)
Called everytime run number changes, provided brun has been called.
uint16_t PBIT
Definition: Df125Config.h:46
uint16_t ABIT
Definition: Df125Config.h:45
bool GetCDCWires(vector< vector< DCDCWire * > > &cdcwires) const
Definition: DGeometry.cc:773
uint32_t pulse_time
identified pulse time as returned by FPGA algorithm
Definition: DCDCDigiHit.h:22
float t
Definition: DCDCHit.h:22
void FillCalibTable(vector< vector< double > > &table, vector< double > &raw_table, vector< unsigned int > &Nstraws)
vector< vector< double > > cdc_digi_constants_t
int ptype
Definition: DCDCHit.h:26
uint32_t pulse_integral
identified pulse integral as returned by FPGA algorithm
Definition: DCDCDigiHit.h:21
DGeometry * GetDGeometry(unsigned int run_number)
#define _DBG_
Definition: HDEVIO.h:12
int ring
Definition: DCDCHit.h:18
uint32_t pulse_number
from Pulse Pedestal Data word
int CDC_HIT_THRESHOLD
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.
const double GetConstant(const cdc_digi_constants_t &the_table, const int in_ring, const int in_straw) const
uint32_t pedestal
from Pulse Pedestal Data word
float q
Definition: DCDCHit.h:20
jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber)
Called every event.
void CalcNstraws(jana::JEventLoop *eventLoop, int32_t runnumber, vector< unsigned int > &Nstraws)
uint32_t QF
Quality Factor from FPGA algorithms.
Definition: DCDCDigiHit.h:24
uint16_t NW
Definition: Df125Config.h:35
float d
Definition: DCDCHit.h:23
jerror_t fini(void)
Called after last event of last event source has been processed.
uint32_t pedestal
pedestal info used by FPGA (if any)
Definition: DCDCDigiHit.h:23
uint32_t pulse_peak
identified pulse first peak as returned by FPGA algorithm (could be either Df125CDCPulse::first_max_a...
Definition: DCDCDigiHit.h:20
int straw
Definition: DCDCHit.h:19
int QF
Definition: DCDCHit.h:24