CMS 3D CMS Logo

RunInfoRead.cc
Go to the documentation of this file.
1 //#include "CondFormats/Common/interface/TimeConversions.h"
2 //#include "CondFormats/Common/interface/Time.h"
7 #include "RelationalAccess/ISessionProxy.h"
8 #include "RelationalAccess/ITransaction.h"
9 #include "RelationalAccess/ISchema.h"
10 #include "RelationalAccess/ITable.h"
11 #include "RelationalAccess/IQuery.h"
12 #include "RelationalAccess/ICursor.h"
13 #include "CoralBase/AttributeList.h"
14 #include "CoralBase/Attribute.h"
15 #include "CoralBase/AttributeSpecification.h"
16 #include "CoralBase/TimeStamp.h"
17 #include <algorithm>
18 #include <iostream>
19 #include <iterator>
20 #include <memory>
21 #include <stdexcept>
22 #include <vector>
23 #include <cmath>
24 
25 
26 
27 namespace {
28  std::string dot(".");
29  std::string quote("\"");
30  std::string bNOTb(" NOT ");
31  std::string squoted( const std::string& s ){
32  return quote+s+quote;
33  }
34  //now strings for the tables and columns to be queried
35  std::string sParameterTable( "RUNSESSION_PARAMETER" );
36  std::string sDateTable( "RUNSESSION_DATE" );
37  std::string sStringTable( "RUNSESSION_STRING" );
38  std::string sIdParameterColumn( "ID" );
39  std::string sRunNumberParameterColumn( "RUNNUMBER" );
40  std::string sNameParameterColumn( "NAME" );
41  std::string sRunSessionParameterIdDataColumn( "RUNSESSION_PARAMETER_ID" );
42  std::string sValueDataColumn( "VALUE" );
43  std::string sDCSMagnetTable( "CMSFWMAGNET" );
44  std::string sDCSMagnetCurrentColumn( "CURRENT" );
45  std::string sDCSMagnetChangeDateColumn( "CHANGE_DATE" );
46 }
47 
48 RunInfoRead::RunInfoRead( const std::string& connectionString
49  , const edm::ParameterSet& connectionPset ):
50  m_connectionString( connectionString )
51  ,m_connectionPset( connectionPset ) {}
52 
54 
55 RunInfo
56 RunInfoRead::readData( const std::string & runinfo_schema
57  , const std::string & dcsenv_schema
58  , const int r_number ) {
59  RunInfo temp_sum;
60  //for B currents...
61  bool Bnotchanged = false;
62  //from TimeConversions.h
63  const boost::posix_time::ptime time0 = boost::posix_time::from_time_t(0);
64  //if cursor is null setting null values
65  temp_sum.m_run = r_number;
66  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: Initialising Connection Pool" << std::endl;
68  connection.setParameters( m_connectionPset );
69  connection.configure();
70  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: Initialising read-only session to " << m_connectionString << std::endl;
71  std::shared_ptr<coral::ISessionProxy> session = connection.createCoralSession( m_connectionString, false );
72  try{
73  session->transaction().start( true );
74  coral::ISchema& schema = session->schema( runinfo_schema );
75  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: Accessing schema " << runinfo_schema << std::endl;
76  //new query to obtain the start_time
77  std::unique_ptr<coral::IQuery> query( schema.newQuery() );
78  query->addToTableList( sParameterTable );
79  query->addToTableList( sDateTable );
80  query->addToOutputList( sValueDataColumn );
81  coral::AttributeList runTimeDataOutput;
82  runTimeDataOutput.extend<coral::TimeStamp>( sValueDataColumn );
83  query->defineOutput( runTimeDataOutput );
84  std::string runStartWhereClause( sRunNumberParameterColumn + std::string( "=:n_run AND " )
85  + sNameParameterColumn + std::string( "='CMS.LVL0:START_TIME_T' AND " )
86  + sIdParameterColumn + std::string( "=" ) + sRunSessionParameterIdDataColumn );
87  coral::AttributeList runNumberBindVariableList;
88  runNumberBindVariableList.extend<int>( "n_run" );
89  runNumberBindVariableList[ "n_run" ].data<int>() = r_number;
90  query->setCondition( runStartWhereClause, runNumberBindVariableList );
91  coral::ICursor& runStartCursor = query->execute();
92  coral::TimeStamp start; //now all times are UTC!
93  if( runStartCursor.next() ) {
94  std::ostringstream osstartdebug;
95  runStartCursor.currentRow().toOutputStream( osstartdebug );
96  LogDebug( "RunInfoReader" ) << osstartdebug.str() << std::endl;
97  const coral::AttributeList& row = runStartCursor.currentRow();
98  start = row[ sValueDataColumn ].data<coral::TimeStamp>();
99  LogDebug( "RunInfoReader" ) << "UTC start time extracted == "
100  << "-->year " << start.year()
101  << "-- month " << start.month()
102  << "-- day " << start.day()
103  << "-- hour " << start.hour()
104  << "-- minute " << start.minute()
105  << "-- second " << start.second()
106  << "-- nanosecond " << start.nanosecond()
107  << std::endl;
108  boost::posix_time::ptime start_ptime = start.time();
109  boost::posix_time::time_duration startTimeFromEpoch = start_ptime - time0;
110  temp_sum.m_start_time_str = boost::posix_time::to_iso_extended_string(start_ptime);
111  temp_sum.m_start_time_ll = startTimeFromEpoch.total_microseconds();
112  std::ostringstream osstart;
113  osstart << "[RunInfoRead::" << __func__ << "]: Timestamp for start of run " << r_number << std::endl
114  << "Posix time: " << start_ptime << std::endl
115  << "ISO string: " << temp_sum.m_start_time_str << std::endl
116  << "Microsecond since Epoch (UTC): " << temp_sum.m_start_time_ll;
117  edm::LogInfo( "RunInfoReader" ) << osstart.str() << std::endl;
118  }
119  else {
120  std::stringstream errMsg;
121  errMsg << "[RunInfoRead::" << __func__ << "]: run " << r_number << " start time not found.";
122  throw std::runtime_error(errMsg.str());
123  }
124 
125  //new query to obtain the stop_time
126  query.reset( schema.newQuery() );
127  query->addToTableList( sParameterTable );
128  query->addToTableList( sDateTable );
129  query->addToOutputList( sValueDataColumn );
130  query->defineOutput( runTimeDataOutput );
131  std::string runStopWhereClause( sRunNumberParameterColumn + std::string( "=:n_run AND " )
132  + sNameParameterColumn + std::string( "='CMS.LVL0:STOP_TIME_T' AND " )
133  + sIdParameterColumn + std::string( "=" ) + sRunSessionParameterIdDataColumn );
134  query->setCondition( runStopWhereClause, runNumberBindVariableList );
135  coral::ICursor& runStopCursor = query->execute();
136  coral::TimeStamp stop;
137  if( runStopCursor.next() ) {
138  std::ostringstream osstopdebug;
139  runStopCursor.currentRow().toOutputStream( osstopdebug );
140  LogDebug( "RunInfoReader" ) << osstopdebug.str() << std::endl;
141  const coral::AttributeList& row = runStopCursor.currentRow();
142  stop = row[ sValueDataColumn ].data<coral::TimeStamp>();
143  LogDebug( "RunInfoReader" ) << "stop time extracted == "
144  << "-->year " << stop.year()
145  << "-- month " << stop.month()
146  << "-- day " << stop.day()
147  << "-- hour " << stop.hour()
148  << "-- minute " << stop.minute()
149  << "-- second " << stop.second()
150  << "-- nanosecond " << stop.nanosecond()
151  << std::endl;
152  boost::posix_time::ptime stop_ptime = stop.time();
153  boost::posix_time::time_duration stopTimeFromEpoch = stop_ptime - time0;
154  temp_sum.m_stop_time_str = boost::posix_time::to_iso_extended_string(stop_ptime);
155  temp_sum.m_stop_time_ll = stopTimeFromEpoch.total_microseconds();
156  std::ostringstream osstop;
157  osstop << "[RunInfoRead::" << __func__ << "]: Timestamp for stop of run " << r_number << std::endl
158  << "Posix time: " << stop_ptime << std::endl
159  << "ISO string: " << temp_sum.m_stop_time_str << std::endl
160  << "Microsecond since Epoch (UTC): " << temp_sum.m_stop_time_ll;
161  edm::LogInfo( "RunInfoReader" ) << osstop.str() << std::endl;
162  }
163  else {
164  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: run " << r_number
165  << " stop time not found." << std::endl;
166  temp_sum.m_stop_time_str = "null";
167  temp_sum.m_stop_time_ll = -1;
168  }
169 
170  //new query for obtaining the list of FEDs included in the run
171  query.reset( schema.newQuery() );
172  query->addToTableList( sParameterTable );
173  query->addToTableList( sStringTable );
174  query->addToOutputList( sValueDataColumn );
175  query->defineOutputType( sValueDataColumn, "string" );
176  std::string fedWhereClause( sRunNumberParameterColumn + std::string( "=:n_run AND " )
177  + sNameParameterColumn + std::string( "='CMS.LVL0:FED_ENABLE_MASK' AND " )
178  + sIdParameterColumn + std::string( "=" ) + sRunSessionParameterIdDataColumn );
179  query->setCondition( fedWhereClause, runNumberBindVariableList );
180  coral::ICursor& fedCursor = query->execute();
181  std::string fed;
182  if ( fedCursor.next() ) {
183  std::ostringstream osfeddebug;
184  fedCursor.currentRow().toOutputStream( osfeddebug );
185  LogDebug( "RunInfoReader" ) << osfeddebug.str() << std::endl;
186  const coral::AttributeList& row = fedCursor.currentRow();
187  fed = row[ sValueDataColumn ].data<std::string>();
188  }
189  else {
190  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: run " << r_number
191  << "has no FED included." << std::endl;
192  fed="null";
193  }
194  std::replace(fed.begin(), fed.end(), '%', ' ');
195  std::stringstream stream(fed);
196  for(;;) {
197  std::string word;
198  if ( !(stream >> word) ){break;}
199  std::replace(word.begin(), word.end(), '&', ' ');
200  std::stringstream ss(word);
201  int fedNumber;
202  int val;
203  ss >> fedNumber >> val;
204  LogDebug( "RunInfoReader" ) << "FED: " << fedNumber << " --> value: " << val << std::endl;
205  //val bit 0 represents the status of the SLINK, but 5 and 7 means the SLINK/TTS is ON but NA or BROKEN (see mail of alex....)
206  if( (val & 0001) == 1 && (val != 5) && (val != 7) )
207  temp_sum.m_fed_in.push_back(fedNumber);
208  }
209  std::ostringstream osfed;
210  osfed << "[RunInfoRead::" << __func__ << "]: feds included in run " << r_number << ": ";
211  std::copy(temp_sum.m_fed_in.begin(), temp_sum.m_fed_in.end(), std::ostream_iterator<int>(osfed, ", "));
212  edm::LogInfo( "RunInfoReader" ) << osfed.str() << std::endl;
213 
214  //we connect now to the DCS schema in order to retrieve the magnet current
215  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: Accessing schema " << dcsenv_schema << std::endl;
216  coral::ISchema& schema2 = session->schema( dcsenv_schema );
217  query.reset( schema2.tableHandle( sDCSMagnetTable ).newQuery() );
218  query->addToOutputList( squoted( sDCSMagnetCurrentColumn ), sDCSMagnetCurrentColumn );
219  query->addToOutputList( sDCSMagnetChangeDateColumn );
220  coral::AttributeList magnetDataOutput;
221  magnetDataOutput.extend<float>( sDCSMagnetCurrentColumn );
222  magnetDataOutput.extend<coral::TimeStamp>( sDCSMagnetChangeDateColumn );
223  query->defineOutput( magnetDataOutput );
224  //condition
225  coral::AttributeList magnetCurrentBindVariableList;
226  float last_current = -1;
227  magnetCurrentBindVariableList.extend<coral::TimeStamp>( "runstart_time" );
228  magnetCurrentBindVariableList[ "runstart_time" ].data<coral::TimeStamp>() = start;
229  std::string magnetCurrentWhereClause;
230  if(temp_sum.m_stop_time_str != "null") {
231  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: Accessing the magnet currents measured during run " << r_number
232  << " between " << temp_sum.m_start_time_str
233  << " and " << temp_sum.m_stop_time_str << std::endl;
234  magnetCurrentBindVariableList.extend<coral::TimeStamp>( "runstop_time" );
235  magnetCurrentBindVariableList[ "runstop_time" ].data<coral::TimeStamp>() = stop;
236  magnetCurrentWhereClause = std::string( "NOT " ) + squoted(sDCSMagnetCurrentColumn) + std::string( " IS NULL AND " )
237  + sDCSMagnetChangeDateColumn + std::string( ">:runstart_time AND " )
238  + sDCSMagnetChangeDateColumn + std::string( "<:runstop_time" );
239  } else {
240  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: Accessing the magnet currents measured before run " << r_number
241  << "start time " << temp_sum.m_start_time_str << std::endl;
242  magnetCurrentWhereClause = std::string( "NOT " ) + squoted(sDCSMagnetCurrentColumn) + std::string( " IS NULL AND " )
243  + sDCSMagnetChangeDateColumn + std::string( "<:runstart_time" );
244  }
245  query->setCondition( magnetCurrentWhereClause, magnetCurrentBindVariableList );
246  query->addToOrderList( sDCSMagnetChangeDateColumn + std::string( " DESC" ) );
247  query->limitReturnedRows( 10000 );
248  coral::ICursor& magnetCurrentCursor = query->execute();
249  coral::TimeStamp lastCurrentDate;
250  std::string last_date;
251  std::vector<double> time_curr;
252  if ( !magnetCurrentCursor.next() ) {
253  // we should deal with stable currents... so the query is returning no value and we should take the last modified current value...
254  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: The magnet current did not change during run " << r_number
255  << ". Looking for the most recent change before " << temp_sum.m_stop_time_str << std::endl;
256  Bnotchanged = true;
257  std::unique_ptr<coral::IQuery> lastValueQuery( schema2.tableHandle(sDCSMagnetTable).newQuery() );
258  lastValueQuery->addToOutputList( squoted(sDCSMagnetCurrentColumn), sDCSMagnetCurrentColumn );
259  lastValueQuery->defineOutputType( sDCSMagnetCurrentColumn, "float" );
260  coral::AttributeList lastValueBindVariableList;
261  lastValueBindVariableList.extend<coral::TimeStamp>( "runstop_time" );
262  lastValueBindVariableList[ "runstop_time" ].data<coral::TimeStamp>() = stop;
263  std::string lastValueWhereClause( std::string( " NOT " ) + squoted(sDCSMagnetCurrentColumn) + std::string( " IS NULL AND " )
264  + sDCSMagnetChangeDateColumn + std::string( " <:runstop_time" ) );
265  lastValueQuery->setCondition( lastValueWhereClause, lastValueBindVariableList );
266  lastValueQuery->addToOrderList( sDCSMagnetChangeDateColumn + std::string( " DESC" ) );
267  coral::ICursor& lastValueCursor = lastValueQuery->execute();
268  if( lastValueCursor.next() ) {
269  std::ostringstream oslastvaluedebug;
270  lastValueCursor.currentRow().toOutputStream( oslastvaluedebug );
271  LogDebug( "RunInfoReader" ) << oslastvaluedebug.str() << std::endl;
272  const coral::AttributeList& row = lastValueCursor.currentRow();
273  last_current = row[sDCSMagnetCurrentColumn].data<float>();
274  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: Magnet current of previos run(s), not changed during run " << r_number
275  << ": " << last_current << std::endl;
276  }
277  temp_sum.m_avg_current = last_current;
278  temp_sum.m_min_current = last_current;
279  temp_sum.m_max_current = last_current;
280  temp_sum.m_stop_current = last_current;
281  temp_sum.m_start_current = last_current;
282  }
283  while( magnetCurrentCursor.next() ) {
284  std::ostringstream oscurrentdebug;
285  magnetCurrentCursor.currentRow().toOutputStream( oscurrentdebug );
286  LogDebug( "RunInfoReader" ) << oscurrentdebug.str() << std::endl;
287  const coral::AttributeList& row = magnetCurrentCursor.currentRow();
288  lastCurrentDate = row[sDCSMagnetChangeDateColumn].data<coral::TimeStamp>();
289  temp_sum.m_current.push_back( row[sDCSMagnetCurrentColumn].data<float>() );
290  if(temp_sum.m_stop_time_str == "null") break;
291  LogDebug( "RunInfoReader" ) << " last current time extracted == "
292  << "-->year " << lastCurrentDate.year()
293  << "-- month " << lastCurrentDate.month()
294  << "-- day " << lastCurrentDate.day()
295  << "-- hour " << lastCurrentDate.hour()
296  << "-- minute " << lastCurrentDate.minute()
297  << "-- second " << lastCurrentDate.second()
298  << "-- nanosecond " << lastCurrentDate.nanosecond()
299  << std::endl;
300  boost::posix_time::ptime lastCurrentDate_ptime = lastCurrentDate.time();
301  boost::posix_time::time_duration lastCurrentDateTimeFromEpoch = lastCurrentDate_ptime - time0;
302  last_date = boost::posix_time::to_iso_extended_string(lastCurrentDate_ptime);
303  long long last_date_ll = lastCurrentDateTimeFromEpoch.total_microseconds();
304  time_curr.push_back(last_date_ll);
305  std::ostringstream ostrans;
306  ostrans << "[RunInfoRead::" << __func__ << "]: Transition of the magnet current " << std::endl
307  << "New value: " << row[sDCSMagnetCurrentColumn].data<float>() << std::endl
308  << "Posix time for the transition timestamp: " << lastCurrentDate_ptime << std::endl
309  << "ISO string for the transition timestamp: " << last_date << std::endl
310  << "Microseconds since Epoch (UTC) for the transition timestamp: " << last_date_ll;
311  edm::LogInfo( "RunInfoReader" ) << ostrans.str() << std::endl;
312  }
313 
314  size_t csize = temp_sum.m_current.size();
315  size_t tsize = time_curr.size();
316  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: size of time: " << tsize
317  << ", size of currents: " << csize << std::endl;
318  if(csize != tsize) {
319  edm::LogWarning( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: current and time not filled correctly." << std::endl;
320  }
321  if(tsize > 1) {
322  temp_sum.m_run_intervall_micros = time_curr.front() - time_curr.back();
323  } else {
324  temp_sum.m_run_intervall_micros = 0;
325  }
326  edm::LogInfo( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: Duration in microseconds of the magnet ramp during run " << r_number
327  << ": " << temp_sum.m_run_intervall_micros << std::endl;
328 
329  double wi = 0;
330  double sumwixi = 0;
331  double sumwi = 0;
332  float min = -1;
333  float max = -1;
334 
335  if(csize != 0) {
336  min = temp_sum.m_current.front();
337  max = temp_sum.m_current.front();
338  for(size_t i = 0; i < csize; ++i) {
339  if( (tsize > 1) && ( i < csize - 1 ) ) {
340  wi = (time_curr[i] - time_curr[i+1]);
341  temp_sum.m_times_of_currents.push_back(wi);
342  sumwixi += wi * temp_sum.m_current[i] ;
343  sumwi += wi;
344  }
345  min = std::min(min, temp_sum.m_current[i]);
346  max = std::max(max, temp_sum.m_current[i]);
347  }
348  std::ostringstream oswi;
349  oswi << "[RunInfoRead::" << __func__ << "]: Duration of current values in run " << r_number << ": ";
350  std::copy(temp_sum.m_times_of_currents.begin(), temp_sum.m_times_of_currents.end(), std::ostream_iterator<float>(oswi, ", "));
351  edm::LogInfo( "RunInfoReader" ) << oswi.str() << std::endl;
352  temp_sum.m_start_current = temp_sum.m_current.back();
353  LogDebug( "RunInfoReader" ) << "start current: " << temp_sum.m_start_current << std::endl;
354  temp_sum.m_stop_current = temp_sum.m_current.front();
355  LogDebug( "RunInfoReader" ) << "stop current: " << temp_sum.m_stop_current << std::endl;
356  if (tsize>1) {
357  temp_sum.m_avg_current=sumwixi/sumwi;
358  } else {
359  temp_sum.m_avg_current= temp_sum.m_start_current;
360  }
361  LogDebug( "RunInfoReader" ) << "average current: " << temp_sum.m_avg_current << std::endl;
362  temp_sum.m_max_current= max;
363  LogDebug( "RunInfoReader" ) << "maximum current: " << temp_sum.m_max_current << std::endl;
364  temp_sum.m_min_current= min;
365  LogDebug( "RunInfoReader" ) << "minimum current: " << temp_sum.m_min_current << std::endl;
366  } else {
367  if (!Bnotchanged) {
368  edm::LogWarning( "RunInfoReader" ) << "Inserting fake values for magnet current." << std::endl;
369  temp_sum.m_avg_current = -1;
370  temp_sum.m_min_current = -1;
371  temp_sum.m_max_current = -1;
372  temp_sum.m_stop_current = -1;
373  temp_sum.m_start_current = -1;
374  }
375  }
376  std::ostringstream oscurr;
377  oscurr << "[RunInfoRead::" << __func__ << "]: Values of currents for run " << r_number << std::endl;
378  oscurr << "Average current (A): " << temp_sum.m_avg_current << std::endl;
379  oscurr << "Minimum current (A): " << temp_sum.m_min_current << std::endl;
380  oscurr << "Maximum current (A): " << temp_sum.m_max_current << std::endl;
381  oscurr << "Current at run stop (A): " << temp_sum.m_stop_current << std::endl;
382  oscurr << "Current at run start (A): " << temp_sum.m_start_current;
383  edm::LogInfo( "RunInfoReader" ) << oscurr.str() << std::endl;
384 
385  session->transaction().commit();
386  }
387  catch (const std::exception& e) {
388  throw cms::Exception( "RunInfoReader" ) << "[RunInfoRead::" << __func__ << "]: "
389  << "Unable to create a RunInfo payload. Original Exception:\n"
390  << e.what() << std::endl;
391  }
392 
393  return temp_sum;
394 }
#define LogDebug(id)
const boost::posix_time::ptime time0
RunInfoRead(const std::string &connectionString, const edm::ParameterSet &connectionPset)
Definition: RunInfoRead.cc:48
def replace(string, replacements)
def query(query_str, verbose=False)
Definition: das.py:5
RunInfo readData(const std::string &runinfo_schema, const std::string &dcsenv_schema, const int r_number)
Definition: RunInfoRead.cc:56
void setParameters(const edm::ParameterSet &connectionPset)
Definition: query.py:1
std::vector< int > m_fed_in
Definition: RunInfo.h:26
std::string m_start_time_str
Definition: RunInfo.h:23
T min(T a, T b)
Definition: MathUtil.h:58
std::vector< float > m_current
Definition: RunInfo.h:33
float m_stop_current
Definition: RunInfo.h:28
long long m_stop_time_ll
Definition: RunInfo.h:24
edm::ParameterSet m_connectionPset
Definition: RunInfoRead.h:16
float m_min_current
Definition: RunInfo.h:31
float m_avg_current
Definition: RunInfo.h:29
float m_run_intervall_micros
Definition: RunInfo.h:32
float m_max_current
Definition: RunInfo.h:30
T dot(const Basic3DVector &v) const
Scalar product, or "dot" product, with a vector of same type.
float m_start_current
Definition: RunInfo.h:27
std::string m_stop_time_str
Definition: RunInfo.h:25
int m_run
Definition: RunInfo.h:21
std::string m_connectionString
Definition: RunInfoRead.h:15
std::vector< float > m_times_of_currents
Definition: RunInfo.h:34
std::shared_ptr< coral::ISessionProxy > createCoralSession(const std::string &connectionString, bool writeCapable=false)
long long m_start_time_ll
Definition: RunInfo.h:22