otsdaq-mu2e-stm  5.02.01
operation_manager.cc
1 // Process Manager code
2 #include "Mu2e-STMDAQ/processing/operation_manager.hh"
3 
4 // Constructor
5 OperationManager::OperationManager(Config& cfg_,
6  const std::shared_ptr<AsyncLogger>& logger_,
7  const std::shared_ptr<STMdata>& stm_,
8  const std::shared_ptr<SignalHandler>& signal_)
9  : cfg(cfg_), logger(logger_), stm(stm_), signal(signal_)
10 {
11  // Get class names from the config file
12  auto class_names = cfg.extractKeysAndValues("stm.operations");
13 
14  // Boolean to signal form events is off
15  bool form_events = false;
16 
17  // Channel number
18  int ch_num = stm->master_config.ch_num;
19 
20  // Loop over all class names in config file
21  for(const auto& class_ : class_names)
22  {
23  // Check if class name is valid
24  if(!isValidClass(class_.first))
25  {
26  // Log critical error to user
27  std::stringstream output;
28  output << "Operation class key: \"" << class_.first << "\" in "
29  << cfg.getXMLpath() << " is NOT a valid class name.";
30  logger->log(output.str(), 0);
31  return;
32  }
33 
34  // Get the xml config file node
35  std::string class_node = "stm.operations." + class_.first;
36  // Get the config file boolean to use or not
37  bool use_class = cfg.getValue<int>(class_node);
38 
39  // If class is switched off
40  if(!use_class)
41  {
42  // Log class is off and continue
43  logger->log(class_.first + " class is OFF.", 1);
44  continue;
45  }
46 
47  // Signal if FormEvents is on
48  if(class_.first == "FormEvents")
49  form_events = true;
50  // If ZeroSuppress or MWD are on and FormEvents is off, switch them off
51  if((class_.first == "ZeroSuppress" || class_.first == "MWD" ||
52  class_.first == "PulseHeight") &&
53  !form_events)
54  {
55  // Log class is off and continue
56  logger->log("WARNING: " + class_.first +
57  " ON when FormEvents OFF. Switching off " + class_.first +
58  ".",
59  2);
60  logger->log(class_.first + " is OFF.", 1);
61  continue;
62  }
63 
64  // Check if ZS find peaks is on for Noise module
65  // If it isn't on, turn Noise off
66  std::pair<std::string, std::string> find_peaks_op = {"ZeroSuppress",
67  "find_peaks"};
68  if(class_.first == "Noise" &&
69  std::find(useOpsFlag.begin(), useOpsFlag.end(), find_peaks_op) ==
70  useOpsFlag.end())
71  {
72  logger->log("WARNING: " + class_.first + " ON when " + find_peaks_op.first +
73  "::" + find_peaks_op.second +
74  " operation is OFF. Switching off " + class_.first + ".",
75  2);
76  logger->log(class_.first + " is OFF.", 1);
77  continue;
78  }
79 
80  // Check correct PH finder for each channel
81  if(ch_num == 1 && class_.first == "MWD")
82  {
83  logger->log("WARNING: " + class_.first + " ON for " +
84  stm->master_config.ch_name + ", use PulseHeight instead" +
85  ". Switching off " + class_.first + ".",
86  2);
87  logger->log(class_.first + " is OFF.", 1);
88  continue;
89  }
90  else if(ch_num == 0 && class_.first == "PulseHeight")
91  {
92  logger->log("WARNING: " + class_.first + " ON for " +
93  stm->master_config.ch_name + ", use MWD instead" +
94  ". Switching off " + class_.first + ".",
95  2);
96  logger->log(class_.first + " is OFF.", 1);
97  continue;
98  }
99 
100  // Turn off baseline for LaBr while we work on convergence
101  if(ch_num == 1 && class_.first == "Baseline")
102  {
103  logger->log("WARNING: Switching off " + class_.first + " for " +
104  stm->master_config.ch_name + ".",
105  2);
106  logger->log(class_.first + " is OFF.", 1);
107  continue;
108  }
109 
110  // Log class is on
111  logger->log(class_.first + " class is ON.", 1);
112 
113  // Find the class name in the name
114  auto it = class_map.find(class_.first);
115  // If class is within the map
116  if(it != class_map.end())
117  {
118  // Instantiate and store the class
119  classes[class_.first] = it->second.constructor();
120  }
121  // Else, class not found in map
122  else
123  {
124  // Log critical error
125  logger->log("ERROR: No class_map entry for class: " + class_.first, 0);
126  }
127 
128  // Get the class operation names
129  auto op_names = cfg.extractKeysAndValues(class_node);
130 
131  // Boolean to turn later class operation off if earlier one is off
132  bool rest_off = false;
133 
134  // Loop over all operation names
135  for(const auto& op_ : op_names)
136  {
137  // Check if operation name is valid
138  if(!isValidOp(class_.first, op_.first))
139  {
140  // Log critical error to user
141  std::stringstream output;
142  output << "Operation key: \"" << class_.first << "::" << op_.first
143  << "\" in " << cfg.getXMLpath()
144  << " is NOT a valid class.operation name.";
145  logger->log(output.str(), 0);
146  return;
147  }
148 
149  // Get the xml config file node
150  std::string op_node = class_node + "." + op_.first;
151  // Get the operation name to print
152  std::string op_name = class_.first + "::" + op_.first;
153  // Get the config file boolean to use or not
154  bool use_op = cfg.getValue<int>(op_node);
155  // If it has been signalled that we should turn the rest off
156  // (UNLESS WRITE STREAM!)
157  if(use_op && rest_off && class_.first != "WriteManager")
158  {
159  // Warn user
160  logger->log("WARNING: " + class_.first + "::" + op_.first +
161  " ON when earlier " + class_.first +
162  " operations OFF. Switching off " + class_.first +
163  "::" + op_.first + ".",
164  2);
165  use_op = false;
166  }
167  // If operation is switched off
168  if(!use_op)
169  {
170  // Log operation is off
171  logger->log("- " + op_name + " is OFF.", 1);
172  // Ensure rest of class is switched off and continue
173  rest_off = true;
174  continue;
175  }
176 
177  // Log class is on
178  logger->log("- " + op_name + " is ON.", 1);
179  // Push back operation to use list
180  useOpsFlag.push_back({class_.first, op_.first});
181  }
182  }
183 
184  // // FOR DEVELOPMENT ONLY: Add last function (defined above) to the use list
185  // if (useOpsFlag.size() > 0 && useOpsFlag[0].first == "UDP"){ // If receiving data...
186  // std::string last_class_name = "TestFuncs";
187  // std::string last_op_name = "doNothing";
188  // // std::string last_op_name = "print";
189  // // std::string last_op_name = "printPackets";
190  // // std::string last_op_name = "check_form_events";
191  // // std::string last_op_name = "check_prep_zs";
192  // // std::string last_op_name = "check_zs";
193  // auto last_class = class_map.find(last_class_name);
194  // classes[last_class_name] = last_class->second.constructor();
195  // logger->log(last_class_name + " is ON.",1);
196  // logger->log("- " + last_class_name + "::" + last_op_name + " is ON.",1);
197  // useOpsFlag.push_back({last_class_name,last_op_name});
198  // }
199 
200  // Loop over all selected operations
201  // for (const auto& [className, opName] : useOpsFlag) {
202  // useOps.emplace_back(className + "::" + opName,
203  // [this, className, opName](std::shared_ptr<DataStruct>& buffer) {
204  // classes[className]->execute(opName, buffer);});
205  // }
206 
207  // Loop over all selected operations
208  for(const auto& [className, opName] : useOpsFlag)
209  {
210  // Defensive: class must exist
211  if(classes.find(className) == classes.end() || !classes[className])
212  {
213  logger->log("ERROR: OperationManager: class '" + className + "' is null.", 0);
214  continue;
215  }
216 
217  // Decide whether op needs 2 buffers
218  const bool needs2 = classes[className]->requires_two_buffers(opName);
219 
220  if(needs2)
221  {
222  // Store a 2-buffer operation
223  useOps.emplace_back(
224  className + "::" + opName,
225  op2{[this, className, opName](std::shared_ptr<DataStruct>& buffer,
226  std::shared_ptr<DataStruct>& prev_buffer) {
227  classes[className]->execute(opName, buffer, prev_buffer);
228  }});
229  }
230  else
231  {
232  // Store a 1-buffer operation
233  useOps.emplace_back(
234  className + "::" + opName,
235  op1{[this, className, opName](std::shared_ptr<DataStruct>& buffer) {
236  classes[className]->execute(opName, buffer);
237  }});
238  }
239  }
240 
241  // Notify user
242  logger->log("OperationManager initialised a total of " +
243  std::to_string(useOps.size()) + " operations",
244  1);
245 
246  // Now number of ops known DQM can allocate shm
247  if(classes.count("DQM"))
248  {
249  auto dqm_ptr = std::dynamic_pointer_cast<DQM>(classes["DQM"]);
250  if(dqm_ptr)
251  dqm_ptr->init_shm();
252  }
253 }
254 
255 // Get the list of selected operations
256 std::vector<std::pair<std::string, op_any>> OperationManager::getUseOps() const
257 {
258  return useOps;
259 }
Definition: config.hh:19