Project
Loading...
Searching...
No Matches
RawToDigitsSpec.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
12#include <string_view>
13#include <unordered_map>
14#include <vector>
15#include <string>
16#include "fmt/format.h"
17
18#include "Framework/Task.h"
21#include "Framework/Logger.h"
24
26#include "Headers/DataHeader.h"
27#include "CCDB/CcdbApi.h"
32
33#include "TPCQC/Clusters.h"
34#include "TPCBase/Mapper.h"
39using namespace o2::framework;
41
42namespace o2
43{
44namespace tpc
45{
46
48{
49 public:
50 TPCDigitDumpDevice(const std::vector<int>& sectors, bool sendCEdigits) : mSectors(sectors), mSendCEdigits(sendCEdigits) {}
51
53 {
54 // parse command line arguments
55 mMaxEvents = static_cast<uint32_t>(ic.options().get<int>("max-events"));
56 mSyncOffsetReference = ic.options().get<uint32_t>("sync-offset-reference");
57 mDecoderType = ic.options().get<uint32_t>("decoder-type");
58 mUseTrigger = !ic.options().get<bool>("ignore-trigger");
59 mUseOldSubspec = ic.options().get<bool>("use-old-subspec");
60 const bool createOccupancyMaps = ic.options().get<bool>("create-occupancy-maps");
61 mForceQuit = ic.options().get<bool>("force-quit");
62 mCheckDuplicates = ic.options().get<bool>("check-for-duplicates");
63 mApplyTailCancellation = ic.options().get<bool>("apply-ion-tail-cancellation");
64 mRemoveDuplicates = ic.options().get<bool>("remove-duplicates");
65 if (mSendCEdigits) {
66 mRemoveCEdigits = true;
67 } else {
68 mRemoveCEdigits = ic.options().get<bool>("remove-ce-digits");
69 }
70
71 if (mUseOldSubspec) {
72 LOGP(info, "Using old subspecification (CruId << 16) | ((LinkId + 1) << (CruEndPoint == 1 ? 8 : 0))");
73 }
74
75 // set up ADC value filling
76 mRawReader.createReader("");
77
78 if (!ic.options().get<bool>("ignore-grp")) {
79 const auto inputGRP = o2::base::NameConf::getGRPFileName();
80 const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP);
81 if (grp) {
82 const auto nhbf = (int)grp->getNHBFPerTF();
83 const int lastTimeBin = nhbf * 891 / 2;
84 mDigitDump.setTimeBinRange(0, lastTimeBin);
85 LOGP(info, "Using GRP NHBF = {} to set last time bin to {}, might be overwritte via --configKeyValues", nhbf, lastTimeBin);
86 }
87 }
88
89 mDigitDump.init();
90 mDigitDump.setInMemoryOnly();
91 const auto pedestalFile = ic.options().get<std::string>("pedestal-url");
92 if (pedestalFile.length()) {
93 if (pedestalFile.find("ccdb") != std::string::npos) {
94 LOGP(info, "Loading pedestals from ccdb: {}", pedestalFile);
96 cdb.setURL(pedestalFile);
97 if (cdb.isHostReachable()) {
98 auto pedestalNoise = cdb.get<std::unordered_map<std::string, CalPad>>("TPC/Calib/PedestalNoise");
99 CalPad* pedestal = nullptr;
100 if (pedestalNoise) {
101 pedestal = &pedestalNoise->at("Pedestals");
102 }
103 if (pedestal) {
104 mDigitDump.setPedestals(pedestal);
105 } else {
106 LOGP(error, "could not load pedestals from {}", pedestalFile);
107 }
108 } else {
109 LOGP(error, "ccdb access to {} requested, but host is not reachable. Cannot load Pedestals", pedestalFile);
110 }
111 } else {
112 LOGP(info, "Setting pedestal file: {}", pedestalFile);
113 mDigitDump.setPedestalAndNoiseFile(pedestalFile);
114 }
115 }
116
117 // set up cluster qc if requested
118 if (createOccupancyMaps) {
119 mClusterQC = std::make_unique<qc::Clusters>();
120 }
121
122 mRawReader.setADCDataCallback([this](const PadROCPos& padROCPos, const CRU& cru, const gsl::span<const uint32_t> data) -> int {
123 const int timeBins = mDigitDump.update(padROCPos, cru, data);
124 mDigitDump.setNumberOfProcessedTimeBins(std::max(mDigitDump.getNumberOfProcessedTimeBins(), size_t(timeBins)));
125 return timeBins;
126 });
127
128 mRawReader.setLinkZSCallback([this](int cru, int rowInSector, int padInRow, int timeBin, float adcValue) -> bool {
129 CRU cruID(cru);
130 const PadRegionInfo& regionInfo = Mapper::instance().getPadRegionInfo(cruID.region());
131 mDigitDump.updateCRU(cruID, rowInSector - regionInfo.getGlobalRowOffset(), padInRow, timeBin, adcValue);
132 if (mClusterQC) {
133 mClusterQC->fillADCValue(cru, rowInSector, padInRow, timeBin, adcValue);
134 }
135 return true;
136 });
137 }
138
140 {
141 // in case the maximum number of events was reached don't do further processing
142 if (mReadyToQuit) {
143 return;
144 }
145
146 auto& reader = mRawReader.getReaders()[0];
147 mActiveSectors = calib_processing_helper::processRawData(pc.inputs(), reader, mUseOldSubspec, std::vector<int>(), nullptr, mSyncOffsetReference, mDecoderType, mUseTrigger);
148
149 mDigitDump.incrementNEvents();
150 if (mClusterQC) {
151 mClusterQC->endTF();
152 }
153 LOGP(info, "Number of processed events: {} ({})", mDigitDump.getNumberOfProcessedEvents(), mMaxEvents);
154
155 snapshotDigits(pc.outputs());
156
157 if (mMaxEvents && (mDigitDump.getNumberOfProcessedEvents() >= mMaxEvents)) {
158 LOGP(info, "Maximm number of events reached ({}), no more processing will be done", mMaxEvents);
159 mReadyToQuit = true;
160 if (mForceQuit) {
161 pc.services().get<ControlService>().endOfStream();
162 pc.services().get<ControlService>().readyToQuit(QuitRequest::All);
163 } else {
164 // pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
165 }
166 }
167 }
168
170 {
171 LOGP(info, "endOfStream");
172 if (mActiveSectors) {
173 snapshotDigits(ec.outputs());
174 }
175 ec.services().get<ControlService>().readyToQuit(QuitRequest::Me);
176
177 if (mClusterQC) {
178 dumpClusterQC();
179 }
180 }
181
182 private:
183 DigitDump mDigitDump;
184 std::unique_ptr<qc::Clusters> mClusterQC;
186 uint32_t mMaxEvents{0};
187 uint32_t mSyncOffsetReference{144};
188 uint32_t mDecoderType{0};
189 bool mReadyToQuit{false};
190 bool mCalibDumped{false};
191 bool mUseOldSubspec{false};
192 bool mForceQuit{false};
193 bool mCheckDuplicates{false};
194 bool mApplyTailCancellation{false};
195 bool mRemoveDuplicates{false};
196 bool mRemoveCEdigits{false};
197 bool mSendCEdigits{false};
198 bool mUseTrigger{false};
199 uint64_t mActiveSectors{0};
200 std::vector<int> mSectors{};
201
202 //____________________________________________________________________________
203 void snapshotDigits(DataAllocator& output)
204 {
205 if (mCheckDuplicates || mRemoveDuplicates) {
206 // iplicityly sorts
207 mDigitDump.checkDuplicates(mRemoveDuplicates);
208 } else {
209 mDigitDump.sortDigits();
210 }
211
212 std::array<std::vector<Digit>, Sector::MAXSECTOR> ceDigits;
213 if (mRemoveCEdigits) {
214 mDigitDump.removeCEdigits(10, 100, &ceDigits);
215 }
216
217 if (mApplyTailCancellation) {
218 auto& digits = mDigitDump.getDigits();
219 IonTailCorrection itCorr;
220 for (auto isector : mSectors) {
221 itCorr.filterDigitsDirect(digits[isector]);
222 }
223 }
224
225 for (auto isector : mSectors) {
226 o2::tpc::TPCSectorHeader header{isector};
227 header.activeSectors = mActiveSectors;
228 // digit for now are transported per sector, not per lane
229 output.snapshot(Output{"TPC", "DIGITS", static_cast<SubSpecificationType>(isector), header},
230 mDigitDump.getDigits(isector));
231 if (mSendCEdigits) {
232 output.snapshot(Output{"TPC", "CEDIGITS", static_cast<SubSpecificationType>(isector), header},
233 ceDigits[isector]);
234 }
235 }
236 mDigitDump.clearDigits();
237 mActiveSectors = 0;
238 }
239
240 //____________________________________________________________________________
241 void dumpClusterQC()
242 {
243 mClusterQC->normalize();
244 mClusterQC->dumpToFile("ClusterQC.root", 2);
245 }
246};
247
248DataProcessorSpec getRawToDigitsSpec(int channel, const std::string inputSpec, bool ignoreDistStf, std::vector<int> const& tpcSectors, bool sendCEdigits)
249{
250 using device = o2::tpc::TPCDigitDumpDevice;
251
252 std::vector<OutputSpec> outputs;
253 for (auto isector : tpcSectors) {
254 outputs.emplace_back("TPC", "DIGITS", static_cast<SubSpecificationType>(isector), Lifetime::Timeframe);
255 if (sendCEdigits) {
256 outputs.emplace_back("TPC", "CEDIGITS", static_cast<SubSpecificationType>(isector), Lifetime::Timeframe);
257 }
258 }
259
260 std::vector<InputSpec> inputs;
261 if (inputSpec != "") {
262 inputs = select(inputSpec.data());
263 } else {
264 inputs.emplace_back(InputSpec{"zsraw", ConcreteDataTypeMatcher{"TPC", "RAWDATA"}, Lifetime::Timeframe});
265 if (!ignoreDistStf) {
266 inputs.emplace_back("stdDist", "FLP", "DISTSUBTIMEFRAME", 0, Lifetime::Timeframe);
267 }
268 }
269
270 return DataProcessorSpec{
271 fmt::format("tpc-raw-to-digits-{}", channel),
272 inputs,
273 outputs,
274 AlgorithmSpec{adaptFromTask<device>(tpcSectors, sendCEdigits)},
275 Options{
276 {"max-events", VariantType::Int, 0, {"maximum number of events to process"}},
277 {"use-old-subspec", VariantType::Bool, false, {"use old subsecifiation definition"}},
278 {"force-quit", VariantType::Bool, false, {"force quit after max-events have been reached"}},
279 {"pedestal-url", VariantType::String, "", {"file with pedestals and noise or ccdb url for zero suppression"}},
280 {"create-occupancy-maps", VariantType::Bool, false, {"create occupancy maps and store them to local root file for debugging"}},
281 {"check-for-duplicates", VariantType::Bool, false, {"check if duplicate digits exist and only report them"}},
282 {"apply-ion-tail-cancellation", VariantType::Bool, false, {"Apply ion tail cancellation"}},
283 {"remove-duplicates", VariantType::Bool, false, {"check if duplicate digits exist and remove them"}},
284 {"remove-ce-digits", VariantType::Bool, false, {"find CE position and remove digits around it"}},
285 {"ignore-grp", VariantType::Bool, false, {"ignore GRP file"}},
286 {"sync-offset-reference", VariantType::UInt32, 144u, {"Reference BCs used for the global sync offset in the CRUs"}},
287 {"decoder-type", VariantType::UInt32, 1u, {"Decoder to use: 0 - TPC, 1 - GPU"}},
288 {"ignore-trigger", VariantType::Bool, false, {"Ignore the trigger information"}},
289 } // end Options
290 }; // end DataProcessorSpec
291}
292} // namespace tpc
293} // namespace o2
Utils and constants for calibration and related workflows.
o2::framework::DataAllocator::SubSpecificationType SubSpecificationType
Header of the General Run Parameters object.
Implementation of the ion tail correction from TPC digits.
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
Definition of the Names Generator class.
static std::string getGRPFileName(const std::string_view prefix=STANDARDSIMPREFIX)
Definition NameConf.cxx:58
static BasicCCDBManager & instance()
o2::header::DataHeader::SubSpecificationType SubSpecificationType
static GRPObject * loadFrom(const std::string &grpFileName="")
unsigned char region() const
Definition CRU.h:64
void setNumberOfProcessedTimeBins(size_t timeBins)
number of processed time bins in last event
Int_t update(const PadROCPos &padROCPos, const CRU &cru, const gsl::span< const uint32_t > data)
void incrementNEvents()
increment number of events
size_t getNumberOfProcessedEvents() const
number of processed events
size_t getNumberOfProcessedTimeBins() const
number of processed time bins in last event
Pedestal calibration class.
Definition DigitDump.h:49
void clearDigits()
clear the digits
Definition DigitDump.h:120
void setTimeBinRange(int first, int last)
set the timeBin range
Definition DigitDump.h:110
void checkDuplicates(bool removeDuplicates=false)
check duplicates and remove the if removeDuplicates is true
void sortDigits()
sort the digits
void removeCEdigits(uint32_t removeNtimeBinsBefore=10, uint32_t removeNtimeBinsAfter=100, std::array< std::vector< Digit >, Sector::MAXSECTOR > *removedDigits=nullptr)
remove digits close to the CE
void setPedestals(const CalPad *pedestal)
Set a custom pedestal object.
Definition DigitDump.h:81
void init()
initialize DigitDump from DigitDumpParam
Definition DigitDump.cxx:37
std::vector< Digit > & getDigits(int sector)
return digits for specific sector
Definition DigitDump.h:136
void setPedestalAndNoiseFile(std::string_view fileName)
pedestal file name
Definition DigitDump.h:58
void setInMemoryOnly(bool mode=true)
set in memory only mode
Definition DigitDump.h:130
Int_t updateCRU(const CRU &cru, const Int_t row, const Int_t pad, const Int_t timeBin, const Float_t signal) final
not used
Definition DigitDump.cxx:56
static Mapper & instance(const std::string mappingDir="")
Definition Mapper.h:44
const PadRegionInfo & getPadRegionInfo(const unsigned char region) const
Definition Mapper.h:385
Pad and row inside a ROC.
Definition PadROCPos.h:37
unsigned char getGlobalRowOffset() const
static constexpr int MAXSECTOR
Definition Sector.h:44
void init(o2::framework::InitContext &ic) final
void endOfStream(o2::framework::EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
TPCDigitDumpDevice(const std::vector< int > &sectors, bool sendCEdigits)
void run(o2::framework::ProcessingContext &pc) final
RawReaderCRU & createReader(const std::string_view inputFileName, uint32_t numTimeBins=0, uint32_t link=0, uint32_t stream=0, uint32_t debugLevel=0, uint32_t verbosity=0, const std::string_view outputFilePrefix="")
create a new raw reader
auto & getReaders()
return vector of readers
void setLinkZSCallback(LinkZSCallback function)
set a callback function for decoded LinkZS data
void setADCDataCallback(ADCDataCallback function)
set a callback function
GLboolean * data
Definition glcorearb.h:298
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > Options
header::DataHeader::SubSpecificationType SubSpecificationType
std::vector< InputSpec > select(char const *matcher="")
uint64_t processRawData(o2::framework::InputRecord &inputs, std::unique_ptr< o2::tpc::rawreader::RawReaderCRU > &reader, bool useOldSubspec=false, const std::vector< int > &sectors={}, size_t *nerrors=nullptr, uint32_t syncOffsetReference=144, uint32_t decoderType=1, bool useTrigger=true, bool returnOnNoTrigger=false)
o2::framework::DataProcessorSpec getRawToDigitsSpec(int channel, const std::string inputSpec, bool ignoreDistStf, std::vector< int > const &tpcSectors, bool sendCEdigits=false)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::vector< Digit > digits