How to access the TimeFrame ID within a DPL workflow

In the MCH processing workflow we would like to define the time of the digits as “TimeFrame ID” + “number of bunch crossings since the beginning of the TimeFrame”.

While we have a solution fo the “number of bunch crossings”, I am not able to find a way to retrieve the current TimeFrame ID when processing the data coming from the TimeFrameBuilder.

My tests are based on some old VerticalSlice test data that we collected in March, replied via the subTimeFrameBuilder with the following command:

StfBuilder --id stf_builder-0 --transport shmem --detector MCH --dpl-channel-name=dpl-chan --channel-config "name=dpl-chan,type=push,method=bind,address=ipc:///tmp/stf-builder-dpl-pipe-0,transport=shmem,rateLogging=1" --data-source-dir=2020-03-10T16_09_42Z --data-source-enable

The input folder looks like this:

$> ls 2020-03-10T16_09_42Z/
2020-03-10_00002478.tf	2020-03-10_00002478.tf.info

and the beginning of the tf.info file is like this:

$> head 2020-03-10T16_09_42Z/2020-03-10_00002478.tf.info 
TF_ID      TF_OFFSET  TF_SIZE   ORIGIN DESC      SUBSPEC    DATA_IDX HDR_OFF    HDR_SIZE DATA_OFF   DATA_SIZE RDH_MEM_SIZE RDH_STOP_BIT RDH_FEE_ID RDH_ORBIT    RDH_BC     RDH_TRG   
2478       0          140108136 MCH    RAWDATA   0x000a0001 0        2536       80       2616       16384     128          1            4844       821853749    0          0x00000803
2478       0          140108136 MCH    RAWDATA   0x000a0001 1        19000      80       19080      16384     128          1            4844       821853750    0          0x00000007
2478       0          140108136 MCH    RAWDATA   0x000a0001 2        35464      80       35544      16384     128          1            4844       821853751    0          0x00000007
2478       0          140108136 MCH    RAWDATA   0x000a0001 3        51928      80       52008      16384     128          1            4844       821853752    0          0x00000007
2478       0          140108136 MCH    RAWDATA   0x000a0001 4        68392      80       68472      16384     128          1            4844       821853753    0          0x00000007
2478       0          140108136 MCH    RAWDATA   0x000a0001 5        84856      80       84936      16384     128          1            4844       821853754    0          0x00000007
2478       0          140108136 MCH    RAWDATA   0x000a0001 6        101320     80       101400     16384     128          1            4844       821853755    0          0x00000007
2478       0          140108136 MCH    RAWDATA   0x000a0001 7        117784     80       117864     16384     128          1            4844       821853756    0          0x00000007
2478       0          140108136 MCH    RAWDATA   0x000a0001 8        134248     80       134328     16384     128          1            4844       821853757    0          0x00000007

In a separate shell I am running the o2-dpl-raw-proxy to inject the TimeFrames into our DPL workflow:

o2-dpl-raw-proxy -b --dataspec "A:MCH/RAWDATA" --channel-config "name=readout-proxy,type=pull,method=connect,address=ipc:///tmp/stf-builder-dpl-pipe-0,transport=shmem,rateLogging=1" --session default | o2-mch-raw-to-digits-workflow -b --session default

The raw-to-digits workflow parses the input messages using the DPLRawParser, like this:

    DPLRawParser parser(inputs, o2::framework::select("TF:MCH/RAWDATA"));

    for (auto it = parser.begin(), end = parser.end(); it != end; ++it) {
      auto const* rdh = it.get_if<RDH>();
      auto const* raw = it.raw();
      size_t payloadSize = it.size();

      const auto* dh = it.o2DataHeader();
    }

Is there a way to access the current TF ID at this level? The DatahHeader structure has a tfCounter field, but it seems to be a simple incremental counter that does not match the actual TF ID…

Thanks!

Cheers, Andrea

Hi @aferrero

I don’t think we have a global TF ID. The DataHeader has a firstTForbit data member, which at the moment is not set/propagated, but it is supposed to proved the 1st orbit (of 1st TF) of the run. Knowing from CCDB the abs. time of SOR, this will allow to get abs time any BC.
But why don’t you use the in the processing need the time (or bc) from the start of given TF? This is what other detectors do.

Cheers,
Ruben

Do you mean to only consider the time within a TimeFrame, and ignore which specific TimeFrame is being processed? This is of course possible (and easier), if the knowledge of the TF ID is not needed further downstream in the processing pipeline.

So far, all inter-detector matching is done based on the the time within the TF, i.e. IR_data - firstTForbit, but the output is stored with full IR.
Above I’ve provided a wrong info: DataHeader.firstTForbit will provide the 1st orbit of the TF being processed. Since this is still not functional, for the simulated data processing one can use the family of methods from the o2::raw::HBFUtils class, operating e.g. on o2::InteractionRecord ir:

auto& hbu = o2::raw::HBFUtils::Instance();
uint32_t tf = hbu,getTF(ir); // TF ID from the beginning of the run
uint32_t hb = hbu.getHBF(ir); // HBF ID within the TF
std::pair<int, int> tfhb = hbu.getTFandHB(ir); // both at the same time
o2::InteractionRecord irFirst = hbu.getFirstIRofTF(ir); // 1st IR of current TF 

By default the HBFUtils assumes IR={0,0} for the start of run, but it derives from ConfigurableParam so can be set from the command line.

Hi Ruben,

I’m a bit confused here. Part of the underlying question (or closely related) is that we need to access the calibrations associated to a given TF, and I thought the key for the CCDB was an absolute timestamp. So how do we get such an absolute time stamp ?

Do I understand that the DataHeader firstOrbit is an “absolute” orbit number (at least relative to a fill) or is it more “local” than that ?

Also, I’ve noticed new (to me at least) fields in the DataHeader : tfCounter and runNumber : what are those exactly ?

Thanks,

Hi @laphecet

The firstTFOrbit is the 1st orbit of the givem TF, counted from the time when the orbit was reset, nominally at the the start of stable beam (though CTP may decide to reset it also in the beginning of the run, if needed). The absolute time can be extracted from this `firsTFOrbit and the 1st orbit of the run + abs SOR time which will be stored in the CCDB.
The tfCounter was added (at the moment) as an ever increasing counter to be able to distinguish TFs in the loop replay mode: both RawFileReader and readout/DD allow to replay a number of TFs in continuous loop, since the firstTFOrbit will repeat in this case, the tfCounter will provide an extra degree of freedom to distinguish them. The runNumber is what it is.
But at the moment neither of these 3 parameters are set or propagated by the DPL, this is yet to be implemented.

Hello @shahoian,
concerning Readout, in file replay “loop” mode, BC counters are modified on the fly in the generated data after the 1st iteration to give a coherent sequence of increasing tfId. So you don’t need tfCounter for this case.

Hi @sy-c

Thanks. You mean you scan all RDHs and patch their orbit/bc? But how this affects the O2 header created by DD (which is used by the DPL to sync. messages)?

Cheers,
Ruben

Yes, RDH are patched. DD gets an increasing sequence of TFids, as it expects. I suppose this is propagated to O2 header.

@sy-c as far as I can see, DD uses the RDH only to set the DataHeader. firstTForbit (which is currently not used or propagated by the DPL), but I could not find where it uses it to set the DataProcessingHeader.startTime used by DPL to match the messages of the same TF. Perhaps @gneskovi can correct me.