Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:38

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "LICENSE".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 #ifndef GAUDIKERNEL_EVENTIDBASE_H
0012 #define GAUDIKERNEL_EVENTIDBASE_H 1
0013 
0014 /**
0015  * @file EventIDBase.h
0016  *
0017  * @brief This class provides a unique identification for each event,
0018  * in terms of run/event number and/or a time stamp.
0019  *
0020  * @author RD Schaffer <R.D.Schaffer@cern.ch>
0021  * @author Paolo Calafiura <pcalafiura@lbl.gov>
0022  * @author Charles Leggett
0023  *
0024  */
0025 
0026 #include <cstdint>
0027 #include <iomanip>
0028 #include <iostream>
0029 #include <tuple>
0030 
0031 #include "GaudiKernel/compose.h"
0032 namespace details {
0033   template <typename lambda>
0034   struct arg_helper : public arg_helper<decltype( &lambda::operator() )> {};
0035   template <typename T, typename Ret, typename Arg>
0036   struct arg_helper<Ret ( T::* )( Arg ) const> {
0037     using type = Arg;
0038   };
0039 
0040   // given a unary lambda whose argument is of type Arg_t,
0041   // argument_t<lambda> will be equal to Arg_t
0042   template <typename lambda>
0043   using argument_t = typename arg_helper<lambda>::type;
0044 
0045   template <typename Fun>
0046   auto add_deref( Fun f ) {
0047     return compose( f, [=]( auto*... p ) { return f( *p... ); } );
0048   }
0049 
0050   template <typename Proj, typename Cmp = std::greater<>>
0051   auto make_cmp( Proj p, Cmp cmp = {} ) {
0052     static_assert( std::is_reference_v<argument_t<Proj>>, "must be a reference" );
0053     static_assert( std::is_const_v<std::remove_reference_t<argument_t<Proj>>>, "must be const" );
0054     return [=]( argument_t<Proj> lhs, argument_t<Proj> rhs ) { return cmp( p( lhs ), p( rhs ) ); };
0055   }
0056 } // namespace details
0057 
0058 /**
0059  * @class EventIDBase
0060  *
0061  * @brief This class provides a unique identification for each event,
0062  * in terms of run/event number and/or a time stamp.
0063  *
0064  */
0065 
0066 class EventIDBase {
0067 public:
0068   typedef unsigned int number_type;
0069   typedef uint64_t     event_number_t;
0070 
0071   static const number_type    UNDEFNUM;
0072   static const event_number_t UNDEFEVT;
0073 
0074   friend class EventIDRange;
0075 
0076 public:
0077   /// \name structors
0078   //@{
0079   EventIDBase(){};
0080   EventIDBase( number_type run_number, event_number_t event_number, number_type time_stamp = UNDEFNUM,
0081                number_type time_stamp_ns_offset = 0, number_type lumi_block = UNDEFNUM,
0082                number_type bunch_crossing_id = 0 );
0083 
0084   EventIDBase( std::tuple<number_type, number_type, event_number_t> run_lumi_ev,
0085                std::tuple<number_type, number_type> time_stamp, number_type bunch_crossing_id );
0086 
0087   // Use default copy constructor.
0088   virtual ~EventIDBase() = default;
0089   //@}
0090 
0091   /// run number - 32 bit unsigned
0092   number_type run_number() const { return m_run_number; }
0093 
0094   /// event number - 64 bit unsigned
0095   event_number_t event_number() const { return m_event_number; }
0096 
0097   /// time stamp - posix time in seconds from 1970, 32 bit unsigned
0098   number_type time_stamp() const { return m_time_stamp; }
0099 
0100   /// time stamp ns - ns time offset for time_stamp, 32 bit unsigned
0101   number_type time_stamp_ns_offset() const { return m_time_stamp_ns_offset; }
0102 
0103   /// luminosity block identifier, 32 bit unsigned
0104   number_type lumi_block() const { return m_lumi_block; }
0105 
0106   /// bunch crossing ID,  32 bit unsigned
0107   number_type bunch_crossing_id() const { return m_bunch_crossing_id; }
0108 
0109   /// set run number
0110   void set_run_number( number_type runNumber ) {
0111     m_run_number = runNumber;
0112     if ( m_event_number != UNDEFEVT ) setRE();
0113     if ( m_lumi_block != UNDEFNUM ) setRL();
0114   }
0115 
0116   /// set event number
0117   void set_event_number( event_number_t eventNumber ) {
0118     m_event_number = eventNumber;
0119     if ( m_run_number != UNDEFNUM ) setRE();
0120     if ( m_lumi_block != UNDEFNUM ) setLE();
0121   }
0122 
0123   /// set time stamp
0124   void set_time_stamp( number_type timeStamp ) {
0125     m_time_stamp = timeStamp;
0126     setTS();
0127   }
0128 
0129   /// set time stamp in ns
0130   void set_time_stamp_ns_offset( number_type timeStampNs ) { m_time_stamp_ns_offset = timeStampNs; }
0131 
0132   /// set luminosity block identifier
0133   void set_lumi_block( number_type lumiBlock ) {
0134     m_lumi_block = lumiBlock;
0135     if ( m_run_number != UNDEFNUM ) setRL();
0136     if ( m_event_number != UNDEFEVT ) setLE();
0137   }
0138 
0139   /// set bunch crossing ID
0140   void set_bunch_crossing_id( number_type bcid ) { m_bunch_crossing_id = bcid; }
0141 
0142   /// Comparison operators
0143   friend bool operator==( const EventIDBase& lhs, const EventIDBase& rhs );
0144   friend bool operator<( const EventIDBase& lhs, const EventIDBase& rhs );
0145   friend bool operator>( const EventIDBase& lhs, const EventIDBase& rhs ) { return rhs < lhs; }
0146   friend bool operator!=( const EventIDBase& lhs, const EventIDBase& rhs ) { return !( lhs == rhs ); }
0147   friend bool operator<=( const EventIDBase& lhs, const EventIDBase& rhs ) { return !( lhs > rhs ); }
0148   friend bool operator>=( const EventIDBase& lhs, const EventIDBase& rhs ) { return !( lhs < rhs ); }
0149 
0150   friend EventIDBase min( const EventIDBase& lhs, const EventIDBase& rhs );
0151   friend EventIDBase max( const EventIDBase& lhs, const EventIDBase& rhs );
0152 
0153   bool isRunEvent() const { return m_type & RunEvent; }
0154   bool isTimeStamp() const { return m_type & TimeStamp; }
0155   bool isLumiEvent() const { return m_type & LumiEvent; }
0156   bool isRunLumi() const { return m_type & RunLumi; }
0157   bool isValid() const { return m_type != Invalid; }
0158 
0159   /// Extraction operators
0160   friend std::ostream& operator<<( std::ostream& os, const EventIDBase& rhs );
0161 
0162   static auto SortByTimeStamp() {
0163     return ::details::add_deref( ::details::make_cmp(
0164         []( const EventIDBase& e ) { return std::tie( e.m_time_stamp, e.m_time_stamp_ns_offset ); } ) );
0165   };
0166 
0167   static auto SortByRunEvent() {
0168     return ::details::add_deref(
0169         ::details::make_cmp( []( const EventIDBase& e ) { return std::tie( e.m_run_number, e.m_event_number ); } ) );
0170   };
0171 
0172   static auto SortByLumiEvent() {
0173     return ::details::add_deref(
0174         ::details::make_cmp( []( const EventIDBase& e ) { return std::tie( e.m_lumi_block, e.m_event_number ); } ) );
0175   };
0176 
0177   static auto SortByRunLumi() {
0178     return ::details::add_deref(
0179         ::details::make_cmp( []( const EventIDBase& e ) { return std::tie( e.m_run_number, e.m_lumi_block ); } ) );
0180   };
0181 
0182 private:
0183   enum Type { Invalid = 0, RunEvent = 1 << 1, TimeStamp = 1 << 2, LumiEvent = 1 << 3, RunLumi = 1 << 4 };
0184 
0185   unsigned m_type{ Invalid };
0186 
0187   void setRE() { m_type |= RunEvent; }
0188   void setTS() { m_type |= TimeStamp; }
0189   void setLE() { m_type |= LumiEvent; }
0190   void setRL() { m_type |= RunLumi; }
0191 
0192   /// run number
0193   number_type m_run_number{ UNDEFNUM };
0194 
0195   /// event number
0196   event_number_t m_event_number{ UNDEFEVT };
0197 
0198   /// posix time in seconds since 1970/01/01
0199   number_type m_time_stamp{ UNDEFNUM };
0200 
0201   /// time stamp ns - ns time offset for time_stamp, 32 bit unsigned
0202   number_type m_time_stamp_ns_offset{ UNDEFNUM };
0203 
0204   /// luminosity block number:
0205   /// the number which uniquely tags a luminosity block within a run
0206   number_type m_lumi_block{ UNDEFNUM };
0207 
0208   /// bunch crossing ID,  32 bit unsigned
0209   number_type m_bunch_crossing_id{ UNDEFNUM };
0210 };
0211 
0212 inline EventIDBase min( const EventIDBase& lhs, const EventIDBase& rhs ) {
0213 
0214   //"min" is easy b/c the numbers denoting invalidty for TS or Run/Event/LB are the
0215   // largest possible numbers, so naturally larger than any valid number
0216 
0217   return EventIDBase( std::min( std::tie( lhs.m_run_number, lhs.m_lumi_block, lhs.m_event_number ),
0218                                 std::tie( rhs.m_run_number, rhs.m_lumi_block, rhs.m_event_number ) ),
0219                       std::min( std::tie( lhs.m_time_stamp, lhs.m_time_stamp_ns_offset ),
0220                                 std::tie( rhs.m_time_stamp, rhs.m_time_stamp_ns_offset ) ),
0221                       lhs.bunch_crossing_id() // bcid doesn't really matter here
0222   );
0223 }
0224 
0225 inline EventIDBase max( const EventIDBase& lhs, const EventIDBase& rhs ) {
0226 
0227   //"max" is much trickier because we need to handle invalid number explicilty by
0228   // checking if a EventIDBase is TS or Run/Lumi
0229 
0230   std::tuple<EventIDBase::number_type, EventIDBase::number_type, EventIDBase::event_number_t> run_lumi_ev;
0231   std::tuple<EventIDBase::number_type, EventIDBase::number_type>                              time_stamp;
0232 
0233   if ( lhs.isTimeStamp() && rhs.isTimeStamp() ) { // both time-stamp, compare them
0234     time_stamp = std::max( std::tie( lhs.m_time_stamp, lhs.m_time_stamp_ns_offset ),
0235                            std::tie( rhs.m_time_stamp, rhs.m_time_stamp_ns_offset ) );
0236   } else if ( lhs.isTimeStamp() ) { // only lhs time-stamp: Use it
0237     time_stamp = std::tie( lhs.m_time_stamp, lhs.m_time_stamp_ns_offset );
0238   } else { // otherwise use rhs time-stamp which might be UNDEFNUM (in case both input values are Run-Lumi only)
0239     time_stamp = std::tie( rhs.m_time_stamp, rhs.m_time_stamp_ns_offset );
0240   }
0241 
0242   if ( lhs.isRunLumi() && rhs.isRunLumi() ) { // both run-lumi, compare them
0243     run_lumi_ev = std::max( std::tie( lhs.m_run_number, lhs.m_lumi_block, lhs.m_event_number ),
0244                             std::tie( rhs.m_run_number, rhs.m_lumi_block, rhs.m_event_number ) );
0245 
0246   } else if ( lhs.isRunLumi() ) { // only lhs run-lumi: Use it
0247     run_lumi_ev = std::tie( lhs.m_run_number, lhs.m_lumi_block, lhs.m_event_number );
0248   } else { // otherwise use rhs run-lumi which might be UNDEFNUM (in case both input values are TS-only)
0249     run_lumi_ev = std::tie( rhs.m_run_number, rhs.m_lumi_block, rhs.m_event_number );
0250   }
0251 
0252   return EventIDBase( run_lumi_ev, time_stamp, lhs.bunch_crossing_id() );
0253 }
0254 
0255 inline bool operator<( const EventIDBase& lhs, const EventIDBase& rhs ) {
0256   // first try ordering by timestamp if both are non-zero
0257   // then try ordering by run/lumi/event
0258   // this assumes that both EventIDBase have the same set of values defined.
0259 
0260   if ( lhs.isTimeStamp() && rhs.isTimeStamp() ) {
0261     return lhs.m_time_stamp < rhs.m_time_stamp;
0262   } else {
0263     return std::tie( lhs.m_run_number, lhs.m_lumi_block, lhs.m_event_number ) <
0264            std::tie( rhs.m_run_number, rhs.m_lumi_block, rhs.m_event_number );
0265   }
0266 }
0267 
0268 inline bool operator==( const EventIDBase& lhs, const EventIDBase& rhs ) {
0269   // We assume that equality via run/event/lumi numbers is sufficient
0270   return ( lhs.m_run_number == rhs.m_run_number && lhs.m_event_number == rhs.m_event_number &&
0271            lhs.m_lumi_block == rhs.m_lumi_block );
0272 }
0273 
0274 inline std::ostream& operator<<( std::ostream& os, const EventIDBase& rhs ) {
0275   if ( rhs.m_type == EventIDBase::Invalid ) return os << "[INVALID]";
0276 
0277   const char* separator = "";
0278   os << "[";
0279   if ( rhs.m_run_number != EventIDBase::UNDEFNUM ) {
0280     os << rhs.m_run_number;
0281     separator = ",";
0282   }
0283 
0284   if ( rhs.m_event_number != EventIDBase::UNDEFEVT ) {
0285     os << separator << rhs.m_event_number;
0286     separator = ",";
0287   }
0288 
0289   if ( rhs.isTimeStamp() ) {
0290     os << separator << "t:" << rhs.m_time_stamp;
0291     if ( rhs.m_time_stamp_ns_offset != 0 ) {
0292       os << "." << std::setfill( '0' ) << std::setw( 9 ) << rhs.m_time_stamp_ns_offset;
0293     }
0294     separator = ",";
0295   }
0296 
0297   if ( rhs.isLumiEvent() || rhs.isRunLumi() ) {
0298     os << separator << "l:" << rhs.m_lumi_block;
0299     separator = ",";
0300   }
0301 
0302   if ( rhs.m_bunch_crossing_id != 0 ) { os << separator << "b:" << rhs.m_bunch_crossing_id; }
0303   os << "]";
0304   return os;
0305 }
0306 
0307 #endif // EVENTINFO_EVENTID_H