JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwHelicityPattern.cc
Go to the documentation of this file.
1/**********************************************************\
2* File: QwHelicityPattern.cc *
3* *
4* Author: *
5* Time-stamp: *
6\**********************************************************/
7
8#include "QwHelicityPattern.h"
9
10// System headers
11#include <stdexcept>
12
13// ROOT headers
14#ifdef HAS_RNTUPLE_SUPPORT
15#include "ROOT/RNTupleModel.hxx"
16#include "ROOT/RField.hxx"
17#endif // HAS_RNTUPLE_SUPPORT
18
19// Qweak headers
20#include "QwLog.h"
21#include "QwHistogramHelper.h"
22#include "QwHelicity.h"
23#include "QwBlinder.h"
24#include "VQwDataElement.h"
25
26#include "QwPromptSummary.h"
27
28/*****************************************************************/
29/**
30 * Defines configuration options using QwOptions functionality.
31 * @param options Options object
32 */
34{
35 options.AddOptions("Helicity pattern")
36 ("enable-burstsum", po::value<bool>()->default_bool_value(false),
37 "enable burst sum calculation");
38 options.AddOptions("Helicity pattern")
39 ("enable-runningsum", po::value<bool>()->default_bool_value(true),
40 "enable running sum calculation");
41 options.AddOptions("Helicity pattern")
42 ("enable-differences", po::value<bool>()->default_bool_value(false),
43 "store pattern differences in tree");
44 options.AddOptions("Helicity pattern")
45 ("enable-alternateasym", po::value<bool>()->default_bool_value(false),
46 "enable alternate asymmetries");
47
48 options.AddOptions("Helicity pattern")
49 ("print-burstsum", po::value<bool>()->default_bool_value(false),
50 "print burst sum of subsystems");
51 options.AddOptions("Helicity pattern")
52 ("print-patternsum", po::value<bool>()->default_bool_value(false),
53 "print pattern sum of subsystems");
54 options.AddOptions("Helicity pattern")
55 ("print-runningsum", po::value<bool>()->default_bool_value(false),
56 "print running sum of subsystems");
57
58 options.AddOptions("Helicity pattern")
59 ("burstlength", po::value<int>()->default_value(9000),
60 "number of patterns per burst");
61
62 options.AddOptions("Helicity pattern")
63 ("max-burst-index", po::value<int>()->default_value(0x7fffffff), // Default to max signed int
64 "max number of bursts for a run");
65
66 options.AddOptions("Helicity pattern")
67 ("print-burst-index-map", po::value<bool>()->default_value(kFALSE),
68 "whether to print the shorter max burst index if the final is shorter than min-burstlength");
69
70 options.AddOptions("Helicity pattern")
71 ("min-burstlength", po::value<int>()->default_value(2333), // Default 1/4 of 9000
72 "minimum acceptable burst length");
73
75}
76
77/*****************************************************************/
79{
80 fEnableBurstSum = options.GetValue<bool>("enable-burstsum");
81 fEnableRunningSum = options.GetValue<bool>("enable-runningsum");
82 fPrintBurstSum = options.GetValue<bool>("print-burstsum");
83 fPrintRunningSum = options.GetValue<bool>("print-runningsum");
84
85 fEnableDifference = options.GetValue<bool>("enable-differences");
86 fEnableAlternateAsym = options.GetValue<bool>("enable-alternateasym");
87
88 fBurstLength = options.GetValue<int>("burstlength");
89 if (fBurstLength == 0) DisableBurstSum();
90
91 fMaxBurstIndex = options.GetValue<int>("max-burst-index");
92 fPrintIndexFile = options.GetValue<bool>("print-burst-index-map");
93 fBurstMinGoodPatterns = options.GetValue<int>("min-burstlength");
94
96 QwWarning << "QwHelicityPattern::ProcessOptions: "
97 << "The 'enable-alternateasym' flag is disabled for pair analysis."
98 << QwLog::endl;
99 fEnableAlternateAsym = kFALSE;
100 }
101
102 fBlinder.ProcessOptions(options);
103}
104
105/*****************************************************************/
107 : fBlinder(),
108 fHelicityIsMissing(kFALSE),
109 fIgnoreHelicity(kFALSE),
110 fYield(event),
111 fDifference(event),
112 fAsymmetry(event),
113 fEnableAlternateAsym(kFALSE),
114 fAsymmetry1(event),
115 fAsymmetry2(event),
116 fEnablePairs(kTRUE),
117 fPairYield(event),
118 fPairDifference(event),
119 fPairAsymmetry(event),
120 fBurstLength(0),
121 fMaxBurstIndex(0x7fffffff),
122 fPrintIndexFile(kFALSE),
124 fGoodPatterns(0),
125 fBurstCounter(0),
126 fEnableBurstSum(kFALSE),
127 fPrintBurstSum(kFALSE),
128 fEnableRunningSum(kTRUE),
129 fPrintRunningSum(kFALSE),
130 fEnableDifference(kFALSE),
131 fAlternateDiff(event),
132 fPositiveHelicitySum(event),
137 fNextPair(0),
138 fPairIsGood(false),
139 fPatternIsGood(false),
140 fIsDataLoaded(false)
141{
142 // Retrieve the helicity subsystem to query for
143 std::vector<VQwSubsystem*> subsys_helicity = event.GetSubsystemByType("QwHelicity");
144 if (subsys_helicity.size() > 0) {
145
146 // Take the first helicity subsystem
147 // fHelicitySubsystem = dynamic_cast<QwHelicity*>(subsys_helicity.at(0));
148 QwHelicity* helicity = dynamic_cast<QwHelicity*>(subsys_helicity.at(0));
149
150 // Get the maximum pattern phase (i.e. pattern size)
151 fPatternSize = helicity->GetMaxPatternPhase();
152
153 // Warn if more than one helicity subsystem defined
154 if (subsys_helicity.size() > 1)
155 QwWarning << "Multiple helicity subsystems defined! "
156 << "Using " << helicity->GetName() << "."
157 << QwLog::endl;
158
159 } else {
160 // We are not using any helicity subsystem
161 QwError << "No helicity subsystem defined! "
162 << "Calculate asymmetries based on (+--+) quartets!"
163 << QwLog::endl;
164 fHelicityIsMissing = kTRUE;
165 fPatternSize = 4; // default to quartets
166 }
167 QwMessage << "QwHelicity::MaxPatternPhase = " << fPatternSize << QwLog::endl;
168
169 try
170 {
171 if(fPatternSize%2 == 0)
172 {
173 fEvents.resize(fPatternSize,event);
174 fHelicity.resize(fPatternSize,-9999);
175 fEventNumber.resize(fPatternSize,-1);
176 fEventLoaded.resize(fPatternSize,kFALSE);
177
178 // Initialize the pattern number
179 fQuartetNumber = 0;
180 fCurrentPatternNumber = -1;
181 }
182 else
183 {
184 TString loc=
185 "Standard exception from QwHelicityPattern : the pattern size has to be even; right now pattern_size=";
186 loc+=Form("%zu",fPatternSize);
187 throw std::invalid_argument(loc.Data());
188 }
189 }
190 catch (std::exception& e)
191 {
192 std::cerr << e.what() << std::endl;
193 }
194
195}
196
197/*****************************************************************/
232
233
234
235//*****************************************************************
236/**
237 * Load event data corresponding to the current pattern from the
238 * subsystems.
239 */
241{
242
243 Bool_t localdebug = kFALSE;
244 fPatternIsGood = kFALSE;
245
246 Long_t localEventNumber = -1;
247 Long_t localPatternNumber = -1;
248 Int_t localPhaseNumber = -1;
249 Int_t localHelicityActual = -1;
250 Bool_t localIgnoreHelicity = kFALSE;
251
252
253 // Get the list of helicity subsystems
254 if (! fHelicityIsMissing){
255 std::vector<VQwSubsystem*> subsys_helicity = event.GetSubsystemByType("QwHelicity");
256 QwHelicity* helicity = 0;
257
258 if (subsys_helicity.size() > 0) {
259 // Take the first helicity subsystem
260 helicity = dynamic_cast<QwHelicity*>(subsys_helicity.at(0));
261 if (helicity->HasDataLoaded()){
262 localIgnoreHelicity = helicity->IsHelicityIgnored();
263 // Get the event, pattern, phase number and helicity
264 localEventNumber = helicity->GetEventNumber();
265 localPatternNumber = helicity->GetPatternNumber();
266 localPhaseNumber = helicity->GetPhaseNumber() - helicity->GetMinPatternPhase(); // Use "reduced pattern phase", counts from 0.
267 localHelicityActual = helicity->GetHelicityActual();
268 } else {
269 QwError << "QwHelicityPattern::LoadEventData: The helicity subsystem does not have valid data!"
270 << QwLog::endl;
271 }
272 } else {
273 // We are not using any helicity subsystem
274 static Bool_t user_has_been_warned = kFALSE;
275 if (! user_has_been_warned) {
276 QwError << "No helicity subsystem found! Dropping to \"Missing Helicity\" mode!" << QwLog::endl;
277 user_has_been_warned = kTRUE;
278 fHelicityIsMissing = kTRUE;
279 }
280 }
281 }
283 localIgnoreHelicity = kTRUE;
284 localPatternNumber = fLastPatternNumber;
285 localEventNumber = fLastWindowNumber + 1;
286 localPhaseNumber = fLastPhaseNumber + 1;
287 if(localPhaseNumber>=fPatternSize){
288 localPatternNumber++;
289 localPhaseNumber = 0; // Use "reduced pattern phase", counts from 0.
290 }
291 fLastWindowNumber = localEventNumber;
292 fLastPhaseNumber = localPhaseNumber;
293 fLastPatternNumber = localPatternNumber;
294 }
295 if(localdebug) {
296 std::cout<<"\n ###################################\n";
297 std::cout<<"QwHelicityPattern::LoadEventData :: ";
298 std::cout<<" event, pattern, phase # "<<localEventNumber<<" "<<localPatternNumber<<" "<<localPhaseNumber<<"\n";
299 std::cout<<" helicity ="<< localHelicityActual<<"\n";
300 for(size_t i=0; i<fEvents.size(); i++)
301 std::cout<<i<<":"<<fEventLoaded[i]<<" ";
302 std::cout<<"\n";
303 }
304 if(fCurrentPatternNumber!=localPatternNumber){
305 // new pattern
307 fCurrentPatternNumber=localPatternNumber;
308 }
309 if(localPhaseNumber<0){
310 QwWarning << "QwHelicityPattern::LoadEventData: "
311 << "Reduced event phase number is less than zero; ignore this event."
312 << QwLog::endl;
314 } else if(localPhaseNumber>=fPatternSize){
315 QwWarning<<" In QwHelicityPattern::LoadEventData trying upload an event with a phase larger than expected \n"
316 <<" phase ="<<localPhaseNumber+1<<" maximum expected phase="<<fPatternSize<<"\n"
317 <<" operation impossible, pattern reset to 0: no asymmetries will be computed "<<QwLog::endl;
319 } else {
320 if(localdebug){
321 std::cout<<"QwHelicityPattern::LoadEventData local i="
322 <<localPhaseNumber<<"\n";
323 }
324 fEvents[localPhaseNumber] = event;
325 fEventLoaded[localPhaseNumber] = kTRUE;
326 fHelicity[localPhaseNumber] = localHelicityActual;
327 fEventNumber[localPhaseNumber] = localEventNumber;
328 // Check to see if we should ignore the helicity; this is
329 // reset to false in ClearEventData.
330 fIgnoreHelicity |= localIgnoreHelicity;
331 SetDataLoaded(kTRUE);
332 }
333 if(localdebug){
334 Print();
335 }
336 return;
337}
338
340{
341 Bool_t complete_and_good = kFALSE;
342 if (NextPairIsComplete()){
343 CalculatePairAsymmetry(); /* Uses the same calculational variables as the pattern */
344 complete_and_good = fPairIsGood;
345 }
346 return complete_and_good;
347};
348
350{
351 Bool_t filled=kFALSE;
352 // Potentially this function could check all possible pairs to see which are complete, if the initial
353 // fNextPair is not complete. The function must end with fNextPair equal to the index of the lowest pair
354 // that is complete.
355 if (fNextPair<fPatternSize/2){
356 size_t firstevt = fNextPair*2;
357 size_t secondevt = firstevt + 1;
358 filled = fEventLoaded.at(firstevt) && fEventLoaded.at(secondevt);
359 }
360 return (filled);
361}
362
364{
365
366 Bool_t localdebug=kFALSE;
367
368 if(localdebug) std::cout<<"Entering QwHelicityPattern::CalculateAsymmetry \n";
369
370 Int_t plushel = 1;
371 Int_t minushel = 0;
372 [[maybe_unused]]
373 Int_t checkhel = 0;
374
375 if (fNextPair<fPatternSize/2){
376 size_t firstevt = fNextPair*2;
377 size_t secondevt = firstevt + 1;
378 fPairIsGood = kTRUE;
379 fNextPair++;
380
381 fPairYield.Sum(fEvents.at(firstevt), fEvents.at(secondevt));
382 fPairYield.Scale(0.5);
383
384 if (fIgnoreHelicity){
385 fPairDifference.Difference(fEvents.at(firstevt), fEvents.at(secondevt));
386 fPairDifference.Scale(0.5);
387 } else {
388 if (fHelicity[firstevt] == plushel && fHelicity[firstevt]!=fHelicity[secondevt]) {
389 fPairDifference.Difference(fEvents.at(firstevt), fEvents.at(secondevt));
390 fPairDifference.Scale(0.5);
391 } else if (fHelicity[firstevt] == minushel && fHelicity[firstevt]!=fHelicity[secondevt]) {
392 fPairDifference.Difference(fEvents.at(secondevt),fEvents.at(firstevt));
393 fPairDifference.Scale(0.5);
394 } else if (fHelicity[firstevt] == -9999 || fHelicity[secondevt]==-9999) {
395 checkhel= -9999;
396 // Helicity polarity is undefined.
397 QwDebug<<" QwHelicityPattern::CalculatePairAsymmetry == \n"
398 <<" undefined local helicity (-9999) \n"
399 <<" impossible to compute asymmetry \n"
400 <<" dropping every thing -- pattern number ="<<fCurrentPatternNumber<<QwLog::endl;
401 // This is an unknown helicity event.
402 fPairIsGood = kFALSE;
403 }else {
404 QwDebug << "QwHelicityPattern::CalculatePairAsymmetry: "
405 << "Helicity should be "<<plushel<<" or "<<minushel
406 <<" but is "<< fHelicity[firstevt] << " and " << fHelicity[secondevt]
407 << "; Asymmetry computation aborted!"<<QwLog::endl;
408 fPairIsGood = kFALSE;
409 // there is a different number of plus and minus helicity window.
410 QwError<<" QwHelicityPattern::CalculatePairAsymmetry == \n"
411 <<" you do not have the same number of positive and negative \n"
412 <<" impossible to compute asymmetry \n"
413 <<" dropping every thing -- pattern number ="<<fCurrentPatternNumber<<QwLog::endl;
414 // This is an unknown helicity event.
415 }
416 }
417 }
418
419 if (fPairIsGood){
420 if (! fIgnoreHelicity){
421 // // Update the blinder if conditions have changed
423 // Only blind the difference if we're using the real helicity.
425 // Update the global error code in fDifference, and use it
426 // to update the errors in fYield, in case blinder errors
427 // can propagate to the global error.
428 fPairDifference.UpdateErrorFlag();
429 fPairYield.UpdateErrorFlag(fPairDifference);
430 if (! fBlinder.IsBlinderOkay()){
433 }
434 }
436 fPairAsymmetry.IncrementErrorCounters();
437 }
438}
439
440
442{
443 Bool_t complete_and_good = kFALSE;
444 if (IsCompletePattern()){
446 complete_and_good = fPatternIsGood;
447 }
448 return complete_and_good;
449};
450
451//*****************************************************************
452/**
453 * Check to see if the pattern is complete.
454 */
456{
457 Bool_t localdebug=kFALSE;
458 Bool_t filled=kTRUE;
459 Int_t i=fPatternSize-1;
460 while(filled && i>-1)
461 {
462 if (localdebug){
463 std::cout<<" i="<<i<<" is loaded ?"
464 <<fEventLoaded[fEvents.size()-i-1]<<"\n";
465 }
466 if(!fEventLoaded[i])
467 filled=kFALSE;
468 i--;
469 }
470
471
472
473 return filled;
474}
475
476
477//*****************************************************************
478/**
479 * Calculate asymmetries for the current pattern.
480 */
482{
483
484 Bool_t localdebug=kFALSE;
485
486 if(localdebug) std::cout<<"Entering QwHelicityPattern::CalculateAsymmetry \n";
487
488 Int_t plushel = 1;
489 Int_t minushel = 0;
490 Int_t checkhel = 0;
491 Bool_t firstplushel=kTRUE;
492 Bool_t firstminushel=kTRUE;
493
494 fPositiveHelicitySum.ClearEventData();
495 fNegativeHelicitySum.ClearEventData();
496
497 if (fIgnoreHelicity){
498 // Don't check to see if we have equal numbers of even and odd helicity states in this pattern.
499 // Build an asymmetry with even-parity phases as "+" and odd-parity phases as "-"
500 for (size_t i = 0; i < fPatternSize; i++) {
501 Int_t localhel = 1;
502 for (size_t j = 0; j < fPatternSize/2; j++) {
503 localhel ^= ((i >> j)&0x1);
504 }
505 if (localhel == plushel) {
506 if (firstplushel) {
508 firstplushel = kFALSE;
509 } else {
511 }
512 } else if (localhel == minushel) {
513 if (firstminushel) {
515 firstminushel = kFALSE;
516 } else {
518 }
519 }
520 }
521 } else {
522 //
523 for (size_t i = 0; i < fPatternSize; i++) {
524 if (fHelicity[i] == plushel) {
525 if (localdebug) std::cout<<"QwHelicityPattern::CalculateAsymmetry: here filling fPositiveHelicitySum \n";
526 if (firstplushel) {
527 if (localdebug) std::cout<<"QwHelicityPattern::CalculateAsymmetry: with = \n";
529 firstplushel = kFALSE;
530 } else {
531 if (localdebug) std::cout<<"QwHelicityPattern::CalculateAsymmetry: with += \n";
533 }
534 checkhel += 1;
535 } else if (fHelicity[i] == minushel) {
536 if (localdebug) std::cout<<"QwHelicityPattern::CalculateAsymmetry: here filling fNegativeHelicitySum \n";
537 if (firstminushel) {
538 if (localdebug) std::cout<<"QwHelicityPattern::CalculateAsymmetry: with = \n";
540 firstminushel = kFALSE;
541 } else {
542 if (localdebug) std::cout<<"QwHelicityPattern::CalculateAsymmetry: with += \n";
544 }
545 checkhel -= 1;
546 } else {
547 QwDebug << "QwHelicityPattern::CalculateAsymmetry: "
548 << "Helicity should be "<<plushel<<" or "<<minushel
549 <<" but is "<< fHelicity[i]
550 << "; Asymmetry computation aborted!"<<QwLog::endl;
552 checkhel = -9999;
553 break;
554 // This is an unknown helicity event.
555 }
556 }
557 }
558
559 if (checkhel == -9999) {
560 //do nothing the asymmetry computation has been aborted earlier in this function
561 fPatternIsGood = kFALSE;
562 } else if (checkhel!=0) {
563 fPatternIsGood = kFALSE;
564 // there is a different number of plus and minus helicity window.
565 QwError<<" QwHelicityPattern::CalculateAsymmetry == \n"
566 <<" you do not have the same number of positive and negative \n"
567 <<" impossible to compute asymmetry \n"
568 <<" dropping every thing -- pattern number ="<<fCurrentPatternNumber<<QwLog::endl;
569 } else {
570 // This is a good pattern.
571 // Calculate the asymmetry.
572 fPatternIsGood = kTRUE;
573 fQuartetNumber++;//Then increment the quartet number
574 //std::cout<<" quartet count ="<<fQuartetNumber<<"\n";
575
577 fYield.Scale(1.0/fPatternSize);
579 fDifference.Scale(1.0/fPatternSize);
580
581
582
583 if (! fIgnoreHelicity){
584 // Update the blinder if conditions have changed
586 // Only blind the difference if we're using the real helicity.
588 // Update the global error code in fDifference, and use it
589 // to update the errors in fYield, in case blinder errors
590 // can propagate to the global error.
591 fDifference.UpdateErrorFlag();
592 fYield.UpdateErrorFlag(fDifference);
593 if (! fBlinder.IsBlinderOkay()){
596 }
597 }
599 fAsymmetry.IncrementErrorCounters();
600
601 /*
602 With additional two asymmetry calculations
603 Don't blind them!
604
605 quartet pattern + - - +
606 1 2 3 4
607 fAsymmetry = (1+4)-(2+3)/(1+2+3+4)
608 fAsymmetry1 = (1+2)-(3+4)/(1+2+3+4)
609 fAsymmetry2 = (1+3)-(2+4)/(1+2+3+4)
610 */
612 // fAsymmetry1: (first 1/2 pattern - second 1/2 pattern)/fYield
613 fPositiveHelicitySum.ClearEventData();
614 fNegativeHelicitySum.ClearEventData();
617 if (fPatternSize/2 > 1){
618 for (size_t i = 1; i < fPatternSize/2 ; i++){
621 }
622 }
623 fAlternateDiff.ClearEventData();
625 fAlternateDiff.Scale(1.0/fPatternSize);
626 // Do not blind this helicity-uncorrelated difference.
628 // fAsymmetry2: (even events - odd events)/fYield
629 // Only build fAsymmetry2 if fPatternSize>2.
630 if (fPatternSize > 2) {
631 fPositiveHelicitySum.ClearEventData();
632 fNegativeHelicitySum.ClearEventData();
635 if (fPatternSize/2 > 1){
636 for (size_t i = 1; i < fPatternSize/2 ; i++){
637 fPositiveHelicitySum += fEvents.at(2*i);
638 fNegativeHelicitySum += fEvents.at(2*i + 1);
639 }
640 }
641 fAlternateDiff.ClearEventData();
643 fAlternateDiff.Scale(1.0/fPatternSize);
644 // Do not blind this helicity-uncorrelated difference.
646 }
647 }
648
649 if (localdebug) QwDebug << " pattern number =" << fQuartetNumber << QwLog::endl;
650 }
651}
652
653//*****************************************************************
654/**
655 * Clear event data and the vectors used for the calculation of.
656 * yields and asymmetries.
657 */
659{
660 fIgnoreHelicity = kFALSE;
661 for(size_t i=0; i<fEvents.size(); i++)
662 {
663 fEvents[i].ClearEventData();
664 fEventLoaded[i]=kFALSE;
665 fHelicity[i]=-999;
666 }
667 fBlinder.ClearEventData();
668
669 // Primary yield and asymmetry
670 fYield.ClearEventData();
671 fAsymmetry.ClearEventData();
672 // Alternate asymmetries
674 fAsymmetry1.ClearEventData();
675 fAsymmetry2.ClearEventData();
676 }
677
678 fPositiveHelicitySum.ClearEventData();
679 fNegativeHelicitySum.ClearEventData();
680 fDifference.ClearEventData();
681 fAlternateDiff.ClearEventData();
682
683 fPairIsGood = kFALSE;
684 fNextPair = 0;
685
686
687 fGoodPatterns = 0;
688 fPatternIsGood = kFALSE;
689 SetDataLoaded(kFALSE);
690}
691
692
693//*****************************************************************
694/**
695 * Accumulate the running sum by adding this helicity pattern to the
696 * running sums of yield, difference and asymmetry.
697 */
698void QwHelicityPattern::AccumulateRunningSum(QwHelicityPattern &entry, Int_t count, Int_t ErrorMask)
699{
700 if (entry.fPatternIsGood){
701 // if ( (*(entry.fAsymmetry.GetEventcutErrorFlagPointer()) & ErrorMask) == 0 ) {
702 if (entry.fAsymmetry.GetEventcutErrorFlag()==0){
704 }
706 fYield.AccumulateRunningSum(entry.fYield, count, ErrorMask);
707 fAsymmetry.AccumulateRunningSum(entry.fAsymmetry, count, ErrorMask);
709 fDifference.AccumulateRunningSum(entry.fDifference, count, ErrorMask);
710 // The difference is blinded, so the running difference is also blinded.
711 }
713 fAsymmetry1.AccumulateRunningSum(entry.fAsymmetry1, count, ErrorMask);
714 fAsymmetry2.AccumulateRunningSum(entry.fAsymmetry2, count, ErrorMask);
715 }
717 }
718}
719
720
721//*****************************************************************
722/**
723 * Accumulate the running sum for pairs by adding this helicity pattern to the
724 * running sums of yield, difference and asymmetry.
725 */
727{
728 if (entry.fPairIsGood){
729 fPairYield.AccumulateRunningSum(entry.fPairYield);
730 fPairAsymmetry.AccumulateRunningSum(entry.fPairAsymmetry);
732 fPairDifference.AccumulateRunningSum(entry.fPairDifference);
733 // The difference is blinded, so the running difference is also blinded.
734 }
735 fPairIsGood = entry.fPairIsGood;
736 }
737}
738
739
740//*****************************************************************
742{
743 fAsymmetry.CalculateRunningAverage();
745 fDifference.CalculateRunningAverage();
746 }
747 fYield.CalculateRunningAverage();
749 fAsymmetry1.CalculateRunningAverage();
750 fAsymmetry2.CalculateRunningAverage();
751 }
752 if (fEnablePairs) {
753 // Pair averages
754 fPairYield.CalculateRunningAverage();
755 fPairAsymmetry.CalculateRunningAverage();
757 fPairDifference.CalculateRunningAverage();
758 }
759 }
760}
761
762
763//*****************************************************************
765{
766 // Pattern
767 QwMessage << " Pattern yields " << QwLog::endl;
768 QwMessage << " ==============================" << QwLog::endl;
769 fYield.PrintValue();
770 QwMessage << " Pattern asymmetry " << QwLog::endl;
771 QwMessage << " ==============================" << QwLog::endl;
772 fAsymmetry.PrintValue();
774 QwMessage << " First/second half asymmetry " << QwLog::endl;
775 QwMessage << " ==============================" << QwLog::endl;
776 fAsymmetry1.PrintValue();
777 QwMessage << " Even/odd asymmetry " << QwLog::endl;
778 QwMessage << " ==============================" << QwLog::endl;
779 fAsymmetry2.PrintValue();
780 }
782 QwMessage << " Pattern difference " << QwLog::endl;
783 QwMessage << " ==============================" << QwLog::endl;
784 fDifference.PrintValue();
785 }
786 if (fEnablePairs){
787 QwMessage << " Pair yield " << QwLog::endl;
788 QwMessage << " ==============================" << QwLog::endl;
789 fPairYield.PrintValue();
790 QwMessage << " Pair asymmetry " << QwLog::endl;
791 QwMessage << " ==============================" << QwLog::endl;
792 fPairAsymmetry.PrintValue();
793 if (fEnableDifference) {
794 QwMessage << " Pair difference " << QwLog::endl;
795 QwMessage << " ==============================" << QwLog::endl;
796 fPairDifference.PrintValue();
797 }
798 }
799}
800
801//*****************************************************************
803{
804 TString prefix = "blinder_";
805 fBlinder.ConstructObjects(folder,prefix);
806
807 prefix = "yield_";
808 fYield.ConstructObjects(folder,prefix);
809 prefix = "asym_";
810 fAsymmetry.ConstructObjects(folder,prefix);
811
812 if (fEnableDifference) {
813 prefix = "diff_";
814 fDifference.ConstructObjects(folder,prefix);
815 }
817 prefix = "asym1_";
818 fAsymmetry1.ConstructObjects(folder,prefix);
819 prefix = "asym2_";
820 fAsymmetry2.ConstructObjects(folder,prefix);
821 }
822}
823
824//*****************************************************************
826{
827 TString prefix = "yield_";
828 fYield.ConstructHistograms(folder,prefix);
829 prefix = "asym_";
830 fAsymmetry.ConstructHistograms(folder,prefix);
831
832 if (fEnableDifference) {
833 prefix = "diff_";
834 fDifference.ConstructHistograms(folder,prefix);
835 }
837 prefix = "asym1_";
838 fAsymmetry1.ConstructHistograms(folder,prefix);
839 prefix = "asym2_";
840 fAsymmetry2.ConstructHistograms(folder,prefix);
841 }
842}
843
845{
846 if (fPatternIsGood) {
847 fYield.FillHistograms();
848 fAsymmetry.FillHistograms();
849 if (fEnableDifference) {
850 fDifference.FillHistograms();
851 }
853 fAsymmetry1.FillHistograms();
854 fAsymmetry2.FillHistograms();
855 }
856 } else {
857 }
858}
859
860void QwHelicityPattern::ConstructBranchAndVector(TTree *tree, TString & prefix, QwRootTreeBranchVector &values)
861{
862TString basename = prefix(0, (prefix.First("|") >= 0)? prefix.First("|"): prefix.Length())+"BurstCounter";
863 tree->Branch(basename,&fBurstCounter,basename+"/S");
864 TString newprefix = "yield_" + prefix;
865 fYield.ConstructBranchAndVector(tree, newprefix, values);
866 newprefix = "asym_" + prefix;
867 fAsymmetry.ConstructBranchAndVector(tree, newprefix, values);
868
869 if (fEnableDifference) {
870 newprefix = "diff_" + prefix;
871 fDifference.ConstructBranchAndVector(tree, newprefix, values);
872 }
874 newprefix = "asym1_" + prefix;
875 fAsymmetry1.ConstructBranchAndVector(tree, newprefix, values);
876 newprefix = "asym2_" + prefix;
877 fAsymmetry2.ConstructBranchAndVector(tree, newprefix, values);
878 }
879}
880
881void QwHelicityPattern::ConstructBranch(TTree *tree, TString & prefix)
882{
883 TString basename = prefix(0, (prefix.First("|") >= 0)? prefix.First("|"): prefix.Length())+"BurstCounter";
884 tree->Branch(basename,&fBurstCounter,basename+"/S");
885
886 TString newprefix = "yield_" + prefix;
887 fYield.ConstructBranch(tree, newprefix);
888 newprefix = "asym_" + prefix;
889 fAsymmetry.ConstructBranch(tree, newprefix);
890
891 if (fEnableDifference) {
892 newprefix = "diff_" + prefix;
893 fDifference.ConstructBranch(tree, newprefix);
894 }
896 newprefix = "asym1_" + prefix;
897 fAsymmetry1.ConstructBranch(tree, newprefix);
898 newprefix = "asym2_" + prefix;
899 fAsymmetry2.ConstructBranch(tree, newprefix);
900 }
901}
902
903void QwHelicityPattern::ConstructBranch(TTree *tree, TString & prefix, QwParameterFile &trim_tree)
904{
905 TString basename = prefix(0, (prefix.First("|") >= 0)? prefix.First("|"): prefix.Length())+"BurstCounter";
906 tree->Branch(basename,&fBurstCounter,basename+"/S");
907 TString newprefix = "yield_" + prefix;
908 fYield.ConstructBranch(tree, newprefix, trim_tree);
909 newprefix = "asym_" + prefix;
910 fAsymmetry.ConstructBranch(tree, newprefix, trim_tree);
911
912 if (fEnableDifference) {
913 newprefix = "diff_" + prefix;
914 fDifference.ConstructBranch(tree, newprefix);
915 }
917 newprefix = "asym1_" + prefix;
918 fAsymmetry1.ConstructBranch(tree, newprefix, trim_tree);
919 newprefix = "asym2_" + prefix;
920 fAsymmetry2.ConstructBranch(tree, newprefix, trim_tree);
921 }
922}
923
925{
926 if (fPatternIsGood) {
927 fYield.FillTreeVector(values);
928 fAsymmetry.FillTreeVector(values);
929 if (fEnableDifference) {
930 fDifference.FillTreeVector(values);
931 }
933 fAsymmetry1.FillTreeVector(values);
934 fAsymmetry2.FillTreeVector(values);
935 }
936 }
937}
938
939#ifdef HAS_RNTUPLE_SUPPORT
940void QwHelicityPattern::ConstructNTupleAndVector(std::unique_ptr<ROOT::RNTupleModel>& model, TString& prefix, std::vector<Double_t>& values, std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
941{
942 TString basename = prefix(0, (prefix.First("|") >= 0)? prefix.First("|"): prefix.Length())+"BurstCounter";
943 // Note: fBurstCounter is a Short_t, but we're only creating Double_t fields for now
944 // This maintains compatibility with the existing TTree structure
945
946 TString newprefix = "yield_" + prefix;
947 fYield.ConstructNTupleAndVector(model, newprefix, values, fieldPtrs);
948 newprefix = "asym_" + prefix;
949 fAsymmetry.ConstructNTupleAndVector(model, newprefix, values, fieldPtrs);
950
951 if (fEnableDifference) {
952 newprefix = "diff_" + prefix;
953 fDifference.ConstructNTupleAndVector(model, newprefix, values, fieldPtrs);
954 }
956 newprefix = "asym1_" + prefix;
957 fAsymmetry1.ConstructNTupleAndVector(model, newprefix, values, fieldPtrs);
958 newprefix = "asym2_" + prefix;
959 fAsymmetry2.ConstructNTupleAndVector(model, newprefix, values, fieldPtrs);
960 }
961}
962
963void QwHelicityPattern::FillNTupleVector(std::vector<Double_t>& values) const
964{
965 if (fPatternIsGood) {
966 fYield.FillNTupleVector(values);
967 fAsymmetry.FillNTupleVector(values);
968 if (fEnableDifference) {
969 fDifference.FillNTupleVector(values);
970 }
972 fAsymmetry1.FillNTupleVector(values);
973 fAsymmetry2.FillNTupleVector(values);
974 }
975 }
976}
977#endif // HAS_RNTUPLE_SUPPORT
978
979#ifdef __USE_DATABASE__
980void QwHelicityPattern::FillDB(QwParityDB *db)
981{
982 fBlinder.FillDB(db,"");
983
984 fYield.FillDB(db, "yield");
985 fAsymmetry.FillDB(db, "asymmetry");
986 if (fEnableDifference) {
987 fDifference.FillDB(db, "difference");
988 }
990 fAsymmetry1.FillDB(db, "asymmetry1");
991 fAsymmetry2.FillDB(db, "asymmetry2");
992 }
993}
994
995void QwHelicityPattern::FillErrDB(QwParityDB *db)
996{
997 fBlinder.FillErrDB(db,"");
998 fAsymmetry.FillErrDB(db, "");
999};
1000#endif // __USE_DATABASE__
1001
1003{
1005 fYield.WritePromptSummary(ps, "yield");
1006 fAsymmetry.WritePromptSummary(ps, "asymmetry");
1007 return;
1008};
1009
1010
1011//*****************************************************************
1012
1014{
1015 QwOut << "Pattern number = " << fCurrentPatternNumber << QwLog::endl;
1016 for (size_t i = 0; i < fPatternSize; i++)
1017 QwOut << "Event " << fEventNumber[i] << ": "
1018 << fEventLoaded[i] << ", " << fHelicity[i] << QwLog::endl;
1019 QwOut << "Is a complete pattern? (n/y:0/1) " << IsCompletePattern() << QwLog::endl;
1020}
1021
1022
1023
1024
Helper functions and utilities for ROOT histogram management.
A logfile class, based on an identical class in the Hermes analyzer.
#define QwOut
Predefined log drain for explicit output.
Definition QwLog.h:34
#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
Definition of the pure virtual base class of all data elements.
Prompt summary data management.
Helicity state management and pattern recognition.
A class for blinding data, adapted from G0 blinder class.
Helicity pattern analysis 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
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.
void SetPatternSize(const Int_t in)
A helper class to manage a vector of branch entries for ROOT trees.
Definition QwRootFile.h:53
Bool_t HasDataLoaded() const
static void DefineOptions(QwOptions &options)
Definition QwBlinder.cc:69
static const UInt_t kErrorFlag_BlinderFail
Error flag value.
Definition QwBlinder.h:78
Subsystem for helicity state management and pattern recognition.
Definition QwHelicity.h:52
Int_t GetMinPatternPhase()
Definition QwHelicity.h:122
Int_t GetPhaseNumber()
Bool_t IsHelicityIgnored()
Definition QwHelicity.h:166
Long_t GetPatternNumber()
Long_t GetEventNumber()
Int_t GetHelicityActual()
QwSubsystemArrayParity fAlternateDiff
void ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values)
void ConstructBranch(TTree *tree, TString &prefix)
QwSubsystemArrayParity fNegativeHelicitySum
QwSubsystemArrayParity fPairDifference
std::vector< Bool_t > fEventLoaded
QwHelicityPattern()
Private default constructor (not implemented, will throw linker error on use)
static void DefineOptions(QwOptions &options)
Define the configuration options.
QwSubsystemArrayParity fDifference
QwSubsystemArrayParity fPairYield
void UpdateBlinder()
Update the blinder status using a random number generator.
std::vector< QwSubsystemArrayParity > fEvents
void ProcessOptions(QwOptions &options)
Process the configuration options.
Bool_t IsCompletePattern() const
void DisableBurstSum()
Disable burst sum calculation.
std::vector< Int_t > fHelicity
void AccumulatePairRunningSum(QwHelicityPattern &entry)
std::vector< Int_t > fEventNumber
void SetDataLoaded(Bool_t flag)
void WritePromptSummary(QwPromptSummary *ps)
QwSubsystemArrayParity fAsymmetry1
void FillTreeVector(QwRootTreeBranchVector &values) const
QwSubsystemArrayParity fPositiveHelicitySum
void LoadEventData(QwSubsystemArrayParity &event)
void AccumulateRunningSum(QwHelicityPattern &entry, Int_t count=0, Int_t ErrorMask=0xFFFFFFF)
QwSubsystemArrayParity fYield
QwSubsystemArrayParity fAsymmetry
QwSubsystemArrayParity fPairAsymmetry
QwSubsystemArrayParity fAsymmetry2
Subsystem array container specialized for parity analysis with asymmetry calculations.
UInt_t GetEventcutErrorFlag() const
Return the error flag to the main routine.