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