Back to home page

EIC code displayed by LXR

 
 

    


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

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 GAUDIALG_GAUDITUPLES_H
0012 #define GAUDIALG_GAUDITUPLES_H 1
0013 // ============================================================================
0014 /* @file GaudiTuples.h
0015  *
0016  *  Header file for class : GaudiTuples
0017  *
0018  *  @author Chris Jones   Christopher.Rob.Jones@cern.ch
0019  *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
0020  *  @date   2005-08-08
0021  */
0022 // ============================================================================
0023 // Include files
0024 // ============================================================================
0025 #include "boost/algorithm/string/replace.hpp"
0026 #include <boost/multi_index/hashed_index.hpp>
0027 #include <boost/multi_index/member.hpp>
0028 #include <boost/multi_index/ordered_index.hpp>
0029 #include <boost/multi_index_container.hpp>
0030 // ============================================================================
0031 // GaudiKernel
0032 // ============================================================================
0033 #include "GaudiKernel/ClassID.h"
0034 // ============================================================================
0035 // GaudiAlg
0036 // ============================================================================
0037 #include "GaudiAlg/GaudiHistoAlg.h"
0038 #include "GaudiAlg/GaudiHistoTool.h"
0039 #include "GaudiAlg/Maps.h"
0040 #include "GaudiAlg/Tuple.h"
0041 #include "GaudiAlg/TupleObj.h"
0042 // ============================================================================
0043 /** @class GaudiTuples GaudiTuples.h GaudiAlg/GaudiTuples.h
0044  *
0045  *  Templated base class providing common 'ntupling' methods
0046  *
0047  *  @author Chris Jones   Christopher.Rob.Jones@cern.ch
0048  *  @author Vanya BELYAEV Ivan.Belyaev@itep.ru
0049  *  @date   2005-08-08
0050  */
0051 // ============================================================================
0052 template <class PBASE>
0053 class GAUDI_API GaudiTuples : public PBASE {
0054 public:
0055   // ==========================================================================
0056   /// the actual type for histogram identifier
0057   typedef GaudiAlg::HistoID HistoID;
0058   /// the actual type of the tuple
0059   typedef Tuples::Tuple Tuple;
0060   /// the actual type of N-tuple ID
0061   typedef GaudiAlg::TupleID TupleID;
0062   // ==========================================================================
0063 public:
0064   // ==========================================================================
0065   /** Access an N-Tuple object (book on-demand) with unique identifier
0066    *
0067    *  @code
0068    *
0069    *  Tuple tuple = nTuple( "My N-Tuple" ) ;
0070    *  tuple->column( "A" , sin(0.1) );
0071    *  tuple->column( "B" , cos(0.1) );
0072    *  tuple->column( "C" , tan(0.1) );
0073    *  tuple->write();
0074    *
0075    *  @endcode
0076    *
0077    *  @attention
0078    *  The NTuple will get a unique identifier automatically assigned which by
0079    *  default will be equal to the histogram title. An option exists to instead
0080    *  use numerical IDs. In this case the first NTuple booked will be ID=1 the
0081    *  next ID=2 and so on. Note though this scheme is not recommended as it does
0082    *  NOT guarantee predictability of the ID a given NTuple will be given when
0083    *  filled under conditional statements, since in these circumstances the order
0084    *  in which the NTuple are first filled, and thus booked, will depend on the
0085    *  nature of the first few events read. This is particularly problematic when
0086    *  users submit many parallel 'sub-jobs' and then attempt to merge the final
0087    *  output ROOT (or HBOOK) files, since a given NTuple could have different IDs
0088    *  in each of the sub-jobs. Consequently it is strongly recommended that users do
0089    *  not use numerical automatic IDs unless they are sure they understand what they
0090    *  are doing.
0091    *
0092    *  @param title   Unique title for N-Tuple
0093    *  @param clid    N-Tuple class identifier (row or column wise)
0094    *  @return ntuple The ntuple object
0095    */
0096   Tuple nTuple( const std::string& title, const CLID& clid = CLID_ColumnWiseTuple ) const;
0097 
0098   /** Access an N-Tuple object (book on-demand) with forced identifier
0099    *
0100    *  @code
0101    *
0102    *  // Book Ntuple with a numeric ID
0103    *  Tuple tuple = nTuple(  1,  "My tuple" ) ;
0104    *  // ... or
0105    *  Tuple tuple = nTuple( "1", "My tuple" ) ;
0106    *
0107    *  // ... or, Book Ntuple with a literal ID
0108    *  Tuple tuple = nTuple( "mytuple", "My tuple" ) ;
0109    *
0110    *  // ... or, Book Ntuple with a literal ID in a sub-dir
0111    *  Tuple tuple = nTuple( "subdir/mytuple", "My tuple" ) ;
0112    *
0113    *  // Fill and write NTuple
0114    *  tuple->column( "A" , sin(0.1) );
0115    *  tuple->column( "B" , cos(0.1) );
0116    *  tuple->column( "C" , tan(0.1) );
0117    *  tuple->write();
0118    *
0119    *  @endcode
0120    *
0121    *  @attention
0122    *   If the N-Tuple with given ID is already booked
0123    *   through automatic assignment of N-Tuple ID,
0124    *   the error will not be detected.
0125    *   Therefore it is recommended
0126    *   to use a non-trivial N-Tuple ID offset  (property "NTupleOffSet")
0127    *   if one need to combine these techniques together
0128    *   It is still desirable to use the unique N-Tuple title
0129    *   to avoid a bad interference.
0130    *
0131    *  @param ID      The forced N-Tuple ID
0132    *  @param title   Unique title for N-Tuple
0133    *  @param clid    N-Tuple class identifier (row or column wise)
0134    *  @return ntuple The ntuple object
0135    */
0136   Tuple nTuple( const TupleID& ID, const std::string& title, const CLID& clid = CLID_ColumnWiseTuple ) const;
0137 
0138   /** Access an Event Tag Collection object (book on-demand) with unique identifier
0139    *
0140    *  @code
0141    *
0142    *  Tuple tuple = evtCol( "My Tag Collection" ) ;
0143    *  tuple->column( "A" , sin(0.1) );
0144    *  tuple->column( "B" , cos(0.1) );
0145    *  tuple->column( "C" , tan(0.1) );
0146    *  tuple->write();
0147    *
0148    *  @endcode
0149    *
0150    *  The Event Tag Collection will get a unique identifier automatically assigned which by
0151    *  default will be equal to the histogram title. An option exists to instead
0152    *  use numerical IDs. In this case the first  Event Tag Collection booked will be ID=1 the
0153    *  next ID=2 and so on. Note though this scheme is not recommended as it does
0154    *  NOT guarantee predictability of the ID a given  Event Tag Collection will be given when
0155    *  filled under conditional statements, since in these circumstances the order
0156    *  in which the  Event Tag Collection are first filled, and thus booked, will depend on the
0157    *  nature of the first few events read. This is particularly problematic when
0158    *  users submit many parallel 'sub-jobs' and then attempt to merge the final
0159    *  output ROOT (or HBOOK) files, since a given  Event Tag Collection could have different IDs
0160    *  in each of the sub-jobs. Consequently it is strongly recommended that users do
0161    *  not use numerical automatic IDs unless they are sure they understand what they
0162    *  are doing.
0163    *
0164    *  @param title   Unique title for Event Tag Collection
0165    *  @param clid    N-Tuple class identifier (row or column wise)
0166    *  @return ntuple The Event Tag Collection object
0167    */
0168   Tuple evtCol( const std::string& title, const CLID& clid = CLID_ColumnWiseTuple ) const;
0169 
0170   /** Access an Event Tag Collection object (book on-demand) with forced identifier
0171    *
0172    *  @code
0173    *
0174    *  // Book Ntuple with a numeric ID
0175    *  Tuple tuple = evtCol(  1,  "My Tag Collection" ) ;
0176    *  // ... or
0177    *  Tuple tuple = evtCol( "1", "My Tag Collection" ) ;
0178    *
0179    *  // ... or, Book Ntuple with a literal ID
0180    *  Tuple tuple = evtCol( "mytuple", "My Tag Collection" ) ;
0181    *
0182    *  // ... or, Book Ntuple with a literal ID in a sub-dir
0183    *  Tuple tuple = evtCol( "subdir/mytuple", "My Tag Collection" ) ;
0184    *
0185    *  // Fill and write
0186    *  tuple->column( "A" , sin(0.1) );
0187    *  tuple->column( "B" , cos(0.1) );
0188    *  tuple->column( "C" , tan(0.1) );
0189    *  tuple->write();
0190    *
0191    *  @endcode
0192    *
0193    *  @attention
0194    *   If the Event Tag Collection with given ID is already booked
0195    *   through automatic assignment of Event Tag Collection ID,
0196    *   the error will not be detected.
0197    *   Therefore it is recommended
0198    *   to use a non-trivial Event Tag Collection ID offset  (property "EvtColOffSet")
0199    *   if one need to combine these techniques together
0200    *   It is still desirable to use the unique Event Tag Collection title
0201    *   to avoid a bad interference.
0202    *
0203    *  @param ID      The forced Event Tag Collection ID
0204    *  @param title   Unique title for Event Tag Collection
0205    *  @param clid    N-Tuple class identifier (row or column wise)
0206    *  @return ntuple The Event Tag Collection object
0207    */
0208   Tuple evtCol( const TupleID& ID, const std::string& title, const CLID& clid = CLID_ColumnWiseTuple ) const;
0209   // ==========================================================================
0210 public: // trivial accessors
0211   // ==========================================================================
0212   /// get the flag for N-Tuple production (property "NTupleProduce")
0213   bool produceNTuples() const { return m_produceNTuples; }
0214   /// get the flag for N-Tuple path split (property "NTupleSplitDir")
0215   bool splitNTupleDir() const { return m_splitNTupleDir; }
0216   /// get the logical unit for N-Tuples   (property "NTupleLUN")
0217   const std::string& nTupleLUN() const { return m_nTupleLUN; }
0218   /// get the top-level N-Tuple directory (property "NTupleTopDir")
0219   const std::string& nTupleTopDir() const { return m_nTupleTopDir; }
0220   /// get the N-Tuple directory           (property "NTupleDir")
0221   const std::string& nTupleDir() const { return m_nTupleDir; }
0222   /// get the value for N-Tuple offset    (property "NTupleOffSet")
0223   TupleID::NumericID nTupleOffSet() const { return m_nTupleOffSet; }
0224   /// get the constructed N-Tuple path
0225   std::string nTuplePath() const;
0226   /// get the flag for Event Tag Collection production (property "EvtColsProduce")
0227   bool produceEvtCols() const { return m_produceEvtCols; }
0228   /// get the flag for Event Tag Collection path split (property "EvtColsSplitDir")
0229   bool splitEvtColDir() const { return m_splitEvtColDir; }
0230   /// get the logical unit for Event Tag Collections   (property "EvtColsLUN")
0231   const std::string& evtColLUN() const { return m_evtColLUN; }
0232   /// get the top-level Event Tag Collection directory (property "EvtColsTopDir")
0233   const std::string& evtColTopDir() const { return m_evtColTopDir; }
0234   /// get the Event Tag Collection directory           (property "EvtColsDir")
0235   const std::string& evtColDir() const { return m_evtColDir; }
0236   /// get the value for Event Tag Collection offset    (property "EvtColsOffSet")
0237   TupleID::NumericID evtColOffSet() const { return m_evtColOffSet; }
0238   /// get the constructed Event Tag Collection path
0239   std::string evtColPath() const;
0240   /// print tuples at finalization
0241   bool tuplesPrint() const { return m_tuplesPrint; }
0242   /// print event collections at finalization
0243   bool evtColsPrint() const { return m_evtColsPrint; }
0244   // ==========================================================================
0245 public:
0246   // ==========================================================================
0247   /** perform the actual printout of N-tuples
0248    *  @return number of active N-Tuples
0249    */
0250   long printTuples() const;
0251   /** perform the actual printout of Event Tag Collections
0252    *  @return number of active Event Tag Collections
0253    */
0254   long printEvtCols() const;
0255   // ==========================================================================
0256   /// check the existence AND validity of the N-Tuple with the given ID
0257   bool nTupleExists( const TupleID& ID ) const;
0258   /// check the existence AND validity of the Event Tag Collection with the given ID
0259   bool evtColExists( const TupleID& ID ) const;
0260   // ==========================================================================
0261 protected:
0262   // ==========================================================================
0263   /** create TupleObj
0264    *  @attention The method should never used directly by users
0265    *  @param name  name/title
0266    *  @param tuple the underlying ntuple implementation
0267    *  @param clid  unique classID for ntuple
0268    *  @return pointer to newly created TupleObj
0269    */
0270   virtual std::unique_ptr<Tuples::TupleObj> createNTuple( const std::string& name, NTuple::Tuple* tuple,
0271                                                           const CLID& clid ) const;
0272   /** create TupleObj for event tag collection
0273    *  @attention The method should never used directly by users
0274    *  @param name  name/title
0275    *  @param tuple the underlying ntuple implementation
0276    *  @param clid  unique classID for ntuple
0277    *  @return pointer to newly created TupelObj
0278    */
0279   virtual std::unique_ptr<Tuples::TupleObj> createEvtCol( const std::string& name, NTuple::Tuple* tuple,
0280                                                           const CLID& clid ) const;
0281   // ==========================================================================
0282 public:
0283   // ==========================================================================
0284   /// Algorithm constructor - the SFINAE constraint below ensures that this is
0285   /// constructor is only defined if PBASE derives from GaudiHistoAlg
0286   template <typename U = PBASE, typename = std::enable_if_t<std::is_base_of_v<GaudiHistoAlg, PBASE>, U>>
0287   GaudiTuples( const std::string& name, ISvcLocator* pSvcLocator ) : PBASE( name, pSvcLocator ) {}
0288   /// Tool constructor - SFINAE-ed to insure this constructor is only defined
0289   /// if PBASE derives from AlgTool.
0290   template <typename U = PBASE, typename = std::enable_if_t<std::is_base_of_v<GaudiHistoTool, PBASE>, U>>
0291   GaudiTuples( const std::string& type, const std::string& name, const IInterface* parent )
0292       : PBASE( type, name, parent ) {}
0293   // ==========================================================================
0294 protected:
0295   // ==========================================================================
0296   /** standard initialization method
0297    *  @return status code
0298    */
0299   StatusCode initialize() override;
0300   /** standard finalization method
0301    *  @return status code
0302    */
0303   StatusCode finalize() override;
0304   // ==========================================================================
0305 private:
0306   // ==========================================================================
0307   Gaudi::Property<bool> m_produceNTuples{ this, "NTupleProduce", true, "general switch to enable/disable N-tuples" };
0308   Gaudi::Property<bool> m_tuplesPrint{ this, "NTuplePrint", true,
0309                                        [this]( auto& ) {
0310                                          // no action if not yet initialized
0311                                          if ( this->FSMState() >= Gaudi::StateMachine::INITIALIZED &&
0312                                               this->tuplesPrint() )
0313                                            this->printTuples();
0314                                        },
0315                                        "print N-tuple statistics" };
0316   Gaudi::Property<bool> m_splitNTupleDir{ this, "NTupleSplitDir", false,
0317                                           "split long directory names into short pieces (suitable for HBOOK)" };
0318   Gaudi::Property<TupleID::NumericID> m_nTupleOffSet{ this, "NTupleOffSet", 0, "offset for numerical N-tuple ID" };
0319   Gaudi::Property<std::string>        m_nTupleLUN{ this, "NTupleLUN", "FILE1", "Logical File Unit for N-tuples" };
0320   Gaudi::Property<std::string>        m_nTupleTopDir{ this, "NTupleTopDir", "", "top-level directory for N-Tuples" };
0321   Gaudi::Property<std::string>        m_nTupleDir{
0322       this, "NTupleDir", boost::algorithm::replace_all_copy( this->name(), ":", "_" ), "subdirectory for N-Tuples" };
0323 
0324   Gaudi::Property<bool>               m_produceEvtCols{ this, "EvtColsProduce", false,
0325                                           "general switch to enable/disable Event Tag Collections" };
0326   Gaudi::Property<bool>               m_evtColsPrint{ this, "EvtColsPrint", false,
0327                                         [this]( auto& ) {
0328                                           // no action if not yet initialized
0329                                           if ( this->FSMState() >= Gaudi::StateMachine::INITIALIZED &&
0330                                                this->evtColsPrint() )
0331                                             this->printEvtCols();
0332                                         },
0333                                         "print statistics for Event Tag Collections " };
0334   Gaudi::Property<bool>               m_splitEvtColDir{ this, "EvtColSplitDir", false,
0335                                           "split long directory names into short pieces" };
0336   Gaudi::Property<TupleID::NumericID> m_evtColOffSet{ this, "EvtColOffSet", 0, "offset for numerical N-tuple ID" };
0337   Gaudi::Property<std::string>        m_evtColLUN{ this, "EvtColLUN", "EVTCOL",
0338                                             "Logical File Unit for Event Tag Collections" };
0339   Gaudi::Property<std::string>        m_evtColTopDir{ this, "EvtColTopDir", "",
0340                                                "Top-level directory for Event Tag Collections" };
0341   Gaudi::Property<std::string>        m_evtColDir{ this, "EvtColDir",
0342                                             boost::algorithm::replace_all_copy( this->name(), ":", "_" ),
0343                                             "Subdirectory for Event Tag Collections" };
0344   struct nTupleMapItem                final {
0345     std::string                       title;
0346     TupleID                           id;
0347     std::shared_ptr<Tuples::TupleObj> tuple;
0348   };
0349   struct title_t {};
0350   struct id_t {};
0351   struct order_t {};
0352   template <typename... Ts>
0353   using indexed_by = boost::multi_index::indexed_by<Ts...>;
0354   template <typename... Ts>
0355   using hashed_unique = boost::multi_index::hashed_unique<Ts...>;
0356   template <typename... Ts>
0357   using ordered_unique = boost::multi_index::ordered_unique<Ts...>;
0358   template <typename Obj, typename Type, Type Obj::*Member>
0359   using member = boost::multi_index::member<Obj, Type, Member>;
0360   template <typename T>
0361   using tag       = boost::multi_index::tag<T>;
0362   using nTupleMap = boost::multi_index_container<
0363       nTupleMapItem, indexed_by<hashed_unique<tag<title_t>, member<nTupleMapItem, std::string, &nTupleMapItem::title>>,
0364                                 hashed_unique<tag<id_t>, member<nTupleMapItem, TupleID, &nTupleMapItem::id>>,
0365                                 ordered_unique<tag<order_t>, member<nTupleMapItem, TupleID, &nTupleMapItem::id>>>>;
0366 
0367   // ==========================================================================
0368   /// the actual storage of ntuples by title and ID
0369   mutable nTupleMap m_nTupleMap;
0370 
0371   decltype( auto ) nTupleByID() const { return m_nTupleMap.template get<id_t>(); }
0372   decltype( auto ) nTupleByTitle() const { return m_nTupleMap.template get<title_t>(); }
0373   decltype( auto ) nTupleOrdered() const { return m_nTupleMap.template get<order_t>(); }
0374 
0375   // ==========================================================================
0376   /// the actual storage of event collections by title and ID
0377   mutable nTupleMap m_evtColMap;
0378 
0379   decltype( auto ) evtColByID() const { return m_evtColMap.template get<id_t>(); }
0380   decltype( auto ) evtColByTitle() const { return m_evtColMap.template get<title_t>(); }
0381   decltype( auto ) evtColOrdered() const { return m_evtColMap.template get<order_t>(); }
0382 
0383   // ==========================================================================
0384 };
0385 // ============================================================================
0386 // The END
0387 // ============================================================================
0388 #endif // GAUDIALG_GAUDITUPLES_H