|
||||
File indexing completed on 2025-01-18 09:57:34
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_TUPLE_H 0012 #define GAUDIALG_TUPLE_H 1 0013 // ============================================================================ 0014 // Include files 0015 // ============================================================================ 0016 // STD & STL 0017 // ============================================================================ 0018 #include <string> 0019 0020 // ============================================================================ 0021 /** @file Tuple.h 0022 * 0023 * Header file for class : Tuple 0024 * 0025 * @date 2002-10-30 0026 * @author Vanya Belyaev Ivan.Belyaev@itep.ru 0027 */ 0028 // ============================================================================ 0029 0030 // ============================================================================ 0031 /** @namespace Tuples 0032 * 0033 * General namespace for Tuple properties 0034 * 0035 * @author Vanya BELYAEV Ivan.Belyaev@itep.ru 0036 * @date 2004-01-23 0037 */ 0038 // ============================================================================ 0039 0040 #include "GaudiAlg/TupleObj.h" 0041 #include "GaudiKernel/SmartIF.h" 0042 0043 namespace Tuples { 0044 0045 template <class ITEM> 0046 class TupleItem; 0047 0048 /** @class Tuple Tuple.h GaudiAlg/Tuple.h 0049 * 0050 * @brief A simple wrapper class over standard 0051 * Gaudi NTuple::Tuple facility 0052 * 0053 * The main advantages of local ntuples with respect to 'standard' 0054 * Gaudi NTuples ( NTuple::Tuple ) is their "locality". 0055 * For 'standard' ntuples one need 0056 * <ol> 0057 * <li> Define all ntuple columns/items as 0058 * data members of the algorithm </li> 0059 * <li> Book the <tt>NTuple::Tuple</tt> object using 0060 * <tt>INTupleSvc</tt></li> 0061 * <li> Add all defined columns/items to the booked ntuple </li> 0062 * <li> Fill ntuple records 0063 * </ol> 0064 * Usually the first step is done in the header file (separate file!) 0065 * of the algorithm, the second and the third steps are done in 0066 * <tt>initialize()</tt> method of the algorithm and 0067 * the fourth step is done somewhere in <tt>execute()</tt> method of 0068 * the same algorithm. Such approach requires to keep track of the 0069 * tuple structure through different method and event through different 0070 * files. And even minor modification of the structure of the ntuple 0071 * will require the modification of at least 2 methods and 2 files. 0072 * 0073 * The <tt>Tuples::Tuple</tt> wrapper over standard Gaudi 0074 * <tt>NTuple::Tuple</tt> class solves all above listed problems with 0075 * "non-local" nature of Gaudi <tt>NTuple::Tuple</tt> objects. 0076 * 0077 * <tt>Tuples::Tuple</tt> object is booked and used 'locally'. 0078 * One does not need to pre-book the ntuple or its columns/items 0079 * somewhere in different compilation units or other methods different 0080 * from the actual point of using the ntuple. 0081 * 0082 * The simplest example of usage Tuple object: 0083 * 0084 * @code 0085 * Tuple tuple = nTuple( "some more or less unique tuple title "); 0086 * for( Loop D0 = loop( "K- pi+", "D0" ) , D0 , ++D0 ) 0087 * { 0088 * tuple -> column ( "mass" , M ( D0 ) / GeV ) ; 0089 * tuple -> column ( "pt" , PT ( D0 ) / GeV ) ; 0090 * tuple -> column ( "p" , P ( D0 ) / GeV ) ; 0091 * tuple -> write () ; 0092 * } 0093 * @endcode 0094 * 0095 * One could fill some Tuple variables in one go 0096 * 0097 * @code 0098 * Tuple tuple = nTuple( "some more or less unique tuple title "); 0099 * for( Loop D0 = loop( "K- pi+", "D0" ) , D0 , ++D0 ) 0100 * { 0101 * tuple -> column ( "mass" , M ( D0 ) / GeV ) ; 0102 * tuple -> fill ( "pt , p " , PT ( D0 ) / GeV , P(D0) / GeV ) ; 0103 * tuple -> write () ; 0104 * } 0105 * @endcode 0106 * 0107 * Even ALL variables could be filled in one go: 0108 * 0109 * @code 0110 * Tuple tuple = nTuple( "some more or less unique tuple title "); 0111 * for( Loop D0 = loop( "K- pi+", "D0" ) , D0 , ++D0 ) 0112 * { 0113 * tuple -> fill ( "mass pt , p ", M(D0)/GeV,PT(D0)/GeV,P(D0)/GeV ) ; 0114 * tuple -> write () ; 0115 * } 0116 * @endcode 0117 * 0118 * All these techniques could be easily combined in arbitrary ways 0119 * 0120 * @see GaudiTupleAlg 0121 * @see TupleObj 0122 * 0123 * @author Vanya BELYAEV Ivan.Belyaev@itep.ru 0124 * @date 2003-02-24 0125 */ 0126 class GAUDI_API Tuple { 0127 public: 0128 /** standard constructor 0129 * @param tuple pointer to "real" tuple object 0130 */ 0131 0132 Tuple( std::shared_ptr<TupleObj> tuple ) : m_tuple( std::move( tuple ) ) {} 0133 0134 virtual ~Tuple() = default; 0135 0136 /** get the pointer to the underlying object 0137 * @return pointer to underlying TupleObj 0138 */ 0139 TupleObj* operator->() const { return m_tuple.get(); } 0140 0141 /// check the validity of the tuple object 0142 bool valid() const { return static_cast<bool>( m_tuple ); } 0143 0144 protected: 0145 TupleObj* tuple() { return m_tuple.get(); } 0146 0147 private: 0148 /// The (shared) tuple object 0149 std::shared_ptr<TupleObj> m_tuple; 0150 }; 0151 0152 /** @class TupleColumn 0153 * 0154 * Helper class which allows to extend the functionality 0155 * of Tuple with possibility to use your own representation 0156 * of complex objects. 0157 * 0158 * It allows to extend the functionality of 0159 * Tuples::Tuple and Tuples::TupleObj classes 0160 * for your own needs, according to your own taste 0161 * and without touching the classes at all. 0162 * Neither the extension or the functionality through 0163 * inheritance nor the extension through aggregation 0164 * is used. One use the trick with 0165 * template specialization of streamer operators. 0166 * 0167 * Assuming one need to add into private code the 0168 * N-Tuple representation of e.g. MyClass class 0169 * 0170 * @code 0171 * 0172 * // 0) Class which needs N-Tuple representation 0173 * class MyClass 0174 * { 0175 * ... 0176 * double field1() const ; 0177 * double field2() const ; 0178 * long field3() const ; 0179 * bool field4() const ; 0180 * }; 0181 * 0182 * // 1) define specialization of operator with needed 0183 * // representation 0184 * template <> 0185 * inline Tuples::Tuple& operator<< 0186 * ( Tuples::Tuple& tuple , 0187 * const Tuples::TupleColumn<MyClass>& item ) 0188 * { 0189 * // no action for invalid tuple 0190 * if( !tuple.valid() ) { return tuple ;} 0191 * tuple->column( item.name() + "field1" , item.value().field1() ); 0192 * tuple->column( item.name() + "field2" , item.value().field2() ); 0193 * tuple->column( item.name() + "field3" , item.value().field3() ); 0194 * tuple->column( item.name() + "field4" , item.value().field4() ); 0195 * return tuple ; 0196 * } 0197 * 0198 * // 3) use the operator to 'stream' objects of type MyClass ito 0199 * // N-Tuple: 0200 * 0201 * Tuple tuple = ... ; 0202 * MyClass a = ... ; 0203 * tuple << Tuples::make_column( "A" , a ) ; 0204 * 0205 * // operators can be chained: 0206 * MyClass a1 = ... ; 0207 * MyClass a2 = ... ; 0208 * MyClass a3 = ... ; 0209 * tuple << Tuples::make_column( "A1" , a1 ) 0210 * << Tuples::make_column( "A2" , a2 ) 0211 * << Tuples::make_column( "A3" , a3 ) ; 0212 * 0213 * @endcode 0214 * 0215 * Alternatively one can use function Tuples::Column 0216 * 0217 * @code 0218 * 0219 * // 0220 * MyClass a1 = ... ; 0221 * MyClass a2 = ... ; 0222 * MyClass a3 = ... ; 0223 * tuple << Tuples::Column( "A1" , a1 ) 0224 * << Tuples::Column( "A2" , a2 ) 0225 * << Tuples::Column( "A3" , a3 ) ; 0226 * 0227 * @endcode 0228 * 0229 * 0230 * Using this technique one can put 'any' object into NTuple 0231 * and create the own representation. E.g. if the 'standard' 0232 * representation of HepLorentzVector is not suitable one 0233 * can create the alternative representation. 0234 * 0235 * Also one can create own representations of complex classes, e.g. 0236 * class MCParticle : 0237 * 0238 * @code 0239 * 0240 * /// 1 ) define template specialization 0241 * template <> 0242 * inline Tuples::Tuple& operator<< 0243 * ( Tuples::Tuple& tuple , 0244 * const Tuples::TupleColumn<const MCParticle*>& item ) 0245 * { 0246 * if( !tuple.valid() ) { return tuple ;} 0247 * const MCParticle* mcp = item.value() ; 0248 * tuple->column( item.name() + "Mom" , mcp->momentum() ) ; 0249 * tuple->column( item.name() + "PID" , mcp->particleID().pid() ) ; 0250 * tuple->column( item.name() + "hasVX" , 0 != mcp->originVertex() ) ; 0251 * }; 0252 * 0253 * /// 2) use the specialization to feed Tuple 0254 * 0255 * 0256 * Tuple tuple = ... ; 0257 * const MCParticle* mcp = ... ; 0258 * tuple << Tuples::Column( "MCP" , mcp ) ; 0259 * 0260 * @endcode 0261 * 0262 * @author Vanya BELYAEV Ivan.Belyaev@itep.ru 0263 */ 0264 template <class ITEM> 0265 class TupleColumn { 0266 public: 0267 TupleColumn( std::string name, ITEM value ) : m_name( std::move( name ) ), m_value( std::move( value ) ) {} 0268 0269 /// Return the column name 0270 const std::string& name() const { return m_name; } 0271 /// Return the column value 0272 const ITEM& value() const { return m_value; } 0273 0274 private: 0275 std::string m_name; ///< The column name 0276 ITEM m_value; ///< The column value 0277 }; 0278 0279 /** helper function to create 'on-the-fly' the 0280 * helper object Tuples::TupleColumn 0281 */ 0282 template <class ITEM> 0283 inline TupleColumn<ITEM> make_column( std::string name, const ITEM& item ) { 0284 return { std::move( name ), item }; 0285 } 0286 0287 /** helper function to create 'on-the-fly' the 0288 * helper object Tuples::TupleColumn 0289 */ 0290 template <class ITEM> 0291 inline TupleColumn<const ITEM*> make_column( std::string name, const ITEM* item ) { 0292 return { std::move( name ), item }; 0293 } 0294 0295 /** helper function to create 'on-the-fly' the 0296 * helper object Tuples::TupleColumn 0297 */ 0298 template <class ITEM> 0299 inline TupleColumn<ITEM*> make_column( std::string name, ITEM* item ) { 0300 return { std::move( name ), item }; 0301 } 0302 0303 template <class ITEM> 0304 inline TupleColumn<ITEM> Column( std::string name, const ITEM& item ) { 0305 return make_column( std::move( name ), item ); 0306 } 0307 0308 template <class ITEM> 0309 inline TupleColumn<const ITEM*> Column( std::string name, const ITEM* item ) { 0310 return make_column( std::move( name ), item ); 0311 } 0312 0313 template <class ITEM> 0314 inline TupleColumn<ITEM*> Column( std::string name, ITEM* item ) { 0315 return make_column( std::move( name ), item ); 0316 } 0317 0318 } // namespace Tuples 0319 0320 // ============================================================================ 0321 /// helper operator to feed Tuple with the data, see Tuples::TupleColumn 0322 // ============================================================================ 0323 template <class ITEM> 0324 inline Tuples::Tuple& operator<<( Tuples::Tuple& tuple, const Tuples::TupleColumn<ITEM>& item ) { 0325 if ( !tuple.valid() ) return tuple; // no action for invalid tuple 0326 tuple->column( item.name(), item.value() ) 0327 .orThrow( "Failed to fill the tuple", "operator<<( Tuples::Tuple&, ...)" ) 0328 .ignore(); 0329 return tuple; 0330 } 0331 // ============================================================================ 0332 0333 // ============================================================================ 0334 // THe END 0335 // ============================================================================ 0336 #endif // GAUDIALG_TUPLE_H
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |