Project
Loading...
Searching...
No Matches
TPCResidualAggregatorSpec.h
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#ifndef O2_TPC_RESIDUALAGGREGATORSPEC_H
13#define O2_TPC_RESIDUALAGGREGATORSPEC_H
14
18
24#include "Framework/Task.h"
30#include <fairmq/Device.h>
31#include <chrono>
32
33using namespace o2::framework;
35
36namespace o2
37{
38namespace calibration
39{
40
42{
43 public:
44 ResidualAggregatorDevice(std::shared_ptr<o2::base::GRPGeomRequest> req, bool trackInput, bool ctpInput, bool writeUnbinnedResiduals, bool writeBinnedResiduals, bool writeTrackData, bool mcInput, std::shared_ptr<o2::globaltracking::DataRequest> dataRequest) : mCCDBRequest(req), mTrackInput(trackInput), mCTPInput(ctpInput), mWriteUnbinnedResiduals(writeUnbinnedResiduals), mWriteBinnedResiduals(writeBinnedResiduals), mWriteTrackData(writeTrackData), mMCInput(mcInput), mDataRequest(dataRequest) {}
45
47 {
49 int minEnt = ic.options().get<int>("min-entries");
50 auto slotLength = ic.options().get<uint32_t>("sec-per-slot");
51 bool useInfiniteSlotLength = false;
52 if (slotLength == 0) {
53 useInfiniteSlotLength = true;
54 }
55 auto updateInterval = ic.options().get<uint32_t>("updateInterval");
56 auto delay = ic.options().get<uint32_t>("max-delay");
57
58 // should we write meta files for epn2eos?
59 bool storeMetaFile = false;
60 std::string metaFileDir = ic.options().get<std::string>("meta-output-dir");
61 if (metaFileDir != "/dev/null") {
62 metaFileDir = o2::utils::Str::rectifyDirectory(metaFileDir);
63 storeMetaFile = true;
64 }
65
66 // where should the ROOT output be written? in case its set to /dev/null
67 // we don't write anything, also no meta files of course
68 bool writeOutput = true;
69 std::string outputDir = ic.options().get<std::string>("output-dir");
70 if (outputDir != "/dev/null") {
71 outputDir = o2::utils::Str::rectifyDirectory(outputDir);
72 } else {
73 writeOutput = false;
74 storeMetaFile = false;
75 }
76
77 LOGP(info, "Creating aggregator with {} entries per voxel minimum. Output file writing enabled: {}, meta file writing enabled: {}",
78 minEnt, writeOutput, storeMetaFile);
79 mAggregator = std::make_unique<o2::tpc::ResidualAggregator>(minEnt);
80 if (writeOutput) {
81 mAggregator->setOutputDir(outputDir);
82 }
83 if (storeMetaFile) {
84 mAggregator->setMetaFileOutputDir(metaFileDir);
85 }
86
87 int autosave = ic.options().get<int>("autosave-interval");
88 mAggregator->setAutosaveInterval(autosave);
89 // TODO mAggregator should get an option to set the binning externally (expose TrackResiduals::setBinning methods to user? as command line option?)
90 mAggregator->setMaxSlotsDelay(delay);
91 if (useInfiniteSlotLength) {
92 mAggregator->setSlotLength(o2::calibration::INFINITE_TF);
93 mAggregator->setCheckIntervalInfiniteSlot(updateInterval);
94 } else {
95 mAggregator->setSlotLengthInSeconds(slotLength);
96 }
97 mAggregator->setWriteBinnedResiduals(mWriteBinnedResiduals);
98 mAggregator->setWriteUnbinnedResiduals(mWriteUnbinnedResiduals);
99 mAggregator->setWriteTrackData(mWriteTrackData);
100 mAggregator->setWriteTrackDataMC(mMCInput);
101 mAggregator->setCompression(ic.options().get<int>("compression"));
102 }
103
104 void finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj) final
105 {
107 return;
108 }
109 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
110 return;
111 }
112 }
113
115 {
116 const auto& tinfo = pc.services().get<o2::framework::TimingInfo>();
117 if (tinfo.globalRunNumberChanged) {
118 // new run is starting
119 LOG(info) << "New run start detected";
120 mRunStopRequested = false;
121 mInitDone = false;
122 }
123 if (mRunStopRequested) {
124 return;
125 }
126 auto runStartTime = std::chrono::high_resolution_clock::now();
128 recoCont.collectData(pc, *mDataRequest);
129 updateTimeDependentParams(pc);
130 std::chrono::duration<double, std::milli> ccdbUpdateTime = std::chrono::high_resolution_clock::now() - runStartTime;
131
132 // we always require the unbinned residuals and the associated detector info and track references
133 auto residualsData = pc.inputs().get<gsl::span<o2::tpc::UnbinnedResid>>("unbinnedRes");
134 auto residualsDataDet = pc.inputs().get<gsl::span<o2::tpc::DetInfoResid>>("detinfoRes");
135 auto trackRefs = pc.inputs().get<gsl::span<o2::tpc::TrackDataCompact>>("trackRefs");
136
137 // track data input is optional
138 const gsl::span<const o2::tpc::TrackData>* trkDataPtr = nullptr;
139 using trkDataType = std::decay_t<decltype(pc.inputs().get<gsl::span<o2::tpc::TrackData>>(""))>;
140 std::optional<trkDataType> trkData;
141 if (mTrackInput) {
142 trkData.emplace(pc.inputs().get<gsl::span<o2::tpc::TrackData>>("trkData"));
143 trkDataPtr = &trkData.value();
144 }
145 // MC truth of the track data (optional, MC only)
146 const gsl::span<const o2::tpc::TrackDataMC>* trkDataMCPtr = nullptr;
147 using trkDataMCType = std::decay_t<decltype(pc.inputs().get<gsl::span<o2::tpc::TrackDataMC>>(""))>;
148 std::optional<trkDataMCType> trkDataMC;
149 if (mMCInput) {
150 trkDataMC.emplace(pc.inputs().get<gsl::span<o2::tpc::TrackDataMC>>("trkDataMC"));
151 trkDataMCPtr = &trkDataMC.value();
152 }
153 // CTP lumi input (optional)
154 const o2::ctp::LumiInfo* lumi = nullptr;
155 using lumiDataType = std::decay_t<decltype(pc.inputs().get<o2::ctp::LumiInfo>(""))>;
156 std::optional<lumiDataType> lumiInput;
157 if (mCTPInput) {
158 lumiInput = recoCont.getCTPLumi();
159 lumi = &lumiInput.value();
160 }
161
162 o2::base::TFIDInfoHelper::fillTFIDInfo(pc, mAggregator->getCurrentTFInfo());
163 LOG(detail) << "Processing TF " << mAggregator->getCurrentTFInfo().tfCounter << " with " << trkData->size() << " tracks and " << residualsData.size() << " unbinned residuals associated to them";
164 mAggregator->process(residualsData, residualsDataDet, trackRefs, trkDataPtr, trkDataMCPtr, lumi);
165 std::chrono::duration<double, std::milli> runDuration = std::chrono::high_resolution_clock::now() - runStartTime;
166 LOGP(debug, "Duration for run method: {} ms. From this taken for time dependent param update: {} ms",
167 std::chrono::duration_cast<std::chrono::milliseconds>(runDuration).count(),
168 std::chrono::duration_cast<std::chrono::milliseconds>(ccdbUpdateTime).count());
169 if (pc.transitionState() == TransitionHandlingState::Requested) {
170 LOG(info) << "Run stop requested, finalizing";
171 mRunStopRequested = true;
172 mAggregator->checkSlotsToFinalize();
173 mAggregator.reset();
174 LOG(info) << "Finalizing done";
175 }
176 }
177
179 {
180 if (mRunStopRequested) {
181 return;
182 }
183 LOG(info) << "Finalizing calibration for end of stream";
184 mAggregator->checkSlotsToFinalize();
185 mAggregator.reset(); // must invoke destructor manually here, otherwise we get a segfault
186 LOG(info) << "Finalizing done for end of stream";
187 }
188
189 private:
190 void updateTimeDependentParams(ProcessingContext& pc)
191 {
193 mTPCVDriftHelper.extractCCDBInputs(pc);
194 if (mTPCVDriftHelper.isUpdated()) {
195 LOGP(info, "Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
196 mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift,
197 mTPCVDriftHelper.getVDriftObject().timeOffsetCorr, mTPCVDriftHelper.getVDriftObject().refTimeOffset,
198 mTPCVDriftHelper.getSourceName());
199 mAggregator->setTPCVDrift(mTPCVDriftHelper.getVDriftObject());
200 mTPCVDriftHelper.acknowledgeUpdate();
201 }
202 if (!mInitDone) {
203 mAggregator->setDataTakingContext(pc.services().get<DataTakingContext>());
204 mAggregator->setOrbitResetTime(o2::base::GRPGeomHelper::instance().getOrbitResetTimeMS());
205 mInitDone = true;
206 }
207 }
208 o2::tpc::VDriftHelper mTPCVDriftHelper{};
209 std::unique_ptr<o2::tpc::ResidualAggregator> mAggregator;
210 std::shared_ptr<o2::base::GRPGeomRequest> mCCDBRequest;
211 std::shared_ptr<o2::globaltracking::DataRequest> mDataRequest;
212 bool mTrackInput{false};
213 bool mCTPInput{false};
214 bool mWriteBinnedResiduals{false};
215 bool mWriteUnbinnedResiduals{false};
216 bool mWriteTrackData{false};
217 bool mMCInput{false};
218 bool mRunStopRequested{false};
219 bool mInitDone{false};
220};
221
222} // namespace calibration
223
224namespace framework
225{
226
227DataProcessorSpec getTPCResidualAggregatorSpec(bool trackInput, bool ctpInput, bool writeUnbinnedResiduals, bool writeBinnedResiduals, bool writeTrackData, bool mcInput = false)
228{
229 std::shared_ptr<o2::globaltracking::DataRequest> dataRequest = std::make_shared<o2::globaltracking::DataRequest>();
230 if (ctpInput) {
231 dataRequest->requestClusters(GID::getSourcesMask("CTP"), false);
232 }
233 auto& inputs = dataRequest->inputs;
235 inputs.emplace_back("unbinnedRes", "GLO", "UNBINNEDRES");
236 inputs.emplace_back("detinfoRes", "GLO", "DETINFORES");
237 inputs.emplace_back("trackRefs", "GLO", "TRKREFS");
238 if (trackInput) {
239 inputs.emplace_back("trkData", "GLO", "TRKDATA");
240 if (mcInput) {
241 inputs.emplace_back("trkDataMC", "GLO", "TRKDATAMC");
242 }
243 }
244 auto ccdbRequest = std::make_shared<o2::base::GRPGeomRequest>(true, // orbitResetTime
245 true, // GRPECS=true
246 false, // GRPLHCIF
247 false, // GRPMagField
248 false, // askMatLUT
250 inputs,
251 true);
252 return DataProcessorSpec{
253 "residual-aggregator",
254 inputs,
255 Outputs{},
256 AlgorithmSpec{adaptFromTask<o2::calibration::ResidualAggregatorDevice>(ccdbRequest, trackInput, ctpInput, writeUnbinnedResiduals, writeBinnedResiduals, writeTrackData, trackInput && mcInput, dataRequest)},
257 Options{
258 {"sec-per-slot", VariantType::UInt32, 600u, {"number of seconds per calibration time slot (put 0 for infinite slot length)"}},
259 {"updateInterval", VariantType::UInt32, 6'000u, {"update interval in number of TFs (only used in case slot length is infinite)"}},
260 {"max-delay", VariantType::UInt32, 1u, {"number of slots in past to consider"}},
261 {"min-entries", VariantType::Int, 0, {"minimum number of entries on average per voxel"}},
262 {"compression", VariantType::Int, 505, {"ROOT compression setting for output file (see TFile documentation for meaning of this number)"}},
263 {"output-dir", VariantType::String, "none", {"Output directory for residuals. Defaults to current working directory. Output is disabled in case set to /dev/null"}},
264 {"meta-output-dir", VariantType::String, "/dev/null", {"Residuals metadata output directory, must exist (if not /dev/null)"}},
265 {"autosave-interval", VariantType::Int, 0, {"Write output to file for every n-th TF. 0 means this feature is OFF"}}}};
266}
267
268} // namespace framework
269} // namespace o2
270
271#endif // O2_TPC_RESIDUALAGGREGATORSPEC_H
Utils and constants for calibration and related workflows.
std::ostringstream debug
Helper for geometry and GRP related CCDB requests.
Collects local TPC cluster residuals from EPNs.
Definition of the TrackResiduals class.
Helper class to extract VDrift from different sources.
void checkUpdates(o2::framework::ProcessingContext &pc)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
ResidualAggregatorDevice(std::shared_ptr< o2::base::GRPGeomRequest > req, bool trackInput, bool ctpInput, bool writeUnbinnedResiduals, bool writeBinnedResiduals, bool writeTrackData, bool mcInput, std::shared_ptr< o2::globaltracking::DataRequest > dataRequest)
void run(o2::framework::ProcessingContext &pc) final
void init(o2::framework::InitContext &ic) final
void endOfStream(o2::framework::EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void finaliseCCDB(o2::framework::ConcreteDataMatcher &matcher, void *obj) final
static mask_t getSourcesMask(const std::string_view srcList)
ServiceRegistryRef services()
The services registry associated with this processing context.
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs, bool laser=true, bool itstpcTgl=true)
void extractCCDBInputs(o2::framework::ProcessingContext &pc, bool laser=true, bool itstpcTgl=true)
const VDriftCorrFact & getVDriftObject() const
bool accountCCDBInputs(const o2::framework::ConcreteDataMatcher &matcher, void *obj)
static std::string_view getSourceName(Source s)
bool isUpdated() const
GLint GLsizei count
Definition glcorearb.h:399
constexpr TFType INFINITE_TF
Definition TimeSlot.h:30
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< OutputSpec > Outputs
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
static void fillTFIDInfo(o2::framework::ProcessingContext &pc, o2::dataformats::TFIDInfo &ti)
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
const o2::ctp::LumiInfo & getCTPLumi() const
float refTimeOffset
additive time offset reference (\mus)
float refVDrift
reference vdrift for which factor was extracted
float timeOffsetCorr
additive time offset correction (\mus)
float corrFact
drift velocity correction factor (multiplicative)
static std::string rectifyDirectory(const std::string_view p)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
LumiInfo lumi