|
||||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |