JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwSubsystemArray.cc
Go to the documentation of this file.
1/*!
2 * \file QwSubsystemArray.cc
3 * \brief Implementation for array container managing multiple subsystems
4 */
5
6#include "QwSubsystemArray.h"
7
8// System headers
9#include <stdexcept>
10
11// Qweak headers
12#include "VQwHardwareChannel.h"
13#include "QwLog.h"
14#include "QwParameterFile.h"
15#include "QwRootFile.h"
16
17//*****************************************************************
18
19/**
20 * Create a subsystem array based on the configuration option 'detectors'
21 */
23: fEventTypeMask(0x0),fnCanContain(myCanContain)
24{
26 QwParameterFile detectors(fSubsystemsMapFile.c_str());
27 QwMessage << "Loading subsystems from " << fSubsystemsMapFile << "." << QwLog::endl;
29}
30
31/**
32 * Copy constructor by reference
33 * @param source Source subsystem array
34 */
36: std::vector<std::shared_ptr<VQwSubsystem>>(),
37 MQwPublishable(source),
49{
50
51 // Make copies of all subsystems rather than copying just the pointers
52 for (const_iterator subsys = source.begin(); subsys != source.end(); ++subsys) {
53 this->push_back(subsys->get()->Clone());
54 // Instruct the subsystem to publish variables
55 if (this->back()->PublishInternalValues() == kFALSE) {
56 QwError << "Not all variables for " << this->back()->GetName()
57 << " could be published!" << QwLog::endl;
58 }
59 }
60}
61
69
71{
72 if (fResolvedSelf.size() == this->size()) return;
73 // Self layout changed: any peer cache built against the old layout is stale.
74 fResolvedPeer = nullptr;
75 fResolvedPeerSlots.clear();
77 fResolvedSelf.assign(this->size(), nullptr);
78 for (size_t i = 0; i < this->size(); ++i) {
79 if (this->at(i) != nullptr) {
80 fResolvedSelf[i] = this->at(i).get();
81 }
82 }
83}
84
85void QwSubsystemArray::ResolvePairing(const QwSubsystemArray& source, const char* context) const
86{
88 const Bool_t cache_valid =
89 (fResolvedPeer == &source)
90 && (fResolvedPeerSlots.size() == source.size())
91 && (fResolvedPairCompatible.size() == source.size());
92 if (cache_valid) return;
93
94 fResolvedPeer = &source;
95 fResolvedPeerSlots.assign(source.size(), nullptr);
96 fResolvedPairCompatible.assign(source.size(), kFALSE);
97 if (this->size() != source.size()) return;
98
99 for (size_t i = 0; i < source.size(); ++i) {
100 VQwSubsystem* ptr1 = fResolvedSelf[i];
101 VQwSubsystem* ptr2 = source.at(i).get();
102 fResolvedPeerSlots[i] = ptr2;
103 if (ptr1 == nullptr || ptr2 == nullptr) continue;
104
105 if (typeid(*ptr1) == typeid(*ptr2)) {
106 fResolvedPairCompatible[i] = kTRUE;
107 } else {
108 QwError << context << " types do not match at slot " << i << QwLog::endl;
109 QwError << " typeid(*ptr1)=" << typeid(*ptr1).name()
110 << " but typeid(*ptr2)=" << typeid(*ptr2).name()
111 << QwLog::endl;
112 }
113 }
114}
115
116
117/**
118 * Assignment operator
119 * @param source Subsystem array to assign to this array
120 * @return This subsystem array after assignment
121 */
123{
124 this->fCodaEventNumber = source.fCodaEventNumber;
125 this->fCodaEventType = source.fCodaEventType;
126 if (!source.empty()){
127 if (this->size() == source.size()){
128 ResolvePairing(source, "QwSubsystemArray::operator=");
129 for(size_t i=0;i<source.size();i++){
130 if (!fResolvedPairCompatible[i]) continue;
132 }
133 } else {
134 // Array sizes don't match
135 }
136 } else {
137 // The source is empty
138 }
139 return *this;
140}
141
142/**
143 * Fill the subsystem array with the contents of a map file
144 * @param detectors Map file
145 */
147{
148 // This is how this should work
149 std::unique_ptr<QwParameterFile> preamble;
150 preamble = detectors.ReadSectionPreamble();
151 // Process preamble
152 QwVerbose << "Preamble:" << QwLog::endl;
153 QwVerbose << *preamble << QwLog::endl;
154 if (preamble) preamble.reset();
155
156 std::unique_ptr<QwParameterFile> section;
157 std::string section_name;
158 while ((section = detectors.ReadNextSection(section_name))) {
159
160 // Debugging output of configuration section
161 QwVerbose << "[" << section_name << "]" << QwLog::endl;
162 QwVerbose << *section << QwLog::endl;
163
164 // Determine type and name of subsystem
165 std::string subsys_type = section_name;
166 std::string subsys_name;
167 if (! section->FileHasVariablePair("=","name",subsys_name)) {
168 QwError << "No name defined in section for subsystem " << subsys_type << "." << QwLog::endl;
169 continue;
170 }
171
172 // If subsystem type is explicitly disabled
173 bool disabled_by_type = false;
174 for (size_t i = 0; i < fSubsystemsDisabledByType.size(); i++)
175 if (subsys_type == fSubsystemsDisabledByType.at(i))
176 disabled_by_type = true;
177 if (disabled_by_type) {
178 QwWarning << "Subsystem of type " << subsys_type << " disabled." << QwLog::endl;
179 continue;
180 }
181
182 // If subsystem name is explicitly disabled
183 bool disabled_by_name = false;
184 for (size_t i = 0; i < fSubsystemsDisabledByName.size(); i++)
185 if (subsys_name == fSubsystemsDisabledByName.at(i))
186 disabled_by_name = true;
187 if (disabled_by_name) {
188 QwWarning << "Subsystem with name " << subsys_name << " disabled." << QwLog::endl;
189 continue;
190 }
191
192 // Create subsystem
193 QwMessage << "Creating subsystem of type " << subsys_type << " "
194 << "with name " << subsys_name << "." << QwLog::endl;
195 VQwSubsystem* subsys = 0;
196 try {
197 subsys =
198 VQwSubsystemFactory::Create(subsys_type, subsys_name);
199 } catch (QwException_TypeUnknown&) {
200 QwError << "No support for subsystems of type " << subsys_type << "." << QwLog::endl;
201 // Fall-through to next error for more the psychological effect of many warnings
202 }
203 if (! subsys) {
204 QwError << "Could not create subsystem " << subsys_type << "." << QwLog::endl;
205 continue;
206 }
207
208 // If this subsystem cannot be stored in this array
209 if (! fnCanContain(subsys)) {
210 QwMessage << "Subsystem " << subsys_name << " cannot be stored in this "
211 << "subsystem array." << QwLog::endl;
212 QwMessage << "Deleting subsystem " << subsys_name << " again" << QwLog::endl;
213 delete subsys; subsys = 0;
214 continue;
215 }
216
217 // Pass detector maps
218 subsys->LoadDetectorMaps(*section);
219 // Add to array
220 this->push_back(subsys);
221
222 // Instruct the subsystem to publish variables
223 if (subsys->PublishInternalValues() == kFALSE) {
224 QwError << "Not all variables for " << subsys->GetName()
225 << " could be published!" << QwLog::endl;
226 }
227 }
228}
229
230//*****************************************************************
231
232/**
233 * Add the subsystem to this array. Do nothing if the subsystem is null or if
234 * there is already a subsystem with that name in the array.
235 * @param subsys Subsystem to add to the array
236 */
238{
239 if (subsys == NULL) {
240 QwError << "QwSubsystemArray::push_back(): NULL subsys"
241 << QwLog::endl;
242 // This is an empty subsystem...
243 // Do nothing for now.
244
245 } else if (!this->empty() && GetSubsystemByName(subsys->GetName())){
246 // There is already a subsystem with this name!
247 QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetName()
248 << " already exists" << QwLog::endl;
249
250 } else if (!fnCanContain(subsys)) {
251 // There is no support for this type of subsystem
252 QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetName()
253 << " is not supported by this subsystem array" << QwLog::endl;
254
255 } else {
256 std::shared_ptr<VQwSubsystem> subsys_tmp(subsys);
257 SubsysPtrs::push_back(subsys_tmp);
259
260 // Set the parent of the subsystem to this array
261 subsys_tmp->SetParent(this);
262
263 // Update the event type mask
264 // Note: Active bits in the mask indicate event types that are accepted
265 fEventTypeMask |= subsys_tmp->GetEventTypeMask();
266 }
267}
268
269
270
271/**
272 * Define configuration options for global array
273 * @param options Options
274 */
276{
277 options.AddOptions()("detectors",
278 po::value<std::string>()->default_value("detectors.map"),
279 "map file with detectors to include");
280
281 options.AddOptions()("bad-event-list",
282 po::value<std::string>()->default_value(""),
283 "map file with bad event ranges");
284
285 // Versions of boost::program_options below 1.39.0 have a bug in multitoken processing
286 options.AddOptions()("disable-by-type",
287 po::value<std::vector <std::string> >()->multitoken(),
288 "subsystem types to disable");
289 options.AddOptions()("disable-by-name",
290 po::value<std::vector <std::string> >()->multitoken(),
291 "subsystem names to disable");
292}
293
294
295/**
296 * Handle configuration options for the subsystem array itself
297 * @param options Options
298 */
300{
301 // Filename to use for subsystem creation (single filename could be expanded
302 // to a list)
303 fSubsystemsMapFile = options.GetValue<std::string>("detectors");
304 // Subsystems to disable
305 fSubsystemsDisabledByName = options.GetValueVector<std::string>("disable-by-name");
306 fSubsystemsDisabledByType = options.GetValueVector<std::string>("disable-by-type");
307}
308
309
310/**
311 * Handle configuration options for all subsystems in the array
312 * @param options Options
313 */
315{
316 LoadAllEventRanges(options);
317
318 for (iterator subsys_iter = begin(); subsys_iter != end(); ++subsys_iter) {
319 VQwSubsystem* subsys = dynamic_cast<VQwSubsystem*>(subsys_iter->get());
320 subsys->ProcessOptions(options);
321 }
322}
323
325
326 std::string fBadEventListFileName = options.GetValue<std::string>("bad-event-list");
327 if (fBadEventListFileName.size() > 0) {
328 QwParameterFile fBadEventListFile(fBadEventListFileName);
329 // If there is an event list, open the next section
330 std::string bad_event_range;
331 while (fBadEventListFile.ReadNextLine(bad_event_range)){
332 // Find next non-whitespace, non-comment, non-empty line, before EOF
333 fBadEventListFile.TrimWhitespace();
334 fBadEventListFile.TrimComment('#');
335 if (fBadEventListFile.LineIsEmpty()) continue;
336 std::pair<UInt_t,UInt_t> aBadEventRange = QwParameterFile::ParseIntRange(":",bad_event_range);
337 fBadEventRange.push_back(aBadEventRange);
338 QwMessage << "Next Bad event range is " << bad_event_range << QwLog::endl;
339 } // end of loop of reading lines.
340 }
341}
342
343/**
344 * Get the subsystem in this array with the specified name
345 * @param name Name of the subsystem
346 * @return Pointer to the subsystem
347 */
349{
350 VQwSubsystem* tmp = NULL;
351 if (!empty()) {
352 // Loop over the subsystems
353 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
354 // Check the name of this subsystem
355 // std::cout<<"QwSubsystemArray::GetSubsystemByName available name=="<<(*subsys)->GetName()<<"== to be compared to =="<<name<<"==\n";
356 if ((*subsys)->GetName() == name) {
357 tmp = (*subsys).get();
358 //std::cout<<"QwSubsystemArray::GetSubsystemByName found a matching name \n";
359 } else {
360 // nothing
361 }
362 }
363 }
364 return tmp;
365}
366
367
368/**
369 * Get the list of subsystems in this array of the specified type
370 * @param type Type of the subsystem
371 * @return Vector of subsystems
372 */
373std::vector<VQwSubsystem*> QwSubsystemArray::GetSubsystemByType(const std::string& type)
374{
375 // Vector of subsystem pointers
376 std::vector<VQwSubsystem*> subsys_list;
377
378 // If this array is not empty
379 if (!empty()) {
380
381 // Loop over the subsystems
382 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
383
384 // Test to see if the subsystem inherits from the required type
385 if (VQwSubsystemFactory::InheritsFrom((*subsys).get(),type)) {
386 subsys_list.push_back((*subsys).get());
387 }
388
389 } // end of loop over subsystems
390
391 } // end of if !empty()
392
393 return subsys_list;
394}
395
396
398{
399 if (!empty()) {
400 SetDataLoaded(kFALSE);
403 std::for_each(begin(), end(),
404 std::mem_fn(&VQwSubsystem::ClearEventData));
405 }
406}
407
409 const ROCID_t roc_id,
410 const BankID_t bank_id,
411 UInt_t* buffer,
412 UInt_t num_words)
413{
414 if (!empty())
415 for (iterator subsys = begin(); subsys != end(); ++subsys){
416 (*subsys)->ProcessConfigurationBuffer(roc_id, bank_id, buffer, num_words);
417 }
418 return 0;
419}
420
421/// QwSubsystemArray::GetMarkerWordList should be called once by QwEventBuffer
422/// to build the marker word list as each roc_id and bank_id are reached in
423/// the decoding.
425 const ROCID_t roc_id,
426 const BankID_t bank_id,
427 std::vector<UInt_t>& marker) const
428{
429 if (!empty()){
430 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
431 (*subsys)->GetMarkerWordList(roc_id, bank_id, marker);
432 }
433 }
434}
435
436
438 const UInt_t event_type,
439 const ROCID_t roc_id,
440 const BankID_t bank_id,
441 UInt_t* buffer,
442 UInt_t num_words)
443{
444 if (!empty()) {
445 SetDataLoaded(kTRUE);
446 for (iterator subsys = begin(); subsys != end(); ++subsys) {
447 (*subsys)->ProcessEvBuffer(event_type, roc_id, bank_id, buffer, num_words);
448 }
449 }
450 return 0;
451}
452
453
455{
456 if (!empty() && HasDataLoaded()) {
457 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::ProcessEvent));
458 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::ExchangeProcessedData));
459 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::ProcessEvent_2));
460 }
461}
462
464{
465 QwDebug << "QwSubsystemArray at end of event loop" << QwLog::endl;
466 if (!empty()) {
467 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::AtEndOfEventLoop));
468 }
469}
470
471//*****************************************************************
472void QwSubsystemArray::RandomizeEventData(int helicity, double time)
473{
474 if (!empty())
475 for (iterator subsys = begin(); subsys != end(); ++subsys) {
476 (*subsys)->RandomizeEventData(helicity, time);
477 }
478}
479
480//*****************************************************************
481void QwSubsystemArray::EncodeEventData(std::vector<UInt_t> &buffer)
482{
483 if (!empty())
484 for (iterator subsys = begin(); subsys != end(); ++subsys) {
485 (*subsys)->EncodeEventData(buffer);
486 }
487}
488//*****************************************************************
489void QwSubsystemArray::GetROCIDList(std::vector<ROCID_t> &list)
490{
491 if (!empty()){
492 std::vector<ROCID_t> tmp;
493 for (iterator subsys = begin(); subsys != end(); ++subsys) {
494 tmp = (*subsys)->GetROCIds();
495 for(auto it = tmp.begin(); it!=tmp.end();it++){
496 if(std::find(list.begin(), list.end(), *it) == list.end() )
497 list.push_back(*it);
498 }
499 }
500 }
501}
502
503//*****************************************************************
504void QwSubsystemArray::ConstructObjects(TDirectory *folder, TString &prefix)
505{
506 if (!empty()) {
507 for (iterator subsys = begin(); subsys != end(); ++subsys){
508 (*subsys)->ConstructObjects(folder,prefix);
509 }
510 }
511}
512
513//*****************************************************************
514void QwSubsystemArray::ConstructHistograms(TDirectory *folder, TString &prefix)
515{
516 if (!empty()) {
517 for (iterator subsys = begin(); subsys != end(); ++subsys){
518 (*subsys)->ConstructHistograms(folder,prefix);
519 }
520 }
521}
522
524{
525 if (!empty())
526 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::FillHistograms));
527}
528
530{
531 if (!empty() && !source.empty()) {
532 if (this->size() == source.size()) {
533 for (size_t i = 0; i < source.size(); ++i) {
534 this->at(i)->ShareHistograms(source.at(i).get());
535 }
536 }
537 }
538}
539//*****************************************************************
540
541/**
542 * Construct the tree for this subsystem
543 * @param folder Directory where to construct the tree
544 * @param prefix Prefix for the name of the tree
545 */
546void QwSubsystemArray::ConstructTree(TDirectory *folder, TString &prefix)
547{
548 if (!empty()) {
549 for (iterator subsys = begin(); subsys != end(); ++subsys){
550 (*subsys)->ConstructTree(folder, prefix);
551 }
552 }
553}
554
555/**
556 * Fill the tree for this subsystem
557 */
559{
560 if (!empty())
561 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::FillTree));
562}
563
564/**
565 * Delete the tree for this subsystem
566 */
568{
569 if (!empty())
570 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::DeleteTree));
571}
572
573//*****************************************************************
574
576{
577 if (!empty()) {
578 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
579 (*subsys)->PrintInfo();
580 }
581 }
582}
583
584//*****************************************************************
585
586/**
587 * Construct the branch and tree vector
588 * @param tree Tree
589 * @param prefix Prefix
590 * @param values Vector of values
591 */
593 TTree *tree,
594 TString& prefix,
596{
597 fTreeArrayIndex = values.size();
598
599 // Each tree should only contain event number and type once, but will
600 // still reserve space in the values vector, so we don't need to modify
601 // FillTreeVector().
602 values.push_back("CodaEventNumber", 'i');
603 values.push_back("CodaEventType", 'i');
604 if (prefix == "" || prefix.Index("yield_") == 0) {
605 tree->Branch("CodaEventNumber",&(values[fTreeArrayIndex]),"CodaEventNumber/i");
606 tree->Branch("CodaEventType",&(values[fTreeArrayIndex+1]),"CodaEventType/i");
607 }
608 for (iterator subsys = begin(); subsys != end(); ++subsys) {
609 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
610 subsys_ptr->ConstructBranchAndVector(tree, prefix, values);
611 }
612
613}
614
615
616/**
617 * Construct the branch for the flat tree
618 * @param tree Tree
619 * @param prefix Prefix
620 */
621void QwSubsystemArray::ConstructBranch(TTree *tree, TString& prefix)
622{
623 // Only MPS tree should contain event number and type
624 if (prefix == "" || prefix == "yield_") {
625 tree->Branch("CodaEventNumber",&fCodaEventNumber,"CodaEventNumber/i");
626 tree->Branch("CodaEventType",&fCodaEventType,"CodaEventType/i");
627 }
628
629 for (iterator subsys = begin(); subsys != end(); ++subsys) {
630 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
631 subsys_ptr->ConstructBranch(tree, prefix);
632 }
633}
634
635
636/**
637 * Construct the branch for the flat tree with tree trim files accepted
638 * @param tree Tree
639 * @param prefix Prefix
640 * @param trim_file Trim file
641 */
643 TTree *tree,
644 TString& prefix,
645 QwParameterFile& trim_file)
646{
647 QwMessage << " QwSubsystemArray::ConstructBranch " << QwLog::endl;
648
649 std::unique_ptr<QwParameterFile> preamble;
650 std::unique_ptr<QwParameterFile> nextsection;
651 preamble = trim_file.ReadSectionPreamble();
652
653 // Process preamble
654 QwVerbose << "QwSubsystemArrayTracking::ConstructBranch Preamble:" << QwLog::endl;
655 QwVerbose << *preamble << QwLog::endl;
656
657 if (prefix == "" || prefix == "yield_") {
658 tree->Branch("CodaEventNumber",&fCodaEventNumber,"CodaEventNumber/i");
659 tree->Branch("CodaEventType",&fCodaEventType,"CodaEventType/i");
660 }
661
662 for (iterator subsys = begin(); subsys != end(); ++subsys) {
663 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
664
665 TString subsysname = subsys_ptr->GetName();
666 //QwMessage << "Tree leaves created for " << subsysname << QwLog::endl;
667
668 if (trim_file.FileHasSectionHeader(subsysname)) {
669 // This section contains modules and their channels to be included in the tree
670 nextsection = trim_file.ReadUntilNextSection();
671 subsys_ptr->ConstructBranch(tree, prefix, *nextsection);
672 QwMessage << "Tree leaves created for " << subsysname << QwLog::endl;
673 } else
674 QwMessage << "No tree leaves created for " << subsysname << QwLog::endl;
675 }
676}
677
678
679/**
680 * Fill the tree vector
681 * @param values Vector of values
682 */
684{
685 // Fill the event number and event type
686 size_t index = fTreeArrayIndex;
687 values.SetValue(index++, this->GetCodaEventNumber());
688 values.SetValue(index++, this->GetCodaEventType());
689
690 // Fill the subsystem data
691 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
692 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
693 subsys_ptr->FillTreeVector(values);
694 }
695}
696
697#ifdef HAS_RNTUPLE_SUPPORT
698/**
699 * Construct the RNTuple fields and ve
700 * @param prefix Prefix
701 * @param values Vector of values
702 * @param fieldPtrs Vector of shared field pointers
703 */
704void QwSubsystemArray::ConstructNTupleAndVector(
705 std::unique_ptr<ROOT::RNTupleModel>& model,
706 TString& prefix,
707 std::vector<Double_t>& values,
708 std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
709{
710 fTreeArrayIndex = values.size();
711
712 // Debug output for eventsum
713 // Reserve space for event metadata
714 values.push_back(0.0);
715 values.push_back(0.0);
716 values.push_back(0.0);
717 values.push_back(0.0);
718 values.push_back(0.0);
719
720 // Add corresponding field pointers and create fields
721 if (prefix == "" || prefix.Index("yield_") == 0) {
722 auto eventNumField = model->MakeField<Double_t>("CodaEventNumber");
723 auto eventTypeField = model->MakeField<Double_t>("CodaEventType");
724
725 fieldPtrs.push_back(eventNumField);
726 fieldPtrs.push_back(eventTypeField);
727 } else {
728 // Still reserve space but don't create duplicate fields
729 fieldPtrs.push_back(nullptr);
730 fieldPtrs.push_back(nullptr);
731 }
732
733 // Process subsystems
734 for (iterator subsys = begin(); subsys != end(); ++subsys) {
735 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
736 subsys_ptr->ConstructNTupleAndVector(model, prefix, values, fieldPtrs);
737 }
738}
739#endif // HAS_RNTUPLE_SUPPORT
740
741#ifdef HAS_RNTUPLE_SUPPORT
742/**
743 * Fill the RNTuple vector
744 * @param values Vector of values
745 */
746void QwSubsystemArray::FillNTupleVector(std::vector<Double_t>& values) const
747{
748 // Fill the event number and event type (same as TTree)
749 size_t index = fTreeArrayIndex;
750 values[index++] = this->GetCodaEventNumber();
751 values[index++] = this->GetCodaEventType();
752
753 // Fill the subsystem data
754 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
755 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
756 subsys_ptr->FillNTupleVector(values);
757 }
758}
759#endif // HAS_RNTUPLE_SUPPORT
760
761
762
763
764// TList* QwSubsystemArray::GetParamFileNameList(TString name) const
765// {
766// if (not empty()) {
767
768// TList* return_maps_TList = new TList;
769// return_maps_TList->SetOwner(true);
770// return_maps_TList->SetName(name);
771
772// std::vector<TString> mapfiles_vector_subsystem;
773
774// Int_t num_of_mapfiles_subsystem = 0;
775
776// for (const_iterator subsys = begin(); subsys != end(); ++subsys)
777// {
778// (*subsys)->PrintDetectorMaps(true);
779// mapfiles_vector_subsystem = (*subsys)->GetParamFileNameList();
780// num_of_mapfiles_subsystem = (Int_t) mapfiles_vector_subsystem.size();
781
782// for (Int_t i=0; i<num_of_mapfiles_subsystem; i++)
783// {
784// return_maps_TList -> AddLast(new TObjString(mapfiles_vector_subsystem[i]));
785// }
786
787// mapfiles_vector_subsystem.clear();
788// }
789// return return_maps_TList;
790// }
791// else {
792// return NULL;
793// }
794// };
795
796
798{
799 if (not empty()) {
800 for (const_iterator subsys = begin(); subsys != end(); ++subsys)
801 {
802 (*subsys)->PrintDetectorMaps(true);
803 }
804 }
805}
806
808{
809 if (not empty()) {
810
811 TList* return_maps_TList = new TList;
812 return_maps_TList->SetName(name);
813
814 std::map<TString, TString> mapfiles_subsystem;
815
816 for (const_iterator subsys = begin(); subsys != end(); ++subsys)
817 {
818 mapfiles_subsystem = (*subsys)->GetDetectorMaps();
819 for( std::map<TString, TString>::iterator ii= mapfiles_subsystem.begin(); ii!= mapfiles_subsystem.end(); ++ii)
820 {
821 TList *test = new TList;
822 test->SetName((*ii).first);
823 test->AddLast(new TObjString((*ii).second));
824 return_maps_TList -> AddLast(test);
825 }
826 }
827
828 return return_maps_TList;
829 }
830 else {
831 return NULL;
832 }
833};
834
835
836
837/**
838 * Add the subsystem to this array. Do nothing if the subsystem is null or if
839 * there is already a subsystem with that name in the array.
840 * @param subsys Subsystem to add to the array
841 */
842void QwSubsystemArray::push_back(std::shared_ptr<VQwSubsystem> subsys)
843{
844
845 if (subsys.get() == NULL) {
846 QwError << "QwSubsystemArray::push_back(): NULL subsys"
847 << QwLog::endl;
848 // This is an empty subsystem...
849 // Do nothing for now.
850
851 } else if (!this->empty() && GetSubsystemByName(subsys->GetName())){
852 // There is already a subsystem with this name!
853 QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetName()
854 << " already exists" << QwLog::endl;
855
856 } else if (!fnCanContain(subsys.get())) {
857 // There is no support for this type of subsystem
858 QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetName()
859 << " is not supported by this subsystem array" << QwLog::endl;
860
861 } else {
862 std::shared_ptr<VQwSubsystem> subsys_tmp(subsys);
863 SubsysPtrs::push_back(subsys_tmp);
865
866 // Set the parent of the subsystem to this array
867 subsys_tmp->SetParent(this);
868
869 // Update the event type mask
870 // Note: Active bits in the mask indicate event types that are accepted
871 fEventTypeMask |= subsys_tmp->GetEventTypeMask();
872
873 // Instruct the subsystem to publish variables
874 if (subsys_tmp->PublishInternalValues() == kFALSE) {
875 QwError << "Not all variables for " << subsys_tmp->GetName()
876 << " could be published!" << QwLog::endl;
877 }
878 }
879}
A logfile class, based on an identical class in the Hermes analyzer.
#define QwVerbose
Predefined log drain for verbose messages.
Definition QwLog.h:54
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
#define QwDebug
Predefined log drain for debugging output.
Definition QwLog.h:59
ROOT file and tree management wrapper classes.
Array container for managing multiple subsystems.
ULong64_t BankID_t
Definition QwTypes.h:21
UInt_t ROCID_t
Definition QwTypes.h:20
Parameter file parsing and management.
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Command-line and configuration file options processor.
Definition QwOptions.h:141
std::vector< T > GetValueVector(const std::string &key)
Get a list of templated values.
Definition QwOptions.h:249
T GetValue(const std::string &key)
Get a templated value.
Definition QwOptions.h:236
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:170
Configuration file parser with flexible tokenization and search capabilities.
Bool_t FileHasSectionHeader(const std::string &secname)
void TrimWhitespace(TString::EStripType head_tail=TString::kBoth)
static std::pair< int, int > ParseIntRange(const std::string &separatorchars, const std::string &range)
Parse a range of integers as #:# where either can be missing.
void TrimComment(const char commentchar)
std::unique_ptr< QwParameterFile > ReadUntilNextSection(const bool add_current_line=false)
std::unique_ptr< QwParameterFile > ReadSectionPreamble()
Rewinds to the start and read until it finds next section header.
std::unique_ptr< QwParameterFile > ReadNextSection(std::string &secname, const bool keep_header=false)
A helper class to manage a vector of branch entries for ROOT trees.
Definition QwRootFile.h:55
size_type size() const noexcept
Definition QwRootFile.h:83
void push_back(const std::string &name, const char type='D')
Definition QwRootFile.h:197
void SetValue(size_type index, Double_t val)
Definition QwRootFile.h:110
std::vector< Bool_t > fResolvedPairCompatible
void BuildResolvedSelf() const
void SetDataLoaded(const Bool_t flag)
Set data loaded flag.
QwSubsystemArray & operator=(const QwSubsystemArray &value)
Assignment operator.
virtual std::vector< VQwSubsystem * > GetSubsystemByType(const std::string &type)
Get the list of subsystems of the specified type.
void ConstructHistograms()
Construct the histograms for this subsystem.
void GetMarkerWordList(const ROCID_t roc_id, const BankID_t bank_id, std::vector< UInt_t > &marker) const
void push_back(VQwSubsystem *subsys)
Add the subsystem to this array.
void EncodeEventData(std::vector< UInt_t > &buffer)
Encode the data in this event.
UInt_t fCodaEventType
CODA event type as provided by QwEventBuffer.
void ConstructObjects()
Construct the objects for this subsystem.
void ProcessEvent()
Process the decoded data in this event.
UInt_t GetCodaEventNumber() const
Get the internal record of the CODA event number.
std::vector< std::string > fSubsystemsDisabledByName
List of disabled types.
const QwSubsystemArray * fResolvedPeer
virtual VQwSubsystem * GetSubsystemByName(const TString &name)
Get the subsystem with the specified name.
QwSubsystemArray()
Private default constructor.
void LoadAllEventRanges(QwOptions &options)
void PrintParamFileList() const
Print list of parameter files.
void ConstructBranchAndVector(TTree *tree, QwRootTreeBranchVector &values)
Construct the tree and vector for this subsystem.
TList * GetParamFileNameList(TString name) const
Get list of parameter files.
CanContainFn fnCanContain
Function to determine which subsystems we can accept.
void PrintInfo() const
Print some information about the subsystem.
Bool_t(* CanContainFn)(VQwSubsystem *)
UInt_t GetCodaEventType() const
Get the internal record of the CODA event type.
static void DefineOptions(QwOptions &options)
Define configuration options for global array.
void ConstructTree()
Construct the tree for this subsystem.
UInt_t fCodaRunNumber
Index of this data element in root tree.
Int_t ProcessEvBuffer(const UInt_t event_type, const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words)
Process the event buffer for events.
void ShareHistograms(const QwSubsystemArray &source)
Share the histograms with another subsystem.
std::vector< VQwSubsystem * > fResolvedSelf
std::string fSubsystemsMapFile
Filename of the global detector map.
std::vector< VQwSubsystem * > fResolvedPeerSlots
void SetCodaEventNumber(UInt_t evtnum)
Set the internal record of the CODA event number.
void FillTree()
Fill the tree for this subsystem.
void RandomizeEventData(int helicity=0, double time=0.0)
Randomize the data in this event.
UInt_t fCodaSegmentNumber
CODA segment number as provided by QwEventBuffer.
std::vector< std::string > fSubsystemsDisabledByType
List of disabled names.
void ConstructBranch(TTree *tree, TString &prefix)
Construct a branch for this subsystem with a prefix.
std::vector< std::pair< UInt_t, UInt_t > > fBadEventRange
void ProcessOptionsToplevel(QwOptions &options)
Process configuration options for the subsystem array itself.
void ResolvePairing(const QwSubsystemArray &source, const char *context) const
UInt_t fEventTypeMask
Mask of event types.
Bool_t fHasDataLoaded
Has this array gotten data to be processed?
void LoadSubsystemsFromParameterFile(QwParameterFile &detectors)
void SetCodaEventType(UInt_t evttype)
Set the internal record of the CODA event type.
void AtEndOfEventLoop()
Perform actions at the end of the event loop.
void ProcessOptionsSubsystems(QwOptions &options)
Process configuration options for all subsystems in the array.
void FillTreeVector(QwRootTreeBranchVector &values) const
Fill the vector for this subsystem.
Bool_t HasDataLoaded() const
Get data loaded flag.
UInt_t fCodaEventNumber
CODA event number as provided by QwEventBuffer.
Int_t ProcessConfigurationBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words)
Process the event buffer for configuration events.
void GetROCIDList(std::vector< ROCID_t > &list)
Get the ROCID list.
void FillHistograms()
Fill the histograms for this subsystem.
void DeleteTree()
Delete the tree for this subsystem.
void InvalidateResolvedDispatchCache()
Base class for subsystems implementing container-delegation pattern.
virtual void AtEndOfEventLoop()
Perform actions at the end of the event loop.
virtual void DeleteTree()
Delete the tree for this subsystem.
Bool_t PublishInternalValues() const override
Publish all variables of the subsystem.
virtual void ProcessOptions(QwOptions &)
Process the command line options.
virtual void FillTree()
Fill the tree for this subsystem.
virtual void FillHistograms()=0
Fill the histograms for this subsystem.
virtual void ExchangeProcessedData()
Request processed data from other subsystems for internal use in the second event processing stage....
virtual void FillTreeVector(QwRootTreeBranchVector &values) const =0
Fill the tree vector.
virtual void ClearEventData()=0
virtual Int_t LoadDetectorMaps(QwParameterFile &file)
Parse parameter file to find the map files.
virtual void ProcessEvent_2()
Process the event data again, including data from other subsystems. Not all derived classes will requ...
TString GetName() const
virtual void ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values)=0
Construct the branch and tree vector.
virtual void ConstructBranch(TTree *tree, TString &prefix)=0
Construct the branch and tree vector.
virtual void ProcessEvent()=0