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