Newer
Older
////////////////////////////////////////////////////////////////////////
//
// THcHelicity
//
// Helicity of the beam in delayed mode using quartets
// +1 = plus, -1 = minus, 0 = unknown
//
// Also supports in-time mode with delay = 0

Sylvester Joosten
committed
//
////////////////////////////////////////////////////////////////////////
#include "THcHelicity.h"

Sylvester Joosten
committed
#include "TH1F.h"
#include "THaApparatus.h"
#include "THaEvData.h"
#include "THcGlobals.h"
#include "THcParmList.h"
#include "TMath.h"
#include <iostream>
using namespace std;
//_____________________________________________________________________________

Sylvester Joosten
committed
THcHelicity::THcHelicity(const char* name, const char* description, THaApparatus* app)
: hcana::ConfigLogging<THaHelicityDet>(name, description, app), fnQrt(-1), fHelDelay(8),
fMAXBIT(30) {
// for( Int_t i = 0; i < NHIST; ++i )
// fHisto[i] = 0;
// memset(fHbits, 0, sizeof(fHbits));
}
//_____________________________________________________________________________
THcHelicity::THcHelicity()

Sylvester Joosten
committed
: hcana::ConfigLogging<THaHelicityDet>(), fnQrt(-1), fHelDelay(8), fMAXBIT(30) {
// Default constructor for ROOT I/O
// for( Int_t i = 0; i < NHIST; ++i )
// fHisto[i] = 0;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
THcHelicity::~THcHelicity() {
DefineVariables(kDelete);
// for( Int_t i = 0; i < NHIST; ++i ) {
// delete fHisto[i];
// }
}
//_____________________________________________________________________________
THaAnalysisObject::EStatus THcHelicity::Init(const TDatime& date) {
// Call `Setup` before everything else.
Setup(GetName(), GetTitle());

Sylvester Joosten
committed
fFirstEvProcessed = kFALSE;
fActualHelicity = kUnknown;
fPredictedHelicity = kUnknown;

Sylvester Joosten
committed
fLastMPSTime = 0;
fFoundMPS = kFALSE;
// Call initializer for base class.
// This also calls `ReadDatabase` and `DefineVariables`.
EStatus status = THaDetector::Init(date);
if (status) {
fStatus = status;
return fStatus;
}

Sylvester Joosten
committed
fDisabled = kFALSE;
fQuadPattern[0] = fQuadPattern[1] = fQuadPattern[2] = fQuadPattern[3] = 0;
fQuadPattern[4] = fQuadPattern[5] = fQuadPattern[6] = fQuadPattern[7] = 0;
fHelperHistory = 0;
fHelperQuartetHistory = 0;
fScalerSeed = 0;
fNBits = 0;
lastispos = 0;
fLastReportedHelicity = kUnknown;
fFixFirstCycle = kFALSE;
fHaveQRT = kFALSE;
fNQRTProblems = 0;
fPeriodCheck = 0.0;
fCycle = 0.0;
fStatus = kOK;
return fStatus;
}
//_____________________________________________________________________________
void THcHelicity::Setup(const char* name, const char* description) {
// Prefix for parameters in `param` file.
string kwPrefix = string(GetApparatus()->GetName()) + "_" + name;
std::transform(kwPrefix.begin(), kwPrefix.end(), kwPrefix.begin(), ::tolower);
fKwPrefix = kwPrefix;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
Int_t THcHelicity::ReadDatabase(const TDatime& date) {
_logger->info("In THcHelicity::ReadDatabase");

Sylvester Joosten
committed
// cout << "In THcHelicity::ReadDatabase" << endl;
// Read general HelicityDet database values (e.g. fSign)
// Int_t st = THaHelicityDet::ReadDatabase( date );
// if( st != kOK )
// return st;
// Read readout parameters (ROC addresses etc.)

Sylvester Joosten
committed
Int_t st = THcHelicityReader::ReadDatabase(GetDBFileName(), GetPrefix(), date, fQWEAKDebug);
if (st != kOK)
return st;

Sylvester Joosten
committed
fSign = 1; // Default helicity sign
fRingSeed_reported_initial = 0; // Initial see that should predict reported

Sylvester Joosten
committed
// helicity of first quartet.
fFirstCycle = -1; // First Cycle that starts a quad (0 to 3)
fFreq = 29.5596;
fHelDelay = 8;
DBRequest list[] = {// {"_hsign", &fSign, kInt, 0, 1},
{"helicity_delay", &fHelDelay, kInt, 0, 1},
{"helicity_freq", &fFreq, kDouble, 0, 1},
// {"helicity_seed", &fRingSeed_reported_initial, kInt, 0, 1},
// {"helicity_cycle", &fFirstCycle, kInt, 0, 1},
{0}};
gHcParms->LoadParmValues(list, "");

Sylvester Joosten
committed
fMAXBIT = 30;

Sylvester Joosten
committed
fTIPeriod = 250000000.0 / fFreq;
// maximum of event in the pattern, for now we are working with quartets

Sylvester Joosten
committed
// Int_t localpattern[4]={1,-1,-1,1};
// careful, the first value here should always +1
// for(int i=0;i<fQWEAKNPattern;i++)
// {
// fPatternSequence.push_back(localpattern[i]);
// }

Sylvester Joosten
committed
HWPIN = kTRUE;

Sylvester Joosten
committed
fQuartet[0] = fQuartet[1] = fQuartet[2] = fQuartet[3] = 0;

Sylvester Joosten
committed
if (fFirstCycle >= 0 && fRingSeed_reported_initial != 0) {
// Set the seed for predicted reported and predicted actual
} else {
// Initialize mode to find quartets and then seed
}

Sylvester Joosten
committed
_logger->info(
"Helicity decoder initialized with frequency of {} Hz and reporting delay of {} cycles.",
fFreq, fHelDelay);
// cout << "Helicity decoder initialized with frequency of " << fFreq
// << " Hz and reporting delay of " << fHelDelay << " cycles." << endl;
return kOK;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
void THcHelicity::MakePrefix() { THaDetector::MakePrefix(); }
//_____________________________________________________________________________

Sylvester Joosten
committed
Int_t THcHelicity::DefineVariables(EMode mode) {
// Initialize global variables
_logger->info("Called THcHelicity::DefineVariables with mode == {}", mode);

Sylvester Joosten
committed
// cout << "Called THcHelicity::DefineVariables with mode == "

Sylvester Joosten
committed
if (mode == kDefine && fIsSetup)
return kOK;
fIsSetup = (mode == kDefine);
// Define standard variables from base class

Sylvester Joosten
committed
THaHelicityDet::DefineVariables(mode);
const RVarDef var[] = {{"nqrt", "position of cycle in quartet", "fnQrt"},
{"hel", "actual helicity for event", "fActualHelicity"},
{"helrep", "reported helicity for event", "fReportedHelicity"},
{"helpred", "predicted reported helicity for event", "fPredictedHelicity"},
{"mps", "In MPS blanking period", "fMPS"},
{0}};
// cout << "Calling THcHelicity DefineVarsFromList" << endl;
_logger->info("Calling THcHelicity DefineVarsFromList");

Sylvester Joosten
committed
return DefineVarsFromList(var, mode);
=======
THaHelicityDet::DefineVariables(mode);
const RVarDef var[] = {{"nqrt", "position of cycle in quartet", "fnQrt"},
{"hel", "actual helicity for event", "fActualHelicity"},
{"helrep", "reported helicity for event", "fReportedHelicity"},
{"helpred", "predicted reported helicity for event", "fPredictedHelicity"},
{"mps", "In MPS blanking period", "fMPS"},
{"pcheck", "Period check", "fPeriodCheck"},
{"cycle", "Helicity Cycle", "fCycle"},
{"qrt", "Last cycle of quartet", "fQrt"},
{0}};
cout << "Calling THcHelicity DefineVarsFromList" << endl;
return DefineVarsFromList(var, mode);
>>>>>>> 77b916167fbc44bfd82e8c4fe2b063c386e89d99
}
//_____________________________________________________________________________

Sylvester Joosten
committed
void THcHelicity::PrintEvent(Int_t evtnum) {

Sylvester Joosten
committed
cout << " ++++++ THcHelicity::Print ++++++\n";

Sylvester Joosten
committed
cout << " +++++++++++++++++++++++++++++++++++++\n";
return;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
Int_t THcHelicity::Begin(THaRunBase*) {
THcHelicityReader::Begin();
// fHisto[0] = new TH1F("hel.seed","hel.seed",32,-1.5,30.5);
// fHisto[1] = new TH1F("hel.error.code","hel.error.code",35,-1.5,33.5);

Sylvester Joosten
committed
return 0;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
// void THcHelicity::FillHisto()
//{
// fHisto[0]->Fill(fRing_NSeed);
// fHisto[1]->Fill(fErrorCode);
// return;
//}
//_____________________________________________________________________________

Sylvester Joosten
committed
void THcHelicity::SetErrorCode(Int_t error) {
// used as a control for the helciity computation
// 2^0: if the reported number of events in a pattern is larger than fQWEAKNPattern
// 2^1: if the offset between the ring reported value and TIR value is not fOffsetTIRvsRing
// 2^2: if the reported time in the ring is 0
// 2^3: if the predicted reported helicity doesn't match the reported helicity in the ring
// 2^4: if the helicity cannot be computed using the SetHelicity routine
// 2^5: if seed is being gathered

Sylvester Joosten
committed
if (fErrorCode == 0)
fErrorCode = (1 << error);
// only one reported error at the time
return;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
void THcHelicity::Clear(Option_t* opt) {
// Clear event-by-event data
THaHelicityDet::Clear(opt);
THcHelicityReader::Clear(opt);
fEvtype = 0;

Sylvester Joosten
committed
fQrt = 0;
fErrorCode = 0;
//_____________________________________________________________________________
void THcHelicity::SetHelicityScaler(THcHelicityScaler* f) {
fglHelicityScaler = f;
fHelicityHistory = fglHelicityScaler->GetHelicityHistoryP();
//_____________________________________________________________________________

Sylvester Joosten
committed
Int_t THcHelicity::Decode(const THaEvData& evdata) {
// Decode Helicity data.
// Return 1 if helicity was assigned, 0 if not, <0 if error.

Sylvester Joosten
committed
Int_t err = ReadData(evdata); // from THcHelicityReader class
if (err) {
Error(Here("THcHelicity::Decode"), "Error decoding helicity data.");

Sylvester Joosten
committed
fReportedHelicity = (fIsHelp ? (fIsHelm ? kUnknown : kPlus) : (fIsHelm ? kMinus : kUnknown));
fMPS = fIsMPS ? 1 : 0;
if (fHelDelay == 0) { // If no delay actual=reported (but zero if in MPS)
fActualHelicity = fIsMPS ? kUnknown : fReportedHelicity;
=======
fReportedHelicity = (fIsHelp ? (fIsHelm ? kUnknown : kPlus) : (fIsHelm ? kMinus : kUnknown));
fMPS = fIsMPS ? 1 : 0;
fQrt = fIsQrt ? 1 : 0; // Last of quartet
if (fglHelicityScaler) {
Int_t nhelev = fglHelicityScaler->GetNevents();
Int_t ncycles = fglHelicityScaler->GetNcycles();
if (nhelev > 0) {
for (Int_t i = 0; i < nhelev; i++) {
fScaleQuartet = (fHelicityHistory[i] & 2) != 0;
Int_t ispos = fHelicityHistory[i] & 1;
if (fScaleQuartet) {
fScalerSeed = ((fScalerSeed << 1) | ispos) & 0x3FFFFFFF;
}
if (fHelDelay == 0) { // If no delay actual=reported (but zero if in MPS)
fActualHelicity = fIsMPS ? kUnknown : fReportedHelicity;
>>>>>>> 77b916167fbc44bfd82e8c4fe2b063c386e89d99

Sylvester Joosten
committed
if (fDisabled) {
fActualHelicity = kUnknown;
return 0;
}
fEvNumCheck++;
Int_t evnum = evdata.GetEvNum();

Sylvester Joosten
committed
if (fEvNumCheck != evnum) {
_logger->info("THcHelicity: Missed {} events at event {}.", evnum - fEvNumCheck, evnum);
_logger->info(" Disabling helicity decoding for rest of run.");
_logger->info(
" Make sure \"RawDecode_master in cuts file accepts all physics events.");
fDisabled = kTRUE;

Sylvester Joosten
committed
if (fFirstEvProcessed) { // Normal processing
// cout << evnum << " " << fNCycle << " " << fIsMPS << " " << fFoundMPS << " " << fTITime <<
// " "
Int_t missed = 0;
// Double_t elapsed_time = (fTITime - fFirstEvTime)/250000000.0;

Sylvester Joosten
committed
if (fIsMPS) {
fActualHelicity = kUnknown;
=======
if (fIsMPS) {
fPeriodCheck = fmod(fTITime / fTIPeriod, 1.0);
fCycle = (fTITime / fTIPeriod);
>>>>>>> 77b916167fbc44bfd82e8c4fe2b063c386e89d99

Sylvester Joosten
committed
if (fFoundMPS) {
missed = TMath::Nint(fTITime / fTIPeriod - fLastMPSTime / fTIPeriod);
if (missed < 1) { // was <=1
fLastMPSTime = (fTITime + fLastMPSTime + missed * fTIPeriod) / 2;
fIsNewCycle = kTRUE;
fActualHelicity = kUnknown;
fPredictedHelicity = kUnknown;
} else {
fLastMPSTime = (fLastMPSTime + fTITime - missed * fTIPeriod) / 2;
}
// If there is a skip, pass it off to next non MPS event
// Need to also check here for missed MPS's
// cout << "Found MPS" << endl;
// check for Nint((time-last)/period) > 1

Sylvester Joosten
committed
fFoundMPS = kTRUE;
fLastMPSTime = fTITime;

Sylvester Joosten
committed
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
} else if (fFoundMPS) { //
if (fTITime - fLastMPSTime > fTIPeriod) { // We missed MPS periods
missed = TMath::Nint(floor((fTITime - fLastMPSTime) / fTIPeriod));
if (missed > 1) {
// cout << "Missed " << missed << " MPSes" << endl;
Int_t newNCycle = fNCycle + missed - 1; // How many cycles really missed
Int_t quartets_missed = (newNCycle - fFirstCycle) / 4 - (fNCycle - fFirstCycle) / 4;
for (Int_t i = 0; i < quartets_missed; i++) { // Advance the seeds.
fRingSeed_reported = RanBit30(fRingSeed_reported);
fRingSeed_actual = RanBit30(fRingSeed_actual);
}
int quartetphase = (newNCycle - fFirstCycle) % 4;
// cout << " " << fNCycle << " " << newNCycle << " " << fFirstCycle << " " <<
// quartets_missed << " " << quartetphase << endl; cout << "Cycles " << fNCycle << "
// " << newNCycle << " " << fFirstCycle
// << " skipped " << quartets_missed << " quartets" << endl;
fNCycle = newNCycle;
// Need to reset fQuartet to reflect where we are based on the current
// reported helicity. So we don't fail quartet testing.
// But only do this if we are calibrated.
if (fNBits >= fMAXBIT) {
fQuartetStartHelicity = (fRingSeed_actual & 1) ? kPlus : kMinus;
fQuartetStartPredictedHelicity = (fRingSeed_reported & 1) ? kPlus : kMinus;
fActualHelicity = (quartetphase == 0 || quartetphase == 3) ? fQuartetStartHelicity
: -fQuartetStartHelicity;
fPredictedHelicity = (quartetphase == 0 || quartetphase == 3)
? fQuartetStartPredictedHelicity
: -fQuartetStartPredictedHelicity;
if (((fNCycle - fFirstCycle) % 2) == 1) {
fQuartet[0] = fReportedHelicity;
fQuartet[1] = fQuartet[2] = -fQuartet[0];
} else {
fQuartet[0] = fQuartet[1] = -fReportedHelicity;
fQuartet[2] = -fQuartet[1];
}
} else {
fActualHelicity = kUnknown;
fQuartet[0] = fReportedHelicity;
fQuartet[1] = 0;
}
}
fLastMPSTime += missed * fTIPeriod;
fIsNewCycle = kTRUE;
fLastReportedHelicity = fReportedHelicity;
} else { // No missed periods. Get helicities from rings
if (fNBits >= fMAXBIT) {
int quartetphase = (fNCycle - fFirstCycle) % 4;
fQuartetStartHelicity = (fRingSeed_actual & 1) ? kPlus : kMinus;
fQuartetStartPredictedHelicity = (fRingSeed_reported & 1) ? kPlus : kMinus;
fActualHelicity = (quartetphase == 0 || quartetphase == 3) ? fQuartetStartHelicity
: -fQuartetStartHelicity;
fPredictedHelicity = (quartetphase == 0 || quartetphase == 3)
? fQuartetStartPredictedHelicity
: -fQuartetStartPredictedHelicity;
} else {
fActualHelicity = 0;
}

Sylvester Joosten
committed
if (fIsNewCycle) {
fQuartet[3] = fQuartet[2];
fQuartet[2] = fQuartet[1];
fQuartet[1] = fQuartet[0];
fQuartet[0] = fReportedHelicity;
fNCycle++;
if ((fNCycle - fFirstCycle) % 4 == 3) { // Test if last in a quartet
if ((abs(fQuartet[0] + fQuartet[3] - fQuartet[1] - fQuartet[2]) == 4)) {
if (!fFoundQuartet) {
// fFirstCycle = fNCycle - 3;
_logger->info("Quartet potentially found, starting at cycle {} - event {}",
fFirstCycle, evdata.GetEvNum());
// cout << "Quartet potentially found, starting at cycle " << fFirstCycle << " - event
// "
// << evdata.GetEvNum() << endl;
fFoundQuartet = kTRUE;

Sylvester Joosten
committed
}
} else {
if (fNCycle - fFirstCycle > 4) { // Not at start of run. Reset
_logger->warn("Lost quartet sync at cycle {} - event {}", fNCycle, evdata.GetEvNum());
_logger->warn("{} {} {} {}", fQuartet[0], fQuartet[1], fQuartet[2], fQuartet[3]);
// cout << "Lost quartet sync at cycle " << fNCycle << " - event " <<
// evdata.GetEvNum()

Sylvester Joosten
committed
// cout << fQuartet[0] << " " << fQuartet[1] << " " << fQuartet[2] << " " <<
// fQuartet[3]

Sylvester Joosten
committed
fFirstCycle += 4 * ((fNCycle - fFirstCycle) / 4); // Update, but don't change phase
}
fFoundQuartet = kFALSE;

Sylvester Joosten
committed
_logger->info("Searching for first of a quartet at cycle {} - event {}", fFirstCycle,
evdata.GetEvNum());
// cout << "Searching for first of a quartet at cycle "
// << " " << fFirstCycle << " - event " << evdata.GetEvNum() << endl;

Sylvester Joosten
committed
// cout << fQuartet[0] << " " << fQuartet[1] << " " << fQuartet[2] << " " << fQuartet[3]
// << endl;
_logger->info("{} {} {} {}", fQuartet[0], fQuartet[1], fQuartet[2], fQuartet[3]);

Sylvester Joosten
committed
fFirstCycle++;
}
}
// Load the actual helicity. Calibrate if not calibrated.
fActualHelicity = kUnknown;
LoadHelicity(fReportedHelicity, fNCycle, missed);
fLastReportedHelicity = fReportedHelicity;
fIsNewCycle = kFALSE;
// cout << fTITime/250000000.0 << " " << fNCycle << " " << fReportedHelicity << endl;
// cout << fNCycle << ": " << fReportedHelicity << " "
// << fPredictedHelicity << " " << fActualHelicity << endl;
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
=======
} else if (fFoundMPS) { //
if (fTITime - fLastMPSTime > fTIPeriod) { // We missed MPS periods
missed = TMath::Nint(floor((fTITime - fLastMPSTime) / fTIPeriod));
if (missed > 1) {
// cout << "Missed " << missed << " MPSes" << endl;
Int_t newNCycle = fNCycle + missed - 1; // How many cycles really missed
Int_t quartets_missed = (newNCycle - fFirstCycle) / 4 - (fNCycle - fFirstCycle) / 4;
int quartetphase = (newNCycle - fFirstCycle) % 4;
// cout << " " << fNCycle << " " << newNCycle << " " << fFirstCycle << " " <<
// quartets_missed << " " << quartetphase << endl; cout << "Cycles " << fNCycle << "
// " << newNCycle << " " << fFirstCycle
// << " skipped " << quartets_missed << " quartets" << endl;
fNCycle = newNCycle;
// Need to reset fQuartet to reflect where we are based on the current
// reported helicity. So we don't fail quartet testing.
// But only do this if we are calibrated.
if (fNBits >= fMAXBIT) {
for (Int_t i = 0; i < quartets_missed; i++) { // Advance the seeds.
// cout << "Advancing seed A " << fNBits << endl;
fRingSeed_reported = RanBit30(fRingSeed_reported);
fRingSeed_actual = RanBit30(fRingSeed_actual);
}
fQuartetStartHelicity = (fRingSeed_actual & 1) ? kPlus : kMinus;
fQuartetStartPredictedHelicity = (fRingSeed_reported & 1) ? kPlus : kMinus;
fActualHelicity = (quartetphase == 0 || quartetphase == 3) ? fQuartetStartHelicity
: -fQuartetStartHelicity;
fPredictedHelicity = (quartetphase == 0 || quartetphase == 3)
? fQuartetStartPredictedHelicity
: -fQuartetStartPredictedHelicity;
if (((fNCycle - fFirstCycle) % 2) == 1) {
fQuartet[0] = fReportedHelicity;
fQuartet[1] = fQuartet[2] = -fQuartet[0];
} else {
fQuartet[0] = fQuartet[1] = -fReportedHelicity;
fQuartet[2] = -fQuartet[1];
}
} else {
fActualHelicity = kUnknown;
fQuartet[0] = fReportedHelicity;
fQuartet[1] = 0;
}
}
fLastMPSTime += missed * fTIPeriod;
fIsNewCycle = kTRUE;
fLastReportedHelicity = fReportedHelicity;
} else { // No missed periods. Get helicities from rings
if (fNBits >= fMAXBIT) {
int quartetphase = (fNCycle - fFirstCycle) % 4;
fQuartetStartHelicity = (fRingSeed_actual & 1) ? kPlus : kMinus;
fQuartetStartPredictedHelicity = (fRingSeed_reported & 1) ? kPlus : kMinus;
fActualHelicity = (quartetphase == 0 || quartetphase == 3) ? fQuartetStartHelicity
: -fQuartetStartHelicity;
fPredictedHelicity = (quartetphase == 0 || quartetphase == 3)
? fQuartetStartPredictedHelicity
: -fQuartetStartPredictedHelicity;
} else {
fActualHelicity = 0;
}
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
if (fIsNewCycle) {
// cout << "Scaler Seed " << bitset<32>(fScalerSeed) << endl;
// Int_t predictedScalerSeed = RanBit30(fScalerSeed);
// cout << "Predct Seed " << bitset<32>(predictedScalerSeed) << endl;
// cout << "Event Seed " << bitset<32>(fRingSeed_reported) << endl;
fQuartet[3] = fQuartet[2];
fQuartet[2] = fQuartet[1];
fQuartet[1] = fQuartet[0];
fQuartet[0] = fReportedHelicity;
fNCycle++;
// cout << "XX: " << fNCycle << " " << fReportedHelicity << " " << fIsQrt <<endl;
if (fIsQrt) { //
fNLastQuartet = fNQuartet;
fNQuartet = (fNCycle - fFirstCycle) / 4;
if (fHaveQRT) { // Should already have phase set
if ((fNCycle - fFirstCycle) % 4 != 0) { // Test if first in a quartet
fNQRTProblems++;
if (fNQRTProblems > 10) {
cout << "QRT Problem resetting" << endl;
fHaveQRT = kFALSE;
fFoundQuartet = kFALSE;
fNQRTProblems = 0;
} else {
cout << "Ignored " << fNQRTProblems << " problems" << endl;
}
} else {
fNQRTProblems = 0;
}
}
if (!fHaveQRT) {
fHaveQRT = kTRUE;
fFoundQuartet = kTRUE;
fFirstCycle = fNCycle; //
fNQuartet = (fNCycle - fFirstCycle) / 4;
fNLastQuartet = fNQuartet - 1; // Make sure LoadHelicity uses
fNBits = 0;
fNQRTProblems = 0;
cout << "Phase found from QRT signal" << endl;
cout << "fFirstcycle = " << fFirstCycle << endl;
}
} else {
if (fHaveQRT) { // Using qrt signal.
fNLastQuartet = fNQuartet;
fNQuartet = (fNCycle - fFirstCycle) / 4;
if ((fNCycle - fFirstCycle) % 4 == 0) { // Shouldn't happen
fNQRTProblems++;
if (fNQRTProblems > 10) {
cout << "Shouldn't happen, cycle=" << fNCycle << "/" << fFirstCycle << endl;
fHaveQRT = kFALSE; // False until a new QRT seen
fNBits = 0; // Reset
fNLastQuartet = fNQuartet; // Make sure LoadHelicity does not use
} else {
cout << "Ignored " << fNQRTProblems << " problems" << endl;
}
}
} else { // Presumable pre qrt signal data
if ((fNCycle - fFirstCycle) % 4 == 3) { // Test if last in a quartet
if ((abs(fQuartet[0] + fQuartet[3] - fQuartet[1] - fQuartet[2]) == 4)) {
if (!fFoundQuartet) {
// fFirstCycle = fNCycle - 3;
cout << "Quartet potentially found, starting at cycle " << fFirstCycle << endl;
fNQuartet = (fNCycle - fFirstCycle) / 4;
fNLastQuartet = fNQuartet - 1; // Make sure LoadHelicity uses
fFoundQuartet = kTRUE;
}
} else {
if (fNCycle - fFirstCycle > 4) { // Not at start of run. Reset
cout << "Lost quartet sync at cycle " << fNCycle << endl;
cout << fQuartet[0] << " " << fQuartet[1] << " " << fQuartet[2] << " "
<< fQuartet[3] << endl;
fFirstCycle +=
4 * ((fNCycle - fFirstCycle) / 4); // Update, but don't change phase
}
fFoundQuartet = kFALSE;
fNBits = 0;
cout << "Searching for first of a quartet at cycle "
<< " " << fFirstCycle << endl;
cout << fQuartet[0] << " " << fQuartet[1] << " " << fQuartet[2] << " "
<< fQuartet[3] << endl;
fFirstCycle++;
}
} else {
fNLastQuartet = fNQuartet;
fNQuartet = (fNCycle - fFirstCycle) / 4;
}
}
}
// Load the actual helicity. Calibrate if not calibrated.
fActualHelicity = kUnknown;
// Here if we know we missed some earlier in the quartet, we need
// to make sure we get here and call LoadHelicity for the missing
// Cycles, reducing the missed count for each extra loadhelicity
// call that we make.
LoadHelicity(fReportedHelicity, fNCycle, missed);
fLastReportedHelicity = fReportedHelicity;
fIsNewCycle = kFALSE;
// cout << fTITime/250000000.0 << " " << fNCycle << " " << fReportedHelicity << endl;
// cout << fNCycle << ": " << fReportedHelicity << " "
// << fPredictedHelicity << " " << fActualHelicity << endl;
>>>>>>> 77b916167fbc44bfd82e8c4fe2b063c386e89d99
}
// Ignore until a MPS Is found

Sylvester Joosten
committed
} else { // No MPS found yet

Sylvester Joosten
committed
// cout << "Initializing" << endl;
_logger->info("Initializing Helicity");
fLastReportedHelicity = fReportedHelicity;

Sylvester Joosten
committed
fActualHelicity = kUnknown;
fPredictedHelicity = kUnknown;
fFirstEvTime = fTITime;
fLastEvTime = fTITime;
fLastMPSTime = fTITime; // Not necessarily during the MPS
fNCycle = 0;
fFirstEvProcessed = kTRUE;
fFoundMPS = kFALSE;
fFoundQuartet = kFALSE;
fIsNewCycle = kFALSE;
fNBits = 0;

Sylvester Joosten
committed
if (fActualHelicity < -5) {
_logger->info("Actual Helicity never got defined");

Sylvester Joosten
committed
if (fNBits < fMAXBIT) {
if (fActualHelicity == -1 || fActualHelicity == 1) {
cout << "Helicity of " << fActualHelicity << " reported prematurely at cycle " << fNCycle
<< endl;
}
}
fLastActualHelicity = fActualHelicity;
return 0;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
Int_t THcHelicity::End(THaRunBase*) {
// End of run processing. Write histograms.
THcHelicityReader::End();
// for( Int_t i = 0; i < NHIST; ++i )
// fHisto[i]->Write();
return 0;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
void THcHelicity::SetDebug(Int_t level) {
// Set debug level of this detector as well as the THcHelicityReader

Sylvester Joosten
committed
THaHelicityDet::SetDebug(level);
fQWEAKDebug = level;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
void THcHelicity::LoadHelicity(Int_t reportedhelicity, Int_t cyclecount, Int_t missedcycles) {
// static const char* const here = "THcHelicity::LoadHelicity";

Sylvester Joosten
committed
int quartetphase = (cyclecount - fFirstCycle) % 4;
fnQrt = quartetphase;

Sylvester Joosten
committed
if (missedcycles > 1) { // If we missed windows
if (fNBits < fMAXBIT) { // and we haven't gotten the seed, start over
fNBits = 0;
return;
}
}

Sylvester Joosten
committed
if (!fFoundQuartet) { // Wait until we have found quad phase before starting
return; // to calibrate

Sylvester Joosten
committed
if (quartetphase == 0) { // Start of a quad
if (fNBits < fMAXBIT) {
if (fNBits == 0) {
_logger->info("Start calibrating at cycle {}", cyclecount);
// cout << "Start calibrating at cycle " << cyclecount << endl;
fRingSeed_reported = 0;

Sylvester Joosten
committed
if (fReportedHelicity == kPlus) {
fRingSeed_reported = ((fRingSeed_reported << 1) | 1) & 0x3FFFFFFF;

Sylvester Joosten
committed
fRingSeed_reported = (fRingSeed_reported << 1) & 0x3FFFFFFF;

Sylvester Joosten
committed
if (fReportedHelicity == kUnknown) {
fNBits = 0;
fRingSeed_reported = 0;
} else if (fNBits == fMAXBIT) {
_logger->info("Seed Found {} at cycle {} with first cycle {}", fRingSeed_reported,
cyclecount, fFirstCycle);
// cout << "Seed Found " << hex << fRingSeed_reported << dec << " at cycle " << cyclecount
// << " with first cycle " << fFirstCycle << endl;
Int_t backseed = GetSeed30(fRingSeed_reported);
_logger->info("Seed at cycle {} should be {}", fFirstCycle, backseed);
// cout << "Seed at cycle " << fFirstCycle << " should be " << hex << backseed << dec <<
// endl;
}
fActualHelicity = kUnknown;
} else if (fNBits >= fMAXBIT) {
fRingSeed_reported = RanBit30(fRingSeed_reported);

Sylvester Joosten
committed
if (fNBits == fMAXBIT) {
fRingSeed_actual = fRingSeed_reported;
for (Int_t i = 0; i < fHelDelay / 4; i++) {
fRingSeed_actual = RanBit30(fRingSeed_actual);
}
fNBits++;

Sylvester Joosten
committed
fRingSeed_actual = RanBit30(fRingSeed_actual);

Sylvester Joosten
committed
fActualHelicity = (fRingSeed_actual & 1) ? kPlus : kMinus;
fPredictedHelicity = (fRingSeed_reported & 1) ? kPlus : kMinus;
// if(fTITime/250000000.0 > 380.0) cout << fTITime/250000000.0 << " " << fNCycle << " "
// << hex <<
// fRingSeed_reported << " " << fRingSeed_actual << dec
//<< endl;
if (fReportedHelicity != fPredictedHelicity) {
_logger->warn("Helicity prediction failed {} {} {}", fReportedHelicity, fPredictedHelicity,
fActualHelicity);
// cout << "Helicity prediction failed " << fReportedHelicity << " "
// << fPredictedHelicity << " " << fActualHelicity << endl;
// cout << hex << fRingSeed_reported << " " << fRingSeed_actual << dec << endl;
fNBits = 0; // Need to reaquire seed
fActualHelicity = kUnknown;
fPredictedHelicity = kUnknown;
=======
// if(!fFixFirstCycle) {
if (fNQuartet - fNLastQuartet > 1) { // If we missed a quartet
if (fNBits < fMAXBIT) { // and we haven't gotten the seed, start over
cout << "fNBits = 0, missedcycles=" << missedcycles << " " << fNLastQuartet << " "
<< fNQuartet << endl;
fNBits = 0;
return;
}
// }
if (!fFoundQuartet) { // Wait until we have found quad phase before starting
return; // to calibrate
// LoadHelicity is called first event of each cycle.
// But only do it's thing if it is first cycle of quartet.
// Need to instead have it do it's thing on the first event of a quartet.
// But only for seed building. Current logic is OK once seed is found.
if (fNBits < fMAXBIT) {
if (fNQuartet != fNLastQuartet) {
// Sanity check fNQuartet == fNLastQuartet+1
if (fNBits == 0) {
cout << "Start calibrating at cycle " << cyclecount << endl;
fRingSeed_reported = 0;
if ((fReportedHelicity == kPlus && (quartetphase == 0 || quartetphase == 3)) ||
(fReportedHelicity == kMinus && (quartetphase == 1 || quartetphase == 2))) {
fRingSeed_reported = ((fRingSeed_reported << 1) | 1) & 0x3FFFFFFF;
// cout << " " << fNQuartet << " 1" << endl;
fRingSeed_reported = (fRingSeed_reported << 1) & 0x3FFFFFFF;
// cout << " " << fNQuartet << " 0" << endl;
if (fReportedHelicity == kUnknown) {
fNBits = 0;
fRingSeed_reported = 0;
} else if (fNBits == fMAXBIT) {
cout << "Seed Found " << bitset<32>(fRingSeed_reported) << " at cycle " << cyclecount
<< " with first cycle " << fFirstCycle << endl;
if (fglHelicityScaler) {
cout << "Scaler Seed " << bitset<32>(fScalerSeed) << endl;
}
Int_t backseed = GetSeed30(fRingSeed_reported);
cout << "Seed at cycle " << fFirstCycle << " should be " << hex << backseed << dec << endl;
// Create the "actual seed"
fRingSeed_actual = fRingSeed_reported;
for (Int_t i = 0; i < fHelDelay / 4; i++) {
fRingSeed_actual = RanBit30(fRingSeed_actual);
}
fActualHelicity = kUnknown;
} // Need to change this to build seed even when not at start of quartet
} else {
// If quartetphase !=, the seeds will alread have been advanced
// except that we won't have made the initial
// cout << "Advancing seed B " << fNBits << endl;
fRingSeed_reported = RanBit30(fRingSeed_reported);
fRingSeed_actual = RanBit30(fRingSeed_actual);
fActualHelicity = (fRingSeed_actual & 1) ? kPlus : kMinus;
fPredictedHelicity = (fRingSeed_reported & 1) ? kPlus : kMinus;
// if(fTITime/250000000.0 > 380.0) cout << fTITime/250000000.0 << " " << fNCycle << " "
// << hex <<
// fRingSeed_reported << " " << fRingSeed_actual << dec
//<< endl;
if (fReportedHelicity != fPredictedHelicity) {
cout << "Helicity prediction failed " << fReportedHelicity << " " << fPredictedHelicity
<< " " << fActualHelicity << endl;
cout << bitset<32>(fRingSeed_reported) << " " << bitset<32>(fRingSeed_actual) << endl;
fNBits = 0; // Need to reaquire seed
fActualHelicity = kUnknown;
fPredictedHelicity = kUnknown;
>>>>>>> 77b916167fbc44bfd82e8c4fe2b063c386e89d99
fQuartetStartHelicity = fActualHelicity;
fQuartetStartPredictedHelicity = fPredictedHelicity;

Sylvester Joosten
committed
fQuartetStartHelicity = fActualHelicity;
fQuartetStartPredictedHelicity = fPredictedHelicity;

Sylvester Joosten
committed
} else { // Not the beginning of a quad
if (fNBits >= fMAXBIT) {
fActualHelicity =
(quartetphase == 0 || quartetphase == 3) ? fQuartetStartHelicity : -fQuartetStartHelicity;
fPredictedHelicity = (quartetphase == 0 || quartetphase == 3)
? fQuartetStartPredictedHelicity
: -fQuartetStartPredictedHelicity;
=======
fActualHelicity =
(quartetphase == 0 || quartetphase == 3) ? fQuartetStartHelicity : -fQuartetStartHelicity;
fPredictedHelicity = (quartetphase == 0 || quartetphase == 3) ? fQuartetStartPredictedHelicity
: -fQuartetStartPredictedHelicity;
>>>>>>> 77b916167fbc44bfd82e8c4fe2b063c386e89d99
}
return;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
Int_t THcHelicity::RanBit30(Int_t ranseed) {
UInt_t bit7 = (ranseed & 0x00000040) != 0;
UInt_t bit28 = (ranseed & 0x08000000) != 0;
UInt_t bit29 = (ranseed & 0x10000000) != 0;
UInt_t bit30 = (ranseed & 0x20000000) != 0;
UInt_t newbit = (bit30 ^ bit29 ^ bit28 ^ bit7) & 0x1;

Sylvester Joosten
committed
if (ranseed <= 0) {
if (fQWEAKDebug > 1)
std::cerr << "ranseed must be greater than zero!"
<< "\n";

Sylvester Joosten
committed
ranseed = ((ranseed << 1) | newbit) & 0x3FFFFFFF;
// here ranseed is changed
if (fQWEAKDebug > 1) {
cout << "THcHelicity::RanBit30, newbit=" << newbit << "\n";
}
return ranseed;
}
//_____________________________________________________________________________

Sylvester Joosten
committed
Int_t THcHelicity::GetSeed30(Int_t currentseed)
/* Back track the seed by 30 samples */
{
#if 1
Int_t seed = currentseed;

Sylvester Joosten
committed
for (Int_t i = 0; i < 30; i++) {
UInt_t bit1 = (seed & 0x00000001) != 0;
UInt_t bit8 = (seed & 0x00000080) != 0;
UInt_t bit29 = (seed & 0x10000000) != 0;
UInt_t bit30 = (seed & 0x20000000) != 0;
UInt_t newbit30 = (bit30 ^ bit29 ^ bit8 ^ bit1) & 0x1;

Sylvester Joosten
committed
seed = (seed >> 1) | (newbit30 << 29);
}
#else
Int_t bits = currentseed;

Sylvester Joosten
committed
Int_t seed = 0;
for (Int_t i = 0; i < 30; i++) {
Int_t val;
// XOR at virtual position 0 and 29

Sylvester Joosten
committed
if (i == 0) {
val = ((bits & (1 << (i))) != 0) ^ ((bits & (1 << (i + 29))) != 0);

Sylvester Joosten
committed
val = ((bits & (1 << (i))) != 0) ^ ((seed & (1 << (i - 1))) != 0);

Sylvester Joosten
committed
if (i <= 1) {
val = ((bits & (1 << (1 - i))) != 0) ^ val;

Sylvester Joosten
committed
val = ((seed & (1 << (i - 2))) != 0) ^ val;

Sylvester Joosten
committed
if (i <= 22) {
val = ((bits & (1 << (i - 22))) != 0) ^ val;

Sylvester Joosten
committed
val = ((seed & (1 << (i - 23))) != 0) ^ val;

Sylvester Joosten
committed
seed |= (val << i);
}
#endif
return seed;
}
ClassImp(THcHelicity)