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"
39#include "TPCFastTransformPOD.h"
40#include "GPUO2ExternalUser.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 "DataFormatsITSMFT/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,
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 ~BarrelAlignmentSpec() override = default;
93 void init(InitContext& ic) final;
94 void run(ProcessingContext& pc) final;
95 void finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj) final;
97
98 private:
99 void updateTimeDependentParams(ProcessingContext& pc);
100 std::string mIniParFile{};
101 bool mUseIniParErrors = true;
102 bool mUseMC = false;
103 bool mIgnoreCCDBAlignment = false;
104 bool mCosmic = false;
105 bool mLoadTPCCalib = false;
106 int mLane = 0;
107 int mPostProcessing = 0; // special mode of extracting alignment or constraints check
108 GTrackID::mask_t mMPsrc{};
109 DetID::mask_t mDetMask{};
110 std::unique_ptr<Controller> mController;
111 std::shared_ptr<DataRequest> mDataRequest;
112 std::shared_ptr<o2::base::GRPGeomRequest> mGRPGeomRequest;
113 std::string mConfMacro{};
114 std::unique_ptr<TMethodCall> mUsrConfMethod;
115 std::unique_ptr<o2::trd::TrackletTransformer> mTRDTransformer;
116 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
117 std::unique_ptr<o2::gpu::GPUParam> mTPCParam;
118
119 o2::tpc::VDriftHelper mTPCVDriftHelper{};
120
121 const o2::gpu::TPCFastTransformPOD* mTPCCorrMaps{};
122
123 //
124 TStopwatch mTimer;
125};
126
128{
129 mTimer.Stop();
130 mTimer.Reset();
132
133 int dbg = ic.options().get<int>("debug-output");
134 mLane = ic.services().get<const o2::framework::DeviceSpec>().inputTimesliceId;
135 mController = std::make_unique<Controller>(mDetMask, mMPsrc, mCosmic, mUseMC, mLane);
136 if (dbg) {
137 mController->setDebugOutputLevel(dbg);
138 }
139
140 mConfMacro = ic.options().get<std::string>("config-macro");
141 if (!mConfMacro.empty()) {
142 if (!std::filesystem::exists(mConfMacro)) {
143 LOG(fatal) << "Requested user macro " << mConfMacro << " does not exist";
144 }
145 std::string tmpmacro = mConfMacro + "+";
146 TString cmd = gSystem->GetMakeSharedLib();
147 cmd += " -O0 -g -ggdb";
148 // protect macro compilation by semaphore (to avoid problems in the pipelined code)
149 {
150 boost::interprocess::named_semaphore* sem = nullptr;
151 std::string semhashedstring{};
152 std::hash<std::string> hasher;
153 semhashedstring = "align_macro_" + std::to_string(hasher(mConfMacro)).substr(0, 16);
154 try {
155 sem = new boost::interprocess::named_semaphore(boost::interprocess::open_or_create_t{}, semhashedstring.c_str(), 1);
156 } catch (std::exception e) {
157 LOGP(error, "Exception occurred during {} compilation semaphore setup", tmpmacro);
158 sem = nullptr;
159 }
160 if (sem) {
161 sem->wait(); // wait until we can enter (no one else there)
162 }
163 gSystem->SetMakeSharedLib(cmd.Data());
164 auto res = gROOT->LoadMacro(tmpmacro.c_str());
165 if (sem) {
166 sem->post();
167 if (sem->try_wait()) { // if nobody else is waiting remove the semaphore resource
168 sem->post();
169 boost::interprocess::named_semaphore::remove(semhashedstring.c_str());
170 }
171 }
172 if (res) {
173 LOG(fatal) << "Failed to load user macro " << tmpmacro;
174 }
175 }
176 std::filesystem::path mpth(mConfMacro);
177 mConfMacro = mpth.stem();
178 mUsrConfMethod = std::make_unique<TMethodCall>();
179 mUsrConfMethod->InitWithPrototype(mConfMacro.c_str(), "o2::align::Controller*, int");
180 }
181 mIgnoreCCDBAlignment = ic.options().get<bool>("ignore-ccdb-alignment");
182 if (!mPostProcessing) {
183 if (GTrackID::includesDet(DetID::TRD, mMPsrc)) {
184 mTRDTransformer.reset(new o2::trd::TrackletTransformer);
185 if (ic.options().get<bool>("apply-xor")) {
186 mTRDTransformer->setApplyXOR();
187 }
188 auto prevShift = mTRDTransformer->isShiftApplied();
189 if (getenv("ALIEN_JDL_LPMPRODUCTIONTYPE") && std::strcmp(getenv("ALIEN_JDL_LPMPRODUCTIONTYPE"), "MC") == 0) {
190 // apply artificial pad shift in case non-ideal alignment is used to compensate for shift in current alignment from real data
191 mTRDTransformer->setApplyShift(false);
192 }
193 LOGP(info, "Old TRD shift : {} new : {}", prevShift, mTRDTransformer->isShiftApplied());
194 mController->setTRDTransformer(mTRDTransformer.get());
195 }
196 mController->setAllowAfterburnerTracks(ic.options().get<bool>("allow-afterburner-tracks"));
197 }
198
199 mIniParFile = ic.options().get<std::string>("initial-params-file");
200 mUseIniParErrors = !ic.options().get<bool>("ignore-initial-params-errors");
201 if (mPostProcessing && !(mPostProcessing != GenPedeFiles) && (mIniParFile.empty() || mIniParFile == "none")) {
202 LOGP(warn, "Postprocessing {} is requested but the initial-params-file is not provided", mPostProcessing);
203 }
204}
205
206void BarrelAlignmentSpec::updateTimeDependentParams(ProcessingContext& pc)
207{
209 auto tinfo = pc.services().get<o2::framework::TimingInfo>();
210 if (pc.services().get<o2::framework::TimingInfo>().globalRunNumberChanged) {
211 if (mController->getDebugOutputLevel()) {
212 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(fmt::format("mpDebug_{}_{:08d}_{:010d}.root", mLane, tinfo.runNumber, tinfo.tfCounter).c_str(), "recreate");
213 mController->setDebugStream(mDBGOut.get());
214 }
215 if (!mIgnoreCCDBAlignment) {
216 for (auto id = DetID::First; id <= DetID::Last; id++) {
217 const auto* alg = o2::base::GRPGeomHelper::instance().getAlignment(id);
218 if (alg && !alg->empty()) {
220 }
221 gGeoManager->RefreshPhysicalNodes(false);
222 }
223 } else {
224 LOG(warn) << "CCDB alignment is NOT applied to ideal geometry";
225 }
226 if (!mController->getInitGeomDone()) {
227 mController->initDetectors();
228 }
229 if (mTRDTransformer) { // need geometry loaded
230 mTRDTransformer->init();
231 }
232
233 if (!(mIniParFile.empty() || mIniParFile == "none")) {
234 mController->readParameters(mIniParFile, mUseIniParErrors);
235 mController->applyAlignmentFromMPSol();
236 }
237
238 // call this in the very end
239 if (mUsrConfMethod) {
240 int dummyPar = 0, ret = -1;
241 Controller* tmpPtr = mController.get();
242 const void* args[2] = {&tmpPtr, &dummyPar};
243 mUsrConfMethod->Execute(nullptr, args, 2, &ret);
244 if (ret != 0) {
245 LOG(fatal) << "Execution of user method config method " << mConfMacro << " failed with " << ret;
246 }
247 }
249 o2::base::PropagatorD::Instance()->setTGeoFallBackAllowed(false);
250 }
251 if (GTrackID::includesDet(DetID::TRD, mMPsrc) && mTRDTransformer) {
252 pc.inputs().get<o2::trd::CalVdriftExB*>("calvdexb"); // just to trigger the finaliseCCDB
253 }
254 if (mLoadTPCCalib) {
255
256 static float prevField = 1e-6;
257 float newField = o2::base::Propagator::Instance()->getNominalBz();
258 if (prevField != newField) {
259 prevField = newField;
260 if (mDetMask[DetID::TPC]) {
261 mTPCParam.reset(new o2::gpu::GPUParam);
262 mTPCParam->SetDefaults(o2::base::Propagator::Instance()->getNominalBz(), false);
263 mController->setTPCParam(mTPCParam.get());
264 }
265 }
266
267 mTPCVDriftHelper.extractCCDBInputs(pc);
268
269 auto const& raw = pc.inputs().get<const char*>("corrMap");
270 mTPCCorrMaps = &o2::gpu::TPCFastTransformPOD::get(raw);
271 mController->setTPCCorrMaps(mTPCCorrMaps);
272 if (mTPCVDriftHelper.isUpdated()) {
273 LOGP(info, "Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
274 mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift,
275 mTPCVDriftHelper.getVDriftObject().timeOffsetCorr, mTPCVDriftHelper.getVDriftObject().refTimeOffset,
276 mTPCVDriftHelper.getSourceName());
277 mController->setTPCVDrift(mTPCVDriftHelper.getVDriftObject());
278 mTPCVDriftHelper.acknowledgeUpdate();
279 }
280 }
281}
282
284{
286 if (matcher == ConcreteDataMatcher("ITS", "CLUSDICT", 0)) {
287 auto* its = mController->getDetector(o2::detectors::DetID::ITS);
288 if (its) {
289 LOG(info) << "cluster dictionary updated";
290 ((AlignableDetectorITS*)its)->setITSDictionary((const o2::itsmft::TopologyDictionary*)obj);
291 return;
292 }
293 }
294 if (matcher == ConcreteDataMatcher("TRD", "CALVDRIFTEXB", 0)) {
295 LOG(info) << "CalVdriftExB object has been updated";
296 mTRDTransformer->setCalVdriftExB((const o2::trd::CalVdriftExB*)obj);
297 return;
298 }
299 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
300
301 return;
302 }
303}
304
306{
307 mTimer.Start(false);
308 if (mPostProcessing) { // special mode, no data processing
309 updateTimeDependentParams(pc);
310 if (mController->getInstanceID() == 0) {
311 if (mPostProcessing & PostProc::CheckConstaints) {
312 mController->addAutoConstraints();
313 mController->checkConstraints();
314 }
315 if (mPostProcessing & PostProc::WriteResults) {
316 mController->writeCalibrationResults();
317 }
318 }
320 } else {
321 RecoContainer recoData;
322 recoData.collectData(pc, *mDataRequest.get());
323 updateTimeDependentParams(pc); // call after collectData !!!
324 mController->setRecoContainer(&recoData);
325 mController->setTimingInfo(pc.services().get<o2::framework::TimingInfo>());
326 if (mCosmic) {
327 mController->processCosmic();
328 } else {
329 mController->process();
330 }
331 }
332 mTimer.Stop();
333}
334
336{
337 auto inst = ec.services().get<const o2::framework::DeviceSpec>().inputTimesliceId;
338 if (!mPostProcessing) {
339 LOGP(info, "Barrel alignment data pereparation total timing: Cpu: {:.3e} Real: {:.3e} s in {} slots, instance {}", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1, inst);
340 mController->closeMPRecOutput();
341 mController->closeMilleOutput();
342 mController->closeResidOutput();
343 }
344 if (inst == 0) {
345 if (!mPostProcessing || (mPostProcessing & PostProc::GenPedeFiles)) {
346 LOG(info) << "Writing millepede control files";
347 if (!mPostProcessing) {
348 mController->terminate(); // finalize data stat
349 }
350 mController->addAutoConstraints();
351 mController->genPedeSteerFile();
352 mController->getStat().print();
353 } else if (mPostProcessing & PostProc::LabelPedeResults) {
354 mController->writeLabeledPedeResults();
355 }
356 }
357 mDBGOut.reset();
358}
359
360DataProcessorSpec getBarrelAlignmentSpec(GTrackID::mask_t srcMP, GTrackID::mask_t src, DetID::mask_t dets, DetID::mask_t skipDetClusters, bool enableCosmic, int postprocess, bool useMC)
361{
362 std::vector<OutputSpec> outputs;
363 auto dataRequest = std::make_shared<DataRequest>();
364 bool loadTPCCalib = false;
365 Options opts{
366 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)"}},
367 ConfigParamSpec{"allow-afterburner-tracks", VariantType::Bool, false, {"allow using ITS-TPC afterburner tracks"}},
368 ConfigParamSpec{"ignore-ccdb-alignment", VariantType::Bool, false, {"do not aplly CCDB alignment to ideal geometry"}},
369 ConfigParamSpec{"initial-params-file", VariantType::String, "", {"initial parameters file"}},
370 ConfigParamSpec{"config-macro", VariantType::String, "", {"configuration macro with signature (o2::align::Controller*, int) to execute from init"}},
371 ConfigParamSpec{"ignore-initial-params-errors", VariantType::Bool, false, {"ignore initial params (if any) errors for precondition"}},
372 ConfigParamSpec{"debug-output", VariantType::Int, 0, {"produce debugging output root files"}}};
373 if (!postprocess) {
374 dataRequest->requestTracks(src, useMC);
375 dataRequest->requestClusters(src, false, skipDetClusters);
376 dataRequest->requestPrimaryVertices(useMC);
377 if (GTrackID::includesDet(DetID::TRD, srcMP)) {
378 dataRequest->inputs.emplace_back("calvdexb", "TRD", "CALVDRIFTEXB", 0, Lifetime::Condition, ccdbParamSpec("TRD/Calib/CalVdriftExB"));
379 }
380 if (enableCosmic) {
381 dataRequest->requestCoscmicTracks(useMC);
382 }
383 if (src[DetID::TPC] && !skipDetClusters[DetID::TPC]) {
384 o2::tpc::VDriftHelper::requestCCDBInputs(dataRequest->inputs);
385 dataRequest->inputs.emplace_back("corrMap", o2::header::gDataOriginTPC, "TPCCORRMAP", 0, Lifetime::Timeframe);
386 loadTPCCalib = true;
387 }
388 }
389 auto ccdbRequest = std::make_shared<o2::base::GRPGeomRequest>(true, // orbitResetTime
390 true, // GRPECS=true
391 false, // GRPLHCIF
392 true, // GRPMagField
393 true, // askMatLUT
395 dataRequest->inputs,
396 false, // ask update once (except field)
397 true, // init PropagatorD
398 "ITS,TPC,TRD,TOF"); // alignment objects to apply
399 return DataProcessorSpec{
400 "barrel-alignment",
401 dataRequest->inputs,
402 outputs,
403 AlgorithmSpec{adaptFromTask<BarrelAlignmentSpec>(srcMP, dataRequest, ccdbRequest, dets, enableCosmic, postprocess, useMC, loadTPCCalib)},
404 opts};
405}
406
407} // namespace align
408} // namespace o2
Configuration file for global alignment.
ITS detector wrapper.
Steering class for the global alignment.
Wrapper container for different reconstructed object types.
Definition of the ClusterTopology class.
Definition of the GeometryManager class.
o2::raw::RawFileWriter * raw
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.
POD correction map.
Helper class to extract VDrift from different sources.
void init(InitContext &ic) final
BarrelAlignmentSpec(GTrackID::mask_t srcMP, std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > ggrec, DetID::mask_t detmask, bool cosmic, int postprocess, bool useMC, bool loadTPCCalib)
~BarrelAlignmentSpec() override=default
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:178
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:95
static constexpr ID TRD
Definition DetID.h:65
static constexpr ID Last
if extra detectors added, update this !!!
Definition DetID.h:93
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.
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
constexpr o2::header::DataOrigin gDataOriginTPC
Definition DataHeader.h:576
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)
create a processor spec
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
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)
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)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"