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