00001 #ifndef PSANA_MODULE_H 00002 #define PSANA_MODULE_H 00003 00004 //-------------------------------------------------------------------------- 00005 // File and Version Information: 00006 // $Id: Module.h 9879 2015-04-08 21:17:39Z davidsch@SLAC.STANFORD.EDU $ 00007 // 00008 // Description: 00009 // Class Module. 00010 // 00011 //------------------------------------------------------------------------ 00012 00013 //----------------- 00014 // C/C++ Headers -- 00015 //----------------- 00016 #include <string> 00017 #include <boost/utility.hpp> 00018 00019 //---------------------- 00020 // Base Class Headers -- 00021 //---------------------- 00022 #include "psana/Configurable.h" 00023 00024 //------------------------------- 00025 // Collaborating Class Headers -- 00026 //------------------------------- 00027 #include "PSEnv/Env.h" 00028 #include "PSEvt/Event.h" 00029 00030 //------------------------------------ 00031 // Collaborating Class Declarations -- 00032 //------------------------------------ 00033 00034 // this is not nice thing to do but we want to simplify user's life 00035 // and provide bunch of simple interfaces to our system 00036 00037 namespace psana {} 00038 using namespace psana; 00039 using namespace PSEnv; 00040 using namespace PSEvt; 00041 using PSHist::Axis; 00042 using boost::shared_ptr; 00043 00044 // define macro for definition of the factory function 00045 #if defined(PSANACAT2_) 00046 #undef PSANACAT2_ 00047 #endif 00048 #define PSANACAT2_(a,b) a ## b 00049 #define PSANA_MODULE_FACTORY(UserModule) \ 00050 extern "C" \ 00051 psana::Module* \ 00052 PSANACAT2_(_psana_module_,UserModule)(const std::string& name) {\ 00053 return new UserModule(name);\ 00054 } 00055 00056 // --------------------- 00057 // -- Class Interface -- 00058 // --------------------- 00059 00060 00061 namespace psana { 00062 00063 /** 00064 * @ingroup psana 00065 * 00066 * @brief Base class for user modules in psana framework. 00067 * 00068 * This is the major customization point available to users. All analysis 00069 * code should inherit from this class and provide implementation of 00070 * one or few methods which have access to all event and non-event data 00071 * being processed by framework. 00072 * 00073 * User modules have some influence on the framework event loop, by calling 00074 * one of the skip(), stop(), or terminate() methods user module can signal the 00075 * framework to either skip the processing of the current event, stop 00076 * analysis gracefully (after closing all output files) or abort anaylis 00077 * immediately. 00078 * 00079 * Subclasses must implement at least event() method, other methods have 00080 * default implementation which does nothing useful. 00081 * 00082 * This software was developed for the LCLS project. If you use all or 00083 * part of it, please give an appropriate acknowledgment. 00084 * 00085 * @version \$Id: Module.h 9879 2015-04-08 21:17:39Z davidsch@SLAC.STANFORD.EDU $ 00086 * 00087 * @author Andrei Salnikov 00088 */ 00089 00090 class Module : boost::noncopyable, protected Configurable { 00091 public: 00092 00093 /** 00094 * @brief Event processing status. 00095 * 00096 * The value returned from status() signals to framework what it should do next. 00097 */ 00098 enum Status { OK, ///< processing finished normally 00099 Skip, ///< skip all remaining modules for this event 00100 Stop, ///< finish with the events 00101 Abort ///< abort immediately, no finalization 00102 }; 00103 00104 // Destructor 00105 virtual ~Module () ; 00106 00107 /// get the name of the module 00108 using Configurable::name; 00109 00110 /// get the class name of the module 00111 using Configurable::className; 00112 00113 /** 00114 * @brief Method which is called once at the beginning of the job 00115 * 00116 * @param[in,out] evt Event object. In this call it does not have any event 00117 * data but can be used to pass information between modules. 00118 * @param[in] env Environment object. 00119 */ 00120 virtual void beginJob(Event& evt, Env& env); 00121 00122 /** 00123 * @brief Method which is called at the beginning of new run 00124 * 00125 * @param[in,out] evt Event object. In this call it does not have any event 00126 * data but can be used to pass information between modules. 00127 * @param[in] env Environment object. 00128 */ 00129 virtual void beginRun(Event& evt, Env& env); 00130 00131 /** 00132 * @brief Method which is called at the beginning of new calibration cycle (step) 00133 * 00134 * @param[in,out] evt Event object. In this call it does not have any event 00135 * data but can be used to pass information between modules. 00136 * @param[in] env Environment object. 00137 */ 00138 virtual void beginCalibCycle(Event& evt, Env& env); 00139 00140 /** 00141 * @brief Method which is called with event data 00142 * 00143 * @param[in,out] evt Event object. 00144 * @param[in] env Environment object. 00145 */ 00146 virtual void event(Event& evt, Env& env) = 0; 00147 00148 /** 00149 * @brief Method which is called at the end of the calibration cycle (step) 00150 * 00151 * @param[in,out] evt Event object. In this call it does not have any event 00152 * data but can be used to pass information between modules. 00153 * @param[in] env Environment object. 00154 */ 00155 virtual void endCalibCycle(Event& evt, Env& env); 00156 00157 /** 00158 * @brief Method which is called at the end of the run 00159 * 00160 * @param[in,out] evt Event object. In this call it does not have any event 00161 * data but can be used to pass information between modules. 00162 * @param[in] env Environment object. 00163 */ 00164 virtual void endRun(Event& evt, Env& env); 00165 00166 /** 00167 * @brief Method which is called once at the end of the job 00168 * 00169 * @param[in,out] evt Event object. In this call it does not have any event 00170 * data but can be used to pass information between modules. 00171 * @param[in] env Environment object. 00172 */ 00173 virtual void endJob(Event& evt, Env& env); 00174 00175 /// reset module status 00176 void reset() { m_status = OK; } 00177 00178 /// get status 00179 Status status() const { return m_status; } 00180 00181 /// Returns true if this module is interested in all events including skipped 00182 bool observeAllEvents() const { return m_observeAllEvents; } 00183 00184 protected: 00185 00186 /// The one and only constructor, needs module name. 00187 Module (const std::string& name, bool observeAllEvents = false) ; 00188 00189 /** 00190 * @brief Signal framework to skip current event and do not call other downstream modules. 00191 * 00192 * Note that this method does not skip code in the current module, control is 00193 * returned back to the module. If you want to stop processing after this call 00194 * then add a return statement. 00195 */ 00196 void skip() { m_status = Skip; } 00197 00198 /** 00199 * @brief Signal framework to stop event loop and finish job gracefully. 00200 * 00201 * Note that this method does not terminate processing in the current module. 00202 * If you want to stop processing after this call then add a return statement. 00203 */ 00204 void stop() { m_status = Stop; } 00205 00206 /** 00207 * @brief Signal framework to terminate immediately. 00208 * 00209 * Note that this method does not terminate processing in the current module. 00210 * If you want to stop processing after this call then add a return statement. 00211 */ 00212 void terminate() { m_status = Abort; } 00213 00214 private: 00215 00216 Status m_status; ///< Current event processing status 00217 bool m_observeAllEvents; ///< If true then this module will receive all events, event skipped ones 00218 00219 }; 00220 00221 // formatting for enum 00222 std::ostream& 00223 operator<<(std::ostream& out, Module::Status stat); 00224 00225 } // namespace psana 00226 00227 #endif // PSANA_MODULE_H