Project
Loading...
Searching...
No Matches
CalibDataProcessorSpec.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
18
19#include <array>
20#include <vector>
21#include <gsl/gsl>
26#include "Framework/InputSpec.h"
27#include "Framework/Logger.h"
28#include "Framework/Task.h"
30#include "CCDB/CcdbObjectInfo.h"
36
37namespace of = o2::framework;
38
39namespace o2
40{
41namespace mid
42{
43
45{
46 public:
47 CalibDataProcessorDPL(const FEEIdConfig& feeIdConfig, const CrateMasks& crateMasks)
48 {
49 auto refMasks = makeDefaultMasksFromCrateConfig(feeIdConfig, crateMasks);
50 mFetToDead.setMasks(refMasks);
51 }
52
54 {
55 mMinDiff = ic.options().get<int64_t>("mid-merge-fet-bc-diff-min");
56 mMaxDiff = ic.options().get<int64_t>("mid-merge-fet-bc-diff-max");
57 }
58
60 {
61 std::array<gsl::span<const ColumnData>, 3> data;
62 std::array<gsl::span<const ROFRecord>, 3> dataRof;
63
64 for (o2::header::DataHeader::SubSpecificationType subSpec = 0; subSpec < NEvTypes; ++subSpec) {
65 data[subSpec] = pc.inputs().get<gsl::span<o2::mid::ColumnData>>(fmt::format("mid_data_{}", subSpec));
66 dataRof[subSpec] = pc.inputs().get<gsl::span<o2::mid::ROFRecord>>(fmt::format("mid_data_rof_{}", subSpec));
67 }
68
69 mNoise.clear();
70 mNoiseROF.clear();
71 mDead.clear();
72 mDeadROF.clear();
73
74 if (data[1].empty()) {
75 mNoise.insert(mNoise.end(), data[0].begin(), data[0].end());
76 mNoiseROF.insert(mNoiseROF.end(), dataRof[0].begin(), dataRof[0].end());
77 } else {
78
79 mNoise.insert(mNoise.end(), data[1].begin(), data[1].end());
80 mNoiseROF.insert(mNoiseROF.end(), dataRof[1].begin(), dataRof[1].end());
81
82 mergeChannels(data[2], dataRof[2], data[0], dataRof[0]);
83 }
84
85 pc.outputs().snapshot(of::Output{header::gDataOriginMID, "NOISE", 0}, mNoise);
86 pc.outputs().snapshot(of::Output{header::gDataOriginMID, "NOISEROF", 0}, mNoiseROF);
87 pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DEAD", 0}, mDead);
88 pc.outputs().snapshot(of::Output{header::gDataOriginMID, "DEADROF", 0}, mDeadROF);
89 }
90
91 private:
92 FetToDead mFetToDead{};
93 std::vector<ColumnData> mNoise;
94 std::vector<ROFRecord> mNoiseROF;
95 std::vector<ColumnData> mDead;
96 std::vector<ROFRecord> mDeadROF;
97 int64_t mMinDiff = -1;
98 int64_t mMaxDiff = 1;
99
100 void mergeChannels(gsl::span<const ColumnData> fetData, gsl::span<const ROFRecord> fetDataRof, gsl::span<const ColumnData> selfTrigData, gsl::span<const ROFRecord> selfTrigDataRof)
101 {
102 // This method selects the self-triggered events that are close in time with a FET event and merges them with the fet event.
103 // This is needed since the detector answer is not perfectly aligned in time.
104 // Since calibration runs occur with no beam, all other self-triggers are actually noise.
105
106 ColumnDataHandler handler;
107 // The FET data can be split into different BCs.
108 // Try to merge the expected FET data with the data in the close BCs
109 // which are probably badly tagged FET data
110 auto auxRofIt = selfTrigDataRof.begin();
111 // Loop on FET ROF
112 for (auto& rof : fetDataRof) {
113 handler.clear();
114 auto eventFetData = fetData.subspan(rof.firstEntry, rof.nEntries);
115 handler.merge(eventFetData);
116 for (; auxRofIt != selfTrigDataRof.end(); ++auxRofIt) {
117 auto bcDiff = auxRofIt->interactionRecord.differenceInBC(rof.interactionRecord);
118 if (bcDiff > mMaxDiff) {
119 // ROFs are time ordered. If the difference is larger than the maximum difference for merging,
120 // it means that the auxRofIt is in the future.
121 // We break and compare it to the next rof.
122 break;
123 } else if (bcDiff >= mMinDiff) {
124 // With the previous condition, this implies mMinDiff <= bcDiff <= mMaxDiff
125 auto auxFet = selfTrigData.subspan(auxRofIt->firstEntry, auxRofIt->nEntries);
126 handler.merge(auxFet);
127 } else {
128 // If bcDiff is < mMinDiff, it means that the auxRofIt is too much in the past
129 // So this was actually noise
130 mNoise.insert(mNoise.end(), selfTrigData.begin() + auxRofIt->firstEntry, selfTrigData.begin() + auxRofIt->getEndIndex());
131 mNoiseROF.emplace_back(*auxRofIt);
132 }
133 }
134 auto eventDeadChannels = mFetToDead.process(handler.getMerged());
135 mDeadROF.emplace_back(rof.interactionRecord, rof.eventType, mDead.size(), eventDeadChannels.size());
136 mDead.insert(mDead.end(), eventDeadChannels.begin(), eventDeadChannels.end());
137 }
138 }
139};
140
142{
143 std::vector<of::InputSpec> inputSpecs;
144 for (o2::header::DataHeader::SubSpecificationType subSpec = 0; subSpec < NEvTypes; ++subSpec) {
145 inputSpecs.emplace_back(fmt::format("mid_data_{}", subSpec), header::gDataOriginMID, "DATA", subSpec, of::Lifetime::Timeframe);
146 inputSpecs.emplace_back(fmt::format("mid_data_rof_{}", subSpec), header::gDataOriginMID, "DATAROF", subSpec, of::Lifetime::Timeframe);
147 }
148
149 std::vector<of::OutputSpec> outputSpecs;
150 outputSpecs.emplace_back(header::gDataOriginMID, "NOISE", 0);
151 outputSpecs.emplace_back(header::gDataOriginMID, "NOISEROF", 0);
152 outputSpecs.emplace_back(header::gDataOriginMID, "DEAD", 0);
153 outputSpecs.emplace_back(header::gDataOriginMID, "DEADROF", 0);
154
156 "MIDFetToDead",
157 {inputSpecs},
158 {outputSpecs},
159 of::AlgorithmSpec{of::adaptFromTask<o2::mid::CalibDataProcessorDPL>(feeIdConfig, crateMasks)},
161 {"mid-merge-fet-bc-diff-min", of::VariantType::Int, -1, {"Merge to FET if BC-BC_FET >= this value"}},
162 {"mid-merge-fet-bc-diff-max", of::VariantType::Int, 1, {"Merge to FET if BC-BC_FET <= this value"}}}};
163}
164} // namespace mid
165} // namespace o2
Device to convert the calibration data into a list of bad channel candidates.
MID digits handler.
Strip pattern (aka digits)
Utils and constants for calibration and related workflows.
Class to convert the FEE test event into dead channels.
A helper class to iteratate over all parts of all input routes.
Definition of the MID event record.
Function to produce the MID masks.
void snapshot(const Output &spec, T const &object)
ConfigParamRegistry const & options()
Definition InitContext.h:33
decltype(auto) get(R binding, int part=0) const
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
InputRecord & inputs()
The inputs associated with this processing context.
void run(of::ProcessingContext &pc)
CalibDataProcessorDPL(const FEEIdConfig &feeIdConfig, const CrateMasks &crateMasks)
std::vector< ColumnData > process(gsl::span< const ColumnData > fetData)
Definition FetToDead.cxx:51
void setMasks(const std::vector< ColumnData > &masks)
Sets the masks.
Definition FetToDead.h:44
GLboolean * data
Definition glcorearb.h:298
constexpr o2::header::DataOrigin gDataOriginMID
Definition DataHeader.h:573
Defining PrimaryVertex explicitly as messageable.
std::vector< ConfigParamSpec > Options
framework::DataProcessorSpec getCalibDataProcessorSpec(const FEEIdConfig &feeIdConfig, const CrateMasks &crateMasks)
std::vector< ColumnData > makeDefaultMasksFromCrateConfig(const FEEIdConfig &feeIdConfig=FEEIdConfig(), const CrateMasks &crateMasks=CrateMasks())
constexpr uint32_t NEvTypes
Definition ROFRecord.h:37
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
void empty(int)
uint32_t SubSpecificationType
Definition DataHeader.h:622