JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwParity.cc
Go to the documentation of this file.
1/*------------------------------------------------------------------------*//*!
2
3 \file QwParity.cc
4
5 \brief main(...) function for the qwparity executable
6
7*//*-------------------------------------------------------------------------*/
8
9// System headers
10#include <iostream>
11#include <fstream>
12#include <vector>
13#include <new>
14
15// ROOT headers
16#include "Rtypes.h"
17#include "TROOT.h"
18#include "TFile.h"
19#ifdef HAS_RNTUPLE_SUPPORT
20#include "ROOT/RNTuple.hxx"
21#include "ROOT/RNTupleModel.hxx"
22#include "ROOT/RField.hxx"
23#endif
24
25// Qweak headers
26#include "QwLog.h"
27#include "QwRootFile.h"
28#include "QwOptionsParity.h"
29#include "QwEventBuffer.h"
30#ifdef __USE_DATABASE__
31#include "QwParityDB.h"
32#endif //__USE_DATABASE__
33#include "QwHistogramHelper.h"
35#include "QwHelicityPattern.h"
36#include "QwEventRing.h"
37#include "QwEPICSEvent.h"
38#include "QwCombiner.h"
39#include "QwCombinerSubsystem.h"
40#include "QwPromptSummary.h"
41#include "QwCorrelator.h"
42#include "QwCorrelatorNew.h"
43#include "GrandCorrelator.h"
44#include "LRBCorrector.h"
45#include "QwExtractor.h"
46#include "QwDataHandlerArray.h"
47
48// Qweak subsystems
49// (for correct dependency generation)
50#include "QwHelicity.h"
51#include "QwFakeHelicity.h"
52#include "QwBeamLine.h"
53#include "QwBeamMod.h"
54
55// Valgrind headers
56#if __has_include(<valgrind/callgrind.h>)
57#include <valgrind/callgrind.h>
58#endif
59
60Int_t main(Int_t argc, Char_t* argv[])
61{
62 /// Enable implicit multi-threading in e.g. TTree::Fill
63 ROOT::EnableImplicitMT();
64
65 /// Define the command line options
67
68 /// Define additional command line arguments and the configuration filename,
69 /// and we define the options that can be used in them (using QwOptions).
70 gQwOptions.AddOptions()("single-output-file", po::value<bool>()->default_bool_value(false), "Write a single output file");
71 gQwOptions.AddOptions()("print-errorcounters", po::value<bool>()->default_bool_value(true), "Print summary of error counters");
72 gQwOptions.AddOptions()("write-promptsummary", po::value<bool>()->default_bool_value(false), "Write PromptSummary");
73 gQwOptions.AddOptions()("callgrind-instr-start-event-loop", po::value<bool>()->default_bool_value(false), "Start callgrind instrumentation with main event loop (with --instr-atstart=no)");
74 gQwOptions.AddOptions()("callgrind-instr-stop-event-loop", po::value<bool>()->default_bool_value(false), "Stop callgrind instrumentation with main event loop (with --instr-atstart=no)");
75
76 /// Without anything, print usage
77 if (argc == 1) {
78 gQwOptions.Usage();
79 exit(0);
80 }
81
82 /// First, fill the search paths for the parameter files; this sets a
83 /// static variable within the QwParameterFile class which will be used by
84 /// all instances.
85 /// The "scratch" directory should be first.
87 QwParameterFile::AppendToSearchPath(getenv_safe_string("QWANALYSIS") + "/Parity/prminput");
88 QwParameterFile::AppendToSearchPath(getenv_safe_string("QWANALYSIS") + "/Analysis/prminput");
89
90 gQwOptions.SetCommandLine(argc, argv);
91 gQwOptions.AddConfigFile("qweak_mysql.conf");
92
93 gQwOptions.ListConfigFiles();
94
95 /// Load command line options for the histogram/tree helper class
96 gQwHists.ProcessOptions(gQwOptions);
97 /// Setup screen and file logging
98 gQwLog.ProcessOptions(&gQwOptions);
99
100
101 /// Create the event buffer
102 QwEventBuffer eventbuffer;
103 eventbuffer.ProcessOptions(gQwOptions);
104
105 /// Create the database connection
106 #ifdef __USE_DATABASE__
107 QwParityDB database(gQwOptions);
108 #endif //__USE_DATABASE__
109
110 // QwPromptSummary promptsummary;
111
112 /// Start loop over all runs
113 Int_t run_number = 0;
114 while (eventbuffer.OpenNextStream() == CODA_OK) {
115
116 /// Begin processing for the first run
117
118 run_number = eventbuffer.GetRunNumber();
119 TString run_label = eventbuffer.GetRunLabel();
120
121 /// Set the current event number for parameter file lookup
123 // Parse the options again, in case there are run-ranged config files
124 gQwOptions.Parse(kTRUE);
125 eventbuffer.ProcessOptions(gQwOptions);
126
127 // if (gQwOptions.GetValue<bool>("write-promptsummary")) {
128 QwPromptSummary promptsummary(run_number, eventbuffer.GetSegmentNumber());
129 // }
130 /// Create an EPICS event
131 QwEPICSEvent epicsevent;
132 epicsevent.ProcessOptions(gQwOptions);
133 epicsevent.LoadChannelMap("EpicsTable.map");
134
135
136 /// Load the detectors from file
138 detectors.ProcessOptions(gQwOptions);
139 detectors.ListPublishedValues();
140
141 /// Create event-based correction subsystem
142 // TString name = "EvtCorrector";
143 // QwCombinerSubsystem corrector_sub(gQwOptions, detectors, name);
144 // detectors.push_back(corrector_sub.GetSharedPointerToStaticObject());
145
146 /// Create the helicity pattern
147 // Instead of having run_label in the constructor of helicitypattern, it might
148 // make since to have it be an option for use globally
149 QwHelicityPattern helicitypattern(detectors,run_label);
150 helicitypattern.ProcessOptions(gQwOptions);
151
152 /// Create the event ring with the subsystem array
153 QwEventRing eventring(gQwOptions,detectors);
154 // Make a copy of the detectors object to hold the
155 // events which pass through the ring.
156 QwSubsystemArrayParity ringoutput(detectors);
157
158 /// Create the data handler arrays
159 QwDataHandlerArray datahandlerarray_evt(gQwOptions,ringoutput,run_label);
160 QwDataHandlerArray datahandlerarray_mul(gQwOptions,helicitypattern,run_label);
161 QwDataHandlerArray datahandlerarray_burst(gQwOptions,helicitypattern,run_label);
162
163 /// Create the burst sum
164 QwHelicityPattern patternsum_per_burst(helicitypattern);
165 patternsum_per_burst.DisablePairs();
166
167 /// Create the running sum
168 QwSubsystemArrayParity eventsum(detectors);
169 QwHelicityPattern patternsum(helicitypattern);
170 patternsum.DisablePairs();
171 QwHelicityPattern burstsum(helicitypattern);
172 burstsum.DisablePairs();
173
174 // Initialize the database connection.
175 #ifdef __USE_DATABASE__
176 database.SetupOneRun(eventbuffer);
177 #endif // __USE_DATABASE__
178
179 // Open the ROOT file (close when scope ends)
180 QwRootFile *treerootfile = NULL;
181 QwRootFile *burstrootfile = NULL;
182 QwRootFile *historootfile = NULL;
183
184
185 if (gQwOptions.GetValue<bool>("single-output-file")) {
186
187 treerootfile = new QwRootFile(run_label);
188 burstrootfile = historootfile = treerootfile;
189 // Construct a tree which contains map file names which are used to analyze data
190 treerootfile->WriteParamFileList("mapfiles", detectors);
191
192 } else {
193
194 treerootfile = new QwRootFile(run_label + ".trees");
195 burstrootfile = new QwRootFile(run_label + ".bursts");
196 historootfile = new QwRootFile(run_label + ".histos");
197
198 // Construct a tree which contains map file names which are used to analyze data
199 detectors.PrintParamFileList();
200 treerootfile->WriteParamFileList("mapfiles", detectors);
201 burstrootfile->WriteParamFileList("mapfiles", detectors);
202 historootfile->WriteParamFileList("mapfiles", detectors);
203 }
204 #ifdef __USE_DATABASE__
205 if (database.AllowsWriteAccess()) {
206 database.FillParameterFiles(detectors);
207 }
208 #endif // __USE_DATABASE__
209 // Construct histograms
210 historootfile->ConstructHistograms("evt_histo", ringoutput);
211 historootfile->ConstructHistograms("mul_histo", helicitypattern);
212 burstrootfile->ConstructHistograms("burst_histo", patternsum_per_burst);
213 detectors.ShareHistograms(ringoutput);
214
215 // Construct tree branches
216 treerootfile->ConstructTreeBranches("evt", "MPS event data tree", ringoutput);
217 treerootfile->ConstructTreeBranches("mul", "Helicity event data tree", helicitypattern);
218 burstrootfile->ConstructTreeBranches("pr", "Pair tree", helicitypattern.GetPairYield(),"yield_");
219 burstrootfile->ConstructTreeBranches("pr", "Pair tree", helicitypattern.GetPairAsymmetry(),"asym_");
220 treerootfile->ConstructTreeBranches("slow", "EPICS and slow control tree", epicsevent);
221 burstrootfile->ConstructTreeBranches("burst", "Burst level data tree", patternsum_per_burst, "|stat");
222
223 // Construct RNTuple fields if enabled
224#ifdef HAS_RNTUPLE_SUPPORT
225 treerootfile->ConstructNTupleFields("evt", "MPS event data RNTuple", ringoutput);
226 treerootfile->ConstructNTupleFields("mul", "Helicity event data RNTuple", helicitypattern);
227 burstrootfile->ConstructNTupleFields("pr_yield", "Pair yield RNTuple", helicitypattern.GetPairYield(),"yield_");
228 burstrootfile->ConstructNTupleFields("pr_asym", "Pair asymmetry RNTuple", helicitypattern.GetPairAsymmetry(),"asym_");
229 treerootfile->ConstructNTupleFields("slow", "EPICS and slow control RNTuple", epicsevent);
230 burstrootfile->ConstructNTupleFields("burst", "Burst level data RNTuple", patternsum_per_burst, "|stat");
231#endif
232
233 historootfile->ConstructHistograms("evt_histo", datahandlerarray_evt);
234 historootfile->ConstructHistograms("mul_histo", datahandlerarray_mul);
235 burstrootfile->ConstructHistograms("burst_histo", datahandlerarray_burst);
236
237 datahandlerarray_evt.ConstructTreeBranches(treerootfile, "evt_");
238 datahandlerarray_mul.ConstructTreeBranches(treerootfile);
239 datahandlerarray_burst.ConstructTreeBranches(burstrootfile, "burst_", "|stat");
240
241 // Construct RNTuple fields for data handlers if enabled
242#ifdef HAS_RNTUPLE_SUPPORT
243 datahandlerarray_evt.ConstructNTupleFields(treerootfile, "evt_");
244 datahandlerarray_mul.ConstructNTupleFields(treerootfile);
245 datahandlerarray_burst.ConstructNTupleFields(burstrootfile, "burst_", "|stat");
246#endif
247
248 treerootfile->ConstructTreeBranches("evts", "Running sum tree", eventsum, "|stat");
249 treerootfile->ConstructTreeBranches("muls", "Running sum tree", patternsum, "|stat");
250 burstrootfile->ConstructTreeBranches("bursts", "Burst running sum tree", burstsum, "|stat");
251
252 // Construct RNTuple fields for additional data if enabled
253#ifdef HAS_RNTUPLE_SUPPORT
254 treerootfile->ConstructNTupleFields("evts", "Running sum RNTuple", eventsum, "|stat");
255 treerootfile->ConstructNTupleFields("muls", "Running sum RNTuple", patternsum, "|stat");
256 burstrootfile->ConstructNTupleFields("bursts", "Burst running sum RNTuple", burstsum, "|stat");
257#endif
258
259 // Summarize the ROOT file structure
260 //treerootfile->PrintTrees();
261 //treerootfile->PrintDirs();
262
263
264 // Clear the single-event running sum at the beginning of the runlet
265 eventsum.ClearEventData();
266 patternsum.ClearEventData();
267 burstsum.ClearEventData();
268 // Clear the running sum of the burst values at the beginning of the runlet
269 helicitypattern.ClearEventData();
270 patternsum_per_burst.ClearEventData();
271
272
273
274 // Load the blinder seed from a random number generator for online mode
275 if (eventbuffer.IsOnline() ){
276 helicitypattern.UpdateBlinder();//this routine will call update blinder mechanism using a random number
277 }else{
278 // Load the blinder seed from the database for this runlet.
279#ifdef __USE_DATABASE__
280 helicitypattern.UpdateBlinder(&database);
281#endif // __USE_DATABASE__
282 }
283
284
285 // Find the first EPICS event and try to initialize
286 // the blinder, but only for disk files, not online.
287 if (! eventbuffer.IsOnline() ){
288 QwMessage << "Finding first EPICS event" << QwLog::endl;
289 while (eventbuffer.GetNextEvent() == CODA_OK) {
290 if (eventbuffer.IsEPICSEvent()) {
291 eventbuffer.FillEPICSData(epicsevent);
292 if (epicsevent.HasDataLoaded()) {
293 helicitypattern.UpdateBlinder(epicsevent);
294 // and break out of this event loop
295 break;
296 }
297 }
298 }
299 epicsevent.ResetCounters();
300 // Rewind stream
301 QwMessage << "Rewinding stream" << QwLog::endl;
302 eventbuffer.ReOpenStream();
303 }
304
305 // Start event loop instrumentation
306#ifdef CALLGRIND_START_INSTRUMENTATION
307 if (gQwOptions.GetValue<bool>("callgrind-instr-start-event-loop")) {
308 QwMessage << "Starting callgrind instrumentation" << QwLog::endl;
309 CALLGRIND_START_INSTRUMENTATION;
310 }
311#endif
312
313 /// Start loop over events
314 while (eventbuffer.GetNextEvent() == CODA_OK) {
315
316 // First, do processing of non-physics events...
317 if (eventbuffer.IsROCConfigurationEvent()) {
318 // Send ROC configuration event data to the subsystem objects.
319 eventbuffer.FillSubsystemConfigurationData(detectors);
320 }
321
322 // Secondly, process EPICS events, but not for online running,
323 // because the EPICS events get messed up by our 32-bit to 64-bit
324 // double ET system.
325 if (! eventbuffer.IsOnline() && eventbuffer.IsEPICSEvent()) {
326 eventbuffer.FillEPICSData(epicsevent);
327 if (epicsevent.HasDataLoaded()){
328 epicsevent.CalculateRunningValues();
329 helicitypattern.UpdateBlinder(epicsevent);
330
331 treerootfile->FillTreeBranches(epicsevent);
332 treerootfile->FillTree("slow");
333
334 // Fill RNTuple if enabled
335#ifdef HAS_RNTUPLE_SUPPORT
336 treerootfile->FillNTupleFields(epicsevent);
337 treerootfile->FillNTuple("slow");
338#endif
339 }
340 }
341
342
343 // Now, if this is not a physics event, go back and get a new event.
344 if (! eventbuffer.IsPhysicsEvent()) continue;
345
346
347 // Fill the subsystem objects with their respective data for this event.
348 eventbuffer.FillSubsystemData(detectors);
349
350 // Process the subsystem data
351 detectors.ProcessEvent();
352
353
354 // The event pass the event cut constraints
355 if (detectors.ApplySingleEventCuts()) {
356
357 // Add event to the ring
358 eventring.push(detectors);
359
360 // Check to see ring is ready
361 if (eventring.IsReady()) {
362 ringoutput = eventring.pop();
363 ringoutput.IncrementErrorCounters();
364
365
366 // Accumulate the running sum to calculate the event based running average
367 eventsum.AccumulateRunningSum(ringoutput);
368
369 // Fill the histograms
370 historootfile->FillHistograms(ringoutput);
371
372 // Fill mps tree branches
373 treerootfile->FillTreeBranches(ringoutput);
374 treerootfile->FillTree("evt");
375
376 // Fill RNTuple if enabled
377#ifdef HAS_RNTUPLE_SUPPORT
378 treerootfile->FillNTupleFields(ringoutput);
379 treerootfile->FillNTuple("evt");
380#endif
381
382 // Process data handlers
383 datahandlerarray_evt.ProcessDataHandlerEntry();
384
385 // Fill data handler histograms
386 historootfile->FillHistograms(datahandlerarray_evt);
387
388 // Fill data handler tree branches
389 datahandlerarray_evt.FillTreeBranches(treerootfile);
390
391 // Fill data handler RNTuple fields if enabled
392#ifdef HAS_RNTUPLE_SUPPORT
393 datahandlerarray_evt.FillNTupleFields(treerootfile);
394#endif
395
396 // Load the event into the helicity pattern
397 helicitypattern.LoadEventData(ringoutput);
398
399 if (helicitypattern.PairAsymmetryIsGood()) {
400 patternsum.AccumulatePairRunningSum(helicitypattern);
401
402 // Fill pair tree branches
403 burstrootfile->FillTreeBranches(helicitypattern.GetPairYield());
404 burstrootfile->FillTreeBranches(helicitypattern.GetPairAsymmetry());
405 burstrootfile->FillTreeBranches(helicitypattern.GetPairDifference());
406 burstrootfile->FillTree("pr");
407
408 // Fill pair RNTuples if enabled
409#ifdef HAS_RNTUPLE_SUPPORT
410 burstrootfile->FillNTupleFields("pr_yield", helicitypattern.GetPairYield());
411 burstrootfile->FillNTupleFields("pr_asym", helicitypattern.GetPairAsymmetry());
412 burstrootfile->FillNTuple("pr_yield");
413 burstrootfile->FillNTuple("pr_asym");
414#endif
415
416 // Clear the data
417 helicitypattern.ClearPairData();
418 }
419
420 // Check to see if we can calculate helicity pattern asymmetry, do so, and report if it worked
421 if (helicitypattern.IsGoodAsymmetry()) {
422 patternsum.AccumulateRunningSum(helicitypattern);
423
424 // Fill histograms
425 historootfile->FillHistograms(helicitypattern);
426
427 // Fill helicity tree branches
428 treerootfile->FillTreeBranches(helicitypattern);
429 treerootfile->FillTree("mul");
430
431 // Fill helicity RNTuple if enabled
432#ifdef HAS_RNTUPLE_SUPPORT
433 treerootfile->FillNTupleFields(helicitypattern);
434 treerootfile->FillNTuple("mul");
435#endif
436
437 // Process data handlers
438 datahandlerarray_mul.ProcessDataHandlerEntry();
439 datahandlerarray_burst.ProcessDataHandlerEntry();
440
441 // Fill data handler histograms
442 historootfile->FillHistograms(datahandlerarray_mul);
443
444 // Fill data handler tree branches
445 datahandlerarray_mul.FillTreeBranches(treerootfile);
446
447 // Fill data handler RNTuple fields if enabled
448#ifdef HAS_RNTUPLE_SUPPORT
449 datahandlerarray_mul.FillNTupleFields(treerootfile);
450#endif
451
452 // Fill the pattern into the sum for this burst
453 patternsum_per_burst.AccumulateRunningSum(helicitypattern);
454
455 // Accumulate data handler arrays
456 //datahandlerarray_burst.AccumulateRunningSum(datahandlerarray_mul);
457
458 // Burst mode
459 if (patternsum_per_burst.IsEndOfBurst()) {
460
461 // Calculate average over this burst
462 patternsum_per_burst.CalculateRunningAverage();
463
464 // Fill the burst into the sum over all bursts
465 burstsum.AccumulateRunningSum(patternsum_per_burst);
466
467 if (gQwOptions.GetValue<bool>("print-burstsum")) {
468 QwMessage << " Running average of this burst" << QwLog::endl;
469 QwMessage << " =============================" << QwLog::endl;
470 patternsum_per_burst.PrintValue();
471 }
472
473 // Fill histograms
474 burstrootfile->FillHistograms(patternsum_per_burst);
475
476 // Fill burst tree branches
477 burstrootfile->FillTreeBranches(patternsum_per_burst);
478 burstrootfile->FillTree("burst");
479
480 // Fill burst RNTuple if enabled
481#ifdef HAS_RNTUPLE_SUPPORT
482 burstrootfile->FillNTupleFields(patternsum_per_burst);
483 burstrootfile->FillNTuple("burst");
484#endif
485
486 // Finish data handler for burst
487 datahandlerarray_burst.FinishDataHandler();
488
489 // Fill data handler histograms
490 burstrootfile->FillHistograms(datahandlerarray_burst);
491
492 // Fill data handler tree branches
493 datahandlerarray_burst.FillTreeBranches(burstrootfile);
494
495 // Fill data handler RNTuple fields if enabled
496#ifdef HAS_RNTUPLE_SUPPORT
497 datahandlerarray_burst.FillNTupleFields(burstrootfile);
498#endif
499
500 helicitypattern.IncrementBurstCounter();
501 datahandlerarray_mul.UpdateBurstCounter(helicitypattern.GetBurstCounter());
502 datahandlerarray_burst.UpdateBurstCounter(helicitypattern.GetBurstCounter());
503 // Clear the data
504 patternsum_per_burst.ClearEventData();
505 datahandlerarray_burst.ClearEventData();
506 }
507
508 // Clear the data
509 helicitypattern.ClearEventData();
510
511 } // helicitypattern.IsGoodAsymmetry()
512
513 } // eventring.IsReady()
514
515 } // detectors.ApplySingleEventCuts()
516
517 } // end of loop over events
518
519 // Unwind event ring
520 QwMessage << "Unwinding event ring" << QwLog::endl;
521 eventring.Unwind();
522
523 // Stop event loop instrumentation
524#ifdef CALLGRIND_START_INSTRUMENTATION
525 if (gQwOptions.GetValue<bool>("callgrind-instr-stop-event-loop")) {
526 CALLGRIND_STOP_INSTRUMENTATION;
527 QwMessage << "Stapped callgrind instrumentation" << QwLog::endl;
528 }
529#endif
530
531 // TODO Drain event run
532
533 // Finalize burst
534 if (patternsum_per_burst.HasBurstData()){
535 // Calculate average over this burst
536 patternsum_per_burst.CalculateRunningAverage();
537
538 // Fill the burst into the sum over all bursts
539 burstsum.AccumulateRunningSum(patternsum_per_burst);
540
541 if (gQwOptions.GetValue<bool>("print-burstsum")) {
542 QwMessage << " Running average of this burst" << QwLog::endl;
543 QwMessage << " =============================" << QwLog::endl;
544 patternsum_per_burst.PrintValue();
545 }
546
547 // Fill histograms
548 burstrootfile->FillHistograms(patternsum_per_burst);
549
550 // Fill burst tree branches
551 burstrootfile->FillTreeBranches(patternsum_per_burst);
552 burstrootfile->FillTree("burst");
553
554 // Fill burst RNTuple if enabled
555#ifdef HAS_RNTUPLE_SUPPORT
556 burstrootfile->FillNTupleFields(patternsum_per_burst);
557 burstrootfile->FillNTuple("burst");
558#endif
559
560 // Finish data handler for burst
561 datahandlerarray_burst.FinishDataHandler();
562
563 // Fill data handler histograms
564 burstrootfile->FillHistograms(datahandlerarray_burst);
565
566 // Fill data handler tree branches
567 datahandlerarray_burst.FillTreeBranches(burstrootfile);
568
569 // Fill data handler RNTuple fields if enabled
570#ifdef HAS_RNTUPLE_SUPPORT
571 datahandlerarray_burst.FillNTupleFields(burstrootfile);
572#endif
573 patternsum_per_burst.PrintIndexMapFile(run_number);
574 }
575
576 // Perform actions at the end of the event loop on the
577 // detectors object, which ought to have handles for the
578 // MPS based histograms.
579 ringoutput.AtEndOfEventLoop();
580
581 QwMessage << "Number of events processed at end of run: "
582 << eventbuffer.GetPhysicsEventNumber() << QwLog::endl;
583
584 // Finish data handlers
585 datahandlerarray_evt.FinishDataHandler();
586 datahandlerarray_mul.FinishDataHandler();
587
588 // Calculate running averages
589 eventsum.CalculateRunningAverage();
590 patternsum.CalculateRunningAverage();
591 burstsum.CalculateRunningAverage();
592
593 // This will calculate running averages over single helicity events
594 if (gQwOptions.GetValue<bool>("print-runningsum")) {
595 QwMessage << " Running average of events" << QwLog::endl;
596 QwMessage << " =========================" << QwLog::endl;
597 eventsum.PrintValue();
598 }
599 treerootfile->FillTreeBranches(eventsum);
600 treerootfile->FillTree("evts");
601
602 // Fill running sum RNTuple if enabled
603#ifdef HAS_RNTUPLE_SUPPORT
604 treerootfile->FillNTupleFields(eventsum);
605 treerootfile->FillNTuple("evts");
606#endif
607
608 if (gQwOptions.GetValue<bool>("print-patternsum")) {
609 QwMessage << " Running average of patterns" << QwLog::endl;
610 QwMessage << " =========================" << QwLog::endl;
611 patternsum.PrintValue();
612 }
613 treerootfile->FillTreeBranches(patternsum);
614 treerootfile->FillTree("muls");
615
616 // Fill pattern sum RNTuple if enabled
617#ifdef HAS_RNTUPLE_SUPPORT
618 treerootfile->FillNTupleFields(patternsum);
619 treerootfile->FillNTuple("muls");
620#endif
621
622 if (gQwOptions.GetValue<bool>("print-burstsum")) {
623 QwMessage << " Running average of bursts" << QwLog::endl;
624 QwMessage << " =========================" << QwLog::endl;
625 burstsum.PrintValue();
626 }
627 burstrootfile->FillTreeBranches(burstsum);
628 burstrootfile->FillTree("bursts");
629
630 // Fill burst sum RNTuple if enabled
631#ifdef HAS_RNTUPLE_SUPPORT
632 burstrootfile->FillNTupleFields(burstsum);
633 burstrootfile->FillNTuple("bursts");
634#endif
635
636 // Construct objects
637 burstrootfile->ConstructObjects("objects", helicitypattern);
638
639 /* Write to the root file, being sure to delete the old cycles *
640 * which were written by Autosave. *
641 * Doing this will remove the multiple copies of the ntuples *
642 * from the root file. *
643 * *
644 * Then, we need to delete the histograms here. *
645 * If we wait until the subsystem destructors, we get a *
646 * segfault; but in addition to that we should delete them *
647 * here, in case we run over multiple runs at a time. */
648 if (treerootfile == historootfile) {
649 // Use different write methods based on output format
650#ifdef HAS_RNTUPLE_SUPPORT
651 if (gQwOptions.GetValue<bool>("enable-rntuples") && gQwOptions.GetValue<bool>("disable-trees")) {
652 // RNTuple-only mode: use Close() for proper RNTuple finalization
653 treerootfile->Close();
654 } else {
655#endif
656 // TTree mode or mixed mode: use Write() for explicit tree writing
657 treerootfile->Write(0, TObject::kOverwrite);
658 treerootfile->Close();
659#ifdef HAS_RNTUPLE_SUPPORT
660 }
661#endif
662 delete treerootfile; treerootfile = 0; burstrootfile = 0; historootfile = 0;
663 } else {
664 // Use different write methods based on output format
665#ifdef HAS_RNTUPLE_SUPPORT
666 if (gQwOptions.GetValue<bool>("enable-rntuples") && gQwOptions.GetValue<bool>("disable-trees")) {
667 // RNTuple-only mode: use Close() for proper RNTuple finalization
668 treerootfile->Close();
669 burstrootfile->Close();
670 historootfile->Close();
671 } else {
672#endif
673 // TTree mode or mixed mode: use Write() for explicit tree writing
674 treerootfile->Write(0, TObject::kOverwrite);
675 burstrootfile->Write(0, TObject::kOverwrite);
676 historootfile->Write(0, TObject::kOverwrite);
677 treerootfile->Close();
678 burstrootfile->Close();
679 historootfile->Close();
680#ifdef HAS_RNTUPLE_SUPPORT
681 }
682#endif
683 delete treerootfile; treerootfile = 0;
684 delete burstrootfile; burstrootfile = 0;
685 delete historootfile; historootfile = 0;
686 }
687
688 // Print the event cut error summary for each subsystem
689 if (gQwOptions.GetValue<bool>("print-errorcounters")) {
690 QwMessage << " ------------ error counters ------------------ " << QwLog::endl;
691 ringoutput.PrintErrorCounters();
692 }
693
694 if (gQwOptions.GetValue<bool>("write-promptsummary")) {
695 // runningsum.WritePromptSummary(&promptsummary, "yield");
696 // runningsum.WritePromptSummary(&promptsummary, "asymmetry");
697 // runningsum.WritePromptSummary(&promptsummary, "difference");
698 datahandlerarray_mul.WritePromptSummary(&promptsummary, "asymmetry");
699 patternsum.WritePromptSummary(&promptsummary);
700 promptsummary.PrintCSV(eventbuffer.GetPhysicsEventNumber(),eventbuffer.GetStartSQLTime(), eventbuffer.GetEndSQLTime());
701 }
702 // Read from the database
703 #ifdef __USE_DATABASE__
704 database.SetupOneRun(eventbuffer);
705
706 // Each subsystem has its own Connect() and Disconnect() functions.
707 if (database.AllowsWriteAccess()) {
708 patternsum.FillDB(&database);
709 patternsum.FillErrDB(&database);
710 epicsevent.FillDB(&database);
711 ringoutput.FillDB_MPS(&database, "optics");
712 }
713 #endif // __USE_DATABASE__
714
715 //epicsevent.WriteEPICSStringValues();
716
717 // Close event buffer stream
718 eventbuffer.CloseStream();
719
720
721
722 // Report run summary
723 eventbuffer.ReportRunSummary();
724 eventbuffer.PrintRunTimes();
725 } // end of loop over runs
726
727 QwMessage << "I have done everything I can do..." << QwLog::endl;
728
729 return 0;
730}
A logfile class, based on an identical class in the Hermes analyzer.
QwLog gQwLog
Definition QwLog.cc:20
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
Event buffer management for reading and processing CODA data.
EPICS data event handling and storage.
Prompt summary data management.
Helper functions and utilities for ROOT histogram management.
QwHistogramHelper gQwHists
Globally defined instance of the QwHistogramHelper class.
ROOT file and tree management wrapper classes.
const std::string getenv_safe_string(const char *name)
Definition QwOptions.h:43
#define gQwOptions
Definition QwOptions.h:31
Int_t main(Int_t argc, Char_t *argv[])
Definition QwParity.cc:60
Event ring buffer for burp detection and stability monitoring.
Helicity state management and pattern recognition.
Subsystem array container for parity analysis with asymmetry calculations.
Correlator data handler using LinRegBlue algorithms.
Beamline subsystem containing BPMs, BCMs, and other beam monitoring devices.
Helicity pattern analysis and management.
Load the options for the parity subsystems.
void DefineOptionsParity(QwOptions &options)
Fake helicity generator using pregenerated random seeds.
Beam modulation subsystem for parity analysis.
Linear regression blue corrector data handler class.
Array container for managing multiple data handlers.
Data combiner handler for channel operations.
Combiner subsystem for parity analysis data handling.
Data extraction handler for output processing.
void ListPublishedValues() const
List all published variables with descriptions Prints a summary of all currently published variables ...
EPICS slow controls data management.
Bool_t HasDataLoaded() const
void ProcessOptions(QwOptions &options)
Process the configuration options.
Int_t LoadChannelMap(TString mapfile)
void CalculateRunningValues()
void FillDB(QwParityDB *db)
void ResetCounters()
Event buffer management for reading and processing CODA data.
TString GetRunLabel() const
Returns a string like <run#> or <run#>.<file#>
TString GetEndSQLTime()
void ReportRunSummary()
Bool_t IsOnline()
Int_t CloseStream()
Closes a currently open event stream.
Bool_t IsEPICSEvent()
Int_t OpenNextStream()
Opens the event stream (file or ET) based on the internal flags.
void ProcessOptions(QwOptions &options)
Sets internal flags based on the QwOptions.
Bool_t FillSubsystemData(QwSubsystemArray &subsystems)
Int_t GetSegmentNumber() const
Return CODA file segment number.
TString GetStartSQLTime()
Int_t GetRunNumber() const
Return CODA file run number.
Bool_t IsROCConfigurationEvent()
Int_t GetPhysicsEventNumber()
Bool_t IsPhysicsEvent()
Bool_t FillEPICSData(QwEPICSEvent &epics)
Bool_t FillSubsystemConfigurationData(QwSubsystemArray &subsystems)
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
static void AppendToSearchPath(const TString &searchdir)
Add a directory to the search path.
static void SetCurrentRunNumber(const UInt_t runnumber)
Set the current run number for looking up the appropriate parameter file.
void PrintCSV(Int_t nEvents, TString start_time, TString end_time)
A wrapper class for a ROOT file or memory mapped file.
Definition QwRootFile.h:849
Int_t FillTree(const std::string &name)
Fill the tree with name.
Definition QwRootFile.h:974
Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
void Close()
void ConstructTreeBranches(const std::string &name, const std::string &desc, T &object, const std::string &prefix="")
Construct the tree branches of a generic object.
void FillHistograms(T &object)
Fill histograms of the subsystem array.
Definition QwRootFile.h:917
void FillTreeBranches(const std::string &name, const T &object)
Fill the tree branches of a generic object by tree name.
Int_t WriteParamFileList(const TString &name, T &object)
void ConstructHistograms(const std::string &name, T &object)
Construct the histograms of a generic object.
void ConstructObjects(const std::string &name, T &object)
Construct the histograms of a generic object.
void ProcessEvent()
Process the decoded data in this event.
void PrintParamFileList() const
Print list of parameter files.
void ShareHistograms(const QwSubsystemArray &source)
Share the histograms with another subsystem.
void ProcessOptions(QwOptions &options)
Process configuration options (default behavior)
void AtEndOfEventLoop()
Perform actions at the end of the event loop.
Virtual base class for the parity handlers.
void UpdateBurstCounter(Short_t burstcounter)
void FillNTupleFields(QwRootFile *treerootfile)
void FillTreeBranches(QwRootFile *treerootfile)
void ConstructTreeBranches(QwRootFile *treerootfile, const std::string &treeprefix="", const std::string &branchprefix="")
void WritePromptSummary(QwPromptSummary *ps, TString type)
void ConstructNTupleFields(QwRootFile *treerootfile, const std::string &treeprefix="", const std::string &branchprefix="")
RNTuple methods.
Ring buffer of subsystem snapshots for burp/stability handling.
Definition QwEventRing.h:28
QwSubsystemArrayParity & pop()
Return the last subsystem in the ring.
void push(QwSubsystemArrayParity &event)
Add the subsystem to the ring.
Bool_t IsReady()
Return the read status of the ring.
void Unwind()
Unwind the ring until empty.
Definition QwEventRing.h:68
Manages yields/differences/asymmetries for helicity patterns.
QwSubsystemArrayParity & GetPairYield()
void DisablePairs()
Disable storing pair differences.
void UpdateBlinder()
Update the blinder status using a random number generator.
void ProcessOptions(QwOptions &options)
Process the configuration options.
void AccumulatePairRunningSum(QwHelicityPattern &entry)
QwSubsystemArrayParity & GetPairAsymmetry()
Short_t GetBurstCounter() const
QwSubsystemArrayParity & GetPairDifference()
void WritePromptSummary(QwPromptSummary *ps)
void PrintIndexMapFile(Int_t runNum)
void LoadEventData(QwSubsystemArrayParity &event)
void AccumulateRunningSum(QwHelicityPattern &entry, Int_t count=0, Int_t ErrorMask=0xFFFFFFF)
Subsystem array container specialized for parity analysis with asymmetry calculations.
void PrintErrorCounters() const
Report the number of events failed due to HW and event cut failures.
void PrintValue() const
Print value of all channels.
void IncrementErrorCounters()
Update the data elements' error counters based on their internal error flags.
void AccumulateRunningSum(const QwSubsystemArrayParity &value, Int_t count=0, Int_t ErrorMask=0xFFFFFFF)
Update the running sums for devices accumulated for the global error non-zero events/patterns.
void CalculateRunningAverage()
Calculate the average for all good events.
void FillDB_MPS(QwParityDB *db, TString type)
Fill the database with MPS-based variables Note that most subsystems don't need to do this.
Bool_t ApplySingleEventCuts()
Apply the single event cuts.