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