diff --git a/Detectors/AOD/CMakeLists.txt b/Detectors/AOD/CMakeLists.txt index 9cab93768602f..238591fed5a55 100644 --- a/Detectors/AOD/CMakeLists.txt +++ b/Detectors/AOD/CMakeLists.txt @@ -26,13 +26,14 @@ o2_add_library( O2::Steer O2::TOFWorkflow O2::TPCWorkflow + O2::CCDB ) o2_add_executable( workflow COMPONENT_NAME aod-producer SOURCES src/aod-producer-workflow.cxx - PUBLIC_LINK_LIBRARIES O2::AODProducerWorkflow + PUBLIC_LINK_LIBRARIES O2::AODProducerWorkflow ) o2_add_executable( diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 77053713e74a0..c36b47bc2800c 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -15,10 +15,12 @@ #include "DataFormatsFT0/RecPoints.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "ReconstructionDataFormats/TrackTPCITS.h" #include "TStopwatch.h" +#include #include #include @@ -50,7 +52,26 @@ using TracksTable = o2::soa::Table; + o2::aod::track::Rho1PtTgl, + o2::aod::track::TPCInnerParam, + o2::aod::track::Flags, + o2::aod::track::ITSClusterMap, + o2::aod::track::TPCNClsFindable, + o2::aod::track::TPCNClsFindableMinusFound, + o2::aod::track::TPCNClsFindableMinusCrossedRows, + o2::aod::track::TPCNClsShared, + o2::aod::track::TRDPattern, + o2::aod::track::ITSChi2NCl, + o2::aod::track::TPCChi2NCl, + o2::aod::track::TRDChi2, + o2::aod::track::TOFChi2, + o2::aod::track::TPCSignal, + o2::aod::track::TRDSignal, + o2::aod::track::TOFSignal, + o2::aod::track::Length, + o2::aod::track::TOFExpMom, + o2::aod::track::TrackEtaEMCAL, + o2::aod::track::TrackPhiEMCAL>; class AODProducerWorkflowDPL : public Task { @@ -71,6 +92,7 @@ class AODProducerWorkflowDPL : public Task uint64_t minGlBC = INT64_MAX; void findMinMaxBc(gsl::span& ft0RecPoints, gsl::span& tracksITSTPC); + int64_t getTFNumber(uint64_t firstVtxGlBC, int runNumber); template void fillTracksTable(const TracksType& tracks, std::vector& vCollRefs, const TracksCursorType& tracksCursor, int trackType); diff --git a/Detectors/AOD/src/AODProducerWorkflow.cxx b/Detectors/AOD/src/AODProducerWorkflow.cxx index cc1d052ab2626..51a46f46f5cd0 100644 --- a/Detectors/AOD/src/AODProducerWorkflow.cxx +++ b/Detectors/AOD/src/AODProducerWorkflow.cxx @@ -35,14 +35,13 @@ framework::WorkflowSpec getAODProducerWorkflow() { // TODO: // switch to configurable parameters (?) - bool useFT0 = true; bool useMC = false; // FIXME: // switch (?) from o2::ft0::getReconstructionSpec to RecPointReader // (which does not return RECCHDATA at the moment) framework::WorkflowSpec specs{ - o2::vertexing::getPrimaryVertexingSpec(useFT0, useMC), + o2::vertexing::getPrimaryVertexReaderSpec(useMC), o2::globaltracking::getTrackTPCITSReaderSpec(useMC), o2::its::getITSTrackReaderSpec(useMC), o2::tpc::getTPCTrackReaderSpec(useMC), diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index b9eabb7f7df9b..ccd90acc63d75 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -15,7 +15,10 @@ #include "DataFormatsITS/TrackITS.h" #include "DataFormatsTPC/TrackTPC.h" #include "DetectorsCommonDataFormats/NameConf.h" +#include +#include "CommonDataFormat/InteractionRecord.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/DataTypes.h" #include "Framework/InputRecordWalker.h" @@ -54,8 +57,8 @@ void AODProducerWorkflowDPL::findMinMaxBc(gsl::span& f } for (auto& trackITSTPC : tracksITSTPC) { - Double_t timeStamp = trackITSTPC.getTimeMUS().getTimeStamp() * 1.E3; // ms to ns - uint64_t bc = (int)(timeStamp / o2::constants::lhc::LHCBunchSpacingNS); + Double_t timeStamp = trackITSTPC.getTimeMUS().getTimeStamp() * 1.E3; // mus to ns + uint64_t bc = (uint64_t)(timeStamp / o2::constants::lhc::LHCBunchSpacingNS); if (minGlBC > bc) { minGlBC = bc; } @@ -65,12 +68,97 @@ void AODProducerWorkflowDPL::findMinMaxBc(gsl::span& f } } +int64_t AODProducerWorkflowDPL::getTFNumber(uint64_t firstVtxGlBC, int runNumber) +{ + // FIXME: + // check if this code is correct + + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); + o2::ccdb::CcdbApi ccdb_api; + const std::string rct_path = "RCT/RunInformation/"; + const std::string start_orbit_path = "Trigger/StartOrbit"; + const std::string url = "http://ccdb-test.cern.ch:8080"; + + mgr.setURL(url); + ccdb_api.init(url); + + std::map* mapStartOrbit = mgr.get>(start_orbit_path); + int64_t ts = 0; + std::map metadata; + std::map headers; + const std::string run_path = Form("%s/%i", rct_path.data(), runNumber); + headers = ccdb_api.retrieveHeaders(run_path, metadata, -1); + ts = atol(headers["SOR"].c_str()); + + // ccdb returns timestamp in mus + // mus to ms + ts = ts / 1000; + + // firstRec --> calculated using `minimal` global BC in the simulation (see AODProducerWorkflowDPL::findMinMaxBc) + // firstVtxGlBC --> calculated using global BC correspinding to the first prim. vertex + + uint32_t initialOrbit = mapStartOrbit->at(runNumber); + uint16_t firstRecBC = minGlBC % o2::constants::lhc::LHCMaxBunches; + uint32_t firstRecOrbit = minGlBC / o2::constants::lhc::LHCMaxBunches; + uint16_t firstVtxBC = firstVtxGlBC % o2::constants::lhc::LHCMaxBunches; + uint32_t firstVtxOrbit = firstVtxGlBC / o2::constants::lhc::LHCMaxBunches; + const o2::InteractionRecord firstRec(firstRecBC, firstRecOrbit); + const o2::InteractionRecord firstVtx(firstVtxBC, firstVtxOrbit); + ts += (firstVtx - firstRec).bc2ns() / 1000000; + + return ts; +}; + template void AODProducerWorkflowDPL::fillTracksTable(const TracksType& tracks, std::vector& vCollRefs, const TracksCursorType& tracksCursor, int trackType) { for (int i = 0; i < tracks.size(); i++) { auto& track = tracks[i]; int collisionID = vCollRefs[i]; + + float tpcInnerParam = 0.f; + uint32_t flags = 0; + uint8_t itsClusterMap = 0; + uint8_t tpcNClsFindable = 0; + int8_t tpcNClsFindableMinusFound = 0; + int8_t tpcNClsFindableMinusCrossedRows = 0; + uint8_t tpcNClsShared = 0; + uint8_t trdPattern = 0; + float itsChi2NCl = -999.f; + float tpcChi2NCl = -999.f; + float trdChi2 = -999.f; + float tofChi2 = -999.f; + float tpcSignal = -999.f; + float trdSignal = -999.f; + float tofSignal = -999.f; + float length = -999.f; + float tofExpMom = -999.f; + float trackEtaEMCAL = -999.f; + float trackPhiEMCAL = -999.f; + + // filling available columns for different track types + // FIXME: + // is there a more nice/simple way to do this? + std::variant tmp = track; + std::visit( + overloaded{ + [&](o2::its::TrackITS itsTrack) { + itsClusterMap = itsTrack.getPattern(); + }, + [&](o2::tpc::TrackTPC tpcTrack) { + tpcChi2NCl = tpcTrack.getChi2(); + // FIXME: + // what values to fill here? + tpcSignal = tpcTrack.getdEdx().dEdxTotTPC; + tpcNClsFindable = tpcTrack.getNClusters(); + }, + [&](o2::dataformats::TrackTPCITS itsTpcTrack) { + LOG(DEBUG) << "TrackTPCITS: check"; + }}, + tmp); + + // TODO: + // fill trackextra table tracksCursor(0, collisionID, trackType, @@ -95,7 +183,26 @@ void AODProducerWorkflowDPL::fillTracksTable(const TracksType& tracks, std::vect (Char_t)(128. * track.getSigma1PtY() / track.getSigma1Pt2() / track.getSigmaY2()), (Char_t)(128. * track.getSigma1PtZ() / track.getSigma1Pt2() / track.getSigmaZ2()), (Char_t)(128. * track.getSigma1PtSnp() / track.getSigma1Pt2() / track.getSigmaSnp2()), - (Char_t)(128. * track.getSigma1PtTgl() / track.getSigma1Pt2() / track.getSigmaTgl2())); + (Char_t)(128. * track.getSigma1PtTgl() / track.getSigma1Pt2() / track.getSigmaTgl2()), + tpcInnerParam, + flags, + itsClusterMap, + tpcNClsFindable, + tpcNClsFindableMinusFound, + tpcNClsFindableMinusCrossedRows, + tpcNClsShared, + trdPattern, + itsChi2NCl, + tpcChi2NCl, + trdChi2, + tofChi2, + tpcSignal, + trdSignal, + tofSignal, + length, + tofExpMom, + trackEtaEMCAL, + trackPhiEMCAL); } } @@ -134,12 +241,12 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto& ft0Builder = pc.outputs().make(Output{"AOD", "FT0"}); auto& mcCollisionsBuilder = pc.outputs().make(Output{"AOD", "MCCOLLISION"}); auto& tracksBuilder = pc.outputs().make(Output{"AOD", "TRACK"}); + auto& timeFrameNumberBuilder = pc.outputs().make(Output{"TFN", "TFNumber"}); - // TODO: - // add FV0A, FV0C, FDD tables - // auto& fv0aBuilder = pc.outputs().make(Output{"AOD", "FV0A"}); - // auto& fv0cBuilder = pc.outputs().make(Output{"AOD", "FV0C"}); - // auto& fddBuilder = pc.outputs().make(Output{"AOD", "FDD"}); + auto& fv0aBuilder = pc.outputs().make(Output{"AOD", "FV0A"}); + auto& fv0cBuilder = pc.outputs().make(Output{"AOD", "FV0C"}); + auto& fddBuilder = pc.outputs().make(Output{"AOD", "FDD"}); + auto& zdcBuilder = pc.outputs().make(Output{"AOD", "ZDC"}); auto bcCursor = bcBuilder.cursor(); auto collisionsCursor = collisionsBuilder.cursor(); @@ -147,19 +254,76 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto mcCollisionsCursor = mcCollisionsBuilder.cursor(); auto tracksCursor = tracksBuilder.cursor(); + auto fv0aCursor = fv0aBuilder.cursor(); + auto fv0cCursor = fv0cBuilder.cursor(); + auto fddCursor = fddBuilder.cursor(); + auto zdcCursor = zdcBuilder.cursor(); + + findMinMaxBc(ft0RecPoints, tracksITSTPC); + + std::map mGlobBC2BCID; + // TODO: - // add FV0A, FV0C, FDD tables - // auto fv0aCursor = fv0aBuilder.cursor(); - // auto fv0cCursor = fv0cBuilder.cursor(); - // auto fddCursor = fddBuilder.cursor(); - - // float dummyfv0AmplA[48] = {0.}; - // float dummyfv0AmplC[32] = {0.}; - // float dummyfddAmplA[4] = {0.}; - // float dummyfddAmplC[4] = {0.}; - // fv0aCursor(0, (uint64_t)0, dummyfv0AmplA, 0.f, (uint8_t)0); - // fv0cCursor(0, (uint64_t)0, dummyfv0AmplC, 0.f); - // fddCursor(0, (uint64_t)0, dummyfddAmplA, dummyfddAmplC, 0.f, 0.f, (uint8_t)0); + // get real run number and triggerMask + int runNumber = 244918; + uint64_t triggerMask = 1; + + // filling BC table and map + for (uint64_t i = 0; i <= maxGlBC - minGlBC; i++) { + bcCursor(0, + runNumber, + minGlBC + i, + triggerMask); + mGlobBC2BCID[minGlBC + i] = i; + } + + // TODO: + // add real FV0A, FV0C, FDD, ZDC tables instead of dummies + float dummyfv0AmplA[48] = {0.}; + fv0aCursor(0, + (uint64_t)0, + dummyfv0AmplA, + 0.f, + (uint8_t)0); + + float dummyfv0AmplC[32] = {0.}; + fv0cCursor(0, + (uint64_t)0, + dummyfv0AmplC, + 0.f); + + float dummyfddAmplA[4] = {0.}; + float dummyfddAmplC[4] = {0.}; + fddCursor(0, + (uint64_t)0, + dummyfddAmplA, + dummyfddAmplC, + 0.f, + 0.f, + (uint8_t)0); + + float dummyEnergySectorZNA[4] = {0.}; + float dummyEnergySectorZNC[4] = {0.}; + float dummyEnergySectorZPA[4] = {0.}; + float dummyEnergySectorZPC[4] = {0.}; + zdcCursor(0, + (uint64_t)0, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + dummyEnergySectorZNA, + dummyEnergySectorZNC, + dummyEnergySectorZPA, + dummyEnergySectorZPC, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f, + 0.f); o2::steer::MCKinematicsReader mcReader("collisioncontext.root"); const auto context = mcReader.getDigitizationContext(); @@ -170,7 +334,6 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) LOG(INFO) << "FOUND " << parts.size() << " parts"; // TODO: - // change index to BCId (?) // figure out generatorID and collision weight int index = 0; int generatorID = 0; @@ -183,8 +346,9 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto eventID = colparts[0].entryID; auto sourceID = colparts[0].sourceID; auto& header = mcReader.getMCEventHeader(sourceID, eventID); + uint64_t globalBC = rec.bc + rec.orbit * o2::constants::lhc::LHCMaxBunches; mcCollisionsCursor(0, - index, + mGlobBC2BCID.at(globalBC), generatorID, header.GetX(), header.GetY(), @@ -195,24 +359,6 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) index++; } - findMinMaxBc(ft0RecPoints, tracksITSTPC); - - std::map mGlobBC2BCID; - - // TODO: - // get real run number and triggerMask - int runNumber = 244918; - uint64_t triggerMask = 1; - - // filling BC table and map - for (uint64_t i = 0; i <= maxGlBC - minGlBC; i++) { - bcCursor(0, - runNumber, - minGlBC + i, - triggerMask); - mGlobBC2BCID[minGlBC + i] = i; - } - // vector of FT0 amplitudes std::vector vAmplitudes(208, 0.); // filling FT0 table @@ -229,7 +375,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) std::copy(vAmplitudes.begin() + 96, vAmplitudes.end(), aAmplitudesC); uint64_t globalBC = ft0RecPoint.getInteractionRecord().orbit * o2::constants::lhc::LHCMaxBunches + ft0RecPoint.getInteractionRecord().bc; ft0Cursor(0, - mGlobBC2BCID[globalBC], + mGlobBC2BCID.at(globalBC), aAmplitudesA, aAmplitudesC, ft0RecPoint.getCollisionTimeA() / 1E3, // ps to ns @@ -242,17 +388,27 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) std::vector vCollRefsTPC(tracksTPC.size(), -1); std::vector vCollRefsTPCITS(tracksITSTPC.size(), -1); + // global bc of the 1st vertex for TF number + uint64_t firstVtxGlBC; + // filling collisions table int collisionID = 0; for (auto& vertex : primVertices) { auto& cov = vertex.getCov(); auto& timeStamp = vertex.getTimeStamp(); - Double_t tsTimeStamp = timeStamp.getTimeStamp() * 1E3; // ms to ns + Double_t tsTimeStamp = timeStamp.getTimeStamp() * 1E3; // mus to ns + // FIXME: + // should use IRMin and IRMax for globalBC calculation uint64_t globalBC = tsTimeStamp / o2::constants::lhc::LHCBunchSpacingNS; - int BCid = mGlobBC2BCID[globalBC]; + + if (collisionID == 0) { + firstVtxGlBC = globalBC; + } + + int BCid = mGlobBC2BCID.at(globalBC); // TODO: // get real collision time mask - int collisionTimeMask = 1; + int collisionTimeMask = 0; collisionsCursor(0, BCid, vertex.getX(), @@ -272,6 +428,9 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto trackRef = primVer2TRefs[collisionID]; int start = trackRef.getFirstEntryOfSource(0); int ntracks = trackRef.getEntriesOfSource(0); + + // FIXME: + // `track<-->vertex` ambiguity is not accounted for in this code for (int ti = 0; ti < ntracks; ti++) { auto trackIndex = primVerGIs[start + ti]; const auto source = trackIndex.getSource(); @@ -300,6 +459,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) fillTracksTable(tracksITSTPC, vCollRefsTPCITS, tracksCursor, o2::vertexing::GIndex::Source::TPCITS); // fTrackType = 0 } + timeFrameNumberBuilder = getTFNumber(firstVtxGlBC, runNumber); + mTimer.Stop(); } @@ -316,8 +477,8 @@ DataProcessorSpec getAODProducerWorkflowSpec() inputs.emplace_back("ft0ChData", "FT0", "RECCHDATA", 0, Lifetime::Timeframe); inputs.emplace_back("ft0RecPoints", "FT0", "RECPOINTS", 0, Lifetime::Timeframe); - inputs.emplace_back("primVer2TRefs", "GLO", "PVTX_CONTIDREFS", 0, Lifetime::Timeframe); - inputs.emplace_back("primVerGIs", "GLO", "PVTX_CONTID", 0, Lifetime::Timeframe); + inputs.emplace_back("primVer2TRefs", "GLO", "PVTX_TRMTCREFS", 0, Lifetime::Timeframe); + inputs.emplace_back("primVerGIs", "GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe); inputs.emplace_back("primVertices", "GLO", "PVTX", 0, Lifetime::Timeframe); inputs.emplace_back("trackITS", "ITS", "TRACKS", 0, Lifetime::Timeframe); inputs.emplace_back("tracksITSTPC", "GLO", "TPCITS", 0, Lifetime::Timeframe); @@ -328,12 +489,14 @@ DataProcessorSpec getAODProducerWorkflowSpec() outputs.emplace_back(OutputLabel{"O2ft0"}, "AOD", "FT0", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2mccollision"}, "AOD", "MCCOLLISION", 0, Lifetime::Timeframe); outputs.emplace_back(OutputLabel{"O2track"}, "AOD", "TRACK", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputSpec{"TFN", "TFNumber"}); // TODO: // add FV0A, FV0C, FDD tables - // outputs.emplace_back(OutputLabel{"O2fv0a"}, "AOD", "FV0A", 0, Lifetime::Timeframe); - // outputs.emplace_back(OutputLabel{"O2fv0c"}, "AOD", "FV0C", 0, Lifetime::Timeframe); - // outputs.emplace_back(OutputLabel{"O2fdd"}, "AOD", "FDD", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2fv0a"}, "AOD", "FV0A", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2fv0c"}, "AOD", "FV0C", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2fdd"}, "AOD", "FDD", 0, Lifetime::Timeframe); + outputs.emplace_back(OutputLabel{"O2zdc"}, "AOD", "ZDC", 0, Lifetime::Timeframe); return DataProcessorSpec{ "aod-producer-workflow",