Skip to content
Snippets Groups Projects
CbmDeviceUnpackTofMcbm2018.cxx 47.9 KiB
Newer Older
/**
 * CbmDeviceUnpackTofMcbm2018.cxx
 *
 * @since 2018-04-24
 * @author F. Uhlig
 */

#include "CbmDeviceUnpackTofMcbm2018.h"
#include "CbmDefs.h"
#include "CbmMQDefs.h"

#include "CbmMcbm2018TofPar.h"
Administrator's avatar
Administrator committed
#include "CbmMcbm2018UnpackerAlgoTof.h"
//#include "CbmHistManager.h"
#include "CbmTbDaqBuffer.h"
#include "CbmTofAddress.h"
Administrator's avatar
Administrator committed
#include "CbmTofDetectorId_v14a.h"  // in cbmdata/tof
#include "CbmTofDigi.h"

#include "StorableTimeslice.hpp"

#include "FairMQLogger.h"
Administrator's avatar
Administrator committed
#include "FairMQProgOptions.h"  // device->fConfig
#include "FairParGenericSet.h"
Administrator's avatar
Administrator committed
#include "FairRuntimeDb.h"

#include "TH1.h"
#include "TH2.h"

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

// include this header to serialize vectors
#include <boost/serialization/vector.hpp>

#include <array>
Administrator's avatar
Administrator committed
#include <iomanip>
#include <string>

#include <stdexcept>
Administrator's avatar
Administrator committed
struct InitTaskError : std::runtime_error {
  using std::runtime_error::runtime_error;
};

using namespace std;

//static Int_t iMess=0;
Administrator's avatar
Administrator committed
const Int_t DetMask = 0x003FFFFF;

CbmDeviceUnpackTofMcbm2018::CbmDeviceUnpackTofMcbm2018()
  : fNumMessages(0)
  , fiSelectComponents(0)
  , fNumTint(0)
  , fEventHeader()
  , fiReqMode(0)
  , fiReqTint(0)
  , fiReqBeam(-1)
  , fiReqDigiAddr()
  , fiPulserMode(0)
  , fiPulMulMin(0)
  , fiPulTotMin(0)
  , fiPulTotMax(1000)
  , fuTotalMsNb(0)
  , fuOverlapMsNb(0)
  , fuCoreMs(0)
Administrator's avatar
Administrator committed
  , fdMsSizeInNs(0)
  , fdTsCoreSizeInNs(0)
Administrator's avatar
Administrator committed
  , fuMinNbGdpb(0)
  , fuNrOfGdpbs(0)
  , fuNrOfFeePerGdpb(0)
  , fuNrOfGet4PerFee(0)
  , fuNrOfChannelsPerGet4(0)
  , fuNrOfChannelsPerFee(0)
  , fuNrOfGet4(0)
  , fuNrOfGet4PerGdpb(0)
  , fuNrOfChannelsPerGdpb(0)
  , fuGdpbId(0)
  , fuGdpbNr(0)
  , fuGet4Id(0)
  , fuGet4Nr(0)
Administrator's avatar
Administrator committed
  , fMsgCounter(11, 0)  // length of enum MessageTypes initialized with 0
  , fGdpbIdIndexMap()
  , fvulCurrentEpoch()
  , fvbFirstEpochSeen()
  , fNofEpochs(0)
  , fulCurrentEpochTime(0.)
  //, fdMsIndex(0.)
  , fdToffTof(0.)
  , fiAddrRef(0)
  //, fuDiamondDpbIdx(3)
  //, fbEpochSuppModeOn( kTRUE )
  //, fbGet4M24b( kFALSE )
  //, fbGet4v20( kTRUE )
  //, fbMergedEpochsOn( kTRUE )
  , fUnpackPar(nullptr)
  , fdLastDigiTime(0.)
  , fdFirstDigiTimeDif(0.)
  //, fdEvTime0(0.)
Administrator's avatar
Administrator committed
  , fhRawTDigEvT0(nullptr)
  , fhRawTDigRef0(nullptr)
  , fhRawTDigRef(nullptr)
  , fhRawTRefDig0(nullptr)
  , fhRawTRefDig1(nullptr)
  , fhRawDigiLastDigi(nullptr)
  , fhRawTotCh()
  , fhChCount()
  , fvbChanThere()
  , fhChanCoinc()
  , fhDetChanCoinc(nullptr)
  , fvuPadiToGet4()
  , fvuGet4ToPadi()
  , fvuElinkToGet4()
  , fvuGet4ToElink()
  , fviRpcType()
  , fviModuleId()
  , fviNrOfRpc()
  , fviRpcSide()
  , fviRpcChUId()
  , fBuffer(CbmTbDaqBuffer::Instance())
Administrator's avatar
Administrator committed
  , fUnpackerAlgo(nullptr) {
  fUnpackerAlgo = new CbmMcbm2018UnpackerAlgoTof();
Administrator's avatar
Administrator committed
CbmDeviceUnpackTofMcbm2018::~CbmDeviceUnpackTofMcbm2018() {
  delete fUnpackerAlgo;
Administrator's avatar
Administrator committed
void CbmDeviceUnpackTofMcbm2018::InitTask() try {
  // Get the information about created channels from the device
  // Check if the defined channels from the topology (by name)
  // are in the list of channels which are possible/allowed
  // for the device
  // The idea is to check at initilization if the devices are
  // properly connected. For the time beeing this is done with a
  // nameing convention. It is not avoided that someone sends other
  // data on this channel.
  //logger::SetLogLevel("INFO");

  int noChannel = fChannels.size();
  LOG(info) << "Number of defined channels: " << noChannel;
  for (auto const& entry : fChannels) {
    LOG(info) << "Channel name: " << entry.first;
    if (!IsChannelNameAllowed(entry.first))
      throw InitTaskError("Channel name does not match.");
    if (entry.first == "syscmd") {
      OnData(entry.first, &CbmDeviceUnpackTofMcbm2018::HandleMessage);
      continue;
Administrator's avatar
Administrator committed
    //if(entry.first != "tofdigis") OnData(entry.first, &CbmDeviceUnpackTofMcbm2018::HandleData);
    if (entry.first != "tofdigis")
      OnData(entry.first, &CbmDeviceUnpackTofMcbm2018::HandleParts);
    else {
      fChannelsToSend[0].push_back(entry.first);
      LOG(info) << "Init to send data to channel " << fChannelsToSend[0][0];
Administrator's avatar
Administrator committed
  }
  InitContainers();
  const Int_t iHeaderSize = 4;
  fEventHeader.resize(iHeaderSize);  // define size of eventheader int[]
  for (int i = 0; i < iHeaderSize; i++)
    fEventHeader[i] = 0;
  LOG(info) << "Read config";
Administrator's avatar
Administrator committed
  fiSelectComponents = fConfig->GetValue<uint64_t>("SelectComponents");
  fiReqMode          = fConfig->GetValue<uint64_t>("ReqMode");
  fiReqTint          = fConfig->GetValue<uint64_t>("ReqTint");
  fiReqBeam          = fConfig->GetValue<uint64_t>("ReqBeam");
Administrator's avatar
Administrator committed
  fiPulserMode       = fConfig->GetValue<int64_t>("PulserMode");
  fiPulMulMin        = fConfig->GetValue<uint64_t>("PulMulMin");
  fiPulTotMin        = fConfig->GetValue<uint64_t>("PulTotMin");
  fiPulTotMax        = fConfig->GetValue<uint64_t>("PulTotMax");
  fdToffTof          = fConfig->GetValue<double_t>("ToffTof");
  Int_t iRefModType  = fConfig->GetValue<int64_t>("RefModType");
  Int_t iRefModId    = fConfig->GetValue<int64_t>("RefModId");
  Int_t iRefCtrType  = fConfig->GetValue<int64_t>("RefCtrType");
  Int_t iRefCtrId    = fConfig->GetValue<int64_t>("RefCtrId");
  if (iRefModType > -1)
    fiAddrRef = CbmTofAddress::GetUniqueAddress(
      iRefModId, iRefCtrId, 0, 0, iRefModType, iRefCtrType);
  LOG(info) << " Using Reference counter address 0x" << std::hex << fiAddrRef;

Administrator's avatar
Administrator committed
  //    Int_t iMaxAsicInactive = fConfig->GetValue<uint64_t>("MaxAsicInactive");
  //    fUnpackerAlgo->SetMaxAsicInactive( iMaxAsicInactive );
  Int_t iReqDet       = 1;
  Int_t iNReq         = 0;
  const Int_t iMaxReq = 50;
Administrator's avatar
Administrator committed

  while (iNReq < iMaxReq) {  // FIXME, setup parameter hardwired!
    iReqDet = fConfig->GetValue<uint64_t>(Form("ReqDet%d", iNReq));
    if (iReqDet == 0) break;
    AddReqDigiAddr(iReqDet);
    iNReq++;
  }
  LOG(info) << "Setup request";
Administrator's avatar
Administrator committed
  if (fiReqMode > 0)
    if (iNReq == 0) {  // take all defined detectors
      for (UInt_t iGbtx = 0; iGbtx < fviNrOfRpc.size(); iGbtx++) {
        switch (fviRpcType[iGbtx]) {
          case 0:  // mTof modules
          case 1:  // eTof modules
            if (iGbtx % 2 == 0)
              for (Int_t iRpc = 0; iRpc < fviNrOfRpc[iGbtx]; iRpc++) {
                Int_t iAddr = CbmTofAddress::GetUniqueAddress(
                  fviModuleId[iGbtx], iRpc, 0, 0, fviRpcType[iGbtx]);
                AddReqDigiAddr(iAddr);
              }
            break;

          case 9:  // HD 2-RPC boxes
            for (Int_t iRpc = 0; iRpc < 2; iRpc++) {
              Int_t iAddr = CbmTofAddress::GetUniqueAddress(
                fviModuleId[iGbtx], iRpc, 0, 0, fviRpcType[iGbtx]);
              AddReqDigiAddr(iAddr);
            }
            break;
          case 6:  // Buc box
            for (Int_t iRpc = 0; iRpc < 2; iRpc++) {
              Int_t iAddr = CbmTofAddress::GetUniqueAddress(
                fviModuleId[iGbtx], iRpc, 0, 0, fviRpcType[iGbtx]);
              AddReqDigiAddr(iAddr);
            }
            break;
Administrator's avatar
Administrator committed
          case 7:  // CERN box
            for (Int_t iRpc = 0; iRpc < 1; iRpc++) {
              Int_t iAddr = CbmTofAddress::GetUniqueAddress(
                fviModuleId[iGbtx], iRpc, 0, 0, 7);
              AddReqDigiAddr(iAddr);
            }
            break;
          case 8:  // ceramics
            for (Int_t iRpc = 0; iRpc < 8; iRpc++) {
              Int_t iAddr = CbmTofAddress::GetUniqueAddress(
                fviModuleId[iGbtx], iRpc, 0, 0, fviRpcType[iGbtx]);
              AddReqDigiAddr(iAddr);
            }
            break;
          case 5:  // add Diamond, single cell RPC
            Int_t iAddr =
              CbmTofAddress::GetUniqueAddress(fviModuleId[iGbtx], 0, 0, 0, 5);
            AddReqDigiAddr(iAddr);
            break;
        }
      }
Administrator's avatar
Administrator committed
  LOG(info) << "ReqMode " << fiReqMode << " in " << fiReqTint << " ns "
            << " with " << fiReqDigiAddr.size() << " detectors out of "
            << fviNrOfRpc.size() << " GBTx, PulserMode " << fiPulserMode
            << " with Mul " << fiPulMulMin << ", TotMin " << fiPulTotMin;
  LOG(info) << Form("ReqBeam 0x%08x", (uint) fiReqBeam);
Administrator's avatar
Administrator committed

} catch (InitTaskError& e) {
  LOG(error) << e.what();
  // Wrapper defined in CbmMQDefs.h to support different FairMQ versions
  cbm::mq::ChangeState(this, cbm::mq::Transition::ErrorFound);
}

Administrator's avatar
Administrator committed
bool CbmDeviceUnpackTofMcbm2018::IsChannelNameAllowed(std::string channelName) {
  for (auto const& entry : fAllowedChannels) {
    LOG(info) << "Inspect " << entry;
    std::size_t pos1 = channelName.find(entry);
Administrator's avatar
Administrator committed
    if (pos1 != std::string::npos) {
      const vector<std::string>::const_iterator pos =
Administrator's avatar
Administrator committed
        std::find(fAllowedChannels.begin(), fAllowedChannels.end(), entry);
      const vector<std::string>::size_type idx = pos - fAllowedChannels.begin();
      LOG(info) << "Found " << entry << " in " << channelName;
      LOG(info) << "Channel name " << channelName
Administrator's avatar
Administrator committed
                << " found in list of allowed channel names at position "
                << idx;
      return true;
    }
  }
  LOG(info) << "Channel name " << channelName
            << " not found in list of allowed channel names.";
  LOG(error) << "Stop device.";
  return false;
}

Administrator's avatar
Administrator committed
Bool_t CbmDeviceUnpackTofMcbm2018::InitContainers() {
  LOG(info) << "Init parameter containers for CbmDeviceUnpackTofMcbm2018.";
Administrator's avatar
Administrator committed
  //  FairRuntimeDb* fRtdb = FairRuntimeDb::instance();

  // NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
  // Should only be used for small data because of the cost of an additional copy
Administrator's avatar
Administrator committed
  std::string message {"CbmMcbm2018TofPar,111"};
  LOG(info)
    << "Requesting parameter container CbmMcbm2018TofPar, sending message: "
    << message;

  FairMQMessagePtr req(NewSimpleMessage("CbmMcbm2018TofPar,111"));
  FairMQMessagePtr rep(NewMessage());

Administrator's avatar
Administrator committed
  if (Send(req, "parameters") > 0) {
    if (Receive(rep, "parameters") >= 0) {
      if (rep->GetSize() != 0) {
        CbmMQTMessage tmsg(rep->GetData(), rep->GetSize());
        fUnpackPar =
          dynamic_cast<CbmMcbm2018TofPar*>(tmsg.ReadObject(tmsg.GetClass()));
        LOG(info) << "Received unpack parameter from parmq server: "
                  << fUnpackPar;
        fUnpackPar->Print();
      } else {
        LOG(error) << "Received empty reply. Parameter not available";
      }
Administrator's avatar
Administrator committed
  }
Administrator's avatar
Administrator committed
  SetParContainers();
Administrator's avatar
Administrator committed
  Bool_t initOK = kTRUE;
  initOK &= fUnpackerAlgo->InitContainers();
  initOK &= ReInitContainers();  // needed for TInt parameters
Administrator's avatar
Administrator committed
  //  CreateHistograms();
  initOK &= fUnpackerAlgo->CreateHistograms();

  fvulCurrentEpoch.resize(fuNrOfGdpbs * fuNrOfGet4PerGdpb);
  fvbFirstEpochSeen.resize(fuNrOfGdpbs * fuNrOfGet4PerGdpb);
  fvbChanThere.resize(fviRpcChUId.size(), kFALSE);
  for (UInt_t i = 0; i < fuNrOfGdpbs; ++i) {
    for (UInt_t j = 0; j < fuNrOfGet4PerGdpb; ++j) {
      fvulCurrentEpoch[GetArrayIndex(i, j)]  = 0;
      fvbFirstEpochSeen[GetArrayIndex(i, j)] = kFALSE;
    }  // for( UInt_t j = 0; j < fuNrOfGet4PerGdpb; ++j )
  }    // for( UInt_t i = 0; i < fuNrOfGdpbs; ++i )
Administrator's avatar
Administrator committed
void CbmDeviceUnpackTofMcbm2018::SetParContainers() {
  FairRuntimeDb* fRtdb = FairRuntimeDb::instance();
Administrator's avatar
Administrator committed
  TList* fParCList = fUnpackerAlgo->GetParList();
Administrator's avatar
Administrator committed
  LOG(info) << "Setting parameter containers for " << fParCList->GetEntries()
            << " entries ";
Administrator's avatar
Administrator committed
  for (Int_t iparC = 0; iparC < fParCList->GetEntries(); ++iparC) {
    FairParGenericSet* tempObj = (FairParGenericSet*) (fParCList->At(iparC));
    fParCList->Remove(tempObj);
Administrator's avatar
Administrator committed
    std::string sParamName {tempObj->GetName()};

    FairParGenericSet* newObj =
      dynamic_cast<FairParGenericSet*>(fRtdb->getContainer(sParamName.data()));
    LOG(info) << " - Get " << sParamName.data() << " at " << newObj;
    if (nullptr == newObj) {

      LOG(error) << "Failed to obtain parameter container " << sParamName
                 << ", for parameter index " << iparC;
      return;
    }  // if( nullptr == newObj )
    if (iparC == 0) {
      newObj = (FairParGenericSet*) fUnpackPar;
      LOG(info) << " - Mod " << sParamName.data() << " to " << newObj;
    }
    fParCList->AddAt(newObj, iparC);
    //      delete tempObj;
  }  // for( Int_t iparC = 0; iparC < fParCList->GetEntries(); ++iparC )
Administrator's avatar
Administrator committed
void CbmDeviceUnpackTofMcbm2018::AddMsComponentToList(size_t component,
                                                      UShort_t usDetectorId) {
  fUnpackerAlgo->AddMsComponentToList(component, usDetectorId);
Administrator's avatar
Administrator committed
Bool_t CbmDeviceUnpackTofMcbm2018::ReInitContainers() {
  LOG(info) << "ReInit parameter containers for CbmDeviceUnpackMcbm2018TofPar.";

  fuNrOfGdpbs = fUnpackPar->GetNrOfGdpbs();
  LOG(info) << "Nr. of Tof GDPBs: " << fuNrOfGdpbs;
  fuMinNbGdpb = fuNrOfGdpbs;

  fuNrOfFeePerGdpb = fUnpackPar->GetNrOfFeesPerGdpb();
  LOG(info) << "Nr. of FEES per Tof GDPB: " << fuNrOfFeePerGdpb;

  fuNrOfGet4PerFee = fUnpackPar->GetNrOfGet4PerFee();
  LOG(info) << "Nr. of GET4 per Tof FEE: " << fuNrOfGet4PerFee;

  fuNrOfChannelsPerGet4 = fUnpackPar->GetNrOfChannelsPerGet4();
  LOG(info) << "Nr. of channels per GET4: " << fuNrOfChannelsPerGet4;

  fuNrOfChannelsPerFee = fuNrOfGet4PerFee * fuNrOfChannelsPerGet4;
  LOG(info) << "Nr. of channels per FEE: " << fuNrOfChannelsPerFee;

  fuNrOfGet4 = fuNrOfGdpbs * fuNrOfFeePerGdpb * fuNrOfGet4PerFee;
  LOG(info) << "Nr. of GET4s: " << fuNrOfGet4;

  fuNrOfGet4PerGdpb = fuNrOfFeePerGdpb * fuNrOfGet4PerFee;
  LOG(info) << "Nr. of GET4s per GDPB: " << fuNrOfGet4PerGdpb;

Administrator's avatar
Administrator committed
  /// TODO: move these constants somewhere shared, e.g the parameter file
  fvuPadiToGet4.resize(fuNrOfChannelsPerFee);
  fvuGet4ToPadi.resize(fuNrOfChannelsPerFee);
  /* source: Monitor
   UInt_t uGet4topadi[32] = {
       4,  3,  2,  1,  // provided by Jochen
      24, 23, 22, 21,
       8,  7,  6,  5,
      28, 27, 26, 25,
      12, 11, 10,  9,
      32, 31, 30, 29,
      16, 15, 14, 13,
      20, 19, 18, 17 };
   */

Administrator's avatar
Administrator committed
  UInt_t uGet4topadi[32] = {4,  3,  2,  1,  // provided by Jochen
                            8,  7,  6,  5,  12, 11, 10, 9,  16, 15,
                            14, 13, 20, 19, 18, 17, 24, 23, 22, 21,
                            28, 27, 26, 25, 32, 31, 30, 29};

  UInt_t uPaditoget4[32] = {4,  3,  2,  1,  // provided by Jochen
                            12, 11, 10, 9,  20, 19, 18, 17, 28, 27,
                            26, 25, 32, 31, 30, 29, 8,  7,  6,  5,
                            16, 15, 14, 13, 24, 23, 22, 21};

  for (UInt_t uChan = 0; uChan < fuNrOfChannelsPerFee; ++uChan) {
    fvuPadiToGet4[uChan] = uPaditoget4[uChan] - 1;
    fvuGet4ToPadi[uChan] = uGet4topadi[uChan] - 1;
  }  // for( UInt_t uChan = 0; uChan < fuNrOfChannelsPerFee; ++uChan )

  /// TODO: move these constants somewhere shared, e.g the parameter file
  fvuElinkToGet4.resize(kuNbGet4PerGbtx);
  fvuGet4ToElink.resize(kuNbGet4PerGbtx);
  UInt_t kuElinkToGet4[kuNbGet4PerGbtx] = {
    27, 2,  7,  3,  31, 26, 30, 1,  33, 37, 32, 13, 9,  14,
    10, 15, 17, 21, 16, 35, 34, 38, 25, 24, 0,  6,  20, 23,
    18, 22, 28, 4,  29, 5,  19, 36, 39, 8,  12, 11};
  UInt_t kuGet4ToElink[kuNbGet4PerGbtx] = {
    24, 7,  1,  3,  31, 33, 25, 2,  37, 12, 14, 39, 38, 11,
    13, 15, 18, 16, 28, 34, 26, 17, 29, 27, 23, 22, 5,  0,
    30, 32, 6,  4,  10, 8,  20, 19, 35, 9,  21, 36};
  for (UInt_t uLinkAsic = 0; uLinkAsic < kuNbGet4PerGbtx; ++uLinkAsic) {
    fvuElinkToGet4[uLinkAsic] = kuElinkToGet4[uLinkAsic];
    fvuGet4ToElink[uLinkAsic] = kuGet4ToElink[uLinkAsic];
  }  // for( UInt_t uChan = 0; uChan < fuNrOfChannelsPerFee; ++uChan )

  UInt_t uNrOfGbtx = fUnpackPar->GetNrOfGbtx();
  fviRpcType.resize(uNrOfGbtx);
  fviModuleId.resize(uNrOfGbtx);
  fviNrOfRpc.resize(uNrOfGbtx);
  fviRpcSide.resize(uNrOfGbtx);

  for (UInt_t iGbtx = 0; iGbtx < uNrOfGbtx; ++iGbtx) {
    fviNrOfRpc[iGbtx]  = fUnpackPar->GetNrOfRpc(iGbtx);
    fviRpcType[iGbtx]  = fUnpackPar->GetRpcType(iGbtx);
    fviRpcSide[iGbtx]  = fUnpackPar->GetRpcSide(iGbtx);
    fviModuleId[iGbtx] = fUnpackPar->GetModuleId(iGbtx);
  }
Administrator's avatar
Administrator committed
  UInt_t uNrOfChannels = fuNrOfGet4 * fuNrOfChannelsPerGet4;
  LOG(info) << "Nr. of possible Tof channels: " << uNrOfChannels;

  //   CbmTofDetectorId* fTofId = new CbmTofDetectorId_v14a();
  fviRpcChUId.resize(uNrOfChannels);
  UInt_t iCh = 0;
  for (UInt_t iGbtx = 0; iGbtx < uNrOfGbtx; iGbtx++) {
    switch (fviRpcType[iGbtx]) {

      case 0:                         // CBM modules
        if (fviRpcSide[iGbtx] < 2) {  // mTof modules
          const Int_t RpcMap[5] = {4, 2, 0, 3, 1};
          for (Int_t iRpc = 0; iRpc < fviNrOfRpc[iGbtx]; iRpc++) {
            Int_t iStrMax = 32;
            Int_t iChNext = 1;

            for (Int_t iStr = 0; iStr < iStrMax; iStr++) {
              Int_t iStrMap = iStr;
              Int_t iRpcMap = RpcMap[iRpc];

              if (fviRpcSide[iGbtx] == 0) iStrMap = 31 - iStr;
              if (fviModuleId[iGbtx] > -1)
                fviRpcChUId[iCh] =
                  CbmTofAddress::GetUniqueAddress(fviModuleId[iGbtx],
                                                  iRpcMap,
                                                  iStrMap,
                                                  fviRpcSide[iGbtx],
                                                  fviRpcType[iGbtx]);
              else
                fviRpcChUId[iCh] = 0;
              //	 LOG(debug)<<Form("Map Ch %d to Address 0x%08x",iCh,fviRpcChUId[iCh]);

              iCh += iChNext;
            }
          }
        }
        break;


      case 1:                         // STAR eTOF  modules
        if (fviRpcSide[iGbtx] < 2) {  // mTof modules
          const Int_t RpcMap[3] = {0, 1, 2};
          for (Int_t iRpc = 0; iRpc < fviNrOfRpc[iGbtx]; iRpc++) {
            Int_t iStrMax = 32;
            Int_t iChNext = 1;

            for (Int_t iStr = 0; iStr < iStrMax; iStr++) {
              Int_t iStrMap = iStr;
              Int_t iRpcMap = RpcMap[iRpc];

              if (fviRpcSide[iGbtx] == 0) iStrMap = 31 - iStr;
              if (fviModuleId[iGbtx] > -1)
                fviRpcChUId[iCh] =
                  CbmTofAddress::GetUniqueAddress(fviModuleId[iGbtx],
                                                  iRpcMap,
                                                  iStrMap,
                                                  fviRpcSide[iGbtx],
                                                  fviRpcType[iGbtx]);
              else
                fviRpcChUId[iCh] = 0;
              //	 LOG(DEBUG)<<Form("Map Ch %d to Address 0x%08x",iCh,fviRpcChUId[iCh]);
              iCh += iChNext;
            }
          }
        }
        iCh += 64;
        break;

      case 5:  // Diamond
      {
        LOG(info) << " Map diamond  at GBTX  -  iCh = " << iCh;
        for (UInt_t uFee = 0; uFee < fUnpackPar->GetNrOfFeePerGbtx(); ++uFee) {
          for (UInt_t uCh = 0; uCh < fUnpackPar->GetNrOfChannelsPerFee();
               ++uCh) {
            if (uFee < 4 && (0 == uCh % 4 || uCh < 4)) {
              //  if(  0 == uCh )  {
              fviRpcChUId[iCh] = CbmTofAddress::GetUniqueAddress(
                fviModuleId[iGbtx],
                0,
                uFee * fUnpackPar->GetNrOfChannelsPerFee() / 4 + uCh / 4
                  + 40 * fviRpcSide[iGbtx],
                //                           0, uFee + 10 * fviRpcSide[iGbtx],
                0,
                fviRpcType[iGbtx]);
              LOG(info) << Form(
                "Map T0 Ch %d to Address 0x%08x", iCh, fviRpcChUId[iCh]);
            } else
              fviRpcChUId[iCh] = 0;

            iCh++;
          }  // for( UInt_t uCh = 0; uCh < fUnpackPar->GetNrOfChannelsPerFee(); ++uCh )
        }  // for( UInt_t uFee = 0; uFee < fUnpackPar->GetNrOfFeePerGbtx(); ++uFee )
      } break;

      case 78:  // cern-20-gap + ceramic module
      {
        LOG(info) << " Map CERN 20 gap  at GBTX  -  iCh = " << iCh;
        const Int_t StrMap[32] = {0,  1,  2,  3,  4,  31, 5,  6,  7,  30, 8,
                                  9,  10, 29, 11, 12, 13, 14, 28, 15, 16, 17,
                                  18, 27, 26, 25, 24, 23, 22, 21, 20, 19};
        Int_t iModuleId        = 0;
        Int_t iModuleType      = 7;
        Int_t iRpcMap          = 0;
        for (Int_t iFeet = 0; iFeet < 2; iFeet++) {
          for (Int_t iStr = 0; iStr < 32; iStr++) {
            Int_t iStrMap  = 31 - 12 - StrMap[iStr];
            Int_t iSideMap = iFeet;

            if (iStrMap < 20)
              fviRpcChUId[iCh] = CbmTofAddress::GetUniqueAddress(
                iModuleId, iRpcMap, iStrMap, iSideMap, iModuleType);
            else
              fviRpcChUId[iCh] = 0;
            iCh++;
          }
        }
      }
        // fall through is intended
      case 8:  // ceramics
      {
        Int_t iModuleId   = 0;
        Int_t iModuleType = 8;
        for (Int_t iRpc = 0; iRpc < 8; iRpc++) {
          fviRpcChUId[iCh] = CbmTofAddress::GetUniqueAddress(
            iModuleId, 7 - iRpc, 0, 0, iModuleType);
          iCh++;
        }
        iCh += (24 + 2 * 32);
      }
        LOG(info) << " Map end ceramics  box  at GBTX  -  iCh = " << iCh;

        break;

      case 9:  // Star2 boxes
      {
        LOG(info) << " Map Star2 box  at GBTX  -  iCh = " << iCh;
        const Int_t iRpc[5]  = {1, -1, 1, 0, 0};
        const Int_t iSide[5] = {1, -1, 0, 1, 0};
        for (Int_t iFeet = 0; iFeet < 5; iFeet++) {
          for (Int_t iStr = 0; iStr < 32; iStr++) {
            Int_t iStrMap  = iStr;
            Int_t iRpcMap  = iRpc[iFeet];
            Int_t iSideMap = iSide[iFeet];
            if (iSideMap == 0) iStrMap = 31 - iStr;
            if (iSideMap > -1)
              fviRpcChUId[iCh] =
                CbmTofAddress::GetUniqueAddress(fviModuleId[iGbtx],
                                                iRpcMap,
                                                iStrMap,
                                                iSideMap,
                                                fviRpcType[iGbtx]);
            else
              fviRpcChUId[iCh] = 0;

            iCh++;
          }
        }
      } break;

      case 6:  // Buc box
      {
        LOG(info) << " Map Buc box  at GBTX  -  iCh = " << iCh;
        const Int_t iRpc[5]  = {0, -1, 0, 1, 1};
        const Int_t iSide[5] = {1, -1, 0, 1, 0};
        for (Int_t iFeet = 0; iFeet < 5; iFeet++) {
          for (Int_t iStr = 0; iStr < 32; iStr++) {
            Int_t iStrMap  = iStr;
            Int_t iRpcMap  = iRpc[iFeet];
            Int_t iSideMap = iSide[iFeet];
            //if(iSideMap == 0)iStrMap=31-iStr;
            switch (fviRpcSide[iGbtx]) {
              case 0:; break;
              case 1:  // HD cosmic 2019, Buc2018, v18n
                iStrMap = 31 - iStr;
                iRpcMap = 1 - iRpcMap;
                break;
              case 2:  // v18m_cosmicHD
                //		 iStrMap=31-iStr;
                iSideMap = 1 - iSideMap;
                break;
              case 3:
                iStrMap  = 31 - iStr;
                iRpcMap  = 1 - iRpcMap;
                iSideMap = 1 - iSideMap;
                break;
              case 4:  // HD cosmic 2019, Buc2018, v18o
                iRpcMap = 1 - iRpcMap;
                break;
              default:;
            }
            if (iSideMap > -1)
              fviRpcChUId[iCh] =
                CbmTofAddress::GetUniqueAddress(fviModuleId[iGbtx],
                                                iRpcMap,
                                                iStrMap,
                                                iSideMap,
                                                fviRpcType[iGbtx]);
            else
              fviRpcChUId[iCh] = 0;

            iCh++;
          }
        }
      } break;

      case -1:
        LOG(info) << " Found unused GBTX link at iCh = " << iCh;
        iCh += 160;
        break;

      default:
        LOG(error) << "Invalid Type  specifier for Gbtx " << iGbtx << ": "
                   << fviRpcType[iGbtx];
    }
  }

  for (UInt_t i = 0; i < uNrOfChannels; i = i + 8) {
    if (i % 64 == 0) LOG(info) << " Index " << i;
    LOG(info) << Form("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
                      fviRpcChUId[i],
                      fviRpcChUId[i + 1],
                      fviRpcChUId[i + 2],
                      fviRpcChUId[i + 3],
                      fviRpcChUId[i + 4],
                      fviRpcChUId[i + 5],
                      fviRpcChUId[i + 6],
                      fviRpcChUId[i + 7]);
  }  // for( UInt_t i = 0; i < uNrOfChannels; ++i)
Administrator's avatar
Administrator committed
void CbmDeviceUnpackTofMcbm2018::CreateHistograms() {
  LOG(info) << "create Histos for " << fuNrOfGdpbs << " gDPBs ";
Administrator's avatar
Administrator committed
  fhRawTDigEvT0 =
    new TH1F(Form("Raw_TDig-EvT0"),
             Form("Raw digi time difference to 1st digi ; time [ns]; cts"),
             500,
             0,
             100.);
  //   fHM->Add( Form("Raw_TDig-EvT0"), fhRawTDigEvT0);

Administrator's avatar
Administrator committed
  fhRawTDigRef0 =
    new TH1F(Form("Raw_TDig-Ref0"),
             Form("Raw digi time difference to Ref ; time [ns]; cts"),
             6000,
             -10000,
             50000);
  //   fHM->Add( Form("Raw_TDig-Ref0"), fhRawTDigRef0);

Administrator's avatar
Administrator committed
  fhRawTDigRef =
    new TH1F(Form("Raw_TDig-Ref"),
             Form("Raw digi time difference to Ref ; time [ns]; cts"),
             6000,
             -1000,
             5000);
  //   fHM->Add( Form("Raw_TDig-Ref"), fhRawTDigRef);

Administrator's avatar
Administrator committed
  fhRawTRefDig0 =
    new TH1F(Form("Raw_TRef-Dig0"),
             Form("Raw Ref time difference to last digi  ; time [ns]; cts"),
             9999,
             -50000,
             50000);
  //   fHM->Add( Form("Raw_TRef-Dig0"), fhRawTRefDig0);

Administrator's avatar
Administrator committed
  fhRawTRefDig1 =
    new TH1F(Form("Raw_TRef-Dig1"),
             Form("Raw Ref time difference to last digi  ; time [ns]; cts"),
             9999,
             -5000,
             5000);
  //   fHM->Add( Form("Raw_TRef-Dig1"), fhRawTRefDig1);

Administrator's avatar
Administrator committed
  fhRawDigiLastDigi =
    new TH1F(Form("Raw_Digi-LastDigi"),
             Form("Raw Digi time difference to last digi  ; time [ns]; cts"),
             9999,
             -5000,
             5000);
  //                                 9999, -5000000, 5000000);
  //   fHM->Add( Form("Raw_Digi-LastDigi"), fhRawDigiLastDigi);

Administrator's avatar
Administrator committed
  fhRawTotCh.resize(fuNrOfGdpbs);
  fhChCount.resize(fuNrOfGdpbs);
  fhChanCoinc.resize(fuNrOfGdpbs * fuNrOfFeePerGdpb / 2);
  for (UInt_t uGdpb = 0; uGdpb < fuNrOfGdpbs; uGdpb++) {
    fhRawTotCh[uGdpb] =
      new TH2F(Form("Raw_Tot_gDPB_%02u", uGdpb),
               Form("Raw TOT gDPB %02u; channel; TOT [bin]", uGdpb),
               fuNrOfChannelsPerGdpb,
               0.,
               fuNrOfChannelsPerGdpb,
               256,
               0.,
               256.);
    //      fHM->Add( Form("Raw_Tot_gDPB_%02u", uGdpb), fhRawTotCh[ uGdpb ]);

    fhChCount[uGdpb] =
      new TH1I(Form("ChCount_gDPB_%02u", uGdpb),
               Form("Channel counts gDPB %02u; channel; Hits", uGdpb),
               fuNrOfChannelsPerGdpb,
               0.,
               fuNrOfChannelsPerGdpb);
    //      fHM->Add( Form("ChCount_gDPB_%02u", uGdpb), fhChCount[ uGdpb ]);
    /*
	for( UInt_t uLeftFeb = uGdpb*fuNrOfFebsPerGdpb / 2;
	uLeftFeb < (uGdpb + 1 )*fuNrOfFebsPerGdpb / 2;
	++uLeftFeb )
	{
	fhChanCoinc[ uLeftFeb ] = new TH2F( Form("fhChanCoinc_%02u", uLeftFeb),
	Form("Channels Coincidence %02; Left; Right", uLeftFeb),
	fuNrOfChannelsPerFee, 0., fuNrOfChannelsPerFee,
	fuNrOfChannelsPerFee, 0., fuNrOfChannelsPerFee );
	} // for( UInt_t uLeftFeb = 0; uLeftFeb < fuNrOfFebsPerGdpb / 2; uLeftFeb ++ )
      */
Administrator's avatar
Administrator committed
    fhChanCoinc[uGdpb] =
      new TH2F(Form("fhChanCoinc_%02u", uGdpb),
               Form("Channels Coincidence %02u; Left; Right", uGdpb),
               fuNrOfChannelsPerGdpb,
               0.,
               fuNrOfChannelsPerGdpb,
               fuNrOfChannelsPerGdpb,
               0.,
               fuNrOfChannelsPerGdpb);
  }  // for( UInt_t uGdpb = 0; uGdpb < fuMinNbGdpb; uGdpb ++)
  fhDetChanCoinc = new TH2F("fhDetChanCoinc",
                            "Det Channels Coincidence; Left; Right",
                            32,
                            0.,
                            32,
                            32,
                            0.,
                            32);
}

// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)
Administrator's avatar
Administrator committed
bool CbmDeviceUnpackTofMcbm2018::HandleData(FairMQMessagePtr& msg,
                                            int /*index*/) {
  // Don't do anything with the data
  // Maybe add an message counter which counts the incomming messages and add
  // an output
Administrator's avatar
Administrator committed
  LOG(debug) << "Received message number " << fNumMessages << " with size "
             << msg->GetSize();

  std::string msgStr(static_cast<char*>(msg->GetData()), msg->GetSize());
  std::istringstream iss(msgStr);
  boost::archive::binary_iarchive inputArchive(iss);

Administrator's avatar
Administrator committed
  fles::StorableTimeslice component {0};
  inputArchive >> component;

  //  CheckTimeslice(component);

  DoUnpack(component, 0);

  BuildTint(0);

Administrator's avatar
Administrator committed
  if (fNumMessages % 10000 == 0)
    LOG(info) << "Processed " << fNumMessages << " time slices";
Administrator's avatar
Administrator committed
bool CbmDeviceUnpackTofMcbm2018::HandleParts(FairMQParts& parts,
                                             int /*index*/) {
  // Don't do anything with the data
  // Maybe add an message counter which counts the incomming messages and add
  // an output
Administrator's avatar
Administrator committed
  LOG(debug) << "Received message number " << fNumMessages << " with "
             << parts.Size() << " parts";

  fles::StorableTimeslice ts {0};
Administrator's avatar
Administrator committed
  switch (fiSelectComponents) {
    case 0: {
      std::string msgStr(static_cast<char*>(parts.At(0)->GetData()),
                         (parts.At(0))->GetSize());
      std::istringstream iss(msgStr);
      boost::archive::binary_iarchive inputArchive(iss);
Administrator's avatar
Administrator committed
      inputArchive >> ts;
      //CheckTimeslice(ts);
Administrator's avatar
Administrator committed
      if (1 == fNumMessages) {
        LOG(info) << "Initialize TS components list to " << ts.num_components();
        for (size_t c {0}; c < ts.num_components(); c++) {
          auto systemID = static_cast<int>(ts.descriptor(c, 0).sys_id);
          LOG(info) << "Found systemID: " << std::hex << systemID << std::dec;
          fUnpackerAlgo->AddMsComponentToList(c, systemID);  // TOF data
        }
      }
      DoUnpack(ts, 0);
    } break;
    case 1: {
      fles::StorableTimeslice component {0};

      uint ncomp = parts.Size();
      for (uint i = 0; i < ncomp; i++) {
        std::string msgStr(static_cast<char*>(parts.At(i)->GetData()),
                           (parts.At(i))->GetSize());
        std::istringstream iss(msgStr);
        boost::archive::binary_iarchive inputArchive(iss);
        //fles::StorableTimeslice component{i};
        inputArchive >> component;

        //      CheckTimeslice(component);
Administrator's avatar
Administrator committed
        fUnpackerAlgo->AddMsComponentToList(0, 0x60);  // TOF data
        LOG(debug) << "HandleParts message " << fNumMessages << " with indx "
                   << component.index();
        DoUnpack(component, 0);
      }
    } break;
    default:;
Administrator's avatar
Administrator committed
  if (fNumMessages % 10000 == 0)
    LOG(info) << "Processed " << fNumMessages << " time slices";
Administrator's avatar
Administrator committed
bool CbmDeviceUnpackTofMcbm2018::HandleMessage(FairMQMessagePtr& msg,
                                               int /*index*/) {
  const char* cmd    = (char*) (msg->GetData());
  const char cmda[4] = {*cmd};
  LOG(info) << "Handle message " << cmd << ", " << cmd[0];
  cbm::mq::LogState(this);

  // only one implemented so far "Stop"

Administrator's avatar
Administrator committed
  if (strcmp(cmda, "STOP")) {
    LOG(info) << "STOP";
    fUnpackerAlgo->Finish();
    cbm::mq::ChangeState(this, cbm::mq::Transition::Ready);
    cbm::mq::LogState(this);
    cbm::mq::ChangeState(this, cbm::mq::Transition::DeviceReady);
    cbm::mq::LogState(this);
    cbm::mq::ChangeState(this, cbm::mq::Transition::Idle);
    cbm::mq::LogState(this);
    cbm::mq::ChangeState(this, cbm::mq::Transition::End);
    cbm::mq::LogState(this);
  }
  return true;
}

Administrator's avatar
Administrator committed
Bool_t CbmDeviceUnpackTofMcbm2018::DoUnpack(const fles::Timeslice& ts,
                                            size_t component) {
  LOG(debug) << "Timeslice " << ts.index() << " contains "
             << ts.num_microslices(component) << " microslices of component "
             << component;

  if (kFALSE == fUnpackerAlgo->ProcessTs(ts)) {
    LOG(error) << "Failed processing TS " << ts.index()
               << " in unpacker algorithm class";
    return kTRUE;
  }  // if( kFALSE == fUnpackerAlgo->ProcessTs( ts ) )

  /// Copy the digis in the DaqBuffer
  std::vector<CbmTofDigi> vDigi = fUnpackerAlgo->GetVector();

  /*
   // time sort vDigis
   sort(vDigi.begin(), vDigi.end(),
        [](const CbmTofDigi & a, const CbmTofDigi & b) -> bool
        {
          return a.GetTime() < b.GetTime();
        });
   */

Administrator's avatar
Administrator committed
  LOG(debug) << "Insert " << vDigi.size()
             << " digis into DAQ buffer  with size " << fBuffer->GetSize();
Administrator's avatar
Administrator committed
  for (auto digi : vDigi) {
    // copy Digi for insertion into DAQ buffer
    CbmTofDigi* fDigi = new CbmTofDigi(digi);

    //if( (fDigi->GetAddress() & 0x000F00F ) != fiAddrRef )  fDigi->SetTime(fDigi->GetTime()+fdToffTof); // shift all Tof Times for v14a geometries
    if ((fDigi->GetAddress() & 0x000780F) != fiAddrRef)
      fDigi->SetTime(fDigi->GetTime()
                     + fdToffTof);  // shift all Tof Times for V21a
Administrator's avatar
Administrator committed
    LOG(debug) << "BufferInsert digi "
               << Form(
                    "0x%08x at %012.2f", fDigi->GetAddress(), fDigi->GetTime())
               << Form(", first %012.2f, last %012.2f, size %u",
                       fBuffer->GetTimeFirst(),
                       fBuffer->GetTimeLast(),
                       fBuffer->GetSize());
Administrator's avatar
Administrator committed
    fBuffer->InsertData<CbmTofDigi>(fDigi);
  }
  vDigi.clear();
  fUnpackerAlgo->ClearVector();
Administrator's avatar
Administrator committed
  return kTRUE;
Administrator's avatar
Administrator committed
void CbmDeviceUnpackTofMcbm2018::BuildTint(int iMode = 0) {
  // iMode - sending condition
  // 0 (default)- build time interval only if last buffer entry is older the start + TSLength
  // 1 (finish), empty buffer without checking
  // Steering variables
  double TSLENGTH    = 1.E6;
Administrator's avatar
Administrator committed
  double fdMaxDeltaT = (double) fiReqTint;  // in ns
  LOG(debug) << "BuildTint: Buffer size " << fBuffer->GetSize() << ", DeltaT "
Administrator's avatar
Administrator committed
             << (fBuffer->GetTimeLast() - fBuffer->GetTimeFirst()) / 1.E9
             << " s";
  CbmTbDaqBuffer::Data data;
  CbmTofDigi* digi;
Administrator's avatar
Administrator committed
  while (fBuffer->GetSize() > 0) {
    Double_t fTimeBufferLast = fBuffer->GetTimeLast();

Administrator's avatar
Administrator committed
    switch (iMode) {
      case 0:
        if (fTimeBufferLast - fBuffer->GetTimeFirst() < TSLENGTH) return;
        break;
      case 1:; break;
    data = fBuffer->GetNextData(fTimeBufferLast);
    digi = boost::any_cast<CbmTofDigi*>(data.first);
    assert(digi);

Administrator's avatar
Administrator committed
    Double_t dTEnd    = digi->GetTime() + fdMaxDeltaT;
    Double_t dTEndMax = digi->GetTime() + 2 * fdMaxDeltaT;
    LOG(debug) << Form(
      "Next event at %f until %f, max %f ", digi->GetTime(), dTEnd, dTEndMax);

Administrator's avatar
Administrator committed
    if (dTEnd > fTimeBufferLast) {
      LOG(warn) << Form("Remaining buffer < %f with %d entries is not "
                        "sufficient for digi ending at %f -> skipped ",
                        fTimeBufferLast,
                        fBuffer->GetSize(),
                        dTEnd);
    LOG(debug) << "BuildTint0 with digi "
               << Form(
                    "0x%08x at %012.2f", digi->GetAddress(), digi->GetTime());

    Bool_t bDet[fiReqDigiAddr.size()][2];