Project
Loading...
Searching...
No Matches
ITSMFTDigitizerSpec.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 "ITSMFTDigitizerSpec.h"
17#include "Framework/Lifetime.h"
18#include "Framework/Task.h"
20#include "Steer/HitProcessingManager.h" // for DigitizationContext
35#include "MFTBase/GeometryTGeo.h"
36#include <TChain.h>
37#include <TStopwatch.h>
38#include <string>
39
40using namespace o2::framework;
42
43namespace o2
44{
45namespace itsmft
46{
47
48using namespace o2::base;
50{
51 public:
54 {
55 mDisableQED = ic.options().get<bool>("disable-qed");
56 }
57
59 {
60 if (mFinished) {
61 return;
62 }
64 mID == o2::detectors::DetID::ITS ? updateTimeDependentParams<o2::detectors::DetID::ITS>(pc) : updateTimeDependentParams<o2::detectors::DetID::MFT>(pc);
65 std::string detStr = mID.getName();
66 // read collision context from input
67 auto context = pc.inputs().get<o2::steer::DigitizationContext*>("collisioncontext");
68 context->initSimChains(mID, mSimChains);
69 const bool withQED = context->isQEDProvided() && !mDisableQED;
70 auto& timesview = context->getEventRecords(withQED);
71 LOG(info) << "GOT " << timesview.size() << " COLLISSION TIMES";
72 LOG(info) << "SIMCHAINS " << mSimChains.size();
73
74 // if there is nothing to do ... return
75 if (timesview.size() == 0) {
76 return;
77 }
78 TStopwatch timer;
79 timer.Start();
80 LOG(info) << " CALLING ITS DIGITIZATION ";
81
85
86 // digits are directly put into DPL owned resource
87 auto& digitsAccum = pc.outputs().make<std::vector<itsmft::Digit>>(Output{mOrigin, "DIGITS", 0});
88
89 auto accumulate = [this, &digitsAccum]() {
90 // accumulate result of single event processing, called after processing every event supplied
91 // AND after the final flushing via digitizer::fillOutputContainer
92 if (!mDigits.size()) {
93 return; // no digits were flushed, nothing to accumulate
94 }
95 auto ndigAcc = digitsAccum.size();
96 std::copy(mDigits.begin(), mDigits.end(), std::back_inserter(digitsAccum));
97
98 // fix ROFrecords references on ROF entries
99 auto nROFRecsOld = mROFRecordsAccum.size();
100
101 for (int i = 0; i < mROFRecords.size(); i++) {
102 auto& rof = mROFRecords[i];
103 rof.setFirstEntry(ndigAcc + rof.getFirstEntry());
104 rof.print();
105
106 if (mFixMC2ROF < mMC2ROFRecordsAccum.size()) { // fix ROFRecord entry in MC2ROF records
107 for (int m2rid = mFixMC2ROF; m2rid < mMC2ROFRecordsAccum.size(); m2rid++) {
108 // need to register the ROFRecors entry for MC event starting from this entry
109 auto& mc2rof = mMC2ROFRecordsAccum[m2rid];
110 if (rof.getROFrame() == mc2rof.minROF) {
111 mFixMC2ROF++;
112 mc2rof.rofRecordID = nROFRecsOld + i;
113 mc2rof.print();
114 }
115 }
116 }
117 }
118
119 std::copy(mROFRecords.begin(), mROFRecords.end(), std::back_inserter(mROFRecordsAccum));
120 if (mWithMCTruth) {
122 }
123 LOG(info) << "Added " << mDigits.size() << " digits ";
124 // clean containers from already accumulated stuff
125 mLabels.clear();
126 mDigits.clear();
127 mROFRecords.clear();
128 }; // and accumulate lambda
129
130 auto& eventParts = context->getEventParts(withQED);
131 int bcShift = mDigitizer.getParams().getROFrameBiasInBC();
132 // loop over all composite collisions given from context (aka loop over all the interaction records)
133 for (int collID = 0; collID < timesview.size(); ++collID) {
134 auto irt = timesview[collID];
135 if (irt.toLong() < bcShift) { // due to the ROF misalignment the collision would go to negative ROF ID, discard
136 continue;
137 }
138 irt -= bcShift; // account for the ROF start shift
139
141 mDigitizer.resetEventROFrames(); // to estimate min/max ROF for this collID
142 // for each collision, loop over the constituents event and source IDs
143 // (background signal merging is basically taking place here)
144 for (auto& part : eventParts[collID]) {
145
146 // get the hits for this event and this source
147 mHits.clear();
148 context->retrieveHits(mSimChains, o2::detectors::SimTraits::DETECTORBRANCHNAMES[mID][0].c_str(), part.sourceID, part.entryID, &mHits);
149
150 if (mHits.size() > 0) {
151 LOG(debug) << "For collision " << collID << " eventID " << part.entryID
152 << " found " << mHits.size() << " hits ";
153 mDigitizer.process(&mHits, part.entryID, part.sourceID); // call actual digitization procedure
154 }
155 }
157 accumulate();
158 }
160 accumulate();
161
162 // here we have all digits and labels and we can send them to consumer (aka snapshot it onto output)
163
164 pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, mROFRecordsAccum);
165 if (mWithMCTruth) {
166 pc.outputs().snapshot(Output{mOrigin, "DIGITSMC2ROF", 0}, mMC2ROFRecordsAccum);
167 auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{mOrigin, "DIGITSMCTR", 0});
168 mLabelsAccum.flatten_to(sharedlabels);
169 // free space of existing label containers
172 }
173 LOG(info) << mID.getName() << ": Sending ROMode= " << mROMode << " to GRPUpdater";
174 pc.outputs().snapshot(Output{mOrigin, "ROMode", 0}, mROMode);
175
176 timer.Stop();
177 LOG(info) << "Digitization took " << timer.CpuTime() << "s";
178
179 // we should be only called once; tell DPL that this process is ready to exit
180 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
181
182 mFinished = true;
183 }
184
185 void finaliseCCDB(ConcreteDataMatcher& matcher, void* obj)
186 {
187 if (matcher == ConcreteDataMatcher(mOrigin, "NOISEMAP", 0)) {
188 LOG(info) << mID.getName() << " noise map updated";
190 return;
191 }
192 if (matcher == ConcreteDataMatcher(mOrigin, "DEADMAP", 0)) {
193 LOG(info) << mID.getName() << " static dead map updated";
196 return;
197 }
198 if (matcher == ConcreteDataMatcher(mOrigin, "TimeDeadMap", 0)) {
200 if (!timedeadmap->isDefault()) {
201 timedeadmap->decodeMap(mFirstOrbitTF, *mDeadMap, true);
203 LOGP(fatal, "Attempt to add time-dependent map to already modified static map");
204 }
205 mTimeDeadMapUpdated = true;
207 LOG(info) << mID.getName() << " time-dependent dead map updated";
208 } else {
209 LOG(info) << mID.getName() << " time-dependent dead map is default/empty";
210 }
211
212 return;
213 }
214 if (matcher == ConcreteDataMatcher(mOrigin, "ALPIDEPARAM", 0)) {
215 LOG(info) << mID.getName() << " Alpide param updated";
218 par.printKeyValues();
219 } else {
221 par.printKeyValues();
222 }
223 return;
224 }
225 }
226
227 protected:
228 ITSMFTDPLDigitizerTask(bool mctruth = true) : BaseDPLDigitizer(InitServices::FIELD | InitServices::GEOM), mWithMCTruth(mctruth) {}
229
230 template <int DETID>
232 {
233 std::string detstr(o2::detectors::DetID::getName(DETID));
234 pc.inputs().get<o2::itsmft::NoiseMap*>(detstr + "_noise");
235 pc.inputs().get<o2::itsmft::NoiseMap*>(detstr + "_dead");
236 // TODO: the code should run even if this object does not exist. Or: create default object
237 pc.inputs().get<o2::itsmft::TimeDeadMap*>(detstr + "_time_dead");
238 pc.inputs().get<o2::itsmft::DPLAlpideParam<DETID>*>(detstr + "_alppar");
239
242 auto& digipar = mDigitizer.getParams();
243 digipar.setContinuous(dopt.continuous);
244 digipar.setROFrameBiasInBC(aopt.roFrameBiasInBC);
245 if (dopt.continuous) {
246 auto frameNS = aopt.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingNS;
247 digipar.setROFrameLengthInBC(aopt.roFrameLengthInBC);
248 digipar.setROFrameLength(frameNS); // RO frame in ns
249 digipar.setStrobeDelay(aopt.strobeDelay); // Strobe delay wrt beginning of the RO frame, in ns
250 digipar.setStrobeLength(aopt.strobeLengthCont > 0 ? aopt.strobeLengthCont : frameNS - aopt.strobeDelay); // Strobe length in ns
251 } else {
252 digipar.setROFrameLength(aopt.roFrameLengthTrig); // RO frame in ns
253 digipar.setStrobeDelay(aopt.strobeDelay); // Strobe delay wrt beginning of the RO frame, in ns
254 digipar.setStrobeLength(aopt.strobeLengthTrig); // Strobe length in ns
255 }
256 // parameters of signal time response: flat-top duration, max rise time and q @ which rise time is 0
257 digipar.getSignalShape().setParameters(dopt.strobeFlatTop, dopt.strobeMaxRiseTime, dopt.strobeQRiseTime0);
258 digipar.setChargeThreshold(dopt.chargeThreshold); // charge threshold in electrons
259 digipar.setNoisePerPixel(dopt.noisePerPixel); // noise level
260 digipar.setTimeOffset(dopt.timeOffset);
261 digipar.setNSimSteps(dopt.nSimSteps);
262 digipar.setIBVbb(dopt.IBVbb);
263 digipar.setOBVbb(dopt.OBVbb);
264 digipar.setVbb(dopt.Vbb);
265
267 LOG(info) << mID.getName() << " simulated in "
268 << ((mROMode == o2::parameters::GRPObject::CONTINUOUS) ? "CONTINUOUS" : "TRIGGERED")
269 << " RO mode";
270
271 // configure digitizer
272 o2::itsmft::GeometryTGeo* geom = nullptr;
275 } else {
277 }
278 geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded
281 }
282
283 bool mWithMCTruth = true;
284 bool mFinished = false;
285 bool mDisableQED = false;
286 unsigned long mFirstOrbitTF = 0x0;
290 std::vector<o2::itsmft::Digit> mDigits;
291 std::vector<o2::itsmft::ROFRecord> mROFRecords;
292 std::vector<o2::itsmft::ROFRecord> mROFRecordsAccum;
293 std::vector<o2::itsmft::Hit> mHits;
294 std::vector<o2::itsmft::Hit>* mHitsP = &mHits;
297 std::vector<o2::itsmft::MC2ROFRecord> mMC2ROFRecordsAccum;
298 std::vector<TChain*> mSimChains;
300
301 int mFixMC2ROF = 0; // 1st entry in mc2rofRecordsAccum to be fixed for ROFRecordID
304};
305
306//_______________________________________________
308{
309 public:
310 // FIXME: origin should be extractable from the DetID, the problem is 3d party header dependencies
313 ITSDPLDigitizerTask(bool mctruth = true) : ITSMFTDPLDigitizerTask(mctruth)
314 {
315 mID = DETID;
316 mOrigin = DETOR;
317 }
318};
319
322
323//_______________________________________________
325{
326 public:
327 // FIXME: origina should be extractable from the DetID, the problem is 3d party header dependencies
331 {
332 mID = DETID;
333 mOrigin = DETOR;
334 }
335};
336
339
340std::vector<OutputSpec> makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth)
341{
342 std::vector<OutputSpec> outputs;
343 outputs.emplace_back(detOrig, "DIGITS", 0, Lifetime::Timeframe);
344 outputs.emplace_back(detOrig, "DIGITSROF", 0, Lifetime::Timeframe);
345 if (mctruth) {
346 outputs.emplace_back(detOrig, "DIGITSMC2ROF", 0, Lifetime::Timeframe);
347 outputs.emplace_back(detOrig, "DIGITSMCTR", 0, Lifetime::Timeframe);
348 }
349 outputs.emplace_back(detOrig, "ROMode", 0, Lifetime::Timeframe);
350 return outputs;
351}
352
353DataProcessorSpec getITSDigitizerSpec(int channel, bool mctruth)
354{
356 auto detOrig = ITSDPLDigitizerTask::DETOR;
357 std::stringstream parHelper;
358 parHelper << "Params as " << o2::itsmft::DPLDigitizerParam<ITSDPLDigitizerTask::DETID>::getParamName().data() << ".<param>=value;... with"
360 << "\n or " << o2::itsmft::DPLAlpideParam<ITSDPLDigitizerTask::DETID>::getParamName().data() << ".<param>=value;... with"
362 std::vector<InputSpec> inputs;
363 inputs.emplace_back("collisioncontext", "SIM", "COLLISIONCONTEXT", static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
364 inputs.emplace_back("ITS_noise", "ITS", "NOISEMAP", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/NoiseMap"));
365 inputs.emplace_back("ITS_dead", "ITS", "DEADMAP", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/DeadMap"));
366 inputs.emplace_back("ITS_time_dead", "ITS", "TimeDeadMap", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/TimeDeadMap"));
367 inputs.emplace_back("ITS_alppar", "ITS", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("ITS/Config/AlpideParam"));
368
369 return DataProcessorSpec{(detStr + "Digitizer").c_str(),
370 inputs, makeOutChannels(detOrig, mctruth),
371 AlgorithmSpec{adaptFromTask<ITSDPLDigitizerTask>(mctruth)},
372 Options{
373 {"disable-qed", o2::framework::VariantType::Bool, false, {"disable QED handling"}}}};
374}
375
376DataProcessorSpec getMFTDigitizerSpec(int channel, bool mctruth)
377{
379 auto detOrig = MFTDPLDigitizerTask::DETOR;
380 std::stringstream parHelper;
381 std::vector<InputSpec> inputs;
382 inputs.emplace_back("collisioncontext", "SIM", "COLLISIONCONTEXT", static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
383 inputs.emplace_back("MFT_noise", "MFT", "NOISEMAP", 0, Lifetime::Condition, ccdbParamSpec("MFT/Calib/NoiseMap"));
384 inputs.emplace_back("MFT_dead", "MFT", "DEADMAP", 0, Lifetime::Condition, ccdbParamSpec("MFT/Calib/DeadMap"));
385 inputs.emplace_back("MFT_time_dead", "MFT", "TimeDeadMap", 0, Lifetime::Condition, ccdbParamSpec("MFT/Calib/TimeDeadMap"));
386 inputs.emplace_back("MFT_alppar", "MFT", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("MFT/Config/AlpideParam"));
387 parHelper << "Params as " << o2::itsmft::DPLDigitizerParam<ITSDPLDigitizerTask::DETID>::getParamName().data() << ".<param>=value;... with"
389 << " or " << o2::itsmft::DPLAlpideParam<ITSDPLDigitizerTask::DETID>::getParamName().data() << ".<param>=value;... with"
391 return DataProcessorSpec{(detStr + "Digitizer").c_str(),
392 inputs, makeOutChannels(detOrig, mctruth),
393 AlgorithmSpec{adaptFromTask<MFTDPLDigitizerTask>(mctruth)},
394 Options{{"disable-qed", o2::framework::VariantType::Bool, false, {"disable QED handling"}}}};
395}
396
397} // end namespace itsmft
398} // end namespace o2
Definition of the base digitizer task class.
A const (ready only) version of MCTruthContainer.
Definition of the ITSMFT digit.
Definition of the Names Generator class.
o2::framework::DataAllocator::SubSpecificationType SubSpecificationType
int32_t i
Header of the General Run Parameters object.
Definition of the GeometryTGeo class.
Definition of the ITSMFT ROFrame (trigger) record.
Definition of the ITS digitizer.
Definition of the ITSMFT NoiseMap.
Definition of the ITSMFT time-dependend dead map.
std::ostringstream debug
virtual void init(o2::framework::InitContext &) final
A read-only version of MCTruthContainer allowing for storage optimisation.
A container to hold and manage MC truth information/labels.
void mergeAtBack(MCTruthContainer< TruthElement > const &other)
size_t flatten_to(ContainerType &container) const
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr const char * getName(ID id)
names of defined detectors
Definition DetID.h:145
static constexpr ID ITS
Definition DetID.h:63
static constexpr ID MFT
Definition DetID.h:71
virtual void fillMatrixCache(int mask)=0
static const std::array< std::vector< std::string >, DetID::nDetectors > DETECTORBRANCHNAMES
Definition SimTraits.h:39
void snapshot(const Output &spec, T const &object)
o2::header::DataHeader::SubSpecificationType SubSpecificationType
decltype(auto) make(const Output &spec, Args... args)
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.
static GeometryTGeo * Instance()
int getROFrameBiasInBC() const
Definition DigiParams.h:71
void setContinuous(bool v)
Definition DigiParams.h:51
void setDeadChannelsMap(const o2::itsmft::NoiseMap *mp)
Definition Digitizer.h:62
void setEventTime(const o2::InteractionTimeRecord &irt)
void setGeometry(const o2::itsmft::GeometryTGeo *gm)
Definition Digitizer.h:85
void setMCLabels(o2::dataformats::MCTruthContainer< o2::MCCompLabel > *mclb)
Definition Digitizer.h:57
void setNoiseMap(const o2::itsmft::NoiseMap *mp)
Definition Digitizer.h:61
void setROFRecords(std::vector< o2::itsmft::ROFRecord > *rec)
Definition Digitizer.h:58
void setDigits(std::vector< o2::itsmft::Digit > *dig)
Definition Digitizer.h:56
uint32_t getEventROFrameMax() const
Definition Digitizer.h:88
o2::itsmft::DigiParams & getParams()
Definition Digitizer.h:59
void process(const std::vector< Hit > *hits, int evID, int srcID)
Steer conversion of hits to digits.
void fillOutputContainer(uint32_t maxFrame=0xffffffff)
uint32_t getEventROFrameMin() const
Definition Digitizer.h:87
static constexpr o2::header::DataOrigin DETOR
static constexpr o2::detectors::DetID::ID DETID
std::vector< o2::itsmft::ROFRecord > mROFRecords
std::vector< o2::itsmft::MC2ROFRecord > mMC2ROFRecordsAccum
o2::dataformats::MCTruthContainer< o2::MCCompLabel > mLabels
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj)
o2::dataformats::MCTruthContainer< o2::MCCompLabel > mLabelsAccum
std::vector< o2::itsmft::ROFRecord > mROFRecordsAccum
void initDigitizerTask(framework::InitContext &ic) override
std::vector< o2::itsmft::Hit > mHits
void run(framework::ProcessingContext &pc)
std::vector< o2::itsmft::Digit > mDigits
void updateTimeDependentParams(ProcessingContext &pc)
o2::parameters::GRPObject::ROMode mROMode
std::vector< o2::itsmft::Hit > * mHitsP
static constexpr o2::detectors::DetID::ID DETID
static constexpr o2::header::DataOrigin DETOR
NoiseMap class for the ITS and MFT.
Definition NoiseMap.h:39
void decodeMap(o2::itsmft::NoiseMap &noisemap)
Definition TimeDeadMap.h:59
static GeometryTGeo * Instance()
bool initSimChains(o2::detectors::DetID detid, std::vector< TChain * > &simchains) const
constexpr o2::header::DataOrigin gDataOriginMFT
Definition DataHeader.h:572
constexpr o2::header::DataOrigin gDataOriginInvalid
Definition DataHeader.h:561
constexpr o2::header::DataOrigin gDataOriginITS
Definition DataHeader.h:570
constexpr double LHCBunchSpacingNS
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
std::vector< OutputSpec > makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth)
DataProcessorSpec getMFTDigitizerSpec(int channel, bool mctruth)
DataProcessorSpec getITSDigitizerSpec(int channel, bool mctruth)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
class listing possible services
static constexpr std::string_view getParamName()
static constexpr std::string_view getParamName()
static constexpr int L2G
Definition Cartesian.h:54
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"