Skip to content
Snippets Groups Projects
THcHelicity.cxx 27.6 KiB
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
////////////////////////////////////////////////////////////////////////

#include "THcHelicity.h"

#include "THaApparatus.h"
#include "THaEvData.h"
#include "THcGlobals.h"
#include "THcHelicityScaler.h"
#include "THcParmList.h"
#include "TMath.h"
#include <bitset>
#include "THaHelicityDet.h"
#include "hcana/Logger.h"

using namespace std;

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

//_____________________________________________________________________________
THcHelicity::THcHelicity()
    : THaHelicityDet(), fnQrt(-1), fHelDelay(8), fMAXBIT(30) {
  // Default constructor for ROOT I/O

  //  for( Int_t i = 0; i < NHIST; ++i )
  //    fHisto[i] = 0;
}

//_____________________________________________________________________________
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());

  fFirstEvProcessed  = kFALSE;
  fActualHelicity    = kUnknown;
  fPredictedHelicity = kUnknown;

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

Stephen A. Wood's avatar
Stephen A. Wood committed
  fEvNumCheck = 0;
  fLastHelpCycle  = -1;
  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;
}

//_____________________________________________________________________________
Int_t THcHelicity::ReadDatabase(const TDatime& date) {
  _logger->info("In THcHelicity::ReadDatabase");
  // 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.)
  Int_t st = THcHelicityReader::ReadDatabase(GetDBFileName(), GetPrefix(), date, fQWEAKDebug);
  if (st != kOK)
    return st;
  fRingSeed_reported_initial = 0; // Initial see that should predict reported
                                  // 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, "");


  // maximum of event in the pattern, for now we are working with quartets
  // careful, the first value here should always +1
  //  for(int i=0;i<fQWEAKNPattern;i++)
  //    {
  //      fPatternSequence.push_back(localpattern[i]);
  //    }
  fQuartet[0] = fQuartet[1] = fQuartet[2] = fQuartet[3] = 0;
  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
  }

  _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;
}

//_____________________________________________________________________________

void THcHelicity::MakePrefix() { THaDetector::MakePrefix(); }
//_____________________________________________________________________________
Int_t THcHelicity::DefineVariables(EMode mode) {
  // Initialize global variables

  _logger->info("Called THcHelicity::DefineVariables with mode == {}", mode);
  // cout << "Called THcHelicity::DefineVariables with mode == "
  //     << mode << endl;
  if (mode == kDefine && fIsSetup)
    return kOK;
  fIsSetup = (mode == kDefine);

  // Define standard variables from base class
  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}};
  _logger->info("Calling THcHelicity DefineVarsFromList");
  return DefineVarsFromList(var, mode);
}
//_____________________________________________________________________________

void THcHelicity::PrintEvent(Int_t evtnum) {
  cout << " ++++++ THcHelicity::Print ++++++\n";
  cout << " +++++++++++++++++++++++++++++++++++++\n";

  return;
}

//_____________________________________________________________________________
  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);
  return 0;
}

//_____________________________________________________________________________
//{
//  fHisto[0]->Fill(fRing_NSeed);
//  fHisto[1]->Fill(fErrorCode);
//  return;
//}
//_____________________________________________________________________________
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

  if (fErrorCode == 0)
    fErrorCode = (1 << error);
  // only one reported error at the time

  return;
}

//_____________________________________________________________________________
  // Clear event-by-event data

  THaHelicityDet::Clear(opt);
  THcHelicityReader::Clear(opt);
  fEvtype = 0;

//_____________________________________________________________________________
void THcHelicity::SetHelicityScaler(THcHelicityScaler* f) {
  fglHelicityScaler = f;
  fHelicityHistory  = fglHelicityScaler->GetHelicityHistoryP();

//_____________________________________________________________________________
Int_t THcHelicity::Decode(const THaEvData& evdata) {

  // Decode Helicity data.
  // Return 1 if helicity was assigned, 0 if not, <0 if error.
  evnum = evdata.GetEvNum();
  Int_t err = ReadData(evdata); // from THcHelicityReader class
  if (err) {
    Error(Here("THcHelicity::Decode"), "Error decoding helicity data.");
  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;
Stephen A. Wood's avatar
Stephen A. Wood committed
    fActualHelicity = kUnknown;
    return 0;
  }

  fEvNumCheck++;
  Int_t evnum = evdata.GetEvNum();
  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;
Stephen A. Wood's avatar
Stephen A. Wood committed
    fActualHelicity = kUnknown;
Stephen A. Wood's avatar
Stephen A. Wood committed

  fActualHelicity = -10.0;
  if (fFirstEvProcessed) { // Normal processing
    //    cout << evnum << " " << fNCycle << " " << fIsMPS << " " << fFoundMPS << " " << fTITime <<
    //    " "
Stephen A. Wood's avatar
Stephen A. Wood committed
    //	 << fLastMPSTime << " " << fNBits << endl;
    Int_t missed = 0;
    //    Double_t elapsed_time = (fTITime - fFirstEvTime)/250000000.0;
      fPeriodCheck       = fmod(fTITime / fTIPeriod, 1.0);
      fCycle             = (fTITime / fTIPeriod);
Stephen A. Wood's avatar
Stephen A. Wood committed
      fPredictedHelicity = kUnknown;
      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
    } 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;
        }
      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;
      }
      // Ignore until a MPS Is found
Stephen A. Wood's avatar
Stephen A. Wood committed
      fActualHelicity = kUnknown;
    _logger->info("Initializing Helicity");
    fLastReportedHelicity = fReportedHelicity;
    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;
Stephen A. Wood's avatar
Stephen A. Wood committed

  // Some sanity checks
  if (fActualHelicity < -5) {
    _logger->info("Actual Helicity never got defined");
  if (fNBits < fMAXBIT) {
    if (fActualHelicity == -1 || fActualHelicity == 1) {
      cout << "Helicity of " << fActualHelicity << " reported prematurely at cycle " << fNCycle
           << endl;
Stephen A. Wood's avatar
Stephen A. Wood committed
    }
  }
  fLastActualHelicity = fActualHelicity;
  return 0;
}
//_____________________________________________________________________________
  // End of run processing. Write histograms.
  THcHelicityReader::End();

  //  for( Int_t i = 0; i < NHIST; ++i )
  //    fHisto[i]->Write();

  return 0;
}
//_____________________________________________________________________________
void THcHelicity::SetDebug(Int_t level) {
  // Set debug level of this detector as well as the THcHelicityReader
  fQWEAKDebug = level;
}
//_____________________________________________________________________________
void THcHelicity::LoadHelicity(Int_t reportedhelicity, Int_t cyclecount, Int_t missedcycles) {
  //  static const char* const here = "THcHelicity::LoadHelicity";
  int quartetphase = (cyclecount - fFirstCycle) % 4;
  fnQrt            = quartetphase;
  //  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;
      // Do phase stuff right here
      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 == 0) {
      // 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;
      fQuartetStartHelicity          = fActualHelicity;
      fQuartetStartPredictedHelicity = fPredictedHelicity;
    fActualHelicity =
        (quartetphase == 0 || quartetphase == 3) ? fQuartetStartHelicity : -fQuartetStartHelicity;
    fPredictedHelicity = (quartetphase == 0 || quartetphase == 3) ? fQuartetStartPredictedHelicity
                                                                  : -fQuartetStartPredictedHelicity;
  }
  return;
}
//_____________________________________________________________________________
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;

  if (ranseed <= 0) {
    if (fQWEAKDebug > 1)
      std::cerr << "ranseed must be greater than zero!"
                << "\n";
  ranseed = ((ranseed << 1) | newbit) & 0x3FFFFFFF;
  // here ranseed is changed
  if (fQWEAKDebug > 1) {
    cout << "THcHelicity::RanBit30, newbit=" << newbit << "\n";
  }

  return ranseed;
}
//_____________________________________________________________________________
Int_t THcHelicity::GetSeed30(Int_t currentseed)
/* Back track the seed by 30 samples */
{
#if 1
  Int_t seed = currentseed;
  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;
  }
#else
  Int_t bits = currentseed;
  Int_t seed = 0;
  for (Int_t i = 0; i < 30; i++) {
    Int_t val;
    // XOR at virtual position 0 and 29
    if (i == 0) {
      val = ((bits & (1 << (i))) != 0) ^ ((bits & (1 << (i + 29))) != 0);
      val = ((bits & (1 << (i))) != 0) ^ ((seed & (1 << (i - 1))) != 0);
    if (i <= 1) {
      val = ((bits & (1 << (1 - i))) != 0) ^ val;
      val = ((seed & (1 << (i - 2))) != 0) ^ val;
    if (i <= 22) {
      val = ((bits & (1 << (i - 22))) != 0) ^ val;
      val = ((seed & (1 << (i - 23))) != 0) ^ val;
  }
#endif
  return seed;
}

ClassImp(THcHelicity)