PSEvt/include/Event.h

Go to the documentation of this file.
00001 #ifndef PSEVT_EVENT_H
00002 #define PSEVT_EVENT_H
00003 
00004 //--------------------------------------------------------------------------
00005 // File and Version Information:
00006 //      $Id: Event.h 8071 2014-04-29 17:39:40Z davidsch@SLAC.STANFORD.EDU $
00007 //
00008 // Description:
00009 //      Class Event.
00010 //
00011 //------------------------------------------------------------------------
00012 
00013 //-----------------
00014 // C/C++ Headers --
00015 //-----------------
00016 #include <string>
00017 #include <list>
00018 #include <typeinfo>
00019 #include <boost/shared_ptr.hpp>
00020 #include <boost/make_shared.hpp>
00021 #include <boost/enable_shared_from_this.hpp>
00022 #include <boost/utility.hpp>
00023 
00024 //----------------------
00025 // Base Class Headers --
00026 //----------------------
00027 
00028 //-------------------------------
00029 // Collaborating Class Headers --
00030 //-------------------------------
00031 #include "PSEvt/EventKey.h"
00032 #include "PSEvt/Proxy.h"
00033 #include "PSEvt/DataProxy.h"
00034 #include "PSEvt/ProxyDictI.h"
00035 #include "PSEvt/Source.h"
00036 #include "pdsdata/xtc/Src.hh"
00037 #include "ndarray/ndarray.h"
00038 #include "MsgLogger/MsgLogger.h"
00039 
00040 //------------------------------------
00041 // Collaborating Class Declarations --
00042 //------------------------------------
00043 
00044 //              ---------------------
00045 //              -- Class Interface --
00046 //              ---------------------
00047 
00048 /**
00049  *  @defgroup PSEvt  PSEvt package
00050  *  
00051  *  @brief PSEvt package contains classes which provide storage and 
00052  *  access to event data in the context of psana framework.
00053  *  
00054  *  The core of the package is the proxy dictionary classes which allow 
00055  *  storage of the arbitrary types. Dictionaries to not store data 
00056  *  directly, instead they store proxy objects which can either contain
00057  *  data objects or implement algorithm to generate data objects when
00058  *  necessary.
00059  *  
00060  *  Main user interface to this package is the Event class which is a 
00061  *  wrapper for proxy dictionary providing more user-friendly interface.
00062  */
00063 
00064 namespace PSEvt {
00065 
00066 /**
00067  *  @ingroup PSEvt
00068  *  
00069  *  @brief Class which manages event data in psana framework.
00070  *  
00071  *  This class is a user-friendly interface to proxy dictionary object. 
00072  *  It provides a number of put() and get() methods to store/retrieve 
00073  *  arbitrarily typed data.
00074  *
00075  *  This software was developed for the LCLS project.  If you use all or 
00076  *  part of it, please give an appropriate acknowledgment.
00077  *
00078  *  @see ProxyDictI
00079  *
00080  *  @version \$Id: Event.h 8071 2014-04-29 17:39:40Z davidsch@SLAC.STANFORD.EDU $
00081  *
00082  *  @author Andrei Salnikov
00083  */
00084 
00085 class Event : public boost::enable_shared_from_this<Event>, boost::noncopyable {
00086 public:
00087 
00088   /// Special class used for type-less return from get()
00089   struct GetResultProxy {
00090     
00091     /// Convert the result of Event::get() call to smart pointer to data object
00092     template<typename T>
00093     operator boost::shared_ptr<T>() {
00094       boost::shared_ptr<void> vptr = m_dict->get(&typeid(const T), m_source, m_key, m_foundSrc);
00095       return boost::static_pointer_cast<T>(vptr);
00096     }
00097 
00098     /// specializiation to help users diagnose problems with using a non const ndarray template 
00099     /// argument when a const argument was intended
00100     template<typename T, unsigned NDim>
00101     operator boost::shared_ptr< ndarray<T,NDim> >() {
00102       boost::shared_ptr<void> vptr = m_dict->get(&typeid(const ndarray<T, NDim>), m_source, m_key, m_foundSrc);
00103       if (not vptr and m_dict->get(&typeid(const ndarray<const T, NDim>), m_source, m_key, 0)) {
00104         MsgLog("Event::get",warning,"Event::get - requested ndarray<T,R> *not* present *but* ndarray<const T,R> is for"
00105                << " src=" << m_source << " key=" << m_key);
00106       }
00107       return boost::static_pointer_cast< ndarray<T,NDim> >(vptr);
00108     }
00109       
00110     boost::shared_ptr<ProxyDictI> m_dict; ///< Proxy dictionary containing the data
00111     Source m_source;         ///< Data source address
00112     std::string m_key;       ///< String key
00113     Pds::Src* m_foundSrc;    ///< Pointer to where to store the exact address of found object
00114   };
00115   
00116   
00117   /**
00118    *  @brief Standard constructor takes proxy dictionary object
00119    *  
00120    *  @param[in] dict Pointer to proxy dictionary
00121    */
00122   explicit Event(const boost::shared_ptr<ProxyDictI>& dict) : m_dict(dict) {}
00123 
00124   //Destructor
00125   ~Event () {}
00126 
00127   /**
00128    *  @brief Add one more proxy object to the event
00129    *  
00130    *  @param[in] proxy  Proxy object for type T.
00131    *  @param[in] key    Optional key to distinguish different objects of the same type.
00132    *
00133    *  @throw ExceptionDuplicateKey
00134    *  @throw ExceptionNoAliasMap
00135    */
00136   template <typename T>
00137   void putProxy(const boost::shared_ptr<Proxy<T> >& proxy, const std::string& key=std::string()) 
00138   {
00139     EventKey evKey(&typeid(const T), EventKey::noSource(), key);
00140     m_dict->put(boost::static_pointer_cast<ProxyI>(proxy), evKey);
00141   }
00142   
00143   /**
00144    *  @brief Add one more proxy object to the event
00145    *  
00146    *  @param[in] proxy   Proxy object for type T.
00147    *  @param[in] source Source detector address.
00148    *  @param[in] key     Optional key to distinguish different objects of the same type.
00149    *
00150    *  @throw ExceptionDuplicateKey
00151    *  @throw ExceptionNoAliasMap
00152    */
00153   template <typename T>
00154   void putProxy(const boost::shared_ptr<Proxy<T> >& proxy, 
00155                 const Pds::Src& source, 
00156                 const std::string& key=std::string()) 
00157   {
00158     EventKey evKey(&typeid(const T), source, key);
00159     m_dict->put(boost::static_pointer_cast<ProxyI>(proxy), evKey);
00160   }
00161   
00162   /**
00163    *  @brief Add one more object to the event
00164    *  
00165    *  @param[in] data   Object to store in the event.
00166    *  @param[in] key    Optional key to distinguish different objects of the same type.
00167    *
00168    *  @throw ExceptionDuplicateKey
00169    *  @throw ExceptionNoAliasMap
00170    */
00171   template <typename T>
00172   void put(const boost::shared_ptr<T>& data, const std::string& key=std::string()) 
00173   {
00174     boost::shared_ptr<ProxyI> proxyPtr(boost::make_shared<DataProxy<T> >(data) );
00175     EventKey evKey(&typeid(const T), EventKey::noSource(), key);
00176     m_dict->put(proxyPtr, evKey);
00177   }
00178   
00179   /**
00180    *  @brief Add one more object to the event
00181    *  
00182    *  @param[in] data    Object to store in the event.
00183    *  @param[in] source Source detector address.
00184    *  @param[in] key     Optional key to distinguish different objects of the same type.
00185    *
00186    *  @throw ExceptionDuplicateKey
00187    *  @throw ExceptionNoAliasMap
00188    */
00189   template <typename T>
00190   void put(const boost::shared_ptr<T>& data, 
00191            const Pds::Src& source, 
00192            const std::string& key=std::string()) 
00193   {
00194     boost::shared_ptr<ProxyI> proxyPtr(boost::make_shared<DataProxy<T> >(data) );
00195     EventKey evKey(&typeid(const T), source, key);
00196     m_dict->put(proxyPtr, evKey);
00197   }
00198   
00199   /**
00200    *  @brief Get an object from event
00201    *  
00202    *  This method finds and returns object in an event which is not associated
00203    *  with any detector device (this is why it does not have source argument).
00204    *  It can be used for example to obtain EventId object or other similar types
00205    *  of data.
00206    *
00207    *  Note that if you pass an std::string to get() then this method will be
00208    *  called even if string may look like device address. Always use Source
00209    *  class as an argument to get() to locate detector data.
00210    *
00211    *  @param[in] key     Optional key to distinguish different objects of the same type.
00212    *  @return Shared pointer which can be zero if object not found.
00213    */
00214   GetResultProxy get(const std::string& key=std::string())
00215   {
00216     GetResultProxy pxy = {m_dict, Source(Source::null), key, (Pds::Src*)(0)};
00217     return pxy;
00218   }
00219   
00220   /**
00221    *  @brief Get an object from event
00222    *  
00223    *  Find and return data object which was produced by specific device. Device is
00224    *  specified as a source object of type Pds::Src. This overloaded function should
00225    *  be used if the source is known exactly, for example when Pds::Src object is
00226    *  returned via foundSrc pointer from previous call to get() method.
00227    *
00228    *  @param[in] source Source detector address.
00229    *  @param[in] key     Optional key to distinguish different objects of the same type.
00230    *  @param[out] foundSrc If pointer is non-zero then pointed object will be assigned 
00231    *                       with the exact source address of the returned object (must 
00232    *                       be the same as source)
00233    *  @return Shared pointer which can be zero if object not found.
00234    */
00235   GetResultProxy get(const Pds::Src& source, const std::string& key=std::string(), Pds::Src* foundSrc=0) 
00236   {
00237     GetResultProxy pxy = {m_dict, Source(source), key, foundSrc};
00238     return pxy;
00239   }
00240   
00241   /**
00242    *  @brief Get an object from event
00243    *  
00244    *  Find and return data object which was produced by device. This method accepts
00245    *  Source object which allows approximate specification of the device addresses.
00246    *  If specified address matches more than one device in the event then one arbitrary
00247    *  object is returned. The foundSrc argument can be used to obtain exact address
00248    *  of a returned object.
00249    *
00250    *  @param[in] source Source detector address.
00251    *  @param[in] key     Optional key to distinguish different objects of the same type.
00252    *  @param[out] foundSrc If pointer is non-zero then pointed object will be assigned 
00253    *                       with the exact source address of the returned object.
00254    *  @return Shared pointer which can be zero if object not found.
00255    */
00256   GetResultProxy get(const Source& source, const std::string& key=std::string(), Pds::Src* foundSrc=0) 
00257   {
00258     GetResultProxy pxy = {m_dict, source, key, foundSrc};
00259     return pxy;
00260   }
00261   
00262   /**
00263    *  @brief Check if object (or proxy) of given type exists in the event
00264    *  
00265    *  This is optimized version of get() which only checks whether the proxy
00266    *  is there but does not ask proxy to do any real work. It is not guaranteed
00267    *  that get() will return any data even if exists() returns true, proxy may
00268    *  decide that its corresponding data does not exits.
00269    *  
00270    *  @param[in] key     Optional key to distinguish different objects of the same type.
00271    *  @return true if object or proxy exists
00272    */
00273   template <typename T>
00274   bool exists(const std::string& key=std::string()) 
00275   {
00276     EventKey evKey(&typeid(const T), Pds::Src(), key);
00277     return m_dict->exists(evKey);
00278   }
00279   
00280   /**
00281    *  @brief Check if object (or proxy) of given type exists in the event
00282    *  
00283    *  This is optimized version of get() which only checks whether the proxy
00284    *  is there but does not ask proxy to do any real work. It is not guaranteed
00285    *  that get() will return any data even if exists() returns true, proxy may
00286    *  decide that its corresponding data does not exits.
00287    *  
00288    *  @param[in] source Source detector address.
00289    *  @param[in] key     Optional key to distinguish different objects of the same type.
00290    *  @return true if object or proxy exists
00291    */
00292   template <typename T>
00293   bool exists(const Pds::Src& source, 
00294               const std::string& key=std::string()) 
00295   {
00296     EventKey evKey(&typeid(const T), source, key);
00297     return m_dict->exists(evKey);
00298   }
00299   
00300   /**
00301    *  @brief Remove object of given type from the event
00302    *  
00303    *  @param[in] key     Optional key to distinguish different objects of the same type.
00304    *  @return false if object did not exist before this call
00305    */
00306   template <typename T>
00307   bool remove(const std::string& key=std::string()) 
00308   {
00309     EventKey evKey(&typeid(const T), Pds::Src(), key);
00310     return m_dict->remove(evKey);
00311   }
00312   
00313   /**
00314    *  @brief Remove object of given type from the event
00315    *  
00316    *  @param[in] source Source detector address.
00317    *  @param[in] key     Optional key to distinguish different objects of the same type.
00318    *  @return false if object did not exist before this call
00319    */
00320   template <typename T>
00321   bool remove(const Pds::Src& source, 
00322               const std::string& key=std::string()) 
00323   {
00324     EventKey evKey(&typeid(const T), source, key);
00325     return m_dict->remove(evKey);
00326   }
00327   
00328   /**
00329    *  @brief Get the list of event keys defined in event matching given source
00330    *  
00331    *  @param[in]  source matching source address
00332    *  @return list of the EventKey objects
00333    */
00334   std::list<EventKey> keys(const Source& source = Source()) const
00335   {
00336     std::list<EventKey> result;
00337     m_dict->keys(result, source);
00338     return result;
00339   }
00340   
00341   /**
00342    *  @brief Get access to proxy dictionary.
00343    *
00344    *  This method exposes underlying proxy dictionary object. It should
00345    *  not be used by ordinary clients but it could be useful for code
00346    *  which implements additional services based on event (such as
00347    *  Python wrappers).
00348    */
00349   const boost::shared_ptr<ProxyDictI>& proxyDict() const { return m_dict; }
00350 
00351 protected:
00352 
00353 private:
00354 
00355   // Data members
00356   boost::shared_ptr<ProxyDictI> m_dict;   ///< Proxy dictionary object 
00357 
00358 };
00359 
00360 } // namespace PSEvt
00361 
00362 #endif // PSEVT_EVENT_H

Generated on 19 Dec 2016 for PSANAclasses by  doxygen 1.4.7