Back to home page

EIC code displayed by LXR

 
 

    


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