JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwHelicity.cc
Go to the documentation of this file.
1/**********************************************************\
2* File: QwHelicity.C *
3* *
4* Author: *
5* Time-stamp: *
6\**********************************************************/
7
8#include "QwHelicity.h"
9
10// System headers
11#include <stdexcept>
12
13// ROOT headers
14#include "TRegexp.h"
15#include "TMath.h"
16#ifdef HAS_RNTUPLE_SUPPORT
17#include "ROOT/RNTupleModel.hxx"
18#include "ROOT/RNTupleWriter.hxx"
19#include "ROOT/RField.hxx"
20#endif // HAS_RNTUPLE_SUPPORT
21
22// Qweak headers
23#include "QwRootFile.h"
24
25// Qweak headers
26#include "QwHistogramHelper.h"
27#ifdef __USE_DATABASE__
28#include "QwParitySchema.h"
29#include "QwParityDB.h"
30#endif // __USE_DATABASE__
31#include "QwLog.h"
32
34//**************************************************//
35
36// Register this subsystem with the factory
38
39
40/// Default helicity bit pattern of 0x69 represents a -++-+--+ octet
41/// (event polarity listed in reverse time order), where the LSB
42/// of the bit pattern is the first event of the pattern.
43const std::vector<UInt_t> QwHelicity::kDefaultHelicityBitPattern{0x69};
44
45//**************************************************//
46/// Constructor with name
86
87//**************************************************//
88/// Copy constructor
89// FIXME this is pretty horrible as a copy constructor, but it gets around
90// all of the copy protection built into the helicity subsystem. I can't be
91// bothered to clean it up right now... (wdc)
93: VQwSubsystem(source.GetName()),
99 //fHelicityBitPattern(source.fHelicityBitPattern),
101 kMpsCounter(source.kMpsCounter),
106{
108 //std::cout << source.fHelicityBitPattern.size() << " " << fHelicityBitPattern.size() << std::endl;
110 // Default helicity delay to two patterns.
111 fHelicityDelay = 2;
112 // Default the EventType flags to HelPlus=1 and HelMinus=4
113 // These are only used in Moller decoding mode.
116 //
120 kUserbit=-1;
126 fHelicityBitPlus=kFALSE;
127 fHelicityBitMinus=kFALSE;
128 fGoodHelicity=kFALSE;
129 fGoodPattern=kFALSE;
131
133
134 this->fWord.resize(source.fWord.size());
135 for(size_t i=0;i<this->fWord.size();i++)
136 {
137 this->fWord[i].fWordName=source.fWord[i].fWordName;
138 this->fWord[i].fModuleType=source.fWord[i].fModuleType;
139 this->fWord[i].fWordType=source.fWord[i].fWordType;
140 }
147 fEventType = source.fEventType;
149 fRandBits = source.fRandBits;
157 iseed_Actual = source.iseed_Actual;
158 n_ranbits = source.n_ranbits;
159 fEventNumber = source.fEventNumber;
165
166 this->kUserbit = source.kUserbit;
167 this->fIgnoreHelicity = source.fIgnoreHelicity;
168}
169
170//**************************************************//
172{
173 options.AddOptions("Helicity options")
174 ("helicity.seed", po::value<int>(),
175 "Number of bits in random seed");
176 options.AddOptions("Helicity options")
177 ("helicity.bitpattern", po::value<std::string>(),
178 "Helicity bit pattern: 0x1 (pair), 0x9 (quartet), 0x69 (octet), 0x666999 (hexo-quad), 0x66669999 (octo-quad)");
179 options.AddOptions("Helicity options")
180 ("helicity.patternoffset", po::value<int>(),
181 "Set 1 when pattern starts with 1 or 0 when starts with 0");
182 options.AddOptions("Helicity options")
183 ("helicity.patternphase", po::value<int>(),
184 "Maximum pattern phase");
185 options.AddOptions("Helicity options")
186 ("helicity.delay", po::value<int>(),
187 "Default delay is 2 patterns, set at the helicity map file.");
188 options.AddOptions("Helicity options")
189 ("helicity.toggle-mode", po::value<bool>()->default_bool_value(false),
190 "Activates helicity toggle-mode, overriding the 'delay', 'patternphase', 'bitpattern', and 'seed' options.");
191}
192
193//**************************************************//
194
196{
197 // Read the cmd options and override channel map settings
198 QwMessage << "QwHelicity::ProcessOptions" << QwLog::endl;
199 if (options.HasValue("helicity.patternoffset")) {
200 if (options.GetValue<int>("helicity.patternoffset") == 1
201 || options.GetValue<int>("helicity.patternoffset") == 0) {
202 fPatternPhaseOffset = options.GetValue<int>("helicity.patternoffset");
203 QwMessage << " Pattern Phase Offset = " << fPatternPhaseOffset << QwLog::endl;
204 } else QwError << "Pattern phase offset should be 0 or 1!" << QwLog::endl;
205 }
206
207 if (options.HasValue("helicity.patternphase")) {
208 if (options.GetValue<int>("helicity.patternphase") % 2 == 0) {
209 fMaxPatternPhase = options.GetValue<int>("helicity.patternphase");
210 QwMessage << " Maximum Pattern Phase = " << fMaxPatternPhase << QwLog::endl;
211 } else QwError << "Pattern phase should be an even integer!" << QwLog::endl;
212 }
213
214 if (options.HasValue("helicity.seed")) {
215 if (options.GetValue<int>("helicity.seed") == 24
216 || options.GetValue<int>("helicity.seed") == 30) {
217 QwMessage << " Random Bits = " << options.GetValue<int>("helicity.seed") << QwLog::endl;
218 fRandBits = options.GetValue<int>("helicity.seed");
219 } else QwError << "Number of random seed bits should be 24 or 30!" << QwLog::endl;
220 }
221
222 if (options.HasValue("helicity.delay")) {
223 QwMessage << " Helicity Delay = " << options.GetValue<int>("helicity.delay") << QwLog::endl;
224 SetHelicityDelay(options.GetValue<int>("helicity.delay"));
225 }
226
227 if (options.HasValue("helicity.bitpattern")) {
228 QwMessage << " Helicity Pattern ="
229 << options.GetValue<std::string>("helicity.bitpattern")
230 << QwLog::endl;
231 std::string hex = options.GetValue<std::string>("helicity.bitpattern");
232 //UInt_t bits = QwParameterFile::GetUInt(hex);
234 } else {
236 }
237
238 if (options.GetValue<bool>("helicity.toggle-mode")) {
239 fHelicityDelay = 0;
240 fUsePredictor = kFALSE;
243 }
244
245 // If we have the default Helicity Bit Pattern & a large fMaxPatternPhase,
246 // try to recompute the Helicity Bit Pattern.
249 }
250
251 // Here we're going to try to get the "online" option which
252 // is defined by QwEventBuffer.
253 if (options.HasValue("online")){
254 fSuppressMPSErrorMsgs = options.GetValue<bool>("online");
255 } else {
256 fSuppressMPSErrorMsgs = kFALSE;
257 }
258}
259
260
262{
263 Bool_t results=kFALSE;
265 results=kTRUE;
266 } else {
267 // Results is already false, so just set the error flag value.
269 }
270 return results;
271}
272
273
275{
276 Bool_t results;
277
278 if((fPatternNumber == fPatternNumberOld) && (fPatternPhaseNumber == fPatternPhaseNumberOld+1))//same pattern new phase
279 results = kTRUE; //got same pattern
281 results=kTRUE; //new pattern
282 else results=kFALSE; //wrong pattern
283
284 if(!results) {
285 QwWarning << "QwHelicity::IsGoodPatternNumber: This is not a good pattern number. New = "<< fPatternNumber << " Old = " << fPatternNumberOld << QwLog::endl;
286 //Print();
287 }
288
289 return results;
290}
291
292
294{
295 Bool_t results;
297 results= kTRUE;
298 else
299 results= kFALSE;
300
301 if(!results) {
302 QwWarning << "QwHelicity::IsGoodEventNumber: \n this is not a good event number indeed:" << QwLog::endl;
303 Print();
304 }
305 return results;
306}
307
308
310{
311 Bool_t results;
312
313 if((fPatternPhaseNumber == fMaxPatternPhase) && (fPatternNumber == fPatternNumberOld )) //maximum phase of old pattern
314 results = kTRUE;
316 results = kTRUE;
318 results= kTRUE;
319 else
320 results = kFALSE;
321
323 results=kFALSE;
324
325 if(!results) {
326 QwWarning << "QwHelicity::IsGoodPhaseNumber: not a good phase number \t"
327 << "Phase: " << fPatternPhaseNumber << " out of "
329 << "(was " << fPatternPhaseNumberOld << ")"
330 << "\tPattern #" << fPatternNumber << "(was "
331 << fPatternNumberOld << ")"
332 << QwLog::endl; //Paul's modifications
333 Print();
334 }
335
336 return results;
337}
338
339
341{
342 fGoodHelicity = kTRUE;
344 /**We are not ignoring the helicity, and the helicities do not match.
345 Check phase number to see if its a new pattern.*/
346 fGoodHelicity=kFALSE;
350 //first event in a new pattern
351 QwError << "QwHelicity::IsGoodHelicity : The helicity reported in event "
352 << fEventNumber
353 << " is not what we expect from the randomseed. Not a good event nor pattern"
354 << QwLog::endl;
355 } else {
356 QwError << "QwHelicity::IsGoodHelicity - The helicity reported in event "
357 << fEventNumber
358 << " is not what we expect according to pattern structure. Not a good event nor pattern"
359 << QwLog::endl;
360 }
361 }
362 if(!fGoodHelicity) {
366 //Have to start over again
368 }
369
370 return fGoodHelicity;
371}
372
373
375{
376 SetDataLoaded(kFALSE);
377 for (size_t i=0;i<fWord.size();i++)
379
380 /**Reset data by setting the old event number, pattern number and pattern phase
381 to the values of the previous event.*/
382 if (fEventNumberFirst==-1 && fEventNumberOld!= -1){
384 }
388 }
389
393
394 //fIgnoreHelicity = kFALSE;
395
396 /**Clear out helicity variables */
400 fHelicityBitPlus = kFALSE;
401 fHelicityBitMinus = kFALSE;
402 // be careful: it is not that I forgot to reset fActualPatternPolarity
403 // or fDelayedPatternPolarity. One doesn't want to do that here.
404 /** Set the new event number and pattern number to -1. If we are not reading these correctly
405 from the data stream, -1 will allow us to identify that.*/
406 fEventNumber = -1;
408 fPatternNumber = -1;
409 return;
410}
411
412Int_t QwHelicity::ProcessConfigurationBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t* buffer, UInt_t num_words)
413{
414 //stub function
415 // QwError << " this function QwHelicity::ProcessConfigurationBuffer does nothing yet " << QwLog::endl;
416 return 0;
417}
418
419Int_t QwHelicity::LoadInputParameters(TString pedestalfile)
420{
421 return 0;
422}
423
424
426 //impose single event cuts //Paul's modifications
427
428 return kTRUE;
429}
430
432{
433 /// TODO: Implement QwHelicity::IncrementErrorCounters()
434}
435
437 // report number of events failed due to HW and event cut failure
438 QwMessage << "\n*********QwHelicity Error Summary****************"
439 << QwLog::endl;
440 QwMessage << "First helicity gate counter: "
442 << "; last helicity gate counter: "
443 << fEventNumber
444 << QwLog::endl;
445 QwMessage << "First pattern counter: "
447 << "; last pattern counter: "
449 << QwLog::endl;
450 QwMessage << "Missed " << fNumMissedGates << " helicity gates in "
451 << fNumMissedEventBlocks << " blocks of missed events."
452 << QwLog::endl;
453 QwMessage << "Number of multiplet-sync-bit errors: "
455 << QwLog::endl;
456 QwMessage << "Number of helicity prediction errors: "
458 << QwLog::endl;
459 QwMessage <<"---------------------------------------------------\n"
460 << QwLog::endl;
461}
462
463UInt_t QwHelicity::GetEventcutErrorFlag(){//return the error flag
464 return fErrorFlag;
465}
466
467/*!
468 * \brief Process helicity information from userbit configuration data.
469 *
470 * This is a complex function (~80 lines) that extracts helicity information
471 * from userbit data for injector tests and special configurations. It handles:
472 *
473 * Userbit Decoding:
474 * - Extracts 3-bit userbit pattern from bits 28-30 of userbit word
475 * - Decodes quartet synchronization bit (bit 3) for pattern timing
476 * - Decodes helicity bit (bit 2) for spin state determination
477 * - Manages scaler offset calculations for event counting
478 *
479 * Event Counting Logic:
480 * - Increments event numbers based on scaler counter ratios
481 * - Handles missed events when scaler offset > 1 (indicates DAQ issues)
482 * - Maintains pattern phase and pattern number synchronization
483 * - Resets quartet phase on quartet sync bit assertion
484 *
485 * Helicity State Management:
486 * - Sets fHelicityBitPlus/fHelicityBitMinus based on userbit helicity bit
487 * - Updates fHelicityReported for downstream processing
488 * - Maintains helicity predictor state for data quality monitoring
489 *
490 * Error Recovery:
491 * - Detects missed events through scaler offset analysis
492 * - Resets helicity predictor when event sequence is uncertain
493 * - Provides debug output for missed event scenarios
494 *
495 * Pattern Synchronization:
496 * - Manages quartet boundaries using sync bits
497 * - Handles pattern phase wraparound at maximum phase
498 * - Maintains continuous event numbering across pattern boundaries
499 *
500 * \note This mode is primarily used for injector testing and is not the
501 * standard helicity decoding method for production Qweak data analysis.
502 *
503 * \warning Missed events (scaler offset > 1) will reset the helicity
504 * predictor and may affect downstream helicity-dependent analyses.
505 */
507{
508
509 /** In this version of the code, the helicity is extracted for a userbit configuration.
510 This is not what we plan to have for Qweak but it was done for injector tests and
511 so is useful to have as another option to get helicity information. */
512
513 Bool_t ldebug=kFALSE;
514 UInt_t userbits;
515 static UInt_t lastuserbits = 0xFF;
516 UInt_t scaleroffset=fWord[kScalerCounter].fValue/32;
517
518 if(scaleroffset==1 || scaleroffset==0) {
519 userbits = (fWord[kUserbit].fValue & 0xE0000000)>>28;
520
521 // Now fake the input register, MPS counter, QRT counter, and QRT phase.
523
524 lastuserbits = userbits;
525
526 if (lastuserbits==0xFF) {
528 } else {
529 if ((lastuserbits & 0x8) == 0x8) {
530 // Quartet bit is set.
531 fPatternPhaseNumber = fMinPatternPhase; // Reset the QRT phase
532 fPatternNumber=fPatternNumberOld+1; // Increment the QRT counter
533 } else {
534 fPatternPhaseNumber=fPatternPhaseNumberOld+1; // Increment the QRT phase
535 }
536
538
539 if ((lastuserbits & 0x4) == 0x4){ // Helicity bit is set.
540 fHelicityReported |= 1; // Set the InputReg HEL+ bit.
541 fHelicityBitPlus=kTRUE;
542 fHelicityBitMinus=kFALSE;
543 } else {
544 fHelicityReported |= 0; // Set the InputReg HEL- bit.
545 fHelicityBitPlus=kFALSE;
546 fHelicityBitMinus=kTRUE;
547 }
548 }
549 } else {
550 QwError << " QwHelicity::ProcessEvent finding a missed read event in the scaler" << QwLog::endl;
551 if(ldebug) {
552 std::cout << " QwHelicity::ProcessEvent :" << scaleroffset << " events were missed \n";
553 std::cout << " before manipulation \n";
554 Print();
555 }
556 //there was more than one event since the last reading of the scalers
557 //ie we should read only one event at the time,
558 //if not something is wrong
559 fEventNumber=fEventNumberOld+scaleroffset;
560 Int_t localphase=fPatternPhaseNumberOld;
561 Int_t localpatternnumber=fPatternNumberOld;
562 for (UInt_t i=0;i<scaleroffset;i++) {
563 fPatternPhaseNumber=localphase+1;
567 localpatternnumber=fPatternNumber;
568 }
569 localphase=fPatternPhaseNumber;
570 }
571 //Reset helicity predictor because we are not sure of what we are doing
574 if(ldebug) {
575 std::cout << " after manipulation \n";
576 Print();
577 }
578 }
579 return;
580}
581
582
584{
585 static Bool_t firstevent = kTRUE;
586 static Bool_t firstpattern = kTRUE;
587 static Bool_t fake_the_counters=kFALSE;
588 UInt_t thisinputregister=fWord[kInputRegister].fValue;
589
590 if (firstpattern){
591 // If any of the special counters are negative or zero, setup to
592 // generate the counters internally.
593 fake_the_counters |= (kPatternCounter<=0)
594 || ( kMpsCounter<=0) || (kPatternPhase<=0);
595 }
596
597 if (CheckIORegisterMask(thisinputregister,fInputReg_FakeMPS))
598 fIgnoreHelicity = kTRUE;
599 else
600 fIgnoreHelicity = kFALSE;
601
602 /** If we get junk for the mps and pattern information from the run
603 we can enable fake counters for mps, pattern number and pattern
604 phase to get the job done.
605 */
606 if (!fake_the_counters){
607 /**
608 In the Input Register Mode,
609 the event number is obtained straight from the wordkMPSCounter.
610 */
612 // When we have the minimum phase from the pattern phase word
613 // and the input register minimum phase bit is set
614 // we can select the second pattern as below.
615 if(fWord[kPatternPhase].fValue - fPatternPhaseOffset == 0)
616 if (firstpattern && CheckIORegisterMask(thisinputregister,fInputReg_PatternSync)){
617 firstpattern = kFALSE;
618 }
619
620 // If firstpattern is still TRUE, we are still searching for the first
621 // pattern of the data stream. So set the pattern number = 0
622 if (firstpattern)
623 fPatternNumber = -1;
624 else {
627 }
628 } else {
629 // Use internal variables for all the counters.
631 if (CheckIORegisterMask(thisinputregister,fInputReg_PatternSync)) {
634 } else {
637 }
638 }
639
640
641 if (firstevent){
642 firstevent = kFALSE;
643 } else if(fEventNumber!=(fEventNumberOld+1)){
644 Int_t nummissed(fEventNumber - (fEventNumberOld+1));
646 QwError << "QwHelicity::ProcessEvent read event# ("
647 << fEventNumber << ") is not old_event#+1; missed "
648 << nummissed << " gates" << QwLog::endl;
649 }
650 fNumMissedGates += nummissed;
653 }
654
656 // Quartet bit is set.
657 QwError << "QwHelicity::ProcessEvent: The Multiplet Sync bit is set, but the Pattern Phase is ("
658 << fPatternPhaseNumber << ") not "
659 << fMinPatternPhase << "! Please check the fPatternPhaseOffset in the helicity map file." << QwLog::endl;
662 }
663
665
666 /**
667 Extract the reported helicity from the input register for each event.
668 */
669
670 if (CheckIORegisterMask(thisinputregister,fInputReg_HelPlus)
671 && CheckIORegisterMask(thisinputregister,fInputReg_HelMinus) ){
672 // Both helicity bits are set.
673 QwError << "QwHelicity::ProcessEvent: Both the H+ and H- bits are set: thisinputregister=="
674 << thisinputregister << QwLog::endl;
676 fHelicityBitPlus = kFALSE;
677 fHelicityBitMinus = kFALSE;
678 } else if (CheckIORegisterMask(thisinputregister,fInputReg_HelPlus)){ // HelPlus bit is set.
679 fHelicityReported |= 1; // Set the InputReg HEL+ bit.
680 fHelicityBitPlus = kTRUE;
681 fHelicityBitMinus = kFALSE;
682 } else {
683 fHelicityReported |= 0; // Set the InputReg HEL- bit.
684 fHelicityBitPlus = kFALSE;
685 fHelicityBitMinus = kTRUE;
686 }
687
688 return;
689}
690
692{
693 static Bool_t firstpattern = kTRUE;
694
695 if(firstpattern && fWord[kPatternCounter].fValue > fPatternNumberOld){
696 firstpattern = kFALSE;
697 }
698
701 Int_t nummissed(fEventNumber - (fEventNumberOld+1));
702 QwError << "QwHelicity::ProcessEvent read event# ("
703 << fEventNumber << ") is not old_event#+1; missed "
704 << nummissed << " gates" << QwLog::endl;
705 fNumMissedGates += nummissed;
707 }
708 if (firstpattern){
709 fPatternNumber = -1;
711 } else {
714 // We are at a new pattern!
716 } else {
718 }
719 }
720
723 // fHelicityReported = (fEventType == 1 ? 0 : 1);
724
725 if (fHelicityReported == 1){
726 fHelicityBitPlus=kTRUE;
727 fHelicityBitMinus=kFALSE;
728 } else {
729 fHelicityBitPlus=kFALSE;
730 fHelicityBitMinus=kTRUE;
731 }
732 return;
733}
734
735
737{
738 Bool_t ldebug = kFALSE;
739 fErrorFlag = 0;
740
741 if (! HasDataLoaded()) return;
742
743 switch (fHelicityDecodingMode)
744 {
745 case kHelUserbitMode :
747 break;
750 break;
753 break;
754 default:
755 QwError << "QwHelicity::ProcessEvent no instructions on how to decode the helicity !!!!" << QwLog::endl;
756 abort();
757 break;
758 }
759
762
763 // Predict helicity if delay is non zero.
766 } else {
767 // Else use the reported helicity values.
770
775 }
776
777 }
778
779 if(ldebug){
780 std::cout<<"\nevent number= "<<fEventNumber<<std::endl;
781 std::cout<<"pattern number = "<<fPatternNumber<<std::endl;
782 std::cout<<"pattern phase = "<<fPatternPhaseNumber<<std::endl;
783 std::cout<<"max pattern phase = "<<fMaxPatternPhase<<std::endl;
784 std::cout<<"min pattern phase = "<<fMinPatternPhase<<std::endl;
785
786
787 }
788 //std::cout << fPatternPhaseNumber << " " << fHelicityReported << " LOOK HERE !!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
789 return;
790
791}
792
793
794void QwHelicity::EncodeEventData(std::vector<UInt_t> &buffer)
795{
796 std::vector<UInt_t> localbuffer;
797 localbuffer.clear();
798
799 // Userbit mode
800 switch (fHelicityDecodingMode) {
801 case kHelUserbitMode: {
802 UInt_t userbit = 0x0;
803 if (fPatternPhaseNumber == fMinPatternPhase) userbit |= 0x80000000;
804 if (fHelicityDelayed == 1) userbit |= 0x40000000;
805
806 // Write the words to the buffer
807 localbuffer.push_back(0x1); // cleandata
808 localbuffer.push_back(0xa); // scandata1
809 localbuffer.push_back(0xa); // scandata2
810 localbuffer.push_back(0x0); // scalerheader
811 localbuffer.push_back(0x20); // scalercounter (32)
812 localbuffer.push_back(userbit); // userbit
813
814 for (int i = 0; i < 64; i++) localbuffer.push_back(0x0); // (not used)
815 break;
816 }
818 UInt_t input_register = 0x0;
819 if (fHelicityDelayed == 1) input_register |= fInputReg_HelPlus;
820 if (fHelicityDelayed == 0) input_register |= fInputReg_HelMinus;
822
823 // Write the words to the buffer
824 localbuffer.push_back(input_register); // input_register
825 localbuffer.push_back(0x0); // output_register
826 localbuffer.push_back(fEventNumber); // mps_counter
827 localbuffer.push_back(fPatternNumber); // pat_counter
828 localbuffer.push_back(fPatternPhaseNumber - fMinPatternPhase + fPatternPhaseOffset); // pat_phase
829
830 for (int i = 0; i < 17; i++) localbuffer.push_back(0x0); // (not used)
831 break;
832 }
833 default:
834 QwWarning << "QwHelicity::EncodeEventData: Unsupported helicity encoding!" << QwLog::endl;
835 break;
836 }
837
838 // If there is element data, generate the subbank header
839 std::vector<UInt_t> subbankheader;
840 std::vector<UInt_t> rocheader;
841 if (localbuffer.size() > 0) {
842
843 // Form CODA subbank header
844 subbankheader.clear();
845 subbankheader.push_back(localbuffer.size() + 1); // subbank size
846 subbankheader.push_back((fCurrentBank_ID << 16) | (0x01 << 8) | (1 & 0xff));
847 // subbank tag | subbank type | event number
848
849 // Form CODA bank/roc header
850 rocheader.clear();
851 rocheader.push_back(subbankheader.size() + localbuffer.size() + 1); // bank/roc size
852 rocheader.push_back((fCurrentROC_ID << 16) | (0x10 << 8) | (1 & 0xff));
853 // bank tag == ROC | bank type | event number
854
855 // Add bank header, subbank header and element data to output buffer
856 buffer.insert(buffer.end(), rocheader.begin(), rocheader.end());
857 buffer.insert(buffer.end(), subbankheader.begin(), subbankheader.end());
858 buffer.insert(buffer.end(), localbuffer.begin(), localbuffer.end());
859 }
860}
861
863{
864 QwOut << "===========================\n"
865 << "This event: Event#, Pattern#, PatternPhase#="
866 << fEventNumber << ", "
867 << fPatternNumber << ", "
869 QwOut << "Previous event: Event#, Pattern#, PatternPhase#="
870 << fEventNumberOld << ", "
871 << fPatternNumberOld << ", "
873 QwOut << "delta = \n(fEventNumberOld)-(fMaxPatternPhase)x(fPatternNumberOld)-(fPatternPhaseNumberOld)= "
875 QwOut << "Helicity Reported, Delayed, Actual ="
876 << fHelicityReported << ","
877 << fHelicityDelayed << ","
879 QwOut << "===" << QwLog::endl;
880 return;
881}
882
883
884Int_t QwHelicity::LoadChannelMap(TString mapfile)
885{
886 Bool_t ldebug=kFALSE;
887
888 Int_t wordsofar=0;
889 Int_t bankindex=-1;
890
891 fPatternPhaseOffset=1;//Phase number offset is set to 1 by default and will be set to 0 if phase number starts from 0
892
893
894 // Default value for random seed is 30 bits
895 fRandBits = 30;
896
897
898 QwParameterFile mapstr(mapfile.Data()); //Open the file
900 mapstr.EnableGreediness();
901 mapstr.SetCommentChars("!");
902
903 UInt_t value = 0;
904 TString valuestr;
905
906 while (mapstr.ReadNextLine()){
907 RegisterRocBankMarker(mapstr);
908
909 if (mapstr.PopValue("patternphase",value)) {
910 fMaxPatternPhase=value;
911 //QwMessage << " fMaxPatternPhase " << fMaxPatternPhase << QwLog::endl;
912 }
913 if (mapstr.PopValue("patternbits",valuestr)) {
914 SetHelicityBitPattern(valuestr);
915 }
916 if (mapstr.PopValue("inputregmask_fakemps",value)) {
917 fInputReg_FakeMPS = value;
918 }
919 if (mapstr.PopValue("inputregmask_helicity",value)) {
920 fInputReg_HelPlus = value;
922 }
923 if (mapstr.PopValue("inputregmask_helplus",value)) {
924 fInputReg_HelPlus = value;
925 }
926 if (mapstr.PopValue("inputregmask_helminus",value)) {
927 fInputReg_HelMinus = value;
928 }
929 if (mapstr.PopValue("inputregmask_pattsync",value)) {
930 fInputReg_PatternSync = value;
931 }
932 if (mapstr.PopValue("inputregmask_pairsync",value)) {
933 fInputReg_PairSync = value;
934 }
935 if (mapstr.PopValue("fakempsbit",value)) {
936 fInputReg_FakeMPS = value;
937 QwWarning << " fInputReg_FakeMPS 0x" << std::hex << fInputReg_FakeMPS << std::dec << QwLog::endl;
938 }
939 if (mapstr.PopValue("numberpatternsdelayed",value)) {
940 SetHelicityDelay(value);
941 }
942 if (mapstr.PopValue("randseedbits",value)) {
943 if (value==24 || value==30)
944 fRandBits = value;
945 }
946 if (mapstr.PopValue("patternphaseoffset",value)) {
948 }
949 if (mapstr.PopValue("helpluseventtype",value)) {
950 kEventTypeHelPlus = value;
951 }
952 if (mapstr.PopValue("helminuseventtype",value)) {
953 kEventTypeHelMinus = value;
954 }
955 if (mapstr.PopValue("helicitydecodingmode",valuestr)) {
956 if (valuestr=="InputRegisterMode") {
957 QwMessage << " **** Input Register Mode **** " << QwLog::endl;
959 } else if (valuestr=="UserbitMode"){
960 QwMessage << " **** Userbit Mode **** " << QwLog::endl;
962 } else if (valuestr=="HelLocalyMadeUp"){
963 QwMessage << "**** Helicity Locally Made Up ****" << QwLog::endl;
965 } else if (valuestr=="InputMollerMode") {
966 QwMessage << "**** Input Moller Mode ****" << QwLog::endl;
968 } else {
969 QwError << "The helicity decoding mode read in file " << mapfile
970 << " is not recognized in function QwHelicity::LoadChannelMap \n"
971 << " Quitting this execution." << QwLog::endl;
972 }
973 }
974
977 if ((bankindex+1)>0){
978 UInt_t numbanks = UInt_t(bankindex+1);
979 if (fWordsPerSubbank.size()<numbanks){
980 fWordsPerSubbank.resize(numbanks,
981 std::pair<Int_t, Int_t>(fWord.size(),fWord.size()));
982 }
983 }
984 wordsofar=0;
985 }
986 mapstr.TrimWhitespace(); // Get rid of leading and trailing spaces.
987 if (mapstr.LineIsEmpty()) continue;
988
989 // Break this line into tokens to process it.
990 TString modtype = mapstr.GetTypedNextToken<TString>(); // module type
991 Int_t modnum = mapstr.GetTypedNextToken<Int_t>(); //slot number
992 /* Int_t channum = */ mapstr.GetTypedNextToken<Int_t>(); //channel number /* unused */
993 TString dettype = mapstr.GetTypedNextToken<TString>(); //type-purpose of the detector
994 dettype.ToLower();
995 TString namech = mapstr.GetTypedNextToken<TString>(); //name of the detector
996 namech.ToLower();
997 TString keyword = mapstr.GetTypedNextToken<TString>();
998 keyword.ToLower();
999 // Notice that "namech" and "keyword" are now forced to lower-case.
1000
1001 if(modtype=="SKIP"){
1002 if (modnum<=0) wordsofar+=1;
1003 else wordsofar+=modnum;
1004 } else if(modtype!="WORD"|| dettype!="helicitydata") {
1005 QwError << "QwHelicity::LoadChannelMap: Unknown detector type: "
1006 << dettype << ", the detector " << namech << " will not be decoded "
1007 << QwLog::endl;
1008 continue;
1009 } else {
1010 QwWord localword;
1011 localword.fSubbankIndex=bankindex;
1012 localword.fWordInSubbank=wordsofar;
1013 wordsofar+=1;
1014 // I assume that one data = one word here. But it is not always the case, for
1015 // example the triumf adc gives 6 words per channel
1016 localword.fModuleType=modtype;
1017 localword.fWordName=namech;
1018 localword.fWordType=dettype;
1019 fWord.push_back(localword);
1020 fWordsPerSubbank.at(bankindex).second = fWord.size();
1021
1022 // Notice that "namech" is in lower-case, so these checks
1023 // should all be in lower-case
1024 switch (fHelicityDecodingMode)
1025 {
1026 case kHelUserbitMode :
1027 if(namech.Contains("userbit")) kUserbit=fWord.size()-1;
1028 if(namech.Contains("scalercounter")) kScalerCounter=fWord.size()-1;
1029 break;
1031 if(namech.Contains("input_register")) kInputRegister= fWord.size()-1;
1032 if(namech.Contains("mps_counter")) kMpsCounter= fWord.size()-1;
1033 if(namech.Contains("pat_counter")) kPatternCounter= fWord.size()-1;
1034 if(namech.Contains("pat_phase")) kPatternPhase= fWord.size()-1;
1035 break;
1036 case kHelInputMollerMode :
1037 if(namech.Contains("mps_counter")) {
1038 kMpsCounter= fWord.size()-1;
1039 }
1040 if(namech.Contains("pat_counter")) {
1041 kPatternCounter = fWord.size()-1;
1042 }
1043 break;
1044 }
1045 }
1046 }
1047
1048
1049 if(ldebug) {
1050 std::cout << "Done with Load map channel \n";
1051 for(size_t i=0;i<fWord.size();i++)
1052 fWord[i].PrintID();
1053 std::cout << " kUserbit=" << kUserbit << "\n";
1054 }
1055 ldebug=kFALSE;
1056
1058 // Check to be sure kEventTypeHelPlus and kEventTypeHelMinus are both defined and not equal
1062 // Everything is okay
1063 QwDebug << "QwHelicity::LoadChannelMap:"
1064 << " We are in Moller Helicity Mode, with HelPlusEventType = "
1066 << "and HelMinusEventType = " << kEventTypeHelMinus
1067 << QwLog::endl;
1068 } else {
1069 QwError << "QwHelicity::LoadChannelMap:"
1070 << " We are in Moller Helicity Mode, and the HelPlus and HelMinus event types are not set properly."
1071 << " HelPlusEventType = " << kEventTypeHelPlus
1072 << ", HelMinusEventType = " << kEventTypeHelMinus
1073 << ". Please correct the helicity map file!"
1074 << QwLog::endl;
1075 exit(65);
1076 }
1077 }
1078
1079std::cout << fHelicityBitPattern.size() << std::endl;
1080
1081 mapstr.Close(); // Close the file (ifstream)
1082 return 0;
1083}
1084
1085
1086Int_t QwHelicity::LoadEventCuts(TString filename){
1087 return 0;
1088}
1089
1090Int_t QwHelicity::ProcessEvBuffer(UInt_t event_type, const ROCID_t roc_id, const BankID_t bank_id, UInt_t* buffer, UInt_t num_words)
1091{
1092 Bool_t lkDEBUG = kFALSE;
1093
1094 if (((0x1 << (event_type - 1)) & this->GetEventTypeMask()) == 0)
1095 return 0;
1096 fEventType = event_type;
1097
1098 Int_t index = GetSubbankIndex(roc_id,bank_id);
1099 if (index >= 0 && num_words > 0) {
1100 SetDataLoaded(kTRUE);
1101 // We want to process this ROC. Begin loopilooping through the data.
1102 QwDebug << "QwHelicity::ProcessEvBuffer: "
1103 << "Begin processing ROC" << roc_id
1104 << " and subbank " << bank_id
1105 << " number of words=" << num_words << QwLog::endl;
1106
1107 for(Int_t i=fWordsPerSubbank.at(index).first; i<fWordsPerSubbank.at(index).second; i++) {
1108 if(fWord[i].fWordInSubbank+1<= (Int_t) num_words) {
1109 fWord[i].fValue=buffer[fWord[i].fWordInSubbank];
1110 } else {
1111 QwWarning << "QwHelicity::ProcessEvBuffer: There is not enough word in the buffer to read data for "
1112 << fWord[i].fWordName << QwLog::endl;
1113 QwWarning << "QwHelicity::ProcessEvBuffer: Words in this buffer:" << num_words
1114 << " trying to read word number =" << fWord[i].fWordInSubbank << QwLog::endl;
1115 }
1116 }
1117 if(lkDEBUG) {
1118 QwDebug << "QwHelicity::ProcessEvBuffer: Done with Processing this event" << QwLog::endl;
1119 for(size_t i=0;i<fWord.size();i++) {
1120 std::cout << " word number = " << i << " ";
1121 fWord[i].Print();
1122 }
1123 }
1124 }
1125 lkDEBUG=kFALSE;
1126 return 0;
1127}
1128
1129
1134
1136{
1137 return fHelicityActual;
1138}
1139
1141{
1142 return fHelicityDelayed;
1143}
1144
1146{
1147 return fPatternNumber;
1148}
1149
1151{
1152 return fEventNumber;
1153}
1154
1156{
1157 return fPatternPhaseNumber;
1158}
1159
1160void QwHelicity::SetEventPatternPhase(Int_t event, Int_t pattern, Int_t phase)
1161{
1162 fEventNumber = event;
1163 fPatternNumber = pattern;
1164 fPatternPhaseNumber = phase;
1165}
1166
1167void QwHelicity::SetFirstBits(UInt_t nbits, UInt_t seed)
1168{
1169 // This gives the predictor a quick start
1170 // At present, this routine can only handle nbits=24 (see GetRandomSeed)
1171 if (nbits != 24)
1172 throw std::invalid_argument("SetFirstBits currently only supports 24 bits.");
1173 // Allocate nbits+1 elements as GetRandomSeed expects Fortran indexing (1-nbits)
1174 UShort_t firstbits[nbits+1]; // NB firstbits[0] is never used
1175 for (unsigned int i = 0; i < nbits+1; i++) firstbits[i] = (seed >> i) & 0x1;
1176 // Set delayed seed
1177 iseed_Delayed = GetRandomSeed(firstbits);
1178 // Progress actual seed by the helicity delay
1180 for (int i = 0; i < fHelicityDelay; i++) GetRandbit(iseed_Actual);
1181}
1182
1183void QwHelicity::SetHistoTreeSave(const TString &prefix)
1184{
1185 Ssiz_t len;
1186 if (TRegexp("diff_").Index(prefix,&len) == 0
1187 || TRegexp("asym[1-9]*_").Index(prefix,&len) == 0)
1189 else if (TRegexp("yield_").Index(prefix,&len) == 0)
1191 else
1193}
1194
1195void QwHelicity::ConstructHistograms(TDirectory *folder, TString &prefix)
1196{
1197 SetHistoTreeSave(prefix);
1198 if (folder != NULL) folder->cd();
1199 TString basename;
1200 size_t index=0;
1201
1203 {
1204 //do nothing
1205 }
1206 else if(fHistoType==kHelSavePattern)
1207 {
1208 fHistograms.resize(1+fWord.size(), NULL);
1209 basename="pattern_polarity";
1210 fHistograms[index] = gQwHists.Construct1DHist(basename);
1211 index+=1;
1212 for (size_t i=0; i<fWord.size(); i++){
1213 basename="hel_"+fWord[i].fWordName;
1214 fHistograms[index] = gQwHists.Construct1DHist(basename);
1215 index+=1;
1216 }
1217 }
1218 else if(fHistoType==kHelSaveMPS)
1219 {
1220 fHistograms.resize(4+fWord.size(), NULL);
1221 //eventnumber, patternnumber, helicity, patternphase + fWord.size
1222 basename=prefix+"delta_event_number";
1223 fHistograms[index] = gQwHists.Construct1DHist(basename);
1224 index+=1;
1225 basename=prefix+"delta_pattern_number";
1226 fHistograms[index] = gQwHists.Construct1DHist(basename);
1227 index+=1;
1228 basename=prefix+"pattern_phase";
1229 fHistograms[index] = gQwHists.Construct1DHist(basename);
1230 index+=1;
1231 basename=prefix+"helicity";
1232 fHistograms[index] = gQwHists.Construct1DHist(basename);
1233 index+=1;
1234 for (size_t i=0; i<fWord.size(); i++){
1235 basename=prefix+fWord[i].fWordName;
1236 fHistograms[index] = gQwHists.Construct1DHist(basename);
1237 index+=1;
1238 }
1239 }
1240 else
1241 QwError << "QwHelicity::ConstructHistograms this prefix--" << prefix << "-- is not unknown:: no histo created" << QwLog::endl;
1242
1243 return;
1244}
1245
1247{
1248 // Bool_t localdebug=kFALSE;
1249
1250 size_t index=0;
1252 {
1253 //do nothing
1254 }
1255 else if(fHistoType==kHelSavePattern)
1256 {
1257 QwDebug << "QwHelicity::FillHistograms helicity info " << QwLog::endl;
1258 QwDebug << "QwHelicity::FillHistograms pattern polarity=" << fActualPatternPolarity << QwLog::endl;
1259 if (fHistograms[index]!=NULL)
1260 fHistograms[index]->Fill(fActualPatternPolarity);
1261 index+=1;
1262
1263 for (size_t i=0; i<fWord.size(); i++){
1264 if (fHistograms[index]!=NULL)
1265 fHistograms[index]->Fill(fWord[i].fValue);
1266 index+=1;
1267 QwDebug << "QwHelicity::FillHistograms " << fWord[i].fWordName << "=" << fWord[i].fValue << QwLog::endl;
1268 }
1269 }
1270 else if(fHistoType==kHelSaveMPS)
1271 {
1272 QwDebug << "QwHelicity::FillHistograms mps info " << QwLog::endl;
1273 if (fHistograms[index]!=NULL)
1275 index+=1;
1276 if (fHistograms[index]!=NULL)
1278 index+=1;
1279 if (fHistograms[index]!=NULL)
1280 fHistograms[index]->Fill(fPatternPhaseNumber);
1281 index+=1;
1282 if (fHistograms[index]!=NULL)
1283 fHistograms[index]->Fill(fHelicityActual);
1284 index+=1;
1285 for (size_t i=0; i<fWord.size(); i++){
1286 if (fHistograms[index]!=NULL)
1287 fHistograms[index]->Fill(fWord[i].fValue);
1288 index+=1;
1289 QwDebug << "QwHelicity::FillHistograms " << fWord[i].fWordName << "=" << fWord[i].fValue << QwLog::endl;
1290 }
1291 }
1292
1293 return;
1294}
1295
1296
1297void QwHelicity::ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values)
1298{
1299 SetHistoTreeSave(prefix);
1300
1301
1302 fTreeArrayIndex = values.size();
1303 TString basename;
1305 {
1306 //do nothing
1307 }
1308 else if(fHistoType==kHelSaveMPS)
1309 {
1310 // basename = "actual_helicity"; //predicted actual helicity before being delayed.
1311 // values.push_back(0.0);
1312 // tree->Branch(basename, &(values.back<Double_t>()), basename+"/D");
1313 //
1314 basename = "delayed_helicity"; //predicted delayed helicity
1315 values.push_back(basename, 'I');
1316 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1317 //
1318 basename = "reported_helicity"; //delayed helicity reported by the input register.
1319 values.push_back(basename, 'I');
1320 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1321 //
1322 basename = "pattern_phase";
1323 values.push_back(basename, 'I');
1324 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1325 //
1326 basename = "pattern_number";
1327 values.push_back(basename, 'I');
1328 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1329 //
1330 basename = "pattern_seed";
1331 values.push_back(basename, 'I');
1332 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1333 //
1334 basename = "event_number";
1335 values.push_back(basename, 'I');
1336 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1337 //
1338 for (size_t i=0; i<fWord.size(); i++)
1339 {
1340 basename = fWord[i].fWordName;
1341 values.push_back(basename, 'I');
1342 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1343 }
1344 }
1345 else if(fHistoType==kHelSavePattern)
1346 {
1347 basename = "actual_helicity"; //predicted actual helicity before being delayed.
1348 values.push_back(basename, 'I');
1349 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1350 //
1351 basename = "actual_pattern_polarity";
1352 values.push_back(basename, 'I');
1353 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1354 //
1355 basename = "actual_previous_pattern_polarity";
1356 values.push_back(basename, 'I');
1357 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1358 //
1359 basename = "delayed_pattern_polarity";
1360 values.push_back(basename, 'I');
1361 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1362 //
1363 basename = "pattern_number";
1364 values.push_back(basename, 'I');
1365 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1366 //
1367 basename = "pattern_seed";
1368 values.push_back(basename, 'I');
1369 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1370 //
1371 for (size_t i=0; i<fWord.size(); i++)
1372 {
1373 basename = fWord[i].fWordName;
1374 values.push_back(basename, 'I');
1375 tree->Branch(basename, &(values.back<Double_t>()), basename+"/I");
1376 }
1377 }
1378
1379 return;
1380}
1381
1382void QwHelicity::ConstructBranch(TTree *tree, TString &prefix)
1383{
1384 TString basename;
1385
1386 SetHistoTreeSave(prefix);
1388 {
1389 //do nothing
1390 }
1391 else if(fHistoType==kHelSaveMPS)
1392 {
1393 // basename = "actual_helicity"; //predicted actual helicity before being delayed.
1394 // tree->Branch(basename, &fHelicityActual, basename+"/I");
1395 //
1396 basename = "delayed_helicity"; //predicted delayed helicity
1397 tree->Branch(basename, &fHelicityDelayed, basename+"/I");
1398 //
1399 basename = "reported_helicity"; //delayed helicity reported by the input register.
1400 tree->Branch(basename, &fHelicityReported, basename+"/I");
1401 //
1402 basename = "pattern_phase";
1403 tree->Branch(basename, &fPatternPhaseNumber, basename+"/I");
1404 //
1405 basename = "pattern_number";
1406 tree->Branch(basename, &fPatternNumber, basename+"/I");
1407 //
1408 basename = "pattern_seed";
1409 tree->Branch(basename, &fPatternSeed, basename+"/I");
1410 //
1411 basename = "event_number";
1412 tree->Branch(basename, &fEventNumber, basename+"/I");
1413 }
1414 else if(fHistoType==kHelSavePattern)
1415 {
1416 basename = "actual_helicity"; //predicted actual helicity before being delayed.
1417 tree->Branch(basename, &fHelicityActual, basename+"/I");
1418 //
1419 basename = "actual_pattern_polarity";
1420 tree->Branch(basename, &fActualPatternPolarity, basename+"/I");
1421 //
1422 basename = "actual_previous_pattern_polarity";
1423 tree->Branch(basename, &fPreviousPatternPolarity, basename+"/I");
1424 //
1425 basename = "delayed_pattern_polarity";
1426 tree->Branch(basename, &fDelayedPatternPolarity, basename+"/I");
1427 //
1428 basename = "pattern_number";
1429 tree->Branch(basename, &fPatternNumber, basename+"/I");
1430 //
1431 basename = "pattern_seed";
1432 tree->Branch(basename, &fPatternSeed, basename+"/I");
1433
1434 for (size_t i=0; i<fWord.size(); i++)
1435 {
1436 basename = fWord[i].fWordName;
1437 tree->Branch(basename, &fWord[i].fValue, basename+"/I");
1438 }
1439 }
1440
1441 return;
1442}
1443
1444void QwHelicity::ConstructBranch(TTree *tree, TString &prefix, QwParameterFile& trim_file)
1445{
1446 TString basename;
1447
1448 SetHistoTreeSave(prefix);
1450 {
1451 //do nothing
1452 }
1453 else if(fHistoType==kHelSaveMPS)
1454 {
1455 // basename = "actual_helicity"; //predicted actual helicity before being delayed.
1456 // tree->Branch(basename, &fHelicityActual, basename+"/I");
1457 //
1458 basename = "delayed_helicity"; //predicted delayed helicity
1459 tree->Branch(basename, &fHelicityDelayed, basename+"/I");
1460 //
1461 basename = "reported_helicity"; //delayed helicity reported by the input register.
1462 tree->Branch(basename, &fHelicityReported, basename+"/I");
1463 //
1464 basename = "pattern_phase";
1465 tree->Branch(basename, &fPatternPhaseNumber, basename+"/I");
1466 //
1467 basename = "pattern_number";
1468 tree->Branch(basename, &fPatternNumber, basename+"/I");
1469 //
1470 basename = "pattern_seed";
1471 tree->Branch(basename, &fPatternSeed, basename+"/I");
1472 //
1473 basename = "event_number";
1474 tree->Branch(basename, &fEventNumber, basename+"/I");
1475 }
1476 else if(fHistoType==kHelSavePattern)
1477 {
1478 basename = "actual_helicity"; //predicted actual helicity before being delayed.
1479 tree->Branch(basename, &fHelicityActual, basename+"/I");
1480 //
1481 basename = "actual_pattern_polarity";
1482 tree->Branch(basename, &fActualPatternPolarity, basename+"/I");
1483 //
1484 basename = "actual_previous_pattern_polarity";
1485 tree->Branch(basename, &fPreviousPatternPolarity, basename+"/I");
1486 //
1487 basename = "delayed_pattern_polarity";
1488 tree->Branch(basename, &fDelayedPatternPolarity, basename+"/I");
1489 //
1490 basename = "pattern_number";
1491 tree->Branch(basename, &fPatternNumber, basename+"/I");
1492 //
1493 basename = "pattern_seed";
1494 tree->Branch(basename, &fPatternSeed, basename+"/I");
1495
1496 for (size_t i=0; i<fWord.size(); i++)
1497 {
1498 basename = fWord[i].fWordName;
1499 tree->Branch(basename,&fWord[i].fValue, basename+"/I");
1500 }
1501
1502 }
1503
1504
1505 return;
1506}
1507
1509{
1510
1511 size_t index=fTreeArrayIndex;
1513 {
1514 // values[index++] = fHelicityActual;
1515 values.SetValue(index++, fHelicityDelayed);
1516 values.SetValue(index++, fHelicityReported);
1517 values.SetValue(index++, fPatternPhaseNumber);
1518 values.SetValue(index++, fPatternNumber);
1519 values.SetValue(index++, fPatternSeed);
1520 values.SetValue(index++, fEventNumber);
1521 for (size_t i=0; i<fWord.size(); i++)
1522 values.SetValue(index++, fWord[i].fValue);
1523 }
1524 else if(fHistoType==kHelSavePattern)
1525 {
1526 values.SetValue(index++, fHelicityActual);
1527 values.SetValue(index++, fActualPatternPolarity);
1528 values.SetValue(index++, fPreviousPatternPolarity);
1529 values.SetValue(index++, fDelayedPatternPolarity);
1530 values.SetValue(index++, fPatternNumber);
1531 values.SetValue(index++, fPatternSeed);
1532 for (size_t i=0; i<fWord.size(); i++){
1533 values.SetValue(index++, fWord[i].fValue);
1534 }
1535 }
1536
1537 return;
1538}
1539
1540#ifdef HAS_RNTUPLE_SUPPORT
1541void QwHelicity::ConstructNTupleAndVector(std::unique_ptr<ROOT::RNTupleModel>& model, TString &prefix, std::vector<Double_t>& values, std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
1542{
1543 SetHistoTreeSave(prefix);
1544
1545 fTreeArrayIndex = values.size();
1546 TString basename;
1548 {
1549 //do nothing
1550 }
1551 else if(fHistoType==kHelSaveMPS)
1552 {
1553 basename = "delayed_helicity"; //predicted delayed helicity
1554 values.push_back(0.0);
1555 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1556 //
1557 basename = "reported_helicity"; //delayed helicity reported by the input register.
1558 values.push_back(0.0);
1559 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1560 //
1561 basename = "pattern_phase";
1562 values.push_back(0.0);
1563 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1564 //
1565 basename = "pattern_number";
1566 values.push_back(0.0);
1567 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1568 //
1569 basename = "pattern_seed";
1570 values.push_back(0.0);
1571 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1572 //
1573 basename = "event_number";
1574 values.push_back(0.0);
1575 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1576 //
1577 for (size_t i=0; i<fWord.size(); i++)
1578 {
1579 basename = fWord[i].fWordName;
1580 values.push_back(0.0);
1581 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1582 }
1583 }
1584 else if(fHistoType==kHelSavePattern)
1585 {
1586 basename = "actual_helicity"; //predicted actual helicity before being delayed.
1587 values.push_back(0.0);
1588 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1589 //
1590 basename = "actual_pattern_polarity";
1591 values.push_back(0.0);
1592 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1593 //
1594 basename = "actual_previous_pattern_polarity";
1595 values.push_back(0.0);
1596 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1597 //
1598 basename = "delayed_pattern_polarity";
1599 values.push_back(0.0);
1600 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1601 //
1602 basename = "pattern_number";
1603 values.push_back(0.0);
1604 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1605 //
1606 basename = "pattern_seed";
1607 values.push_back(0.0);
1608 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1609 //
1610 for (size_t i=0; i<fWord.size(); i++){
1611 basename = fWord[i].fWordName;
1612 values.push_back(0.0);
1613 fieldPtrs.push_back(model->MakeField<Double_t>(basename.Data()));
1614 }
1615 }
1616
1617 fTreeArrayNumEntries = values.size() - fTreeArrayIndex;
1618}
1619
1620void QwHelicity::FillNTupleVector(std::vector<Double_t>& values) const
1621{
1622 // Use the same logic as FillTreeVector
1623 size_t index=fTreeArrayIndex;
1625 {
1626 values[index++] = fHelicityDelayed;
1627 values[index++] = fHelicityReported;
1628 values[index++] = fPatternPhaseNumber;
1629 values[index++] = fPatternNumber;
1630 values[index++] = fPatternSeed;
1631 values[index++] = fEventNumber;
1632 for (size_t i=0; i<fWord.size(); i++)
1633 values[index++] = fWord[i].fValue;
1634 }
1635 else if(fHistoType==kHelSavePattern)
1636 {
1637 values[index++] = fHelicityActual;
1638 values[index++] = fActualPatternPolarity;
1639 values[index++] = fPreviousPatternPolarity;
1640 values[index++] = fDelayedPatternPolarity;
1641 values[index++] = fPatternNumber;
1642 values[index++] = fPatternSeed;
1643 for (size_t i=0; i<fWord.size(); i++){
1644 values[index++] = fWord[i].fValue;
1645 }
1646 }
1647}
1648#endif // HAS_RNTUPLE_SUPPORT
1649
1650#ifdef __USE_DATABASE__
1651void QwHelicity::FillDB(QwParityDB *db, TString type)
1652{
1653 if (type=="yield" || type=="asymmetry")
1654 return;
1655
1656 //db->Connect();
1657
1658 // No database operation
1659
1660 //db->Disconnect();
1661}
1662
1663
1664
1665void QwHelicity::FillErrDB(QwParityDB *db, TString type)
1666{
1667 return;
1668}
1669#endif // __USE_DATABASE__
1670
1671
1672UInt_t QwHelicity::GetRandbit(UInt_t& ranseed){
1673 Bool_t status = false;
1674
1675 if (fRandBits == 24)
1676 status = GetRandbit24(ranseed);
1677 if (fRandBits == 30)
1678 status = GetRandbit30(ranseed);
1679
1680 return status;
1681}
1682
1683UInt_t QwHelicity::GetRandbit24(UInt_t& ranseed)
1684{
1685 /** This is a 24 bit random bit generator according to the "new" algorithm
1686 described in "G0 Helicity Digital Controls" by E. Stangland, R. Flood, H. Dong.
1687
1688
1689 The helicity board uses a maximum-length linear feedback shift registers
1690 for the generation of a pseudo-random sequence of bits. The length of the
1691 register (24 bits or 30 bits) defines the length before a sequence is
1692 repeated: 2^n - 1.
1693
1694 For a mathematical introduction to the generation of pseudo-random numbers
1695 with maximum-length linear feedback shift registers (LFSR), see the
1696 following web references:
1697 http://en.wikipedia.org/wiki/Linear_feedback_shift_register
1698 http://www.newwaveinstruments.com/resources/articles/m_sequence_linear_feedback_shift_register_lfsr.htm
1699
1700 In particular, the used solutions are to place XNOR taps at the bits
1701 24 stages, 4 taps: (47 sets)
1702 [24, 23, 21, 20]
1703 30 stages, 4 taps: (104 sets)
1704 [30, 29, 28, 7]
1705
1706 The 24 stage solution we use has been mirrored by transforming [m, A, B, C]
1707 into [m, m-C, m-B, m-A]. This goes through the sequence in the opposite
1708 direction.
1709 */
1710
1711 const UInt_t IB1 = 1; //Bit 1 of shift register 000000000000000000000001
1712 const UInt_t IB3 = 4; //Bit 3 of shift register 000000000000000000000100
1713 const UInt_t IB4 = 8; //Bit 4 of shift register 000000000000000000001000
1714 const UInt_t IB24 = 8388608; //Bit 24 of shift register 100000000000000000000000
1715 const UInt_t MASK = IB1+IB3+IB4+IB24; //Sum of the four feedback bits is 100000000000000000001101
1716
1717 UInt_t result; //The generated pattern
1718
1719 if(ranseed<=0)
1720 {
1721 QwError << "ranseed must be greater than zero!" << QwLog::endl;
1722 result = 0;
1723 }
1724
1725 if(ranseed & IB24) // if bit 24 of ranseed = 1, then output 1
1726 {
1727 ranseed = (((ranseed^MASK) << 1)|IB1);
1728 result = 1;
1729 }
1730 else
1731 {
1732 ranseed <<= 1;
1733 result = 0;
1734 }
1735 return(result);
1736
1737}
1738
1739
1740UInt_t QwHelicity::GetRandbit30(UInt_t& ranseed)
1741{
1742 /* For an explanation of the algorithm, see above in GetRandbit24() */
1743
1744 UInt_t bit7 = (ranseed & 0x00000040) != 0;
1745 UInt_t bit28 = (ranseed & 0x08000000) != 0;
1746 UInt_t bit29 = (ranseed & 0x10000000) != 0;
1747 UInt_t bit30 = (ranseed & 0x20000000) != 0;
1748
1749 UInt_t result = (bit30 ^ bit29 ^ bit28 ^ bit7) & 0x1;
1750
1751 if(ranseed<=0) {
1752 QwError << "ranseed must be greater than zero!" << QwLog::endl;
1753 result = 0;
1754 }
1755 ranseed = ( (ranseed << 1) | result ) & 0x3FFFFFFF;
1756
1757 return(result);
1758}
1759
1760
1761UInt_t QwHelicity::GetRandomSeed(UShort_t* first24randbits)
1762{
1763 Bool_t ldebug=0;
1764 QwDebug << " Entering QwHelicity::GetRandomSeed \n";
1765
1766 /** This the random seed generator used in G0 (L.Jianglai)
1767 Here we get the 24 random bits and derive the random seed from that.
1768 random seed : b24 b23 b22.....b2 b1
1769 first 24 random bit from this seed: h1 h2 h3 ....h23 h24
1770 we have,
1771 b23 = h1, b22 = h2,... b5 = h20,
1772 h21^b24 = b4 , h3^b24^b23 = b3 ,h23^b23^b22 = b2, h24^b22^b24 = b1.
1773 Thus by using h1,...h24, we can derive the b24,..b1 of the randseed.
1774 */
1775
1776 UShort_t b[25];
1777 UInt_t ranseed = 0;
1778
1779 if(ldebug)
1780 {
1781 for(size_t i=1;i<25;i++)
1782 std::cout << i << " : " << first24randbits[i] << "\n";
1783 }
1784
1785 for(size_t i=24;i>=5;i--) b[i]= first24randbits[24-i+1]; //fill h24..h5
1786
1787 // fill b[4] to b[1]
1788 b[4] = first24randbits[21]^b[24]; //h21^b24 = b4
1789 b[3] = first24randbits[22]^b[24]^b[23]; //h22^b24^b23 = b3
1790 b[2] = first24randbits[23]^b[23]^b[22];// h23^b23^b22 = b2
1791 b[1] = first24randbits[24]^b[21]^b[22]^b[24];// h24^b22^b24 = b1
1792
1793 ///assign the values in the h array and into the sead
1794 for(size_t i=24;i>=1;i--) ranseed = (ranseed << 1) | (b[i]&1);
1795
1796 ranseed = ranseed&0xFFFFFF; //put a mask
1797
1798 QwDebug << " seed =" << ranseed <<QwLog::endl;
1799 QwDebug << " Exiting QwHelicity::GetRandomSeed \n";
1800
1801
1802 return ranseed;
1803
1804}
1805
1806
1808{
1809 Int_t ldebug = kFALSE;
1810
1811 if(ldebug) std::cout << "Entering QwHelicity::RunPredictor for fEventNumber, " << fEventNumber
1812 << ", fPatternNumber, " << fPatternNumber
1813 << ", and fPatternPhaseNumber, " << fPatternPhaseNumber << std::endl;
1814
1815 /**Update the random seed if the new event is from a different pattern.
1816 Check the difference between old pattern number and the new one and
1817 to see how many patterns we have missed or skipped. Then loop back
1818 to get the correct pattern polarities.
1819 */
1820
1821
1822 for (int i = 0; i < fPatternNumber - fPatternNumberOld; i++) //got a new pattern
1823 {
1827 QwDebug << "Predicting : seed actual, delayed: " << iseed_Actual
1828 << ":" << iseed_Delayed <<QwLog::endl;
1829 }
1830
1831 /**Predict the helicity according to pattern
1832 Defined patterns:
1833 Pair: +- or -+
1834 Quartet: +--+ or -++-
1835 Octet: +--+-++- or -++-+--+
1836 Symmetric octet: +-+--+-+ or -+-++-+-
1837 Octo-quad: +--++--++--++--+-++--++--++--++-
1838 */
1839
1840 Int_t localphase = fPatternPhaseNumber-fMinPatternPhase;//Paul's modifications
1841
1842 Int_t localbit,indexnum,shiftnum;
1843 indexnum = TMath::FloorNint(localphase/32.);
1844 shiftnum = localphase - indexnum*32;
1845 //std::cout << localphase << " " << indexnum << " " << shiftnum << " "<< fHelicityBitPattern.size() << std::endl;
1846 localbit = ((fHelicityBitPattern.at(indexnum))>>shiftnum)&0x1;
1847 //std::cout<< localphase << " " << indexnum << " " << shiftnum <<std::hex << fHelicityBitPattern.at(indexnum) << std::dec << " " << localbit << std::endl;
1848 // Use the stored helicity bit pattern to calculate the helicity of this window
1849 if (localbit == (fHelicityBitPattern[0] & 0x1)) {
1852 } else {
1855 }
1856 // Past highest pattern phase
1857 if (localphase > fMaxPatternPhase)
1859
1860 if(ldebug){
1861 std::cout << "Predicted Polarity ::: Delayed ="
1862 << fDelayedPatternPolarity << " Actual ="
1863 << fActualPatternPolarity << "\n";
1864 std::cout << "Predicted Helicity ::: Delayed Helicity=" << fHelicityDelayed
1865 << " Actual Helicity=" << fHelicityActual << " Reported Helicity=" << fHelicityReported << "\n";
1866 QwError << "Exiting QwHelicity::RunPredictor " << QwLog::endl;
1867
1868 }
1869
1870 return;
1871}
1872
1873
1875{
1876 Bool_t status = false;
1877
1878 if (fRandBits == 24)
1879 status = CollectRandBits24();
1880 if (fRandBits == 30)
1881 status = CollectRandBits30();
1882
1883 return status;
1884}
1885
1886
1887
1889{
1890 //routine to collect 24 random bits before getting the randseed for prediction
1891 Bool_t ldebug = kFALSE;
1892 const UInt_t ranbit_goal = 24;
1893
1894 QwDebug << "QwHelicity::Entering CollectRandBits24...." << QwLog::endl;
1895
1896
1897 if (n_ranbits==ranbit_goal) return kTRUE;
1898
1900 {
1901 QwMessage << "Collecting information from event #" << fEventNumber << " to generate helicity seed"
1902 << "(need 24 bit, so far got " << n_ranbits << " bits )" << QwLog::endl;
1903 }
1904
1905
1906 static UShort_t first24bits[25]; //array to store the first 24 bits
1907
1908 fGoodHelicity = kFALSE; //reset before prediction begins
1909 if(IsContinuous())
1910 {
1912 {
1913 first24bits[n_ranbits+1] = fHelicityReported;
1914 n_ranbits ++;
1915 if(ldebug)
1916 {
1917 std::cout << " event number" << fEventNumber << ", fPatternNumber"
1918 << fPatternNumber << ", n_ranbit" << n_ranbits
1919 << ", fHelicityReported" << fHelicityReported << "\n";
1920 }
1921
1922 if(n_ranbits == ranbit_goal ) //If its the 24th consecative random bit,
1923 {
1924 if(ldebug)
1925 {
1926 std::cout << "Collected 24 random bits. Get the random seed for the predictor." << "\n";
1927 for(UInt_t i=0;i<ranbit_goal;i++) std::cout << " i:bit =" << i << ":" << first24bits[i] << "\n";
1928 }
1929 iseed_Delayed = GetRandomSeed(first24bits);
1930 //This random seed will predict the helicity of the event (24+fHelicityDelay) patterns before;
1931 // run GetRandBit 24 times to get the delayed helicity for this event
1932 QwDebug << "The reported seed 24 patterns ago = " << iseed_Delayed << "\n";
1933
1934 for(UInt_t i=0;i<ranbit_goal;i++) fDelayedPatternPolarity =GetRandbit(iseed_Delayed);
1936 //The helicity of the first phase in a pattern is
1937 //equal to the polarity of the pattern
1938
1939 //Check whether the reported helicity is the same as the helicity predicted by the random seed
1940
1941 if(fHelicityDelay >=0){
1943 for(Int_t i=0; i<fHelicityDelay; i++)
1944 {
1945 QwDebug << "Delaying helicity " << QwLog::endl;
1948 }
1949 }
1950 else
1951 {
1952 QwError << "QwHelicity::CollectRandBits We cannot handle negative delay(prediction) in the reported helicity. Exiting." << QwLog::endl;
1954 }
1955
1957 }
1958 }
1959 }
1960 else // while collecting the seed, we encounter non continuous events.
1961 {
1963 QwError << "QwHelicity::CollectRandBits, while collecting the seed, we encountered non continuous events: need to reset the seed collecting " << QwLog::endl
1964 << " event number=" << fEventNumber << ", fPatternNumber="
1965 << fPatternNumber << ", fPatternPhaseNumber=" << fPatternPhaseNumber << QwLog::endl;
1966 }
1967
1968 //else n randbits have been set to zero in the error checking routine
1969 //start over from the next pattern
1970 QwDebug << "QwHelicity::CollectRandBits24 => Done collecting ..." << QwLog::endl;
1971
1972 return kFALSE;
1973
1974}
1975
1976
1978{
1979 /** Starting to collect 30 bits/helicity state to get the
1980 random seed for the 30 bit helicity predictor.
1981 These bits (1/0) are the reported helicity states of the first event
1982 of each new pattern or the so called pattern polarity.*/
1983
1984 // Bool_t ldebug = kFALSE;
1985 const UInt_t ranbit_goal = 30;
1986
1987 /** If we have finished collecting the bits then ignore the rest of this function and return true.
1988 No need to recollect!*/
1989 if (n_ranbits == ranbit_goal) return kTRUE;
1990
1991 /** If we are still collecting the bits, make sure we collect them from only the
1992 events with the minimum pattern phase.*/
1993
1994 if (n_ranbits < ranbit_goal && fPatternPhaseNumber == fMinPatternPhase) {
1995 QwMessage << "Collecting information (";
1996 if (fHelicityReported == 1) QwMessage << "+";
1997 else QwMessage << "-";
1998 QwMessage << ") from event #" << fEventNumber << " to generate helicity seed ";
1999 QwMessage << "(need " << ranbit_goal << " bit, so far got " << n_ranbits << " bits )" << QwLog::endl;
2000 }
2001
2002 /** If the events are continuous, start to make the ranseed for the helicity
2003 pattern we are getting which is the delayed helicity.*/
2004
2005 fGoodHelicity = kFALSE; //reset before prediction begins
2006
2007 if(IsContinuous()) {
2008 /** Make sure we are at the beginning of a valid pattern. */
2010 iseed_Delayed = ((iseed_Delayed << 1)&0x3FFFFFFF)|fHelicityReported;
2011 QwDebug << "QwHelicity:: CollectRandBits30: Collecting randbit " << n_ranbits << ".." << QwLog::endl;
2012 n_ranbits++;
2013
2014 /** If we got the 30th bit,*/
2015 if(n_ranbits == ranbit_goal){
2016 QwDebug << "QwHelicity:: CollectRandBits30: done Collecting 30 randbits" << QwLog::endl;
2017
2018 /** set the polarity of the current pattern to be equal to the reported helicity,*/
2020 QwDebug << "QwHelicity:: CollectRandBits30: delayedpatternpolarity =" << fDelayedPatternPolarity << QwLog::endl;
2021
2022 /** then use it as the delayed helicity, */
2024
2025 /**if the helicity is delayed by a positive number of patterns then loop the delayed ranseed backward to get the ranseed
2026 for the actual helicity */
2027 if(fHelicityDelay >=0){
2029 for(Int_t i=0; i<fHelicityDelay; i++) {
2030 /**, get the pattern polarity for the actual pattern using that actual ranseed.*/
2033 }
2034 } else {
2035 /** If we have a negative delay. Reset the predictor.*/
2036 QwError << "QwHelicity::CollectRandBits30: We cannot handle negative delay(prediction) in the reported helicity. Exiting." << QwLog::endl;
2038 }
2039 /** If all is well so far, set the actual pattern polarity as the actual helicity.*/
2041 }
2042 }
2043 } else {
2044 /** while collecting the seed, we encounter non continuous events.Discard bit. Reset the predition*/
2046 QwWarning << "QwHelicity::CollectRandBits30: While collecting the seed, we encountered non continuous events: Need to reset the seed collecting " << QwLog::endl;
2047 QwDebug << " event number=" << fEventNumber << ", fPatternNumber="<< fPatternNumber << ", fPatternPhaseNumber=" << fPatternPhaseNumber << QwLog::endl;
2048 }
2049 return kFALSE;
2050}
2051
2052
2054{
2055 Bool_t ldebug=kFALSE;
2056
2057 if(ldebug) std::cout << "Entering QwHelicity::PredictHelicity \n";
2058
2059 /**Routine to predict the true helicity from the delayed helicity.
2060 Helicities are usually delayed by 8 events or 2 quartets. This delay
2061 can now be set as a cmd line option.
2062 */
2063
2064 if(CollectRandBits()) {
2065 /**After accumulating 24/30 helicity bits, iseed is up-to-date.
2066 If nothing goes wrong, n-ranbits will stay as 24/30
2067 Reset it to zero if something goes wrong.
2068 */
2069
2070 if(ldebug) std::cout << "QwHelicity::PredictHelicity=>Predicting the helicity \n";
2071 RunPredictor();
2072
2073 /** If not good helicity, start over again by resetting the predictor. */
2074 if(!IsGoodHelicity())
2076 }
2077
2078 if(ldebug) std::cout << "n_ranbit exiting the function = " << n_ranbits << "\n";
2079
2080 return;
2081}
2082
2083
2084
2086{
2087 /**Sets the number of bits the helicity reported gets delayed with.
2088 We predict helicity only if there is a non-zero pattern delay given. */
2089
2090 if(delay>=0){
2091 fHelicityDelay = delay;
2092 if(delay == 0){
2093 QwWarning << "QwHelicity : SetHelicityDelay :: helicity delay is set to 0."
2094 << " Disabling helicity predictor and using reported helicity information."
2095 << QwLog::endl;
2096 fUsePredictor = kFALSE;
2097 }
2098 else
2099 fUsePredictor = kTRUE;
2100 }
2101 else
2102 QwError << "QwHelicity::SetHelicityDelay We cannot handle negative delay in the prediction of delayed helicity. Exiting.." << QwLog::endl;
2103
2104 return;
2105}
2106
2107
2109{
2110 fHelicityBitPattern.clear();
2112 /* // Set the helicity pattern bits
2113 if (parity(bits) == 0)
2114 fHelicityBitPattern = bits;
2115 else QwError << "What, exactly, are you trying to do ?!?!?" << QwLog::endl;
2116 */
2117 // Notify the user
2118 QwMessage << " fPatternBits 0x" ;
2119 for (int i = fHelicityBitPattern.size()-1;i>=0; i--){
2120 QwMessage << std::hex << fHelicityBitPattern[i] << " ";
2121 }
2122 QwMessage << std::dec << QwLog::endl;
2123}
2124
2126{
2127 /**Start a new helicity prediction sequence.*/
2128
2129 QwWarning << "QwHelicity::ResetPredictor: Resetting helicity prediction!" << QwLog::endl;
2130 n_ranbits = 0;
2131 fGoodHelicity = kFALSE;
2132 fGoodPattern = kFALSE;
2133 return;
2134}
2135
2136
2137
2139{
2140 Bool_t ldebug = kFALSE;
2141 if(Compare(value))
2142 {
2143
2144 //QwHelicity* input= (QwHelicity*)value;
2146 QwHelicity* input= dynamic_cast<QwHelicity*>(value);
2147
2148 for(size_t i=0;i<input->fWord.size();i++)
2149 this->fWord[i].fValue=input->fWord[i].fValue;
2150 this->fHelicityActual = input->fHelicityActual;
2151 this->fPatternNumber = input->fPatternNumber;
2152 this->fPatternSeed = input->fPatternSeed;
2154 this->fEventNumber=input->fEventNumber;
2159 this->fHelicityActual=input->fHelicityActual;
2163 this->fGoodHelicity=input->fGoodHelicity;
2164 this->fGoodPattern=input->fGoodPattern;
2165 this->fIgnoreHelicity = input->fIgnoreHelicity;
2166
2167 this->fErrorFlag = input->fErrorFlag;
2168 this->fEventNumberFirst = input->fEventNumberFirst;
2170 this->fNumMissedGates = input->fNumMissedGates;
2174
2175 if(ldebug){
2176 std::cout << "QwHelicity::operator = this->fPatternNumber=" << this->fPatternNumber << std::endl;
2177 std::cout << "input->fPatternNumber=" << input->fPatternNumber << "\n";
2178 }
2179 }
2180
2181 return *this;
2182}
2183
2185{
2186 // Bool_t localdebug=kFALSE;
2187 QwDebug << "Entering QwHelicity::operator+= adding " << value->GetName() << " to " << this->GetName() << " " << QwLog::endl;
2188
2189 //this routine is most likely to be called during the computatin of asymmetry
2190 //this call doesn't make too much sense for this class so the following lines
2191 //are only use to put safe gards testing for example if the two instantiation indeed
2192 // refers to elements in the same pattern.
2193 CheckPatternNum(value);
2194 MergeCounters(value);
2195 return *this;
2196}
2197
2199{
2200 // Bool_t localdebug=kFALSE;
2201 if(Compare(value)) {
2202 QwHelicity* input= dynamic_cast<QwHelicity*>(value);
2203 QwDebug << "QwHelicity::MergeCounters: this->fPatternNumber=" << this->fPatternNumber
2204 << ", input->fPatternNumber=" << input->fPatternNumber << QwLog::endl;
2205
2206 this->fErrorFlag |= input->fErrorFlag;
2207
2208 // Make sure the pattern number and poalrity agree!
2209 if(this->fPatternNumber!=input->fPatternNumber)
2210 this->fPatternNumber=-999999;
2212 this->fPatternNumber=-999999;
2213 if (this->fPatternNumber==-999999){
2215 }
2216 }
2217}
2218
2220{
2221 // Bool_t localdebug=kFALSE;
2222 if(Compare(value)) {
2223 QwHelicity* input= dynamic_cast<QwHelicity*>(value);
2224
2225 fEventNumber = (fEventNumber == 0) ? input->fEventNumber :
2226 std::min(fEventNumber, input->fEventNumber);
2227 for (size_t i=0; i<fWord.size(); i++) {
2228 fWord[i].fValue = (fWord[i].fValue == 0) ? input->fWord[i].fValue :
2229 std::min( fWord[i].fValue, input->fWord[i].fValue);
2230 }
2231 }
2232}
2233
2235{
2236 // this is stub function defined here out of completion and uniformity between each subsystem
2237 *this = value1;
2238 CheckPatternNum(value2);
2239 MergeCounters(value2);
2240}
2241
2242void QwHelicity::AccumulateRunningSum(VQwSubsystem* value, Int_t count, Int_t ErrorMask){
2243 if (Compare(value)) {
2244 MergeCounters(value);
2245 QwHelicity* input = dynamic_cast<QwHelicity*>(value);
2246 fPatternNumber = (fPatternNumber <=0 ) ? input->fPatternNumber :
2247 std::min(fPatternNumber, input->fPatternNumber);
2248 // Keep track of the various error quantities, so we can print
2249 // them at the end.
2254 }
2255}
2256
2258{
2259 Bool_t res=kTRUE;
2260 if(typeid(*value)!=typeid(*this)) {
2261 res=kFALSE;
2262 } else {
2263 QwHelicity* input= dynamic_cast<QwHelicity*>(value);
2264 if(input->fWord.size()!=fWord.size()) {
2265 res=kFALSE;
2266 }
2267 }
2268 return res;
2269}
2270
2271UInt_t QwHelicity::BuildHelicityBitPattern(Int_t patternsize){
2272 UInt_t bitpattern = 0;
2273 // Standard helicity board patterns (last to first):
2274 // Pair, quad, octet: -++-+--+ : 0x69
2275 // Hexo-quad: -++--++--++-+--++--++--+ : 0x666999
2276 // Octo-quad: -++--++--++--++-+--++--++--++--+ : 0x66669999
2277 //
2278 //std::cout << fHelicityBitPattern.size() << std::endl;
2279 fHelicityBitPattern.clear();
2280 if (patternsize<8){
2282 } else if (patternsize%2==0 && patternsize>0 && patternsize < 129){
2283 int num_int = TMath::CeilNint(patternsize/32.);
2284 //std::cout << num_int << " " << patternsize << " " << TMath::Ceil(patternsize/32.) << std::endl;
2285 fHelicityBitPattern.resize(num_int);
2286 bitpattern = 0x69969669;
2287 fHelicityBitPattern[0] = bitpattern;
2288 for (int i = 1; i<num_int; i++){
2290 }
2291 /*if (patternsize%8==0){
2292 Int_t halfshift = patternsize/2;
2293 for (Int_t i=0; i<(patternsize/8); i++){
2294 bitpattern += (0x9<<(i*4));
2295 bitpattern += (0x6<<(halfshift+i*4));
2296 }
2297 */
2298 } else {
2299 QwError << "QwHelicity::BuildHelicityBitPattern: "
2300 << "Unable to build standard bit pattern for pattern size of "
2301 << patternsize << ". Try a pattern of 0x69."
2302 << QwLog::endl;
2304 }
2305 //std::cout << fHelicityBitPattern.size() << std::endl;
2306 /*QwMessage << "QwHelicity::BuildHelicityBitPattern: "
2307 << "Built pattern 0x" << std::hex << bitpattern
2308 << std::dec << " for pattern size "
2309 << patternsize << "." << QwLog::endl;
2310 */
2311 QwMessage << "QwHelicity::BuildHelicityBitPattern: "
2312 << "Built pattern 0x";
2313 for (int i = fHelicityBitPattern.size()-1;i>=0; i--){
2314 QwMessage << std::hex << fHelicityBitPattern[i] << " ";
2315 }
2316 QwMessage << std::dec << "for pattern size "
2317 << patternsize << "." << QwLog::endl;
2318 // Now set the bit pattern.
2319 // SetHelicityBitPattern(bitpattern);
2320 return fHelicityBitPattern[0];
2321}
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.
#define REGISTER_SUBSYSTEM_FACTORY(A)
Definition QwFactory.h:270
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
Definition QwHelicity.h:37
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:53
size_type size() const noexcept
Definition QwRootFile.h:81
void push_back(const std::string &name, const char type='D')
Definition QwRootFile.h:195
void SetValue(size_type index, Double_t val)
Definition QwRootFile.h:108
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.
Bool_t HasDataLoaded() const
Subsystem for helicity state management and pattern recognition.
Definition QwHelicity.h:52
void ResetPredictor()
Int_t LoadEventCuts(TString filename) override
Optional event cut file.
Int_t kUserbit
Definition QwHelicity.h:215
Bool_t Compare(VQwSubsystem *source)
Int_t fNumMissedEventBlocks
Definition QwHelicity.h:312
void ConstructBranch(TTree *tree, TString &prefix) override
Construct the branch and tree vector.
Bool_t CheckIORegisterMask(const UInt_t &ioregister, const UInt_t &mask) const
Definition QwHelicity.h:175
void SetHelicityBitPattern(TString hex)
Int_t fPatternNumberOld
Definition QwHelicity.h:229
void ProcessEventInputRegisterMode()
virtual Bool_t IsGoodHelicity()
void ProcessOptions(QwOptions &options) override
Process the command line options.
Int_t GetPhaseNumber()
Int_t kPatternCounter
Definition QwHelicity.h:223
void MergeCounters(VQwSubsystem *value)
Int_t fPatternNumber
Definition QwHelicity.h:229
void SetFirstBits(UInt_t nbits, UInt_t firstbits)
UInt_t GetRandbit30(UInt_t &ranseed)
Int_t GetHelicityDelayed()
Int_t fPatternNumberFirst
Definition QwHelicity.h:301
Long_t GetPatternNumber()
Int_t kMpsCounter
Definition QwHelicity.h:223
Int_t fDelayedPatternPolarity
Reported polarity of the current pattern.
Definition QwHelicity.h:232
void ClearEventData() override
Int_t fMaxPatternPhase
Definition QwHelicity.h:269
Bool_t CollectRandBits30()
Int_t ProcessConfigurationBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words) override
Int_t fHelicityDelayed
Definition QwHelicity.h:234
Int_t fPatternPhaseOffset
Definition QwHelicity.h:293
UInt_t fInputReg_FakeMPS
Definition QwHelicity.h:195
Bool_t IsGoodPatternNumber()
UInt_t n_ranbits
Definition QwHelicity.h:262
Int_t fPatternPhaseNumberOld
Definition QwHelicity.h:228
Bool_t IsGoodPhaseNumber()
Int_t kScalerCounter
Definition QwHelicity.h:219
virtual UInt_t GetRandbit(UInt_t &ranseed)
Int_t fPatternPhaseNumber
Definition QwHelicity.h:228
std::vector< QwWord > fWord
Definition QwHelicity.h:205
Bool_t fHelicityInfoOK
Definition QwHelicity.h:292
UInt_t kEventTypeHelMinus
Definition QwHelicity.h:225
void FillHistograms() override
Fill the histograms for this subsystem.
UInt_t fEventType
Definition QwHelicity.h:297
VQwSubsystem & operator+=(VQwSubsystem *value) override
void SetHelicityDelay(Int_t delay)
static const Int_t kUndefinedHelicity
Definition QwHelicity.h:256
Int_t fHelicityDelay
Definition QwHelicity.h:266
Int_t LoadInputParameters(TString pedestalfile) override
Mandatory parameter file definition.
void SetHistoTreeSave(const TString &prefix)
virtual Bool_t CollectRandBits()
virtual void ConstructHistograms()
Construct the histograms for this subsystem.
Int_t kPatternPhase
Definition QwHelicity.h:223
Int_t fRandBits
Definition QwHelicity.h:290
void ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values) override
Construct the branch and tree vector.
Bool_t fIgnoreHelicity
Definition QwHelicity.h:295
UInt_t fErrorFlag
Definition QwHelicity.h:316
UInt_t GetEventcutErrorFlag() override
Return the error flag to the top level routines related to stability checks and ErrorFlag updates.
UInt_t iseed_Actual
Definition QwHelicity.h:263
UInt_t iseed_Delayed
Definition QwHelicity.h:264
void RunPredictor()
Bool_t fGoodHelicity
Definition QwHelicity.h:242
Int_t LoadChannelMap(TString mapfile) override
Mandatory map file definition.
void PrintErrorCounters() const override
Bool_t IsGoodEventNumber()
Long_t GetEventNumber()
Int_t fPreviousPatternPolarity
True polarity of the previous pattern.
Definition QwHelicity.h:233
Int_t fHelicityDecodingMode
Definition QwHelicity.h:208
QwHelicity()
Private default constructor (not implemented, will throw linker error on use)
UInt_t fInputReg_HelMinus
Definition QwHelicity.h:197
Int_t fHistoType
Definition QwHelicity.h:245
Int_t fPatternSeed
Definition QwHelicity.h:230
Bool_t fUsePredictor
Definition QwHelicity.h:291
UInt_t BuildHelicityBitPattern(Int_t patternsize)
@ kDefaultInputReg_FakeMPS
Definition QwHelicity.h:193
@ kDefaultInputReg_PatternSync
Definition QwHelicity.h:192
@ kDefaultInputReg_HelPlus
Definition QwHelicity.h:190
@ kDefaultInputReg_HelMinus
Definition QwHelicity.h:191
void CheckPatternNum(VQwSubsystem *value)
@ kHelInputMollerMode
Definition QwHelicity.h:187
@ kHelInputRegisterMode
Definition QwHelicity.h:185
Int_t ProcessEvBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words) override
TODO: The non-event-type-aware ProcessEvBuffer routine should be replaced with the event-type-aware v...
Definition QwHelicity.h:91
void SetEventPatternPhase(Int_t event, Int_t pattern, Int_t phase)
Bool_t fHelicityBitPlus
Definition QwHelicity.h:240
Int_t kInputRegister
Definition QwHelicity.h:223
UInt_t fInputReg_HelPlus
Definition QwHelicity.h:196
void FillTreeVector(QwRootTreeBranchVector &values) const override
Fill the tree vector.
void ProcessEventUserbitMode()
Process helicity information from userbit configuration data.
VQwSubsystem & operator=(VQwSubsystem *value) override
Assignment Note: Must be called at the beginning of all subsystems routine call to operator=(VQwSubsy...
void Ratio(VQwSubsystem *numer, VQwSubsystem *denom) override
static const std::vector< UInt_t > kDefaultHelicityBitPattern
Definition QwHelicity.h:43
UInt_t fInputReg_PairSync
Definition QwHelicity.h:199
UInt_t kEventTypeHelPlus
Definition QwHelicity.h:225
void ClearErrorCounters()
Definition QwHelicity.h:303
Bool_t fHelicityBitMinus
Definition QwHelicity.h:241
void Print() const
Int_t GetHelicityActual()
Int_t fHelicityReported
Definition QwHelicity.h:234
Bool_t fSuppressMPSErrorMsgs
Definition QwHelicity.h:320
std::vector< UInt_t > fHelicityBitPattern
Definition QwHelicity.h:203
UInt_t fInputReg_PatternSync
Definition QwHelicity.h:198
Bool_t ApplySingleEventCuts() override
Apply the single event cuts.
Int_t fEventNumberOld
Definition QwHelicity.h:227
Int_t fHelicityActual
Definition QwHelicity.h:234
Int_t fNumMultSyncErrors
Definition QwHelicity.h:313
void ProcessEventInputMollerMode()
size_t fTreeArrayNumEntries
Definition QwHelicity.h:261
size_t fTreeArrayIndex
Definition QwHelicity.h:260
Int_t fNumHelicityErrors
Definition QwHelicity.h:314
void ProcessEvent() override
Int_t fNumMissedGates
Definition QwHelicity.h:311
UInt_t GetRandbit24(UInt_t &ranseed)
Int_t fEventNumberFirst
Definition QwHelicity.h:300
void AccumulateRunningSum(VQwSubsystem *value, Int_t count=0, Int_t ErrorMask=0xFFFFFFF) override
Update the running sums for devices.
Bool_t IsContinuous()
std::vector< std::pair< Int_t, Int_t > > fWordsPerSubbank
Definition QwHelicity.h:206
Bool_t CollectRandBits24()
void IncrementErrorCounters() override
Increment the error counters.
Int_t GetHelicityReported()
UInt_t GetRandomSeed(UShort_t *first24randbits)
void EncodeEventData(std::vector< UInt_t > &buffer) override
Int_t fActualPatternPolarity
True polarity of the current pattern.
Definition QwHelicity.h:231
Bool_t fGoodPattern
Definition QwHelicity.h:243
Int_t fEventNumber
Definition QwHelicity.h:227
void PredictHelicity()
Int_t fMinPatternPhase
Definition QwHelicity.h:270
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)