QwAnalysis
QwSubsystemArray.cc
Go to the documentation of this file.
1 /**********************************************************\
2 * File: QwSubsystemArray.cc *
3 * *
4 * Author: *
5 * Time-stamp: *
6 \**********************************************************/
7 
8 #include "QwSubsystemArray.h"
9 
10 // System headers
11 #include <stdexcept>
12 
13 // Qweak headers
14 #include "VQwHardwareChannel.h"
15 #include "QwLog.h"
16 #include "QwParameterFile.h"
17 
18 /// \todo TODO (wdc) QwVQWK_Channel necessary due to explicit cast in ReturnInternalValue (yuck)
19 #include "QwVQWK_Channel.h"
20 
21 //*****************************************************************
22 
23 /**
24  * Create a subsystem array based on the configuration option 'detectors'
25  */
26 QwSubsystemArray::QwSubsystemArray(QwOptions& options, CanContainFn myCanContain)
27 : fEventTypeMask(0x0),fnCanContain(myCanContain)
28 {
29  ProcessOptionsToplevel(options);
30  QwParameterFile detectors(fSubsystemsMapFile.c_str());
31  QwMessage << "Loading subsystems from " << fSubsystemsMapFile << "." << QwLog::endl;
33 }
34 
35 /**
36  * Copy constructor by reference
37  * @param source Source subsystem array
38  */
40 : fTreeArrayIndex(source.fTreeArrayIndex),
41  fCodaRunNumber(source.fCodaRunNumber),
42  fCodaSegmentNumber(source.fCodaSegmentNumber),
43  fCodaEventNumber(source.fCodaEventNumber),
44  fCodaEventType(source.fCodaEventType),
45  fEventTypeMask(source.fEventTypeMask),
46  fHasDataLoaded(source.fHasDataLoaded),
47  fnCanContain(source.fnCanContain),
48  fSubsystemsMapFile(source.fSubsystemsMapFile),
49  fSubsystemsDisabledByName(source.fSubsystemsDisabledByName),
50  fSubsystemsDisabledByType(source.fSubsystemsDisabledByType)
51 {
55 
56  // Make copies of all subsystems rather than copying just the pointers
57  for (const_iterator subsys = source.begin(); subsys != source.end(); ++subsys) {
58  this->push_back(subsys->get()->Clone());
59  // Instruct the subsystem to publish variables
60  if (this->back()->PublishInternalValues() == kFALSE) {
61  QwError << "Not all variables for " << this->back()->GetSubsystemName()
62  << " could be published!" << QwLog::endl;
63  }
64  }
65 }
66 
67 
68 /**
69  * Fill the subsystem array with the contents of a map file
70  * @param detectors Map file
71  */
73 {
74  // This is how this should work
75  QwParameterFile* preamble;
76  preamble = detectors.ReadSectionPreamble();
77  // Process preamble
78  QwVerbose << "Preamble:" << QwLog::endl;
79  QwVerbose << *preamble << QwLog::endl;
80  if (preamble) delete preamble;
81 
82  QwParameterFile* section;
83  std::string section_name;
84  while ((section = detectors.ReadNextSection(section_name))) {
85 
86  // Debugging output of configuration section
87  QwVerbose << "[" << section_name << "]" << QwLog::endl;
88  QwVerbose << *section << QwLog::endl;
89 
90  // Determine type and name of subsystem
91  std::string subsys_type = section_name;
92  std::string subsys_name;
93  if (! section->FileHasVariablePair("=","name",subsys_name)) {
94  QwError << "No name defined in section for subsystem " << subsys_type << "." << QwLog::endl;
95  delete section; section = 0;
96  continue;
97  }
98 
99  // If subsystem type is explicitly disabled
100  bool disabled_by_type = false;
101  for (size_t i = 0; i < fSubsystemsDisabledByType.size(); i++)
102  if (subsys_type == fSubsystemsDisabledByType.at(i))
103  disabled_by_type = true;
104  if (disabled_by_type) {
105  QwWarning << "Subsystem of type " << subsys_type << " disabled." << QwLog::endl;
106  delete section; section = 0;
107  continue;
108  }
109 
110  // If subsystem name is explicitly disabled
111  bool disabled_by_name = false;
112  for (size_t i = 0; i < fSubsystemsDisabledByName.size(); i++)
113  if (subsys_name == fSubsystemsDisabledByName.at(i))
114  disabled_by_name = true;
115  if (disabled_by_name) {
116  QwWarning << "Subsystem with name " << subsys_name << " disabled." << QwLog::endl;
117  delete section; section = 0;
118  continue;
119  }
120 
121  // Create subsystem
122  QwMessage << "Creating subsystem of type " << subsys_type << " "
123  << "with name " << subsys_name << "." << QwLog::endl;
124  VQwSubsystem* subsys = 0;
125  try {
126  subsys =
127  VQwSubsystemFactory::Create(subsys_type, subsys_name);
128  } catch (QwException_TypeUnknown&) {
129  QwError << "No support for subsystems of type " << subsys_type << "." << QwLog::endl;
130  // Fall-through to next error for more the psychological effect of many warnings
131  }
132  if (! subsys) {
133  QwError << "Could not create subsystem " << subsys_type << "." << QwLog::endl;
134  delete section; section = 0;
135  continue;
136  }
137 
138  // If this subsystem cannot be stored in this array
139  if (! fnCanContain(subsys)) {
140  QwMessage << "Subsystem " << subsys_name << " cannot be stored in this "
141  << "subsystem array." << QwLog::endl;
142  QwMessage << "Deleting subsystem " << subsys_name << " again" << QwLog::endl;
143  delete section; section = 0;
144  delete subsys; subsys = 0;
145  continue;
146  }
147 
148  // Pass detector maps
149  subsys->LoadDetectorMaps(*section);
150  // Add to array
151  this->push_back(subsys);
152 
153  // Instruct the subsystem to publish variables
154  if (subsys->PublishInternalValues() == kFALSE) {
155  QwError << "Not all variables for " << subsys->GetSubsystemName()
156  << " could be published!" << QwLog::endl;
157  }
158 
159  // Delete parameter file section
160  delete section; section = 0;
161  }
162 }
163 
164 //*****************************************************************
165 
166 /**
167  * Add the subsystem to this array. Do nothing if the subsystem is null or if
168  * there is already a subsystem with that name in the array.
169  * @param subsys Subsystem to add to the array
170  */
172 {
173  if (subsys == NULL) {
174  QwError << "QwSubsystemArray::push_back(): NULL subsys"
175  << QwLog::endl;
176  // This is an empty subsystem...
177  // Do nothing for now.
178 
179  } else if (!this->empty() && GetSubsystemByName(subsys->GetSubsystemName())){
180  // There is already a subsystem with this name!
181  QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetSubsystemName()
182  << " already exists" << QwLog::endl;
183 
184  } else if (!fnCanContain(subsys)) {
185  // There is no support for this type of subsystem
186  QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetSubsystemName()
187  << " is not supported by this subsystem array" << QwLog::endl;
188 
189  } else {
190  boost::shared_ptr<VQwSubsystem> subsys_tmp(subsys);
191  SubsysPtrs::push_back(subsys_tmp);
192 
193  // Set the parent of the subsystem to this array
194  subsys_tmp->SetParent(this);
195 
196  // Update the event type mask
197  // Note: Active bits in the mask indicate event types that are accepted
198  fEventTypeMask |= subsys_tmp->GetEventTypeMask();
199  }
200 }
201 
202 
203 
204 /**
205  * Define configuration options for global array
206  * @param options Options
207  */
209 {
210  options.AddOptions()("detectors",
211  po::value<std::string>()->default_value("detectors.map"),
212  "map file with detectors to include");
213 
214  // Versions of boost::program_options below 1.39.0 have a bug in multitoken processing
215 #if BOOST_VERSION < 103900
216  options.AddOptions()("disable-by-type",
217  po::value<std::vector <std::string> >(),
218  "subsystem types to disable");
219  options.AddOptions()("disable-by-name",
220  po::value<std::vector <std::string> >(),
221  "subsystem names to disable");
222 #else // BOOST_VERSION >= 103900
223  options.AddOptions()("disable-by-type",
224  po::value<std::vector <std::string> >()->multitoken(),
225  "subsystem types to disable");
226  options.AddOptions()("disable-by-name",
227  po::value<std::vector <std::string> >()->multitoken(),
228  "subsystem names to disable");
229 #endif // BOOST_VERSION
230 }
231 
232 
233 /**
234  * Handle configuration options for the subsystem array itself
235  * @param options Options
236  */
238 {
239  // Filename to use for subsystem creation (single filename could be expanded
240  // to a list)
241  fSubsystemsMapFile = options.GetValue<std::string>("detectors");
242  // Subsystems to disable
243  fSubsystemsDisabledByName = options.GetValueVector<std::string>("disable-by-name");
244  fSubsystemsDisabledByType = options.GetValueVector<std::string>("disable-by-type");
245 }
246 
247 
248 /**
249  * Handle configuration options for all subsystems in the array
250  * @param options Options
251  */
253 {
254  for (iterator subsys_iter = begin(); subsys_iter != end(); ++subsys_iter) {
255  VQwSubsystem* subsys = dynamic_cast<VQwSubsystem*>(subsys_iter->get());
256  subsys->ProcessOptions(options);
257  }
258 }
259 
260 
261 /**
262  * Get the subsystem in this array with the spcified name
263  * @param name Name of the subsystem
264  * @return Pointer to the subsystem
265  */
267 {
268  VQwSubsystem* tmp = NULL;
269  if (!empty()) {
270  // Loop over the subsystems
271  for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
272  // Check the name of this subsystem
273  // std::cout<<"QwSubsystemArray::GetSubsystemByName available name=="<<(*subsys)->GetSubsystemName()<<"== to be compared to =="<<name<<"==\n";
274  if ((*subsys)->GetSubsystemName() == name) {
275  tmp = (*subsys).get();
276  //std::cout<<"QwSubsystemArray::GetSubsystemByName found a matching name \n";
277  } else {
278  // nothing
279  }
280  }
281  }
282  return tmp;
283 }
284 
285 
286 /**
287  * Get the list of subsystems in this array of the specified type
288  * @param type Type of the subsystem
289  * @return Vector of subsystems
290  */
291 std::vector<VQwSubsystem*> QwSubsystemArray::GetSubsystemByType(const std::string& type)
292 {
293  // Vector of subsystem pointers
294  std::vector<VQwSubsystem*> subsys_list;
295 
296  // If this array is not empty
297  if (!empty()) {
298 
299  // Loop over the subsystems
300  for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
301 
302  // Test to see if the subsystem inherits from the required type
303  if (VQwSubsystemFactory::InheritsFrom((*subsys).get(),type)) {
304  subsys_list.push_back((*subsys).get());
305  }
306 
307  } // end of loop over subsystems
308 
309  } // end of if !empty()
310 
311  return subsys_list;
312 }
313 
314 
316 {
317  if (!empty()) {
318  SetDataLoaded(kFALSE);
320  SetCodaEventType(0);
321  std::for_each(begin(), end(),
322  boost::mem_fn(&VQwSubsystem::ClearEventData));
323  }
324 }
325 
327  const UInt_t roc_id,
328  const UInt_t bank_id,
329  UInt_t* buffer,
330  UInt_t num_words)
331 {
332  if (!empty())
333  for (iterator subsys = begin(); subsys != end(); ++subsys){
334  (*subsys)->ProcessConfigurationBuffer(roc_id, bank_id, buffer, num_words);
335  }
336  return 0;
337 }
338 
340  const UInt_t event_type,
341  const UInt_t roc_id,
342  const UInt_t bank_id,
343  UInt_t* buffer,
344  UInt_t num_words)
345 {
346  if (!empty())
347  SetDataLoaded(kTRUE);
348  for (iterator subsys = begin(); subsys != end(); ++subsys){
349  (*subsys)->ProcessEvBuffer(event_type, roc_id, bank_id, buffer, num_words);
350  }
351  return 0;
352 }
353 
354 
356 {
357  if (!empty() && HasDataLoaded()) {
358  std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::ProcessEvent));
359  std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::ExchangeProcessedData));
360  std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::ProcessEvent_2));
361  }
362 }
363 
365 {
366  QwDebug << "QwSubsystemArray at end of event loop" << QwLog::endl;
367  if (!empty()) {
368  std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::AtEndOfEventLoop));
369  }
370 }
371 
372 //*****************************************************************
373 void QwSubsystemArray::RandomizeEventData(int helicity, double time)
374 {
375  if (!empty())
376  for (iterator subsys = begin(); subsys != end(); ++subsys) {
377  (*subsys)->RandomizeEventData(helicity, time);
378  }
379 }
380 
381 //*****************************************************************
382 void QwSubsystemArray::EncodeEventData(std::vector<UInt_t> &buffer)
383 {
384  if (!empty())
385  for (iterator subsys = begin(); subsys != end(); ++subsys) {
386  (*subsys)->EncodeEventData(buffer);
387  }
388 }
389 
390 
391 //*****************************************************************
392 void QwSubsystemArray::ConstructHistograms(TDirectory *folder, TString &prefix)
393 {
394  if (!empty()) {
395  for (iterator subsys = begin(); subsys != end(); ++subsys){
396  (*subsys)->ConstructHistograms(folder,prefix);
397  }
398  }
399 }
400 
402 {
403  if (!empty())
404  std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::FillHistograms));
405 }
406 
408 {
409  if (!empty() && !source.empty()) {
410  if (this->size() == source.size()) {
411  for (size_t i = 0; i < source.size(); ++i) {
412  this->at(i)->ShareHistograms(source.at(i).get());
413  }
414  }
415  }
416 }
417 //*****************************************************************
418 
419 /**
420  * Construct the tree for this subsystem
421  * @param folder Directory where to construct the tree
422  * @param prefix Prefix for the name of the tree
423  */
424 void QwSubsystemArray::ConstructTree(TDirectory *folder, TString &prefix)
425 {
426  if (!empty()) {
427  for (iterator subsys = begin(); subsys != end(); ++subsys){
428  (*subsys)->ConstructTree(folder, prefix);
429  }
430  }
431 }
432 
433 /**
434  * Fill the tree for this subsystem
435  */
437 {
438  if (!empty())
439  std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::FillTree));
440 }
441 
442 /**
443  * Delete the tree for this subsystem
444  */
446 {
447  if (!empty())
448  std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::DeleteTree));
449 }
450 
451 //*****************************************************************
452 
454 {
455  if (!empty()) {
456  for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
457  (*subsys)->PrintInfo();
458  }
459  }
460 }
461 
462 //*****************************************************************
463 
464 /**
465  * Construct the branch and tree vector
466  * @param tree Tree
467  * @param prefix Prefix
468  * @param values Vector of values
469  */
471  TTree *tree,
472  TString& prefix,
473  std::vector<Double_t>& values)
474 {
475  fTreeArrayIndex = values.size();
476 
477  // Each tree should only contain event number and type once, but will
478  // still reserve space in the values vector, so we don't need to modify
479  // FillTreeVector().
480  values.push_back(0.0);
481  values.push_back(0.0);
482  values.push_back(0.0);
483  values.push_back(0.0);
484  values.push_back(0.0);
485  if (prefix == "" || prefix == "yield_") {
486  tree->Branch("CodaEventNumber",&(values[fTreeArrayIndex]),"CodaEventNumber/D");
487  tree->Branch("CodaEventType",&(values[fTreeArrayIndex+1]),"CodaEventType/D");
488  tree->Branch("Coda_CleanData",&(values[fTreeArrayIndex+2]),"Coda_CleanData/D");
489  tree->Branch("Coda_ScanData1",&(values[fTreeArrayIndex+3]),"Coda_ScanData1/D");
490  tree->Branch("Coda_ScanData2",&(values[fTreeArrayIndex+4]),"Coda_ScanData2/D");
491  }
492 
493  for (iterator subsys = begin(); subsys != end(); ++subsys) {
494  VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
495  subsys_ptr->ConstructBranchAndVector(tree, prefix, values);
496  }
497 
498 }
499 
500 
501 /**
502  * Construct the branch for the flat tree
503  * @param tree Tree
504  * @param prefix Prefix
505  */
506 void QwSubsystemArray::ConstructBranch(TTree *tree, TString& prefix)
507 {
508  // Only MPS tree should contain event number and type
509  if (prefix == "" || prefix == "yield_") {
510  tree->Branch("CodaEventNumber",&fCodaEventNumber,"CodaEventNumber/I");
511  tree->Branch("CodaEventType",&fCodaEventType,"CodaEventType/I");
512  }
513 
514  for (iterator subsys = begin(); subsys != end(); ++subsys) {
515  VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
516  subsys_ptr->ConstructBranch(tree, prefix);
517  }
518 }
519 
520 
521 /**
522  * Construct the branch for the flat tree with tree trim files accepted
523  * @param tree Tree
524  * @param prefix Prefix
525  * @param trim_file Trim file
526  */
528  TTree *tree,
529  TString& prefix,
530  QwParameterFile& trim_file)
531 {
532  QwMessage << " QwSubsystemArray::ConstructBranch " << QwLog::endl;
533 
534  QwParameterFile* preamble;
535  QwParameterFile* nextsection;
536  preamble = trim_file.ReadSectionPreamble();
537 
538  // Process preamble
539  QwVerbose << "QwSubsystemArrayTracking::ConstructBranch Preamble:" << QwLog::endl;
540  QwVerbose << *preamble << QwLog::endl;
541 
542  if (prefix == "" || prefix == "yield_") {
543  tree->Branch("CodaEventNumber",&fCodaEventNumber,"CodaEventNumber/I");
544  tree->Branch("CodaEventType",&fCodaEventType,"CodaEventType/I");
545  }
546 
547  for (iterator subsys = begin(); subsys != end(); ++subsys) {
548  VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
549 
550  TString subsysname = subsys_ptr->GetSubsystemName();
551  //QwMessage << "Tree leaves created for " << subsysname << QwLog::endl;
552 
553  if (trim_file.FileHasSectionHeader(subsysname)) {
554  // This section contains modules and their channels to be included in the tree
555  nextsection = trim_file.ReadUntilNextSection();
556  subsys_ptr->ConstructBranch(tree, prefix, *nextsection);
557  QwMessage << "Tree leaves created for " << subsysname << QwLog::endl;
558  } else
559  QwMessage << "No tree leaves created for " << subsysname << QwLog::endl;
560  }
561 }
562 
563 
564 /**
565  * Fill the tree vector
566  * @param values Vector of values
567  */
568 void QwSubsystemArray::FillTreeVector(std::vector<Double_t>& values) const
569 {
570  // Fill the event number and event type
571  size_t index = fTreeArrayIndex;
572  values[index++] = this->GetCodaEventNumber();
573  values[index++] = this->GetCodaEventType();
574  values[index++] = this->fCleanParameter[0];
575  values[index++] = this->fCleanParameter[1];
576  values[index++] = this->fCleanParameter[2];
577 
578 
579  // Fill the subsystem data
580  for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
581  VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
582  subsys_ptr->FillTreeVector(values);
583  }
584 }
585 
586 //*****************************************************************
587 
588 /**
589  * Retrieve the variable name from other subsystem arrays
590  * @param name Variable name to be retrieved
591  * @param value (return) Data element with the variable name
592  * @return True if the variable is found, false if not found
593  */
594 Bool_t QwSubsystemArray::RequestExternalValue(const TString& name, VQwHardwareChannel* value) const
595 {
596  // If this has a parent, we should escalate the call to that object,
597  // but so far we don't have that capability.
598  return ReturnInternalValue(name, value);
599 }
600 
601 /**
602  * Retrieve the variable name from subsystems in this subsystem array
603  * @param name Variable name to be retrieved
604  * @return Data element with the variable name, null if not found
605  */
607 {
608  // First try to find the value in the list of published values.
609  std::map<TString, const VQwHardwareChannel*>::const_iterator iter1 =
610  fPublishedValuesDataElement.find(name);
611  if (iter1 != fPublishedValuesDataElement.end()) {
612  return iter1->second;
613  }
614  // Second, ask the subsystem that has claimed the value
615  std::map<TString, const VQwSubsystem*>::const_iterator iter2 =
616  fPublishedValuesSubsystem.find(name);
617  if (iter2 != fPublishedValuesSubsystem.end()) {
618  return (iter2->second)->ReturnInternalValue(name);
619  }
620  // If the value is not yet published, try requesting it.
621  if (const_cast<QwSubsystemArray*>(this)->PublishByRequest(name)){
622  iter1 = fPublishedValuesDataElement.find(name);
623  if (iter1 != fPublishedValuesDataElement.end()) {
624  return iter1->second;
625  }
626  QwError << "PublishByRequest succeeded, but can't find the record for "
627  << name << QwLog::endl;
628 
629  } else {
630  QwError << "PublishByRequest failed for " << name << QwLog::endl;
631  }
632  // Not found
633  return 0;
634 }
635 
636 /**
637  * Retrieve the variable name from subsystems in this subsystem array
638  * @param name Variable name to be retrieved
639  * @param value (return) Data element with the variable name
640  * @return True if the variable was found, false if not found
641  */
642 Bool_t QwSubsystemArray::ReturnInternalValue(const TString& name, VQwHardwareChannel* value) const
643 {
644  Bool_t foundit = kFALSE;
645 
646  // Check for null pointer
647  if (! value)
648  QwWarning << "QwSubsystemArray::ReturnInternalValue requires that "
649  << "'value' be a non-null pointer to a VQwHardwareChannel."
650  << QwLog::endl;
651 
652  // Get a const pointer to the internal value
653  VQwHardwareChannel* internal_value = const_cast<VQwHardwareChannel*>(ReturnInternalValue(name));
654  if (value && internal_value && typeid(value) == typeid(internal_value)) {
655  /// \todo TODO (wdc) Remove this ugly statement by redefining
656  /// QwVQWK_Channel::operator= to accept any VQwHardwareChannel.
657  //*(dynamic_cast<QwVQWK_Channel*>(value)) = *(dynamic_cast<QwVQWK_Channel*>(internal_value));
658  value->AssignValueFrom(internal_value);
659  foundit = kTRUE;
660  } else
661  QwWarning << "QwSubsystemArray::ReturnInternalValue: name \""
662  << name << "\" not found in array." << QwLog::endl;
663 
664  return foundit;
665 }
666 
667 /**
668  * Publish the value name with description from a subsystem in this array
669  * @param name Name of the variable
670  * @param desc Description of the variable
671  * @param subsys Subsystem that contains the variable
672  * @param element Data element that contains the variable
673  * @return True if the variable could be published, false if not published
674  */
676  const TString name,
677  const TString desc,
678  const VQwSubsystem* subsys,
679  const VQwHardwareChannel* element)
680 {
681  if (fPublishedValuesSubsystem.count(name) > 0) {
682  QwError << "Attempting to publish existing variable key!" << QwLog::endl;
684  return kFALSE;
685  }
686  fPublishedValuesSubsystem[name] = subsys;
687  fPublishedValuesDescription[name] = desc;
688  fPublishedValuesDataElement[name] = element;
689  return kTRUE;
690 }
691 
692 /**
693  * Try to publish an internal variable matching the submitted name
694  * @param device_name Name of the desired published variable
695  * @return True if the variable could be published, false if not published
696  */
697 Bool_t QwSubsystemArray::PublishByRequest(TString device_name){
698  Bool_t status = kFALSE;
699  if (fPublishedValuesSubsystem.count(device_name) > 0) {
700  QwError << "QwSubsystemArray::PublishByRequest: Channel "
701  << device_name << " has already been published."
702  << QwLog::endl;
704  status = kTRUE;
705  } else if (not empty()) {
706  for (iterator subsys = begin(); subsys != end(); ++subsys)
707  {
708  status = (*subsys)->PublishByRequest(device_name);
709  if (status) break;
710  }
711  // Report failure to publish
712  if (! status) {
713  QwError << "QwSubsystemArray::PublishByRequest: Failed to publish channel name: "
714  << device_name << QwLog::endl;
715  }
716  }
717  return status;
718 }
719 
720 
721 /**
722  * List the published values and description in this subsystem array
723  */
725 {
726  QwOut << "List of published values:" << QwLog::endl;
727  std::map<TString,TString>::const_iterator iter;
728  for (iter = fPublishedValuesDescription.begin();
729  iter != fPublishedValuesDescription.end(); iter++) {
730  QwOut << iter->first << ": " << iter->second << QwLog::endl;
731  }
732 }
733 
734 /**
735  * Retrieve the variable name from subsystems in this subsystem array
736  * @param name Variable name to be retrieved
737  * @return Data element with the variable name
738  */
740 {
741  return const_cast<VQwHardwareChannel*>(ReturnInternalValue(name));
742 }
743 
744 
745 
746 // TList* QwSubsystemArray::GetParamFileNameList(TString name) const
747 // {
748 // if (not empty()) {
749 
750 // TList* return_maps_TList = new TList;
751 // return_maps_TList->SetOwner(true);
752 // return_maps_TList->SetName(name);
753 
754 // std::vector<TString> mapfiles_vector_subsystem;
755 
756 // Int_t num_of_mapfiles_subsystem = 0;
757 
758 // for (const_iterator subsys = begin(); subsys != end(); ++subsys)
759 // {
760 // (*subsys)->PrintDetectorMaps(true);
761 // mapfiles_vector_subsystem = (*subsys)->GetParamFileNameList();
762 // num_of_mapfiles_subsystem = (Int_t) mapfiles_vector_subsystem.size();
763 
764 // for (Int_t i=0; i<num_of_mapfiles_subsystem; i++)
765 // {
766 // return_maps_TList -> AddLast(new TObjString(mapfiles_vector_subsystem[i]));
767 // }
768 
769 // mapfiles_vector_subsystem.clear();
770 // }
771 // return return_maps_TList;
772 // }
773 // else {
774 // return NULL;
775 // }
776 // };
777 
778 
780 {
781  if (not empty()) {
782  for (const_iterator subsys = begin(); subsys != end(); ++subsys)
783  {
784  (*subsys)->PrintDetectorMaps(true);
785  }
786  }
787 }
788 
789 TList* QwSubsystemArray::GetParamFileNameList(TString name) const
790 {
791  if (not empty()) {
792 
793  TList* return_maps_TList = new TList;
794  return_maps_TList->SetName(name);
795 
796  std::map<TString, TString> mapfiles_subsystem;
797 
798  for (const_iterator subsys = begin(); subsys != end(); ++subsys)
799  {
800  mapfiles_subsystem = (*subsys)->GetDetectorMaps();
801  for( std::map<TString, TString>::iterator ii= mapfiles_subsystem.begin(); ii!= mapfiles_subsystem.end(); ++ii)
802  {
803  TList *test = new TList;
804  test->SetName((*ii).first);
805  test->AddLast(new TObjString((*ii).second));
806  return_maps_TList -> AddLast(test);
807  }
808  }
809 
810  return return_maps_TList;
811  }
812  else {
813  return NULL;
814  }
815 };
816 
817 
818 
819 /**
820  * Add the subsystem to this array. Do nothing if the subsystem is null or if
821  * there is already a subsystem with that name in the array.
822  * @param subsys Subsystem to add to the array
823  */
824 void QwSubsystemArray::push_back(boost::shared_ptr<VQwSubsystem> subsys)
825 {
826 
827  if (subsys.get() == NULL) {
828  QwError << "QwSubsystemArray::push_back(): NULL subsys"
829  << QwLog::endl;
830  // This is an empty subsystem...
831  // Do nothing for now.
832 
833  } else if (!this->empty() && GetSubsystemByName(subsys->GetSubsystemName())){
834  // There is already a subsystem with this name!
835  QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetSubsystemName()
836  << " already exists" << QwLog::endl;
837 
838  } else if (!fnCanContain(subsys.get())) {
839  // There is no support for this type of subsystem
840  QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetSubsystemName()
841  << " is not supported by this subsystem array" << QwLog::endl;
842 
843  } else {
844  boost::shared_ptr<VQwSubsystem> subsys_tmp(subsys);
845  SubsysPtrs::push_back(subsys_tmp);
846 
847  // Set the parent of the subsystem to this array
848  subsys_tmp->SetParent(this);
849 
850  // Update the event type mask
851  // Note: Active bits in the mask indicate event types that are accepted
852  fEventTypeMask |= subsys_tmp->GetEventTypeMask();
853 
854  // Instruct the subsystem to publish variables
855  if (subsys_tmp->PublishInternalValues() == kFALSE) {
856  QwError << "Not all variables for " << subsys_tmp->GetSubsystemName()
857  << " could be published!" << QwLog::endl;
858  }
859  }
860 }
861 
862 
863 
864 
865 
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
virtual void ConstructBranch(TTree *tree, TString &prefix)=0
Construct the branch and tree vector.
std::map< TString, const VQwSubsystem * > fPublishedValuesSubsystem
std::map< TString, TString > fPublishedValuesDescription
const VQwHardwareChannel * ReturnInternalValue(const TString &name) const
Retrieve the variable name from subsystems in this subsystem array.
#define QwOut
Predefined log drain for explicit output.
Definition: QwLog.h:35
virtual void FillTreeVector(std::vector< Double_t > &values) const =0
Fill the tree vector.
void ConstructHistograms()
Construct the histograms for this subsystem.
virtual VQwSubsystem * GetSubsystemByName(const TString &name)
Get the subsystem with the specified name.
virtual void ProcessOptions(QwOptions &options)
Process the command line options.
Definition: VQwSubsystem.h:90
An options class.
Definition: QwOptions.h:133
TList * GetParamFileNameList(TString name) const
Get list of parameter files.
QwSubsystemArray()
Private default constructor.
Int_t ProcessEvBuffer(const UInt_t event_type, const UInt_t roc_id, const UInt_t bank_id, UInt_t *buffer, UInt_t num_words)
Process the event buffer for events.
Bool_t PublishInternalValue(const TString name, const TString desc, const VQwSubsystem *subsys, const VQwHardwareChannel *element)
Publish the value name with description from a subsystem in this array.
Bool_t FileHasSectionHeader(const std::string &secname)
void push_back(VQwSubsystem *subsys)
Add the subsystem to this array.
void SetCodaEventNumber(UInt_t evtnum)
Set the internal record of the CODA event number.
UInt_t GetCodaEventType() const
Get the internal record of the CODA event type.
UInt_t fCodaEventNumber
CODA event number as provided by QwEventBuffer.
std::vector< T > GetValueVector(const std::string &key)
Get a list of templated values.
Definition: QwOptions.h:253
Bool_t RequestExternalValue(const TString &name, VQwHardwareChannel *value) const
Retrieve the variable name from other subsystem arrays.
virtual void ProcessEvent_2()
Process the event data again, including data from other subsystems. Not all derived classes will requ...
Definition: VQwSubsystem.h:194
void PrintParamFileList() const
Print list of parameter files.
#define QwVerbose
Predefined log drain for verbose messages.
Definition: QwLog.h:55
virtual Int_t LoadDetectorMaps(QwParameterFile &file)
Parse parameter file to find the map files.
Definition: VQwSubsystem.cc:37
void PrintInfo() const
Print some information about the subsystem.
void EncodeEventData(std::vector< UInt_t > &buffer)
Encode the data in this event.
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition: QwOptions.h:164
QwParameterFile * ReadNextSection(std::string &secname, const bool keep_header=false)
std::map< TString, const VQwHardwareChannel * > fPublishedValuesDataElement
Published values.
T GetValue(const std::string &key)
Get a templated value.
Definition: QwOptions.h:240
void SetDataLoaded(const Bool_t flag)
Set data loaded flag.
std::string fSubsystemsMapFile
Filename of the global detector map.
void ConstructTree()
Construct the tree for this subsystem.
#define QwDebug
Predefined log drain for debugging output.
Definition: QwLog.h:60
A logfile class, based on an identical class in the Hermes analyzer.
UInt_t fCodaEventType
CODA event type as provided by QwEventBuffer.
QwParameterFile * ReadUntilNextSection(const bool add_current_line=false)
virtual void FillHistograms()=0
Fill the histograms for this subsystem.
virtual void DeleteTree()
Delete the tree for this subsystem.
Definition: VQwSubsystem.h:275
void AtEndOfEventLoop()
Perform actions at the end of the event loop.
void ProcessOptionsToplevel(QwOptions &options)
Process configuration options for the subsystem array itself.
void ListPublishedValues() const
List the published values and description in this subsystem array.
void ConstructBranchAndVector(TTree *tree, std::vector< Double_t > &values)
Construct the tree and vector for this subsystem.
void ConstructBranch(TTree *tree, TString &prefix)
Construct a branch for this subsystem with a prefix.
void FillHistograms()
Fill the histograms for this subsystem.
virtual void ProcessEvent()=0
The pure virtual base class of all subsystems.
Definition: VQwSubsystem.h:59
static void DefineOptions(QwOptions &options)
Define configuration options for global array.
Bool_t FileHasVariablePair(const std::string &separatorchars, const std::string &varname, std::string &varvalue)
void AssignValueFrom(const VQwDataElement *valueptr)=0
UInt_t GetCodaEventNumber() const
Get the internal record of the CODA event number.
Int_t ProcessConfigurationBuffer(const UInt_t roc_id, const UInt_t bank_id, UInt_t *buffer, UInt_t num_words)
Process the event buffer for configuration events.
void FillTree()
Fill the tree for this subsystem.
void ShareHistograms(const QwSubsystemArray &source)
Share the histograms with another subsystem.
QwParameterFile * ReadSectionPreamble()
Rewinds to the start and read until it finds next section header.
virtual void ConstructBranchAndVector(TTree *tree, TString &prefix, std::vector< Double_t > &values)=0
Construct the branch and tree vector.
CanContainFn fnCanContain
Function to determine which subsystems we can accept.
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
void ProcessOptionsSubsystems(QwOptions &options)
Process configuration options for all subsystems in the array.
Double_t fCleanParameter[3]
Bool_t HasDataLoaded() const
Get data loaded flag.
void ProcessEvent()
Process the decoded data in this event.
Bool_t PublishByRequest(TString device_name)
Try to publish an internal variable matching the submitted name.
std::vector< std::string > fSubsystemsDisabledByType
List of disabled names.
void LoadSubsystemsFromParameterFile(QwParameterFile &detectors)
virtual void FillTree()
Fill the tree for this subsystem.
Definition: VQwSubsystem.h:273
std::vector< std::string > fSubsystemsDisabledByName
List of disabled types.
void SetCodaEventType(UInt_t evttype)
Set the internal record of the CODA event type.
VQwHardwareChannel * ReturnInternalValueForFriends(const TString &name) const
Retrieve the variable name from subsystems in this subsystem array.
UInt_t fEventTypeMask
Mask of event types.
#define QwWarning
Predefined log drain for warnings.
Definition: QwLog.h:45
virtual std::vector< VQwSubsystem * > GetSubsystemByType(const std::string &type)
Get the list of subsystems of the specified type.
virtual void ExchangeProcessedData()
Request processed data from other subsystems for internal use in the second event processing stage...
Definition: VQwSubsystem.h:189
void DeleteTree()
Delete the tree for this subsystem.
void RandomizeEventData(int helicity=0, double time=0.0)
Randomize the data in this event.
virtual Bool_t PublishInternalValues() const
Publish all variables of the subsystem.
Definition: VQwSubsystem.h:109
#define QwError
Predefined log drain for errors.
Definition: QwLog.h:40
TString GetSubsystemName() const
Definition: VQwSubsystem.h:93
void FillTreeVector(std::vector< Double_t > &values) const
Fill the vector for this subsystem.
virtual void ClearEventData()=0
virtual void AtEndOfEventLoop()
Perform actions at the end of the event loop.
Definition: VQwSubsystem.h:198