Project
Loading...
Searching...
No Matches
MCHDigitizerSpec.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 "MCHDigitizerSpec.h"
13
23#include "Framework/Lifetime.h"
24#include "Framework/Task.h"
29#include "MCHSimulation/Hit.h"
31#include "TChain.h"
34#include <TGeoManager.h>
35#include <algorithm>
36#include <map>
37
38using namespace o2::framework;
40
41namespace o2
42{
43namespace mch
44{
45
47{
48 public:
49 MCHDPLDigitizerTask() : o2::base::BaseDPLDigitizer(o2::base::InitServices::FIELD | o2::base::InitServices::GEOM) {}
50
52 {
54 mDigitizer = std::make_unique<Digitizer>(transformation);
55 }
56
57 void logStatus(gsl::span<Digit> digits, gsl::span<ROFRecord> rofs, o2::dataformats::MCLabelContainer& labels,
58 size_t nPileup, std::chrono::high_resolution_clock::time_point start)
59 {
60 LOGP(info, "Number of digits : {}", digits.size());
61 LOGP(info, "Number of rofs : {}", rofs.size());
62 LOGP(info, "Number of labels : {} (indexed {})", labels.getNElements(), labels.getIndexedSize());
63 if (labels.getIndexedSize() != digits.size()) {
64 LOGP(error, "Number of labels != number of digits");
65 }
66 LOGP(info, "Number of signal pileup : {} ({} %)", nPileup, 100. * nPileup / digits.size());
67 auto tEnd = std::chrono::high_resolution_clock::now();
68 auto duration = tEnd - start;
69 auto d = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
70 LOGP(info, "Digitizer time {} ms", d);
71 }
72
74 {
75 static bool finished = false;
76 if (finished) {
77 return;
78 }
79
80 mDigitizer->setFirstTFOrbit(pc.services().get<o2::framework::TimingInfo>().firstTForbit);
81
82 auto tStart = std::chrono::high_resolution_clock::now();
83 auto context = pc.inputs().get<o2::steer::DigitizationContext*>("collisioncontext");
84 context->initSimChains(o2::detectors::DetID::MCH, mSimChains);
85 const auto& eventRecords = context->getEventRecords();
86 auto timeOffset = DigitFilterParam::Instance().timeOffset;
87
88 // generate signals produced by every hits
89 if (!DigitizerParam::Instance().onlyNoise) {
90 const auto& eventParts = context->getEventParts();
91 for (auto i = 0; i < eventRecords.size(); i++) {
92 auto ir = eventRecords[i];
93 // apply time offset, discarding events going to negative IR
94 if (ir.toLong() < timeOffset) {
95 continue;
96 }
97 ir -= timeOffset;
98 for (const auto& part : eventParts[i]) {
99 std::vector<Hit> hits{};
100 context->retrieveHits(mSimChains, "MCHHit", part.sourceID, part.entryID, &hits);
101 mDigitizer->processHits(hits, ir, part.entryID, part.sourceID);
102 }
103 }
104 }
105
106 // generate noise-only signals between first and last collisions ± 100 BC (= 25 ADC samples).
107 // A timeframe can hold no collision at all when the interaction rate is low; take the range
108 // from the timeframe itself in that case, since there are no collisions to take it from.
109 int64_t firstLong, lastLong;
110 if (eventRecords.empty()) {
111 const auto& hbf = o2::raw::HBFUtils::Instance();
112 firstLong = InteractionRecord(0, hbf.orbitFirstSampled).toLong();
113 lastLong = InteractionRecord(0, hbf.orbitFirstSampled + hbf.nHBFPerTF).toLong();
114 } else {
115 firstLong = eventRecords.front().toLong();
116 lastLong = eventRecords.back().toLong();
117 }
118 auto firstIR = InteractionRecord::long2IR(std::max(int64_t(0), firstLong - timeOffset - 100));
119 auto lastIR = InteractionRecord::long2IR(std::max(int64_t(0), lastLong - timeOffset + 100));
120 mDigitizer->addNoise(firstIR, lastIR);
121
122 // digitize
123 std::vector<Digit> digits{};
124 std::vector<ROFRecord> rofs{};
126 auto nPileup = mDigitizer->digitize(rofs, digits, labels);
127
128 pc.outputs().snapshot(Output{"MCH", "DIGITS", 0}, digits);
129 pc.outputs().snapshot(Output{"MCH", "DIGITROFS", 0}, rofs);
130 if (pc.outputs().isAllowed({"MCH", "DIGITSLABELS", 0})) {
131 pc.outputs().snapshot(Output{"MCH", "DIGITSLABELS", 0}, labels);
132 }
133 pc.outputs().snapshot(Output{"MCH", "ROMode", 0},
135
136 // we should be only called once; tell DPL that this process is ready to exit
137 pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
138 finished = true;
139
140 logStatus(digits, rofs, labels, nPileup, tStart);
141 }
142
143 private:
144 std::unique_ptr<Digitizer> mDigitizer{};
145 std::vector<TChain*> mSimChains{};
146};
147
149{
150 std::vector<OutputSpec> outputs{};
151 outputs.emplace_back("MCH", "DIGITS", 0, Lifetime::Timeframe);
152 outputs.emplace_back("MCH", "DIGITROFS", 0, Lifetime::Timeframe);
153 if (mctruth) {
154 outputs.emplace_back("MCH", "DIGITSLABELS", 0, Lifetime::Timeframe);
155 }
156 outputs.emplace_back("MCH", "ROMode", 0, Lifetime::Timeframe);
157
158 return DataProcessorSpec{
159 "MCHDigitizer",
160 Inputs{InputSpec{"collisioncontext", "SIM", "COLLISIONCONTEXT", static_cast<SubSpecificationType>(channel), Lifetime::Timeframe}},
161 outputs,
162 AlgorithmSpec{adaptFromTask<MCHDPLDigitizerTask>()},
163 Options{}};
164}
165
166} // end namespace mch
167} // end namespace o2
std::vector< std::string > labels
Definition of the base digitizer task class.
o2::framework::DataAllocator::SubSpecificationType SubSpecificationType
int32_t i
Header of the General Run Parameters object.
Definition of a container to keep Monte Carlo truth external to simulation objects.
Definition of the MCH ROFrame record.
static constexpr ID MCH
Definition DetID.h:72
void snapshot(const Output &spec, T const &object)
o2::header::DataHeader::SubSpecificationType SubSpecificationType
bool isAllowed(Output const &query)
check if a certain output is allowed
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 run(framework::ProcessingContext &pc)
void initDigitizerTask(framework::InitContext &ic) override
void logStatus(gsl::span< Digit > digits, gsl::span< ROFRecord > rofs, o2::dataformats::MCLabelContainer &labels, size_t nPileup, std::chrono::high_resolution_clock::time_point start)
bool initSimChains(o2::detectors::DetID detid, std::vector< TChain * > &simchains) const
GLuint start
Definition glcorearb.h:469
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< ConfigParamSpec > Options
header::DataHeader::SubSpecificationType SubSpecificationType
std::vector< InputSpec > Inputs
TransformationCreator transformationFromTGeoManager(const TGeoManager &geo)
o2::framework::DataProcessorSpec getMCHDigitizerSpec(int channel, bool mctruth)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
static InteractionRecord long2IR(int64_t l)
auto transformation
o2::InteractionRecord ir(0, 0)
std::vector< Digit > digits