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 if (matcher == ConcreteDataMatcher(mOrigin, "ALPIDERESPVbb0", 0)) {
226 LOG(info) << mID.getName() << " loaded AlpideResponseData for Vbb=0V";
228 }
229 if (matcher == ConcreteDataMatcher(mOrigin, "ALPIDERESPVbbM3", 0)) {
230 LOG(info) << mID.getName() << " loaded AlpideResponseData for Vbb=-3V";
232 }
233 }
234
235 protected:
236 ITSMFTDPLDigitizerTask(bool mctruth = true) : BaseDPLDigitizer(InitServices::FIELD | InitServices::GEOM), mWithMCTruth(mctruth) {}
237
238 template <int DETID>
240 {
241 std::string detstr(o2::detectors::DetID::getName(DETID));
242 pc.inputs().get<o2::itsmft::NoiseMap*>(detstr + "_noise");
243 pc.inputs().get<o2::itsmft::NoiseMap*>(detstr + "_dead");
244 // TODO: the code should run even if this object does not exist. Or: create default object
245 pc.inputs().get<o2::itsmft::TimeDeadMap*>(detstr + "_time_dead");
246 pc.inputs().get<o2::itsmft::DPLAlpideParam<DETID>*>(detstr + "_alppar");
247 pc.inputs().get<o2::itsmft::AlpideSimResponse*>(detstr + "_alpiderespvbb0");
248 pc.inputs().get<o2::itsmft::AlpideSimResponse*>(detstr + "_alpiderespvbbm3");
249
252 auto& digipar = mDigitizer.getParams();
253 digipar.setContinuous(dopt.continuous);
254 digipar.setROFrameBiasInBC(aopt.roFrameBiasInBC);
255 if (dopt.continuous) {
256 auto frameNS = aopt.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingNS;
257 digipar.setROFrameLengthInBC(aopt.roFrameLengthInBC);
258 digipar.setROFrameLength(frameNS); // RO frame in ns
259 digipar.setStrobeDelay(aopt.strobeDelay); // Strobe delay wrt beginning of the RO frame, in ns
260 digipar.setStrobeLength(aopt.strobeLengthCont > 0 ? aopt.strobeLengthCont : frameNS - aopt.strobeDelay); // Strobe length in ns
261 } else {
262 digipar.setROFrameLength(aopt.roFrameLengthTrig); // RO frame in ns
263 digipar.setStrobeDelay(aopt.strobeDelay); // Strobe delay wrt beginning of the RO frame, in ns
264 digipar.setStrobeLength(aopt.strobeLengthTrig); // Strobe length in ns
265 }
266 // parameters of signal time response: flat-top duration, max rise time and q @ which rise time is 0
267 digipar.getSignalShape().setParameters(dopt.strobeFlatTop, dopt.strobeMaxRiseTime, dopt.strobeQRiseTime0);
268 digipar.setChargeThreshold(dopt.chargeThreshold); // charge threshold in electrons
269 digipar.setNoisePerPixel(dopt.noisePerPixel); // noise level
270 digipar.setTimeOffset(dopt.timeOffset);
271 digipar.setNSimSteps(dopt.nSimSteps);
272 digipar.setIBVbb(dopt.IBVbb);
273 digipar.setOBVbb(dopt.OBVbb);
274 digipar.setVbb(dopt.Vbb);
275
277 LOG(info) << mID.getName() << " simulated in "
278 << ((mROMode == o2::parameters::GRPObject::CONTINUOUS) ? "CONTINUOUS" : "TRIGGERED")
279 << " RO mode";
280
281 // configure digitizer
282 o2::itsmft::GeometryTGeo* geom = nullptr;
285 } else {
287 }
288 geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded
291 }
292
293 bool mWithMCTruth = true;
294 bool mFinished = false;
295 bool mDisableQED = false;
296 unsigned long mFirstOrbitTF = 0x0;
300 std::vector<o2::itsmft::Digit> mDigits;
301 std::vector<o2::itsmft::ROFRecord> mROFRecords;
302 std::vector<o2::itsmft::ROFRecord> mROFRecordsAccum;
303 std::vector<o2::itsmft::Hit> mHits;
304 std::vector<o2::itsmft::Hit>* mHitsP = &mHits;
307 std::vector<o2::itsmft::MC2ROFRecord> mMC2ROFRecordsAccum;
308 std::vector<TChain*> mSimChains;
310
311 int mFixMC2ROF = 0; // 1st entry in mc2rofRecordsAccum to be fixed for ROFRecordID
314};
315
316//_______________________________________________
318{
319 public:
320 // FIXME: origin should be extractable from the DetID, the problem is 3d party header dependencies
323 ITSDPLDigitizerTask(bool mctruth = true) : ITSMFTDPLDigitizerTask(mctruth)
324 {
325 mID = DETID;
326 mOrigin = DETOR;
327 }
328};
329
332
333//_______________________________________________
335{
336 public:
337 // FIXME: origina should be extractable from the DetID, the problem is 3d party header dependencies
341 {
342 mID = DETID;
343 mOrigin = DETOR;
344 }
345};
346
349
350std::vector<OutputSpec> makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth)
351{
352 std::vector<OutputSpec> outputs;
353 outputs.emplace_back(detOrig, "DIGITS", 0, Lifetime::Timeframe);
354 outputs.emplace_back(detOrig, "DIGITSROF", 0, Lifetime::Timeframe);
355 if (mctruth) {
356 outputs.emplace_back(detOrig, "DIGITSMC2ROF", 0, Lifetime::Timeframe);
357 outputs.emplace_back(detOrig, "DIGITSMCTR", 0, Lifetime::Timeframe);
358 }
359 outputs.emplace_back(detOrig, "ROMode", 0, Lifetime::Timeframe);
360 return outputs;
361}
362
363DataProcessorSpec getITSDigitizerSpec(int channel, bool mctruth)
364{
366 auto detOrig = ITSDPLDigitizerTask::DETOR;
367 std::stringstream parHelper;
368 parHelper << "Params as " << o2::itsmft::DPLDigitizerParam<ITSDPLDigitizerTask::DETID>::getParamName().data() << ".<param>=value;... with"
370 << "\n or " << o2::itsmft::DPLAlpideParam<ITSDPLDigitizerTask::DETID>::getParamName().data() << ".<param>=value;... with"
372 std::vector<InputSpec> inputs;
373 inputs.emplace_back("collisioncontext", "SIM", "COLLISIONCONTEXT", static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
374 inputs.emplace_back("ITS_noise", "ITS", "NOISEMAP", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/NoiseMap"));
375 inputs.emplace_back("ITS_dead", "ITS", "DEADMAP", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/DeadMap"));
376 inputs.emplace_back("ITS_time_dead", "ITS", "TimeDeadMap", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/TimeDeadMap"));
377 inputs.emplace_back("ITS_alppar", "ITS", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("ITS/Config/AlpideParam"));
378 inputs.emplace_back("ITS_alpiderespvbb0", "ITS", "ALPIDERESPVbb0", 0, Lifetime::Condition, ccdbParamSpec("ITSMFT/Calib/ALPIDEResponseVbb0"));
379 inputs.emplace_back("ITS_alpiderespvbbm3", "ITS", "ALPIDERESPVbbM3", 0, Lifetime::Condition, ccdbParamSpec("ITSMFT/Calib/ALPIDEResponseVbbM3"));
380
381 return DataProcessorSpec{(detStr + "Digitizer").c_str(),
382 inputs, makeOutChannels(detOrig, mctruth),
383 AlgorithmSpec{adaptFromTask<ITSDPLDigitizerTask>(mctruth)},
384 Options{
385 {"disable-qed", o2::framework::VariantType::Bool, false, {"disable QED handling"}}}};
386}
387
388DataProcessorSpec getMFTDigitizerSpec(int channel, bool mctruth)
389{
391 auto detOrig = MFTDPLDigitizerTask::DETOR;
392 std::stringstream parHelper;
393 std::vector<InputSpec> inputs;
394 inputs.emplace_back("collisioncontext", "SIM", "COLLISIONCONTEXT", static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
395 inputs.emplace_back("MFT_noise", "MFT", "NOISEMAP", 0, Lifetime::Condition, ccdbParamSpec("MFT/Calib/NoiseMap"));
396 inputs.emplace_back("MFT_dead", "MFT", "DEADMAP", 0, Lifetime::Condition, ccdbParamSpec("MFT/Calib/DeadMap"));
397 inputs.emplace_back("MFT_time_dead", "MFT", "TimeDeadMap", 0, Lifetime::Condition, ccdbParamSpec("MFT/Calib/TimeDeadMap"));
398 inputs.emplace_back("MFT_alppar", "MFT", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("MFT/Config/AlpideParam"));
399 inputs.emplace_back("MFT_alpiderespvbb0", "MFT", "ALPIDERESPVbb0", 0, Lifetime::Condition, ccdbParamSpec("ITSMFT/Calib/ALPIDEResponseVbb0"));
400 inputs.emplace_back("MFT_alpiderespvbbm3", "MFT", "ALPIDERESPVbbM3", 0, Lifetime::Condition, ccdbParamSpec("ITSMFT/Calib/ALPIDEResponseVbbM3"));
401 parHelper << "Params as " << o2::itsmft::DPLDigitizerParam<ITSDPLDigitizerTask::DETID>::getParamName().data() << ".<param>=value;... with"
403 << " or " << o2::itsmft::DPLAlpideParam<ITSDPLDigitizerTask::DETID>::getParamName().data() << ".<param>=value;... with"
405 return DataProcessorSpec{(detStr + "Digitizer").c_str(),
406 inputs, makeOutChannels(detOrig, mctruth),
407 AlgorithmSpec{adaptFromTask<MFTDPLDigitizerTask>(mctruth)},
408 Options{{"disable-qed", o2::framework::VariantType::Bool, false, {"disable QED handling"}}}};
409}
410
411} // end namespace itsmft
412} // 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
std::ostringstream debug
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.
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:146
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:86
void setMCLabels(o2::dataformats::MCTruthContainer< o2::MCCompLabel > *mclb)
Definition Digitizer.h:57
void setAlpideResponse(const o2::itsmft::AlpideSimResponse *resp, int i)
Definition Digitizer.h:65
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:89
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:88
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(NoiseMap &noisemap) const
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.
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"