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
131{
132 ATH_MSG_VERBOSE ( "In execute()" );
133 const EventContext& ctx = Gaudi::Hive::currentContext();
134
135 // Get run number...
136 unsigned int thisrun=ctx.eventID().run_number();
137
138 // ... and get new calib constants (only if calibration constant file has been specified!)
139 if( thisrun != m_runnumber && m_calib_filename != "" ) {
140 m_runnumber= thisrun;
141 if ( getnewcalib() == StatusCode::FAILURE ) {
142 setFilterPassed(false);
143 return StatusCode::SUCCESS;
144 }
145 }
146
147 TBTDCRawCont * tdcRawCont = nullptr;
148 StatusCode sc = evtStore()->retrieve(tdcRawCont, "TDCRawCont");
149 if (sc.isFailure()) {
150 ATH_MSG_ERROR ( "TBObjectReco: Retrieval of TDCRawCont failed" );
152 setFilterPassed(false);
153 }
154 return StatusCode::SUCCESS;
155 }
156
157 std::vector<float> tdcQuality;
158 std::vector<float> tdcdTtoWAC;
159 tdcQuality.resize(m_nTDC);
160 tdcdTtoWAC.resize(m_nTDC);
161 for (int k = 0; k < m_nTDC; k++) {
162 m_phaseReco[k] = unknown;
163 m_tdcRaw[k] = 0;
164 tdcQuality[k] = 0.;
165 tdcdTtoWAC[k] = 0.;
166 }
167
168 // Loop over TDC's
169 int tdcFound = 0;
170 int tdcFoundAndOK = 0;
171 for (const TBTDCRaw* tdcRaw : *tdcRawCont) {
172 std::string tdcName = tdcRaw->getDetectorName();
173 int tdcIndex = 0;
174 for (; tdcIndex < m_nTDC; tdcIndex++) {
175 if (tdcName == m_tdcNames[tdcIndex]) break;
176 }
177 if (tdcIndex < m_nTDC) { // found the sought tdc
178 tdcFound++;
179
180 // get the raw tdc value
181 m_tdcRaw[tdcIndex] = tdcRaw->getTDC();
182
183 if (m_tdcRaw[tdcIndex] <= 0 || tdcRaw->isOverflow() || tdcRaw->isUnderThreshold()) {
184 // bad tdc
185 if (m_tdcRaw[tdcIndex] <= 0)
186 ATH_MSG_DEBUG ( "Bad TDC" << tdcIndex << "; value = " << m_tdcRaw[tdcIndex] );
187 if (tdcRaw->isOverflow())
188 ATH_MSG_DEBUG ( "Bad TDC" << tdcIndex << " is overflow" );
189 if (tdcRaw->isUnderThreshold())
190 ATH_MSG_DEBUG ( "Bad TDC" << tdcIndex << " is underthreshold" );
191 } else {
192 // found andvalid tdc
193 tdcFoundAndOK++;
194
195 // compute a quality factor used to decide which tdc to use for the phase
196 // lowest distance (tdc units) to tdcMin or tdcMax or tdcwac
197
198 float dTotdcMin = fabs(m_tdcRaw[tdcIndex] - m_tdcMin[tdcIndex]);
199 float tdcMax = m_tdcMin[tdcIndex] + m_delta/fabs(m_tdcToTime[tdcIndex]);
200 float dTotdcMax = fabs(m_tdcRaw[tdcIndex] - tdcMax);
201 float dTotdcwac = fabs(m_tdcRaw[tdcIndex] - m_tdcwac[tdcIndex]);
202 float dtemp = (dTotdcMin < dTotdcMax) ? dTotdcMin : dTotdcMax;
203 tdcQuality[tdcIndex] = (dtemp < dTotdcwac) ? dtemp : dTotdcwac;
204 tdcdTtoWAC[tdcIndex] = m_tdcRaw[tdcIndex] - m_tdcwac[tdcIndex];
205
207 ( "TDC" << tdcIndex << " value = " << m_tdcRaw[tdcIndex]
208 << "; tdc quality"
209 << ": to tdcMin = " << dTotdcMin
210 << "; to tdcMax = " << dTotdcMax
211 << "; to tdcwac = " << dTotdcwac
212 << "; final = " << tdcQuality[tdcIndex] );
213
214 // compute the phase
215 m_phaseReco[tdcIndex] = computePhase(tdcIndex);
216
218 ( "TDC" << tdcIndex << " value = " << m_tdcRaw[tdcIndex]
219 << "; reconstructed phase = " << m_phaseReco[tdcIndex]/ns << " ns"
220 );
221 }
222
223 if (tdcFound == m_nTDC) break ; // exit container loop if all TDCs found
224 }
225 }
226
227 if (tdcFound == 0 || tdcFoundAndOK == 0) {
228 // Check if this is a random trigger and set tdc=12.5 ns
229 // retrieve Event Info
230 const TBEventInfo* theEventInfo;
231 StatusCode checkOut = evtStore()->retrieve(theEventInfo,"TBEventInfo");
232 if ( checkOut.isFailure() )
233 {
234 ATH_MSG_ERROR ( "cannot retrieve TBEventInfo from StoreGate" );
235 setFilterPassed(false);
236 return StatusCode::SUCCESS;
237 }
238 else
239 {
240 ATH_MSG_DEBUG ( "TBEventInfo object found in TDS" );
241 }
242 int evtType = theEventInfo->getEventType();
243 ATH_MSG_DEBUG ( "Event Type found " << evtType );
244 if (evtType != 1) { // Not a physics trigger found
245 float phase = 12.5;
246 short phaseInd = (short)floor(phase/m_delta * (float)m_timeBins);
247 float tdc_to_wac = 100.;
248 TBPhase* theTBPhase = new TBPhase(phase, phaseInd, tdc_to_wac);
249 sc = evtStore()->record(theTBPhase, m_TBPhaseKey);
250 if (sc.isFailure( )) {
251 ATH_MSG_FATAL ( "Cannot record TBPhase" );
252 setFilterPassed(false); // always return failure for this one!
253 return StatusCode::SUCCESS;
254 }
255 return StatusCode::SUCCESS;
256 }
257 if (tdcFound == 0) {
258 ATH_MSG_ERROR ( "no TDCs found in StoreGate" );
259 } else {
260 ATH_MSG_ERROR ( "no valid TDC data found" );
261 }
263 setFilterPassed(false);
264 }
265 return StatusCode::SUCCESS;
266 }
267 if (tdcFound < m_nTDC || tdcFoundAndOK < m_nTDC) {
268 if (tdcFound < m_nTDC) {
269 ATH_MSG_WARNING ( "not all the requested TDCs were found in StoreGate" );
270 } else {
271 ATH_MSG_WARNING ( "not all the requested TDCs contained valid data" );
272 }
273 }
274
275 // choose/compute best phase, compute corresponding best phaseind, create TBPhase instance
276 int tdcBestIndex = 0;
277 float QMax = 0.;
278 for (int k = 0; k < m_nTDC; k++) {
279 if (tdcQuality[k] > QMax) {
280 QMax = tdcQuality[k];
281 tdcBestIndex = k;
282 }
283 }
284 float bestPhase = m_phaseReco[tdcBestIndex];
285
287 ( "best quality for TDC" << tdcBestIndex
288 << ", with reconstructed phase = " << bestPhase/ns << " ns" );
289
290 // If the tdc is working properly and if the TBPhaseRec jobOptions correctly calibrate the tdc,
291 // then this timeSampleShift should be zero always.
292 int timeSampleShift = (int)floor(bestPhase/m_delta);
293 if (timeSampleShift != 0) {
295 ( "TBPhaseRec time sample shift non zero: " << timeSampleShift );
296 }
297
298 // the phase is between 0 and the ttcClockPeriod
299 float phase = bestPhase - timeSampleShift*m_delta; // "wrapped around" phase in case of shift
300
301 // the phase index must be between 0 and m_timeBins-1
302 short phaseInd = (short)floor(phase/m_delta * (float)m_timeBins);
303 if (phaseInd < 0 || phaseInd > m_timeBins - 1) {
305 ( "Phase " << phase/ns << " ns "
306 << "has phase index " << phaseInd
307 << " outside of the bounds [0," << m_timeBins-1 << "]" );
309 setFilterPassed(false);
310 }
311 return StatusCode::SUCCESS;
312 }
313
314 // guard region cut
315 if ( m_guardValue > 0. && fabs(tdcdTtoWAC[tdcBestIndex]) < m_guardValue ) {
317 ( "Phase " << phase/ns << " ns "
318 << "has TDC-WAC " << tdcdTtoWAC[tdcBestIndex]
319 << " inside the guard region [0," << m_guardValue << "]" );
321 setFilterPassed(false);
322 }
323 return StatusCode::SUCCESS;
324 }
325
327 ( "Phase = " << phase/ns << " ns; "
328 << "phase index = " << phaseInd );
329
330 // create and store the TBPhase
331 // TBPhase* theTBPhase = new TBPhase(phase, phaseInd);
332 TBPhase* theTBPhase = new TBPhase(phase, phaseInd, tdcdTtoWAC[tdcBestIndex] );
333
334 sc = evtStore()->record(theTBPhase, m_TBPhaseKey);
335 if (sc.isFailure( )) {
336 ATH_MSG_FATAL ( "Cannot record TBPhase" );
337 setFilterPassed(false); // always return failure for this one!
338 return StatusCode::SUCCESS;
339 }
340
341 return StatusCode::SUCCESS;
342
343}
344
346 return StatusCode::SUCCESS;
347}
348
349float TBPhaseRec::computePhase(int tdcIndex) {
350
351 float phaseReco = m_tdcToTime[tdcIndex] * ((float)m_tdcRaw[tdcIndex] - m_tdcwac[tdcIndex]);
352 if (m_tdcToTime[tdcIndex] > 0.) {
353 if ((float)m_tdcRaw[tdcIndex] < m_tdcwac[tdcIndex]) phaseReco += m_delta;
354 } else {
355 if ((float)m_tdcRaw[tdcIndex] > m_tdcwac[tdcIndex]) phaseReco += m_delta;
356 }
357
358 return phaseReco ;
359}
360
361
362
364 //
365 // Get calib constant from an ASCII file with the following structure :
366 //
367 // runnumber
368 // tdcnumber TDCToTime TDCwac TDCMin
369 // ...
370
371 ATH_MSG_INFO ( "Get TDC calibration constants for run " << m_runnumber);
372
373 int tdcnumber= m_tdcNames.size();
374
375 m_tdcToTime.clear(); m_tdcToTime.resize(tdcnumber);
376 m_tdcwac.clear(); m_tdcwac.resize(tdcnumber);
377 m_tdcMin.clear(); m_tdcMin.resize(tdcnumber);
378
379 // find file in share directory
381
382 std::ifstream calibfile;
383 calibfile.open(m_calib_filename.c_str());
384 if (!calibfile.good()) {
385 ATH_MSG_INFO ( "Problem with calibration file "<< m_calib_filename );
386 return StatusCode::FAILURE;
387 }
388
389 int pos = -1 ;
390 int runnumber = 0, prevrunnumber = 0;
391
392 /*
393
394 Parsing of TDC calibration constants file
395
396 Loop is exited when a run number bigger then the current is found: calibration constants of
397 previous available run will be used, last step is used only to define interval of validity
398 (TDC calibration constant obtained from a run are considered valid _from_ that run (included)
399 since the next one used for TDC calibration)
400
401 If the calibration constants file has only one line, or provide calibration constants for run
402 numbers smaller than the current one, or a empty line is found, the last read TDC calibration
403 constants are used but a warning message is issued.
404
405 */
406
407 while ( !calibfile.eof() ) {
408 prevrunnumber = runnumber ;
409 runnumber = -1 ;
410 calibfile >> runnumber;
411 if ( runnumber==-1 ) { // reached an empty line
412 ATH_MSG_WARNING ( "Empty line found in " << m_calib_filename );
413 calibfile.clear();
414 runnumber = prevrunnumber ;
415 break ;
416 }
417 if ( runnumber > int(m_runnumber) ) break ;
418 pos = calibfile.tellg();
419 for(int j=0; j<tdcnumber+1; j++) calibfile.ignore(5000,'\n'); // discard next lines
420 }
421
422 // this take care of the case in which only one line is present in the file,
423 // and the corresponding run number is greater than the current one
424 if ( pos == -1 ) {
425 pos = calibfile.tellg();
426 prevrunnumber = runnumber ;
427 }
428 // Now we should have found a good set of constant (the ones following pos)
429 ATH_MSG_DEBUG ( "Position in file stream = "<< pos );
430 calibfile.seekg(pos);
431
432 ATH_MSG_INFO ( "TDC calibration constants obtained from run " << prevrunnumber );
433 if ( prevrunnumber != runnumber ) {
434 ATH_MSG_INFO ( "valid for run interval " << prevrunnumber << " - " << runnumber );
435 } else {
436 ATH_MSG_WARNING ( "TDC calibration constants could not be optimal... ");
437 }
438
439 for(int j=0;j<tdcnumber;j++) {
440 int tdcn;
441 calibfile >> tdcn;
442 calibfile >> m_tdcToTime[j];
443 calibfile >> m_tdcwac[j];
444 calibfile >> m_tdcMin[j];
445 ATH_MSG_INFO ( " * TDC n. " << tdcn );
446 ATH_MSG_INFO ( " - TDCToTime = " << m_tdcToTime[j] );
447 ATH_MSG_INFO ( " - TDCwac = " << m_tdcwac[j] );
448 ATH_MSG_INFO ( " - TDCMin = " << m_tdcMin[j] );
449 }
450
451 calibfile.close();
452
453 return StatusCode::SUCCESS;
454
455}
#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 with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
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)
virtual StatusCode execute() override
std::vector< std::string > m_tdcNames
Definition TBPhaseRec.h:39
StatusCode getnewcalib()
virtual StatusCode initialize() override
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