ATLAS Offline Software
TBPhaseRec.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
6 #include "TBPhaseRec.h"
7 
8 #include "TBEvent/TBTDCRaw.h"
9 #include "TBEvent/TBTDCRawCont.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 
22 using Athena::Units::ns;
23 
24 TBPhaseRec::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")
30  , m_neverReturnFailure(false)
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 
53 { }
54 
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;
148  StatusCode sc = evtStore()->retrieve(tdcRawCont, "TDCRawCont");
149  if (sc.isFailure()) {
150  ATH_MSG_ERROR ( "TBObjectReco: Retrieval of TDCRawCont failed" );
151  if (!m_neverReturnFailure) {
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  }
262  if (!m_neverReturnFailure) {
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 << "]" );
308  if (!m_neverReturnFailure) {
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 << "]" );
320  if (!m_neverReturnFailure) {
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 
349 float 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 }
TBTDCRaw
Definition: TBTDCRaw.h:21
ReadOfcFromCool.phase
phase
Definition: ReadOfcFromCool.py:127
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
TBPhaseRec::m_tdcMin
std::vector< float > m_tdcMin
Definition: TBPhaseRec.h:42
xAOD::short
short
Definition: Vertex_v1.cxx:165
TBPhaseRec::m_timeBins
int m_timeBins
Definition: TBPhaseRec.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
TBPhaseRec::m_delta
float m_delta
Definition: TBPhaseRec.h:43
PathResolver::find_file
static std::string find_file(const std::string &logical_file_name, const std::string &search_path, SearchType search_type=LocalSearch)
Definition: PathResolver.cxx:251
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
TBPhaseRec::m_guardValue
float m_guardValue
Definition: TBPhaseRec.h:51
TBEventInfo::getEventType
int getEventType() const
Definition: TBEventInfo.h:66
TBPhaseRec::m_tdcRaw
std::vector< int > m_tdcRaw
Definition: TBPhaseRec.h:58
TBPhaseRec::getnewcalib
StatusCode getnewcalib()
Definition: TBPhaseRec.cxx:363
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
TBPhaseRec::m_tdcwac
std::vector< float > m_tdcwac
Definition: TBPhaseRec.h:41
TBPhaseRec::m_calib_filename
std::string m_calib_filename
Definition: TBPhaseRec.h:48
TBPhaseRec::m_TBPhaseKey
std::string m_TBPhaseKey
Definition: TBPhaseRec.h:45
TBPhaseRec::TBPhaseRec
TBPhaseRec(const std::string &name, ISvcLocator *pSvcLocator)
Definition: TBPhaseRec.cxx:24
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
TBPhaseRec::finalize
virtual StatusCode finalize() override
Definition: TBPhaseRec.cxx:345
TBPhaseRec::unknown
static const int unknown
Definition: TBPhaseRec.h:33
AthCommonDataStore< AthCommonMsg< Algorithm > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
TBTDCRawCont.h
TBPhaseRec::~TBPhaseRec
virtual ~TBPhaseRec()
Definition: TBPhaseRec.cxx:52
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TBPhaseRec::m_runnumber
unsigned int m_runnumber
Definition: TBPhaseRec.h:49
TBPhaseRec::m_nTDC
int m_nTDC
Definition: TBPhaseRec.h:57
TBPhaseRec::m_neverReturnFailure
bool m_neverReturnFailure
Definition: TBPhaseRec.h:46
TBTDCRawCont
Definition: TBTDCRawCont.h:21
AthAlgorithm
Definition: AthAlgorithm.h:47
DeMoScan.runnumber
runnumber
Definition: DeMoScan.py:266
TBPhaseRec::m_tdcNames
std::vector< std::string > m_tdcNames
Definition: TBPhaseRec.h:39
PathResolver.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
TBPhaseRec::m_tdcToTime
std::vector< float > m_tdcToTime
Definition: TBPhaseRec.h:40
TBPhaseRec::m_phaseReco
std::vector< float > m_phaseReco
Definition: TBPhaseRec.h:59
Units.h
Wrapper to avoid constant divisions when using units.
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
TBPhase
Definition: TBPhase.h:22
TBEventInfo
Definition: TBEventInfo.h:27
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
TBPhaseRec.h
TBTDCRaw.h
TBPhaseRec::computePhase
float computePhase(int tdcIndex)
Definition: TBPhaseRec.cxx:349
TBPhase.h
TBPhaseRec::initialize
virtual StatusCode initialize() override
Definition: TBPhaseRec.cxx:56
python.SystemOfUnits.ns
int ns
Definition: SystemOfUnits.py:130
TBEventInfo.h
readCCLHist.float
float
Definition: readCCLHist.py:83
TBPhaseRec::execute
virtual StatusCode execute() override
Definition: TBPhaseRec.cxx:130
fitman.k
k
Definition: fitman.py:528