ATLAS Offline Software
Loading...
Searching...
No Matches
TBPhaseRec.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6#include "TBPhaseRec.h"
7
8#include "TBEvent/TBTDCRaw.h"
10#include "TBEvent/TBPhase.h"
11#include "TBEvent/TBEventInfo.h"
12
14#include "AthenaKernel/Units.h"
15
16#include <algorithm>
17#include <cmath>
18
19#include <iostream>
20#include <fstream>
21
22using Athena::Units::ns;
23
24TBPhaseRec::TBPhaseRec(const std::string& name,
25 ISvcLocator* pSvcLocator) :
26 AthAlgorithm(name,pSvcLocator)
27 , m_delta(25.0*ns)
28 , m_timeBins(25)
29 , m_TBPhaseKey("TBPhase")
31 , m_guardValue(-1.) // in TDC counts
32 , m_nTDC(0)
33 {
34 // job options
35 declareProperty("CalibFileName",m_calib_filename="");
36 m_tdcNames.resize(0);
37 m_tdcToTime.resize(0);
38 m_tdcwac.resize(0);
39 m_tdcMin.resize(0);
40 declareProperty("TDCNames", m_tdcNames);
41 declareProperty("TDCToTime", m_tdcToTime);
42 declareProperty("TDCwac", m_tdcwac);
43 declareProperty("TDCMin", m_tdcMin);
44 declareProperty("TTCClockPeriod", m_delta);
45 declareProperty("TimeBins", m_timeBins);
46 declareProperty("TBPhaseKey", m_TBPhaseKey);
47 declareProperty("NeverReturnFailure", m_neverReturnFailure);
48 declareProperty("GuardCutValue", m_guardValue);
49 m_runnumber = 0;
50}
51
54
55StatusCode
57{
58 // check consistency of jobOptions, set defaults if required
59 float default_tdc2time = 0.050*ns;
60 float default_tdcwac = 0.;
61 float default_tdcMin = 0.;
62
63 m_nTDC = m_tdcNames.size() ;
64 if ( m_nTDC == 0 ) {
65 ATH_MSG_ERROR ( "Empty list of TDC names" );
66 return StatusCode::FAILURE ;
67 }
68
69 if (m_nTDC != (int)m_tdcToTime.size()) { // check consistency of joboption vectors
70 if (m_tdcToTime.size() == 0) {
71 m_tdcToTime.resize(m_nTDC) ;
72 for (int k = 0; k < m_nTDC; k++) m_tdcToTime[k] = default_tdc2time;
73 } else if (m_tdcToTime.size() == 1) {
74 m_tdcToTime.resize(m_nTDC);
75 float tdc2time = m_tdcToTime[0];
76 for (int k = 0; k < m_nTDC; k++) m_tdcToTime[k] = tdc2time;
77 } else {
78 ATH_MSG_FATAL ( "Nunber of TDCs not equal to nunber of tdc2time constants" );
79 return StatusCode::FAILURE ;
80 }
81 }
82
83 if (m_nTDC != (int)m_tdcwac.size()) { // check consistency of joboption vectors
84 if (m_tdcwac.size() == 0) {
85 m_tdcwac.resize(m_nTDC) ;
86 for (int k = 0; k < m_nTDC; k++) m_tdcwac[k] = default_tdcwac;
87 } else if (m_tdcwac.size() == 1) {
88 m_tdcwac.resize(m_nTDC);
89 float tdcwac = m_tdcwac[0];
90 for (int k = 0; k < m_nTDC; k++) m_tdcwac[k] = tdcwac;
91 } else {
92 ATH_MSG_FATAL ( "Nunber of TDCs not equal to nuunber of wac constants" );
93 return StatusCode::FAILURE ;
94 }
95 }
96
97 if (m_nTDC != (int)m_tdcMin.size()) { // check consistency of joboption vectors
98 if (m_tdcMin.size() == 0) {
99 m_tdcMin.resize(m_nTDC) ;
100 for (int k = 0; k < m_nTDC; k++) m_tdcMin[k] = default_tdcMin;
101 } else if (m_tdcMin.size() == 1) {
102 m_tdcMin.resize(m_nTDC);
103 float tdcMin = m_tdcMin[0];
104 for (int k = 0; k < m_nTDC; k++) m_tdcMin[k] = tdcMin;
105 } else {
106 ATH_MSG_FATAL ( "Nunber of TDCs not equal to nuunber of tdcMin constants" );
107 return StatusCode::FAILURE ;
108 }
109 }
110
112 ( "TTCClockPeriod = " << m_delta/ns << " ns" );
113 for (int k = 0; k < m_nTDC; k++) {
115 ( "\042" + m_tdcNames[k] + "\042"
116 << " PhaseTDCToTime = " << m_tdcToTime[k]/ns << " ns/TDC"
117 << " PhaseTDCwac = " << m_tdcwac[k]
118 << " PhaseTDCMin = " << m_tdcMin[k] );
119 }
120
121 m_phaseReco.resize(m_nTDC);
122 m_tdcRaw.resize(m_nTDC);
123
124 if ( m_guardValue > 0. )
125 ATH_MSG_INFO ( " Cut events using guard value: " << m_guardValue );
126
127 return StatusCode::SUCCESS ;
128}
129
130StatusCode TBPhaseRec::execute(const EventContext& ctx)
131{
132 ATH_MSG_VERBOSE ( "In execute()" );
133
134 // Get run number...
135 unsigned int thisrun=ctx.eventID().run_number();
136
137 // ... and get new calib constants (only if calibration constant file has been specified!)
138 if( thisrun != m_runnumber && m_calib_filename != "" ) {
139 m_runnumber= thisrun;
140 if ( getnewcalib() == StatusCode::FAILURE ) {
141 setFilterPassed(false, ctx);
142 return StatusCode::SUCCESS;
143 }
144 }
145
146 TBTDCRawCont * tdcRawCont = nullptr;
147 StatusCode sc = evtStore()->retrieve(tdcRawCont, "TDCRawCont");
148 if (sc.isFailure()) {
149 ATH_MSG_ERROR ( "TBObjectReco: Retrieval of TDCRawCont failed" );
151 setFilterPassed(false, ctx);
152 }
153 return StatusCode::SUCCESS;
154 }
155
156 std::vector<float> tdcQuality;
157 std::vector<float> tdcdTtoWAC;
158 tdcQuality.resize(m_nTDC);
159 tdcdTtoWAC.resize(m_nTDC);
160 for (int k = 0; k < m_nTDC; k++) {
161 m_phaseReco[k] = unknown;
162 m_tdcRaw[k] = 0;
163 tdcQuality[k] = 0.;
164 tdcdTtoWAC[k] = 0.;
165 }
166
167 // Loop over TDC's
168 int tdcFound = 0;
169 int tdcFoundAndOK = 0;
170 for (const TBTDCRaw* tdcRaw : *tdcRawCont) {
171 std::string tdcName = tdcRaw->getDetectorName();
172 int tdcIndex = 0;
173 for (; tdcIndex < m_nTDC; tdcIndex++) {
174 if (tdcName == m_tdcNames[tdcIndex]) break;
175 }
176 if (tdcIndex < m_nTDC) { // found the sought tdc
177 tdcFound++;
178
179 // get the raw tdc value
180 m_tdcRaw[tdcIndex] = tdcRaw->getTDC();
181
182 if (m_tdcRaw[tdcIndex] <= 0 || tdcRaw->isOverflow() || tdcRaw->isUnderThreshold()) {
183 // bad tdc
184 if (m_tdcRaw[tdcIndex] <= 0)
185 ATH_MSG_DEBUG ( "Bad TDC" << tdcIndex << "; value = " << m_tdcRaw[tdcIndex] );
186 if (tdcRaw->isOverflow())
187 ATH_MSG_DEBUG ( "Bad TDC" << tdcIndex << " is overflow" );
188 if (tdcRaw->isUnderThreshold())
189 ATH_MSG_DEBUG ( "Bad TDC" << tdcIndex << " is underthreshold" );
190 } else {
191 // found andvalid tdc
192 tdcFoundAndOK++;
193
194 // compute a quality factor used to decide which tdc to use for the phase
195 // lowest distance (tdc units) to tdcMin or tdcMax or tdcwac
196
197 float dTotdcMin = fabs(m_tdcRaw[tdcIndex] - m_tdcMin[tdcIndex]);
198 float tdcMax = m_tdcMin[tdcIndex] + m_delta/fabs(m_tdcToTime[tdcIndex]);
199 float dTotdcMax = fabs(m_tdcRaw[tdcIndex] - tdcMax);
200 float dTotdcwac = fabs(m_tdcRaw[tdcIndex] - m_tdcwac[tdcIndex]);
201 float dtemp = (dTotdcMin < dTotdcMax) ? dTotdcMin : dTotdcMax;
202 tdcQuality[tdcIndex] = (dtemp < dTotdcwac) ? dtemp : dTotdcwac;
203 tdcdTtoWAC[tdcIndex] = m_tdcRaw[tdcIndex] - m_tdcwac[tdcIndex];
204
206 ( "TDC" << tdcIndex << " value = " << m_tdcRaw[tdcIndex]
207 << "; tdc quality"
208 << ": to tdcMin = " << dTotdcMin
209 << "; to tdcMax = " << dTotdcMax
210 << "; to tdcwac = " << dTotdcwac
211 << "; final = " << tdcQuality[tdcIndex] );
212
213 // compute the phase
214 m_phaseReco[tdcIndex] = computePhase(tdcIndex);
215
217 ( "TDC" << tdcIndex << " value = " << m_tdcRaw[tdcIndex]
218 << "; reconstructed phase = " << m_phaseReco[tdcIndex]/ns << " ns"
219 );
220 }
221
222 if (tdcFound == m_nTDC) break ; // exit container loop if all TDCs found
223 }
224 }
225
226 if (tdcFound == 0 || tdcFoundAndOK == 0) {
227 // Check if this is a random trigger and set tdc=12.5 ns
228 // retrieve Event Info
229 const TBEventInfo* theEventInfo;
230 StatusCode checkOut = evtStore()->retrieve(theEventInfo,"TBEventInfo");
231 if ( checkOut.isFailure() )
232 {
233 ATH_MSG_ERROR ( "cannot retrieve TBEventInfo from StoreGate" );
234 setFilterPassed(false, ctx);
235 return StatusCode::SUCCESS;
236 }
237 else
238 {
239 ATH_MSG_DEBUG ( "TBEventInfo object found in TDS" );
240 }
241 int evtType = theEventInfo->getEventType();
242 ATH_MSG_DEBUG ( "Event Type found " << evtType );
243 if (evtType != 1) { // Not a physics trigger found
244 float phase = 12.5;
245 short phaseInd = (short)floor(phase/m_delta * (float)m_timeBins);
246 float tdc_to_wac = 100.;
247 TBPhase* theTBPhase = new TBPhase(phase, phaseInd, tdc_to_wac);
248 sc = evtStore()->record(theTBPhase, m_TBPhaseKey);
249 if (sc.isFailure( )) {
250 ATH_MSG_FATAL ( "Cannot record TBPhase" );
251 setFilterPassed(false, ctx); // always return failure for this one!
252 return StatusCode::SUCCESS;
253 }
254 return StatusCode::SUCCESS;
255 }
256 if (tdcFound == 0) {
257 ATH_MSG_ERROR ( "no TDCs found in StoreGate" );
258 } else {
259 ATH_MSG_ERROR ( "no valid TDC data found" );
260 }
262 setFilterPassed(false, ctx);
263 }
264 return StatusCode::SUCCESS;
265 }
266 if (tdcFound < m_nTDC || tdcFoundAndOK < m_nTDC) {
267 if (tdcFound < m_nTDC) {
268 ATH_MSG_WARNING ( "not all the requested TDCs were found in StoreGate" );
269 } else {
270 ATH_MSG_WARNING ( "not all the requested TDCs contained valid data" );
271 }
272 }
273
274 // choose/compute best phase, compute corresponding best phaseind, create TBPhase instance
275 int tdcBestIndex = 0;
276 float QMax = 0.;
277 for (int k = 0; k < m_nTDC; k++) {
278 if (tdcQuality[k] > QMax) {
279 QMax = tdcQuality[k];
280 tdcBestIndex = k;
281 }
282 }
283 float bestPhase = m_phaseReco[tdcBestIndex];
284
286 ( "best quality for TDC" << tdcBestIndex
287 << ", with reconstructed phase = " << bestPhase/ns << " ns" );
288
289 // If the tdc is working properly and if the TBPhaseRec jobOptions correctly calibrate the tdc,
290 // then this timeSampleShift should be zero always.
291 int timeSampleShift = (int)floor(bestPhase/m_delta);
292 if (timeSampleShift != 0) {
294 ( "TBPhaseRec time sample shift non zero: " << timeSampleShift );
295 }
296
297 // the phase is between 0 and the ttcClockPeriod
298 float phase = bestPhase - timeSampleShift*m_delta; // "wrapped around" phase in case of shift
299
300 // the phase index must be between 0 and m_timeBins-1
301 short phaseInd = (short)floor(phase/m_delta * (float)m_timeBins);
302 if (phaseInd < 0 || phaseInd > m_timeBins - 1) {
304 ( "Phase " << phase/ns << " ns "
305 << "has phase index " << phaseInd
306 << " outside of the bounds [0," << m_timeBins-1 << "]" );
308 setFilterPassed(false, ctx);
309 }
310 return StatusCode::SUCCESS;
311 }
312
313 // guard region cut
314 if ( m_guardValue > 0. && fabs(tdcdTtoWAC[tdcBestIndex]) < m_guardValue ) {
316 ( "Phase " << phase/ns << " ns "
317 << "has TDC-WAC " << tdcdTtoWAC[tdcBestIndex]
318 << " inside the guard region [0," << m_guardValue << "]" );
320 setFilterPassed(false, ctx);
321 }
322 return StatusCode::SUCCESS;
323 }
324
326 ( "Phase = " << phase/ns << " ns; "
327 << "phase index = " << phaseInd );
328
329 // create and store the TBPhase
330 // TBPhase* theTBPhase = new TBPhase(phase, phaseInd);
331 TBPhase* theTBPhase = new TBPhase(phase, phaseInd, tdcdTtoWAC[tdcBestIndex] );
332
333 sc = evtStore()->record(theTBPhase, m_TBPhaseKey);
334 if (sc.isFailure( )) {
335 ATH_MSG_FATAL ( "Cannot record TBPhase" );
336 setFilterPassed(false, ctx); // always return failure for this one!
337 return StatusCode::SUCCESS;
338 }
339
340 return StatusCode::SUCCESS;
341
342}
343
345 return StatusCode::SUCCESS;
346}
347
348float TBPhaseRec::computePhase(int tdcIndex) {
349
350 float phaseReco = m_tdcToTime[tdcIndex] * ((float)m_tdcRaw[tdcIndex] - m_tdcwac[tdcIndex]);
351 if (m_tdcToTime[tdcIndex] > 0.) {
352 if ((float)m_tdcRaw[tdcIndex] < m_tdcwac[tdcIndex]) phaseReco += m_delta;
353 } else {
354 if ((float)m_tdcRaw[tdcIndex] > m_tdcwac[tdcIndex]) phaseReco += m_delta;
355 }
356
357 return phaseReco ;
358}
359
360
361
363 //
364 // Get calib constant from an ASCII file with the following structure :
365 //
366 // runnumber
367 // tdcnumber TDCToTime TDCwac TDCMin
368 // ...
369
370 ATH_MSG_INFO ( "Get TDC calibration constants for run " << m_runnumber);
371
372 int tdcnumber= m_tdcNames.size();
373
374 m_tdcToTime.clear(); m_tdcToTime.resize(tdcnumber);
375 m_tdcwac.clear(); m_tdcwac.resize(tdcnumber);
376 m_tdcMin.clear(); m_tdcMin.resize(tdcnumber);
377
378 // find file in share directory
380
381 std::ifstream calibfile;
382 calibfile.open(m_calib_filename.c_str());
383 if (!calibfile.good()) {
384 ATH_MSG_INFO ( "Problem with calibration file "<< m_calib_filename );
385 return StatusCode::FAILURE;
386 }
387
388 int pos = -1 ;
389 int runnumber = 0, prevrunnumber = 0;
390
391 /*
392
393 Parsing of TDC calibration constants file
394
395 Loop is exited when a run number bigger then the current is found: calibration constants of
396 previous available run will be used, last step is used only to define interval of validity
397 (TDC calibration constant obtained from a run are considered valid _from_ that run (included)
398 since the next one used for TDC calibration)
399
400 If the calibration constants file has only one line, or provide calibration constants for run
401 numbers smaller than the current one, or a empty line is found, the last read TDC calibration
402 constants are used but a warning message is issued.
403
404 */
405
406 while ( !calibfile.eof() ) {
407 prevrunnumber = runnumber ;
408 runnumber = -1 ;
409 calibfile >> runnumber;
410 if ( runnumber==-1 ) { // reached an empty line
411 ATH_MSG_WARNING ( "Empty line found in " << m_calib_filename );
412 calibfile.clear();
413 runnumber = prevrunnumber ;
414 break ;
415 }
416 if ( runnumber > int(m_runnumber) ) break ;
417 pos = calibfile.tellg();
418 for(int j=0; j<tdcnumber+1; j++) calibfile.ignore(5000,'\n'); // discard next lines
419 }
420
421 // this take care of the case in which only one line is present in the file,
422 // and the corresponding run number is greater than the current one
423 if ( pos == -1 ) {
424 pos = calibfile.tellg();
425 prevrunnumber = runnumber ;
426 }
427 // Now we should have found a good set of constant (the ones following pos)
428 ATH_MSG_DEBUG ( "Position in file stream = "<< pos );
429 calibfile.seekg(pos);
430
431 ATH_MSG_INFO ( "TDC calibration constants obtained from run " << prevrunnumber );
432 if ( prevrunnumber != runnumber ) {
433 ATH_MSG_INFO ( "valid for run interval " << prevrunnumber << " - " << runnumber );
434 } else {
435 ATH_MSG_WARNING ( "TDC calibration constants could not be optimal... ");
436 }
437
438 for(int j=0;j<tdcnumber;j++) {
439 int tdcn;
440 calibfile >> tdcn;
441 calibfile >> m_tdcToTime[j];
442 calibfile >> m_tdcwac[j];
443 calibfile >> m_tdcMin[j];
444 ATH_MSG_INFO ( " * TDC n. " << tdcn );
445 ATH_MSG_INFO ( " - TDCToTime = " << m_tdcToTime[j] );
446 ATH_MSG_INFO ( " - TDCwac = " << m_tdcwac[j] );
447 ATH_MSG_INFO ( " - TDCMin = " << m_tdcMin[j] );
448 }
449
450 calibfile.close();
451
452 return StatusCode::SUCCESS;
453
454}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sc
Wrapper to avoid constant divisions when using units.
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
virtual void setFilterPassed(bool state, const EventContext &ctx) const
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
int getEventType() const
Definition TBEventInfo.h:71
std::string m_TBPhaseKey
Definition TBPhaseRec.h:45
unsigned int m_runnumber
Definition TBPhaseRec.h:49
std::string m_calib_filename
Definition TBPhaseRec.h:48
static const int unknown
Definition TBPhaseRec.h:33
std::vector< float > m_tdcwac
Definition TBPhaseRec.h:41
virtual ~TBPhaseRec()
int m_timeBins
Definition TBPhaseRec.h:44
virtual StatusCode finalize() override
std::vector< float > m_phaseReco
Definition TBPhaseRec.h:59
float m_delta
Definition TBPhaseRec.h:43
TBPhaseRec(const std::string &name, ISvcLocator *pSvcLocator)
float computePhase(int tdcIndex)
std::vector< std::string > m_tdcNames
Definition TBPhaseRec.h:39
StatusCode getnewcalib()
virtual StatusCode initialize() override
virtual StatusCode execute(const EventContext &ctx) override
Execute method.
std::vector< float > m_tdcMin
Definition TBPhaseRec.h:42
std::vector< int > m_tdcRaw
Definition TBPhaseRec.h:58
bool m_neverReturnFailure
Definition TBPhaseRec.h:46
std::vector< float > m_tdcToTime
Definition TBPhaseRec.h:40
float m_guardValue
Definition TBPhaseRec.h:51
"TBEvent/TBTDCRawCont.h"
Data object holding tdc measurement.
Definition TBTDCRaw.h:21
static std::vector< uint32_t > runnumber
Definition iLumiCalc.h:37