/* * */ #ifndef CHIMERATK_APPLICATION_CORE_MICRO_DAQ_H #define CHIMERATK_APPLICATION_CORE_MICRO_DAQ_H #include "ApplicationCore.h" #include <ChimeraTK/SupportedUserTypes.h> namespace ChimeraTK { namespace detail { struct AccessorAttacher; struct H5storage; struct DataSpaceCreator; struct DataWriter; } /** * MicroDAQ module for logging data to HDF5 files. This can be usefull in enviromenents where no sufficient logging * of data is possible through the control system. Any ChimeraTK::Module can act as a data source. Which variables * should be logged can be selected through EntityOwner::findTag(). */ struct MicroDAQ : public ApplicationModule { /** * Constructor. decimationFactor and decimationThreshold are configuration constants which determine how the * data reduction is working. Arrays with a size bigger than decimationThreshold will be decimated by * decimationFactor before writing to the HDF5 file. */ MicroDAQ(EntityOwner *owner, const std::string &name, const std::string &description, uint32_t decimationFactor=10, uint32_t decimationThreshold=1000, bool eliminateHierarchy=false, const std::unordered_set<std::string> &tags={}) : ApplicationModule(owner, name, description, eliminateHierarchy, tags), decimationFactor_(decimationFactor), decimationThreshold_(decimationThreshold) {} /** Default constructor, creates a non-working module. Can be used for late initialisation. */ MicroDAQ() : decimationFactor_(0), decimationThreshold_(0) {} ScalarPushInput<int> trigger{this, "trigger", "", "When written, the MicroDAQ write snapshot of all variables " "to the file", {"MicroDAQ.CONFIG"}}; ScalarPollInput<int> enable{this, "enable", "", "DAQ is active when set to 0 and disabled when set to 0.", {"MicroDAQ.CONFIG"}}; ScalarPollInput<uint32_t> nMaxFiles{this, "nMaxFiles", "", "Maximum number of files in the ring buffer " "(oldest file will be overwritten).", {"MicroDAQ.CONFIG"}}; ScalarPollInput<uint32_t> nTriggersPerFile{this, "nTriggersPerFile", "", "Number of triggers stored in each file.", {"MicroDAQ.CONFIG"}}; ScalarOutput<uint32_t> currentFile{this, "currentFile", "", "File number currently written to.", {"MicroDAQ.CONFIG"}}; /** Add a Module as a source to this DAQ. */ void addSource(const Module &source, const std::string &namePrefix=""); protected: void mainLoop() override; template<typename UserType> VariableNetworkNode getAccessor(const std::string &variableName); /** boost::fusion::map of UserTypes to std::lists containing the ArrayPollInput accessors. These accessors are * dynamically created by the AccessorAttacher. */ template<typename UserType> using AccessorList = std::list<ArrayPollInput<UserType>>; TemplateUserTypeMap<AccessorList> accessorListMap; /** boost::fusion::map of UserTypes to std::lists containing the names of the accessors. Technically there would * be no need to use TemplateUserTypeMap for this (as type does not depend on the UserType), but since these * lists must be filled consistently with the accessorListMap, the same construction is used here. */ template<typename UserType> using NameList = std::list<std::string>; TemplateUserTypeMap<NameList> nameListMap; /** Overall variable name list, used to detect name collisions */ std::list<std::string> overallVariableList; /** Parameters for the data decimation */ uint32_t decimationFactor_, decimationThreshold_; friend struct detail::AccessorAttacher; friend struct detail::H5storage; friend struct detail::DataSpaceCreator; friend struct detail::DataWriter; }; } // namespace ChimeraTK #endif /* CHIMERATK_APPLICATION_CORE_MICRO_DAQ_H */