diff --git a/Detectors/AOD/CMakeLists.txt b/Detectors/AOD/CMakeLists.txt index 7174760a64e6b..b145a71ffb19a 100644 --- a/Detectors/AOD/CMakeLists.txt +++ b/Detectors/AOD/CMakeLists.txt @@ -9,33 +9,40 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2_add_library( +add_library(AODProducerWorkflow INTERFACE) + +target_link_libraries( AODProducerWorkflow - SOURCES src/AODProducerWorkflowSpec.cxx - PUBLIC_LINK_LIBRARIES - O2::DetectorsVertexing - O2::FT0Workflow - O2::FDDWorkflow - O2::FV0Workflow - O2::Framework - O2::GlobalTracking - O2::GlobalTrackingWorkflow - O2::ITSMFTWorkflow - O2::ITSWorkflow - O2::ITStracking - O2::MCHTracking - O2::MFTWorkflow - O2::MathUtils - O2::SimulationDataFormat - O2::Steer - O2::TPCWorkflow + INTERFACE + O2::DetectorsVertexing + O2::FT0Workflow + O2::FDDWorkflow + O2::FV0Workflow + O2::Framework + O2::GlobalTracking + O2::GlobalTrackingWorkflow + O2::ITSMFTWorkflow + O2::ITSWorkflow + O2::ITStracking + O2::MCHTracking + O2::MFTWorkflow + O2::MathUtils + O2::SimulationDataFormat + O2::Steer + O2::TPCWorkflow ) + +target_include_directories(AODProducerWorkflow INTERFACE include) + +add_library(internal::AODProducerWorkflow ALIAS AODProducerWorkflow) + o2_add_executable( - workflow - COMPONENT_NAME aod-producer - SOURCES src/aod-producer-workflow.cxx - PUBLIC_LINK_LIBRARIES O2::AODProducerWorkflow + workflow + COMPONENT_NAME aod-producer + SOURCES src/aod-producer-workflow.cxx src/AODProducerWorkflowSpec.cxx + PUBLIC_LINK_LIBRARIES internal::AODProducerWorkflow O2::Version ) + o2_add_executable( standalone-aod-producer COMPONENT_NAME reco diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index dfc295f6ae2d9..297fe21a45699 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -34,6 +34,7 @@ #include "ReconstructionDataFormats/VtxTrackIndex.h" #include "SimulationDataFormat/MCCompLabel.h" #include "Steer/MCKinematicsReader.h" +#include "TMap.h" #include "TStopwatch.h" #include @@ -191,7 +192,7 @@ typedef boost::unordered_map Triple class AODProducerWorkflowDPL : public Task { public: - AODProducerWorkflowDPL(GID::mask_t src, std::shared_ptr dataRequest) : mInputSources(src), mDataRequest(dataRequest) {} + AODProducerWorkflowDPL(GID::mask_t src, std::shared_ptr dataRequest, std::string resFile) : mInputSources(src), mDataRequest(dataRequest), mResFile(resFile) {} ~AODProducerWorkflowDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -204,6 +205,8 @@ class AODProducerWorkflowDPL : public Task int64_t mTFNumber{-1}; int mTruncate{1}; int mRecoOnly{0}; + TString mResFile{"AO2D"}; + std::string mProdTags{"LHC21Axx,pass1,LHC15o,pass1"}; TStopwatch mTimer; // unordered map connects global indices and table indices of barrel tracks @@ -213,6 +216,9 @@ class AODProducerWorkflowDPL : public Task TripletsMap_t mToStore; + // MC production metadata holder + TMap mMetaData; + std::shared_ptr mDataRequest; // truncation is enabled by default @@ -352,7 +358,7 @@ class AODProducerWorkflowDPL : public Task }; /// create a processor spec -framework::DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool useMC); +framework::DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool useMC, std::string resFile); } // namespace o2::aodproducer diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 59d756d3e9c86..098e9dd5d064a 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -52,10 +52,13 @@ #include "SimulationDataFormat/MCEventLabel.h" #include "SimulationDataFormat/MCTrack.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "O2Version.h" #include "TMath.h" #include "MathUtils/Utils.h" #include "Math/SMatrix.h" -#include +#include "TMatrixD.h" +#include "TString.h" +#include "TObjString.h" #include #include #include @@ -299,11 +302,6 @@ void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID, } else { auto contributorsGID = data.getSingleDetectorRefs(trackIndex); const auto& trackPar = data.getTrackParam(trackIndex); - if (contributorsGID[GIndex::Source::ITS].isIndexSet() || contributorsGID[GIndex::Source::ITSAB].isIndexSet()) { - int nClusters = itsTracks[contributorsGID[GIndex::ITS].getIndex()].getNClusters(); - float chi2 = itsTracks[contributorsGID[GIndex::ITS].getIndex()].getChi2(); - extraInfoHolder.itsChi2NCl = nClusters != 0 ? chi2 / (float)nClusters : 0; - } if (contributorsGID[GIndex::Source::ITS].isIndexSet()) { extraInfoHolder.itsClusterMap = itsTracks[contributorsGID[GIndex::ITS].getIndex()].getPattern(); } else if (contributorsGID[GIndex::Source::ITSAB].isIndexSet()) { // this is an ITS-TPC afterburner contributor @@ -658,14 +656,8 @@ void AODProducerWorkflowDPL::fillMCParticlesTable(o2::steer::MCKinematicsReader& } int statusCode = 0; uint8_t flags = 0; - if (!mcParticles[particle].isPrimary()) { - flags |= o2::aod::mcparticle::enums::ProducedByTransport; // mark as produced by transport - statusCode = mcParticles[particle].getProcess(); - } else { - statusCode = mcParticles[particle].getStatusCode(); - } if (source == 0) { - flags |= o2::aod::mcparticle::enums::FromBackgroundEvent; // mark as particle from background event + flags |= 1 << 1; // mark as particle from background event } float weight = 0.f; int mcMother0 = mcParticles[particle].getMotherTrackId(); @@ -857,6 +849,7 @@ uint8_t AODProducerWorkflowDPL::getTRDPattern(const o2::trd::TrackTRD& track) void AODProducerWorkflowDPL::init(InitContext& ic) { mTimer.Stop(); + mProdTags = ic.options().get("prod-tags"); mTFNumber = ic.options().get("aod-timeframe-id"); mRecoOnly = ic.options().get("reco-mctracks-only"); mTruncate = ic.options().get("enable-truncation"); @@ -903,6 +896,45 @@ void AODProducerWorkflowDPL::init(InitContext& ic) // Needed by MCH track extrapolation o2::base::GeometryManager::loadGeometry(); + // writing metadata if it's not yet in AOD file + // note: `--aod-writer-resmode "UPDATE"` have to be used, + // so that metadata is not overwritten + mResFile += ".root"; + auto* fResFile = TFile::Open(mResFile, "UPDATE"); + if (fResFile) { + if (!fResFile->FindObjectAny("metaData")) { + std::vector vTags; + std::stringstream ss(mProdTags); + while (ss.good()) { + std::string substr; + std::getline(ss, substr, ','); + vTags.emplace_back(substr); + } + // assuming all tags passed as in `prod-tags` description + TString LPMProdTag = vTags[0]; + TString anchorPass = vTags[1]; + TString anchorProd = vTags[2]; + TString recoPass = vTags[3]; + // populating metadata map + mMetaData.Add(new TObjString("DataType"), new TObjString("MC")); + mMetaData.Add(new TObjString("Run"), new TObjString("3")); + TString converterVersion = "o2 "; + converterVersion += o2::fullVersion(); + converterVersion += " ; root "; + converterVersion += ROOT_RELEASE; + mMetaData.Add(new TObjString("Run3ConverterVersion"), new TObjString(converterVersion)); + mMetaData.Add(new TObjString("RecoPassName"), new TObjString(recoPass)); + mMetaData.Add(new TObjString("AnchorProduction"), new TObjString(anchorProd)); + mMetaData.Add(new TObjString("AnchorPassName"), new TObjString(anchorPass)); + mMetaData.Add(new TObjString("LPMProductionTag"), new TObjString(LPMProdTag)); + LOGF(info, "Metadata: writing into %s", mResFile); + fResFile->WriteObject(&mMetaData, "metaData"); + } else { + LOGF(info, "Metadata: target file not found or metadata is already written"); + } + fResFile->Close(); + } + mTimer.Reset(); } @@ -1324,7 +1356,7 @@ void AODProducerWorkflowDPL::endOfStream(EndOfStreamContext& ec) mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool useMC) +DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool useMC, std::string resFile) { std::vector outputs; auto dataRequest = std::make_shared(); @@ -1363,10 +1395,11 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool useMC) "aod-producer-workflow", dataRequest->inputs, outputs, - AlgorithmSpec{adaptFromTask(src, dataRequest)}, + AlgorithmSpec{adaptFromTask(src, dataRequest, resFile)}, Options{ ConfigParamSpec{"aod-timeframe-id", VariantType::Int64, -1L, {"Set timeframe number"}}, ConfigParamSpec{"enable-truncation", VariantType::Int, 1, {"Truncation parameter: 1 -- on, != 1 -- off"}}, + ConfigParamSpec{"prod-tags", VariantType::String, "LHC21Axx,pass1,LHC15o,pass1", {"Comma separated list of production tags: `LPMProductionTag,AnchorPassName,AnchorProduction,RecoPassName`"}}, ConfigParamSpec{"reco-mctracks-only", VariantType::Int, 0, {"Store only reconstructed MC tracks and their mothers/daughters. 0 -- off, != 0 -- on"}}}}; } diff --git a/Detectors/AOD/src/aod-producer-workflow.cxx b/Detectors/AOD/src/aod-producer-workflow.cxx index 16c6ac8641ccd..5870875a56efd 100644 --- a/Detectors/AOD/src/aod-producer-workflow.cxx +++ b/Detectors/AOD/src/aod-producer-workflow.cxx @@ -42,12 +42,13 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); auto useMC = !configcontext.options().get("disable-mc"); + auto resFile = configcontext.options().get("aod-writer-resfile"); GID::mask_t allowedSrc = GID::getSourcesMask("ITS,MFT,MCH,TPC,ITS-TPC,ITS-TPC-TOF,TPC-TOF,MFT-MCH,FT0,FV0,FDD,TPC-TRD,ITS-TPC-TRD,FT0,FV0,FDD,ZDC"); GID::mask_t src = allowedSrc & GID::getSourcesMask(configcontext.options().get("info-sources")); WorkflowSpec specs; - specs.emplace_back(o2::aodproducer::getAODProducerWorkflowSpec(src, useMC)); + specs.emplace_back(o2::aodproducer::getAODProducerWorkflowSpec(src, useMC, resFile)); o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, src, src, src, useMC, src); o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC);