JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwHelicityBase.cc
Go to the documentation of this file.
1/**********************************************************\
2* File: QwHelicityBase.C *
3* *
4* Author: Arindam Sen (asen@jlab.org) *
5* Time-stamp: November, 2025 *
6\**********************************************************/
7
8#include "QwHelicityBase.h"
9
10// System headers
11#include <stdexcept>
12
13// ROOT headers
14#include "TRegexp.h"
15#include "TMath.h"
16
17#ifdef HAS_RNTUPLE_SUPPORT
18#include "ROOT/RNTupleModel.hxx"
19#include "ROOT/RNTupleWriter.hxx"
20#include "ROOT/RField.hxx"
21#endif // HAS_RNTUPLE_SUPPORT
22
23// Qweak headers
24#include "QwHistogramHelper.h"
25#include "QwRootFile.h"
26#include "QwLog.h"
27#ifdef __USE_DATABASE__
28#include "QwParitySchema.h"
29#include "QwParityDB.h"
30#endif // __USE_DATABASE__
31
33//**************************************************//
34/// Default helicity bit pattern of 0x69 represents a -++-+--+ octet
35/// (event polarity listed in reverse time order), where the LSB
36/// of the bit pattern is the first event of the pattern.
37const std::vector<UInt_t> QwHelicityBase::kDefaultHelicityBitPattern{0x69};
38
39//**************************************************//
40/// Constructor with name
42: VQwSubsystem(name),
49{
51 // Default helicity delay to two patterns.
53 // Default the EventType flags to HelPlus=1 and HelMinus=4
54 // These are only used in Moller decoding mode.
57 //
61 kUserbit=-1;
67 fHelicityBitPlus=kFALSE;
68 fHelicityBitMinus=kFALSE;
69 n_ranbits = 0;
70 fGoodHelicity=kFALSE;
71 fGoodPattern=kFALSE;
73
74// fInputReg_FakeMPS = kDefaultInputReg_FakeMPS;
75}
76
77//**************************************************//
78/// Copy constructor
79// FIXME this is pretty horrible as a copy constructor, but it gets around
80// all of the copy protection built into the helicity subsystem. I can't be
81// bothered to clean it up right now... (wdc)
83: VQwSubsystem(source.GetName()),
91{
94 // Default helicity delay to two patterns.
96 // Default the EventType flags to HelPlus=1 and HelMinus=4
97 // These are only used in Moller decoding mode.
100 //
104 kUserbit=-1;
110 fHelicityBitPlus=kFALSE;
111 fHelicityBitMinus=kFALSE;
112 fGoodHelicity=kFALSE;
113 fGoodPattern=kFALSE;
115
116 this->fWord.resize(source.fWord.size());
117 for(size_t i=0;i<this->fWord.size();i++)
118 {
119 this->fWord[i].fWordName=source.fWord[i].fWordName;
120 this->fWord[i].fModuleType=source.fWord[i].fModuleType;
121 this->fWord[i].fWordType=source.fWord[i].fWordType;
122 }
129 fEventType = source.fEventType;
131 fRandBits = source.fRandBits;
139 iseed_Actual = source.iseed_Actual;
140 n_ranbits = source.n_ranbits;
141 fEventNumber = source.fEventNumber;
147
148 this->kUserbit = source.kUserbit;
149 this->fIgnoreHelicity = source.fIgnoreHelicity;
150}
151
152//**************************************************//
154{
155 options.AddOptions("Helicity options")
156 ("helicity.seed", po::value<int>(),
157 "Number of bits in random seed");
158 options.AddOptions("Helicity options")
159 ("helicity.bitpattern", po::value<std::string>(),
160 "Helicity bit pattern: 0x1 (pair), 0x9 (quartet), 0x69 (octet), 0x666999 (hexo-quad), 0x66669999 (octo-quad)");
161 options.AddOptions("Helicity options")
162 ("helicity.patternoffset", po::value<int>(),
163 "Set 1 when pattern starts with 1 or 0 when starts with 0");
164 options.AddOptions("Helicity options")
165 ("helicity.patternphase", po::value<int>(),
166 "Maximum pattern phase");
167 options.AddOptions("Helicity options")
168 ("helicity.delay", po::value<int>(),
169 "Default delay is 2 patterns, set at the helicity map file.");
170 options.AddOptions("Helicity options")
171 ("helicity.toggle-mode", po::value<bool>()->default_bool_value(false),
172 "Activates helicity toggle-mode, overriding the 'delay', 'patternphase', 'bitpattern', and 'seed' options.");
173}
174
175//**************************************************//
176
178{
179 // Read the cmd options and override channel map settings
180 QwMessage << "QwHelicityBase::ProcessOptions" << QwLog::endl;
181 if (options.HasValue("helicity.patternoffset")) {
182 if (options.GetValue<int>("helicity.patternoffset") == 1
183 || options.GetValue<int>("helicity.patternoffset") == 0) {
184 fPatternPhaseOffset = options.GetValue<int>("helicity.patternoffset");
185 QwMessage << " Pattern Phase Offset = " << fPatternPhaseOffset << QwLog::endl;
186 } else QwError << "Pattern phase offset should be 0 or 1!" << QwLog::endl;
187 }
188
189 if (options.HasValue("helicity.patternphase")) {
190 if (options.GetValue<int>("helicity.patternphase") % 2 == 0) {
191 fMaxPatternPhase = options.GetValue<int>("helicity.patternphase");
192 QwMessage << " Maximum Pattern Phase = " << fMaxPatternPhase << QwLog::endl;
193 } else QwError << "Pattern phase should be an even integer!" << QwLog::endl;
194 }
195
196 if (options.HasValue("helicity.seed")) {
197 if (options.GetValue<int>("helicity.seed") == 24
198 || options.GetValue<int>("helicity.seed") == 30) {
199 QwMessage << " Random Bits = " << options.GetValue<int>("helicity.seed") << QwLog::endl;
200 fRandBits = options.GetValue<int>("helicity.seed");
201 } else QwError << "Number of random seed bits should be 24 or 30!" << QwLog::endl;
202 }
203
204 if (options.HasValue("helicity.delay")) {
205 QwMessage << " Helicity Delay = " << options.GetValue<int>("helicity.delay") << QwLog::endl;
206 SetHelicityDelay(options.GetValue<int>("helicity.delay"));
207 }
208
209 if (options.HasValue("helicity.bitpattern")) {
210 QwMessage << " Helicity Pattern ="
211 << options.GetValue<std::string>("helicity.bitpattern")
212 << QwLog::endl;
213 std::string hex = options.GetValue<std::string>("helicity.bitpattern");
214 //UInt_t bits = QwParameterFile::GetUInt(hex);
216 } else {
218 }
219
220 if (options.GetValue<bool>("helicity.toggle-mode")) {
221 fHelicityDelay = 0;
222 fUsePredictor = kFALSE;
225 }
226
227 // If we have the default Helicity Bit Pattern & a large fMaxPatternPhase,
228 // try to recompute the Helicity Bit Pattern.
231 }
232
233 // Here we're going to try to get the "online" option which
234 // is defined by QwEventBuffer.
235 if (options.HasValue("online")){
236 fSuppressMPSErrorMsgs = options.GetValue<bool>("online");
237 } else {
238 fSuppressMPSErrorMsgs = kFALSE;
239 }
240}
241
242
244{
245 Bool_t results=kFALSE;
247 results=kTRUE;
248 } else {
249 // Results is already false, so just set the error flag value.
251 }
252 return results;
253}
254
255
257{
258 Bool_t results;
259
260 if((fPatternNumber == fPatternNumberOld) && (fPatternPhaseNumber == fPatternPhaseNumberOld+1))//same pattern new phase
261 results = kTRUE; //got same pattern
263 results=kTRUE; //new pattern
264 else results=kFALSE; //wrong pattern
265
266 if(!results) {
267 QwWarning << "QwHelicityBase::IsGoodPatternNumber: This is not a good pattern number. New = "<< fPatternNumber << " Old = " << fPatternNumberOld << QwLog::endl;
268 //Print();
269 }
270
271 return results;
272}
273
274
276{
277 Bool_t results;
279 results= kTRUE;
280 else
281 results= kFALSE;
282
283 if(!results) {
284 QwWarning << "QwHelicityBase::IsGoodEventNumber: \n this is not a good event number indeed:" << QwLog::endl;
285 Print();
286 }
287 return results;
288}
289
290
292{
293 Bool_t results;
294
295 if((fPatternPhaseNumber == fMaxPatternPhase) && (fPatternNumber == fPatternNumberOld )) //maximum phase of old pattern
296 results = kTRUE;
298 results = kTRUE;
300 results= kTRUE;
301 else
302 results = kFALSE;
303
305 results=kFALSE;
306
307 if(!results) {
308 QwWarning << "QwHelicityBase::IsGoodPhaseNumber: not a good phase number \t"
309 << "Phase: " << fPatternPhaseNumber << " out of "
311 << "(was " << fPatternPhaseNumberOld << ")"
312 << "\tPattern #" << fPatternNumber << "(was "
313 << fPatternNumberOld << ")"
314 << QwLog::endl; //Paul's modifications
315 Print();
316 }
317
318 return results;
319}
320
321
323{
324 fGoodHelicity = kTRUE;
326 /**We are not ignoring the helicity, and the helicities do not match.
327 Check phase number to see if its a new pattern.*/
328 fGoodHelicity=kFALSE;
332 //first event in a new pattern
333 QwError << "QwHelicityBase::IsGoodHelicity : The helicity reported in event "
334 << fEventNumber
335 << " is not what we expect from the randomseed. Not a good event nor pattern"
336 << QwLog::endl;
337 } else {
338 QwError << "QwHelicityBase::IsGoodHelicity - The helicity reported in event "
339 << fEventNumber
340 << " is not what we expect according to pattern structure. Not a good event nor pattern"
341 << QwLog::endl;
342 }
343 }
344 if(!fGoodHelicity) {
348 //Have to start over again
350 }
351
352 return fGoodHelicity;
353}
354
355
357{
358 SetDataLoaded(kFALSE);
359 for (size_t i=0;i<fWord.size();i++)
361
362 /**Reset data by setting the old event number, pattern number and pattern phase
363 to the values of the previous event.*/
364 if (fEventNumberFirst==-1 && fEventNumberOld!= -1){
366 }
370 }
371
375
376 //fIgnoreHelicity = kFALSE;
377
378 /**Clear out helicity variables */
382 fHelicityBitPlus = kFALSE;
383 fHelicityBitMinus = kFALSE;
384 // be careful: it is not that I forgot to reset fActualPatternPolarity
385 // or fDelayedPatternPolarity. One doesn't want to do that here.
386 /** Set the new event number and pattern number to -1. If we are not reading these correctly
387 from the data stream, -1 will allow us to identify that.*/
388 fEventNumber = -1;
390 fPatternNumber = -1;
391 return;
392}
393
394Int_t QwHelicityBase::ProcessConfigurationBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t* buffer, UInt_t num_words)
395{
396 //stub function
397 // QwError << " this function QwHelicityBase::ProcessConfigurationBuffer does nothing yet " << QwLog::endl;
398 return 0;
399}
400
401Int_t QwHelicityBase::LoadInputParameters(TString pedestalfile)
402{
403 return 0;
404}
405
406
408 //impose single event cuts //Paul's modifications
409
410 return kTRUE;
411}
412
414{
415 /// TODO: Implement QwHelicityBase::IncrementErrorCounters()
416}
417
419 // report number of events failed due to HW and event cut faliure
420 QwMessage << "\n*********QwHelicityBase Error Summary****************"
421 << QwLog::endl;
422 QwMessage << "First helicity gate counter: "
424 << "; last helicity gate counter: "
425 << fEventNumber
426 << QwLog::endl;
427 QwMessage << "First pattern counter: "
429 << "; last pattern counter: "
431 << QwLog::endl;
432 QwMessage << "Missed " << fNumMissedGates << " helicity gates in "
433 << fNumMissedEventBlocks << " blocks of missed events."
434 << QwLog::endl;
435 QwMessage << "Number of multiplet-sync-bit errors: "
437 << QwLog::endl;
438 QwMessage << "Number of helicity prediction errors: "
440 << QwLog::endl;
441 QwMessage <<"---------------------------------------------------\n"
442 << QwLog::endl;
443}
444
445UInt_t QwHelicityBase::GetEventcutErrorFlag(){//return the error flag
446 return fErrorFlag;
447}
448
450{
451 QwOut << "===========================\n"
452 << "This event: Event#, Pattern#, PatternPhase#="
453 << fEventNumber << ", "
454 << fPatternNumber << ", "
456 QwOut << "Previous event: Event#, Pattern#, PatternPhase#="
457 << fEventNumberOld << ", "
458 << fPatternNumberOld << ", "
460 QwOut << "delta = \n(fEventNumberOld)-(fMaxPatternPhase)x(fPatternNumberOld)-(fPatternPhaseNumberOld)= "
462 QwOut << "Helicity Reported, Delayed, Actual ="
463 << fHelicityReported << ","
464 << fHelicityDelayed << ","
466 QwOut << "===" << QwLog::endl;
467 return;
468}
469
470
471Int_t QwHelicityBase::LoadChannelMap(TString mapfile)
472{
473 Bool_t ldebug=kFALSE;
474
475 Int_t wordsofar=0;
476 Int_t bankindex=-1;
477
478 fPatternPhaseOffset=1;//Phase number offset is set to 1 by default and will be set to 0 if phase number starts from 0
479
480
481 // Default value for random seed is 30 bits
482 fRandBits = 30;
483
484
485 QwParameterFile mapstr(mapfile.Data()); //Open the file
487 mapstr.EnableGreediness();
488 mapstr.SetCommentChars("!");
489
490 UInt_t value = 0;
491 TString valuestr;
492
493 while (mapstr.ReadNextLine()){
494 RegisterRocBankMarker(mapstr);
495
496 if (mapstr.PopValue("patternphase",value)) {
497 fMaxPatternPhase=value;
499 //QwMessage << " fMaxPatternPhase " << fMaxPatternPhase << QwLog::endl;
500 }
501 if (mapstr.PopValue("patternbits",valuestr)) {
502 SetHelicityBitPattern(valuestr);
503 }
504// if (mapstr.PopValue("inputregmask_fakemps",value)) {
505// fInputReg_FakeMPS = value;
506// }
507// if (mapstr.PopValue("inputregmask_helicity",value)) {
508// fInputReg_HelPlus = value;
509// fInputReg_HelMinus = 0;
510// }
511// if (mapstr.PopValue("inputregmask_helplus",value)) {
512// fInputReg_HelPlus = value;
513// }
514// if (mapstr.PopValue("inputregmask_helminus",value)) {
515// fInputReg_HelMinus = value;
516// }
517// if (mapstr.PopValue("inputregmask_pattsync",value)) {
518// fInputReg_PatternSync = value;
519// }
520// if (mapstr.PopValue("inputregmask_pairsync",value)) {
521// fInputReg_PairSync = value;
522// }
523// if (mapstr.PopValue("fakempsbit",value)) {
524// fInputReg_FakeMPS = value;
525// QwWarning << " fInputReg_FakeMPS 0x" << std::hex << fInputReg_FakeMPS << std::dec << QwLog::endl;
526// }
527 if (mapstr.PopValue("numberpatternsdelayed",value)) {
528 SetHelicityDelay(value);
529 }
530 if (mapstr.PopValue("randseedbits",value)) {
531 if (value==24 || value==30)
532 fRandBits = value;
533 }
534 if (mapstr.PopValue("patternphaseoffset",value)) {
536 }
537 if (mapstr.PopValue("helpluseventtype",value)) {
538 kEventTypeHelPlus = value;
539 }
540 if (mapstr.PopValue("helminuseventtype",value)) {
541 kEventTypeHelMinus = value;
542 }
545 if ((bankindex+1)>0){
546 UInt_t numbanks = UInt_t(bankindex+1);
547 if (fWordsPerSubbank.size()<numbanks){
548 fWordsPerSubbank.resize(numbanks,
549 std::pair<Int_t, Int_t>(fWord.size(),fWord.size()));
550 }
551 }
552 wordsofar=0;
553 }
554 mapstr.TrimWhitespace(); // Get rid of leading and trailing spaces.
555 if (mapstr.LineIsEmpty()) continue;
556
557 // Break this line into tokens to process it.
558 TString modtype = mapstr.GetTypedNextToken<TString>(); // module type
559 Int_t modnum = mapstr.GetTypedNextToken<Int_t>(); //slot number
560 /* Int_t channum = */ mapstr.GetTypedNextToken<Int_t>(); //channel number /* unused */
561 TString dettype = mapstr.GetTypedNextToken<TString>(); //type-purpose of the detector
562 dettype.ToLower();
563 TString namech = mapstr.GetTypedNextToken<TString>(); //name of the detector
564 namech.ToLower();
565 TString keyword = mapstr.GetTypedNextToken<TString>();
566 keyword.ToLower();
567 // Notice that "namech" and "keyword" are now forced to lower-case.
568
569 if(modtype=="SKIP"){
570 if (modnum<=0) wordsofar+=1;
571 else wordsofar+=modnum;
572 } else if(modtype!="WORD"|| dettype!="helicitydata") {
573 QwError << "QwHelicityBase::LoadChannelMap: Unknown detector type: "
574 << dettype << ", the detector " << namech << " will not be decoded "
575 << QwLog::endl;
576 continue;
577 } else {
578 QwWord localword;
579 localword.fSubbankIndex=bankindex;
580 localword.fWordInSubbank=wordsofar;
581 wordsofar+=1;
582 // I assume that one data = one word here. But it is not always the case, for
583 // example the triumf adc gives 6 words per channel
584 localword.fModuleType=modtype;
585 localword.fWordName=namech;
586 localword.fWordType=dettype;
587 fWord.push_back(localword);
588 fWordsPerSubbank.at(bankindex).second = fWord.size();
589 }
590 }
591
592 if(ldebug) {
593 std::cout << "Done with Load map channel \n";
594 for(size_t i=0;i<fWord.size();i++)
595 fWord[i].PrintID();
596 std::cout << " kUserbit=" << kUserbit << "\n";
597 }
598 ldebug=kFALSE;
599
600 mapstr.Close(); // Close the file (ifstream)
601 return 0;
602}
603
604
605Int_t QwHelicityBase::LoadEventCuts(TString filename){
606 return 0;
607}
608
609Int_t QwHelicityBase::ProcessEvBuffer(UInt_t event_type, const ROCID_t roc_id, const BankID_t bank_id, UInt_t* buffer, UInt_t num_words)
610{
611 Bool_t lkDEBUG = kFALSE;
612
613 if (((0x1 << (event_type - 1)) & this->GetEventTypeMask()) == 0)
614 return 0;
615 fEventType = event_type;
616
617 Int_t index = GetSubbankIndex(roc_id,bank_id);
618 if (index >= 0 && num_words > 0) {
619 SetDataLoaded(kTRUE);
620 // We want to process this ROC. Begin loopilooping through the data.
621 QwDebug << "QwHelicityBase::ProcessEvBuffer: "
622 << "Begin processing ROC" << roc_id
623 << " and subbank " << bank_id
624 << " number of words=" << num_words << QwLog::endl;
625
626 for(Int_t i=fWordsPerSubbank.at(index).first; i<fWordsPerSubbank.at(index).second; i++) {
627 if(fWord[i].fWordInSubbank+1<= (Int_t) num_words) {
628 fWord[i].fValue=buffer[fWord[i].fWordInSubbank];
629 } else {
630 QwWarning << "QwHelicityBase::ProcessEvBuffer: There is not enough word in the buffer to read data for "
631 << fWord[i].fWordName << QwLog::endl;
632 QwWarning << "QwHelicityBase::ProcessEvBuffer: Words in this buffer:" << num_words
633 << " trying to read word number =" << fWord[i].fWordInSubbank << QwLog::endl;
634 }
635 }
636 if(lkDEBUG) {
637 QwDebug << "QwHelicityBase::ProcessEvBuffer: Done with Processing this event" << QwLog::endl;
638 for(size_t i=0;i<fWord.size();i++) {
639 std::cout << "QwHelicityBase::ProcessEvBuffer: word number = " << i << " ";
640 fWord[i].Print();
641 }
642 }
643 }
644 lkDEBUG=kFALSE;
645 return 0;
646}
647
648
653
658
663
668
670{
671 return fEventNumber;
672}
673
678
679void QwHelicityBase::SetEventPatternPhase(Int_t event, Int_t pattern, Int_t phase)
680{
681 fEventNumber = event;
682 fPatternNumber = pattern;
683 fPatternPhaseNumber = phase;
684}
685
686void QwHelicityBase::SetFirstBits(UInt_t nbits, UInt_t seed)
687{
688 // This gives the predictor a quick start
689 UShort_t firstbits[nbits];
690 for (unsigned int i = 0; i < nbits; i++) firstbits[i] = (seed >> i) & 0x1;
691 // Set delayed seed
692 iseed_Delayed = GetRandomSeed(firstbits);
693 // Progress actual seed by the helicity delay
695 for (int i = 0; i < fHelicityDelay; i++) GetRandbit(iseed_Actual);
696}
697
698void QwHelicityBase::SetHistoTreeSave(const TString &prefix)
699{
700 Ssiz_t len;
701 if (TRegexp("diff_").Index(prefix,&len) == 0
702 || TRegexp("asym[1-9]*_").Index(prefix,&len) == 0)
704 else if (TRegexp("yield_").Index(prefix,&len) == 0)
706 else
708}
709
710void QwHelicityBase::ConstructHistograms(TDirectory *folder, TString &prefix)
711{
712 SetHistoTreeSave(prefix);
713 if (folder != NULL) folder->cd();
714 TString basename;
715 size_t index=0;
716
718 {
719 //do nothing
720 }
722 {
723 fHistograms.resize(1+fWord.size(), NULL);
724 basename="pattern_polarity";
725 fHistograms[index] = gQwHists.Construct1DHist(basename);
726 index+=1;
727 for (size_t i=0; i<fWord.size(); i++){
728 basename="hel_"+fWord[i].fWordName;
729 fHistograms[index] = gQwHists.Construct1DHist(basename);
730 index+=1;
731 }
732 }
733 else if(fHistoType==kHelSaveMPS)
734 {
735 fHistograms.resize(4+fWord.size(), NULL);
736 basename=prefix+"delta_event_number";
737 fHistograms[index] = gQwHists.Construct1DHist(basename);
738 index+=1;
739 basename=prefix+"delta_pattern_number";
740 fHistograms[index] = gQwHists.Construct1DHist(basename);
741 index+=1;
742 basename=prefix+"pattern_phase";
743 fHistograms[index] = gQwHists.Construct1DHist(basename);
744 index+=1;
745 basename=prefix+"helicity";
746 fHistograms[index] = gQwHists.Construct1DHist(basename);
747 index+=1;
748 for (size_t i=0; i<fWord.size(); i++){
749 basename=prefix+fWord[i].fWordName;
750 fHistograms[index] = gQwHists.Construct1DHist(basename);
751 index+=1;
752 }
753 }
754 else
755 QwError << "QwHelicityBase::ConstructHistograms this prefix--" << prefix << "-- is not unknown:: no histo created" << QwLog::endl;
756
757 return;
758}
759
761{
762 // Bool_t localdebug=kFALSE;
763
764 size_t index=0;
766 {
767 //do nothing
768 }
770 {
771 QwDebug << "QwHelicityBase::FillHistograms helicity info " << QwLog::endl;
772 QwDebug << "QwHelicityBase::FillHistograms pattern polarity=" << fActualPatternPolarity << QwLog::endl;
773 if (fHistograms[index]!=NULL)
775 index+=1;
776
777 for (size_t i=0; i<fWord.size(); i++){
778 if (fHistograms[index]!=NULL)
779 fHistograms[index]->Fill(fWord[i].fValue);
780 index+=1;
781 QwDebug << "QwHelicityBase::FillHistograms " << fWord[i].fWordName << "=" << fWord[i].fValue << QwLog::endl;
782 }
783 }
784 else if(fHistoType==kHelSaveMPS)
785 {
786 QwDebug << "QwHelicityBase::FillHistograms mps info " << QwLog::endl;
787 if (fHistograms[index]!=NULL)
789 index+=1;
790 if (fHistograms[index]!=NULL)
792 index+=1;
793 if (fHistograms[index]!=NULL)
794 fHistograms[index]->Fill(fPatternPhaseNumber);
795 index+=1;
796 if (fHistograms[index]!=NULL)
797 fHistograms[index]->Fill(fHelicityActual);
798 index+=1;
799 for (size_t i=0; i<fWord.size(); i++){
800 if (fHistograms[index]!=NULL)
801 fHistograms[index]->Fill(fWord[i].fValue);
802 index+=1;
803 QwDebug << "QwHelicityBase::FillHistograms " << fWord[i].fWordName << "=" << fWord[i].fValue << QwLog::endl;
804 }
805 }
806
807 return;
808}
809
810void QwHelicityBase::ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values)
811{
812 SetHistoTreeSave(prefix);
813 fTreeArrayIndex = values.size();
814 TString basename;
816 {
817 //do nothing
818 }
819 else if(fHistoType==kHelSaveMPS)
820 {
821 // basename = "actual_helicity"; //predicted actual helicity before being delayed.
822 // values.push_back(basename, 'I');
823 // tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
824 //
825 basename = "delayed_helicity"; //predicted delayed helicity
826 values.push_back(basename, 'I');
827 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
828 //
829 basename = "reported_helicity"; //delayed helicity reported by the input register.
830 values.push_back(basename, 'I');
831 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
832 //
833 basename = "pattern_phase";
834 values.push_back(basename, 'I');
835 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
836 //
837 basename = "pattern_number";
838 values.push_back(basename, 'I');
839 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
840 //
841 basename = "pattern_seed";
842 values.push_back(basename, 'I');
843 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
844 //
845 basename = "event_number";
846 values.push_back(basename, 'I');
847 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
848 //
849 for (size_t i=0; i<fWord.size(); i++)
850 {
851 basename = fWord[i].fWordName;
852 values.push_back(basename, 'I');
853 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
854 }
855 }
857 {
858 basename = "actual_helicity"; //predicted actual helicity before being delayed.
859 values.push_back(basename, 'I');
860 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
861 //
862 basename = "actual_pattern_polarity";
863 values.push_back(basename, 'I');
864 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
865 //
866 basename = "actual_previous_pattern_polarity";
867 values.push_back(basename, 'I');
868 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
869 //
870 basename = "delayed_pattern_polarity";
871 values.push_back(basename, 'I');
872 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
873 //
874 basename = "pattern_number";
875 values.push_back(basename, 'I');
876 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
877 //
878 basename = "pattern_seed";
879 values.push_back(basename, 'I');
880 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
881 //
882 for (size_t i=0; i<fWord.size(); i++)
883 {
884 basename = fWord[i].fWordName;
885 values.push_back(basename, 'I');
886 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
887 }
888 }
889
890 return;
891}
892
893void QwHelicityBase::ConstructBranch(TTree *tree, TString &prefix)
894{
895 TString basename;
896
897 SetHistoTreeSave(prefix);
899 {
900 //do nothing
901 }
902 else if(fHistoType==kHelSaveMPS)
903 {
904 // basename = "actual_helicity"; //predicted actual helicity before being delayed.
905 // tree->Branch(basename, &fHelicityActual, basename+"/I");
906 //
907 basename = "delayed_helicity"; //predicted delayed helicity
908 tree->Branch(basename, &fHelicityDelayed, basename+"/I");
909 //
910 basename = "reported_helicity"; //delayed helicity reported by the input register.
911 tree->Branch(basename, &fHelicityReported, basename+"/I");
912 //
913 basename = "pattern_phase";
914 tree->Branch(basename, &fPatternPhaseNumber, basename+"/I");
915 //
916 basename = "pattern_number";
917 tree->Branch(basename, &fPatternNumber, basename+"/I");
918 //
919 basename = "pattern_seed";
920 tree->Branch(basename, &fPatternSeed, basename+"/I");
921 //
922 basename = "event_number";
923 tree->Branch(basename, &fEventNumber, basename+"/I");
924 }
926 {
927 basename = "actual_helicity"; //predicted actual helicity before being delayed.
928 tree->Branch(basename, &fHelicityActual, basename+"/I");
929 //
930 basename = "actual_pattern_polarity";
931 tree->Branch(basename, &fActualPatternPolarity, basename+"/I");
932 //
933 basename = "actual_previous_pattern_polarity";
934 tree->Branch(basename, &fPreviousPatternPolarity, basename+"/I");
935 //
936 basename = "delayed_pattern_polarity";
937 tree->Branch(basename, &fDelayedPatternPolarity, basename+"/I");
938 //
939 basename = "pattern_number";
940 tree->Branch(basename, &fPatternNumber, basename+"/I");
941 //
942 basename = "pattern_seed";
943 tree->Branch(basename, &fPatternSeed, basename+"/I");
944
945 for (size_t i=0; i<fWord.size(); i++)
946 {
947 basename = fWord[i].fWordName;
948 tree->Branch(basename, &fWord[i].fValue, basename+"/I");
949 }
950 }
951
952 return;
953}
954
955void QwHelicityBase::ConstructBranch(TTree *tree, TString &prefix, QwParameterFile& trim_file)
956{
957 TString basename;
958
959 SetHistoTreeSave(prefix);
961 {
962 //do nothing
963 }
964 else if(fHistoType==kHelSaveMPS)
965 {
966 // basename = "actual_helicity"; //predicted actual helicity before being delayed.
967 // tree->Branch(basename, &fHelicityActual, basename+"/I");
968 //
969 basename = "delayed_helicity"; //predicted delayed helicity
970 tree->Branch(basename, &fHelicityDelayed, basename+"/I");
971 //
972 basename = "reported_helicity"; //delayed helicity reported by the input register.
973 tree->Branch(basename, &fHelicityReported, basename+"/I");
974 //
975 basename = "pattern_phase";
976 tree->Branch(basename, &fPatternPhaseNumber, basename+"/I");
977 //
978 basename = "pattern_number";
979 tree->Branch(basename, &fPatternNumber, basename+"/I");
980 //
981 basename = "pattern_seed";
982 tree->Branch(basename, &fPatternSeed, basename+"/I");
983 //
984 basename = "event_number";
985 tree->Branch(basename, &fEventNumber, basename+"/I");
986 }
988 {
989 basename = "actual_helicity"; //predicted actual helicity before being delayed.
990 tree->Branch(basename, &fHelicityActual, basename+"/I");
991 //
992 basename = "actual_pattern_polarity";
993 tree->Branch(basename, &fActualPatternPolarity, basename+"/I");
994 //
995 basename = "actual_previous_pattern_polarity";
996 tree->Branch(basename, &fPreviousPatternPolarity, basename+"/I");
997 //
998 basename = "delayed_pattern_polarity";
999 tree->Branch(basename, &fDelayedPatternPolarity, basename+"/I");
1000 //
1001 basename = "pattern_number";
1002 tree->Branch(basename, &fPatternNumber, basename+"/I");
1003 //
1004 basename = "pattern_seed";
1005 tree->Branch(basename, &fPatternSeed, basename+"/I");
1006
1007 for (size_t i=0; i<fWord.size(); i++)
1008 {
1009 basename = fWord[i].fWordName;
1010 tree->Branch(basename,&fWord[i].fValue, basename+"/I");
1011 }
1012
1013 }
1014
1015
1016 return;
1017}
1018
1020{
1021
1022 size_t index=fTreeArrayIndex;
1024 {
1025 // values[index++] = fHelicityActual;
1026 values.SetValue(index++, fHelicityDelayed);
1027 values.SetValue(index++, fHelicityReported);
1028 values.SetValue(index++, fPatternPhaseNumber);
1029 values.SetValue(index++, fPatternNumber);
1030 values.SetValue(index++, fPatternSeed);
1031 values.SetValue(index++, fEventNumber);
1032 for (size_t i=0; i<fWord.size(); i++)
1033 values.SetValue(index++, fWord[i].fValue);
1034 }
1035 else if(fHistoType==kHelSavePattern)
1036 {
1037 values.SetValue(index++, fHelicityActual);
1038 values.SetValue(index++, fActualPatternPolarity);
1039 values.SetValue(index++, fPreviousPatternPolarity);
1040 values.SetValue(index++, fDelayedPatternPolarity);
1041 values.SetValue(index++, fPatternNumber);
1042 values.SetValue(index++, fPatternSeed);
1043 for (size_t i=0; i<fWord.size(); i++){
1044 values.SetValue(index++, fWord[i].fValue);
1045 }
1046 }
1047
1048 return;
1049}
1050
1051
1052#ifdef __USE_DATABASE__
1053void QwHelicityBase::FillDB(QwParityDB *db, TString type)
1054{
1055 if (type=="yield" || type=="asymmetry")
1056 return;
1057
1058 // db->Connect();
1059 // mysqlpp::Query query = db->Query();
1060
1061 // db->Disconnect();
1062}
1063
1064
1065
1066void QwHelicityBase::FillErrDB(QwParityDB *db, TString type)
1067{
1068 return;
1069}
1070#endif // __USE_DATABASE__
1071
1072
1073UInt_t QwHelicityBase::GetRandbit(UInt_t& ranseed){
1074 Bool_t status = false;
1075
1076 if (fRandBits == 24)
1077 status = GetRandbit24(ranseed);
1078 if (fRandBits == 30)
1079 status = GetRandbit30(ranseed);
1080
1081 return status;
1082}
1083
1084UInt_t QwHelicityBase::GetRandbit24(UInt_t& ranseed)
1085{
1086 /** This is a 24 bit random bit generator according to the "new" algorithm
1087 described in "G0 Helicity Digital Controls" by E. Stangland, R. Flood, H. Dong.
1088
1089
1090 The helicity board uses a maximum-length linear feedback shift registers
1091 for the generation of a pseudo-random sequence of bits. The length of the
1092 register (24 bits or 30 bits) defines the length before a sequence is
1093 repeated: 2^n - 1.
1094
1095 For a mathematical introduction to the generation of pseudo-random numbers
1096 with maximum-length linear feedback shift registers (LFSR), see the
1097 following web references:
1098 http://en.wikipedia.org/wiki/Linear_feedback_shift_register
1099 http://www.newwaveinstruments.com/resources/articles/m_sequence_linear_feedback_shift_register_lfsr.htm
1100
1101 In particular, the used solutions are to place XNOR taps at the bits
1102 24 stages, 4 taps: (47 sets)
1103 [24, 23, 21, 20]
1104 30 stages, 4 taps: (104 sets)
1105 [30, 29, 28, 7]
1106
1107 The 24 stage solution we use has been mirrored by transforming [m, A, B, C]
1108 into [m, m-C, m-B, m-A]. This goes through the sequence in the opposite
1109 direction.
1110 */
1111
1112 const UInt_t IB1 = 1; //Bit 1 of shift register 000000000000000000000001
1113 const UInt_t IB3 = 4; //Bit 3 of shift register 000000000000000000000100
1114 const UInt_t IB4 = 8; //Bit 4 of shift register 000000000000000000001000
1115 const UInt_t IB24 = 8388608; //Bit 24 of shift register 100000000000000000000000
1116 const UInt_t MASK = IB1+IB3+IB4+IB24; //Sum of the four feedback bits is 100000000000000000001101
1117
1118 UInt_t result; //The generated pattern
1119
1120 if(ranseed<=0)
1121 {
1122 QwError << "ranseed must be greater than zero!" << QwLog::endl;
1123 result = 0;
1124 }
1125
1126 if(ranseed & IB24) // if bit 24 of ranseed = 1, then output 1
1127 {
1128 ranseed = (((ranseed^MASK) << 1)|IB1);
1129 result = 1;
1130 }
1131 else
1132 {
1133 ranseed <<= 1;
1134 result = 0;
1135 }
1136 return(result);
1137
1138}
1139
1140
1141UInt_t QwHelicityBase::GetRandbit30(UInt_t& ranseed)
1142{
1143 /* For an explanation of the algorithm, see above in GetRandbit24() */
1144
1145 UInt_t bit7 = (ranseed & 0x00000040) != 0;
1146 UInt_t bit28 = (ranseed & 0x08000000) != 0;
1147 UInt_t bit29 = (ranseed & 0x10000000) != 0;
1148 UInt_t bit30 = (ranseed & 0x20000000) != 0;
1149
1150 UInt_t result = (bit30 ^ bit29 ^ bit28 ^ bit7) & 0x1;
1151
1152 if(ranseed<=0) {
1153 QwError << "ranseed must be greater than zero!" << QwLog::endl;
1154 result = 0;
1155 }
1156 ranseed = ( (ranseed << 1) | result ) & 0x3FFFFFFF;
1157
1158 return(result);
1159}
1160
1161
1162UInt_t QwHelicityBase::GetRandomSeed(UShort_t* first24randbits)
1163{
1164 Bool_t ldebug=0;
1165 QwDebug << " Entering QwHelicityBase::GetRandomSeed \n";
1166
1167 /** This the random seed generator used in G0 (L.Jianglai)
1168 Here we get the 24 random bits and derive the randome seed from that.
1169 randome seed : b24 b23 b22.....b2 b1
1170 first 24 random bit from this seed: h1 h2 h3 ....h23 h24
1171 we have,
1172 b23 = h1, b22 = h2,... b5 = h20,
1173 h21^b24 = b4 , h3^b24^b23 = b3 ,h23^b23^b22 = b2, h24^b22^b24 = b1.
1174 Thus by using h1,...h24, we can derive the b24,..b1 of the randseed.
1175 */
1176
1177 UShort_t b[25];
1178 UInt_t ranseed = 0;
1179
1180 if(ldebug)
1181 {
1182 for(size_t i=0;i<25;i++)
1183 std::cout << i << " : " << first24randbits[i] << "\n";
1184 }
1185
1186 for(size_t i=24;i>=5;i--) b[i]= first24randbits[24-i+1]; //fill h24..h5
1187
1188 // fill b[4] to b[1]
1189 b[4] = first24randbits[21]^b[24]; //h21^b24 = b4
1190 b[3] = first24randbits[22]^b[24]^b[23]; //h22^b24^b23 = b3
1191 b[2] = first24randbits[23]^b[23]^b[22];// h23^b23^b22 = b2
1192 b[1] = first24randbits[24]^b[21]^b[22]^b[24];// h24^b22^b24 = b1
1193
1194 ///assign the values in the h aray and into the sead
1195 for(size_t i=24;i>=1;i--) ranseed = (ranseed << 1) | (b[i]&1);
1196
1197 ranseed = ranseed&0xFFFFFF; //put a mask
1198
1199 QwDebug << " seed =" << ranseed <<QwLog::endl;
1200 QwDebug << " Exiting QwHelicityBase::GetRandomSeed \n";
1201
1202
1203 return ranseed;
1204
1205}
1206
1207
1209{
1210 Int_t ldebug = kFALSE;
1211
1212 if(ldebug) std::cout << "Entering QwHelicityBase::RunPredictor for fEventNumber, " << fEventNumber
1213 << ", fPatternNumber, " << fPatternNumber
1214 << ", and fPatternPhaseNumber, " << fPatternPhaseNumber << std::endl;
1215
1216 /**Update the random seed if the new event is from a different pattern.
1217 Check the difference between old pattern number and the new one and
1218 to see how many patterns we have missed or skipped. Then loop back
1219 to get the correct pattern polarities.
1220 */
1221
1222
1223 for (int i = 0; i < fPatternNumber - fPatternNumberOld; i++) //got a new pattern
1224 {
1228 QwDebug << "Predicting : seed actual, delayed: " << iseed_Actual
1229 << ":" << iseed_Delayed <<QwLog::endl;
1230 }
1231
1232 /**Predict the helicity according to pattern
1233 Defined patterns:
1234 Pair: +- or -+
1235 Quartet: +--+ or -++-
1236 Octet: +--+-++- or -++-+--+
1237 Symmetric octet: +-+--+-+ or -+-++-+-
1238 Octo-quad: +--++--++--++--+-++--++--++--++-
1239 */
1240
1241 Int_t localphase = fPatternPhaseNumber-fMinPatternPhase;//Paul's modifications
1242
1243 UInt_t localbit;
1244 Int_t indexnum,shiftnum;
1245 indexnum = TMath::FloorNint(localphase/32.);
1246 shiftnum = localphase - indexnum*32;
1247 //std::cout << localphase << " " << indexnum << " " << shiftnum << " "<< fHelicityBitPattern.size() << std::endl;
1248 localbit = ((fHelicityBitPattern.at(indexnum))>>shiftnum)&0x1;
1249 //std::cout<< localphase << " " << indexnum << " " << shiftnum <<std::hex << fHelicityBitPattern.at(indexnum) << std::dec << " " << localbit << std::endl;
1250 // Use the stored helicity bit pattern to calculate the helicity of this window
1251 if (localbit == (fHelicityBitPattern[0] & 0x1)) {
1254 } else {
1257 }
1258 // Past highest pattern phase
1259 if (localphase > fMaxPatternPhase)
1261
1262 if(ldebug){
1263 std::cout << "Predicted Polarity ::: Delayed ="
1264 << fDelayedPatternPolarity << " Actual ="
1265 << fActualPatternPolarity << "\n";
1266 std::cout << "Predicted Helicity ::: Delayed Helicity=" << fHelicityDelayed
1267 << " Actual Helicity=" << fHelicityActual << " Reported Helicity=" << fHelicityReported << "\n";
1268 QwError << "Exiting QwHelicityBase::RunPredictor " << QwLog::endl;
1269
1270 }
1271
1272 return;
1273}
1274
1275
1277{
1278 Bool_t status = false;
1279
1280 if (fRandBits == 24)
1281 status = CollectRandBits24();
1282 if (fRandBits == 30)
1283 status = CollectRandBits30();
1284
1285 return status;
1286}
1287
1288
1289
1291{
1292 //routine to collect 24 random bits before getting the randseed for prediction
1293 Bool_t ldebug = kFALSE;
1294 const UInt_t ranbit_goal = 24;
1295
1296 QwDebug << "QwHelicityBase::Entering CollectRandBits24...." << QwLog::endl;
1297
1298
1299 if (n_ranbits==ranbit_goal) return kTRUE;
1300
1302 {
1303 QwMessage << "Collecting information from event #" << fEventNumber << " to generate helicity seed"
1304 << "(need 24 bit, so far got " << n_ranbits << " bits )" << QwLog::endl;
1305 }
1306
1307
1308 static UShort_t first24bits[25]; //array to store the first 24 bits
1309
1310 fGoodHelicity = kFALSE; //reset before prediction begins
1311 if(IsContinuous())
1312 {
1314 {
1315 first24bits[n_ranbits+1] = fHelicityReported;
1316 n_ranbits ++;
1317 if(ldebug)
1318 {
1319 std::cout << " event number" << fEventNumber << ", fPatternNumber"
1320 << fPatternNumber << ", n_ranbit" << n_ranbits
1321 << ", fHelicityReported" << fHelicityReported << "\n";
1322 }
1323
1324 if(n_ranbits == ranbit_goal ) //If its the 24th consecative random bit,
1325 {
1326 if(ldebug)
1327 {
1328 std::cout << "Collected 24 random bits. Get the random seed for the predictor." << "\n";
1329 for(UInt_t i=0;i<ranbit_goal;i++) std::cout << " i:bit =" << i << ":" << first24bits[i] << "\n";
1330 }
1331 iseed_Delayed = GetRandomSeed(first24bits);
1332 //This random seed will predict the helicity of the event (24+fHelicityDelay) patterns before;
1333 // run GetRandBit 24 times to get the delayed helicity for this event
1334 QwDebug << "The reported seed 24 patterns ago = " << iseed_Delayed << "\n";
1335
1336 for(UInt_t i=0;i<ranbit_goal;i++) fDelayedPatternPolarity =GetRandbit(iseed_Delayed);
1338 //The helicity of the first phase in a pattern is
1339 //equal to the polarity of the pattern
1340
1341 //Check whether the reported helicity is the same as the helicity predicted by the random seed
1342
1343 if(fHelicityDelay >=0){
1345 for(Int_t i=0; i<fHelicityDelay; i++)
1346 {
1347 QwDebug << "Delaying helicity " << QwLog::endl;
1350 }
1351 }
1352 else
1353 {
1354 QwError << "QwHelicityBase::CollectRandBits We cannot handle negative delay(prediction) in the reported helicity. Exiting." << QwLog::endl;
1356 }
1357
1359 }
1360 }
1361 }
1362 else // while collecting the seed, we encounter non continuous events.
1363 {
1365 QwError << "QwHelicityBase::CollectRandBits, while collecting the seed, we encountered non continuous events: need to reset the seed collecting " << QwLog::endl
1366 << " event number=" << fEventNumber << ", fPatternNumber="
1367 << fPatternNumber << ", fPatternPhaseNumber=" << fPatternPhaseNumber << QwLog::endl;
1368 }
1369
1370 //else n randbits have been set to zero in the error checking routine
1371 //start over from the next pattern
1372 QwDebug << "QwHelicityBase::CollectRandBits24 => Done collecting ..." << QwLog::endl;
1373
1374 return kFALSE;
1375
1376}
1377
1378
1380{
1381 /** Starting to collect 30 bits/helicity state to get the
1382 random seed for the 30 bit helicity predictor.
1383 These bits (1/0) are the reported helicity states of the first event
1384 of each new pattern ot the so called pattern polarity.*/
1385
1386 // Bool_t ldebug = kFALSE;
1387 const UInt_t ranbit_goal = 30;
1388
1389 /** If we have finished collecting the bits then ignore the rest of this funciton and return true.
1390 No need to recollect!*/
1391 if (n_ranbits == ranbit_goal) return kTRUE;
1392
1393 /** If we are still collecting the bits, make sure we collect them from only the
1394 events with the minimum pattern phase.*/
1395
1396 if (n_ranbits < ranbit_goal && fPatternPhaseNumber == fMinPatternPhase) {
1397 QwMessage << "Collecting information (";
1398 if (fHelicityReported == 1) QwMessage << "+";
1399 else QwMessage << "-";
1400 QwMessage << ") from event #" << fEventNumber << " to generate helicity seed ";
1401 QwMessage << "(need " << ranbit_goal << " bit, so far got " << n_ranbits << " bits )" << QwLog::endl;
1402 }
1403
1404 /** If the events are continuous, start to make the ranseed for the helicity
1405 pattern we are getting which is the delayed helicity.*/
1406
1407 fGoodHelicity = kFALSE; //reset before prediction begins
1408
1409 if(IsContinuous()) {
1410 /** Make sure we are at the beging of a valid pattern. */
1412 iseed_Delayed = ((iseed_Delayed << 1)&0x3FFFFFFF)|fHelicityReported;
1413 QwDebug << "QwHelicityBase:: CollectRandBits30: Collecting randbit " << n_ranbits << ".." << QwLog::endl;
1414 n_ranbits++;
1415
1416 /** If we got the 30th bit,*/
1417 if(n_ranbits == ranbit_goal){
1418 QwDebug << "QwHelicityBase:: CollectRandBits30: done Collecting 30 randbits" << QwLog::endl;
1419
1420 /** set the polarity of the current pattern to be equal to the reported helicity,*/
1422 QwDebug << "QwHelicityBase:: CollectRandBits30: delayedpatternpolarity =" << fDelayedPatternPolarity << QwLog::endl;
1423
1424 /** then use it as the delayed helicity, */
1426
1427 /**if the helicity is delayed by a positive number of patterns then loop the delayed ranseed backward to get the ranseed
1428 for the actual helicity */
1429 if(fHelicityDelay >=0){
1431 for(Int_t i=0; i<fHelicityDelay; i++) {
1432 /**, get the pattern polarity for the actual pattern using that actual ranseed.*/
1435 }
1436 } else {
1437 /** If we have a negative delay. Reset the predictor.*/
1438 QwError << "QwHelicityBase::CollectRandBits30: We cannot handle negative delay(prediction) in the reported helicity. Exiting." << QwLog::endl;
1440 }
1441 /** If all is well so far, set the actual pattern polarity as the actual helicity.*/
1443 }
1444 }
1445 } else {
1446 /** while collecting the seed, we encounter non continuous events.Discard bit. Reset the predition*/
1448 QwWarning << "QwHelicityBase::CollectRandBits30: While collecting the seed, we encountered non continuous events: Need to reset the seed collecting " << QwLog::endl;
1449 QwDebug << " event number=" << fEventNumber << ", fPatternNumber="<< fPatternNumber << ", fPatternPhaseNumber=" << fPatternPhaseNumber << QwLog::endl;
1450 }
1451 return kFALSE;
1452}
1453
1454
1456{
1457 Bool_t ldebug=kFALSE;
1458
1459 if(ldebug) std::cout << "Entering QwHelicityBase::PredictHelicity \n";
1460
1461 /**Routine to predict the true helicity from the delayed helicity.
1462 Helicities are usually delayed by 8 events or 2 quartets. This delay
1463 can now be set as a cmd line option.
1464 */
1465
1466 if(CollectRandBits()) {
1467 /**After accumulating 24/30 helicity bits, iseed is up-to-date.
1468 If nothing goes wrong, n-ranbits will stay as 24/30
1469 Reset it to zero if something goes wrong.
1470 */
1471
1472 if(ldebug) std::cout << "QwHelicityBase::PredictHelicity=>Predicting the helicity \n";
1473 RunPredictor();
1474
1475 /** If not good helicity, start over again by resetting the predictor. */
1476 if(!IsGoodHelicity())
1478 }
1479
1480 if(ldebug) std::cout << "n_ranbit exiting the function = " << n_ranbits << "\n";
1481
1482 return;
1483}
1484
1485
1486
1488{
1489 /**Sets the number of bits the helicity reported gets delayed with.
1490 We predict helicity only if there is a non-zero pattern delay given. */
1491
1492 if(delay>=0){
1493 fHelicityDelay = delay;
1494 if(delay == 0){
1495 QwWarning << "QwHelicityBase : SetHelicityDelay :: helicity delay is set to 0."
1496 << " Disabling helicity predictor and using reported helicity information."
1497 << QwLog::endl;
1498 fUsePredictor = kFALSE;
1499 }
1500 else
1501 fUsePredictor = kTRUE;
1502 }
1503 else
1504 QwError << "QwHelicityBase::SetHelicityDelay We cannot handle negative delay in the prediction of delayed helicity. Exiting.." << QwLog::endl;
1505
1506 return;
1507}
1508
1509
1511{
1512 fHelicityBitPattern.clear();
1514 /* // Set the helicity pattern bits
1515 if (parity(bits) == 0)
1516 fHelicityBitPattern = bits;
1517 else QwError << "What, exactly, are you trying to do ?!?!?" << QwLog::endl;
1518 */
1519 // Notify the user
1520 QwMessage << " fPatternBits 0x" ;
1521 for (int i = fHelicityBitPattern.size()-1;i>=0; i--){
1522 QwMessage << std::hex << fHelicityBitPattern[i] << " ";
1523 }
1524 QwMessage << std::dec << QwLog::endl;
1525}
1526
1528{
1529 /**Start a new helicity prediction sequence.*/
1530
1531 QwWarning << "QwHelicityBase::ResetPredictor: Resetting helicity prediction!" << QwLog::endl;
1532 n_ranbits = 0;
1533 fGoodHelicity = kFALSE;
1534 fGoodPattern = kFALSE;
1535 return;
1536}
1537
1538
1539
1541{
1542 Bool_t ldebug = kFALSE;
1543 QwHelicityBase* input= dynamic_cast<QwHelicityBase*>(value);
1544 if (input) {
1545 this->VQwSubsystem::operator=(value);
1546 QwHelicityBase* input= dynamic_cast<QwHelicityBase*>(value);
1547 for(size_t i=0;i<input->fWord.size();i++)
1548 this->fWord[i].fValue=input->fWord[i].fValue;
1549 this->fHelicityActual = input->fHelicityActual;
1550 this->fPatternNumber = input->fPatternNumber;
1551 this->fPatternSeed = input->fPatternSeed;
1553 this->fEventNumber=input->fEventNumber;
1558 this->fHelicityActual=input->fHelicityActual;
1562 this->fGoodHelicity=input->fGoodHelicity;
1563 this->fGoodPattern=input->fGoodPattern;
1564 this->fIgnoreHelicity = input->fIgnoreHelicity;
1565
1566 this->fErrorFlag = input->fErrorFlag;
1567 this->fEventNumberFirst = input->fEventNumberFirst;
1569 this->fNumMissedGates = input->fNumMissedGates;
1573
1574 if(ldebug){
1575 std::cout << "QwHelicityBase::operator = this->fPatternNumber=" << this->fPatternNumber << std::endl;
1576 std::cout << "input->fPatternNumber=" << input->fPatternNumber << "\n";
1577 }
1578 }
1579 return *this;
1580}
1581
1583{
1584 // Bool_t localdebug=kFALSE;
1585 QwDebug << "Entering QwHelicityBase::operator+= adding " << value->GetName() << " to " << this->GetName() << " " << QwLog::endl;
1586
1587 //this routine is most likely to be called during the computatin of assymetry
1588 //this call doesn't make too much sense for this class so the following lines
1589 //are only use to put safe gards testing for example if the two instantiation indeed
1590 // refers to elements in the same pattern.
1591 CheckPatternNum(value);
1592 MergeCounters(value);
1593 return *this;
1594}
1595
1597{
1598 // Bool_t localdebug=kFALSE;
1599 if(Compare(value)) {
1600 QwHelicityBase* input= dynamic_cast<QwHelicityBase*>(value);
1601 QwDebug << "QwHelicityBase::MergeCounters: this->fPatternNumber=" << this->fPatternNumber
1602 << ", input->fPatternNumber=" << input->fPatternNumber << QwLog::endl;
1603
1604 this->fErrorFlag |= input->fErrorFlag;
1605
1606 // Make sure the pattern number and poalrity agree!
1607 if(this->fPatternNumber!=input->fPatternNumber)
1608 this->fPatternNumber=-999999;
1610 this->fPatternNumber=-999999;
1611 if (this->fPatternNumber==-999999){
1613 }
1614 }
1615}
1616
1618{
1619 // Bool_t localdebug=kFALSE;
1620 if(Compare(value)) {
1621 QwHelicityBase* input= dynamic_cast<QwHelicityBase*>(value);
1622
1623 fEventNumber = (fEventNumber == 0) ? input->fEventNumber :
1624 std::min(fEventNumber, input->fEventNumber);
1625 for (size_t i=0; i<fWord.size(); i++) {
1626 fWord[i].fValue = (fWord[i].fValue == 0) ? input->fWord[i].fValue :
1627 std::min( fWord[i].fValue, input->fWord[i].fValue);
1628 }
1629 }
1630}
1631
1633{
1634 // this is stub function defined here out of completion and uniformity between each subsystem
1635 *this = value1;
1636 CheckPatternNum(value2);
1637 MergeCounters(value2);
1638}
1639
1640void QwHelicityBase::AccumulateRunningSum(VQwSubsystem* value, Int_t count, Int_t ErrorMask){
1641 if (Compare(value)) {
1642 MergeCounters(value);
1643 QwHelicityBase* input = dynamic_cast<QwHelicityBase*>(value);
1644 fPatternNumber = (fPatternNumber <=0 ) ? input->fPatternNumber :
1645 std::min(fPatternNumber, input->fPatternNumber);
1646 // Keep track of the various error quantities, so we can print
1647 // them at the end.
1652 }
1653}
1654
1656{
1657 Bool_t res=kTRUE;
1658 if(typeid(*value)!=typeid(*this)) {
1659 res=kFALSE;
1660 } else {
1661 QwHelicityBase* input= dynamic_cast<QwHelicityBase*>(value);
1662 if(input->fWord.size()!=fWord.size()) {
1663 res=kFALSE;
1664 }
1665 }
1666 return res;
1667}
1668
1670 UInt_t bitpattern = 0;
1671 // Standard helicity board patterns (last to first):
1672 // Pair, quad, octet: -++-+--+ : 0x69
1673 // Hexo-quad: -++--++--++-+--++--++--+ : 0x666999
1674 // Octo-quad: -++--++--++--++-+--++--++--++--+ : 0x66669999
1675 //
1676 //std::cout << fHelicityBitPattern.size() << std::endl;
1677 fHelicityBitPattern.clear();
1678 if (patternsize<8){
1680 } else if (patternsize%2==0 && patternsize>0 && patternsize < 129){
1681 int num_int = TMath::CeilNint(patternsize/32.);
1682 //std::cout << num_int << " " << patternsize << " " << TMath::Ceil(patternsize/32.) << std::endl;
1683 fHelicityBitPattern.resize(num_int);
1684 bitpattern = 0x69969669;
1685 fHelicityBitPattern[0] = bitpattern;
1686 for (int i = 1; i<num_int; i++){
1688 }
1689 /*if (patternsize%8==0){
1690 Int_t halfshift = patternsize/2;
1691 for (Int_t i=0; i<(patternsize/8); i++){
1692 bitpattern += (0x9<<(i*4));
1693 bitpattern += (0x6<<(halfshift+i*4));
1694 }
1695 */
1696 } else {
1697 QwError << "QwHelicityBase::BuildHelicityBitPattern: "
1698 << "Unable to build standard bit pattern for pattern size of "
1699 << patternsize << ". Try a pattern of 0x69."
1700 << QwLog::endl;
1702 }
1703 //std::cout << fHelicityBitPattern.size() << std::endl;
1704 /*QwMessage << "QwHelicityBase::BuildHelicityBitPattern: "
1705 << "Built pattern 0x" << std::hex << bitpattern
1706 << std::dec << " for pattern size "
1707 << patternsize << "." << QwLog::endl;
1708 */
1709 QwMessage << "QwHelicityBase::BuildHelicityBitPattern: "
1710 << "Built pattern 0x";
1711 for (int i = fHelicityBitPattern.size()-1;i>=0; i--){
1712 QwMessage << std::hex << fHelicityBitPattern[i] << " ";
1713 }
1714 QwMessage << std::dec << "for pattern size "
1715 << patternsize << "." << QwLog::endl;
1716 // Now set the bit pattern.
1717 // SetHelicityBitPattern(bitpattern);
1718 return fHelicityBitPattern[0];
1719}
1720
1721#ifdef HAS_RNTUPLE_SUPPORT
1722void QwHelicityBase::ConstructNTupleAndVector(std::unique_ptr<ROOT::RNTupleModel>& model, TString &prefix, std::vector<Double_t>& values, std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
1723{
1724 SetHistoTreeSave(prefix);
1725
1726 fTreeArrayIndex = values.size();
1727 TString basename;
1729 {
1730 //do nothing
1731 }
1732 else if(fHistoType==kHelSaveMPS)
1733 {
1734 basename = "delayed_helicity"; //predicted delayed helicity
1735 values.push_back(0.0);
1736 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1737 //
1738 basename = "reported_helicity"; //delayed helicity reported by the input register.
1739 values.push_back(0.0);
1740 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1741 //
1742 basename = "pattern_phase";
1743 values.push_back(0.0);
1744 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1745 //
1746 basename = "pattern_number";
1747 values.push_back(0.0);
1748 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1749 //
1750 basename = "pattern_seed";
1751 values.push_back(0.0);
1752 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1753 //
1754 basename = "event_number";
1755 values.push_back(0.0);
1756 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1757 //
1758 for (size_t i=0; i<fWord.size(); i++)
1759 {
1760 basename = fWord[i].fWordName;
1761 values.push_back(0.0);
1762 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1763 }
1764 }
1765 else if(fHistoType==kHelSavePattern)
1766 {
1767 basename = "actual_helicity"; //predicted actual helicity before being delayed.
1768 values.push_back(0.0);
1769 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1770 //
1771 basename = "actual_pattern_polarity";
1772 values.push_back(0.0);
1773 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1774 //
1775 basename = "actual_previous_pattern_polarity";
1776 values.push_back(0.0);
1777 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1778 //
1779 basename = "delayed_pattern_polarity";
1780 values.push_back(0.0);
1781 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1782 //
1783 basename = "pattern_number";
1784 values.push_back(0.0);
1785 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1786 //
1787 basename = "pattern_seed";
1788 values.push_back(0.0);
1789 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1790 //
1791 for (size_t i=0; i<fWord.size(); i++){
1792 basename = fWord[i].fWordName;
1793 values.push_back(0.0);
1794 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1795 }
1796 }
1797
1798 fTreeArrayNumEntries = values.size() - fTreeArrayIndex;
1799}
1800
1801void QwHelicityBase::FillNTupleVector(std::vector<Double_t>& values) const
1802{
1803 // Use the same logic as FillTreeVector
1804 size_t index=fTreeArrayIndex;
1806 {
1807 values[index++] = fHelicityDelayed;
1808 values[index++] = fHelicityReported;
1809 values[index++] = fPatternPhaseNumber;
1810 values[index++] = fPatternNumber;
1811 values[index++] = fPatternSeed;
1812 values[index++] = fEventNumber;
1813 for (size_t i=0; i<fWord.size(); i++)
1814 values[index++] = fWord[i].fValue;
1815 }
1816 else if(fHistoType==kHelSavePattern)
1817 {
1818 values[index++] = fHelicityActual;
1819 values[index++] = fActualPatternPolarity;
1820 values[index++] = fPreviousPatternPolarity;
1821 values[index++] = fDelayedPatternPolarity;
1822 values[index++] = fPatternNumber;
1823 values[index++] = fPatternSeed;
1824 for (size_t i=0; i<fWord.size(); i++){
1825 values[index++] = fWord[i].fValue;
1826 }
1827 }
1828}
1829#endif // HAS_RNTUPLE_SUPPORT
Helper functions and utilities for ROOT histogram management.
QwHistogramHelper gQwHists
Globally defined instance of the QwHistogramHelper class.
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
ROOT file and tree management wrapper classes.
static const UInt_t kErrorFlag_Helicity
Definition QwTypes.h:175
static const UInt_t kGlobalCut
Definition QwTypes.h:182
ULong64_t BankID_t
Definition QwTypes.h:21
static const UInt_t kEventCutMode3
Definition QwTypes.h:174
UInt_t ROCID_t
Definition QwTypes.h:20
Helicity state management and pattern recognition.
@ kHelNoSave
std::vector< TH1_ptr > fHistograms
Histograms associated with this data element.
Utility class for histogram creation 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
bool HasValue(const std::string &key)
Has this key been defined.
Definition QwOptions.h:229
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.
T GetTypedNextToken()
Get next token into specific type.
Bool_t PopValue(const std::string keyname, T &retvalue)
void TrimWhitespace(TString::EStripType head_tail=TString::kBoth)
void SetCommentChars(const std::string value)
Set various sets of special characters.
const std::pair< TString, TString > GetParamFileNameContents()
A helper class to manage a vector of branch entries for ROOT trees.
Definition QwRootFile.h:55
size_type size() const noexcept
Definition QwRootFile.h:83
void push_back(const std::string &name, const char type='D')
Definition QwRootFile.h:197
void SetValue(size_type index, Double_t val)
Definition QwRootFile.h:110
Word-level data manipulation and bit operations.
Definition QwWord.h:31
Int_t fWordInSubbank
Definition QwWord.h:38
Int_t fSubbankIndex
Definition QwWord.h:37
TString fWordType
Definition QwWord.h:41
TString fModuleType
Definition QwWord.h:39
TString fWordName
Definition QwWord.h:40
BankID_t fCurrentBank_ID
Bank ID (and Marker word) that is currently being processed;.
Int_t GetSubbankIndex() const
UInt_t GetEventTypeMask() const
Get event type mask.
virtual VQwSubsystem & operator=(VQwSubsystem *value)
Assignment Note: Must be called at the beginning of all subsystems routine call to operator=(VQwSubsy...
void RegisterRocBankMarker(QwParameterFile &mapstr)
static void DefineOptions()
Define options function (note: no virtual static functions in C++)
TString GetName() const
std::map< TString, TString > fDetectorMaps
Map of file name to full path or content.
VQwSubsystem(const TString &name)
Constructor with name.
void SetDataLoaded(Bool_t flag)
ROCID_t fCurrentROC_ID
ROC ID that is currently being processed.
void FillTreeVector(QwRootTreeBranchVector &values) const override
Fill the tree vector.
void SetHelicityBitPattern(TString hex)
void SetHelicityDelay(Int_t delay)
static const std::vector< UInt_t > kDefaultHelicityBitPattern
std::vector< std::pair< Int_t, Int_t > > fWordsPerSubbank
void CheckPatternNum(VQwSubsystem *value)
std::vector< QwWord > fWord
Bool_t CollectRandBits24()
UInt_t BuildHelicityBitPattern(Int_t patternsize)
VQwSubsystem & operator=(VQwSubsystem *value) override
Assignment Note: Must be called at the beginning of all subsystems routine call to operator=(VQwSubsy...
Int_t ProcessConfigurationBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words) override
Int_t fActualPatternPolarity
True polarity of the current pattern.
UInt_t GetRandomSeed(UShort_t *first24randbits)
QwHelicityBase()
Private default constructor (not implemented, will throw linker error on use)
Bool_t IsGoodPatternNumber()
Bool_t fSuppressMPSErrorMsgs
UInt_t GetEventcutErrorFlag() override
Return the error flag to the top level routines related to stability checks and ErrorFlag updates.
Int_t GetHelicityActual()
UInt_t GetRandbit24(UInt_t &ranseed)
virtual void ConstructHistograms()
Construct the histograms for this subsystem.
VQwSubsystem & operator+=(VQwSubsystem *value) override
Long_t GetPatternNumber()
virtual UInt_t GetRandbit(UInt_t &ranseed)
UInt_t kEventTypeHelMinus
Int_t fNumMissedEventBlocks
Int_t fPreviousPatternPolarity
True polarity of the previous pattern.
Int_t LoadInputParameters(TString pedestalfile) override
Mandatory parameter file definition.
void FillHistograms() override
Fill the histograms for this subsystem.
void IncrementErrorCounters() override
Increment the error counters.
virtual Bool_t CollectRandBits()
std::vector< UInt_t > fHelicityBitPattern
void PrintErrorCounters() const override
virtual void ClearEventData() override
Bool_t IsGoodPhaseNumber()
Int_t GetHelicityReported()
UInt_t GetRandbit30(UInt_t &ranseed)
void Print() const
void SetEventPatternPhase(Int_t event, Int_t pattern, Int_t phase)
Int_t fHelicityDecodingMode
virtual Bool_t IsGoodHelicity()
void ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values) override
Construct the branch and tree vector.
size_t fTreeArrayNumEntries
Int_t LoadChannelMap(TString mapfile) override
Mandatory map file definition.
Int_t LoadEventCuts(TString filename) override
Optional event cut file.
static const Int_t kUndefinedHelicity
Int_t fDelayedPatternPolarity
Reported polarity of the current pattern.
Int_t fPatternPhaseNumberOld
void ConstructBranch(TTree *tree, TString &prefix) override
Construct the branch and tree vector.
void SetFirstBits(UInt_t nbits, UInt_t firstbits)
Long_t GetEventNumber()
void SetHistoTreeSave(const TString &prefix)
void ProcessOptions(QwOptions &options) override
Process the command line options.
Int_t ProcessEvBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words)
TODO: The non-event-type-aware ProcessEvBuffer routine should be replaced with the event-type-aware v...
Bool_t Compare(VQwSubsystem *source)
void ClearErrorCounters()
Bool_t ApplySingleEventCuts() override
Apply the single event cuts.
Int_t GetHelicityDelayed()
void MergeCounters(VQwSubsystem *value)
Bool_t IsGoodEventNumber()
Bool_t CollectRandBits30()
void AccumulateRunningSum(VQwSubsystem *value, Int_t count=0, Int_t ErrorMask=0xFFFFFFF) override
Update the running sums for devices.
void Ratio(VQwSubsystem *numer, VQwSubsystem *denom) override
VQwSubsystemParity()
Private default constructor (not implemented, will throw linker error on use)
virtual void FillDB(QwParityDB *, TString)
Fill the database.
virtual void FillErrDB(QwParityDB *, TString)