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: fCleanParameter{0,0,0},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 for (size_t i = 0; i < 3; i++)
51 fCleanParameter[i] = source.fCleanParameter[i];
52
53 // Make copies of all subsystems rather than copying just the pointers
54 for (const_iterator subsys = source.begin(); subsys != source.end(); ++subsys) {
55 this->push_back(subsys->get()->Clone());
56 // Instruct the subsystem to publish variables
57 if (this->back()->PublishInternalValues() == kFALSE) {
58 QwError << "Not all variables for " << this->back()->GetName()
59 << " could be published!" << QwLog::endl;
60 }
61 }
62}
63
64
65/**
66 * Assignment operator
67 * @param source Subsystem array to assign to this array
68 * @return This subsystem array after assignment
69 */
71{
73 this->fCodaEventType = source.fCodaEventType;
74 if (!source.empty()){
75 if (this->size() == source.size()){
76 for(size_t i=0;i<source.size();i++){
77 if (source.at(i)==NULL || this->at(i)==NULL){
78 // Either the source or the destination subsystem
79 // are null
80 } else {
81 VQwSubsystem *ptr1 =
82 dynamic_cast<VQwSubsystem*>(this->at(i).get());
83 VQwSubsystem *ptr2 = source.at(i).get();
84 if (typeid(*ptr1)==typeid(*(ptr2))){
85 *(ptr1) = source.at(i).get();
86 } else {
87 // Subsystems don't match
88 QwError << " QwSubsystemArray::operator= types do not mach" << QwLog::endl;
89 QwError << " typeid(*ptr1)=" << typeid(*ptr1).name()
90 << " but typeid(*ptr2)=" << typeid(*ptr2).name()
91 << QwLog::endl;
92 }
93 }
94 }
95 } else {
96 // Array sizes don't match
97 }
98 } else {
99 // The source is empty
100 }
101 return *this;
102}
103
104/**
105 * Fill the subsystem array with the contents of a map file
106 * @param detectors Map file
107 */
109{
110 // This is how this should work
111 std::unique_ptr<QwParameterFile> preamble;
112 preamble = detectors.ReadSectionPreamble();
113 // Process preamble
114 QwVerbose << "Preamble:" << QwLog::endl;
115 QwVerbose << *preamble << QwLog::endl;
116 if (preamble) preamble.reset();
117
118 std::unique_ptr<QwParameterFile> section;
119 std::string section_name;
120 while ((section = detectors.ReadNextSection(section_name))) {
121
122 // Debugging output of configuration section
123 QwVerbose << "[" << section_name << "]" << QwLog::endl;
124 QwVerbose << *section << QwLog::endl;
125
126 // Determine type and name of subsystem
127 std::string subsys_type = section_name;
128 std::string subsys_name;
129 if (! section->FileHasVariablePair("=","name",subsys_name)) {
130 QwError << "No name defined in section for subsystem " << subsys_type << "." << QwLog::endl;
131 continue;
132 }
133
134 // If subsystem type is explicitly disabled
135 bool disabled_by_type = false;
136 for (size_t i = 0; i < fSubsystemsDisabledByType.size(); i++)
137 if (subsys_type == fSubsystemsDisabledByType.at(i))
138 disabled_by_type = true;
139 if (disabled_by_type) {
140 QwWarning << "Subsystem of type " << subsys_type << " disabled." << QwLog::endl;
141 continue;
142 }
143
144 // If subsystem name is explicitly disabled
145 bool disabled_by_name = false;
146 for (size_t i = 0; i < fSubsystemsDisabledByName.size(); i++)
147 if (subsys_name == fSubsystemsDisabledByName.at(i))
148 disabled_by_name = true;
149 if (disabled_by_name) {
150 QwWarning << "Subsystem with name " << subsys_name << " disabled." << QwLog::endl;
151 continue;
152 }
153
154 // Create subsystem
155 QwMessage << "Creating subsystem of type " << subsys_type << " "
156 << "with name " << subsys_name << "." << QwLog::endl;
157 VQwSubsystem* subsys = 0;
158 try {
159 subsys =
160 VQwSubsystemFactory::Create(subsys_type, subsys_name);
161 } catch (QwException_TypeUnknown&) {
162 QwError << "No support for subsystems of type " << subsys_type << "." << QwLog::endl;
163 // Fall-through to next error for more the psychological effect of many warnings
164 }
165 if (! subsys) {
166 QwError << "Could not create subsystem " << subsys_type << "." << QwLog::endl;
167 continue;
168 }
169
170 // If this subsystem cannot be stored in this array
171 if (! fnCanContain(subsys)) {
172 QwMessage << "Subsystem " << subsys_name << " cannot be stored in this "
173 << "subsystem array." << QwLog::endl;
174 QwMessage << "Deleting subsystem " << subsys_name << " again" << QwLog::endl;
175 delete subsys; subsys = 0;
176 continue;
177 }
178
179 // Pass detector maps
180 subsys->LoadDetectorMaps(*section);
181 // Add to array
182 this->push_back(subsys);
183
184 // Instruct the subsystem to publish variables
185 if (subsys->PublishInternalValues() == kFALSE) {
186 QwError << "Not all variables for " << subsys->GetName()
187 << " could be published!" << QwLog::endl;
188 }
189 }
190}
191
192//*****************************************************************
193
194/**
195 * Add the subsystem to this array. Do nothing if the subsystem is null or if
196 * there is already a subsystem with that name in the array.
197 * @param subsys Subsystem to add to the array
198 */
200{
201 if (subsys == NULL) {
202 QwError << "QwSubsystemArray::push_back(): NULL subsys"
203 << QwLog::endl;
204 // This is an empty subsystem...
205 // Do nothing for now.
206
207 } else if (!this->empty() && GetSubsystemByName(subsys->GetName())){
208 // There is already a subsystem with this name!
209 QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetName()
210 << " already exists" << QwLog::endl;
211
212 } else if (!fnCanContain(subsys)) {
213 // There is no support for this type of subsystem
214 QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetName()
215 << " is not supported by this subsystem array" << QwLog::endl;
216
217 } else {
218 std::shared_ptr<VQwSubsystem> subsys_tmp(subsys);
219 SubsysPtrs::push_back(subsys_tmp);
220
221 // Set the parent of the subsystem to this array
222 subsys_tmp->SetParent(this);
223
224 // Update the event type mask
225 // Note: Active bits in the mask indicate event types that are accepted
226 fEventTypeMask |= subsys_tmp->GetEventTypeMask();
227 }
228}
229
230
231
232/**
233 * Define configuration options for global array
234 * @param options Options
235 */
237{
238 options.AddOptions()("detectors",
239 po::value<std::string>()->default_value("detectors.map"),
240 "map file with detectors to include");
241
242 options.AddOptions()("bad-event-list",
243 po::value<std::string>()->default_value(""),
244 "map file with bad event ranges");
245
246 // Versions of boost::program_options below 1.39.0 have a bug in multitoken processing
247 options.AddOptions()("disable-by-type",
248 po::value<std::vector <std::string> >()->multitoken(),
249 "subsystem types to disable");
250 options.AddOptions()("disable-by-name",
251 po::value<std::vector <std::string> >()->multitoken(),
252 "subsystem names to disable");
253}
254
255
256/**
257 * Handle configuration options for the subsystem array itself
258 * @param options Options
259 */
261{
262 // Filename to use for subsystem creation (single filename could be expanded
263 // to a list)
264 fSubsystemsMapFile = options.GetValue<std::string>("detectors");
265 // Subsystems to disable
266 fSubsystemsDisabledByName = options.GetValueVector<std::string>("disable-by-name");
267 fSubsystemsDisabledByType = options.GetValueVector<std::string>("disable-by-type");
268}
269
270
271/**
272 * Handle configuration options for all subsystems in the array
273 * @param options Options
274 */
276{
277 LoadAllEventRanges(options);
278
279 for (iterator subsys_iter = begin(); subsys_iter != end(); ++subsys_iter) {
280 VQwSubsystem* subsys = dynamic_cast<VQwSubsystem*>(subsys_iter->get());
281 subsys->ProcessOptions(options);
282 }
283}
284
286
287 std::string fBadEventListFileName = options.GetValue<std::string>("bad-event-list");
288 if (fBadEventListFileName.size() > 0) {
289 QwParameterFile fBadEventListFile(fBadEventListFileName);
290 // If there is an event list, open the next section
291 std::string bad_event_range;
292 while (fBadEventListFile.ReadNextLine(bad_event_range)){
293 // Find next non-whitespace, non-comment, non-empty line, before EOF
294 fBadEventListFile.TrimWhitespace();
295 fBadEventListFile.TrimComment('#');
296 if (fBadEventListFile.LineIsEmpty()) continue;
297 std::pair<UInt_t,UInt_t> aBadEventRange = QwParameterFile::ParseIntRange(":",bad_event_range);
298 fBadEventRange.push_back(aBadEventRange);
299 QwMessage << "Next Bad event range is " << bad_event_range << QwLog::endl;
300 } // end of loop of reading lines.
301 }
302}
303
304/**
305 * Get the subsystem in this array with the specified name
306 * @param name Name of the subsystem
307 * @return Pointer to the subsystem
308 */
310{
311 VQwSubsystem* tmp = NULL;
312 if (!empty()) {
313 // Loop over the subsystems
314 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
315 // Check the name of this subsystem
316 // std::cout<<"QwSubsystemArray::GetSubsystemByName available name=="<<(*subsys)->GetName()<<"== to be compared to =="<<name<<"==\n";
317 if ((*subsys)->GetName() == name) {
318 tmp = (*subsys).get();
319 //std::cout<<"QwSubsystemArray::GetSubsystemByName found a matching name \n";
320 } else {
321 // nothing
322 }
323 }
324 }
325 return tmp;
326}
327
328
329/**
330 * Get the list of subsystems in this array of the specified type
331 * @param type Type of the subsystem
332 * @return Vector of subsystems
333 */
334std::vector<VQwSubsystem*> QwSubsystemArray::GetSubsystemByType(const std::string& type)
335{
336 // Vector of subsystem pointers
337 std::vector<VQwSubsystem*> subsys_list;
338
339 // If this array is not empty
340 if (!empty()) {
341
342 // Loop over the subsystems
343 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
344
345 // Test to see if the subsystem inherits from the required type
346 if (VQwSubsystemFactory::InheritsFrom((*subsys).get(),type)) {
347 subsys_list.push_back((*subsys).get());
348 }
349
350 } // end of loop over subsystems
351
352 } // end of if !empty()
353
354 return subsys_list;
355}
356
357
359{
360 if (!empty()) {
361 SetDataLoaded(kFALSE);
364 std::for_each(begin(), end(),
365 std::mem_fn(&VQwSubsystem::ClearEventData));
366 }
367}
368
370 const ROCID_t roc_id,
371 const BankID_t bank_id,
372 UInt_t* buffer,
373 UInt_t num_words)
374{
375 if (!empty())
376 for (iterator subsys = begin(); subsys != end(); ++subsys){
377 (*subsys)->ProcessConfigurationBuffer(roc_id, bank_id, buffer, num_words);
378 }
379 return 0;
380}
381
382/// QwSubsystemArray::GetMarkerWordList should be called once by QwEventBuffer
383/// to build the marker word list as each roc_id and bank_id are reached in
384/// the decoding.
386 const ROCID_t roc_id,
387 const BankID_t bank_id,
388 std::vector<UInt_t>& marker) const
389{
390 if (!empty()){
391 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
392 (*subsys)->GetMarkerWordList(roc_id, bank_id, marker);
393 }
394 }
395}
396
397
399 const UInt_t event_type,
400 const ROCID_t roc_id,
401 const BankID_t bank_id,
402 UInt_t* buffer,
403 UInt_t num_words)
404{
405 if (!empty()) {
406 SetDataLoaded(kTRUE);
407 for (iterator subsys = begin(); subsys != end(); ++subsys) {
408 (*subsys)->ProcessEvBuffer(event_type, roc_id, bank_id, buffer, num_words);
409 }
410 }
411 return 0;
412}
413
414
416{
417 if (!empty() && HasDataLoaded()) {
418 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::ProcessEvent));
419 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::ExchangeProcessedData));
420 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::ProcessEvent_2));
421 }
422}
423
425{
426 QwDebug << "QwSubsystemArray at end of event loop" << QwLog::endl;
427 if (!empty()) {
428 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::AtEndOfEventLoop));
429 }
430}
431
432//*****************************************************************
433void QwSubsystemArray::RandomizeEventData(int helicity, double time)
434{
435 if (!empty())
436 for (iterator subsys = begin(); subsys != end(); ++subsys) {
437 (*subsys)->RandomizeEventData(helicity, time);
438 }
439}
440
441//*****************************************************************
442void QwSubsystemArray::EncodeEventData(std::vector<UInt_t> &buffer)
443{
444 if (!empty())
445 for (iterator subsys = begin(); subsys != end(); ++subsys) {
446 (*subsys)->EncodeEventData(buffer);
447 }
448}
449//*****************************************************************
450void QwSubsystemArray::GetROCIDList(std::vector<ROCID_t> &list)
451{
452 if (!empty()){
453 std::vector<ROCID_t> tmp;
454 for (iterator subsys = begin(); subsys != end(); ++subsys) {
455 tmp = (*subsys)->GetROCIds();
456 for(auto it = tmp.begin(); it!=tmp.end();it++){
457 if(std::find(list.begin(), list.end(), *it) == list.end() )
458 list.push_back(*it);
459 }
460 }
461 }
462}
463
464//*****************************************************************
465void QwSubsystemArray::ConstructObjects(TDirectory *folder, TString &prefix)
466{
467 if (!empty()) {
468 for (iterator subsys = begin(); subsys != end(); ++subsys){
469 (*subsys)->ConstructObjects(folder,prefix);
470 }
471 }
472}
473
474//*****************************************************************
475void QwSubsystemArray::ConstructHistograms(TDirectory *folder, TString &prefix)
476{
477 if (!empty()) {
478 for (iterator subsys = begin(); subsys != end(); ++subsys){
479 (*subsys)->ConstructHistograms(folder,prefix);
480 }
481 }
482}
483
485{
486 if (!empty())
487 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::FillHistograms));
488}
489
491{
492 if (!empty() && !source.empty()) {
493 if (this->size() == source.size()) {
494 for (size_t i = 0; i < source.size(); ++i) {
495 this->at(i)->ShareHistograms(source.at(i).get());
496 }
497 }
498 }
499}
500//*****************************************************************
501
502/**
503 * Construct the tree for this subsystem
504 * @param folder Directory where to construct the tree
505 * @param prefix Prefix for the name of the tree
506 */
507void QwSubsystemArray::ConstructTree(TDirectory *folder, TString &prefix)
508{
509 if (!empty()) {
510 for (iterator subsys = begin(); subsys != end(); ++subsys){
511 (*subsys)->ConstructTree(folder, prefix);
512 }
513 }
514}
515
516/**
517 * Fill the tree for this subsystem
518 */
520{
521 if (!empty())
522 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::FillTree));
523}
524
525/**
526 * Delete the tree for this subsystem
527 */
529{
530 if (!empty())
531 std::for_each(begin(), end(), boost::mem_fn(&VQwSubsystem::DeleteTree));
532}
533
534//*****************************************************************
535
537{
538 if (!empty()) {
539 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
540 (*subsys)->PrintInfo();
541 }
542 }
543}
544
545//*****************************************************************
546
547/**
548 * Construct the branch and tree vector
549 * @param tree Tree
550 * @param prefix Prefix
551 * @param values Vector of values
552 */
554 TTree *tree,
555 TString& prefix,
557{
558 fTreeArrayIndex = values.size();
559
560 // Each tree should only contain event number and type once, but will
561 // still reserve space in the values vector, so we don't need to modify
562 // FillTreeVector().
563 values.push_back("CodaEventNumber", 'i');
564 values.push_back("CodaEventType", 'i');
565 values.push_back("Coda_CleanData", 'D');
566 values.push_back("Coda_ScanData1", 'D');
567 values.push_back("Coda_ScanData2", 'D');
568 if (prefix == "" || prefix.Index("yield_") == 0) {
569 tree->Branch("CodaEventNumber",&(values[fTreeArrayIndex]),"CodaEventNumber/i");
570 tree->Branch("CodaEventType",&(values[fTreeArrayIndex+1]),"CodaEventType/i");
571 tree->Branch("Coda_CleanData",&(values[fTreeArrayIndex+2]),"Coda_CleanData/D");
572 tree->Branch("Coda_ScanData1",&(values[fTreeArrayIndex+3]),"Coda_ScanData1/D");
573 tree->Branch("Coda_ScanData2",&(values[fTreeArrayIndex+4]),"Coda_ScanData2/D");
574 }
575 for (iterator subsys = begin(); subsys != end(); ++subsys) {
576 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
577 subsys_ptr->ConstructBranchAndVector(tree, prefix, values);
578 }
579
580}
581
582
583/**
584 * Construct the branch for the flat tree
585 * @param tree Tree
586 * @param prefix Prefix
587 */
588void QwSubsystemArray::ConstructBranch(TTree *tree, TString& prefix)
589{
590 // Only MPS tree should contain event number and type
591 if (prefix == "" || prefix == "yield_") {
592 tree->Branch("CodaEventNumber",&fCodaEventNumber,"CodaEventNumber/i");
593 tree->Branch("CodaEventType",&fCodaEventType,"CodaEventType/i");
594 }
595
596 for (iterator subsys = begin(); subsys != end(); ++subsys) {
597 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
598 subsys_ptr->ConstructBranch(tree, prefix);
599 }
600}
601
602
603/**
604 * Construct the branch for the flat tree with tree trim files accepted
605 * @param tree Tree
606 * @param prefix Prefix
607 * @param trim_file Trim file
608 */
610 TTree *tree,
611 TString& prefix,
612 QwParameterFile& trim_file)
613{
614 QwMessage << " QwSubsystemArray::ConstructBranch " << QwLog::endl;
615
616 std::unique_ptr<QwParameterFile> preamble;
617 std::unique_ptr<QwParameterFile> nextsection;
618 preamble = trim_file.ReadSectionPreamble();
619
620 // Process preamble
621 QwVerbose << "QwSubsystemArrayTracking::ConstructBranch Preamble:" << QwLog::endl;
622 QwVerbose << *preamble << QwLog::endl;
623
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
632 TString subsysname = subsys_ptr->GetName();
633 //QwMessage << "Tree leaves created for " << subsysname << QwLog::endl;
634
635 if (trim_file.FileHasSectionHeader(subsysname)) {
636 // This section contains modules and their channels to be included in the tree
637 nextsection = trim_file.ReadUntilNextSection();
638 subsys_ptr->ConstructBranch(tree, prefix, *nextsection);
639 QwMessage << "Tree leaves created for " << subsysname << QwLog::endl;
640 } else
641 QwMessage << "No tree leaves created for " << subsysname << QwLog::endl;
642 }
643}
644
645
646/**
647 * Fill the tree vector
648 * @param values Vector of values
649 */
651{
652 // Fill the event number and event type
653 size_t index = fTreeArrayIndex;
654 values.SetValue(index++, this->GetCodaEventNumber());
655 values.SetValue(index++, this->GetCodaEventType());
656 values.SetValue(index++, this->fCleanParameter[0]);
657 values.SetValue(index++, this->fCleanParameter[1]);
658 values.SetValue(index++, this->fCleanParameter[2]);
659
660 // Fill the subsystem data
661 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
662 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
663 subsys_ptr->FillTreeVector(values);
664 }
665}
666
667#ifdef HAS_RNTUPLE_SUPPORT
668/**
669 * Construct the RNTuple fields and ve
670 * @param prefix Prefix
671 * @param values Vector of values
672 * @param fieldPtrs Vector of shared field pointers
673 */
674void QwSubsystemArray::ConstructNTupleAndVector(
675 std::unique_ptr<ROOT::RNTupleModel>& model,
676 TString& prefix,
677 std::vector<Double_t>& values,
678 std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
679{
680 fTreeArrayIndex = values.size();
681
682 // Debug output for eventsum
683 // Reserve space for event metadata
684 values.push_back(0.0);
685 values.push_back(0.0);
686 values.push_back(0.0);
687 values.push_back(0.0);
688 values.push_back(0.0);
689
690 // Add corresponding field pointers and create fields
691 if (prefix == "" || prefix.Index("yield_") == 0) {
692 auto eventNumField = model->MakeField<Double_t>("CodaEventNumber");
693 auto eventTypeField = model->MakeField<Double_t>("CodaEventType");
694 auto cleanDataField = model->MakeField<Double_t>("Coda_CleanData");
695 auto scanData1Field = model->MakeField<Double_t>("Coda_ScanData1");
696 auto scanData2Field = model->MakeField<Double_t>("Coda_ScanData2");
697
698 fieldPtrs.push_back(eventNumField);
699 fieldPtrs.push_back(eventTypeField);
700 fieldPtrs.push_back(cleanDataField);
701 fieldPtrs.push_back(scanData1Field);
702 fieldPtrs.push_back(scanData2Field);
703 } else {
704 // Still reserve space but don't create duplicate fields
705 fieldPtrs.push_back(nullptr);
706 fieldPtrs.push_back(nullptr);
707 fieldPtrs.push_back(nullptr);
708 fieldPtrs.push_back(nullptr);
709 fieldPtrs.push_back(nullptr);
710 }
711
712 // Process subsystems
713 for (iterator subsys = begin(); subsys != end(); ++subsys) {
714 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
715 subsys_ptr->ConstructNTupleAndVector(model, prefix, values, fieldPtrs);
716 }
717}
718#endif // HAS_RNTUPLE_SUPPORT
719
720#ifdef HAS_RNTUPLE_SUPPORT
721/**
722 * Fill the RNTuple vector
723 * @param values Vector of values
724 */
725void QwSubsystemArray::FillNTupleVector(std::vector<Double_t>& values) const
726{
727 // Fill the event number and event type (same as TTree)
728 size_t index = fTreeArrayIndex;
729 values[index++] = this->GetCodaEventNumber();
730 values[index++] = this->GetCodaEventType();
731 values[index++] = this->fCleanParameter[0];
732 values[index++] = this->fCleanParameter[1];
733 values[index++] = this->fCleanParameter[2];
734
735 // Fill the subsystem data
736 for (const_iterator subsys = begin(); subsys != end(); ++subsys) {
737 VQwSubsystem* subsys_ptr = dynamic_cast<VQwSubsystem*>(subsys->get());
738 subsys_ptr->FillNTupleVector(values);
739 }
740}
741#endif // HAS_RNTUPLE_SUPPORT
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
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 */
824void QwSubsystemArray::push_back(std::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->GetName())){
834 // There is already a subsystem with this name!
835 QwError << "QwSubsystemArray::push_back(): subsys " << subsys->GetName()
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->GetName()
841 << " is not supported by this subsystem array" << QwLog::endl;
842
843 } else {
844 std::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->GetName()
857 << " could be published!" << QwLog::endl;
858 }
859 }
860}
861
862
863
864
865
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
Array container for managing multiple subsystems.
ROOT file and tree management wrapper classes.
Parameter file parsing and management.
ULong64_t BankID_t
Definition QwTypes.h:21
UInt_t ROCID_t
Definition QwTypes.h:20
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:53
size_type size() const noexcept
Definition QwRootFile.h:81
void push_back(const std::string &name, const char type='D')
Definition QwRootFile.h:195
void SetValue(size_type index, Double_t val)
Definition QwRootFile.h:108
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.
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.
Double_t fCleanParameter[3]
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::string fSubsystemsMapFile
Filename of the global detector map.
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.
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.
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