Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DPSHit_factory.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DPSHit_factory.cc
4 // Created: Wed Oct 15 16:45:01 EDT 2014
5 // Creator: staylor (on Linux gluon05.jlab.org 2.6.32-358.18.1.el6.x86_64 x86_64)
6 //
7 #include <iostream>
8 #include <iomanip>
9 using namespace std;
10 
11 #include "DPSHit_factory.h"
12 #include <DAQ/Df250PulsePedestal.h>
13 #include <DAQ/Df250PulseIntegral.h>
14 #include <TTAB/DTTabUtilities.h>
15 using namespace jana;
16 
17 
18 //------------------
19 // init
20 //------------------
21 jerror_t DPSHit_factory::init(void)
22 {
23  ADC_THRESHOLD = 500.0; // ADC integral counts
24  gPARMS->SetDefaultParameter("PSHit:ADC_THRESHOLD",ADC_THRESHOLD,
25  "pedestal-subtracted pulse integral threshold");
26 
27  /// set the base conversion scales
28  a_scale = 0.0001;
29  t_scale = 0.0625; // 62.5 ps/count
30  t_base = 0.; // ns
31 
32  CHECK_FADC_ERRORS = true;
33  gPARMS->SetDefaultParameter("PSHit:CHECK_FADC_ERRORS", CHECK_FADC_ERRORS, "Set to 1 to reject hits with fADC250 errors, ser to 0 to keep these hits");
34 
35  return NOERROR;
36 }
37 
38 //------------------
39 // brun
40 //------------------
41 jerror_t DPSHit_factory::brun(jana::JEventLoop *eventLoop, int32_t runnumber)
42 {
43  // Only print messages for one thread whenever run number change
44  static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;
45  static set<int> runs_announced;
46  pthread_mutex_lock(&print_mutex);
47  bool print_messages = false;
48  if(runs_announced.find(runnumber) == runs_announced.end()){
49  print_messages = true;
50  runs_announced.insert(runnumber);
51  }
52  pthread_mutex_unlock(&print_mutex);
53 
54  /// Read in calibration constants
55  if(print_messages) jout << "In DPSHit_factory, loading constants..." << endl;
56 
57  // extract the PS Geometry
58  vector<const DPSGeometry*> psGeomVect;
59  eventLoop->Get(psGeomVect);
60  if (psGeomVect.size() < 1)
61  return OBJECT_NOT_AVAILABLE;
62  const DPSGeometry& psGeom = *(psGeomVect[0]);
63 
64  // load scale factors
65  map<string,double> scale_factors;
66  if (eventLoop->GetCalib("/PHOTON_BEAM/pair_spectrometer/digi_scales", scale_factors))
67  jout << "Error loading /PHOTON_BEAM/pair_spectrometer/digi_scales !" << endl;
68  if (scale_factors.find("PS_ADC_ASCALE") != scale_factors.end())
69  a_scale = scale_factors["PS_ADC_ASCALE"];
70  else
71  jerr << "Unable to get PS_ADC_ASCALE from /PHOTON_BEAM/pair_spectrometer/digi_scales !"
72  << endl;
73  if (scale_factors.find("PS_ADC_TSCALE") != scale_factors.end())
74  t_scale = scale_factors["PS_ADC_TSCALE"];
75  else
76  jerr << "Unable to get PS_ADC_TSCALE from /PHOTON_BEAM/pair_spectrometer/digi_scales !"
77  << endl;
78 
79  // load base time offset
80  map<string,double> base_time_offset;
81  if (eventLoop->GetCalib("/PHOTON_BEAM/pair_spectrometer/base_time_offset",base_time_offset))
82  jout << "Error loading /PHOTON_BEAM/pair_spectrometer/base_time_offset !" << endl;
83  if (base_time_offset.find("PS_FINE_BASE_TIME_OFFSET") != base_time_offset.end())
84  t_base = base_time_offset["PS_FINE_BASE_TIME_OFFSET"];
85  else
86  jerr << "Unable to get PS_FINE_BASE_TIME_OFFSET from /PHOTON_BEAM/pair_spectrometer/base_time_offset !" << endl;
87 
88  FillCalibTable(adc_pedestals, "/PHOTON_BEAM/pair_spectrometer/fine/adc_pedestals", psGeom);
89  FillCalibTable(adc_gains, "/PHOTON_BEAM/pair_spectrometer/fine/adc_gain_factors", psGeom);
90  FillCalibTable(adc_time_offsets, "/PHOTON_BEAM/pair_spectrometer/fine/adc_timing_offsets", psGeom);
91 
92  return NOERROR;
93 }
94 
95 //------------------
96 // evnt
97 //------------------
98 jerror_t DPSHit_factory::evnt(JEventLoop *loop, uint64_t eventnumber)
99 {
100  /// Generate DPSHit object for each DPSDigiHit object.
101  /// This is where the first set of calibration constants
102  /// is applied to convert from digitzed units into natural
103  /// units.
104  ///
105  /// Note that this code does NOT get called for simulated
106  /// data in HDDM format. The HDDM event source will copy
107  /// the precalibrated values directly into the _data vector.
108 
109  // extract the PS Geometry
110  vector<const DPSGeometry*> psGeomVect;
111  eventLoop->Get(psGeomVect);
112  if (psGeomVect.size() < 1)
113  return OBJECT_NOT_AVAILABLE;
114  const DPSGeometry& psGeom = *(psGeomVect[0]);
115 
116  const DTTabUtilities* locTTabUtilities = nullptr;
117  loop->GetSingle(locTTabUtilities);
118 
119  // First, make hits out of all fADC250 hits
120  vector<const DPSDigiHit*> digihits;
121  loop->Get(digihits);
122  char str[256];
123 
124  for (unsigned int i=0; i < digihits.size(); i++) {
125  const DPSDigiHit *digihit = digihits[i];
126 
127  // Make sure channel id is in valid range
128  if( (digihit->arm < 0) || (digihit->arm >= psGeom.NUM_ARMS) ) {
129  sprintf(str, "DPSDigiHit arm out of range! arm=%d (should be 0-%d)",
130  digihit->arm, psGeom.NUM_ARMS);
131  throw JException(str);
132  }
133  if( (digihit->column <= 0) || (digihit->column > psGeom.NUM_FINE_COLUMNS) ) {
134  sprintf(str, "DPSDigiHit column out of range! column=%d (should be 0-%d)",
135  digihit->column, psGeom.NUM_FINE_COLUMNS);
136  throw JException(str);
137  }
138 
139  // Throw away hits with firmware errors (post-summer 2016 firmware)
140  if(CHECK_FADC_ERRORS && !locTTabUtilities->CheckFADC250_NoErrors(digihit->QF))
141  continue;
142 
143  // Get pedestal, prefer associated event pedestal if it exists,
144  // otherwise, use the average pedestal from CCDB
145  double pedestal = GetConstant(adc_pedestals,digihit,psGeom);
146  double nsamples_integral = (double)digihit->nsamples_integral;
147  double nsamples_pedestal = (double)digihit->nsamples_pedestal;
148 
149  // nsamples_pedestal should always be positive for valid data - err on the side of caution for now
150  if(nsamples_pedestal == 0) {
151  jerr << "DPSDigiHit with nsamples_pedestal == 0 ! Event = " << eventnumber << endl;
152  continue;
153  }
154 
155  // digihit->pedestal is the sum of "nsamples_pedestal" samples
156  // Calculate the average pedestal per sample
157  if ( (digihit->pedestal>0) && locTTabUtilities->CheckFADC250_PedestalOK(digihit->QF) ) {
158  pedestal = (double)digihit->pedestal/nsamples_pedestal;
159  }
160 
161  // Subtract pedestal from pulse peak
162  if (digihit->pulse_time == 0 || digihit->pedestal == 0 || digihit->pulse_peak == 0) continue;
163  double pulse_peak = digihit->pulse_peak - pedestal;
164 
165  // Subtract pedestal from pulse integral
166  double A = (double)digihit->pulse_integral;
167  A -= pedestal*nsamples_integral;
168 
169  // Throw away hits with small pedestal-subtracted integrals
170  if (A < ADC_THRESHOLD) continue;
171 
172  // Apply calibration constants
173  double T = (double)digihit->pulse_time;
174 
175  DPSHit *hit = new DPSHit;
176  // The PSHit class labels hits as
177  // arm: North/South (0/1)
178  // column: 1-145
179  hit->arm = digihit->arm;
180  hit->column = digihit->column;
181  hit->integral = A;
182  hit->pulse_peak = pulse_peak;
183  hit->npix_fadc = A * a_scale * GetConstant(adc_gains, digihit, psGeom);
184  hit->t = t_scale * T - GetConstant(adc_time_offsets, digihit, psGeom) + t_base;
185  hit->E = 0.5*(psGeom.getElow(digihit->arm,digihit->column) + psGeom.getEhigh(digihit->arm,digihit->column));
186 
187  hit->AddAssociatedObject(digihit);
188 
189  _data.push_back(hit);
190  }
191 
192 
193  return NOERROR;
194 }
195 
196 //------------------
197 // erun
198 //------------------
199 jerror_t DPSHit_factory::erun(void)
200 {
201  return NOERROR;
202 }
203 
204 //------------------
205 // fini
206 //------------------
207 jerror_t DPSHit_factory::fini(void)
208 {
209  return NOERROR;
210 }
211 
212 //------------------
213 // FillCalibTable
214 //------------------
215 void DPSHit_factory::FillCalibTable(ps_digi_constants_t &table, string table_name,
216  const DPSGeometry &psGeom)
217 {
218  char str[256];
219 
220  // load constant table
221  if(eventLoop->GetCalib(table_name, table))
222  jout << "Error loading " + table_name + " !" << endl;
223 
224 
225  // check that the size of the tables loaded are correct
226  if( (int)table.size() != psGeom.NUM_FINE_COLUMNS ) {
227  sprintf(str, "PS table loaded with wrong size! number of columns=%d (should be %d)",
228  (int)table.size(), psGeom.NUM_FINE_COLUMNS );
229  cerr << str << endl;
230  throw JException(str);
231  }
232 
233  for( int column=0; column < psGeom.NUM_FINE_COLUMNS; column++) {
234  if( (int)table[column].size() != psGeom.NUM_ARMS ) {
235  sprintf(str, "PS table loaded with wrong size! column=%d number of arms=%d (should be %d)",
236  column, (int)table[column].size(), psGeom.NUM_ARMS );
237  cerr << str << endl;
238  throw JException(str);
239  }
240  }
241 }
242 
243 //------------------------------------
244 // GetConstant
245 // Allow a few different interfaces
246 //
247 // PS Geometry as defined in the Translation Table:
248 // arm: North/South (0/1)
249 // column: 1-145
250 // Note the different counting schemes used
251 //------------------------------------
252 const double DPSHit_factory::GetConstant( const ps_digi_constants_t &the_table,
253  const DPSGeometry::Arm in_arm, const int in_column,
254  const DPSGeometry &psGeom ) const
255 {
256  char str[256];
257 
258  if( (in_arm != DPSGeometry::kNorth) && (in_arm != DPSGeometry::kSouth)) {
259  sprintf(str, "Bad arm requested in DPSHit_factory::GetConstant()! requested=%d , should be 0-%d",
260  static_cast<int>(in_arm), static_cast<int>(DPSGeometry::kSouth));
261  cerr << str << endl;
262  throw JException(str);
263  }
264  if( (in_column <= 0) || (in_column > psGeom.NUM_FINE_COLUMNS)) {
265  sprintf(str, "Bad column # requested in DPSHit_factory::GetConstant()! requested=%d , should be 1-%d", in_column, psGeom.NUM_FINE_COLUMNS);
266  cerr << str << endl;
267  throw JException(str);
268  }
269 
270  // the tables are indexed by column, with the different values for the two arms
271  // stored in the two fields of the pair
272  if(in_arm == DPSGeometry::kNorth) {
273  return the_table[in_column-1][in_arm];
274  } else {
275  return the_table[in_column-1][in_arm];
276  }
277 }
278 
279 const double DPSHit_factory::GetConstant( const ps_digi_constants_t &the_table,
280  const DPSHit *in_hit, const DPSGeometry &psGeom ) const
281 {
282  char str[256];
283 
284  if( (in_hit->arm != DPSGeometry::kNorth) && (in_hit->arm != DPSGeometry::kSouth)) {
285  sprintf(str, "Bad arm requested in DPSHit_factory::GetConstant()! requested=%d , should be 0-%d",
286  static_cast<int>(in_hit->arm), static_cast<int>(DPSGeometry::kSouth));
287  cerr << str << endl;
288  throw JException(str);
289  }
290  if( (in_hit->column <= 0) || (in_hit->column > psGeom.NUM_FINE_COLUMNS)) {
291  sprintf(str, "Bad column # requested in DPSHit_factory::GetConstant()! requested=%d , should be 1-%d", in_hit->column, psGeom.NUM_FINE_COLUMNS);
292  cerr << str << endl;
293  throw JException(str);
294  }
295 
296  // the tables are indexed by column, with the different values for the two arms
297  // stored in the two fields of the pair
298  if(in_hit->arm == DPSGeometry::kNorth) {
299  return the_table[in_hit->column-1][in_hit->arm];
300  } else {
301  return the_table[in_hit->column-1][in_hit->arm];
302  }
303 }
304 
305 const double DPSHit_factory::GetConstant( const ps_digi_constants_t &the_table,
306  const DPSDigiHit *in_digihit, const DPSGeometry &psGeom) const
307 {
308  char str[256];
309 
310  if( (in_digihit->arm != DPSGeometry::kNorth) && (in_digihit->arm != DPSGeometry::kSouth)) {
311  sprintf(str, "Bad arm requested in DPSHit_factory::GetConstant()! requested=%d , should be 0-%d",
312  static_cast<int>(in_digihit->arm), static_cast<int>(DPSGeometry::kSouth));
313  cerr << str << endl;
314  throw JException(str);
315  }
316  if( (in_digihit->column <= 0) || (in_digihit->column > psGeom.NUM_FINE_COLUMNS)) {
317  sprintf(str, "Bad column # requested in DPSHit_factory::GetConstant()! requested=%d , should be 1-%d", in_digihit->column, psGeom.NUM_FINE_COLUMNS);
318  cerr << str << endl;
319  throw JException(str);
320  }
321 
322  // the tables are indexed by column, with the different values for the two arms
323  // stored in the two fields of the pair
324  if(in_digihit->arm == DPSGeometry::kNorth) {
325  return the_table[in_digihit->column-1][in_digihit->arm];
326  } else {
327  return the_table[in_digihit->column-1][in_digihit->arm];
328  }
329 }
330 
uint32_t pulse_integral
identified pulse integral as returned by FPGA algorithm
Definition: DPSDigiHit.h:21
bool CheckFADC250_NoErrors(uint32_t QF) const
Definition: DPSHit.h:15
if(locHist_BCALShowerPhiVsZ!=NULL)
static const int NUM_ARMS
Definition: DPSGeometry.h:22
char str[256]
uint32_t pedestal
pedestal info used by FPGA (if any)
Definition: DPSDigiHit.h:23
sprintf(text,"Post KinFit Cut")
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.
jerror_t init(void)
Called once at program start.
double getEhigh(int arm, int column) const
Definition: DPSGeometry.cc:48
uint32_t pulse_peak
maximum sample in pulse
Definition: DPSDigiHit.h:27
vector< vector< double > > ps_digi_constants_t
void FillCalibTable(ps_digi_constants_t &table, string table_name, const DPSGeometry &psGeom)
jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber)
Called every event.
DPSGeometry::Arm arm
Definition: DPSDigiHit.h:19
const double GetConstant(const ps_digi_constants_t &the_table, const DPSGeometry::Arm in_arm, const int in_column, const DPSGeometry &psGeom) const
bool CheckFADC250_PedestalOK(uint32_t QF) const
jerror_t erun(void)
Called everytime run number changes, provided brun has been called.
jerror_t fini(void)
Called after last event of last event source has been processed.
uint32_t QF
Quality Factor from FPGA algorithms.
Definition: DPSDigiHit.h:24
int column
Definition: DPSDigiHit.h:20
uint32_t pulse_time
identified pulse time as returned by FPGA algorithm
Definition: DPSDigiHit.h:22
static TH1I * pedestal[nChan]
uint32_t nsamples_pedestal
number of samples used in pedestal
Definition: DPSDigiHit.h:26
DPSGeometry::Arm arm
Definition: DPSHit.h:19
static const int NUM_FINE_COLUMNS
Definition: DPSGeometry.h:26
int column
Definition: DPSHit.h:20
vector< double > adc_time_offsets
uint32_t nsamples_integral
number of samples used in integral
Definition: DPSDigiHit.h:25
double getElow(int arm, int column) const
Definition: DPSGeometry.cc:40