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