Project
Loading...
Searching...
No Matches
TRKDigitizerSpec.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 "TRKDigitizerSpec.h"
18#include "Framework/Lifetime.h"
19#include "Framework/Task.h"
33
34#include <TChain.h>
35#include <TStopwatch.h>
36
37#include <string>
38
39using namespace o2::framework;
41
42namespace
43{
44std::vector<OutputSpec> makeOutChannels(o2::header::DataOrigin detOrig, bool mctruth)
45{
46 std::vector<OutputSpec> outputs;
47 outputs.emplace_back(detOrig, "DIGITS", 0, Lifetime::Timeframe);
48 outputs.emplace_back(detOrig, "DIGITSROF", 0, Lifetime::Timeframe);
49 if (mctruth) {
50 outputs.emplace_back(detOrig, "DIGITSMC2ROF", 0, Lifetime::Timeframe);
51 outputs.emplace_back(detOrig, "DIGITSMCTR", 0, Lifetime::Timeframe);
52 }
53 outputs.emplace_back(detOrig, "ROMode", 0, Lifetime::Timeframe);
54 return outputs;
55}
56} // namespace
57
58namespace o2::trk
59{
60using namespace o2::base;
62{
63 public:
65
66 TRKDPLDigitizerTask(bool mctruth = true) : BaseDPLDigitizer(InitServices::FIELD | InitServices::GEOM), mWithMCTruth(mctruth) {}
67
69 {
70 mDisableQED = ic.options().get<bool>("disable-qed");
71 }
72
74 {
75 if (mFinished) {
76 return;
77 }
79
80 // read collision context from input
81 auto context = pc.inputs().get<o2::steer::DigitizationContext*>("collisioncontext");
82 context->initSimChains(mID, mSimChains);
83 const bool withQED = context->isQEDProvided() && !mDisableQED;
84 auto& timesview = context->getEventRecords(withQED);
85 LOG(info) << "GOT " << timesview.size() << " COLLISION TIMES";
86 LOG(info) << "SIMCHAINS " << mSimChains.size();
87
88 // if there is nothing to do ... return
89 if (timesview.empty()) {
90 return;
91 }
92 TStopwatch timer;
93 timer.Start();
94 LOG(info) << " CALLING TRK DIGITIZATION ";
95
96 mDigitizer.setDigits(&mDigits);
97 mDigitizer.setROFRecords(&mROFRecords);
98 mDigitizer.setMCLabels(&mLabels);
99
100 // digits are directly put into DPL owned resource
101 auto& digitsAccum = pc.outputs().make<std::vector<itsmft::Digit>>(Output{mOrigin, "DIGITS", 0});
102
103 auto accumulate = [this, &digitsAccum]() {
104 // accumulate result of single event processing, called after processing every event supplied
105 // AND after the final flushing via digitizer::fillOutputContainer
106 if (mDigits.empty()) {
107 LOG(debug) << "No digits to accumulate";
108 return; // no digits were flushed, nothing to accumulate
109 }
110 LOG(debug) << "Accumulating " << mDigits.size() << " digits ";
111 auto ndigAcc = digitsAccum.size();
112 std::copy(mDigits.begin(), mDigits.end(), std::back_inserter(digitsAccum));
113
114 // fix ROFrecords references on ROF entries
115 auto nROFRecsOld = mROFRecordsAccum.size();
116
117 for (int i = 0; i < mROFRecords.size(); i++) {
118 auto& rof = mROFRecords[i];
119 rof.setFirstEntry(ndigAcc + rof.getFirstEntry());
120 rof.print();
121
122 if (mFixMC2ROF < mMC2ROFRecordsAccum.size()) { // fix ROFRecord entry in MC2ROF records
123 for (int m2rid = mFixMC2ROF; m2rid < mMC2ROFRecordsAccum.size(); m2rid++) {
124 // need to register the ROFRecors entry for MC event starting from this entry
125 auto& mc2rof = mMC2ROFRecordsAccum[m2rid];
126 if (rof.getROFrame() == mc2rof.minROF) {
127 mFixMC2ROF++;
128 mc2rof.rofRecordID = nROFRecsOld + i;
129 mc2rof.print();
130 }
131 }
132 }
133 }
134
135 std::copy(mROFRecords.begin(), mROFRecords.end(), std::back_inserter(mROFRecordsAccum));
136 if (mWithMCTruth) {
137 mLabelsAccum.mergeAtBack(mLabels);
138 }
139 LOG(info) << "Added " << mDigits.size() << " digits ";
140 // clean containers from already accumulated stuff
141 mLabels.clear();
142 mDigits.clear();
143 mROFRecords.clear();
144 }; // end accumulate lambda
145
146 auto& eventParts = context->getEventParts(withQED);
147 // loop over all composite collisions given from context (aka loop over all the interaction records)
148 const int bcShift = mDigitizer.getParams().getROFrameBiasInBC();
149 // loop over all composite collisions given from context (aka loop over all the interaction records)
150 for (size_t collID = 0; collID < timesview.size(); ++collID) {
151 auto irt = timesview[collID];
152 if (irt.toLong() < bcShift) { // due to the ROF misalignment the collision would go to negative ROF ID, discard
153 continue;
154 }
155 irt -= bcShift; // account for the ROF start shift
156
157 mDigitizer.setEventTime(irt);
158 mDigitizer.resetEventROFrames(); // to estimate min/max ROF for this collID
159 // for each collision, loop over the constituents event and source IDs
160 // (background signal merging is basically taking place here)
161 for (auto& part : eventParts[collID]) {
162
163 // get the hits for this event and this source
164 mHits.clear();
165 context->retrieveHits(mSimChains, o2::detectors::SimTraits::DETECTORBRANCHNAMES[mID][0].c_str(), part.sourceID, part.entryID, &mHits);
166
167 if (!mHits.empty()) {
168 LOG(debug) << "For collision " << collID << " eventID " << part.entryID
169 << " found " << mHits.size() << " hits ";
170 mDigitizer.process(&mHits, part.entryID, part.sourceID); // call actual digitization procedure
171 }
172 }
173 mMC2ROFRecordsAccum.emplace_back(collID, -1, mDigitizer.getEventROFrameMin(), mDigitizer.getEventROFrameMax());
174 accumulate();
175 }
176 mDigitizer.fillOutputContainer();
177 LOG(debug) << "mDigits size after fill: " << mDigits.size();
178 accumulate();
179
180 // here we have all digits and labels and we can send them to consumer (aka snapshot it onto output)
181
182 pc.outputs().snapshot(Output{mOrigin, "DIGITSROF", 0}, mROFRecordsAccum);
183 if (mWithMCTruth) {
184 pc.outputs().snapshot(Output{mOrigin, "DIGITSMC2ROF", 0}, mMC2ROFRecordsAccum);
185 auto& sharedlabels = pc.outputs().make<o2::dataformats::ConstMCTruthContainer<o2::MCCompLabel>>(Output{mOrigin, "DIGITSMCTR", 0});
186 mLabelsAccum.flatten_to(sharedlabels);
187 // free space of existing label containers
188 mLabels.clear_andfreememory();
189 mLabelsAccum.clear_andfreememory();
190 }
191 LOG(info) << mID.getName() << ": Sending ROMode= " << mROMode << " to GRPUpdater";
192 pc.outputs().snapshot(Output{mOrigin, "ROMode", 0}, mROMode);
193
194 timer.Stop();
195 LOG(info) << "Digitization took " << timer.CpuTime() << "s";
196
197 // we should be only called once; tell DPL that this process is ready to exit
198 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
199
200 mFinished = true;
201 }
202
204 {
205 static bool initOnce{false};
206 if (!initOnce) {
207 initOnce = true;
208 auto& digipar = mDigitizer.getParams();
209
210 // configure digitizer
212 geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)); // make sure L2G matrices are loaded
213 geom->Print();
214 mDigitizer.setGeometry(geom);
215
219 digipar.setContinuous(dopt.continuous);
220 digipar.setROFrameBiasInBC(aopt.roFrameBiasInBC);
221 if (dopt.continuous) {
223 digipar.setROFrameLengthInBC(aopt.roFrameLengthInBC);
224 digipar.setROFrameLength(frameNS); // RO frame in ns
225 digipar.setStrobeDelay(aopt.strobeDelay); // Strobe delay wrt beginning of the RO frame, in ns
226 digipar.setStrobeLength(aopt.strobeLengthCont > 0 ? aopt.strobeLengthCont : frameNS - aopt.strobeDelay); // Strobe length in ns
227 } else {
228 digipar.setROFrameLength(aopt.roFrameLengthTrig); // RO frame in ns
229 digipar.setStrobeDelay(aopt.strobeDelay); // Strobe delay wrt beginning of the RO frame, in ns
230 digipar.setStrobeLength(aopt.strobeLengthTrig); // Strobe length in ns
231 }
232 // parameters of signal time response: flat-top duration, max rise time and q @ which rise time is 0
233 digipar.getSignalShape().setParameters(dopt.strobeFlatTop, dopt.strobeMaxRiseTime, dopt.strobeQRiseTime0);
234 digipar.setChargeThreshold(dopt.chargeThreshold); // charge threshold in electrons
235 digipar.setNoisePerPixel(dopt.noisePerPixel); // noise level
236 digipar.setTimeOffset(dopt.timeOffset);
237 digipar.setNSimSteps(dopt.nSimSteps);
238
240 LOG(info) << mID.getName() << " simulated in "
241 << ((mROMode == o2::parameters::GRPObject::CONTINUOUS) ? "CONTINUOUS" : "TRIGGERED")
242 << " RO mode";
243
244 // if (oTRKParams::Instance().useDeadChannelMap) {
245 // pc.inputs().get<o2::itsmft::NoiseMap*>("TRK_dead"); // trigger final ccdb update
246 // }
247
248 // init digitizer
249 mDigitizer.init();
250 }
251 // Other time-dependent parameters can be added below
252 }
253
254 void finaliseCCDB(ConcreteDataMatcher& matcher, void* obj)
255 {
256 if (matcher == ConcreteDataMatcher(detectors::DetID::ITS, "ALPIDEPARAM", 0)) {
257 LOG(info) << mID.getName() << " Alpide param updated";
259 par.printKeyValues();
260 return;
261 }
262 // if (matcher == ConcreteDataMatcher(mOrigin, "DEADMAP", 0)) {
263 // LOG(info) << mID.getName() << " static dead map updated";
264 // mDigitizer.setDeadChannelsMap((o2::itsmft::NoiseMap*)obj);
265 // return;
266 // }
267 }
268
269 private:
270 bool mWithMCTruth{true};
271 bool mFinished{false};
272 bool mDisableQED{false};
273 const o2::detectors::DetID mID{o2::detectors::DetID::TRK};
275 o2::trk::Digitizer mDigitizer{};
276 std::vector<o2::itsmft::Digit> mDigits{};
277 std::vector<o2::itsmft::ROFRecord> mROFRecords{};
278 std::vector<o2::itsmft::ROFRecord> mROFRecordsAccum{};
279 std::vector<o2::itsmft::Hit> mHits{};
280 std::vector<o2::itsmft::Hit>* mHitsP{&mHits};
283 std::vector<o2::itsmft::MC2ROFRecord> mMC2ROFRecordsAccum{};
284 std::vector<TChain*> mSimChains{};
285
286 int mFixMC2ROF = 0; // 1st entry in mc2rofRecordsAccum to be fixed for ROFRecordID
288};
289
290DataProcessorSpec getTRKDigitizerSpec(int channel, bool mctruth)
291{
292 std::string detStr = o2::detectors::DetID::getName(o2::detectors::DetID::TRK);
293 auto detOrig = o2::header::gDataOriginTRK;
294 std::vector<InputSpec> inputs;
295 inputs.emplace_back("collisioncontext", "SIM", "COLLISIONCONTEXT", static_cast<SubSpecificationType>(channel), Lifetime::Timeframe);
296 inputs.emplace_back("ITS_alppar", "ITS", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("ITS/Config/AlpideParam"));
297 // if (oTRKParams::Instance().useDeadChannelMap) {
298 // inputs.emplace_back("TRK_dead", "TRK", "DEADMAP", 0, Lifetime::Condition, ccdbParamSpec("TRK/Calib/DeadMap"));
299 // }
300
301 return DataProcessorSpec{detStr + "Digitizer",
302 inputs, makeOutChannels(detOrig, mctruth),
303 AlgorithmSpec{adaptFromTask<TRKDPLDigitizerTask>(mctruth)},
304 Options{{"disable-qed", o2::framework::VariantType::Bool, false, {"disable QED handling"}}}};
305}
306
307} // namespace o2::trk
Definition of the base digitizer task class.
A const (ready only) version of MCTruthContainer.
Definition of the ITSMFT digit.
o2::framework::DataAllocator::SubSpecificationType SubSpecificationType
int32_t i
Header of the General Run Parameters object.
Definition of the ITSMFT ROFrame (trigger) record.
Definition of the TRK digitizer.
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 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.
bool initSimChains(o2::detectors::DetID detid, std::vector< TChain * > &simchains) const
int getROFrameBiasInBC() const
Definition DigiParams.h:72
void setEventTime(const o2::InteractionTimeRecord &irt)
void fillOutputContainer(uint32_t maxFrame=0xffffffff)
o2::trk::DigiParams & getParams()
Definition Digitizer.h:49
void process(const std::vector< itsmft::Hit > *hits, int evID, int srcID)
Steer conversion of hits to digits.
uint32_t getEventROFrameMin() const
Definition Digitizer.h:75
void setDigits(std::vector< o2::itsmft::Digit > *dig)
Definition Digitizer.h:45
void setROFRecords(std::vector< o2::itsmft::ROFRecord > *rec)
Definition Digitizer.h:47
void setMCLabels(o2::dataformats::MCTruthContainer< o2::MCCompLabel > *mclb)
Definition Digitizer.h:46
void setGeometry(const o2::trk::GeometryTGeo *gm)
Definition Digitizer.h:73
uint32_t getEventROFrameMax() const
Definition Digitizer.h:76
void resetEventROFrames()
Definition Digitizer.h:77
void Print(Option_t *opt="") const
void fillMatrixCache(int mask)
static GeometryTGeo * Instance()
TRKDPLDigitizerTask(bool mctruth=true)
void run(framework::ProcessingContext &pc)
void updateTimeDependentParams(ProcessingContext &pc)
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj)
void initDigitizerTask(framework::InitContext &ic) override
constexpr o2::header::DataOrigin gDataOriginTRK
Definition DataHeader.h:584
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
DataProcessorSpec getTRKDigitizerSpec(int channel, bool mctruth)
class listing possible services
int roFrameBiasInBC
bias of the start of ROF wrt orbit start: t_irof = (irof*roFrameLengthInBC + roFrameBiasInBC)*BClengt...
float strobeDelay
strobe start (in ns) wrt ROF start
int roFrameLengthInBC
ROF length in BC for continuos mode.
float strobeLengthCont
if < 0, full ROF length - delay
float strobeLengthTrig
length of the strobe in ns (sig. over threshold checked in this window only)
float roFrameLengthTrig
length of RO frame in ns for triggered mode
static constexpr int L2G
Definition Cartesian.h:54
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"