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* Contributor: Arindam Sen (asen@jlab.org) *
5* Time-stamp: November, 2025 *
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
17// Qweak headers
18#include "QwRootFile.h"
19
20// Qweak headers
21#include "QwHistogramHelper.h"
22#include "QwLog.h"
23
25
26//**************************************************//
27/// Default helicity bit pattern of 0x69 represents a -++-+--+ octet
28/// (event polarity listed in reverse time order), where the LSB
29/// of the bit pattern is the first event of the pattern.
30//**************************************************//
31
32/// Constructor with name
44
45//**************************************************//
47: VQwSubsystem(source.GetName()),
48 QwHelicityBase(source.GetName()),
53{
56 // Default helicity delay to two patterns.
58 // Default the EventType flags to HelPlus=1 and HelMinus=4
59 // These are only used in Moller decoding mode.
62 //
66 kUserbit=-1;
72 fHelicityBitPlus=kFALSE;
73 fHelicityBitMinus=kFALSE;
74 fGoodHelicity=kFALSE;
75 fGoodPattern=kFALSE;
77
78 this->fWord.resize(source.fWord.size());
79 for(size_t i=0;i<this->fWord.size();i++)
80 {
81 this->fWord[i].fWordName=source.fWord[i].fWordName;
82 this->fWord[i].fModuleType=source.fWord[i].fModuleType;
83 this->fWord[i].fWordType=source.fWord[i].fWordType;
84 }
91 fEventType = source.fEventType;
93 fRandBits = source.fRandBits;
101 iseed_Actual = source.iseed_Actual;
102 n_ranbits = source.n_ranbits;
103 fEventNumber = source.fEventNumber;
109
110 this->kUserbit = source.kUserbit;
111 this->fIgnoreHelicity = source.fIgnoreHelicity;
112}
113
114//**************************************************//
116{
117 options.AddOptions("Helicity options")
118 ("helicity.seed", po::value<int>(),
119 "Number of bits in random seed");
120 options.AddOptions("Helicity options")
121 ("helicity.bitpattern", po::value<std::string>(),
122 "Helicity bit pattern: 0x1 (pair), 0x9 (quartet), 0x69 (octet), 0x666999 (hexo-quad), 0x66669999 (octo-quad)");
123 options.AddOptions("Helicity options")
124 ("helicity.patternoffset", po::value<int>(),
125 "Set 1 when pattern starts with 1 or 0 when starts with 0");
126 options.AddOptions("Helicity options")
127 ("helicity.patternphase", po::value<int>(),
128 "Maximum pattern phase");
129 options.AddOptions("Helicity options")
130 ("helicity.delay", po::value<int>(),
131 "Default delay is 2 patterns, set at the helicity map file.");
132 options.AddOptions("Helicity options")
133 ("helicity.toggle-mode", po::value<bool>()->default_bool_value(false),
134 "Activates helicity toggle-mode, overriding the 'delay', 'patternphase', 'bitpattern', and 'seed' options.");
135}
136
137//**************************************************//
138
140{
141 // Read the cmd options and override channel map settings
142 QwMessage << "QwHelicity::ProcessOptions" << QwLog::endl;
143 if (options.HasValue("helicity.patternoffset")) {
144 if (options.GetValue<int>("helicity.patternoffset") == 1
145 || options.GetValue<int>("helicity.patternoffset") == 0) {
146 fPatternPhaseOffset = options.GetValue<int>("helicity.patternoffset");
147 QwMessage << " Pattern Phase Offset = " << fPatternPhaseOffset << QwLog::endl;
148 } else QwError << "Pattern phase offset should be 0 or 1!" << QwLog::endl;
149 }
150
151 if (options.HasValue("helicity.patternphase")) {
152 if (options.GetValue<int>("helicity.patternphase") % 2 == 0) {
153 fMaxPatternPhase = options.GetValue<int>("helicity.patternphase");
154 QwMessage << " Maximum Pattern Phase = " << fMaxPatternPhase << QwLog::endl;
155 } else QwError << "Pattern phase should be an even integer!" << QwLog::endl;
156 }
157
158 if (options.HasValue("helicity.seed")) {
159 if (options.GetValue<int>("helicity.seed") == 24
160 || options.GetValue<int>("helicity.seed") == 30) {
161 QwMessage << " Random Bits = " << options.GetValue<int>("helicity.seed") << QwLog::endl;
162 fRandBits = options.GetValue<int>("helicity.seed");
163 } else QwError << "Number of random seed bits should be 24 or 30!" << QwLog::endl;
164 }
165
166 if (options.HasValue("helicity.delay")) {
167 QwMessage << " Helicity Delay = " << options.GetValue<int>("helicity.delay") << QwLog::endl;
168 SetHelicityDelay(options.GetValue<int>("helicity.delay"));
169 }
170
171 if (options.HasValue("helicity.bitpattern")) {
172 QwMessage << " Helicity Pattern ="
173 << options.GetValue<std::string>("helicity.bitpattern")
174 << QwLog::endl;
175 std::string hex = options.GetValue<std::string>("helicity.bitpattern");
177 } else {
178 }
179
180 if (options.GetValue<bool>("helicity.toggle-mode")) {
181 fHelicityDelay = 0;
182 fUsePredictor = kFALSE;
185 }
186
187 // If we have the default Helicity Bit Pattern & a large fMaxPatternPhase,
188 // try to recompute the Helicity Bit Pattern.
190 }
191
192 // Here we're going to try to get the "online" option which
193 // is defined by QwEventBuffer.
194 if (options.HasValue("online")){
195 fSuppressMPSErrorMsgs = options.GetValue<bool>("online");
196 } else {
197 fSuppressMPSErrorMsgs = kFALSE;
198 }
199}
200
201
203{
204 SetDataLoaded(kFALSE);
205 for (size_t i=0;i<fWord.size();i++)
207
208 /**Reset data by setting the old event number, pattern number and pattern phase
209 to the values of the previous event.*/
210 if (fEventNumberFirst==-1 && fEventNumberOld!= -1){
212 }
216 }
217
221
222 //fIgnoreHelicity = kFALSE;
223
224 /**Clear out helicity variables */
228 fHelicityBitPlus = kFALSE;
229 fHelicityBitMinus = kFALSE;
230 // be careful: it is not that I forgot to reset fActualPatternPolarity
231 // or fDelayedPatternPolarity. One doesn't want to do that here.
232 /** Set the new event number and pattern number to -1. If we are not reading these correctly
233 from the data stream, -1 will allow us to identify that.*/
234 fEventNumber = -1;
236 fPatternNumber = -1;
237 return;
238}
239
240Int_t QwHelicity::ProcessConfigurationBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t* buffer, UInt_t num_words)
241{
242 //stub function
243 // QwError << " this function QwHelicity::ProcessConfigurationBuffer does nothing yet " << QwLog::endl;
244 return 0;
245}
246
247Int_t QwHelicity::LoadInputParameters(TString pedestalfile)
248{
249 return 0;
250}
251
252
254 //impose single event cuts //Paul's modifications
255
256 return kTRUE;
257}
258
259/*!
260 * \brief Process helicity information from userbit configuration data.
261 *
262 * This is a complex function (~80 lines) that extracts helicity information
263 * from userbit data for injector tests and special configurations. It handles:
264 *
265 * Userbit Decoding:
266 * - Extracts 3-bit userbit pattern from bits 28-30 of userbit word
267 * - Decodes quartet synchronization bit (bit 3) for pattern timing
268 * - Decodes helicity bit (bit 2) for spin state determination
269 * - Manages scaler offset calculations for event counting
270 *
271 * Event Counting Logic:
272 * - Increments event numbers based on scaler counter ratios
273 * - Handles missed events when scaler offset > 1 (indicates DAQ issues)
274 * - Maintains pattern phase and pattern number synchronization
275 * - Resets quartet phase on quartet sync bit assertion
276 *
277 * Helicity State Management:
278 * - Sets fHelicityBitPlus/fHelicityBitMinus based on userbit helicity bit
279 * - Updates fHelicityReported for downstream processing
280 * - Maintains helicity predictor state for data quality monitoring
281 *
282 * Error Recovery:
283 * - Detects missed events through scaler offset analysis
284 * - Resets helicity predictor when event sequence is uncertain
285 * - Provides debug output for missed event scenarios
286 *
287 * Pattern Synchronization:
288 * - Manages quartet boundaries using sync bits
289 * - Handles pattern phase wraparound at maximum phase
290 * - Maintains continuous event numbering across pattern boundaries
291 *
292 * \note This mode is primarily used for injector testing and is not the
293 * standard helicity decoding method for production Qweak data analysis.
294 *
295 * \warning Missed events (scaler offset > 1) will reset the helicity
296 * predictor and may affect downstream helicity-dependent analyses.
297 */
299{
300
301 /** In this version of the code, the helicity is extracted for a userbit configuration.
302 This is not what we plan to have for Qweak but it was done for injector tests and
303 so is useful to have as another option to get helicity information. */
304
305 Bool_t ldebug=kFALSE;
306 UInt_t userbits;
307 static UInt_t lastuserbits = 0xFF;
308 UInt_t scaleroffset=fWord[kScalerCounter].fValue/32;
309
310 if(scaleroffset==1 || scaleroffset==0) {
311 userbits = (fWord[kUserbit].fValue & 0xE0000000)>>28;
312
313 // Now fake the input register, MPS counter, QRT counter, and QRT phase.
315
316 lastuserbits = userbits;
317
318 if (lastuserbits==0xFF) {
320 } else {
321 if ((lastuserbits & 0x8) == 0x8) {
322 // Quartet bit is set.
323 fPatternPhaseNumber = fMinPatternPhase; // Reset the QRT phase
324 fPatternNumber=fPatternNumberOld+1; // Increment the QRT counter
325 } else {
326 fPatternPhaseNumber=fPatternPhaseNumberOld+1; // Increment the QRT phase
327 }
328
330
331 if ((lastuserbits & 0x4) == 0x4){ // Helicity bit is set.
332 fHelicityReported |= 1; // Set the InputReg HEL+ bit.
333 fHelicityBitPlus=kTRUE;
334 fHelicityBitMinus=kFALSE;
335 } else {
336 fHelicityReported |= 0; // Set the InputReg HEL- bit.
337 fHelicityBitPlus=kFALSE;
338 fHelicityBitMinus=kTRUE;
339 }
340 }
341 } else {
342 QwError << " QwHelicity::ProcessEvent finding a missed read event in the scaler" << QwLog::endl;
343 if(ldebug) {
344 std::cout << " QwHelicity::ProcessEvent :" << scaleroffset << " events were missed \n";
345 std::cout << " before manipulation \n";
346 Print();
347 }
348 //there was more than one event since the last reading of the scalers
349 //ie we should read only one event at the time,
350 //if not something is wrong
351 fEventNumber=fEventNumberOld+scaleroffset;
352 Int_t localphase=fPatternPhaseNumberOld;
353 Int_t localpatternnumber=fPatternNumberOld;
354 for (UInt_t i=0;i<scaleroffset;i++) {
355 fPatternPhaseNumber=localphase+1;
359 localpatternnumber=fPatternNumber;
360 }
361 localphase=fPatternPhaseNumber;
362 }
363 //Reset helicity predictor because we are not sure of what we are doing
366 if(ldebug) {
367 std::cout << " after manipulation \n";
368 Print();
369 }
370 }
371 return;
372}
373
374
376{
377 static Bool_t firstevent = kTRUE;
378 static Bool_t firstpattern = kTRUE;
379 static Bool_t fake_the_counters=kFALSE;
380 UInt_t thisinputregister=fWord[kInputRegister].fValue;
381
382 if (firstpattern){
383 // If any of the special counters are negative or zero, setup to
384 // generate the counters internally.
385 fake_the_counters |= (kPatternCounter<=0)
386 || ( kMpsCounter<=0) || (kPatternPhase<=0);
387 }
388
389 if (CheckIORegisterMask(thisinputregister,fInputReg_FakeMPS))
390 fIgnoreHelicity = kTRUE;
391 else
392 fIgnoreHelicity = kFALSE;
393
394 /** If we get junk for the mps and pattern information from the run
395 we can enable fake counters for mps, pattern number and pattern
396 phase to get the job done.
397 */
398 if (!fake_the_counters){
399 /**
400 In the Input Register Mode,
401 the event number is obtained straight from the wordkMPSCounter.
402 */
404 // When we have the minimum phase from the pattern phase word
405 // and the input register minimum phase bit is set
406 // we can select the second pattern as below.
407 if(fWord[kPatternPhase].fValue - fPatternPhaseOffset == 0)
408 if (firstpattern && CheckIORegisterMask(thisinputregister,fInputReg_PatternSync)){
409 firstpattern = kFALSE;
410 }
411
412 // If firstpattern is still TRUE, we are still searching for the first
413 // pattern of the data stream. So set the pattern number = 0
414 if (firstpattern)
415 fPatternNumber = -1;
416 else {
419 }
420 } else {
421 // Use internal variables for all the counters.
423 if (CheckIORegisterMask(thisinputregister,fInputReg_PatternSync)) {
426 } else {
429 }
430 }
431
432
433 if (firstevent){
434 firstevent = kFALSE;
435 } else if(fEventNumber!=(fEventNumberOld+1)){
436 Int_t nummissed(fEventNumber - (fEventNumberOld+1));
438 QwError << "QwHelicity::ProcessEvent read event# ("
439 << fEventNumber << ") is not old_event#+1; missed "
440 << nummissed << " gates" << QwLog::endl;
441 }
442 fNumMissedGates += nummissed;
445 }
446
448 // Quartet bit is set.
449 QwError << "QwHelicity::ProcessEvent: The Multiplet Sync bit is set, but the Pattern Phase is ("
450 << fPatternPhaseNumber << ") not "
451 << fMinPatternPhase << "! Please check the fPatternPhaseOffset in the helicity map file." << QwLog::endl;
454 }
455
457
458 /**
459 Extract the reported helicity from the input register for each event.
460 */
461
462 if (CheckIORegisterMask(thisinputregister,fInputReg_HelPlus)
463 && CheckIORegisterMask(thisinputregister,fInputReg_HelMinus) ){
464 // Both helicity bits are set.
465 QwError << "QwHelicity::ProcessEvent: Both the H+ and H- bits are set: thisinputregister=="
466 << thisinputregister << QwLog::endl;
468 fHelicityBitPlus = kFALSE;
469 fHelicityBitMinus = kFALSE;
470 } else if (CheckIORegisterMask(thisinputregister,fInputReg_HelPlus)){ // HelPlus bit is set.
471 fHelicityReported |= 1; // Set the InputReg HEL+ bit.
472 fHelicityBitPlus = kTRUE;
473 fHelicityBitMinus = kFALSE;
474 } else {
475 fHelicityReported |= 0; // Set the InputReg HEL- bit.
476 fHelicityBitPlus = kFALSE;
477 fHelicityBitMinus = kTRUE;
478 }
479
480 return;
481}
482
484{
485 static Bool_t firstpattern = kTRUE;
486
487 if(firstpattern && fWord[kPatternCounter].fValue > fPatternNumberOld){
488 firstpattern = kFALSE;
489 }
490
493 Int_t nummissed(fEventNumber - (fEventNumberOld+1));
494 QwError << "QwHelicity::ProcessEvent read event# ("
495 << fEventNumber << ") is not old_event#+1; missed "
496 << nummissed << " gates" << QwLog::endl;
497 fNumMissedGates += nummissed;
499 }
500 if (firstpattern){
501 fPatternNumber = -1;
503 } else {
506 // We are at a new pattern!
508 } else {
510 }
511 }
512
515 // fHelicityReported = (fEventType == 1 ? 0 : 1);
516
517 if (fHelicityReported == 1){
518 fHelicityBitPlus=kTRUE;
519 fHelicityBitMinus=kFALSE;
520 } else {
521 fHelicityBitPlus=kFALSE;
522 fHelicityBitMinus=kTRUE;
523 }
524 return;
525}
526
527
529{
530 Bool_t ldebug = kFALSE;
531 fErrorFlag = 0;
532
533 if (! HasDataLoaded()) return;
534
535 switch (fHelicityDecodingMode)
536 {
537 case kHelUserbitMode :
539 break;
542 break;
545 break;
546 default:
547 QwError << "QwHelicity::ProcessEvent no instructions on how to decode the helicity !!!!" << QwLog::endl;
548 abort();
549 break;
550 }
551
554
555 // Predict helicity if delay is non zero.
558 } else {
559 // Else use the reported helicity values.
562
567 }
568
569 }
570
571 if(ldebug){
572 std::cout<<"\nevent number= "<<fEventNumber<<std::endl;
573 std::cout<<"pattern number = "<<fPatternNumber<<std::endl;
574 std::cout<<"pattern phase = "<<fPatternPhaseNumber<<std::endl;
575 std::cout<<"max pattern phase = "<<fMaxPatternPhase<<std::endl;
576 std::cout<<"min pattern phase = "<<fMinPatternPhase<<std::endl;
577 }
578
579 return;
580}
581
582
583void QwHelicity::EncodeEventData(std::vector<UInt_t> &buffer)
584{
585 std::vector<UInt_t> localbuffer;
586 localbuffer.clear();
587
588 // Userbit mode
589 switch (fHelicityDecodingMode) {
590 case kHelUserbitMode: {
591 UInt_t userbit = 0x0;
592 if (fPatternPhaseNumber == fMinPatternPhase) userbit |= 0x80000000;
593 if (fHelicityDelayed == 1) userbit |= 0x40000000;
594
595 // Write the words to the buffer
596 localbuffer.push_back(0x0); // scalerheader
597 localbuffer.push_back(0x20); // scalercounter (32)
598 localbuffer.push_back(userbit); // userbit
599
600 for (int i = 0; i < 64; i++) localbuffer.push_back(0x0); // (not used)
601 break;
602 }
604 UInt_t input_register = 0x0;
605 if (fHelicityDelayed == 1) input_register |= fInputReg_HelPlus;
606 if (fHelicityDelayed == 0) input_register |= fInputReg_HelMinus;
608
609 // Write the words to the buffer
610 localbuffer.push_back(input_register); // input_register
611 localbuffer.push_back(0x0); // output_register
612 localbuffer.push_back(fEventNumber); // mps_counter
613 localbuffer.push_back(fPatternNumber); // pat_counter
614 localbuffer.push_back(fPatternPhaseNumber - fMinPatternPhase + fPatternPhaseOffset); // pat_phase
615
616 for (int i = 0; i < 17; i++) localbuffer.push_back(0x0); // (not used)
617 break;
618 }
619 default:
620 QwWarning << "QwHelicity::EncodeEventData: Unsupported helicity encoding!" << QwLog::endl;
621 break;
622 }
623
624 // If there is element data, generate the subbank header
625 std::vector<UInt_t> subbankheader;
626 std::vector<UInt_t> rocheader;
627 if (localbuffer.size() > 0) {
628
629 // Form CODA subbank header
630 subbankheader.clear();
631 subbankheader.push_back(localbuffer.size() + 1); // subbank size
632 subbankheader.push_back((fCurrentBank_ID << 16) | (0x01 << 8) | (1 & 0xff));
633 // subbank tag | subbank type | event number
634
635 // Form CODA bank/roc header
636 rocheader.clear();
637 rocheader.push_back(subbankheader.size() + localbuffer.size() + 1); // bank/roc size
638 rocheader.push_back((fCurrentROC_ID << 16) | (0x10 << 8) | (1 & 0xff));
639 // bank tag == ROC | bank type | event number
640
641 // Add bank header, subbank header and element data to output buffer
642 buffer.insert(buffer.end(), rocheader.begin(), rocheader.end());
643 buffer.insert(buffer.end(), subbankheader.begin(), subbankheader.end());
644 buffer.insert(buffer.end(), localbuffer.begin(), localbuffer.end());
645 }
646}
647
648Int_t QwHelicity::LoadChannelMap(TString mapfile)
649{
650 Bool_t ldebug=kFALSE;
651
652 Int_t wordsofar=0;
653 Int_t bankindex=-1;
654
655 fPatternPhaseOffset=1;//Phase number offset is set to 1 by default and will be set to 0 if phase number starts from 0
656
657
658 // Default value for random seed is 30 bits
659 fRandBits = 30;
660
661
662 QwParameterFile mapstr(mapfile.Data()); //Open the file
664 mapstr.EnableGreediness();
665 mapstr.SetCommentChars("!");
666
667 UInt_t value = 0;
668 TString valuestr;
669
670 while (mapstr.ReadNextLine()){
671 RegisterRocBankMarker(mapstr);
672
673 if (mapstr.PopValue("patternphase",value)) {
674 fMaxPatternPhase=value;
676 }
677 if (mapstr.PopValue("patternbits",valuestr)) {
678 SetHelicityBitPattern(valuestr);
679 }
680 if (mapstr.PopValue("inputregmask_fakemps",value)) {
681 fInputReg_FakeMPS = value;
682 }
683 if (mapstr.PopValue("inputregmask_helicity",value)) {
684 fInputReg_HelPlus = value;
686 }
687 if (mapstr.PopValue("inputregmask_helplus",value)) {
688 fInputReg_HelPlus = value;
689 }
690 if (mapstr.PopValue("inputregmask_helminus",value)) {
691 fInputReg_HelMinus = value;
692 }
693 if (mapstr.PopValue("inputregmask_pattsync",value)) {
694 fInputReg_PatternSync = value;
695 }
696 if (mapstr.PopValue("inputregmask_pairsync",value)) {
697 fInputReg_PairSync = value;
698 }
699 if (mapstr.PopValue("fakempsbit",value)) {
700 fInputReg_FakeMPS = value;
701 QwWarning << " fInputReg_FakeMPS 0x" << std::hex << fInputReg_FakeMPS << std::dec << QwLog::endl;
702 }
703 if (mapstr.PopValue("numberpatternsdelayed",value)) {
704 SetHelicityDelay(value);
705 }
706 if (mapstr.PopValue("randseedbits",value)) {
707 if (value==24 || value==30)
708 fRandBits = value;
709 }
710 if (mapstr.PopValue("patternphaseoffset",value)) {
712 }
713 if (mapstr.PopValue("helpluseventtype",value)) {
714 kEventTypeHelPlus = value;
715 }
716 if (mapstr.PopValue("helminuseventtype",value)) {
717 kEventTypeHelMinus = value;
718 }
719 if (mapstr.PopValue("helicitydecodingmode",valuestr)) {
720 if (valuestr=="InputRegisterMode") {
721 QwMessage << " **** Input Register Mode **** " << QwLog::endl;
723 } else if (valuestr=="UserbitMode"){
724 QwMessage << " **** Userbit Mode **** " << QwLog::endl;
726 } else if (valuestr=="HelLocalyMadeUp"){
727 QwMessage << "**** Helicity Locally Made Up ****" << QwLog::endl;
729 } else if (valuestr=="InputMollerMode") {
730 QwMessage << "**** Input Moller Mode ****" << QwLog::endl;
732 } else {
733 QwError << "The helicity decoding mode read in file " << mapfile
734 << " is not recognized in function QwHelicity::LoadChannelMap \n"
735 << " Quitting this execution." << QwLog::endl;
736 }
737 }
738
741 if ((bankindex+1)>0){
742 UInt_t numbanks = UInt_t(bankindex+1);
743 if (fWordsPerSubbank.size()<numbanks){
744 fWordsPerSubbank.resize(numbanks,
745 std::pair<Int_t, Int_t>(fWord.size(),fWord.size()));
746 }
747 }
748 wordsofar=0;
749 }
750 mapstr.TrimWhitespace(); // Get rid of leading and trailing spaces.
751 if (mapstr.LineIsEmpty()) continue;
752
753 // Break this line into tokens to process it.
754 TString modtype = mapstr.GetTypedNextToken<TString>(); // module type
755 Int_t modnum = mapstr.GetTypedNextToken<Int_t>(); //slot number
756 /* Int_t channum = */ mapstr.GetTypedNextToken<Int_t>(); //channel number /* unused */
757 TString dettype = mapstr.GetTypedNextToken<TString>(); //type-purpose of the detector
758 dettype.ToLower();
759 TString namech = mapstr.GetTypedNextToken<TString>(); //name of the detector
760 namech.ToLower();
761 TString keyword = mapstr.GetTypedNextToken<TString>();
762 keyword.ToLower();
763 // Notice that "namech" and "keyword" are now forced to lower-case.
764
765 if(modtype=="SKIP"){
766 if (modnum<=0) wordsofar+=1;
767 else wordsofar+=modnum;
768 } else if(modtype!="WORD"|| dettype!="helicitydata") {
769 QwError << "QwHelicity::LoadChannelMap: Unknown detector type: "
770 << dettype << ", the detector " << namech << " will not be decoded "
771 << QwLog::endl;
772 continue;
773 } else {
774 QwWord localword;
775 localword.fSubbankIndex=bankindex;
776 localword.fWordInSubbank=wordsofar;
777 wordsofar+=1;
778 // I assume that one data = one word here. But it is not always the case, for
779 // example the triumf adc gives 6 words per channel
780 localword.fModuleType=modtype;
781 localword.fWordName=namech;
782 localword.fWordType=dettype;
783 fWord.push_back(localword);
784 fWordsPerSubbank.at(bankindex).second = fWord.size();
785
786 // Notice that "namech" is in lower-case, so these checks
787 // should all be in lower-case
788 switch (fHelicityDecodingMode)
789 {
790 case kHelUserbitMode :
791 if(namech.Contains("userbit")) kUserbit=fWord.size()-1;
792 if(namech.Contains("scalercounter")) kScalerCounter=fWord.size()-1;
793 break;
795 if(namech.Contains("input_register")) kInputRegister= fWord.size()-1;
796 if(namech.Contains("mps_counter")) kMpsCounter= fWord.size()-1;
797 if(namech.Contains("pat_counter")) kPatternCounter= fWord.size()-1;
798 if(namech.Contains("pat_phase")) kPatternPhase= fWord.size()-1;
799 break;
801 if(namech.Contains("mps_counter")) {
802 kMpsCounter= fWord.size()-1;
803 }
804 if(namech.Contains("pat_counter")) {
805 kPatternCounter = fWord.size()-1;
806 }
807 break;
808 }
809 }
810 }
811
812
813 if(ldebug) {
814 std::cout << "Done with Load map channel \n";
815 for(size_t i=0;i<fWord.size();i++)
816 fWord[i].PrintID();
817 std::cout << " kUserbit=" << kUserbit << "\n";
818 }
819 ldebug=kFALSE;
820
822 // Check to be sure kEventTypeHelPlus and kEventTypeHelMinus are both defined and not equal
826 // Everything is okay
827 QwDebug << "QwHelicity::LoadChannelMap:"
828 << " We are in Moller Helicity Mode, with HelPlusEventType = "
830 << "and HelMinusEventType = " << kEventTypeHelMinus
831 << QwLog::endl;
832 } else {
833 QwError << "QwHelicity::LoadChannelMap:"
834 << " We are in Moller Helicity Mode, and the HelPlus and HelMinus event types are not set properly."
835 << " HelPlusEventType = " << kEventTypeHelPlus
836 << ", HelMinusEventType = " << kEventTypeHelMinus
837 << ". Please correct the helicity map file!"
838 << QwLog::endl;
839 exit(65);
840 }
841 }
842
843std::cout << fHelicityBitPattern.size() << std::endl;
844
845 mapstr.Close(); // Close the file (ifstream)
846 return 0;
847}
848
849
850Int_t QwHelicity::LoadEventCuts(TString filename){
851 return 0;
852}
853
854Int_t QwHelicity::ProcessEvBuffer(UInt_t event_type, const ROCID_t roc_id, const BankID_t bank_id, UInt_t* buffer, UInt_t num_words)
855{
856 Bool_t lkDEBUG = kFALSE;
857
858 if (((0x1 << (event_type - 1)) & this->GetEventTypeMask()) == 0)
859 return 0;
860 fEventType = event_type;
861
862 Int_t index = GetSubbankIndex(roc_id,bank_id);
863 if (index >= 0 && num_words > 0) {
864 SetDataLoaded(kTRUE);
865 // We want to process this ROC. Begin loopilooping through the data.
866 QwDebug << "QwHelicity::ProcessEvBuffer: "
867 << "Begin processing ROC" << roc_id
868 << " and subbank " << bank_id
869 << " number of words=" << num_words << QwLog::endl;
870
871 for(Int_t i=fWordsPerSubbank.at(index).first; i<fWordsPerSubbank.at(index).second; i++) {
872 if(fWord[i].fWordInSubbank+1<= (Int_t) num_words) {
873 fWord[i].fValue=buffer[fWord[i].fWordInSubbank];
874 } else {
875 QwWarning << "QwHelicity::ProcessEvBuffer: There is not enough word in the buffer to read data for "
876 << fWord[i].fWordName << QwLog::endl;
877 QwWarning << "QwHelicity::ProcessEvBuffer: Words in this buffer:" << num_words
878 << " trying to read word number =" << fWord[i].fWordInSubbank << QwLog::endl;
879 }
880 }
881 if(lkDEBUG) {
882 QwDebug << "QwHelicity::ProcessEvBuffer: Done with Processing this event" << QwLog::endl;
883 for(size_t i=0;i<fWord.size();i++) {
884 std::cout << "QwHelicity::ProcessEvBuffer: word number = " << i << " ";
885 fWord[i].Print();
886 }
887 }
888 }
889 lkDEBUG=kFALSE;
890 return 0;
891}
892
893
894void QwHelicity::ConstructHistograms(TDirectory *folder, TString &prefix)
895{
896 SetHistoTreeSave(prefix);
897 if (folder != NULL) folder->cd();
898 TString basename;
899 size_t index=0;
900
902 {
903 //do nothing
904 }
906 {
907 fHistograms.resize(1+fWord.size(), NULL);
908 basename="pattern_polarity";
909 fHistograms[index] = gQwHists.Construct1DHist(basename);
910 index+=1;
911 for (size_t i=0; i<fWord.size(); i++){
912 basename="hel_"+fWord[i].fWordName;
913 fHistograms[index] = gQwHists.Construct1DHist(basename);
914 index+=1;
915 }
916 }
917 else if(fHistoType==kHelSaveMPS)
918 {
919 fHistograms.resize(4+fWord.size(), NULL);
920 //eventnumber, patternnumber, helicity, patternphase + fWord.size
921 basename=prefix+"delta_event_number";
922 fHistograms[index] = gQwHists.Construct1DHist(basename);
923 index+=1;
924 basename=prefix+"delta_pattern_number";
925 fHistograms[index] = gQwHists.Construct1DHist(basename);
926 index+=1;
927 basename=prefix+"pattern_phase";
928 fHistograms[index] = gQwHists.Construct1DHist(basename);
929 index+=1;
930 basename=prefix+"helicity";
931 fHistograms[index] = gQwHists.Construct1DHist(basename);
932 index+=1;
933 for (size_t i=0; i<fWord.size(); i++){
934 basename=prefix+fWord[i].fWordName;
935 fHistograms[index] = gQwHists.Construct1DHist(basename);
936 index+=1;
937 }
938 }
939 else
940 QwError << "QwHelicity::ConstructHistograms this prefix--" << prefix << "-- is not unknown:: no histo created" << QwLog::endl;
941
942 return;
943}
944
A logfile class, based on an identical class in the Hermes analyzer.
#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
Helper functions and utilities for ROOT histogram management.
QwHistogramHelper gQwHists
Globally defined instance of the QwHistogramHelper class.
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.
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()
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.
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
Int_t LoadEventCuts(TString filename) override
Optional event cut file.
Bool_t CheckIORegisterMask(const UInt_t &ioregister, const UInt_t &mask) const
Definition QwHelicity.h:88
void ProcessEventInputRegisterMode()
void ProcessOptions(QwOptions &options) override
Process the command line options.
void ClearEventData() override
Int_t ProcessConfigurationBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words) override
UInt_t fInputReg_FakeMPS
Definition QwHelicity.h:105
Int_t LoadInputParameters(TString pedestalfile) override
Mandatory parameter file definition.
virtual void ConstructHistograms()
Construct the histograms for this subsystem.
Int_t LoadChannelMap(TString mapfile) override
Mandatory map file definition.
QwHelicity()
Private default constructor (not implemented, will throw linker error on use)
UInt_t fInputReg_HelMinus
Definition QwHelicity.h:107
@ kDefaultInputReg_FakeMPS
Definition QwHelicity.h:101
@ kDefaultInputReg_PatternSync
Definition QwHelicity.h:100
@ kDefaultInputReg_HelPlus
Definition QwHelicity.h:98
@ kDefaultInputReg_HelMinus
Definition QwHelicity.h:99
@ kHelInputMollerMode
Definition QwHelicity.h:95
@ kHelInputRegisterMode
Definition QwHelicity.h:93
@ kHelUserbitMode
Definition QwHelicity.h:92
@ kHelLocalyMadeUp
Definition QwHelicity.h:94
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:63
UInt_t fInputReg_HelPlus
Definition QwHelicity.h:106
void ProcessEventUserbitMode()
Process helicity information from userbit configuration data.
UInt_t fInputReg_PairSync
Definition QwHelicity.h:109
UInt_t fInputReg_PatternSync
Definition QwHelicity.h:108
Bool_t ApplySingleEventCuts() override
Apply the single event cuts.
void ProcessEventInputMollerMode()
void ProcessEvent() override
void EncodeEventData(std::vector< UInt_t > &buffer) override
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
std::vector< QwWord > fWord
UInt_t BuildHelicityBitPattern(Int_t patternsize)
Int_t fActualPatternPolarity
True polarity of the current pattern.
QwHelicityBase()
Private default constructor (not implemented, will throw linker error on use)
Bool_t fSuppressMPSErrorMsgs
UInt_t kEventTypeHelMinus
Int_t fNumMissedEventBlocks
Int_t fPreviousPatternPolarity
True polarity of the previous pattern.
std::vector< UInt_t > fHelicityBitPattern
void Print() const
Int_t fHelicityDecodingMode
static const Int_t kUndefinedHelicity
Int_t fDelayedPatternPolarity
Reported polarity of the current pattern.
Int_t fPatternPhaseNumberOld
void SetHistoTreeSave(const TString &prefix)
void ClearErrorCounters()