Project
Loading...
Searching...
No Matches
TOFDigitizerSpec.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 "TOFDigitizerSpec.h"
17#include "Framework/Lifetime.h"
18#include "Framework/Task.h"
19#include "TStopwatch.h"
20#include "Steer/HitProcessingManager.h" // for DigitizationContext
21#include "TChain.h"
29#include "TOFBase/CalibTOFapi.h"
33#include "TOFBase/Geo.h"
37
38using namespace o2::framework;
39using namespace o2::dataformats;
40
42
43namespace o2
44{
45namespace tof
46{
47
49{
50 public:
51 TOFDPLDigitizerTask(bool useCCDB, std::string ccdb_url, int timestamp) : mUseCCDB{useCCDB}, mCCDBurl(ccdb_url), mTimestamp(timestamp), o2::base::BaseDPLDigitizer(o2::base::InitServices::FIELD | o2::base::InitServices::GEOM), mPass(o2::conf::DigiParams::Instance().passName){};
52
54 {
55 LOG(info) << "Initializing TOF digitization";
56
57 mSimChains = std::move(std::make_unique<std::vector<TChain*>>());
58
59 // the instance of the actual digitizer
60 mDigitizer = std::move(std::make_unique<o2::tof::Digitizer>());
61 // containers for digits and labels
62 mDigits = std::move(std::make_unique<std::vector<o2::tof::Digit>>());
63 mLabels = std::move(std::make_unique<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>());
64
65 // init digitizer
66 mDigitizer->init();
67 const bool isContinuous = ic.options().get<int>("pileup");
68 LOG(info) << "CONTINUOUS " << isContinuous;
69 mDigitizer->setContinuous(isContinuous);
70 mDigitizer->setMCTruthContainer(mLabels.get());
71 LOG(info) << "TOF initialization done";
72 }
73
75 {
76 if (matcher == ConcreteDataMatcher("TOF", "DiagnosticCal", 0)) {
77 mUpdateCCDB = true;
78 return;
79 }
80 if (matcher == ConcreteDataMatcher("TOF", "LHCphaseCal", 0)) {
81 mUpdateCCDB = true;
82 return;
83 }
84 if (matcher == ConcreteDataMatcher("TOF", "ChannelCalibCal", 0)) {
85 mUpdateCCDB = true;
86 return;
87 }
88 if (matcher == ConcreteDataMatcher("TOF", "StatusTOF", 0)) {
89 mUpdateCCDB = true;
90 return;
91 }
92 if (matcher == ConcreteDataMatcher("TOF", "parameters", 0)) {
93 mUpdateCCDB = true;
94 return;
95 }
96 }
97
99 {
100 static bool finished = false;
101 if (finished) {
102 return;
103 }
104 // RS: at the moment using hardcoded flag for continuos readout
106
107 // read collision context from input
108 auto context = pc.inputs().get<o2::steer::DigitizationContext*>("collisioncontext");
109 auto& timesview = context->getEventRecords();
110 LOG(debug) << "GOT " << timesview.size() << " COLLISSION TIMES";
111
112 context->initSimChains(o2::detectors::DetID::TOF, *mSimChains.get());
113
114 // if there is nothing to do ... return
115 if (timesview.size() == 0) {
116 return;
117 }
118
119 TStopwatch timer;
120 timer.Start();
121
122 LOG(info) << " CALLING TOF DIGITIZATION ";
125
126 if (mUseCCDB) {
127 const auto lhcPhaseIn = pc.inputs().get<o2::dataformats::CalibLHCphaseTOF*>("tofccdbLHCphase");
128 const auto channelCalibIn = pc.inputs().get<o2::dataformats::CalibTimeSlewingParamTOF*>("tofccdbChannelCalib");
129 const auto diagnosticIn = pc.inputs().get<o2::tof::Diagnostic*>("tofccdbDia");
130 const auto statusIn = pc.inputs().get<o2::tof::TOFFEElightInfo*>("tofccdbStatus");
131 const auto tofParams = pc.inputs().get<o2::tof::ParameterCollection*>("tofccdbParams");
132
133 if (tofParams->getSize(mPass) < 0) { // this is supposed to be temporary till all the pieces are in place
134 LOG(info) << "Pass " << mPass << " requested but not found in the tofParams object -> using unanchored";
135 mPass = "unanchored";
136 }
137
138 if (tofParams->getSize(mPass) < 0) {
139 LOG(fatal) << "Pass " << mPass << " not found in the tofParams object (stop here!)";
140 } else {
141 const auto& params = tofParams->getPars(mPass);
142 if (params.count("time_resolution")) {
143 mDigitizer->setResolution(params.at("time_resolution"));
144 LOG(info) << "time_resolution load from ccdb -> " << params.at("time_resolution");
145 }
146 if (params.count("eff_center")) {
147 mDigitizer->setEffCenter(params.at("eff_center"));
148 LOG(info) << "eff_center load from ccdb -> " << params.at("eff_center");
149 }
150 if (params.count("eff_boundary1")) {
151 mDigitizer->setEffBoundary1(params.at("eff_boundary1"));
152 LOG(info) << "eff_boundary1 load from ccdb -> " << params.at("eff_boundary1");
153 }
154 if (params.count("eff_boundary2")) {
155 mDigitizer->setEffBoundary2(params.at("eff_boundary2"));
156 LOG(info) << "eff_boundary2 load from ccdb -> " << params.at("eff_boundary2");
157 }
158 if (params.count("eff_boundary3")) {
159 mDigitizer->setEffBoundary3(params.at("eff_boundary3"));
160 LOG(info) << "eff_boundary3 load from ccdb -> " << params.at("eff_boundary3");
161 }
162 }
163
164 if (!mCalibApi) {
165 o2::dataformats::CalibLHCphaseTOF* lhcPhase = new o2::dataformats::CalibLHCphaseTOF(std::move(*lhcPhaseIn));
166 o2::dataformats::CalibTimeSlewingParamTOF* channelCalib = new o2::dataformats::CalibTimeSlewingParamTOF(std::move(*channelCalibIn));
167 o2::tof::Diagnostic* diagnostic = new o2::tof::Diagnostic(std::move(*diagnosticIn));
168 o2::tof::TOFFEElightInfo* status = new o2::tof::TOFFEElightInfo(std::move(*statusIn));
169
170 mCalibApi = new o2::tof::CalibTOFapi(long(0), lhcPhase, channelCalib, diagnostic);
171 mCalibApi->loadDiagnosticFrequencies();
172 mCalibApi->loadActiveMap(status);
173 mUpdateCCDB = false;
174 } else { // update if necessary
175 if (mUpdateCCDB) {
176 LOG(info) << "Update CCDB objects since new";
177 delete mCalibApi;
180 o2::tof::Diagnostic* diagnostic = new o2::tof::Diagnostic(std::move(*diagnosticIn));
181 o2::tof::TOFFEElightInfo* status = new o2::tof::TOFFEElightInfo(std::move(*statusIn));
182 mCalibApi = new o2::tof::CalibTOFapi(long(0), lhcPhase, channelCalib, diagnostic);
183 mCalibApi->loadDiagnosticFrequencies();
184 mCalibApi->loadActiveMap(status);
185 mUpdateCCDB = false;
186 } else {
187 // do nothing
188 }
189 }
190 } else if (!mCalibApi) { // calibration objects set to zero
191 auto* lhcPhaseDummy = new o2::dataformats::CalibLHCphaseTOF();
192 auto* channelCalibDummy = new o2::dataformats::CalibTimeSlewingParamTOF();
193
194 lhcPhaseDummy->addLHCphase(0, 0);
195 lhcPhaseDummy->addLHCphase(2000000000, 0);
196
197 for (int ich = 0; ich < o2::dataformats::CalibTimeSlewingParamTOF::NCHANNELS; ich++) {
198 channelCalibDummy->addTimeSlewingInfo(ich, 0, 0);
201 channelCalibDummy->setFractionUnderPeak(sector, channelInSector, 1);
202 }
203 mCalibApi = new o2::tof::CalibTOFapi(long(mTimestamp), lhcPhaseDummy, channelCalibDummy);
204
205 if (mUseCCDB) {
206 mCalibApi->setURL(mCCDBurl);
207 mCalibApi->readDiagnosticFrequencies();
208 mCalibApi->readLHCphase();
209 mCalibApi->readActiveMap();
210 mCalibApi->readTimeSlewingParam();
211 }
212 }
213
214 mDigitizer->setCalibApi(mCalibApi);
215
216 mCalibApi->setTimeStamp(o2::raw::HBFUtils::Instance().startTime / 1000);
217
218 static std::vector<o2::tof::HitType> hits;
219
220 auto& eventParts = context->getEventParts();
221 // loop over all composite collisions given from context
222 // (aka loop over all the interaction records)
223 // o2::InteractionTimeRecord firstorbit(o2::InteractionRecord(0, o2::raw::HBFUtils::Instance().orbitFirstSampled), 0.0);
224 for (int collID = 0; collID < timesview.size(); ++collID) {
225 o2::InteractionTimeRecord orbit(timesview[collID]);
226 // orbit += firstorbit;
227 mDigitizer->setEventTime(orbit);
228
229 // for each collision, loop over the constituents event and source IDs
230 // (background signal merging is basically taking place here)
231 for (auto& part : eventParts[collID]) {
232 mDigitizer->setEventID(part.entryID);
233 mDigitizer->setSrcID(part.sourceID);
234
235 // get the hits for this event and this source
236 hits.clear();
237 context->retrieveHits(*mSimChains.get(), "TOFHit", part.sourceID, part.entryID, &hits);
238
239 // LOG(info) << "For collision " << collID << " eventID " << part.entryID << " found " << hits.size() << " hits ";
240
241 // call actual digitization procedure
242 mLabels->clear();
243 mDigits->clear();
244 mDigitizer->process(&hits, mDigits.get());
245 }
246 }
247 if (mDigitizer->isContinuous()) {
248 LOG(info) << "clear all";
249 mDigits->clear();
250 mLabels->clear();
251 LOG(info) << "finalize";
252 mDigitizer->flushOutputContainer(*mDigits.get());
253 }
254
255 std::vector<Digit>* digitsVector = mDigitizer->getDigitPerTimeFrame();
256 std::vector<ReadoutWindowData>* readoutwindow = mDigitizer->getReadoutWindowData();
257 std::vector<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>* mcLabVecOfVec = mDigitizer->getMCTruthPerTimeFrame();
258
259 LOG(info) << "Post " << digitsVector->size() << " digits in " << readoutwindow->size() << " RO windows";
260
261 // here we have all digits and we can send them to consumer (aka snapshot it onto output)
262 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITS", 0}, *digitsVector);
263 if (pc.outputs().isAllowed({o2::header::gDataOriginTOF, "DIGITSMCTR", 0})) {
264 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITSMCTR", 0}, *mcLabVecOfVec);
265 }
266 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "READOUTWINDOW", 0}, *readoutwindow);
267
268 // send empty pattern from digitizer (it may change in future)
269 std::vector<uint8_t>& patterns = mDigitizer->getPatterns();
270 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "PATTERNS", 0}, patterns);
271
272 DigitHeader& digitH = mDigitizer->getDigitHeader();
273 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "DIGITHEADER", 0}, digitH);
274
275 LOG(info) << "TOF: Sending ROMode= " << roMode << " to GRPUpdater";
276 pc.outputs().snapshot(Output{o2::header::gDataOriginTOF, "ROMode", 0}, roMode);
277
278 timer.Stop();
279 LOG(info) << "Digitization took " << timer.CpuTime() << "s";
280
281 // we should be only called once; tell DPL that this process is ready to exit
283
284 finished = true;
285 }
286
288 {
289 LOGF(debug, "TOF Digitizer endOfStream");
290 }
291
292 private:
293 std::unique_ptr<std::vector<TChain*>> mSimChains;
294 std::unique_ptr<o2::tof::Digitizer> mDigitizer;
295 std::unique_ptr<std::vector<o2::tof::Digit>> mDigits;
296 std::unique_ptr<o2::dataformats::MCTruthContainer<o2::MCCompLabel>> mLabels;
297 bool mUseCCDB = false;
298 std::string mCCDBurl;
299 int mTimestamp = 0;
300 bool mUpdateCCDB = false;
301 o2::tof::CalibTOFapi* mCalibApi = nullptr;
302 std::string mPass;
303};
304
305DataProcessorSpec getTOFDigitizerSpec(int channel, bool useCCDB, bool mctruth, std::string ccdb_url, int timestamp)
306{
307 // create the full data processor spec using
308 // a name identifier
309 // input description
310 // algorithmic description (here a lambda getting called once to setup the actual processing function)
311 // options that can be used for this processor (here: input file names where to take the hits)
312 std::vector<InputSpec> inputs;
313 inputs.emplace_back("collisioncontext", "SIM", "COLLISIONCONTEXT", static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
314 // if (useCCDB) {
315 // inputs.emplace_back("tofccdbLHCphase", o2::header::gDataOriginTOF, "LHCphase");
316 // inputs.emplace_back("tofccdbChannelCalib", o2::header::gDataOriginTOF, "ChannelCalib");
317 // }
318
319 if (useCCDB) {
320 inputs.emplace_back("tofccdbStatus", "TOF", "StatusTOF", 0, Lifetime::Condition, ccdbParamSpec("TOF/Calib/FEELIGHT"));
321 inputs.emplace_back("tofccdbDia", "TOF", "DiagnosticCal", 0, Lifetime::Condition, ccdbParamSpec("TOF/Calib/Diagnostic"));
322 inputs.emplace_back("tofccdbLHCphase", "TOF", "LHCphaseCal", 0, Lifetime::Condition, ccdbParamSpec("TOF/Calib/LHCphase"));
323 inputs.emplace_back("tofccdbChannelCalib", "TOF", "ChannelCalibCal", 0, Lifetime::Condition, ccdbParamSpec("TOF/Calib/ChannelCalib"));
324 inputs.emplace_back("tofccdbParams", "TOF", "parameters", 0, Lifetime::Condition, ccdbParamSpec("TOF/Calib/Params"));
325 }
326
327 std::vector<OutputSpec> outputs;
328 outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITHEADER", 0, Lifetime::Timeframe);
329 outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITS", 0, Lifetime::Timeframe);
330 outputs.emplace_back(o2::header::gDataOriginTOF, "READOUTWINDOW", 0, Lifetime::Timeframe);
331 outputs.emplace_back(o2::header::gDataOriginTOF, "PATTERNS", 0, Lifetime::Timeframe);
332 if (mctruth) {
333 outputs.emplace_back(o2::header::gDataOriginTOF, "DIGITSMCTR", 0, Lifetime::Timeframe);
334 }
335 outputs.emplace_back(o2::header::gDataOriginTOF, "ROMode", 0, Lifetime::Timeframe);
336 return DataProcessorSpec{
337 "TOFDigitizer",
338 inputs,
339 outputs,
340 AlgorithmSpec{adaptFromTask<TOFDPLDigitizerTask>(useCCDB, ccdb_url, timestamp)},
341 Options{{"pileup", VariantType::Int, 1, {"whether to run in continuous time mode"}}}
342 // I can't use VariantType::Bool as it seems to have a problem
343 };
344}
345} // end namespace tof
346} // end namespace o2
Definition of the base digitizer task class.
Class to store the output of the matching to TOF for calibration.
Class to use TOF calibration (decalibration, calibration)
Class to store the output of the matching to TOF for calibration.
Definition of the GeometryManager class.
o2::framework::DataAllocator::SubSpecificationType SubSpecificationType
uint64_t orbit
Definition RawEventData.h:6
Header of the General Run Parameters object.
Definition of a container to keep Monte Carlo truth external to simulation objects.
Definitions of the containers for the general parameters.
std::ostringstream debug
A container to hold and manage MC truth information/labels.
static constexpr ID TOF
Definition DetID.h:66
void snapshot(const Output &spec, T const &object)
o2::header::DataHeader::SubSpecificationType SubSpecificationType
bool isAllowed(Output const &query)
check if a certain output is allowed
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.
ServiceRegistryRef services()
The services registry associated with this processing context.
bool initSimChains(o2::detectors::DetID detid, std::vector< TChain * > &simchains) const
std::vector< o2::InteractionTimeRecord > & getEventRecords(bool withQED=false)
void setTimeStamp(long t)
Definition CalibTOFapi.h:58
void loadActiveMap(TOFFEElightInfo *fee)
void setURL(const std::string url)
Definition CalibTOFapi.h:62
Diagnostic class for TOF.
Definition Diagnostic.h:32
Class container to hold different parameters meant to be stored on the CCDB.
void initDigitizerTask(framework::InitContext &ic) override
void endOfStream(EndOfStreamContext &ec)
TOFDPLDigitizerTask(bool useCCDB, std::string ccdb_url, int timestamp)
void finaliseCCDB(o2::framework::ConcreteDataMatcher matcher, void *obj)
void run(framework::ProcessingContext &pc)
GLenum const GLfloat * params
Definition glcorearb.h:272
constexpr o2::header::DataOrigin gDataOriginTOF
Definition DataHeader.h:575
Definition of a container to keep/associate and arbitrary number of labels associated to an index wit...
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
std::vector< ConfigParamSpec > Options
header::DataHeader::SubSpecificationType SubSpecificationType
DataProcessorSpec getTOFDigitizerSpec(int channel, bool useCCDB, bool mctruth, std::string ccdb_url, int timestamp)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"