1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | #include <iostream> |
9 | #include <iomanip> |
10 | #include <cmath> |
11 | #include <vector> |
12 | #include <limits> |
13 | using namespace std; |
14 | |
15 | #include "DPSCHit_factory.h" |
16 | #include "DPSCDigiHit.h" |
17 | #include "DPSCTDCDigiHit.h" |
18 | #include <DAQ/Df250PulsePedestal.h> |
19 | #include <DAQ/Df250PulseIntegral.h> |
20 | using namespace jana; |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | jerror_t DPSCHit_factory::init(void) |
27 | { |
28 | DELTA_T_ADC_TDC_MAX = 4.0; |
29 | gPARMS->SetDefaultParameter("PSCHit:DELTA_T_ADC_TDC_MAX", DELTA_T_ADC_TDC_MAX, |
30 | "Maximum difference in ns between a (calibrated) fADC time and" |
31 | " F1TDC time for them to be matched in a single hit"); |
32 | ADC_THRESHOLD = 500.0; |
33 | gPARMS->SetDefaultParameter("PSCHit:ADC_THRESHOLD",ADC_THRESHOLD, |
34 | "pedestal-subtracted pulse integral threshold"); |
35 | |
36 | |
37 | a_scale = 0.0001; |
38 | t_scale = 0.0625; |
39 | t_base = 0.; |
40 | t_tdc_base = 0.; |
41 | |
42 | return NOERROR; |
43 | } |
44 | |
45 | |
46 | |
47 | |
48 | jerror_t DPSCHit_factory::brun(jana::JEventLoop *eventLoop, int runnumber) |
49 | { |
50 | |
51 | static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, { 0, 0 } } }; |
52 | static set<int> runs_announced; |
53 | pthread_mutex_lock(&print_mutex); |
54 | bool print_messages = false; |
55 | if(runs_announced.find(runnumber) == runs_announced.end()){ |
56 | print_messages = true; |
57 | runs_announced.insert(runnumber); |
58 | } |
59 | pthread_mutex_unlock(&print_mutex); |
60 | |
61 | |
62 | if(print_messages) jout << "In DPSCHit_factory, loading constants..." << endl; |
63 | |
64 | |
65 | vector<const DPSGeometry*> psGeomVect; |
66 | eventLoop->Get( psGeomVect ); |
67 | if (psGeomVect.size() < 1) |
68 | return OBJECT_NOT_AVAILABLE; |
69 | const DPSGeometry& psGeom = *(psGeomVect[0]); |
70 | |
71 | |
72 | map<string,double> scale_factors; |
73 | if (eventLoop->GetCalib("/PHOTON_BEAM/pair_spectrometer/digi_scales", scale_factors)) |
74 | jout << "Error loading /PHOTON_BEAM/pair_spectrometer/digi_scales !" << endl; |
75 | if (scale_factors.find("PSC_ADC_ASCALE") != scale_factors.end()) |
76 | a_scale = scale_factors["PSC_ADC_ASCALE"]; |
77 | else |
78 | jerr << "Unable to get PSC_ADC_ASCALE from /PHOTON_BEAM/pair_spectrometer/digi_scales !" |
79 | << endl; |
80 | if (scale_factors.find("PSC_ADC_TSCALE") != scale_factors.end()) |
81 | t_scale = scale_factors["PSC_ADC_TSCALE"]; |
82 | else |
83 | jerr << "Unable to get PSC_ADC_TSCALE from /PHOTON_BEAM/pair_spectrometer/digi_scales !" |
84 | << endl; |
85 | |
86 | |
87 | map<string,double> base_time_offset; |
88 | if (eventLoop->GetCalib("/PHOTON_BEAM/pair_spectrometer/base_time_offset",base_time_offset)) |
89 | jout << "Error loading /PHOTON_BEAM/pair_spectrometer/base_time_offset !" << endl; |
90 | if (base_time_offset.find("PS_COARSE_BASE_TIME_OFFSET") != base_time_offset.end()) |
91 | t_base = base_time_offset["PS_COARSE_BASE_TIME_OFFSET"]; |
92 | else |
93 | jerr << "Unable to get PS_COARSE_BASE_TIME_OFFSET from /PHOTON_BEAM/pair_spectrometer/base_time_offset !" << endl; |
94 | |
95 | if (base_time_offset.find("PS_COARSE_TDC_BASE_TIME_OFFSET") != base_time_offset.end()) |
96 | t_tdc_base = base_time_offset["PS_COARSE_TDC_BASE_TIME_OFFSET"]; |
97 | else |
98 | jerr << "Unable to get PS_COARSE_TDC_BASE_TIME_OFFSET from /PHOTON_BEAM/pair_spectrometer/base_time_offset !" << endl; |
99 | |
100 | |
101 | vector<double> raw_adc_pedestals; |
102 | vector<double> raw_adc_gains; |
103 | vector<double> raw_adc_offsets; |
104 | vector<double> raw_tdc_offsets; |
105 | |
106 | |
107 | if(eventLoop->GetCalib("/PHOTON_BEAM/pair_spectrometer/coarse/adc_pedestals", raw_adc_pedestals)) |
108 | jout << "Error loading /PHOTON_BEAM/pair_spectrometer/coarse/adc_pedestals !" << endl; |
109 | if(eventLoop->GetCalib("/PHOTON_BEAM/pair_spectrometer/coarse/adc_gain_factors", raw_adc_gains)) |
110 | jout << "Error loading /PHOTON_BEAM/pair_spectrometer/coarse/adc_gain_factors !" << endl; |
111 | if(eventLoop->GetCalib("/PHOTON_BEAM/pair_spectrometer/coarse/adc_timing_offsets", raw_adc_offsets)) |
112 | jout << "Error loading /PHOTON_BEAM/pair_spectrometer/coarse/adc_timing_offsets !" << endl; |
113 | if(eventLoop->GetCalib("/PHOTON_BEAM/pair_spectrometer/coarse/tdc_timing_offsets", raw_tdc_offsets)) |
114 | jout << "Error loading /PHOTON_BEAM/pair_spectrometer/coarse/tdc_timing_offsets !" << endl; |
115 | |
116 | |
117 | FillCalibTable(adc_pedestals, raw_adc_pedestals, psGeom); |
118 | FillCalibTable(adc_gains, raw_adc_gains, psGeom); |
119 | FillCalibTable(adc_time_offsets, raw_adc_offsets, psGeom); |
120 | FillCalibTable(tdc_time_offsets, raw_tdc_offsets, psGeom); |
121 | |
122 | |
123 | if (eventLoop->GetCalib("/PHOTON_BEAM/pair_spectrometer/tdc_timewalk_corrections", tw_parameters)) |
124 | jout << "Error loading /PHOTON_BEAM/pair_spectrometer/tdc_timewalk_corrections !" << endl; |
125 | |
126 | return NOERROR; |
127 | } |
128 | |
129 | |
130 | |
131 | |
132 | jerror_t DPSCHit_factory::evnt(JEventLoop *loop, int eventnumber) |
133 | { |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | vector<const DPSGeometry*> psGeomVect; |
145 | eventLoop->Get(psGeomVect); |
146 | if (psGeomVect.size() < 1) |
147 | return OBJECT_NOT_AVAILABLE; |
148 | const DPSGeometry& psGeom = *(psGeomVect[0]); |
149 | |
150 | const DTTabUtilities* locTTabUtilities = NULL__null; |
151 | loop->GetSingle(locTTabUtilities); |
152 | |
153 | |
154 | vector<const DPSCDigiHit*> digihits; |
155 | loop->Get(digihits); |
156 | char str[256]; |
157 | |
158 | for (unsigned int i=0; i < digihits.size(); i++){ |
159 | const DPSCDigiHit *digihit = digihits[i]; |
160 | |
161 | |
162 | const int PSC_MAX_CHANNELS = psGeom.NUM_COARSE_COLUMNS*psGeom.NUM_ARMS; |
163 | if( (digihit->counter_id <= 0) || (digihit->counter_id > PSC_MAX_CHANNELS)) { |
164 | sprintf(str, "DPSCDigiHit sector out of range! sector=%d (should be 1-%d)", |
165 | digihit->counter_id, PSC_MAX_CHANNELS); |
166 | throw JException(str); |
167 | } |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | const Df250PulsePedestal* PPobj = NULL__null; |
174 | digihit->GetSingle(PPobj); |
175 | if (PPobj != NULL__null){ |
176 | if (PPobj->pedestal == 0 || PPobj->pulse_peak == 0) continue; |
177 | } |
178 | else continue; |
179 | |
180 | |
181 | |
182 | double pedestal = GetConstant(adc_pedestals,digihit,psGeom); |
| Value stored to 'pedestal' during its initialization is never read |
183 | const Df250PulseIntegral* PIobj = NULL__null; |
184 | digihit->GetSingle(PIobj); |
185 | if (PIobj != NULL__null) { |
186 | |
187 | |
188 | |
189 | double ped_sum = (double)PIobj->pedestal; |
190 | double nsamples_integral = (double)PIobj->nsamples_integral; |
191 | double nsamples_pedestal = (double)PIobj->nsamples_pedestal; |
192 | pedestal = ped_sum * nsamples_integral/nsamples_pedestal; |
193 | } |
194 | else continue; |
195 | |
196 | |
197 | double P = PPobj->pulse_peak - PPobj->pedestal; |
198 | double A = (double)digihit->pulse_integral; |
199 | A -= pedestal; |
200 | |
201 | if (A < ADC_THRESHOLD) continue; |
202 | double T = (double)digihit->pulse_time; |
203 | |
204 | DPSCHit *hit = new DPSCHit; |
205 | hit->arm = GetArm(digihit->counter_id,psGeom.NUM_COARSE_COLUMNS); |
206 | hit->module = GetModule(digihit->counter_id,psGeom.NUM_COARSE_COLUMNS); |
207 | hit->integral = A; |
208 | hit->pulse_peak = P; |
209 | hit->npe_fadc = A * a_scale * GetConstant(adc_gains, digihit, psGeom); |
210 | hit->time_fadc = t_scale * T - GetConstant(adc_time_offsets, digihit, psGeom) + t_base; |
211 | hit->t = hit->time_fadc; |
212 | hit->time_tdc = numeric_limits<double>::quiet_NaN(); |
213 | hit->has_fADC = true; |
214 | hit->has_TDC = false; |
215 | |
216 | hit->AddAssociatedObject(digihit); |
217 | |
218 | _data.push_back(hit); |
219 | } |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | vector<const DPSCTDCDigiHit*> tdcdigihits; |
226 | loop->Get(tdcdigihits); |
227 | |
228 | for(unsigned int i=0; i<tdcdigihits.size(); i++) { |
229 | const DPSCTDCDigiHit *digihit = tdcdigihits[i]; |
230 | |
231 | |
232 | DPSGeometry::Arm arm = GetArm(digihit->counter_id,psGeom.NUM_COARSE_COLUMNS); |
233 | int module = GetModule(digihit->counter_id,psGeom.NUM_COARSE_COLUMNS); |
234 | |
235 | |
236 | double T = locTTabUtilities->Convert_DigiTimeToNs_F1TDC(digihit) - GetConstant(tdc_time_offsets, digihit, psGeom) + t_tdc_base; |
237 | |
238 | |
239 | DPSCHit *hit = FindMatch(arm, module, T); |
240 | if (!hit) { |
241 | hit = new DPSCHit; |
242 | hit->arm = arm; |
243 | hit->module = module; |
244 | hit->time_fadc = numeric_limits<double>::quiet_NaN(); |
245 | hit->integral = numeric_limits<double>::quiet_NaN(); |
246 | hit->pulse_peak = numeric_limits<double>::quiet_NaN(); |
247 | hit->npe_fadc = numeric_limits<double>::quiet_NaN(); |
248 | hit->has_fADC = false; |
249 | _data.push_back(hit); |
250 | } |
251 | hit->time_tdc = T; |
252 | hit->has_TDC = true; |
253 | |
254 | if (hit->pulse_peak > 0) { |
255 | if (tw_parameters[module - 1][0] == 0) { |
256 | c1 = tw_parameters[module - 1][3]; |
257 | c2 = tw_parameters[module - 1][4]; |
258 | thresh = tw_parameters[module - 1][5]; |
259 | P_0 = tw_parameters[module - 1][6]; |
260 | } |
261 | else { |
262 | c1 = tw_parameters[module + 7][3]; |
263 | c2 = tw_parameters[module + 7][4]; |
264 | thresh = tw_parameters[module + 7][5]; |
265 | P_0 = tw_parameters[module + 7][6]; |
266 | } |
267 | double P = hit->pulse_peak; |
268 | T -= c1*(pow(P/thresh,c2) - pow(P_0/thresh,c2)); |
269 | } |
270 | hit->t = T; |
271 | |
272 | hit->AddAssociatedObject(digihit); |
273 | } |
274 | |
275 | return NOERROR; |
276 | } |
277 | |
278 | |
279 | |
280 | |
281 | DPSCHit* DPSCHit_factory::FindMatch(DPSGeometry::Arm arm, int module, double T) |
282 | { |
283 | DPSCHit* best_match = NULL__null; |
284 | |
285 | |
286 | |
287 | for(unsigned int i=0; i<_data.size(); i++) { |
288 | DPSCHit *hit = _data[i]; |
289 | |
290 | if(!hit->has_fADC) continue; |
291 | if(hit->arm != arm) continue; |
292 | if(hit->module != module) continue; |
293 | |
294 | double delta_T = fabs(T - hit->t); |
295 | if(delta_T > DELTA_T_ADC_TDC_MAX) continue; |
296 | |
297 | return hit; |
298 | |
299 | |
300 | if(best_match != NULL__null) { |
301 | if(delta_T < fabs(best_match->t - T)) |
302 | best_match = hit; |
303 | } else { |
304 | best_match = hit; |
305 | } |
306 | |
307 | } |
308 | |
309 | return best_match; |
310 | } |
311 | |
312 | |
313 | |
314 | |
315 | |
316 | const DPSGeometry::Arm DPSCHit_factory::GetArm(const int counter_id,const int num_counters_per_arm) const { |
317 | return counter_id <= num_counters_per_arm ? DPSGeometry::kNorth : DPSGeometry::kSouth; |
318 | } |
319 | const int DPSCHit_factory::GetModule(const int counter_id,const int num_counters_per_arm) const { |
320 | return counter_id <= num_counters_per_arm ? counter_id : counter_id - num_counters_per_arm; |
321 | } |
322 | |
323 | |
324 | |
325 | |
326 | jerror_t DPSCHit_factory::erun(void) |
327 | { |
328 | return NOERROR; |
329 | } |
330 | |
331 | |
332 | |
333 | |
334 | jerror_t DPSCHit_factory::fini(void) |
335 | { |
336 | return NOERROR; |
337 | } |
338 | |
339 | |
340 | |
341 | |
342 | void DPSCHit_factory::FillCalibTable(psc_digi_constants_t &table, vector<double> &raw_table, |
343 | const DPSGeometry &psGeom) |
344 | { |
345 | char str[256]; |
346 | const int PSC_MAX_CHANNELS = psGeom.NUM_COARSE_COLUMNS*psGeom.NUM_ARMS; |
347 | int channel = 0; |
348 | |
349 | |
350 | table.clear(); |
351 | |
352 | |
353 | for(int column=0; column<psGeom.NUM_COARSE_COLUMNS; column++) |
354 | table.push_back( pair<double,double>() ); |
355 | |
356 | |
357 | |
358 | |
359 | for(int column=0; column<psGeom.NUM_COARSE_COLUMNS; column++) { |
360 | if( column+psGeom.NUM_COARSE_COLUMNS > PSC_MAX_CHANNELS) { |
361 | sprintf(str, "Too many channels for PSC table! channel=%d (should be %d)", |
362 | channel, PSC_MAX_CHANNELS); |
363 | cerr << str << endl; |
364 | throw JException(str); |
365 | } |
366 | |
367 | table[column] = pair<double,double>(raw_table[column],raw_table[column+psGeom.NUM_COARSE_COLUMNS]); |
368 | channel += 2; |
369 | } |
370 | |
371 | |
372 | if(channel != PSC_MAX_CHANNELS) { |
373 | sprintf(str, "Not enough channels for PSC table! channel=%d (should be %d)", |
374 | channel, PSC_MAX_CHANNELS); |
375 | cerr << str << endl; |
376 | throw JException(str); |
377 | } |
378 | } |
379 | |
380 | |
381 | |
382 | |
383 | |
384 | |
385 | |
386 | |
387 | |
388 | |
389 | const double DPSCHit_factory::GetConstant( const psc_digi_constants_t &the_table, |
390 | const DPSGeometry::Arm in_arm, const int in_module, |
391 | const DPSGeometry &psGeom ) const |
392 | { |
393 | char str[256]; |
394 | |
395 | if( (in_arm != DPSGeometry::kNorth) && (in_arm != DPSGeometry::kSouth)) { |
396 | sprintf(str, "Bad arm requested in DPSCHit_factory::GetConstant()! requested=%d , should be 0-%d", |
397 | static_cast<int>(in_arm), static_cast<int>(DPSGeometry::kSouth)); |
398 | cerr << str << endl; |
399 | throw JException(str); |
400 | } |
401 | if( (in_module <= 0) || (in_module > psGeom.NUM_COARSE_COLUMNS)) { |
402 | sprintf(str, "Bad module # requested in DPSCHit_factory::GetConstant()! requested=%d , should be 1-%d", in_module, psGeom.NUM_COARSE_COLUMNS); |
403 | cerr << str << endl; |
404 | throw JException(str); |
405 | } |
406 | |
407 | |
408 | |
409 | if(in_arm == DPSGeometry::kNorth) { |
410 | return the_table[in_module-1].first; |
411 | } else { |
412 | return the_table[in_module-1].second; |
413 | } |
414 | } |
415 | |
416 | const double DPSCHit_factory::GetConstant( const psc_digi_constants_t &the_table, |
417 | const DPSCHit *in_hit, const DPSGeometry &psGeom ) const |
418 | { |
419 | char str[256]; |
420 | |
421 | if( (in_hit->arm != DPSGeometry::kNorth) && (in_hit->arm != DPSGeometry::kSouth)) { |
422 | sprintf(str, "Bad arm requested in DPSCHit_factory::GetConstant()! requested=%d , should be 0-%d", |
423 | static_cast<int>(in_hit->arm), static_cast<int>(DPSGeometry::kSouth)); |
424 | cerr << str << endl; |
425 | throw JException(str); |
426 | } |
427 | if( (in_hit->module <= 0) || (in_hit->module > psGeom.NUM_COARSE_COLUMNS)) { |
428 | sprintf(str, "Bad module # requested in DPSCHit_factory::GetConstant()! requested=%d , should be 1-%d", in_hit->module, psGeom.NUM_COARSE_COLUMNS); |
429 | cerr << str << endl; |
430 | throw JException(str); |
431 | } |
432 | |
433 | |
434 | |
435 | if(in_hit->arm == DPSGeometry::kNorth) { |
436 | return the_table[in_hit->module-1].first; |
437 | } else { |
438 | return the_table[in_hit->module-1].second; |
439 | } |
440 | } |
441 | |
442 | const double DPSCHit_factory::GetConstant( const psc_digi_constants_t &the_table, |
443 | const DPSCDigiHit *in_digihit, const DPSGeometry &psGeom) const |
444 | { |
445 | char str[256]; |
446 | |
447 | DPSGeometry::Arm arm = GetArm(in_digihit->counter_id,psGeom.NUM_COARSE_COLUMNS); |
448 | int module = GetModule(in_digihit->counter_id,psGeom.NUM_COARSE_COLUMNS); |
449 | |
450 | if( (module <= 0) || (module > psGeom.NUM_COARSE_COLUMNS)) { |
451 | sprintf(str, "Bad module # requested in DPSCHit_factory::GetConstant()! requested=%d , should be 1-%d", module, psGeom.NUM_COARSE_COLUMNS); |
452 | cerr << str << endl; |
453 | throw JException(str); |
454 | } |
455 | |
456 | |
457 | |
458 | if(arm == DPSGeometry::kNorth) { |
459 | return the_table[module-1].first; |
460 | } else { |
461 | return the_table[module-1].second; |
462 | } |
463 | } |
464 | |
465 | const double DPSCHit_factory::GetConstant( const psc_digi_constants_t &the_table, |
466 | const DPSCTDCDigiHit *in_digihit, const DPSGeometry &psGeom ) const |
467 | { |
468 | char str[256]; |
469 | |
470 | DPSGeometry::Arm arm = GetArm(in_digihit->counter_id,psGeom.NUM_COARSE_COLUMNS); |
471 | int module = GetModule(in_digihit->counter_id,psGeom.NUM_COARSE_COLUMNS); |
472 | |
473 | if( (module <= 0) || (module > psGeom.NUM_COARSE_COLUMNS)) { |
474 | sprintf(str, "Bad module # requested in DPSCHit_factory::GetConstant()! requested=%d , should be 1-%d", module, psGeom.NUM_COARSE_COLUMNS); |
475 | cerr << str << endl; |
476 | throw JException(str); |
477 | } |
478 | |
479 | |
480 | |
481 | if(arm == DPSGeometry::kNorth) { |
482 | return the_table[module-1].first; |
483 | } else { |
484 | return the_table[module-1].second; |
485 | } |
486 | } |
487 | |