Project
Loading...
Searching...
No Matches
BarrelAlignmentSpec.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
13
14#include <vector>
15#include <string>
16#include <filesystem>
17#include <TMethodCall.h>
18#include <TStopwatch.h>
19#include <TROOT.h>
20#include <TSystem.h>
21#include "TMethodCall.h"
24#include "Align/Controller.h"
25#include "Align/AlignConfig.h"
40#include "GPUO2Interface.h"
41#include "GPUO2InterfaceUtils.h"
42#include "GPUParam.h"
43#include "Headers/DataHeader.h"
45#include "Framework/Task.h"
49
50#include <boost/interprocess/sync/named_semaphore.hpp>
51
52/*
53#include "DataFormatsITSMFT/TopologyDictionary.h"
54#include "DataFormatsTPC/Constants.h"
55#include "ReconstructionDataFormats/GlobalTrackAccessor.h"
56#include "ReconstructionDataFormats/TrackTPCITS.h"
57#include "ReconstructionDataFormats/MatchInfoTOF.h"
58#include "ReconstructionDataFormats/TrackTPCTOF.h"
59#include "DataFormatsITS/TrackITS.h"
60#include "DataFormatsITSMFT/CompCluster.h"
61#include "DataFormatsITSMFT/ROFRecord.h"
62#include "DataFormatsITSMFT/TopologyDictionary.h"
63#include "DataFormatsTPC/TrackTPC.h"
64#include "DataFormatsTPC/ClusterNative.h"
65#include "DataFormatsTPC/WorkflowHelper.h"
66#include "ITSBase/GeometryTGeo.h"
67#include "ITSMFTBase/DPLAlpideParam.h"
68*/
69
70using namespace o2::framework;
71using namespace o2::globaltracking;
72using namespace o2::align;
73
76
77namespace o2
78{
79namespace align
80{
81
83{
84 public:
85 enum PostProc { WriteResults = 0x1 << 0,
86 CheckConstaints = 0x1 << 1,
87 GenPedeFiles = 0x1 << 2,
88 LabelPedeResults = 0x1 << 3 };
89 BarrelAlignmentSpec(GTrackID::mask_t srcMP, std::shared_ptr<DataRequest> dr, std::shared_ptr<o2::base::GRPGeomRequest> ggrec, const o2::tpc::CorrectionMapsLoaderGloOpts& tpcOpt,
90 DetID::mask_t detmask, bool cosmic, int postprocess, bool useMC, bool loadTPCCalib)
91 : mDataRequest(dr), mGRPGeomRequest(ggrec), mMPsrc{srcMP}, mDetMask{detmask}, mCosmic(cosmic), mPostProcessing(postprocess), mUseMC(useMC), mLoadTPCCalib(loadTPCCalib)
92 {
93 mTPCCorrMapsLoader.setLumiScaleType(tpcOpt.lumiType);
94 mTPCCorrMapsLoader.setLumiScaleMode(tpcOpt.lumiMode);
95 mTPCCorrMapsLoader.setCheckCTPIDCConsistency(tpcOpt.checkCTPIDCconsistency);
96 }
97 ~BarrelAlignmentSpec() override = default;
98 void init(InitContext& ic) final;
99 void run(ProcessingContext& pc) final;
100 void finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj) final;
102
103 private:
104 void updateTimeDependentParams(ProcessingContext& pc);
105 std::string mIniParFile{};
106 bool mUseIniParErrors = true;
107 bool mUseMC = false;
108 bool mIgnoreCCDBAlignment = false;
109 bool mCosmic = false;
110 bool mLoadTPCCalib = false;
111 int mLane = 0;
112 int mPostProcessing = 0; // special mode of extracting alignment or constraints check
113 GTrackID::mask_t mMPsrc{};
114 DetID::mask_t mDetMask{};
115 std::unique_ptr<Controller> mController;
116 std::shared_ptr<DataRequest> mDataRequest;
117 std::shared_ptr<o2::base::GRPGeomRequest> mGRPGeomRequest;
118 std::string mConfMacro{};
119 std::unique_ptr<TMethodCall> mUsrConfMethod;
120 std::unique_ptr<o2::trd::TrackletTransformer> mTRDTransformer;
121 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
122 std::unique_ptr<o2::gpu::GPUParam> mTPCParam;
123
124 o2::tpc::VDriftHelper mTPCVDriftHelper{};
125 o2::tpc::CorrectionMapsLoader mTPCCorrMapsLoader{};
126
127 //
128 TStopwatch mTimer;
129};
130
132{
133 mTimer.Stop();
134 mTimer.Reset();
136
137 int dbg = ic.options().get<int>("debug-output");
138 mLane = ic.services().get<const o2::framework::DeviceSpec>().inputTimesliceId;
139 mController = std::make_unique<Controller>(mDetMask, mMPsrc, mCosmic, mUseMC, mLane);
140 if (dbg) {
141 mController->setDebugOutputLevel(dbg);
142 }
143
144 mConfMacro = ic.options().get<std::string>("config-macro");
145 if (!mConfMacro.empty()) {
146 if (!std::filesystem::exists(mConfMacro)) {
147 LOG(fatal) << "Requested user macro " << mConfMacro << " does not exist";
148 }
149 std::string tmpmacro = mConfMacro + "+";
150 TString cmd = gSystem->GetMakeSharedLib();
151 cmd += " -O0 -g -ggdb";
152 // protect macro compilation by semaphore (to avoid problems in the pipelined code)
153 {
154 boost::interprocess::named_semaphore* sem = nullptr;
155 std::string semhashedstring{};
156 std::hash<std::string> hasher;
157 semhashedstring = "align_macro_" + std::to_string(hasher(mConfMacro)).substr(0, 16);
158 try {
159 sem = new boost::interprocess::named_semaphore(boost::interprocess::open_or_create_t{}, semhashedstring.c_str(), 1);
160 } catch (std::exception e) {
161 LOGP(error, "Exception occurred during {} compilation semaphore setup", tmpmacro);
162 sem = nullptr;
163 }
164 if (sem) {
165 sem->wait(); // wait until we can enter (no one else there)
166 }
167 gSystem->SetMakeSharedLib(cmd.Data());
168 auto res = gROOT->LoadMacro(tmpmacro.c_str());
169 if (sem) {
170 sem->post();
171 if (sem->try_wait()) { // if nobody else is waiting remove the semaphore resource
172 sem->post();
173 boost::interprocess::named_semaphore::remove(semhashedstring.c_str());
174 }
175 }
176 if (res) {
177 LOG(fatal) << "Failed to load user macro " << tmpmacro;
178 }
179 }
180 std::filesystem::path mpth(mConfMacro);
181 mConfMacro = mpth.stem();
182 mUsrConfMethod = std::make_unique<TMethodCall>();
183 mUsrConfMethod->InitWithPrototype(mConfMacro.c_str(), "o2::align::Controller*, int");
184 }
185 mIgnoreCCDBAlignment = ic.options().get<bool>("ignore-ccdb-alignment");
186 if (!mPostProcessing) {
187 if (mLoadTPCCalib) {
188 mTPCCorrMapsLoader.init(ic);
189 }
190 if (GTrackID::includesDet(DetID::TRD, mMPsrc)) {
191 mTRDTransformer.reset(new o2::trd::TrackletTransformer);
192 if (ic.options().get<bool>("apply-xor")) {
193 mTRDTransformer->setApplyXOR();
194 }
195 auto prevShift = mTRDTransformer->isShiftApplied();
196 if (getenv("ALIEN_JDL_LPMPRODUCTIONTYPE") && std::strcmp(getenv("ALIEN_JDL_LPMPRODUCTIONTYPE"), "MC") == 0) {
197 // apply artificial pad shift in case non-ideal alignment is used to compensate for shift in current alignment from real data
198 mTRDTransformer->setApplyShift(false);
199 }
200 LOGP(info, "Old TRD shift : {} new : {}", prevShift, mTRDTransformer->isShiftApplied());
201 mController->setTRDTransformer(mTRDTransformer.get());
202 }
203 mController->setAllowAfterburnerTracks(ic.options().get<bool>("allow-afterburner-tracks"));
204 }
205
206 mIniParFile = ic.options().get<std::string>("initial-params-file");
207 mUseIniParErrors = !ic.options().get<bool>("ignore-initial-params-errors");
208 if (mPostProcessing && !(mPostProcessing != GenPedeFiles) && (mIniParFile.empty() || mIniParFile == "none")) {
209 LOGP(warn, "Postprocessing {} is requested but the initial-params-file is not provided", mPostProcessing);
210 }
211}
212
213void BarrelAlignmentSpec::updateTimeDependentParams(ProcessingContext& pc)
214{
216 auto tinfo = pc.services().get<o2::framework::TimingInfo>();
217 if (pc.services().get<o2::framework::TimingInfo>().globalRunNumberChanged) {
218 if (mController->getDebugOutputLevel()) {
219 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(fmt::format("mpDebug_{}_{:08d}_{:010d}.root", mLane, tinfo.runNumber, tinfo.tfCounter).c_str(), "recreate");
220 mController->setDebugStream(mDBGOut.get());
221 }
222 if (!mIgnoreCCDBAlignment) {
223 for (auto id = DetID::First; id <= DetID::Last; id++) {
224 const auto* alg = o2::base::GRPGeomHelper::instance().getAlignment(id);
225 if (alg && !alg->empty()) {
227 }
228 gGeoManager->RefreshPhysicalNodes(false);
229 }
230 } else {
231 LOG(warn) << "CCDB alignment is NOT applied to ideal geometry";
232 }
233 if (!mController->getInitGeomDone()) {
234 mController->initDetectors();
235 }
236 if (mTRDTransformer) { // need geometry loaded
237 mTRDTransformer->init();
238 }
239
240 if (!(mIniParFile.empty() || mIniParFile == "none")) {
241 mController->readParameters(mIniParFile, mUseIniParErrors);
242 mController->applyAlignmentFromMPSol();
243 }
244
245 // call this in the very end
246 if (mUsrConfMethod) {
247 int dummyPar = 0, ret = -1;
248 Controller* tmpPtr = mController.get();
249 const void* args[2] = {&tmpPtr, &dummyPar};
250 mUsrConfMethod->Execute(nullptr, args, 2, &ret);
251 if (ret != 0) {
252 LOG(fatal) << "Execution of user method config method " << mConfMacro << " failed with " << ret;
253 }
254 }
256 o2::base::PropagatorD::Instance()->setTGeoFallBackAllowed(false);
257 }
258 if (GTrackID::includesDet(DetID::TRD, mMPsrc) && mTRDTransformer) {
259 pc.inputs().get<o2::trd::CalVdriftExB*>("calvdexb"); // just to trigger the finaliseCCDB
260 }
261 if (mLoadTPCCalib) {
262
263 static float prevField = 1e-6;
264 float newField = o2::base::Propagator::Instance()->getNominalBz();
265 if (prevField != newField) {
266 prevField = newField;
267 if (mDetMask[DetID::TPC]) {
268 mTPCParam.reset(new o2::gpu::GPUParam);
269 mTPCParam->SetDefaults(o2::base::Propagator::Instance()->getNominalBz(), false);
270 mController->setTPCParam(mTPCParam.get());
271 }
272 }
273
274 mTPCVDriftHelper.extractCCDBInputs(pc);
275 mTPCCorrMapsLoader.extractCCDBInputs(pc);
276 bool updateMaps = false;
277 if (mTPCCorrMapsLoader.isUpdated()) {
278 mTPCCorrMapsLoader.acknowledgeUpdate();
279 updateMaps = true;
280 }
281 mController->setTPCCorrMaps(&mTPCCorrMapsLoader);
282 if (mTPCVDriftHelper.isUpdated()) {
283 LOGP(info, "Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
284 mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift,
285 mTPCVDriftHelper.getVDriftObject().timeOffsetCorr, mTPCVDriftHelper.getVDriftObject().refTimeOffset,
286 mTPCVDriftHelper.getSourceName());
287 mController->setTPCVDrift(mTPCVDriftHelper.getVDriftObject());
288 mTPCVDriftHelper.acknowledgeUpdate();
289 updateMaps = true;
290 }
291 if (updateMaps) {
292 mTPCCorrMapsLoader.updateVDrift(mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift, mTPCVDriftHelper.getVDriftObject().getTimeOffset());
293 }
294 }
295}
296
298{
300 if (matcher == ConcreteDataMatcher("ITS", "CLUSDICT", 0)) {
301 auto* its = mController->getDetector(o2::detectors::DetID::ITS);
302 if (its) {
303 LOG(info) << "cluster dictionary updated";
304 ((AlignableDetectorITS*)its)->setITSDictionary((const o2::itsmft::TopologyDictionary*)obj);
305 return;
306 }
307 }
308 if (matcher == ConcreteDataMatcher("TRD", "CALVDRIFTEXB", 0)) {
309 LOG(info) << "CalVdriftExB object has been updated";
310 mTRDTransformer->setCalVdriftExB((const o2::trd::CalVdriftExB*)obj);
311 return;
312 }
313 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
314
315 return;
316 }
317 if (mTPCCorrMapsLoader.accountCCDBInputs(matcher, obj)) {
318 return;
319 }
320}
321
323{
324 mTimer.Start(false);
325 if (mPostProcessing) { // special mode, no data processing
326 updateTimeDependentParams(pc);
327 if (mController->getInstanceID() == 0) {
328 if (mPostProcessing & PostProc::CheckConstaints) {
329 mController->addAutoConstraints();
330 mController->checkConstraints();
331 }
332 if (mPostProcessing & PostProc::WriteResults) {
333 mController->writeCalibrationResults();
334 }
335 }
337 } else {
338 RecoContainer recoData;
339 recoData.collectData(pc, *mDataRequest.get());
340 updateTimeDependentParams(pc); // call after collectData !!!
341 mController->setRecoContainer(&recoData);
342 mController->setTimingInfo(pc.services().get<o2::framework::TimingInfo>());
343 if (mCosmic) {
344 mController->processCosmic();
345 } else {
346 mController->process();
347 }
348 }
349 mTimer.Stop();
350}
351
353{
354 auto inst = ec.services().get<const o2::framework::DeviceSpec>().inputTimesliceId;
355 if (!mPostProcessing) {
356 LOGP(info, "Barrel alignment data pereparation total timing: Cpu: {:.3e} Real: {:.3e} s in {} slots, instance {}", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1, inst);
357 mController->closeMPRecOutput();
358 mController->closeMilleOutput();
359 mController->closeResidOutput();
360 }
361 if (inst == 0) {
362 if (!mPostProcessing || (mPostProcessing & PostProc::GenPedeFiles)) {
363 LOG(info) << "Writing millepede control files";
364 if (!mPostProcessing) {
365 mController->terminate(); // finalize data stat
366 }
367 mController->addAutoConstraints();
368 mController->genPedeSteerFile();
369 mController->getStat().print();
370 } else if (mPostProcessing & PostProc::LabelPedeResults) {
371 mController->writeLabeledPedeResults();
372 }
373 }
374 mDBGOut.reset();
375}
376
377DataProcessorSpec getBarrelAlignmentSpec(GTrackID::mask_t srcMP, GTrackID::mask_t src, DetID::mask_t dets, DetID::mask_t skipDetClusters, bool enableCosmic, int postprocess, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts)
378{
379 std::vector<OutputSpec> outputs;
380 auto dataRequest = std::make_shared<DataRequest>();
381 bool loadTPCCalib = false;
382 Options opts{
383 ConfigParamSpec{"apply-xor", o2::framework::VariantType::Bool, false, {"flip the 8-th bit of slope and position (for processing TRD CTFs from 2021 pilot beam)"}},
384 ConfigParamSpec{"allow-afterburner-tracks", VariantType::Bool, false, {"allow using ITS-TPC afterburner tracks"}},
385 ConfigParamSpec{"ignore-ccdb-alignment", VariantType::Bool, false, {"do not aplly CCDB alignment to ideal geometry"}},
386 ConfigParamSpec{"initial-params-file", VariantType::String, "", {"initial parameters file"}},
387 ConfigParamSpec{"config-macro", VariantType::String, "", {"configuration macro with signature (o2::align::Controller*, int) to execute from init"}},
388 ConfigParamSpec{"ignore-initial-params-errors", VariantType::Bool, false, {"ignore initial params (if any) errors for precondition"}},
389 ConfigParamSpec{"debug-output", VariantType::Int, 0, {"produce debugging output root files"}}};
390 if (!postprocess) {
391 dataRequest->requestTracks(src, useMC);
392 dataRequest->requestClusters(src, false, skipDetClusters);
393 dataRequest->requestPrimaryVertices(useMC);
394 if (GTrackID::includesDet(DetID::TRD, srcMP)) {
395 dataRequest->inputs.emplace_back("calvdexb", "TRD", "CALVDRIFTEXB", 0, Lifetime::Condition, ccdbParamSpec("TRD/Calib/CalVdriftExB"));
396 }
397 if (enableCosmic) {
398 dataRequest->requestCoscmicTracks(useMC);
399 }
400 if (src[DetID::TPC] && !skipDetClusters[DetID::TPC]) {
401 o2::tpc::VDriftHelper::requestCCDBInputs(dataRequest->inputs);
402 o2::tpc::CorrectionMapsLoader::requestCCDBInputs(dataRequest->inputs, opts, sclOpts);
403 loadTPCCalib = true;
404 }
405 }
406 auto ccdbRequest = std::make_shared<o2::base::GRPGeomRequest>(true, // orbitResetTime
407 true, // GRPECS=true
408 false, // GRPLHCIF
409 true, // GRPMagField
410 true, // askMatLUT
412 dataRequest->inputs,
413 false, // ask update once (except field)
414 true, // init PropagatorD
415 "ITS,TPC,TRD,TOF"); // alignment objects to apply
416 return DataProcessorSpec{
417 "barrel-alignment",
418 dataRequest->inputs,
419 outputs,
420 AlgorithmSpec{adaptFromTask<BarrelAlignmentSpec>(srcMP, dataRequest, ccdbRequest, sclOpts, dets, enableCosmic, postprocess, useMC, loadTPCCalib)},
421 opts};
422}
423
424} // namespace align
425} // namespace o2
Configuration file for global alignment.
ITS detector wrapper.
Steering class for the global alignment.
Helper class to access load maps from CCDB.
Wrapper container for different reconstructed object types.
Definition of the ClusterTopology class.
Definition of the GeometryManager class.
Helper for geometry and GRP related CCDB requests.
Header of the General Run Parameters object.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
Definition of the Names Generator class.
uint32_t res
Definition RawData.h:0
Wrapper container for different reconstructed object types.
Helper class to extract VDrift from different sources.
void init(InitContext &ic) final
~BarrelAlignmentSpec() override=default
BarrelAlignmentSpec(GTrackID::mask_t srcMP, std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > ggrec, const o2::tpc::CorrectionMapsLoaderGloOpts &tpcOpt, DetID::mask_t detmask, bool cosmic, int postprocess, bool useMC, bool loadTPCCalib)
void finaliseCCDB(o2::framework::ConcreteDataMatcher &matcher, void *obj) final
void endOfStream(framework::EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void run(ProcessingContext &pc) final
void checkUpdates(o2::framework::ProcessingContext &pc)
auto getAlignment(o2::detectors::DetID det) const
bool finaliseCCDB(o2::framework::ConcreteDataMatcher &matcher, void *obj)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
static bool applyAlignment(const std::vector< o2::detectors::AlignParam > &algPars)
misalign geometry with alignment objects from the array, optionaly check overlaps
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:143
void printKeyValues(bool showProv=true, bool useLogger=false, bool withPadding=true, bool showHash=true) const final
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
static constexpr ID ITS
Definition DetID.h:63
static constexpr ID First
Definition DetID.h:94
static constexpr ID TRD
Definition DetID.h:65
static constexpr ID Last
if extra detectors added, update this !!!
Definition DetID.h:92
static constexpr ID TPC
Definition DetID.h:64
ServiceRegistryRef services()
Definition InitContext.h:34
ConfigParamRegistry const & options()
Definition InitContext.h:33
decltype(auto) get(R binding, int part=0) const
InputRecord & inputs()
The inputs associated with this processing context.
ServiceRegistryRef services()
The services registry associated with this processing context.
void extractCCDBInputs(o2::framework::ProcessingContext &pc)
void updateVDrift(float vdriftCorr, float vdrifRef, float driftTimeOffset=0)
bool accountCCDBInputs(const o2::framework::ConcreteDataMatcher &matcher, void *obj)
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs, std::vector< o2::framework::ConfigParamSpec > &options, const CorrectionMapsLoaderGloOpts &gloOpts)
void init(o2::framework::InitContext &ic)
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
GLenum src
Definition glcorearb.h:1767
framework::DataProcessorSpec getBarrelAlignmentSpec(o2::dataformats::GlobalTrackID::mask_t srcMP, o2::dataformats::GlobalTrackID::mask_t src, o2::detectors::DetID::mask_t dets, o2::detectors::DetID::mask_t skipDetClusters, bool enableCosmic, int postproc, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts &sclOpts)
create a processor spec
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)
@ Me
Only quit this data processor.
std::vector< ConfigParamSpec > Options
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
int lumiType
what estimator to used for corrections scaling: 0: no scaling, 1: CTP, 2: IDC
int lumiMode
what corrections method to use: 0: classical scaling, 1: Using of the derivative map,...
float refTimeOffset
additive time offset reference (\mus)
float refVDrift
reference vdrift for which factor was extracted
float getTimeOffset() const
float timeOffsetCorr
additive time offset correction (\mus)
float corrFact
drift velocity correction factor (multiplicative)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"