Newer
Older
*/
#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;
} // namespace detail
/**
* 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),
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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 RegisterPath &namePrefix = "");
protected:
void mainLoop() override;
template <typename UserType>
VariableNetworkNode getAccessor(const std::string &variableName);
/** Map of VariableGroups required to build the hierarchies. The key it the
* full path name. */
std::map<std::string, VariableGroup> groupMap;
/** 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 */