Newer
Older
/* Copyright (C) 2018-2020 PI-UHd, GSI
SPDX-License-Identifier: GPL-3.0-only
Authors: Florian Uhlig, Norbert Herrmann [committer] */
/**
* CbmDeviceUnpackTofMcbm2018.cxx
*
* @since 2018-04-24
* @author F. Uhlig
*/
#include "CbmDeviceUnpackTofMcbm2018.h"
#include "CbmMQDefs.h"
#include "CbmMcbm2018TofPar.h"
//#include "CbmHistManager.h"
#include "CbmTbDaqBuffer.h"
#include "CbmTofAddress.h"
#include "CbmTofDetectorId_v21a.h" // in cbmdata/tof
#include "StorableTimeslice.hpp"
#include "FairMQLogger.h"
#include "FairParGenericSet.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>
struct InitTaskError : std::runtime_error {
using std::runtime_error::runtime_error;
};
using namespace std;
//static Int_t iMess=0;
CbmDeviceUnpackTofMcbm2018::CbmDeviceUnpackTofMcbm2018()
: fNumMessages(0)
, fiSelectComponents(0)
, fNumTint(0)
, fEventHeader()
, fiReqMode(0)
, fiReqTint(0)
, fiReqDigiAddr()
, fiPulserMode(0)
, fiPulMulMin(0)
, fiPulTotMin(0)
, fiPulTotMax(1000)
, fuTotalMsNb(0)
, fuOverlapMsNb(0)
, fuCoreMs(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)
, fMsgCounter(11, 0) // length of enum MessageTypes initialized with 0
, fGdpbIdIndexMap()
, fvulCurrentEpoch()
, fvbFirstEpochSeen()
, fNofEpochs(0)
, fulCurrentEpochTime(0.)
//, fdMsIndex(0.)
//, fuDiamondDpbIdx(3)
//, fbEpochSuppModeOn( kTRUE )
//, fbGet4M24b( kFALSE )
//, fbGet4v20( kTRUE )
//, fbMergedEpochsOn( kTRUE )
, fUnpackPar(nullptr)
, fdLastDigiTime(0.)
, fdFirstDigiTimeDif(0.)
//, fdEvTime0(0.)
, 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())
CbmDeviceUnpackTofMcbm2018::~CbmDeviceUnpackTofMcbm2018() { delete fUnpackerAlgo; }
// 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;
//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];
}
InitContainers();
const Int_t iHeaderSize = 4;
fEventHeader.resize(iHeaderSize); // define size of eventheader int[]
for (int i = 0; i < iHeaderSize; i++)
fEventHeader[i] = 0;
fiSelectComponents = fConfig->GetValue<uint64_t>("SelectComponents");
fiReqMode = fConfig->GetValue<uint64_t>("ReqMode");
fiReqTint = fConfig->GetValue<uint64_t>("ReqTint");
fiReqBeam = fConfig->GetValue<uint64_t>("ReqBeam");
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;
// Int_t iMaxAsicInactive = fConfig->GetValue<uint64_t>("MaxAsicInactive");
// fUnpackerAlgo->SetMaxAsicInactive( iMaxAsicInactive );
Int_t iReqDet = 1;
Int_t iNReq = 0;
while (iNReq < iMaxReq) { // FIXME, setup parameter hardwired!
iReqDet = fConfig->GetValue<uint64_t>(Form("ReqDet%d", iNReq));
if (iReqDet == 0) break;
AddReqDigiAddr(iReqDet);
iNReq++;
}
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]);
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]);
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);
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);
LOG(error) << e.what();
// Wrapper defined in CbmMQDefs.h to support different FairMQ versions
cbm::mq::ChangeState(this, cbm::mq::Transition::ErrorFound);
}
bool CbmDeviceUnpackTofMcbm2018::IsChannelNameAllowed(std::string channelName)
{
LOG(info) << "Inspect " << entry;
std::size_t pos1 = channelName.find(entry);
const vector<std::string>::const_iterator pos =
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 << " found in list of allowed channel names at position " << idx;
LOG(info) << "Channel name " << channelName << " not found in list of allowed channel names.";
LOG(error) << "Stop device.";
return false;
}
Bool_t CbmDeviceUnpackTofMcbm2018::InitContainers()
{
LOG(info) << "Init parameter containers for CbmDeviceUnpackTofMcbm2018.";
// 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
LOG(info) << "Requesting parameter container CbmMcbm2018TofPar, sending message: " << message;
FairMQMessagePtr req(NewSimpleMessage("CbmMcbm2018TofPar,111"));
FairMQMessagePtr rep(NewMessage());
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;
LOG(error) << "Received empty reply. Parameter not available";
}
Bool_t initOK = kTRUE;
initOK &= fUnpackerAlgo->InitContainers();
initOK &= ReInitContainers(); // needed for TInt parameters
// 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 )
fNumTint = 0;
return initOK;
}
void CbmDeviceUnpackTofMcbm2018::SetParContainers()
{
LOG(info) << "Setting parameter containers for " << fParCList->GetEntries() << " entries ";
for (Int_t iparC = 0; iparC < fParCList->GetEntries(); ++iparC) {
FairParGenericSet* tempObj = (FairParGenericSet*) (fParCList->At(iparC));
fParCList->Remove(tempObj);
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 )
void CbmDeviceUnpackTofMcbm2018::AddMsComponentToList(size_t component, UShort_t usDetectorId)
{
fUnpackerAlgo->AddMsComponentToList(component, usDetectorId);
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;
/// 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 };
*/
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);
}
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]);
// 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],
LOG(info) << Form("Map Bmon Ch %d to Address 0x%08x", iCh, fviRpcChUId[iCh]);
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};
// clang-format on
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++;
}
}
}
[[fallthrough]]; // 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;
switch (fviRpcSide[iGbtx]) {
case 0:; break;
case 1:; break;
case 2:
switch (iFeet) {
case 1:
iRpcMap = iRpc[4];
iSideMap = iSide[4];
break;
case 4:
iRpcMap = iRpc[1];
iSideMap = iSide[1];
break;
default:;
}
break;
}
CbmTofAddress::GetUniqueAddress(fviModuleId[iGbtx], iRpcMap, iStrMap, iSideMap, fviRpcType[iGbtx]);
else
fviRpcChUId[iCh] = 0;
iCh++;
}
}
} break;
case 6: // Buc box
{
LOG(info) << " DevMap Buc box at GBTX - iCh = " << iCh;
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
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;
case 5: // HD cosmic 2020, Buc2018, v20a
iStrMap = 31 - iStr;
break;
case 6: //BUC special
{
switch (fviModuleId[iGbtx]) {
case 0: iRpcMap = 0; break;
case 1: iRpcMap = 1; break;
}
if (iFeet > 2) iModuleIdMap = 1;
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
case 7: {
// clang-format off
const Int_t iChMap[160]={
127, 126, 125, 124, 12, 13, 14, 15, 7, 6, 5, 4, 28, 29, 30, 31, 123, 122, 121, 120, 8, 9, 10, 11, 107, 106, 105, 104, 108, 109, 110, 111,
39, 38, 37, 36, 52, 53, 54, 55, 63, 62, 61, 60, 128, 129, 130, 131, 43, 42, 41, 40, 148, 149, 150, 151, 59, 58, 57, 56, 132, 133, 134, 135,
139, 138, 137, 136, 140, 141, 142, 143, 99, 98, 97, 96, 64, 65, 66, 67, 103, 102, 101, 100, 84, 85, 86, 87, 155, 154, 153, 152, 68, 69, 70, 71,
159, 158, 157, 156, 144, 145, 146, 147, 47, 46, 45, 44, 76, 77, 78, 79, 51, 50, 49, 48, 20, 21, 22, 23, 35, 34, 33, 32, 116, 117, 118, 119,
75, 74, 73, 72, 92, 93, 94, 95, 19, 18, 17, 16, 80, 81, 82, 83, 115, 114, 113, 112, 24, 25, 26, 27, 91, 90, 89, 88, 0, 1, 2, 3
};
// clang-format on
Int_t iInd = iFeet * 32 + iStr;
Int_t i = 0;
for (; i < 160; i++)
if (iInd == iChMap[i]) break;
iStrMap = i % 32;
Int_t iFeetInd = (i - iStrMap) / 32;
switch (iFeet) {
case 0:
iRpcMap = 0;
iSideMap = 1;
break;
case 1:
iRpcMap = 1;
iSideMap = 1;
break;
case 2:
iRpcMap = 1;
iSideMap = 0;
break;
case 3:
iRpcMap = 0;
iSideMap = 0;
break;
case 4: iSideMap = -1; break;
}
iModuleIdMap = fviModuleId[iGbtx];
LOG(info) << "Buc of GBTX " << iGbtx
<< Form(", Feet %1d, Str %2d, i %3d, FeetInd %1d, Rpc %1d, Side %1d, Str %2d ", iFeet, iStr,
i, iFeetInd, iRpcMap, iSideMap, iStrMap);
} break;
fviRpcChUId[iCh] =
CbmTofAddress::GetUniqueAddress(iModuleIdMap, 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]);
return kTRUE;
}
void CbmDeviceUnpackTofMcbm2018::CreateHistograms()
{
LOG(info) << "create Histos for " << fuNrOfGdpbs << " gDPBs ";
fhRawTDigEvBmon =
new TH1F(Form("Raw_TDig-EvBmon"), Form("Raw digi time difference to 1st digi ; time [ns]; cts"), 500, 0, 100.);
// fHM->Add( Form("Raw_TDig-EvBmon"), fhRawTDigEvBmon);
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);
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);
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);
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);
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);
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 ++ )
*/
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)
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
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);
inputArchive >> component;
DoUnpack(component, 0);
BuildTint(0);
if (fNumMessages % 10000 == 0) LOG(info) << "Processed " << fNumMessages << " time slices";
return true;
}
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
LOG(debug) << "Received message number " << fNumMessages << " with " << parts.Size() << " parts";
std::string msgStr(static_cast<char*>(parts.At(0)->GetData()), (parts.At(0))->GetSize());
std::istringstream iss(msgStr);
boost::archive::binary_iarchive inputArchive(iss);
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;
fUnpackerAlgo->AddMsComponentToList(0, 0x60); // TOF data
LOG(debug) << "HandleParts message " << fNumMessages << " with indx " << component.index();
DoUnpack(component, 0);
}
} break;
default:;
}
BuildTint(0);
if (fNumMessages % 10000 == 0) LOG(info) << "Processed " << fNumMessages << " time slices";
return true;
}
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"
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;
}
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;
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();
});
*/
LOG(debug) << "Insert " << vDigi.size() << " digis into DAQ buffer with size " << fBuffer->GetSize();
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
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->InsertData<CbmTofDigi>(fDigi);
}
vDigi.clear();
fUnpackerAlgo->ClearVector();
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;
LOG(debug) << "BuildTint: Buffer size " << fBuffer->GetSize() << ", DeltaT "
<< (fBuffer->GetTimeLast() - fBuffer->GetTimeFirst()) / 1.E9 << " s";
CbmTbDaqBuffer::Data data;
CbmTofDigi* digi;
Double_t fTimeBufferLast = fBuffer->GetTimeLast();
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);
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);
if (dTEnd > fTimeBufferLast) {
LOG(warn) << Form("Remaining buffer < %f with %d entries is not "
"sufficient for digi ending at %f -> skipped ",
LOG(debug) << "BuildTint0 with digi " << Form("0x%08x at %012.2f", digi->GetAddress(), digi->GetTime());
Bool_t bDet[fiReqDigiAddr.size()][2];
for (UInt_t i = 0; i < fiReqDigiAddr.size(); i++)
for (Int_t j = 0; j < 2; j++)
bDet[i][j] = kFALSE; //initialize
Bool_t bPul[fiReqDigiAddr.size()][2];
for (UInt_t i = 0; i < fiReqDigiAddr.size(); i++)
for (Int_t j = 0; j < 2; j++)
bPul[i][j] = kFALSE; //initialize
std::vector<CbmTofDigi*> vdigi;
UInt_t nDigi = 0;
//const Int_t AddrMask=0x003FFFFF;
const Int_t AddrMask = 0x001FFFFF;
while (data.second != ECbmModuleId::kNotExist) { // build digi array
digi = boost::any_cast<CbmTofDigi*>(data.first);
LOG(debug) << "GetNextData " << digi << ", " << data.second << ", " << Form("%f %f", digi->GetTime(), dTEnd)
<< ", Mul " << nDigi;
if (nDigi == vdigi.size()) vdigi.resize(nDigi + 100);
vdigi[nDigi++] = digi;
Int_t iAddr = digi->GetAddress() & AddrMask;
if (iAddr == 0x00003006 || iAddr == 0x0000b006) {
iBucMul++;
LOG(debug) << Form("Event %10d: BucMul %2d, addr 0x%08x, side %d, strip %2d, rpc %d", fEventHeader[0], iBucMul,
digi->GetAddress(), (Int_t) digi->GetSide(), (Int_t) digi->GetChannel(),
(Int_t) digi->GetRpc());
}
for (UInt_t i = 0; i < fiReqDigiAddr.size(); i++)
if ((digi->GetAddress() & AddrMask) == fiReqDigiAddr[i]) {
Int_t j = ((CbmTofDigi*) digi)->GetSide();
bDet[i][j] = kTRUE;
if (fiReqDigiAddr[i] == (Int_t) fiReqBeam) {
bBeam = kTRUE;
LOG(debug) << "Found ReqBeam at index " << nDigi - 1 << ", req " << i;