From 33f2d0cf4c01ead52e1a4c8b7fb254a0207f62c2 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:51:50 +0100 Subject: [PATCH 0001/2997] DPL: replace LOG with Signposts (#12947) Move a bunch of log messages to use signposts for: * AsyncQueue * TimesliceIndex * CommonServices * DataRelayer Also modified the async queue to get the oldest possible timeslice as index, so that we can use that to track executions. --- Framework/Core/include/Framework/AsyncQueue.h | 8 ++-- Framework/Core/src/AsyncQueue.cxx | 39 +++++++++++----- Framework/Core/src/CommonServices.cxx | 24 ++++++---- Framework/Core/src/DataProcessingDevice.cxx | 20 ++++++-- Framework/Core/src/DataRelayer.cxx | 12 +++++ Framework/Core/src/TimesliceIndex.cxx | 46 ++++++++++++++----- Framework/Core/test/test_AsyncQueue.cxx | 28 +++++------ 7 files changed, 123 insertions(+), 54 deletions(-) diff --git a/Framework/Core/include/Framework/AsyncQueue.h b/Framework/Core/include/Framework/AsyncQueue.h index 37971fbe03bfb..6945c2a5ab1da 100644 --- a/Framework/Core/include/Framework/AsyncQueue.h +++ b/Framework/Core/include/Framework/AsyncQueue.h @@ -32,8 +32,9 @@ struct AsyncTaskId { /// An actuatual task to be executed struct AsyncTask { - // The task to be executed - std::function task; + // The task to be executed. Id can be used as unique + // id for the signpost in the async_queue stream. + std::function task; // The associated task spec AsyncTaskId id = {-1}; TimesliceId timeslice = {TimesliceId::INVALID}; @@ -49,10 +50,11 @@ struct AsyncQueue { }; struct AsyncQueueHelpers { + using AsyncCallback = std::function; static AsyncTaskId create(AsyncQueue& queue, AsyncTaskSpec spec); // Schedule a task with @a taskId to be executed whenever the timeslice // is past timeslice. If debounce is provided, only execute the task - static void post(AsyncQueue& queue, AsyncTaskId taskId, std::function task, TimesliceId timeslice, int64_t debounce = 0); + static void post(AsyncQueue& queue, AsyncTaskId taskId, AsyncCallback task, TimesliceId timeslice, int64_t debounce = 0); /// Run all the tasks which are older than the oldestPossible timeslice /// executing them by: /// 1. sorting the tasks by timeslice diff --git a/Framework/Core/src/AsyncQueue.cxx b/Framework/Core/src/AsyncQueue.cxx index 44115d4985e91..36c0c17009f82 100644 --- a/Framework/Core/src/AsyncQueue.cxx +++ b/Framework/Core/src/AsyncQueue.cxx @@ -10,9 +10,11 @@ // or submit itself to any jurisdiction. #include "Framework/AsyncQueue.h" -#include "Framework/Logger.h" +#include "Framework/Signpost.h" #include +O2_DECLARE_DYNAMIC_LOG(async_queue); + namespace o2::framework { auto AsyncQueueHelpers::create(AsyncQueue& queue, AsyncTaskSpec spec) -> AsyncTaskId @@ -23,7 +25,7 @@ auto AsyncQueueHelpers::create(AsyncQueue& queue, AsyncTaskSpec spec) -> AsyncTa return id; } -auto AsyncQueueHelpers::post(AsyncQueue& queue, AsyncTaskId id, std::function task, TimesliceId timeslice, int64_t debounce) -> void +auto AsyncQueueHelpers::post(AsyncQueue& queue, AsyncTaskId id, AsyncCallback task, TimesliceId timeslice, int64_t debounce) -> void { AsyncTask taskToPost; taskToPost.task = task; @@ -38,7 +40,8 @@ auto AsyncQueueHelpers::run(AsyncQueue& queue, TimesliceId oldestPossible) -> vo if (queue.tasks.empty()) { return; } - LOGP(debug, "Attempting at running {} tasks", queue.tasks.size()); + O2_SIGNPOST_ID_GENERATE(opid, async_queue); + O2_SIGNPOST_START(async_queue, opid, "run", "Attempting at running %zu tasks with oldestPossible timeframe %zu", queue.tasks.size(), oldestPossible.value); std::vector order; order.resize(queue.tasks.size()); std::iota(order.begin(), order.end(), 0); @@ -47,6 +50,10 @@ auto AsyncQueueHelpers::run(AsyncQueue& queue, TimesliceId oldestPossible) -> vo if (task.timeslice.value <= oldestPossible.value) { task.runnable = true; } + O2_SIGNPOST_EVENT_EMIT(async_queue, opid, "run", + "Task %d (timeslice %zu), score %d, debounce %d is %{public}s when oldestPossible timeframe is %zu", + task.id.value, task.timeslice.value, queue.prototypes[task.id.value].score, task.debounce, + task.runnable ? "runnable" : "not runnable", oldestPossible.value); } // Sort by runnable, timeslice, then priority and finally debounce @@ -69,34 +76,43 @@ auto AsyncQueueHelpers::run(AsyncQueue& queue, TimesliceId oldestPossible) -> vo return queue.tasks[a].timeslice.value > queue.tasks[b].timeslice.value; } }); + for (auto i : order) { if (queue.tasks[i].runnable) { - LOGP(debug, "AsyncQueue: Running task {}, timeslice {}, score {}, debounce {}", queue.tasks[i].id.value, queue.tasks[i].timeslice.value, queue.prototypes[queue.tasks[i].id.value].score, queue.tasks[i].debounce); + O2_SIGNPOST_EVENT_EMIT(async_queue, opid, "run", "Running task %d (%d), (timeslice %zu), score %d, debounce %d", queue.tasks[i].id.value, i, queue.tasks[i].timeslice.value, queue.prototypes[queue.tasks[i].id.value].score, queue.tasks[i].debounce); } else { - LOGP(debug, "AsyncQueue: Skipping task {}, timeslice {}, score {}, debounce {}", queue.tasks[i].id.value, queue.tasks[i].timeslice.value, queue.prototypes[queue.tasks[i].id.value].score, queue.tasks[i].debounce); + O2_SIGNPOST_EVENT_EMIT(async_queue, opid, "run", "Skipping task %d (%d) (timeslice %zu), score %d, debounce %d", queue.tasks[i].id.value, i, queue.tasks[i].timeslice.value, queue.prototypes[queue.tasks[i].id.value].score, queue.tasks[i].debounce); } } // Keep only the tasks with the highest debounce value for a given id auto newEnd = std::unique(order.begin(), order.end(), [&queue](int a, int b) { return queue.tasks[a].runnable == queue.tasks[b].runnable && queue.tasks[a].id.value == queue.tasks[b].id.value && queue.tasks[a].debounce >= 0 && queue.tasks[b].debounce >= 0; }); + for (auto ii = newEnd; ii != order.end(); ii++) { + O2_SIGNPOST_EVENT_EMIT(async_queue, opid, "dropping", "Dropping task %d for timeslice %zu", queue.tasks[*ii].id.value, queue.tasks[*ii].timeslice.value); + } order.erase(newEnd, order.end()); if (order.empty() && queue.tasks.size() > 0) { - LOGP(debug, "AsyncQueue: not running iteration {} timeslice {} pending {}.", order.size(), queue.iteration, oldestPossible.value, queue.tasks.size()); + O2_SIGNPOST_END(async_queue, opid, "run", "Not running iteration %zu pending %zu.", + queue.iteration, queue.tasks.size()); return; } else if (order.empty()) { + O2_SIGNPOST_END(async_queue, opid, "run", "Not running iteration %zu. No tasks.", queue.iteration); return; } - LOGP(debug, "AsyncQueue: Running {} tasks in iteration {} timeslice {}", order.size(), queue.iteration, oldestPossible.value); - bool obsolete = true; + O2_SIGNPOST_EVENT_EMIT(async_queue, opid, "run", "Running %zu tasks in iteration %zu", order.size(), queue.iteration); + int runCount = 0; for (auto i : order) { if (queue.tasks[i].runnable) { + runCount++; // If a task is runable, we can run the task and remove it from the queue - LOGP(debug, "Running task {} ({})", queue.prototypes[queue.tasks[i].id.value].name, i); - queue.tasks[i].task(); - LOGP(debug, "Done running {}", i); + O2_SIGNPOST_EVENT_EMIT(async_queue, opid, "run", "Running task %{public}s (%d) for timeslice %zu", + queue.prototypes[queue.tasks[i].id.value].name.c_str(), i, + queue.tasks[i].timeslice.value); + queue.tasks[i].task(opid.value); + O2_SIGNPOST_EVENT_EMIT(async_queue, opid, "run", "Done running %d", i); } } // Remove all runnable tasks regardless they actually @@ -105,6 +121,7 @@ auto AsyncQueueHelpers::run(AsyncQueue& queue, TimesliceId oldestPossible) -> vo return task.runnable; }), queue.tasks.end()); + O2_SIGNPOST_END(async_queue, opid, "run", "Done running %d/%zu tasks", runCount, order.size()); } auto AsyncQueueHelpers::reset(AsyncQueue& queue) -> void diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 0d0828729ef42..7e16c03ef69e1 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -82,6 +82,7 @@ using Value = o2::monitoring::tags::Value; O2_DECLARE_DYNAMIC_LOG(data_processor_context); O2_DECLARE_DYNAMIC_LOG(stream_context); +O2_DECLARE_DYNAMIC_LOG(async_queue); namespace o2::framework { @@ -580,11 +581,14 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() (uint64_t)oldestPossibleOutput.timeslice.value, oldestPossibleOutput.slot.index == -1 ? "channel" : "slot", (uint64_t)(oldestPossibleOutput.slot.index == -1 ? oldestPossibleOutput.channel.value : oldestPossibleOutput.slot.index)); + O2_SIGNPOST_EVENT_EMIT_ERROR(data_processor_context, cid, "oldest_possible_timeslice", "Ordered active %d", decongestion->orderedCompletionPolicyActive); if (decongestion->orderedCompletionPolicyActive) { auto oldNextTimeslice = decongestion->nextTimeslice; decongestion->nextTimeslice = std::max(decongestion->nextTimeslice, (int64_t)oldestPossibleOutput.timeslice.value); + timesliceIndex.updateOldestPossibleOutput(); + O2_SIGNPOST_EVENT_EMIT_ERROR(data_processor_context, cid, "oldest_possible_timeslice", "Next timeslice %" PRIi64, decongestion->nextTimeslice); if (oldNextTimeslice != decongestion->nextTimeslice) { - LOGP(error, "Some Lifetime::Timeframe data got dropped starting at {}", oldNextTimeslice); + O2_SIGNPOST_EVENT_EMIT_ERROR(data_processor_context, cid, "oldest_possible_timeslice", "Some Lifetime::Timeframe data got dropped starting at %" PRIi64, oldNextTimeslice); timesliceIndex.rescan(); } } @@ -630,7 +634,7 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() auto oldestPossibleOutput = relayer.getOldestPossibleOutput(); if (oldestPossibleOutput.timeslice.value == decongestion.lastTimeslice) { - O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Not sending already sent value: %" PRIu64, (uint64_t)oldestPossibleOutput.timeslice.value); + O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Synchronous: Not sending already sent value: %" PRIu64, (uint64_t)oldestPossibleOutput.timeslice.value); return; } if (oldestPossibleOutput.timeslice.value < decongestion.lastTimeslice) { @@ -646,14 +650,15 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Queueing oldest possible timeslice %" PRIu64 " propagation for execution.", (uint64_t)oldestPossibleOutput.timeslice.value); AsyncQueueHelpers::post( - queue, decongestion.oldestPossibleTimesliceTask, [ref = services, oldestPossibleOutput, &decongestion, &proxy, &spec, device, ×liceIndex]() { - O2_SIGNPOST_ID_FROM_POINTER(cid, data_processor_context, &decongestion); + queue, decongestion.oldestPossibleTimesliceTask, [ref = services, oldestPossibleOutput, &decongestion, &proxy, &spec, device, ×liceIndex](size_t id) { + O2_SIGNPOST_ID_GENERATE(cid, async_queue); + cid.value = id; if (decongestion.lastTimeslice >= oldestPossibleOutput.timeslice.value) { - O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Not sending already sent value: %" PRIu64 "> %" PRIu64, + O2_SIGNPOST_EVENT_EMIT(async_queue, cid, "oldest_possible_timeslice", "Not sending already sent value: %" PRIu64 "> %" PRIu64, decongestion.lastTimeslice, (uint64_t)oldestPossibleOutput.timeslice.value); return; } - O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Running oldest possible timeslice %" PRIu64 " propagation.", + O2_SIGNPOST_EVENT_EMIT(async_queue, cid, "oldest_possible_timeslice", "Running oldest possible timeslice %" PRIu64 " propagation.", (uint64_t)oldestPossibleOutput.timeslice.value); DataProcessingHelpers::broadcastOldestPossibleTimeslice(ref, oldestPossibleOutput.timeslice.value); @@ -662,21 +667,22 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() auto& state = proxy.getForwardChannelState(ChannelIndex{fi}); // TODO: this we could cache in the proxy at the bind moment. if (info.channelType != ChannelAccountingType::DPL) { - O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Skipping channel %{public}s", info.name.c_str()); + O2_SIGNPOST_EVENT_EMIT(async_queue, cid, "oldest_possible_timeslice", "Skipping channel %{public}s", info.name.c_str()); continue; } if (DataProcessingHelpers::sendOldestPossibleTimeframe(ref, info, state, oldestPossibleOutput.timeslice.value)) { - O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", + O2_SIGNPOST_EVENT_EMIT(async_queue, cid, "oldest_possible_timeslice", "Forwarding to channel %{public}s oldest possible timeslice %" PRIu64 ", priority %d", info.name.c_str(), (uint64_t)oldestPossibleOutput.timeslice.value, 20); } } decongestion.lastTimeslice = oldestPossibleOutput.timeslice.value; if (decongestion.orderedCompletionPolicyActive) { + int64_t oldNextTimeslice = decongestion.nextTimeslice; decongestion.nextTimeslice = std::max(decongestion.nextTimeslice, (int64_t)oldestPossibleOutput.timeslice.value); if (oldNextTimeslice != decongestion.nextTimeslice) { - LOGP(error, "Some Lifetime::Timeframe data got dropped starting at {}", oldNextTimeslice); + O2_SIGNPOST_EVENT_EMIT_ERROR(async_queue, cid, "oldest_possible_timeslice", "Some Lifetime::Timeframe data got dropped starting at %" PRIi64, oldNextTimeslice); timesliceIndex.rescan(); } } diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 70654bc43e84b..35cc2524ed98b 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -92,6 +92,8 @@ struct formatter : ostream_format O2_DECLARE_DYNAMIC_LOG(device); // Special log to keep track of the lifetime of the parts O2_DECLARE_DYNAMIC_LOG(parts); +// Special log to track the async queue behavior +O2_DECLARE_DYNAMIC_LOG(async_queue); using namespace o2::framework; using ConfigurationInterface = o2::configuration::ConfigurationInterface; @@ -681,9 +683,11 @@ static auto forwardInputs = [](ServiceRegistryRef registry, TimesliceSlot slot, auto& asyncQueue = registry.get(); auto& decongestion = registry.get(); - LOG(debug) << "Queuing forwarding oldestPossible " << oldestTimeslice.timeslice.value; + auto& timesliceIndex = registry.get(); + O2_SIGNPOST_ID_GENERATE(aid, async_queue); + O2_SIGNPOST_EVENT_EMIT(async_queue, aid, "forwardInputs", "Queuing forwarding oldestPossible %zu", oldestTimeslice.timeslice.value); AsyncQueueHelpers::post( - asyncQueue, decongestion.oldestPossibleTimesliceTask, [&proxy, &decongestion, registry, oldestTimeslice]() { + asyncQueue, decongestion.oldestPossibleTimesliceTask, [&proxy, &decongestion, registry, oldestTimeslice, ×liceIndex](size_t aid) { // DataProcessingHelpers::broadcastOldestPossibleTimeslice(proxy, oldestTimeslice.timeslice.value); if (oldestTimeslice.timeslice.value <= decongestion.lastTimeslice) { LOG(debug) << "Not sending already sent oldest possible timeslice " << oldestTimeslice.timeslice.value; @@ -692,13 +696,17 @@ static auto forwardInputs = [](ServiceRegistryRef registry, TimesliceSlot slot, for (int fi = 0; fi < proxy.getNumForwardChannels(); fi++) { auto& info = proxy.getForwardChannelInfo(ChannelIndex{fi}); auto& state = proxy.getForwardChannelState(ChannelIndex{fi}); + O2_SIGNPOST_ID_GENERATE(aid, async_queue); // TODO: this we could cache in the proxy at the bind moment. if (info.channelType != ChannelAccountingType::DPL) { - LOG(debug) << "Skipping channel"; + O2_SIGNPOST_EVENT_EMIT(async_queue, aid, "forwardInputsCallback", "Skipping channel %{public}s because it's not a DPL channel", + info.name.c_str()); + continue; } if (DataProcessingHelpers::sendOldestPossibleTimeframe(registry, info, state, oldestTimeslice.timeslice.value)) { - LOGP(debug, "Forwarding to channel {} oldest possible timeslice {}, prio 20", info.name, oldestTimeslice.timeslice.value); + O2_SIGNPOST_EVENT_EMIT(async_queue, aid, "forwardInputsCallback", "Forwarding to channel %{public}s oldest possible timeslice %zu, prio 20", + info.name.c_str(), oldestTimeslice.timeslice.value); } } }, @@ -1900,7 +1908,9 @@ void DataProcessingDevice::handleData(ServiceRegistryRef ref, InputChannelInfo& ii += (nMessages / 2) - 1; } auto onDrop = [ref](TimesliceSlot slot, std::vector& dropped, TimesliceIndex::OldestOutputInfo oldestOutputInfo) { - LOGP(debug, "Dropping message from slot {}. Forwarding as needed. Timeslice {}", slot.index, oldestOutputInfo.timeslice.value); + O2_SIGNPOST_ID_GENERATE(cid, async_queue); + O2_SIGNPOST_EVENT_EMIT(async_queue, cid, "onDrop", "Dropping message from slot %zu. Forwarding as needed. Timeslice %zu", + slot.index, oldestOutputInfo.timeslice.value); ref.get(); ref.get(); ref.get(); diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index 1daf4bbd2a20b..bcb5f2a0d9d74 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -54,6 +54,8 @@ using DataHeader = o2::header::DataHeader; using DataProcessingHeader = o2::framework::DataProcessingHeader; using Verbosity = o2::monitoring::Verbosity; +O2_DECLARE_DYNAMIC_LOG(data_relayer); + namespace o2::framework { @@ -369,6 +371,8 @@ void DataRelayer::pruneCache(TimesliceSlot slot, OnDropCallback onDrop) } bool anyDropped = std::any_of(dropped.begin(), dropped.end(), [](auto& m) { return m.size(); }); if (anyDropped) { + O2_SIGNPOST_ID_GENERATE(aid, data_relayer); + O2_SIGNPOST_EVENT_EMIT(data_relayer, aid, "pruneCache", "Dropping stuff from slot %zu %zu", slot.index, oldestPossibleTimeslice.timeslice.value); onDrop(slot, dropped, oldestPossibleTimeslice); } } @@ -440,6 +444,8 @@ DataRelayer::RelayChoice &nPayloads, &cache = mCache, numInputTypes = mDistinctRoutesIndex.size()](TimesliceId timeslice, int input, TimesliceSlot slot) { + O2_SIGNPOST_ID_GENERATE(aid, data_relayer); + O2_SIGNPOST_EVENT_EMIT(data_relayer, aid, "saveInSlot", "saving %zu in slot %zu", timeslice.value, slot.index); auto cacheIdx = numInputTypes * slot.index + input; MessageSet& target = cache[cacheIdx]; cachedStateMetrics[cacheIdx] = CacheEntryStatus::PENDING; @@ -573,8 +579,14 @@ DataRelayer::RelayChoice return RelayChoice{.type = RelayChoice::Type::Invalid, .timeslice = timeslice}; } + O2_SIGNPOST_ID_GENERATE(aid, data_relayer); TimesliceIndex::ActionTaken action; std::tie(action, slot) = index.replaceLRUWith(pristineContext, timeslice); + uint64_t const* debugTimestamp = std::get_if(&pristineContext.get(0)); + if (action != TimesliceIndex::ActionTaken::Wait) { + O2_SIGNPOST_EVENT_EMIT(data_relayer, aid, "saveInSlot", + "Slot %zu updated with %zu using action %d, %" PRIu64, slot.index, timeslice.value, (int)action, *debugTimestamp); + } updateStatistics(action); diff --git a/Framework/Core/src/TimesliceIndex.cxx b/Framework/Core/src/TimesliceIndex.cxx index 4d5cf443e5385..843ef55ead060 100644 --- a/Framework/Core/src/TimesliceIndex.cxx +++ b/Framework/Core/src/TimesliceIndex.cxx @@ -9,7 +9,9 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include "Framework/TimesliceIndex.h" -#include "Framework/Logger.h" +#include "Framework/Signpost.h" + +O2_DECLARE_DYNAMIC_LOG(timeslice_index); namespace o2::framework { @@ -33,6 +35,8 @@ void TimesliceIndex::associate(TimesliceId timestamp, TimesliceSlot slot) mVariables[slot.index].put({0, static_cast(timestamp.value)}); mVariables[slot.index].commit(); mDirty[slot.index] = true; + O2_SIGNPOST_ID_GENERATE(tid, timeslice_index); + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "associate", "Associating timestamp %zu to slot %zu", timestamp.value, slot.index); } TimesliceSlot TimesliceIndex::findOldestSlot(TimesliceId timestamp) const @@ -63,13 +67,18 @@ TimesliceSlot TimesliceIndex::findOldestSlot(TimesliceId timestamp) const std::tuple TimesliceIndex::replaceLRUWith(data_matcher::VariableContext& newContext, TimesliceId timestamp) { auto oldestSlot = findOldestSlot(timestamp); + O2_SIGNPOST_ID_GENERATE(tid, timeslice_index); if (TimesliceIndex::isValid(oldestSlot) == false) { mVariables[oldestSlot.index] = newContext; + auto debugTimestamp = std::get_if(&mVariables[oldestSlot.index].get(0)); + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "replaceLRUWith", "slot %zu timeslice %zu (%" PRIu64 ")", oldestSlot.index, timestamp.value, *debugTimestamp); return std::make_tuple(ActionTaken::ReplaceUnused, oldestSlot); } auto oldTimestamp = std::get_if(&mVariables[oldestSlot.index].get(0)); if (oldTimestamp == nullptr) { mVariables[oldestSlot.index] = newContext; + auto debugTimestamp = std::get_if(&mVariables[oldestSlot.index].get(0)); + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "replaceLRUWith", "slot %zu timeslice %zu (%" PRIu64 ")", oldestSlot.index, timestamp.value, *debugTimestamp); return std::make_tuple(ActionTaken::ReplaceUnused, oldestSlot); } @@ -80,9 +89,12 @@ std::tuple TimesliceIndex::replaceLR if (*newTimestamp > *oldTimestamp) { switch (mBackpressurePolicy) { - case BackpressureOp::DropAncient: + case BackpressureOp::DropAncient: { mVariables[oldestSlot.index] = newContext; + auto debugTimestamp = std::get_if(&mVariables[oldestSlot.index].get(0)); + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "replaceLRUWith", "slot %zu timeslice %zu (%" PRIu64 ")", oldestSlot.index, timestamp.value, *debugTimestamp); return std::make_tuple(ActionTaken::ReplaceObsolete, oldestSlot); + } case BackpressureOp::DropRecent: return std::make_tuple(ActionTaken::DropObsolete, TimesliceSlot{TimesliceSlot::INVALID}); case BackpressureOp::Wait: @@ -90,9 +102,12 @@ std::tuple TimesliceIndex::replaceLR } } else { switch (mBackpressurePolicy) { - case BackpressureOp::DropRecent: + case BackpressureOp::DropRecent: { mVariables[oldestSlot.index] = newContext; + auto debugTimestamp = std::get_if(&mVariables[oldestSlot.index].get(0)); + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "replaceLRUWith", "slot %zu timeslice %zu (%" PRIu64 ")", oldestSlot.index, timestamp.value, *debugTimestamp); return std::make_tuple(ActionTaken::ReplaceObsolete, oldestSlot); + } case BackpressureOp::DropAncient: return std::make_tuple(ActionTaken::DropObsolete, TimesliceSlot{TimesliceSlot::INVALID}); case BackpressureOp::Wait: @@ -124,9 +139,12 @@ bool TimesliceIndex::didReceiveData() const TimesliceIndex::OldestInputInfo TimesliceIndex::setOldestPossibleInput(TimesliceId timestamp, ChannelIndex channel) { + O2_SIGNPOST_ID_GENERATE(tid, timeslice_index); // Each channel oldest possible input must be monotoically increasing. if (timestamp.value < mChannels[channel.value].oldestForChannel.value) { - LOG(error) << "Received bogus oldest possible timeslice " << timestamp.value << " for channel " << channel.value << ". Expected >= " << mChannels[channel.value].oldestForChannel.value; + O2_SIGNPOST_EVENT_EMIT_ERROR(timeslice_index, tid, "setOldestPossibleInput", + "Received bogus oldest possible timeslice %zu for channel %d. Expected >= %zu.", + timestamp.value, channel.value, mChannels[channel.value].oldestForChannel.value); } mChannels[channel.value].oldestForChannel = timestamp; OldestInputInfo result{timestamp, channel}; @@ -144,11 +162,13 @@ TimesliceIndex::OldestInputInfo TimesliceIndex::setOldestPossibleInput(Timeslice } } if (changed && mOldestPossibleInput.timeslice.value != result.timeslice.value) { - LOG(debug) << "Success: Oldest possible input is " << result.timeslice.value << " due to channel " << result.channel.value; + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "setOldestPossibleInput", "Success: Oldest possible input is %zu due to channel %d", + result.timeslice.value, result.channel.value); } else if (mOldestPossibleInput.timeslice.value != result.timeslice.value) { - LOG(debug) << "Oldest possible input updated from timestamp: " << mOldestPossibleInput.timeslice.value << " --> " << result.timeslice.value; + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "setOldestPossibleInput", "Oldest possible input updated from timestamp: %zu --> %zu", + mOldestPossibleInput.timeslice.value, result.timeslice.value); } else { - LOG(debug) << "No change in oldest possible input"; + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "setOldestPossibleInput", "No change in oldest possible input"); } mOldestPossibleInput = result; return mOldestPossibleInput; @@ -187,13 +207,15 @@ TimesliceIndex::OldestOutputInfo TimesliceIndex::updateOldestPossibleOutput() result.channel = {(int)-1}; } } + O2_SIGNPOST_ID_GENERATE(tid, timeslice_index); if (changed && mOldestPossibleOutput.timeslice.value != result.timeslice.value) { - LOGP(debug, "Oldest possible output {} due to {} {}", - result.timeslice.value, - result.channel.value == -1 ? "slot" : "channel", - result.channel.value == -1 ? mOldestPossibleOutput.slot.index : mOldestPossibleOutput.channel.value); + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "updateOldestPossibleOutput", "Oldest possible output %zu due to %{public}s %zu", + result.timeslice.value, + result.channel.value == -1 ? "slot" : "channel", + result.channel.value == -1 ? mOldestPossibleOutput.slot.index : mOldestPossibleOutput.channel.value); } else if (mOldestPossibleOutput.timeslice.value != result.timeslice.value) { - LOG(debug) << "Oldest possible output updated from oldest Input : " << mOldestPossibleOutput.timeslice.value << " --> " << result.timeslice.value; + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "updateOldestPossibleOutput", "Oldest possible output updated from oldest Input : %zu --> %zu", + mOldestPossibleOutput.timeslice.value, result.timeslice.value); } mOldestPossibleOutput = result; diff --git a/Framework/Core/test/test_AsyncQueue.cxx b/Framework/Core/test/test_AsyncQueue.cxx index c3ac4ea06bd82..635eb131cc666 100644 --- a/Framework/Core/test/test_AsyncQueue.cxx +++ b/Framework/Core/test/test_AsyncQueue.cxx @@ -22,9 +22,9 @@ TEST_CASE("TestDebouncing") // Push two tasks on the queue with the same id auto count = 0; AsyncQueueHelpers::post( - queue, taskId, [&count]() { count += 1; }, TimesliceId{0}, 10); + queue, taskId, [&count](size_t) { count += 1; }, TimesliceId{0}, 10); AsyncQueueHelpers::post( - queue, taskId, [&count]() { count += 2; }, TimesliceId{1}, 20); + queue, taskId, [&count](size_t) { count += 2; }, TimesliceId{1}, 20); AsyncQueueHelpers::run(queue, TimesliceId{2}); REQUIRE(count == 2); } @@ -39,9 +39,9 @@ TEST_CASE("TestPriority") // Push two tasks on the queue with the same id auto count = 0; AsyncQueueHelpers::post( - queue, taskId1, [&count]() { count += 10; }, TimesliceId{0}); + queue, taskId1, [&count](size_t) { count += 10; }, TimesliceId{0}); AsyncQueueHelpers::post( - queue, taskId2, [&count]() { count /= 10; }, TimesliceId{0}); + queue, taskId2, [&count](size_t) { count /= 10; }, TimesliceId{0}); AsyncQueueHelpers::run(queue, TimesliceId{2}); REQUIRE(count == 10); } @@ -56,9 +56,9 @@ TEST_CASE("TestOldestTimeslice") // Push two tasks on the queue with the same id auto count = 0; AsyncQueueHelpers::post( - queue, taskId1, [&count]() { count += 10; }, TimesliceId{1}); + queue, taskId1, [&count](size_t) { count += 10; }, TimesliceId{1}); AsyncQueueHelpers::post( - queue, taskId2, [&count]() { count += 20; }, TimesliceId{0}); + queue, taskId2, [&count](size_t) { count += 20; }, TimesliceId{0}); AsyncQueueHelpers::run(queue, TimesliceId{0}); REQUIRE(count == 20); AsyncQueueHelpers::run(queue, TimesliceId{0}); @@ -77,11 +77,11 @@ TEST_CASE("TestOldestTimesliceWithBounce") // Push two tasks on the queue with the same id auto count = 0; AsyncQueueHelpers::post( - queue, taskId1, [&count]() { count += 10; }, TimesliceId{2}); + queue, taskId1, [&count](size_t) { count += 10; }, TimesliceId{2}); AsyncQueueHelpers::post( - queue, taskId2, [&count]() { count += 20; }, TimesliceId{1}, 10); + queue, taskId2, [&count](size_t) { count += 20; }, TimesliceId{1}, 10); AsyncQueueHelpers::post( - queue, taskId2, [&count]() { count += 30; }, TimesliceId{1}, 20); + queue, taskId2, [&count](size_t) { count += 30; }, TimesliceId{1}, 20); AsyncQueueHelpers::run(queue, TimesliceId{0}); REQUIRE(count == 0); REQUIRE(queue.tasks.size() == 3); @@ -103,11 +103,11 @@ TEST_CASE("TestOldestTimesliceWithNegativeBounce") // Push two tasks on the queue with the same id auto count = 0; AsyncQueueHelpers::post( - queue, taskId1, [&count]() { count += 10; }, TimesliceId{2}); + queue, taskId1, [&count](size_t) { count += 10; }, TimesliceId{2}); AsyncQueueHelpers::post( - queue, taskId2, [&count]() { count += 20; }, TimesliceId{1}, -10); + queue, taskId2, [&count](size_t) { count += 20; }, TimesliceId{1}, -10); AsyncQueueHelpers::post( - queue, taskId2, [&count]() { count += 30; }, TimesliceId{1}, -20); + queue, taskId2, [&count](size_t) { count += 30; }, TimesliceId{1}, -20); AsyncQueueHelpers::run(queue, TimesliceId{0}); REQUIRE(count == 0); REQUIRE(queue.tasks.size() == 3); @@ -128,13 +128,13 @@ TEST_CASE("TestOldestTimeslicePerTimeslice") // Push two tasks on the queue with the same id auto count = 0; AsyncQueueHelpers::post( - queue, taskId1, [&count]() { count += 10; }, TimesliceId{1}); + queue, taskId1, [&count](size_t) { count += 10; }, TimesliceId{1}); REQUIRE(queue.tasks.size() == 1); AsyncQueueHelpers::run(queue, TimesliceId{0}); REQUIRE(queue.tasks.size() == 1); REQUIRE(count == 0); AsyncQueueHelpers::post( - queue, taskId1, [&count]() { count += 20; }, TimesliceId{2}); + queue, taskId1, [&count](size_t) { count += 20; }, TimesliceId{2}); REQUIRE(queue.tasks.size() == 2); AsyncQueueHelpers::run(queue, TimesliceId{1}); REQUIRE(queue.tasks.size() == 1); From 7b945eb3da59d05c9eaade9a0dbda43a15ccbde2 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 28 Mar 2024 16:35:16 +0100 Subject: [PATCH 0002/2997] DPL: fix spurios error message and wrong update. (#12956) --- Framework/Core/src/CommonServices.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 7e16c03ef69e1..d7f6538310cb4 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -581,12 +581,11 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() (uint64_t)oldestPossibleOutput.timeslice.value, oldestPossibleOutput.slot.index == -1 ? "channel" : "slot", (uint64_t)(oldestPossibleOutput.slot.index == -1 ? oldestPossibleOutput.channel.value : oldestPossibleOutput.slot.index)); - O2_SIGNPOST_EVENT_EMIT_ERROR(data_processor_context, cid, "oldest_possible_timeslice", "Ordered active %d", decongestion->orderedCompletionPolicyActive); + O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Ordered active %d", decongestion->orderedCompletionPolicyActive); if (decongestion->orderedCompletionPolicyActive) { auto oldNextTimeslice = decongestion->nextTimeslice; decongestion->nextTimeslice = std::max(decongestion->nextTimeslice, (int64_t)oldestPossibleOutput.timeslice.value); - timesliceIndex.updateOldestPossibleOutput(); - O2_SIGNPOST_EVENT_EMIT_ERROR(data_processor_context, cid, "oldest_possible_timeslice", "Next timeslice %" PRIi64, decongestion->nextTimeslice); + O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Next timeslice %" PRIi64, decongestion->nextTimeslice); if (oldNextTimeslice != decongestion->nextTimeslice) { O2_SIGNPOST_EVENT_EMIT_ERROR(data_processor_context, cid, "oldest_possible_timeslice", "Some Lifetime::Timeframe data got dropped starting at %" PRIi64, oldNextTimeslice); timesliceIndex.rescan(); From 1277f953c37bdc21cb191ffe64f3b25dd15ef063 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 28 Mar 2024 21:59:16 +0100 Subject: [PATCH 0003/2997] DPL: move StringLiteral to FunctionalHelpers (#12766) --- Framework/Core/include/Framework/AlgorithmSpec.h | 11 ----------- .../Foundation/include/Framework/FunctionalHelpers.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Framework/Core/include/Framework/AlgorithmSpec.h b/Framework/Core/include/Framework/AlgorithmSpec.h index 39d0582a0f1ee..e08d829e489bd 100644 --- a/Framework/Core/include/Framework/AlgorithmSpec.h +++ b/Framework/Core/include/Framework/AlgorithmSpec.h @@ -83,17 +83,6 @@ struct AlgorithmSpec { struct AlgorithmPlugin { virtual AlgorithmSpec create() = 0; }; - -template -struct StringLiteral { - constexpr StringLiteral(const char (&str)[N]) - { - std::copy_n(str, N, value); - } - - char value[N]; -}; - // Allow fetching inputs from the context using a string literal. template struct Input { diff --git a/Framework/Foundation/include/Framework/FunctionalHelpers.h b/Framework/Foundation/include/Framework/FunctionalHelpers.h index 7e060e8816e3b..12470a7eb0f1c 100644 --- a/Framework/Foundation/include/Framework/FunctionalHelpers.h +++ b/Framework/Foundation/include/Framework/FunctionalHelpers.h @@ -25,6 +25,16 @@ struct memfun_type { }; } // namespace +template +struct StringLiteral { + constexpr StringLiteral(const char (&str)[N]) + { + std::copy_n(str, N, value); + } + + char value[N]; +}; + /// Type helper to hold metadata about a lambda or a class /// method. template From f741609793acc9fed689242dd8500728f79c537e Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 28 Mar 2024 14:21:27 +0100 Subject: [PATCH 0004/2997] GPU: Add RTCrunTest option to only test RTC compilation without a device and then exit --- .../Base/cuda/GPUReconstructionCUDA.cu | 42 ++++++++++++------- .../Base/cuda/GPUReconstructionCUDA.h | 3 +- .../Base/cuda/GPUReconstructionCUDAGenRTC.cxx | 2 +- GPU/GPUTracking/Definitions/GPUSettingsList.h | 1 + 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 63549fc861368..c8a5124aa4842 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -115,6 +115,11 @@ int GPUReconstructionCUDA::InitDevice_Runtime() constexpr int reqVerMaj = 2; constexpr int reqVerMin = 0; #endif + if (mProcessingSettings.rtc.enable && mProcessingSettings.rtc.runTest == 2) { + genAndLoadRTC(); + exit(0); + } + if (mMaster == nullptr) { cudaDeviceProp deviceProp; int count, bestDevice = -1; @@ -350,18 +355,7 @@ int GPUReconstructionCUDA::InitDevice_Runtime() #ifndef GPUCA_ALIROOT_LIB if (mProcessingSettings.rtc.enable) { - std::string filename = ""; - unsigned int nCompile = 0; - if (genRTC(filename, nCompile)) { - throw std::runtime_error("Runtime compilation failed"); - } - for (unsigned int i = 0; i < nCompile; i++) { - mInternals->kernelModules.emplace_back(std::make_unique()); - GPUFailedMsg(cuModuleLoad(mInternals->kernelModules.back().get(), (filename + "_" + std::to_string(i) + ".cubin").c_str())); - remove((filename + "_" + std::to_string(i) + ".cu").c_str()); - remove((filename + "_" + std::to_string(i) + ".cubin").c_str()); - } - loadKernelModules(mProcessingSettings.rtc.compilePerKernel); + genAndLoadRTC(); } #if defined(GPUCA_KERNEL_COMPILE_MODE) && GPUCA_KERNEL_COMPILE_MODE == 1 else { @@ -423,6 +417,27 @@ int GPUReconstructionCUDA::InitDevice_Runtime() return (0); } +void GPUReconstructionCUDA::genAndLoadRTC() +{ + std::string filename = ""; + unsigned int nCompile = 0; + if (genRTC(filename, nCompile)) { + throw std::runtime_error("Runtime compilation failed"); + } + for (unsigned int i = 0; i < nCompile; i++) { + if (mProcessingSettings.rtc.runTest != 2) { + mInternals->kernelModules.emplace_back(std::make_unique()); + GPUFailedMsg(cuModuleLoad(mInternals->kernelModules.back().get(), (filename + "_" + std::to_string(i) + ".cubin").c_str())); + } + remove((filename + "_" + std::to_string(i) + ".cu").c_str()); + remove((filename + "_" + std::to_string(i) + ".cubin").c_str()); + } + if (mProcessingSettings.rtc.runTest == 2) { + return; + } + loadKernelModules(mProcessingSettings.rtc.compilePerKernel); +} + int GPUReconstructionCUDA::ExitDevice_Runtime() { // Uninitialize CUDA @@ -600,7 +615,7 @@ void GPUReconstructionCUDABackend::PrintKernelOccupancies() } } -int GPUReconstructionCUDA::loadKernelModules(bool perKernel, bool perSingleMulti) +void GPUReconstructionCUDA::loadKernelModules(bool perKernel, bool perSingleMulti) { unsigned int j = 0; #define GPUCA_KRNL(...) \ @@ -632,7 +647,6 @@ int GPUReconstructionCUDA::loadKernelModules(bool perKernel, bool perSingleMulti if (j != mInternals->kernelModules.size()) { GPUFatal("Did not load all kernels (%u < %u)", j, (unsigned int)mInternals->kernelModules.size()); } - return 0; } #ifndef __HIPCC__ // CUDA diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h index 94da335ce40ae..55e71f97d5cd9 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h @@ -100,7 +100,8 @@ class GPUReconstructionCUDA : public GPUReconstructionKernels= 3) { diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index bc399b42f0188..1a7c719de2911 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -195,6 +195,7 @@ AddOption(cacheOutput, bool, false, "", 0, "Cache RTC compilation results") AddOption(optConstexpr, bool, true, "", 0, "Replace constant variables by static constexpr expressions") AddOption(compilePerKernel, bool, true, "", 0, "Run one RTC compilation per kernel") AddOption(enable, bool, false, "", 0, "Use RTC to optimize GPU code") +AddOption(runTest, int, 0, "", 0, "Do not run the actual benchmark, but just test RTC compilation (1 full test, 2 test only compilation)") AddHelp("help", 'h') EndConfig() From b2a56bf251c9c767afb451f59871677acdfc6618 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 28 Mar 2024 14:45:10 +0100 Subject: [PATCH 0005/2997] ITS GPU: Remove hip_runtime.h include from headers, include cuda/hip runtime in source files --- Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Array.h | 3 --- .../ITSMFT/ITS/tracking/GPU/ITStrackingGPU/ClusterLinesGPU.h | 3 --- Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Context.h | 3 --- Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Stream.h | 4 ---- .../ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h | 4 ---- Detectors/ITSMFT/ITS/tracking/GPU/cuda/ClusterLinesGPU.cu | 3 ++- Detectors/ITSMFT/ITS/tracking/GPU/cuda/Context.cu | 1 + Detectors/ITSMFT/ITS/tracking/GPU/cuda/Stream.cu | 3 ++- Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu | 3 ++- Detectors/ITSMFT/ITS/tracking/GPU/cuda/TracerGPU.cu | 3 ++- Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu | 1 + Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu | 1 + Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu | 1 + cmake/O2AddHipifiedExecutable.cmake | 2 +- cmake/O2AddHipifiedLibrary.cmake | 2 +- 15 files changed, 14 insertions(+), 23 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Array.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Array.h index 9d969a3d0fb1c..f4f73e715c305 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Array.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Array.h @@ -17,9 +17,6 @@ #define ITSTRACKINGGPU_ARRAY_H_ #include "GPUCommonDef.h" -#ifdef __HIPCC__ -#include -#endif namespace o2 { diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/ClusterLinesGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/ClusterLinesGPU.h index 3a8af39d1ee63..ecb25b7bc9d71 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/ClusterLinesGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/ClusterLinesGPU.h @@ -18,9 +18,6 @@ #include "GPUCommonDef.h" #include /// Required to properly compile MathUtils #include "ITStracking/ClusterLines.h" -#ifdef __HIPCC__ -#include -#endif namespace o2 { diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Context.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Context.h index 294016ffdcaee..bfc4c63756e0b 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Context.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Context.h @@ -19,9 +19,6 @@ #include #include #include "ITStracking/Definitions.h" -#ifdef __HIPCC__ -#include -#endif namespace o2 { diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Stream.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Stream.h index 0ac38e7a8ac4c..b6fbbe166cafe 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Stream.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Stream.h @@ -18,10 +18,6 @@ #include "ITStracking/Definitions.h" -#ifdef __HIPCC__ -#include -#endif - namespace o2 { namespace its diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h index a429db4b0ea25..2a2fadb21caeb 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h @@ -13,10 +13,6 @@ #ifndef TRACKINGITSGPU_INCLUDE_TIMEFRAMEGPU_H #define TRACKINGITSGPU_INCLUDE_TIMEFRAMEGPU_H -#ifdef __HIPCC__ -#include -#endif - #include "ITStracking/TimeFrame.h" #include "ITStracking/Configuration.h" diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/ClusterLinesGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/ClusterLinesGPU.cu index e7753087715d5..79f4e40dc5f10 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/ClusterLinesGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/ClusterLinesGPU.cu @@ -11,6 +11,7 @@ /// /// \author matteo.concas@cern.ch +#include #include "ITStrackingGPU/ClusterLinesGPU.h" namespace o2 @@ -134,4 +135,4 @@ GPUd() void ClusterLinesGPU::computeClusterCentroid() } } // namespace gpu } // namespace its -} // namespace o2 \ No newline at end of file +} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Context.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Context.cu index 2df3544012e59..f3bced9463020 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Context.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Context.cu @@ -9,6 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include #include "ITStrackingGPU/Context.h" #include "ITStrackingGPU/Utils.h" diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Stream.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Stream.cu index 980ba507bd613..885587d8d4544 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Stream.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Stream.cu @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. /// +#include #include "ITStrackingGPU/Stream.h" #include "ITStrackingGPU/Utils.h" #include "GPUCommonLogger.h" @@ -39,4 +40,4 @@ const GPUStream& Stream::get() const } // namespace gpu } // namespace its -} // namespace o2 \ No newline at end of file +} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu index 532e4d1492d0b..e758bf4990c4f 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu @@ -9,6 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// +#include #include #include @@ -615,4 +616,4 @@ template class TimeFrameGPU<7>; template class GpuTimeFrameChunk<7>; } // namespace gpu } // namespace its -} // namespace o2 \ No newline at end of file +} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TracerGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TracerGPU.cu index 7c09851eaa2fb..0bca6360d268c 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TracerGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TracerGPU.cu @@ -9,6 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include #include "ITStrackingGPU/TracerGPU.h" #if !defined(__HIPCC__) && defined(__USE_GPU_TRACER__) @@ -44,4 +45,4 @@ Tracer::~Tracer() } // namespace gpu } // namespace its } // namespace o2 -#endif \ No newline at end of file +#endif diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 274c0b573e454..36bf58da50783 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. /// +#include #include #include #include diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu index d49837c6272e1..42b0cb2ce2d5b 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu @@ -9,6 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include #include "ITStrackingGPU/Utils.h" #include "ITStrackingGPU/Context.h" #include "ITStracking/Constants.h" diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu index 42881e5ed7d4b..d8a7985b33343 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu @@ -11,6 +11,7 @@ // /// \author matteo.concas@cern.ch +#include #include #include #include diff --git a/cmake/O2AddHipifiedExecutable.cmake b/cmake/O2AddHipifiedExecutable.cmake index d071e9cc76081..c7354fd989e76 100644 --- a/cmake/O2AddHipifiedExecutable.cmake +++ b/cmake/O2AddHipifiedExecutable.cmake @@ -37,7 +37,7 @@ function(o2_add_hipified_executable baseTargetName) add_custom_command( OUTPUT ${OUTPUT_HIP_FILE} - COMMAND ${hip_HIPIFY_PERL_EXECUTABLE} --quiet-warnings ${ABS_CUDA_SORUCE} | sed '1{/\#include \"hip\\/hip_runtime.h\"/d}' > ${OUTPUT_HIP_FILE} + COMMAND ${hip_HIPIFY_PERL_EXECUTABLE} --quiet-warnings ${ABS_CUDA_SORUCE} > ${OUTPUT_HIP_FILE} DEPENDS ${file} COMMENT "Hippifying ${HIP_SOURCE}" ) diff --git a/cmake/O2AddHipifiedLibrary.cmake b/cmake/O2AddHipifiedLibrary.cmake index a93898b06223a..a9d8602bf87e3 100644 --- a/cmake/O2AddHipifiedLibrary.cmake +++ b/cmake/O2AddHipifiedLibrary.cmake @@ -37,7 +37,7 @@ function(o2_add_hipified_library baseTargetName) add_custom_command( OUTPUT ${OUTPUT_HIP_FILE} - COMMAND ${hip_HIPIFY_PERL_EXECUTABLE} --quiet-warnings ${ABS_CUDA_SORUCE} | sed '1{/\#include \"hip\\/hip_runtime.h\"/d}' > ${OUTPUT_HIP_FILE} + COMMAND ${hip_HIPIFY_PERL_EXECUTABLE} --quiet-warnings ${ABS_CUDA_SORUCE} > ${OUTPUT_HIP_FILE} DEPENDS ${file} COMMENT "Hippifying ${HIP_SOURCE}" ) From fc1b2dfcb19efd2a1536e0b4861a3788454d4d61 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Fri, 29 Mar 2024 10:28:09 +0100 Subject: [PATCH 0006/2997] [EMCAL-741] Fix number of LEDMON channels in pedestal extraction (#12953) --- .../include/EMCALCalibration/EMCALCalibExtractor.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h index e557702150fae..e9b59e8afa2dc 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h @@ -427,8 +427,9 @@ class EMCALCalibExtractor Pedestal pedestalData; // loop over both low and high gain data as well as normal and LEDMON data for (const auto& isLEDMON : {false, true}) { + auto maxChannels = isLEDMON ? mLEDMONs : mNcells; for (const auto& isLG : {false, true}) { - for (unsigned short iCell = 0; iCell < mNcells; ++iCell) { + for (unsigned short iCell = 0; iCell < maxChannels; ++iCell) { auto [mean, rms] = obj.getValue(iCell, isLG, isLEDMON); // get mean and rms for pedestals pedestalData.addPedestalValue(iCell, mean, isLG, isLEDMON); } @@ -446,12 +447,13 @@ class EMCALCalibExtractor Pedestal extractPedestals(TProfile* objHG = nullptr, TProfile* objLG = nullptr, bool isLEDMON = false) { Pedestal pedestalData; + auto maxChannels = isLEDMON ? mLEDMONs : mNcells; // loop over both low and high gain data for (const auto& isLG : {false, true}) { auto obj = (isLG == true ? objLG : objHG); if (!obj) continue; - for (unsigned short iCell = 0; iCell < mNcells; ++iCell) { + for (unsigned short iCell = 0; iCell < maxChannels; ++iCell) { short mean = static_cast(obj->GetBinContent(iCell + 1)); pedestalData.addPedestalValue(iCell, mean, isLG, isLEDMON); } @@ -481,6 +483,7 @@ class EMCALCalibExtractor o2::emcal::Geometry* mGeometry = nullptr; ///< pointer to the emcal geometry class static constexpr int mNcells = 17664; ///< Number of total cells of EMCal + DCal + static constexpr int mLEDMONs = 480; ///< Number of total LEDMONS of EMCal + DCal ClassDefNV(EMCALCalibExtractor, 1); }; From a00dcdb5b1438b545d0dc386bf0aa67a8b393b69 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 28 Mar 2024 14:34:15 +0100 Subject: [PATCH 0007/2997] GPU: Optionally silence RTC console output --- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx | 5 +++++ GPU/GPUTracking/Definitions/GPUSettingsList.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx index 68ad7d348487d..ba7dca723e51d 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx @@ -163,6 +163,11 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) fclose(fp); std::string command = std::string(_binary_GPUReconstructionCUDArtc_command_start, _binary_GPUReconstructionCUDArtc_command_len); command += " -c " + filename + "_" + std::to_string(i) + ".cu -o " + filename + "_" + std::to_string(i) + ".cubin"; + if (mProcessingSettings.debugLevel < 0) { + command += " &> /dev/null"; + } else if (mProcessingSettings.debugLevel < 2) { + command += " > /dev/null"; + } if (mProcessingSettings.debugLevel >= 3) { printf("Running command %s\n", command.c_str()); } diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 1a7c719de2911..92ead6858c85e 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -214,7 +214,7 @@ AddOption(globalInitMutex, bool, false, "", 0, "Use global mutex to synchronize AddOption(stuckProtection, int, 0, "", 0, "Timeout in us, When AMD GPU is stuck, just continue processing and skip tracking, do not crash or stall the chain") AddOption(trdNCandidates, int, 3, "", 0, "Number of branching track candidates for single input track during propagation") AddOption(trdTrackModelO2, bool, false, "", 0, "Use O2 track model instead of GPU track model for TRD tracking") -AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silend)") +AddOption(debugLevel, int, -1, "debug", 'd', "Set debug level (-1 = silent)") AddOption(allocDebugLevel, int, 0, "allocDebug", 0, "Some debug output for memory allocations (without messing with normal debug level)") AddOption(debugMask, int, 262143, "", 0, "Mask for debug output dumps to file") AddOption(checkKernelFailures, bool, false, "", 0, "Synchronize after each kernel call and identify failing kernels") From 532f39ce3bc07f0f4d232695a2cc4201c863159a Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 28 Mar 2024 14:36:24 +0100 Subject: [PATCH 0008/2997] GPU: Fix missing include --- GPU/GPUTracking/Base/GPUParam.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index 16df4eb4f8d7c..97618b0a82e49 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -275,6 +275,7 @@ std::string GPUParamRTC::generateRTCCode(const GPUParam& param, bool useConstexp { return "#ifndef GPUCA_GPUCODE_DEVICE\n" "#include \n" + "#include \n" "#endif\n" "namespace o2::gpu { class GPUDisplayFrontendInterface; }\n" + qConfigPrintRtc(std::make_tuple(¶m.rec.tpc, ¶m.rec.trd, ¶m.rec, ¶m.par), useConstexpr); From d0ec535c617d67c3fd3da8fe3ef468843b08d635 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 28 Mar 2024 15:05:36 +0100 Subject: [PATCH 0009/2997] GPU: Use correct files endings for RTC of CUDA and HIP --- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 13 ++++++++++--- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h | 1 + .../Base/cuda/GPUReconstructionCUDAGenRTC.cxx | 10 +++++----- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index c8a5124aa4842..61a1f47a83d4b 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -82,6 +82,13 @@ void GPUReconstructionCUDABackend::GPUFailedMsgA(const long long int error, cons GPUReconstructionCUDA::GPUReconstructionCUDA(const GPUSettingsDeviceBackend& cfg) : GPUReconstructionKernels(cfg) { mDeviceBackendSettings.deviceType = DeviceType::CUDA; +#ifndef __HIPCC__ // CUDA + mRtcSrcExtension = ".cu"; + mRtcBinExtension = ".fatbin"; +#else // HIP + mRtcSrcExtension = ".hip"; + mRtcBinExtension = ".o"; +#endif } GPUReconstructionCUDA::~GPUReconstructionCUDA() @@ -427,10 +434,10 @@ void GPUReconstructionCUDA::genAndLoadRTC() for (unsigned int i = 0; i < nCompile; i++) { if (mProcessingSettings.rtc.runTest != 2) { mInternals->kernelModules.emplace_back(std::make_unique()); - GPUFailedMsg(cuModuleLoad(mInternals->kernelModules.back().get(), (filename + "_" + std::to_string(i) + ".cubin").c_str())); + GPUFailedMsg(cuModuleLoad(mInternals->kernelModules.back().get(), (filename + "_" + std::to_string(i) + mRtcBinExtension).c_str())); } - remove((filename + "_" + std::to_string(i) + ".cu").c_str()); - remove((filename + "_" + std::to_string(i) + ".cubin").c_str()); + remove((filename + "_" + std::to_string(i) + mRtcSrcExtension).c_str()); + remove((filename + "_" + std::to_string(i) + mRtcBinExtension).c_str()); } if (mProcessingSettings.rtc.runTest == 2) { return; diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h index 55e71f97d5cd9..8a483adb3353a 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.h @@ -102,6 +102,7 @@ class GPUReconstructionCUDA : public GPUReconstructionKernels= 3) { - printf("Compiling %s\n", (filename + "_" + std::to_string(i) + ".cu").c_str()); + printf("Compiling %s\n", (filename + "_" + std::to_string(i) + mRtcSrcExtension).c_str()); } - FILE* fp = fopen((filename + "_" + std::to_string(i) + ".cu").c_str(), "w+b"); + FILE* fp = fopen((filename + "_" + std::to_string(i) + mRtcSrcExtension).c_str(), "w+b"); if (fp == nullptr) { throw std::runtime_error("Error opening file"); } @@ -162,7 +162,7 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) } fclose(fp); std::string command = std::string(_binary_GPUReconstructionCUDArtc_command_start, _binary_GPUReconstructionCUDArtc_command_len); - command += " -c " + filename + "_" + std::to_string(i) + ".cu -o " + filename + "_" + std::to_string(i) + ".cubin"; + command += " -c " + filename + "_" + std::to_string(i) + mRtcSrcExtension + " -o " + filename + "_" + std::to_string(i) + mRtcBinExtension; if (mProcessingSettings.debugLevel < 0) { command += " &> /dev/null"; } else if (mProcessingSettings.debugLevel < 2) { @@ -199,7 +199,7 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) std::vector buffer; for (unsigned int i = 0; i < nCompile; i++) { - FILE* fp2 = fopen((filename + "_" + std::to_string(i) + ".cubin").c_str(), "rb"); + FILE* fp2 = fopen((filename + "_" + std::to_string(i) + mRtcBinExtension).c_str(), "rb"); if (fp2 == nullptr) { throw std::runtime_error("Cannot open cuda module file"); } From a9d34940d1b5569f40c38b2e411a2880f4a8239b Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 28 Mar 2024 15:57:57 +0100 Subject: [PATCH 0010/2997] GPU: hipModuleGetGlobal seems broken if bytes ptr is not supplied, so provide a dummy ptr --- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 61a1f47a83d4b..250f74f803564 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -309,7 +309,7 @@ int GPUReconstructionCUDA::InitDevice_Runtime() } #else // HIP if (GPUFailedMsgI(hipSetDeviceFlags(hipDeviceScheduleBlockingSync))) { - GPUError("Could not set HIP Device!"); + GPUError("Could not set HIP Device flags!"); return (1); } #endif @@ -380,8 +380,13 @@ int GPUReconstructionCUDA::InitDevice_Runtime() runConstantRegistrators(); devPtrConstantMem = mDeviceConstantMemList[0]; for (unsigned int i = 0; i < mInternals->kernelModules.size(); i++) { - CUdeviceptr tmp; - GPUFailedMsg(cuModuleGetGlobal(&tmp, nullptr, *mInternals->kernelModules[i], "gGPUConstantMemBuffer")); +#ifndef __HIPCC__ + CUdeviceptr tmp; // CUDA has a custom type, that initializes to zero and cannot be initialized with nullptr +#else + CUdeviceptr tmp = nullptr; // HIP just uses void* +#endif + size_t tmpSize = 0; + GPUFailedMsg(cuModuleGetGlobal(&tmp, &tmpSize, *mInternals->kernelModules[i], "gGPUConstantMemBuffer")); mDeviceConstantMemList.emplace_back((void*)tmp); } #else From 19eb985c84cfdeae8b360dc45b862d9de4178e61 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 29 Mar 2024 00:53:54 +0100 Subject: [PATCH 0011/2997] ITS GPU: Fix coding conventions --- Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 36bf58da50783..080c7aafaf4e5 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -53,8 +53,9 @@ inline void gpuAssert(cudaError_t code, const char* file, int line, bool abort = { if (code != cudaSuccess) { LOGF(error, "GPUassert: %s %s %d", cudaGetErrorString(code), file, line); - if (abort) + if (abort) { throw std::runtime_error("GPU assert failed."); + } } } From 0e5785523cfcfb3f06a12a0361d54f73c4861c8b Mon Sep 17 00:00:00 2001 From: lietava Date: Fri, 29 Mar 2024 17:48:52 +0100 Subject: [PATCH 0012/2997] fatal changed to error --- Detectors/CTP/workflow/src/RawDecoderSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/CTP/workflow/src/RawDecoderSpec.cxx b/Detectors/CTP/workflow/src/RawDecoderSpec.cxx index 578ed0c4d7996..b3c140279e8f1 100644 --- a/Detectors/CTP/workflow/src/RawDecoderSpec.cxx +++ b/Detectors/CTP/workflow/src/RawDecoderSpec.cxx @@ -118,7 +118,7 @@ void RawDecoderSpec::run(framework::ProcessingContext& ctx) payloadSize += o2::framework::DataRefUtils::getPayloadSize(ref); } if (payloadSize > (size_t)mMaxInputSize) { - LOG(fatal) << "Input data size:" << payloadSize; + LOG(error) << "Input data size:" << payloadSize; dummyOutput(); return; } From 6640363eaeb33cc43ea91ff4cb1f30dc13014b29 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 29 Mar 2024 15:48:22 +0100 Subject: [PATCH 0013/2997] GPU: Fix missing includes for GCC 13 --- .../Reconstruction/include/ReconstructionDataFormats/PID.h | 4 ++++ DataFormats/Reconstruction/src/TrackLTIntegral.cxx | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h index 3f6ab06f6b2f2..e01ce253156a7 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h @@ -16,6 +16,10 @@ #ifndef ALICEO2_track_PID_H_ #define ALICEO2_track_PID_H_ +#ifndef GPUCA_GPUCODE_DEVICE +#include +#endif + #include "GPUCommonDef.h" #include "GPUCommonRtypes.h" #include "CommonConstants/PhysicsConstants.h" diff --git a/DataFormats/Reconstruction/src/TrackLTIntegral.cxx b/DataFormats/Reconstruction/src/TrackLTIntegral.cxx index 52a77ce92a4da..3efddff00f512 100644 --- a/DataFormats/Reconstruction/src/TrackLTIntegral.cxx +++ b/DataFormats/Reconstruction/src/TrackLTIntegral.cxx @@ -9,6 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#ifndef GPUCA_GPUCODE_DEVICE +#include +#endif + #include "ReconstructionDataFormats/TrackLTIntegral.h" #include "CommonConstants/PhysicsConstants.h" #include "MathUtils/Utils.h" From 19ddfa002ec60f66e4d3ee7988ef79898411b9ee Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 29 Mar 2024 15:48:47 +0100 Subject: [PATCH 0014/2997] GPU: OpenCL CMake: Be specific about the emitter, so I do not forget the option name again... --- GPU/GPUTracking/Base/opencl2/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Base/opencl2/CMakeLists.txt b/GPU/GPUTracking/Base/opencl2/CMakeLists.txt index df3e823e9c251..ec2a4446142c8 100644 --- a/GPU/GPUTracking/Base/opencl2/CMakeLists.txt +++ b/GPU/GPUTracking/Base/opencl2/CMakeLists.txt @@ -48,6 +48,7 @@ if(OPENCL2_ENABLED_SPIRV) # BUILD OpenCL2 intermediate code for SPIR-V target COMMAND ${CMAKE_COMMAND} -E env "PATH=${TMP_LLVM_SPIRV_PATH}:\$$PATH" ${LLVM_CLANG} -O0 --target=spirv64 + -fno-integrated-objemitter ${OCL_FLAGS} ${OCL_DEFINECL} -o ${CL_BIN}.spirv -c ${CL_SRC} From 8d86431155762fb90f50d54cd1013860a886b246 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 29 Mar 2024 15:49:41 +0100 Subject: [PATCH 0015/2997] GPU: Port AliRoot GPU changes 00acf7cb (sprintf to snprintf) --- GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx | 2 +- GPU/GPUTracking/Merger/macros/checkPropagation.C | 4 ++-- GPU/GPUTracking/Standalone/Benchmark/standalone.cxx | 2 +- GPU/GPUTracking/display/GPUDisplay.cxx | 12 ++++++------ GPU/GPUTracking/display/GPUDisplayKeys.cxx | 2 +- GPU/GPUTracking/qa/genEvents.cxx | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx b/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx index 00f0d17365e5d..d85a4a9a183fb 100644 --- a/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx +++ b/GPU/GPUTracking/Global/AliHLTGPUDumpComponent.cxx @@ -486,7 +486,7 @@ int AliHLTGPUDumpComponent::DoEvent(const AliHLTComponentEventData& evtData, con fRec->DumpSettings(); } - sprintf(filename, GPUCA_EVDUMP_FILE ".%d.dump", nEvent++); + snprintf(filename, 256, GPUCA_EVDUMP_FILE ".%d.dump", nEvent++); fChain->DumpData(filename); return (0); } diff --git a/GPU/GPUTracking/Merger/macros/checkPropagation.C b/GPU/GPUTracking/Merger/macros/checkPropagation.C index 052eda76484c3..bdceb8fde999f 100644 --- a/GPU/GPUTracking/Merger/macros/checkPropagation.C +++ b/GPU/GPUTracking/Merger/macros/checkPropagation.C @@ -66,8 +66,8 @@ int checkPropagation() for (int i = 0; i < 3; i++) { char* s = i == 0 ? "X" : (i == 1 ? "Y" : "Z"); char name[1024], title[1024]; - sprintf(name, "hDiff%s", s); - sprintf(title, "Propagation Difference in %s", s); + snprintf(name, 1024, "hDiff%s", s); + snprintf(title, 1024, "Propagation Difference in %s", s); hDiff[i] = new TH1F(name, title, 1000, -20., 20.); hDiff[i]->GetXaxis()->SetTitle("Propagation difference [um]"); } diff --git a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx index a78b696e4aa69..4e3cff32c5bc9 100644 --- a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx +++ b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx @@ -863,7 +863,7 @@ int main(int argc, char** argv) } if (configStandalone.dumpEvents) { char fname[1024]; - sprintf(fname, "event.%d.dump", nEventsProcessed); + snprintf(fname, 1024, "event.%d.dump", nEventsProcessed); chainTracking->DumpData(fname); if (nEventsProcessed == 0) { rec->DumpSettings(); diff --git a/GPU/GPUTracking/display/GPUDisplay.cxx b/GPU/GPUTracking/display/GPUDisplay.cxx index b620e3f8c8d01..bae8da5a6bf01 100644 --- a/GPU/GPUTracking/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/display/GPUDisplay.cxx @@ -2215,11 +2215,11 @@ void GPUDisplay::DrawGLScene_internal(float animateTime, bool renderToMixBuffer) double fpstime = mTimerFPS.GetCurrentElapsedTime(); char info[1024]; float fps = (double)mFramesDoneFPS / fpstime; - sprintf(info, - "FPS: %6.2f (Slice: %d, 1:Clusters %d, 2:Prelinks %d, 3:Links %d, 4:Seeds %d, 5:Tracklets %d, 6:Tracks %d, 7:GTracks %d, 8:Merger %d) (%d frames, %d draw calls) " - "(X %1.2f Y %1.2f Z %1.2f / R %1.2f Phi %1.1f Theta %1.1f) / Yaw %1.1f Pitch %1.1f Roll %1.1f)", - fps, mCfgL.drawSlice, mCfgL.drawClusters, mCfgL.drawInitLinks, mCfgL.drawLinks, mCfgL.drawSeeds, mCfgL.drawTracklets, mCfgL.drawTracks, mCfgL.drawGlobalTracks, mCfgL.drawFinal, mFramesDone, mNDrawCalls, mXYZ[0], mXYZ[1], mXYZ[2], mRPhiTheta[0], mRPhiTheta[1] * 180 / CAMath::Pi(), - mRPhiTheta[2] * 180 / CAMath::Pi(), mAngle[1] * 180 / CAMath::Pi(), mAngle[0] * 180 / CAMath::Pi(), mAngle[2] * 180 / CAMath::Pi()); + snprintf(info, 1024, + "FPS: %6.2f (Slice: %d, 1:Clusters %d, 2:Prelinks %d, 3:Links %d, 4:Seeds %d, 5:Tracklets %d, 6:Tracks %d, 7:GTracks %d, 8:Merger %d) (%d frames, %d draw calls) " + "(X %1.2f Y %1.2f Z %1.2f / R %1.2f Phi %1.1f Theta %1.1f) / Yaw %1.1f Pitch %1.1f Roll %1.1f)", + fps, mCfgL.drawSlice, mCfgL.drawClusters, mCfgL.drawInitLinks, mCfgL.drawLinks, mCfgL.drawSeeds, mCfgL.drawTracklets, mCfgL.drawTracks, mCfgL.drawGlobalTracks, mCfgL.drawFinal, mFramesDone, mNDrawCalls, mXYZ[0], mXYZ[1], mXYZ[2], mRPhiTheta[0], mRPhiTheta[1] * 180 / CAMath::Pi(), + mRPhiTheta[2] * 180 / CAMath::Pi(), mAngle[1] * 180 / CAMath::Pi(), mAngle[0] * 180 / CAMath::Pi(), mAngle[2] * 180 / CAMath::Pi()); if (fpstime > 1.) { if (mPrintInfoText & 2) { GPUInfo("%s", info); @@ -2242,7 +2242,7 @@ void GPUDisplay::DrawGLScene_internal(float animateTime, bool renderToMixBuffer) std::vector pixels = mBackend->getPixels(); char tmpFileName[48]; if (mAnimateScreenshot) { - sprintf(tmpFileName, "mAnimation%d_%05d.bmp", mAnimationExport, mAnimationFrame); + snprintf(tmpFileName, 48, "mAnimation%d_%05d.bmp", mAnimationExport, mAnimationFrame); } DoScreenshot(mAnimateScreenshot ? tmpFileName : mScreenshotFile.c_str(), pixels); } diff --git a/GPU/GPUTracking/display/GPUDisplayKeys.cxx b/GPU/GPUTracking/display/GPUDisplayKeys.cxx index f66256fb1e63a..7b5ab3a060255 100644 --- a/GPU/GPUTracking/display/GPUDisplayKeys.cxx +++ b/GPU/GPUTracking/display/GPUDisplayKeys.cxx @@ -348,7 +348,7 @@ void GPUDisplay::HandleKey(unsigned char key) } else if (key == 't') { static int nScreenshot = 1; char fname[32]; - sprintf(fname, "screenshot%d.bmp", nScreenshot++); + snprintf(fname, 32, "screenshot%d.bmp", nScreenshot++); mRequestScreenshot = true; mScreenshotFile = fname; SetInfo("Taking screenshot (%s)", fname); diff --git a/GPU/GPUTracking/qa/genEvents.cxx b/GPU/GPUTracking/qa/genEvents.cxx index 68cbd43a94d52..280a1eb025479 100644 --- a/GPU/GPUTracking/qa/genEvents.cxx +++ b/GPU/GPUTracking/qa/genEvents.cxx @@ -106,9 +106,9 @@ void genEvents::InitEventGenerator() for (int j = 0; j < 2; j++) { char name[1024], title[1024]; - sprintf(name, "clError%s%d", (j == 0 ? "Y" : "Z"), i); + snprintf(name, 1024, "clError%s%d", (j == 0 ? "Y" : "Z"), i); - sprintf(title, "Cluster %s Error for rows %s", (j == 0 ? "Y" : "Z"), rows[i]); + snprintf(title, 1024, "Cluster %s Error for rows %s", (j == 0 ? "Y" : "Z"), rows[i]); mClusterError[i][j] = new TH1F(name, title, 1000, 0., .7); mClusterError[i][j]->GetXaxis()->SetTitle("Cluster Error [cm]"); From 93eedb8d2044a62f9d699b2374cfead9758cfee1 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 29 Mar 2024 15:50:04 +0100 Subject: [PATCH 0016/2997] GPU: Remove supious std::move in return statements --- GPU/GPUTracking/Global/GPUChain.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChain.h b/GPU/GPUTracking/Global/GPUChain.h index 05b043ba9e1c2..21245a415a5cd 100644 --- a/GPU/GPUTracking/Global/GPUChain.h +++ b/GPU/GPUTracking/Global/GPUChain.h @@ -161,7 +161,7 @@ class GPUChain template inline std::unique_ptr ReadFlatObjectFromFile(const char* file) { - return std::move(mRec->ReadFlatObjectFromFile(file)); + return mRec->ReadFlatObjectFromFile(file); } template inline void DumpStructToFile(const T* obj, const char* file) @@ -171,7 +171,7 @@ class GPUChain template inline std::unique_ptr ReadStructFromFile(const char* file) { - return std::move(mRec->ReadStructFromFile(file)); + return mRec->ReadStructFromFile(file); } template inline void ReadStructFromFile(const char* file, T* obj) From 0280ce73d99d87e63618aec43c4282eb57be38a4 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 29 Mar 2024 22:39:13 +0100 Subject: [PATCH 0017/2997] GPU: Bump GPU compilation to C++ 20 --- dependencies/FindO2GPU.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 1805c046d0596..a3af9c8d9bbc2 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -66,7 +66,7 @@ endfunction() STRING(REGEX REPLACE "\-std=[^ ]*" "" O2_GPU_CMAKE_CXX_FLAGS_NOSTD "${CMAKE_CXX_FLAGS}") # Need to strip c++17 imposed by alidist defaults if(ENABLE_CUDA) - set(CMAKE_CUDA_STANDARD 17) + set(CMAKE_CUDA_STANDARD 20) set(CMAKE_CUDA_STANDARD_REQUIRED TRUE) include(CheckLanguage) check_language(CUDA) @@ -206,7 +206,7 @@ endif() # Detect and enable HIP if(ENABLE_HIP) if("$ENV{CMAKE_PREFIX_PATH}" MATCHES "rocm") - set(CMAKE_HIP_STANDARD 17) + set(CMAKE_HIP_STANDARD 20) set(CMAKE_HIP_STANDARD_REQUIRED TRUE) if(HIP_AMDGPUTARGET) set(AMDGPU_TARGETS "${HIP_AMDGPUTARGET}" CACHE STRING "AMD GPU targets to compile for" FORCE) From df319775092adc6973b66b2bf5d7ebc8d4f793c2 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 30 Mar 2024 00:20:13 +0100 Subject: [PATCH 0018/2997] CMake: Make sure CMAKE_BUILD_TYPE_UPPER is defined if GPU Cmake is used outside of O2 --- dependencies/FindO2GPU.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index a3af9c8d9bbc2..3d32bbe693931 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -25,6 +25,9 @@ string(TOUPPER "${ENABLE_CUDA}" ENABLE_CUDA) string(TOUPPER "${ENABLE_OPENCL1}" ENABLE_OPENCL1) string(TOUPPER "${ENABLE_OPENCL2}" ENABLE_OPENCL2) string(TOUPPER "${ENABLE_HIP}" ENABLE_HIP) +if(NOT DEFINED CMAKE_BUILD_TYPE_UPPER) + string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_UPPER) +endif() if(CUDA_COMPUTETARGET AND CUDA_COMPUTETARGET STREQUAL "default") set(CUDA_COMPUTETARGET 86 89) From fa8dafbfb9995cf2295f34859b87e6488aff7d30 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 30 Mar 2024 09:57:41 +0100 Subject: [PATCH 0019/2997] GPU: Fixes for running with Run 2 data --- GPU/GPUTracking/Base/GPUConstantMem.h | 15 ++++++++++++--- GPU/GPUTracking/Base/GPUParam.cxx | 2 +- GPU/GPUTracking/Base/GPUParam.inc | 2 +- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 12 +++++++----- GPU/GPUTracking/Base/hip/CMakeLists.txt | 16 +++++++++------- GPU/GPUTracking/CMakeLists.txt | 5 +++-- .../AliHLTTPCClusterStatComponent.cxx | 2 +- GPU/GPUTracking/DataTypes/GPUO2FakeClasses.h | 2 ++ GPU/GPUTracking/Global/GPUChainTracking.cxx | 6 ++++++ GPU/GPUTracking/Global/GPUChainTrackingTRD.cxx | 5 ++++- GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx | 2 ++ GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h | 12 ++++++------ GPU/GPUTracking/cmake/kernel_helpers.cmake | 8 ++++++-- GPU/GPUTracking/kernels.cmake | 8 +++++++- GPU/GPUTracking/qa/GPUQA.h | 1 + 15 files changed, 68 insertions(+), 30 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUConstantMem.h b/GPU/GPUTracking/Base/GPUConstantMem.h index 3f74e4482f47f..17e6268764606 100644 --- a/GPU/GPUTracking/Base/GPUConstantMem.h +++ b/GPU/GPUTracking/Base/GPUConstantMem.h @@ -21,11 +21,9 @@ #include "GPUErrors.h" // Dummies for stuff not supported in legacy code (ROOT 5 / OPENCL1.2) -#if defined(GPUCA_NOCOMPAT_ALLCINT) && (!defined(GPUCA_GPUCODE) || !defined(GPUCA_ALIROOT_LIB)) +#if defined(GPUCA_NOCOMPAT_ALLCINT) #include "GPUTPCGMMerger.h" -#include "GPUTRDTracker.h" #else -#include "GPUTRDDef.h" namespace GPUCA_NAMESPACE { namespace gpu @@ -33,6 +31,17 @@ namespace gpu class GPUTPCGMMerger { }; +} // namespace gpu +} // namespace GPUCA_NAMESPACE +#endif +#if defined(GPUCA_NOCOMPAT_ALLCINT) && (!defined(GPUCA_GPUCODE) || !defined(GPUCA_ALIROOT_LIB)) +#include "GPUTRDTracker.h" +#else +#include "GPUTRDDef.h" +namespace GPUCA_NAMESPACE +{ +namespace gpu +{ template class GPUTRDTracker_t { diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index 97618b0a82e49..3865010000566 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -217,7 +217,7 @@ void GPUParam::LoadClusterErrors(bool Print) for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 4; k++) { - ParamErrorsSeeding0[i][j][k] = clparam->GetParamErrorsSeeding0(i, j, k); + ParamErrorsSeeding0[i][j][k] = clparam->GetParamRMS0(i, j, k); } } } diff --git a/GPU/GPUTracking/Base/GPUParam.inc b/GPU/GPUTracking/Base/GPUParam.inc index 0b31a224fc3a1..d5b4e9bc77810 100644 --- a/GPU/GPUTracking/Base/GPUParam.inc +++ b/GPU/GPUTracking/Base/GPUParam.inc @@ -161,7 +161,7 @@ GPUdi() float MEM_LG(GPUParam)::GetSystematicClusterErrorIFC2(float trackX, floa } MEM_CLASS_PRE() -GPUd() float MEM_LG(GPUParam)::GetSystematicClusterErrorC122(float trackX, float trackY, char sector) const +GPUdi() float MEM_LG(GPUParam)::GetSystematicClusterErrorC122(float trackX, float trackY, char sector) const { return 0; } diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index f5d32ea6c18c0..6d49c83164b00 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -199,8 +199,10 @@ if(NOT GPUCA_CUDA_COMPILE_MODE STREQUAL "rdc") set_property(TARGET ${targetName} PROPERTY CUDA_SEPARABLE_COMPILATION OFF) endif() -add_library(GPUTrackingCUDAExternalProvider OBJECT GPUReconstructionCUDAExternalProvider.cu) -add_library(O2::GPUTrackingCUDAExternalProvider ALIAS GPUTrackingCUDAExternalProvider) -set_property(TARGET GPUTrackingCUDAExternalProvider PROPERTY CUDA_SEPARABLE_COMPILATION ON) -target_compile_definitions(GPUTrackingCUDAExternalProvider PRIVATE $) -target_include_directories(GPUTrackingCUDAExternalProvider PRIVATE $) +if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") + add_library(GPUTrackingCUDAExternalProvider OBJECT GPUReconstructionCUDAExternalProvider.cu) + add_library(O2::GPUTrackingCUDAExternalProvider ALIAS GPUTrackingCUDAExternalProvider) + set_property(TARGET GPUTrackingCUDAExternalProvider PROPERTY CUDA_SEPARABLE_COMPILATION ON) + target_compile_definitions(GPUTrackingCUDAExternalProvider PRIVATE $) + target_include_directories(GPUTrackingCUDAExternalProvider PRIVATE $) +endif() diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index 4a2a98dbc22a5..d575c74e24a60 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -150,7 +150,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") # Generate the dictionary get_directory_property(incdirs INCLUDE_DIRECTORIES) - generate_dictionary("${targetName}" "" "GPUReconstructionHIP.h" "${incdirs} .") + generate_dictionary("${targetName}" "" "${GPUCA_HIP_SOURCE_DIR}/GPUReconstructionHIP.h" "${incdirs} .") # Generate the ROOT map Dependecies generate_rootmap("${targetName}" "" "") @@ -257,9 +257,11 @@ if(NOT GPUCA_HIP_COMPILE_MODE STREQUAL "rdc") target_link_options(${targetName} PRIVATE "-fno-gpu-rdc") endif() -add_library(GPUTrackingHIPExternalProvider OBJECT ${GPUCA_HIP_SOURCE_DIR}/GPUReconstructionHIPExternalProvider.hip) -add_library(O2::GPUTrackingHIPExternalProvider ALIAS GPUTrackingHIPExternalProvider) -target_compile_options(GPUTrackingHIPExternalProvider PRIVATE "-fgpu-rdc") -target_link_options(GPUTrackingHIPExternalProvider PRIVATE "-fgpu-rdc") -target_compile_definitions(GPUTrackingHIPExternalProvider PRIVATE $) -target_include_directories(GPUTrackingHIPExternalProvider PRIVATE $) +if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") + add_library(GPUTrackingHIPExternalProvider OBJECT ${GPUCA_HIP_SOURCE_DIR}/GPUReconstructionHIPExternalProvider.hip) + add_library(O2::GPUTrackingHIPExternalProvider ALIAS GPUTrackingHIPExternalProvider) + target_compile_options(GPUTrackingHIPExternalProvider PRIVATE "-fgpu-rdc") + target_link_options(GPUTrackingHIPExternalProvider PRIVATE "-fgpu-rdc") + target_compile_definitions(GPUTrackingHIPExternalProvider PRIVATE $) + target_include_directories(GPUTrackingHIPExternalProvider PRIVATE $) +endif() diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 81832fe00e25d..aa81f2e6a0cb7 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -13,7 +13,7 @@ set(MODULE GPUTracking) # set(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} -O0") # to uncomment if needed, tired of typing this... -if(NOT ${GPUCA_NO_FAST_MATH} AND NOT CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG") +if(NOT "${GPUCA_NO_FAST_MATH}" AND NOT CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math") endif() @@ -453,6 +453,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") ${SRCS_NO_CINT} ${SRCS_NO_H} ${SRCS_DATATYPES} + ${SRCS_DATATYPE_HEADERS} G__Ali${MODULE}.cxx) target_link_libraries(Ali${MODULE} ${LIBDEPS}) @@ -479,7 +480,7 @@ endif() # Main CMake part for Standalone if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") - add_library(${MODULE} SHARED ${SRCS} ${SRCS_NO_CINT} ${SRCS_NO_H} ${SRCS_DATATYPES}) + add_library(${MODULE} SHARED ${SRCS} ${SRCS_NO_CINT} ${SRCS_NO_H} ${SRCS_DATATYPES} ${SRCS_DATATYPE_HEADERS}) set(targetName ${MODULE}) add_library(O2::${MODULE} ALIAS ${MODULE}) install(TARGETS ${MODULE}) diff --git a/GPU/GPUTracking/DataCompression/AliHLTTPCClusterStatComponent.cxx b/GPU/GPUTracking/DataCompression/AliHLTTPCClusterStatComponent.cxx index 54d6db3768ad2..3891e72a97243 100644 --- a/GPU/GPUTracking/DataCompression/AliHLTTPCClusterStatComponent.cxx +++ b/GPU/GPUTracking/DataCompression/AliHLTTPCClusterStatComponent.cxx @@ -467,7 +467,7 @@ int AliHLTTPCClusterStatComponent::DoEvent(const AliHLTComponentEventData& evtDa if (ip != 0) { int rowType = padrow < 64 ? 0 : (padrow < 128 ? 2 : 1); - prop.Update(xyz[1], xyz[2], rowType, *mSliceParam, 0, 0, nullptr, false); + prop.Update(xyz[1], xyz[2], rowType, *mSliceParam, 0, 0, nullptr, false, slice > 18, -1.f, 0.f, 0.f); } } if (hitsUsed) { diff --git a/GPU/GPUTracking/DataTypes/GPUO2FakeClasses.h b/GPU/GPUTracking/DataTypes/GPUO2FakeClasses.h index 9a1db75b11185..073d5e74c21ae 100644 --- a/GPU/GPUTracking/DataTypes/GPUO2FakeClasses.h +++ b/GPU/GPUTracking/DataTypes/GPUO2FakeClasses.h @@ -38,6 +38,8 @@ class TrackTPC }; class CalibdEdxContainer { + public: + static bool isDead(int slice, int row, int pad) { return false; } }; struct ClusterNative { GPUd() static float getTime() { return 0.f; } diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 1ee030f241e4a..bd1cd9859cbd2 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -643,9 +643,11 @@ int GPUChainTracking::DoQueuedUpdates(int stream, bool updateSlave) retVal = 1; } if (mUpdateNewCalibObjects) { +#ifdef GPUCA_HAVE_O2HEADERS if (mNewCalibObjects->o2Propagator && ((mNewCalibObjects->o2Propagator->getGPUField() != nullptr) ^ GetProcessingSettings().o2PropagatorUseGPUField)) { GPUFatal("GPU magnetic field for propagator requested, but received an O2 propagator without GPU field"); } +#endif void* const* pSrc = (void* const*)mNewCalibObjects.get(); void** pDst = (void**)&processors()->calibObjects; for (unsigned int i = 0; i < sizeof(processors()->calibObjects) / sizeof(void*); i++) { @@ -768,9 +770,11 @@ int GPUChainTracking::RunChain() } } +#ifdef GPUCA_HAVE_O2HEADERS if (GetProcessingSettings().trdTrackModelO2 ? runRecoStep(RecoStep::TRDTracking, &GPUChainTracking::RunTRDTracking) : runRecoStep(RecoStep::TRDTracking, &GPUChainTracking::RunTRDTracking)) { return 1; } +#endif if (runRecoStep(RecoStep::Refit, &GPUChainTracking::RunRefit)) { return 1; @@ -1010,7 +1014,9 @@ const o2::base::Propagator* GPUChainTracking::GetDeviceO2Propagator() void GPUChainTracking::SetO2Propagator(const o2::base::Propagator* prop) { processors()->calibObjects.o2Propagator = prop; +#ifdef GPUCA_HAVE_O2HEADERS if ((prop->getGPUField() != nullptr) ^ GetProcessingSettings().o2PropagatorUseGPUField) { GPUFatal("GPU magnetic field for propagator requested, but received an O2 propagator without GPU field"); } +#endif } diff --git a/GPU/GPUTracking/Global/GPUChainTrackingTRD.cxx b/GPU/GPUTracking/Global/GPUChainTrackingTRD.cxx index cf4fa40aff6bb..8e27de9511af4 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingTRD.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingTRD.cxx @@ -20,6 +20,7 @@ #include "GPUTRDTrack.h" #include "GPUTRDTracker.h" #include "GPUTrackingInputProvider.h" +#include "GPUTRDTrackerKernels.h" #include "utils/strtag.h" using namespace GPUCA_NAMESPACE::gpu; @@ -28,6 +29,7 @@ using namespace o2::trd; template int GPUChainTracking::RunTRDTracking() { +#ifndef GPUCA_ALIROOT_LIB if (!processors()->trdTrackerGPU.IsInitialized()) { return 1; } @@ -127,6 +129,7 @@ int GPUChainTracking::RunTRDTracking() } mRec->PopNonPersistentMemory(RecoStep::TRDTracking, qStr2Tag("TRDTRACK")); +#endif // GPUCA_ALIROOT_LIB return 0; } @@ -195,8 +198,8 @@ int GPUChainTracking::DoTRDGPUTracking(T* externalInstance) } template int GPUChainTracking::RunTRDTracking(); -template int GPUChainTracking::RunTRDTracking(); template int GPUChainTracking::DoTRDGPUTracking(GPUTRDTrackerGPU*); template int GPUChainTracking::DoTRDGPUTracking(GPUTRDTracker*); +template int GPUChainTracking::RunTRDTracking(); template int GPUChainTracking::DoTRDGPUTracking(GPUTRDTracker*); template int GPUChainTracking::DoTRDGPUTracking(GPUTRDTrackerGPU*); diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx index ec26f927806d5..1a9f9c536565e 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerGPU.cxx @@ -12,6 +12,7 @@ /// \file GPUTPCGMMergerGPU.cxx /// \author David Rohr +#if !defined(GPUCA_GPUCODE) || !defined(GPUCA_ALIROOT_LIB) // GPU Merger was not available for Run 2 #include "GPUTPCGMMergerGPU.h" #include "GPUCommonAlgorithm.h" #if defined(WITH_OPENMP) && !defined(GPUCA_GPUCODE) @@ -217,3 +218,4 @@ GPUdii() void GPUTPCGMMergerMergeLoopers::Thread<2>(int nBlocks, int nThreads, i { merger.MergeLoopersMain(nBlocks, nThreads, iBlock, iThread); } +#endif // !defined(GPUCA_GPUCODE) || !defined(GPUCA_ALIROOT_LIB) diff --git a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h index f8a3cf6236a32..8915408c63f87 100644 --- a/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h +++ b/GPU/GPUTracking/TRDTracking/GPUTRDInterfaces.h @@ -49,19 +49,19 @@ class trackInterface : public AliExternalTrackParam { public: - trackInterface() : AliExternalTrackParam(){}; - trackInterface(const trackInterface& param) : AliExternalTrackParam(param){}; - trackInterface(const AliExternalTrackParam& param) CON_DELETE; - trackInterface(const AliHLTExternalTrackParam& param) : AliExternalTrackParam() + trackInterface() : AliExternalTrackParam(){}; + trackInterface(const trackInterface& param) : AliExternalTrackParam(param){}; + trackInterface(const AliExternalTrackParam& param) CON_DELETE; + trackInterface(const AliHLTExternalTrackParam& param) : AliExternalTrackParam() { float paramTmp[5] = {param.fY, param.fZ, param.fSinPhi, param.fTgl, param.fq1Pt}; Set(param.fX, param.fAlpha, paramTmp, param.fC); } - trackInterface(const GPUTPCGMMergedTrack& trk) : AliExternalTrackParam() + trackInterface(const GPUTPCGMMergedTrack& trk) : AliExternalTrackParam() { Set(trk.GetParam().GetX(), trk.GetAlpha(), trk.GetParam().GetPar(), trk.GetParam().GetCov()); } - trackInterface(const gputpcgmmergertypes::GPUTPCOuterParam& param) : AliExternalTrackParam() + trackInterface(const gputpcgmmergertypes::GPUTPCOuterParam& param) : AliExternalTrackParam() { Set(param.X, param.alpha, param.P, param.C); } diff --git a/GPU/GPUTracking/cmake/kernel_helpers.cmake b/GPU/GPUTracking/cmake/kernel_helpers.cmake index 46fe975988bde..571303df4c6c2 100644 --- a/GPU/GPUTracking/cmake/kernel_helpers.cmake +++ b/GPU/GPUTracking/cmake/kernel_helpers.cmake @@ -105,7 +105,9 @@ function(o2_gpu_kernel_file_list list) define_property(TARGET PROPERTY O2_GPU_KERNELS_FILE_LIST_${list}) list(LENGTH ARGV n) if(2 GREATER ${n}) - message(FATAL_ERROR "File list must contain at least one file") + set_property(TARGET O2_GPU_KERNELS PROPERTY O2_GPU_KERNELS_FILE_LIST_${list} "-") + return() + # message(FATAL_ERROR "File list must contain at least one file") endif() if(list MATCHES "[^A-Z0-9_]") message(FATAL_ERROR "Invalid character in file list name ${list}") @@ -117,7 +119,9 @@ function(o2_gpu_kernel_file_list list) if(NOT TMP_SUB_FILE_LIST) message(FATAL_ERROR "Invalid file list ${ARGV${i}}") endif() - list(APPEND TMP_FILE_LIST ${TMP_SUB_FILE_LIST}) + if(NOT TMP_SUB_FILE_LIST STREQUAL "-") + list(APPEND TMP_FILE_LIST ${TMP_SUB_FILE_LIST}) + endif() else() list(APPEND TMP_FILE_LIST ${ARGV${i}}) set_property(TARGET O2_GPU_KERNELS APPEND PROPERTY O2_GPU_KERNEL_FILES "${ARGV${i}}") diff --git a/GPU/GPUTracking/kernels.cmake b/GPU/GPUTracking/kernels.cmake index 8bdb543230ab6..d4f5ca93e9def 100644 --- a/GPU/GPUTracking/kernels.cmake +++ b/GPU/GPUTracking/kernels.cmake @@ -17,15 +17,21 @@ o2_gpu_kernel_file_list(TPCTRACKER ERRORS GPUTPCTrackParam.cxx GPUTPCTrack.cxx G o2_gpu_kernel_file_list(TPCTRACKLETCONS GPUTPCTrackletConstructor.cxx) o2_gpu_kernel_file_list(TPCSLICEDATA TPCTRACKER GPUTPCSliceData.cxx) o2_gpu_kernel_file_list(TPCOCCUPANCY GPUTPCClusterOccupancyMap.cxx) +if(ALIGPU_BUILD_TYPE STREQUAL "O2" OR CONFIG_O2_EXTENSIONS) o2_gpu_kernel_file_list(TPCDEDX GPUdEdx.cxx) -o2_gpu_kernel_file_list(TPCMERGER ERRORS GPUTPCGMMerger.cxx GPUTPCGMSliceTrack.cxx GPUTPCGMTrackParam.cxx GPUTPCGMPhysicalTrackModel.cxx GPUTPCGMPropagator.cxx) o2_gpu_kernel_file_list(MATLUT MatLayerCylSet.cxx MatLayerCyl.cxx Ray.cxx) +o2_gpu_kernel_file_list(TPCMERGER ERRORS GPUTPCGMMerger.cxx GPUTPCGMSliceTrack.cxx GPUTPCGMTrackParam.cxx GPUTPCGMPhysicalTrackModel.cxx GPUTPCGMPropagator.cxx) o2_gpu_kernel_file_list(O2PROPAGATOR TrackParametrization.cxx TrackParametrizationWithError.cxx Propagator.cxx TrackLTIntegral.cxx) o2_gpu_kernel_file_list(TPCCOMPRESSION GPUTPCCompressionTrackModel.cxx) o2_gpu_kernel_file_list(TPCDECOMPRESSION GPUTPCCompressionTrackModel.cxx ERRORS) o2_gpu_kernel_file_list(TPCCLUSTERFINDER ERRORS ClusterAccumulator.cxx) o2_gpu_kernel_file_list(TRDTRACKER GPUTRDTrack.cxx GPUTRDTracker.cxx GPUTRDTrackletWord.cxx GeometryBase.cxx) o2_gpu_kernel_file_list(GLOBALREFIT TPCMERGER O2PROPAGATOR MATLUT GPUTrackingRefit.cxx) +else() +o2_gpu_kernel_file_list(TPCDEDX) +o2_gpu_kernel_file_list(MATLUT) +o2_gpu_kernel_file_list(TPCMERGER) +endif() o2_gpu_add_kernel("GPUTPCNeighboursFinder" "= TPCTRACKER" LB_OCL1 single) o2_gpu_add_kernel("GPUTPCNeighboursCleaner" "= TPCTRACKER" LB_OCL1 single) diff --git a/GPU/GPUTracking/qa/GPUQA.h b/GPU/GPUTracking/qa/GPUQA.h index d5fef788c099c..79580a737cdf2 100644 --- a/GPU/GPUTracking/qa/GPUQA.h +++ b/GPU/GPUTracking/qa/GPUQA.h @@ -57,6 +57,7 @@ class GPUQA void* AllocateScratchBuffer(size_t nBytes) { return nullptr; } static bool QAAvailable() { return false; } static bool IsInitialized() { return false; } + void UpdateChain(GPUChainTracking* chain) {} }; } // namespace gpu } // namespace GPUCA_NAMESPACE From b4af31f50c301f3f667e6023a1c9cde906200994 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 29 Mar 2024 23:50:46 +0100 Subject: [PATCH 0020/2997] ITS GPU: Fix missing include for GCC13 --- Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu index 42b0cb2ce2d5b..0ed5c58e29c43 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu @@ -20,6 +20,7 @@ #include #include #include +#include namespace { From 872ff06d0d280a008d97f1ae352e5e6aafb8aa0c Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 31 Mar 2024 20:37:49 +0200 Subject: [PATCH 0021/2997] GPU CXX Standard: should not force it to 20 but use CMAKE_CXX_STANDARD --- dependencies/FindO2GPU.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 3d32bbe693931..14d1e77838597 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -69,7 +69,7 @@ endfunction() STRING(REGEX REPLACE "\-std=[^ ]*" "" O2_GPU_CMAKE_CXX_FLAGS_NOSTD "${CMAKE_CXX_FLAGS}") # Need to strip c++17 imposed by alidist defaults if(ENABLE_CUDA) - set(CMAKE_CUDA_STANDARD 20) + set(CMAKE_CUDA_STANDARD ${CMAKE_CXX_STANDARD}) set(CMAKE_CUDA_STANDARD_REQUIRED TRUE) include(CheckLanguage) check_language(CUDA) @@ -209,7 +209,7 @@ endif() # Detect and enable HIP if(ENABLE_HIP) if("$ENV{CMAKE_PREFIX_PATH}" MATCHES "rocm") - set(CMAKE_HIP_STANDARD 20) + set(CMAKE_HIP_STANDARD ${CMAKE_CXX_STANDARD}) set(CMAKE_HIP_STANDARD_REQUIRED TRUE) if(HIP_AMDGPUTARGET) set(AMDGPU_TARGETS "${HIP_AMDGPUTARGET}" CACHE STRING "AMD GPU targets to compile for" FORCE) From e1dfa8efb087fe49f4a78f0f12fc8ad28df6de92 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 31 Mar 2024 21:26:53 +0200 Subject: [PATCH 0022/2997] GPU: Fix compiler errors/warnings when HIP flags leak into .cxx compilation --- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 5 +---- GPU/GPUTracking/Base/hip/CMakeLists.txt | 24 +++++++++++------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 6d49c83164b00..395e69c43457a 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -99,7 +99,6 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") TARGETVARNAME targetName) target_compile_definitions(${targetName} PUBLIC $) - set_target_properties(${targetName} PROPERTIES LINKER_LANGUAGE CXX) install(FILES ${HDRS} DESTINATION include/GPU) endif() @@ -118,9 +117,6 @@ if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") add_library_tested(${targetName} SHARED ${SRCS} G__${targetName}.cxx) target_link_libraries(${targetName} PUBLIC ${TMP_BASELIB}) - # Additional compilation flags - set_target_properties(${targetName} PROPERTIES COMPILE_FLAGS "") - # Installation install(TARGETS ${targetName} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib) @@ -197,6 +193,7 @@ else() endif() if(NOT GPUCA_CUDA_COMPILE_MODE STREQUAL "rdc") set_property(TARGET ${targetName} PROPERTY CUDA_SEPARABLE_COMPILATION OFF) + set_target_properties(${targetName} PROPERTIES LINKER_LANGUAGE CXX) endif() if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index d575c74e24a60..7044a8f7210eb 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -156,16 +156,14 @@ if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") generate_rootmap("${targetName}" "" "") # Add a library to the project using the specified source files - add_library_tested(${targetName} SHARED ${SRCS} G__${targetName}.cxx) + add_library_tested(${targetName} SHARED ${SRCS}) + set(SRCS_CXX ${SRCS_CXX} G__${targetName}.cxx) # CMake HIP language feature will parse hip flags to everything that is linked to hip libraries, so add the ROOT dictionary file here target_link_libraries(${targetName} PUBLIC ${TMP_BASELIB}) # ROOT Cannot load this library, so we have to remove it from the list list(REMOVE_ITEM ALILIBSTESTED ${targetName}) set(ALILIBSTESTED ${ALILIBSTESTED} CACHE INTERNAL "ALILIBSTESTED") - # Additional compilation flags - set_target_properties(${targetName} PROPERTIES COMPILE_FLAGS "") - # Installation install(TARGETS ${targetName} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib) @@ -182,7 +180,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") include_directories(${GPUCA_HIP_SOURCE_DIR}) endif() -add_library(${MODULE}_CXX OBJECT ${SRCS_CXX}) +add_library(${MODULE}_CXX OBJECT ${SRCS_CXX}) # Adding a C++ library for the .cxx code of the HIP library, such that it does not link to HIP libraries, and CMake HIP Language doesn't add HIP compile flags. target_compile_definitions(${MODULE}_CXX PRIVATE $) target_include_directories(${MODULE}_CXX PRIVATE $) target_link_libraries(${targetName} PRIVATE ${MODULE}_CXX) @@ -216,8 +214,8 @@ if(GPUCA_HIP_COMPILE_MODE STREQUAL "onefile") elseif(GPUCA_HIP_COMPILE_MODE STREQUAL "perkernel") add_library(GPUTrackingHIPKernels OBJECT $,REPLACE,[^A-Za-z0-9]+,_>,PREPEND,${O2_GPU_KERNEL_WRAPPER_FOLDER}/krnl_>,APPEND,.cu>, >) set_property(TARGET GPUTrackingHIPKernels PROPERTY HIP_FATBIN_COMPILATION ON) - target_compile_options(GPUTrackingHIPKernels PRIVATE "-fno-gpu-rdc") - target_link_options(GPUTrackingHIPKernels PRIVATE "-fno-gpu-rdc") + target_compile_options(GPUTrackingHIPKernels PRIVATE $<$:-fno-gpu-rdc>) + target_link_options(GPUTrackingHIPKernels PRIVATE $<$:-fno-gpu-rdc>) target_compile_definitions(${targetName} PRIVATE GPUCA_KERNEL_COMPILE_MODE=1) target_compile_definitions(GPUTrackingHIPKernels PRIVATE $) target_include_directories(GPUTrackingHIPKernels PRIVATE $) @@ -246,22 +244,22 @@ elseif(GPUCA_HIP_COMPILE_MODE STREQUAL "perkernel") elseif(GPUCA_HIP_COMPILE_MODE STREQUAL "rdc") message(FATAL_ERROR "HIP RDC compilation of GPUReconstruction ios not yet working!") target_compile_definitions(${targetName} PRIVATE GPUCA_KERNEL_COMPILE_MODE=2) - target_compile_options(${targetName} PRIVATE "-fgpu-rdc") - target_link_options(${targetName} PRIVATE "-fgpu-rdc") + target_compile_options(${targetName} PRIVATE $<$:-fgpu-rdc>) + target_link_options(${targetName} PRIVATE $<$:-fgpu-rdc>) target_sources(${targetName} PRIVATE $,REPLACE,[^A-Za-z0-9]+,_>,PREPEND,${O2_GPU_KERNEL_WRAPPER_FOLDER}/krnl_>,APPEND,.hip>, >) else() message(FATAL_ERROR "Invalid compile mode") endif() if(NOT GPUCA_HIP_COMPILE_MODE STREQUAL "rdc") - target_compile_options(${targetName} PRIVATE "-fno-gpu-rdc") - target_link_options(${targetName} PRIVATE "-fno-gpu-rdc") + target_compile_options(${targetName} PRIVATE $<$:-fno-gpu-rdc>) + target_link_options(${targetName} PRIVATE $<$:-fno-gpu-rdc>) endif() if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") add_library(GPUTrackingHIPExternalProvider OBJECT ${GPUCA_HIP_SOURCE_DIR}/GPUReconstructionHIPExternalProvider.hip) add_library(O2::GPUTrackingHIPExternalProvider ALIAS GPUTrackingHIPExternalProvider) - target_compile_options(GPUTrackingHIPExternalProvider PRIVATE "-fgpu-rdc") - target_link_options(GPUTrackingHIPExternalProvider PRIVATE "-fgpu-rdc") + target_compile_options(GPUTrackingHIPExternalProvider PRIVATE $<$:-fgpu-rdc>) + target_link_options(GPUTrackingHIPExternalProvider PRIVATE $<$:-fgpu-rdc>) target_compile_definitions(GPUTrackingHIPExternalProvider PRIVATE $) target_include_directories(GPUTrackingHIPExternalProvider PRIVATE $) endif() From f312b640dc4a8590f2d932d98caf28f29db029f6 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 29 Mar 2024 22:40:25 +0100 Subject: [PATCH 0023/2997] onnxruntime upstream uses onnxruntime::onnxruntime: Adhere to that and remain compatible with our custom onnxruntime build --- CMakeLists.txt | 5 +---- Detectors/ZDC/CMakeLists.txt | 2 +- Detectors/ZDC/fastsimulation/CMakeLists.txt | 2 +- Detectors/ZDC/simulation/CMakeLists.txt | 2 +- dependencies/FindONNXRuntime.cmake | 20 ++++++++++++++++++++ 5 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 dependencies/FindONNXRuntime.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index deacb50958b84..d28f191021fdf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,10 +41,7 @@ o2_build_sanity_checks() set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED TRUE) -find_package(ONNXRuntime::ONNXRuntime CONFIG) -if (ONNXRuntime::ONNXRuntime_FOUND) - add_definitions(-DZDC_FASTSIM_ONNX) -endif() +include(dependencies/FindONNXRuntime.cmake) include(O2CheckCXXFeatures) o2_check_cxx_features() diff --git a/Detectors/ZDC/CMakeLists.txt b/Detectors/ZDC/CMakeLists.txt index c9f51fc56c903..d3c6a661a8131 100644 --- a/Detectors/ZDC/CMakeLists.txt +++ b/Detectors/ZDC/CMakeLists.txt @@ -9,7 +9,7 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -if (ONNXRuntime::ONNXRuntime_FOUND) +if (onnxruntime_FOUND) add_subdirectory(fastsimulation) endif() add_subdirectory(base) diff --git a/Detectors/ZDC/fastsimulation/CMakeLists.txt b/Detectors/ZDC/fastsimulation/CMakeLists.txt index c3ce25b9cc28c..ec65489366d22 100644 --- a/Detectors/ZDC/fastsimulation/CMakeLists.txt +++ b/Detectors/ZDC/fastsimulation/CMakeLists.txt @@ -14,7 +14,7 @@ o2_add_library(FASTSimulation SOURCES src/FastSimulations.cxx src/Processors.cxx src/Utils.cxx - PUBLIC_LINK_LIBRARIES ONNXRuntime::ONNXRuntime) + PUBLIC_LINK_LIBRARIES onnxruntime::onnxruntime) o2_data_file(COPY scales DESTINATION Detectors/ZDC/fastsimulation) diff --git a/Detectors/ZDC/simulation/CMakeLists.txt b/Detectors/ZDC/simulation/CMakeLists.txt index 96eef618c79d8..d0dcb2ff577b3 100644 --- a/Detectors/ZDC/simulation/CMakeLists.txt +++ b/Detectors/ZDC/simulation/CMakeLists.txt @@ -17,7 +17,7 @@ list(APPEND LinkLibraries O2::SimulationDataFormat O2::DetectorsRaw O2::Headers) -if (ONNXRuntime::ONNXRuntime_FOUND) +if (onnxruntime_FOUND) list(APPEND LinkLibraries O2::FASTSimulation) endif() diff --git a/dependencies/FindONNXRuntime.cmake b/dependencies/FindONNXRuntime.cmake new file mode 100644 index 0000000000000..4915965cbc05f --- /dev/null +++ b/dependencies/FindONNXRuntime.cmake @@ -0,0 +1,20 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +find_package(onnxruntime CONFIG) +if (NOT onnxruntime_FOUND) + find_package(ONNXRuntime::ONNXRuntime CONFIG) + if (ONNXRuntime::ONNXRuntime_FOUND) + add_definitions(-DZDC_FASTSIM_ONNX) + set(onnxruntime_FOUND 1) + add_library(onnxruntime::onnxruntime ALIAS ONNXRuntime::ONNXRuntime) + endif() +endif() From cf7b5ff524157f00ee1005f205fe4c6ef009bf3e Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 30 Mar 2024 10:02:48 +0100 Subject: [PATCH 0024/2997] ZDC Sim: Don't set ZDC_FASTSIM_ONNX as global define but as target compile definition --- Detectors/ZDC/simulation/CMakeLists.txt | 4 ++++ dependencies/FindONNXRuntime.cmake | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Detectors/ZDC/simulation/CMakeLists.txt b/Detectors/ZDC/simulation/CMakeLists.txt index d0dcb2ff577b3..dda2e019c02b9 100644 --- a/Detectors/ZDC/simulation/CMakeLists.txt +++ b/Detectors/ZDC/simulation/CMakeLists.txt @@ -22,11 +22,15 @@ if (onnxruntime_FOUND) endif() o2_add_library(ZDCSimulation + TARGETVARNAME targetName SOURCES src/Detector.cxx src/Digitizer.cxx src/SimCondition.cxx src/ZDCSimParam.cxx src/SpatialPhotonResponse.cxx src/Digits2Raw.cxx src/DigitizerTest.cxx PUBLIC_LINK_LIBRARIES ${LinkLibraries}) +if (onnxruntime_FOUND) + target_compile_definitions(${targetName} PUBLIC ZDC_FASTSIM_ONNX) +endif() o2_target_root_dictionary(ZDCSimulation HEADERS include/ZDCSimulation/Digitizer.h diff --git a/dependencies/FindONNXRuntime.cmake b/dependencies/FindONNXRuntime.cmake index 4915965cbc05f..b34782e99050f 100644 --- a/dependencies/FindONNXRuntime.cmake +++ b/dependencies/FindONNXRuntime.cmake @@ -13,7 +13,6 @@ find_package(onnxruntime CONFIG) if (NOT onnxruntime_FOUND) find_package(ONNXRuntime::ONNXRuntime CONFIG) if (ONNXRuntime::ONNXRuntime_FOUND) - add_definitions(-DZDC_FASTSIM_ONNX) set(onnxruntime_FOUND 1) add_library(onnxruntime::onnxruntime ALIAS ONNXRuntime::ONNXRuntime) endif() From 5a5d73ca888e01158780d22047e473737699192f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 30 Mar 2024 10:05:01 +0100 Subject: [PATCH 0025/2997] ZDC: Fix copyright statement syntax --- Detectors/ZDC/fastsimulation/CMakeLists.txt | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Detectors/ZDC/fastsimulation/CMakeLists.txt b/Detectors/ZDC/fastsimulation/CMakeLists.txt index ec65489366d22..527a7ca2553a2 100644 --- a/Detectors/ZDC/fastsimulation/CMakeLists.txt +++ b/Detectors/ZDC/fastsimulation/CMakeLists.txt @@ -1,13 +1,13 @@ -# Copyright 2019-2020 CERN and copyright holders of ALICE O2. -# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -# All rights not expressly granted are reserved. - -# This software is distributed under the terms of the GNU General Public -# License v3 (GPL Version 3), copied verbatim in the file "COPYING". - -# In applying this license CERN does not waive the privileges and immunities -# granted to it by virtue of its status as an Intergovernmental Organization -# or submit itself to any jurisdiction. +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. # @author SwirtaB @@ -22,4 +22,3 @@ o2_add_executable(fastsim-example SOURCES tests/run-example.cxx PUBLIC_LINK_LIBRARIES O2::FASTSimulation COMPONENT_NAME zdc) - From 9cbf7a5499d1499849c73f86e3e55f5e6f75b9e9 Mon Sep 17 00:00:00 2001 From: pillot Date: Mon, 1 Apr 2024 12:27:31 +0200 Subject: [PATCH 0026/2997] new functionalities to fill MCH status map (#12945) --- .../MCH/Status/include/MCHStatus/StatusMap.h | 28 +++++- Detectors/MUON/MCH/Status/src/StatusMap.cxx | 59 ++++++++++++- .../MUON/MCH/Status/src/testStatusMap.cxx | 86 +++++++++++++++++-- 3 files changed, 158 insertions(+), 15 deletions(-) diff --git a/Detectors/MUON/MCH/Status/include/MCHStatus/StatusMap.h b/Detectors/MUON/MCH/Status/include/MCHStatus/StatusMap.h index 8d082f9fe34a9..7e7bb707588f5 100644 --- a/Detectors/MUON/MCH/Status/include/MCHStatus/StatusMap.h +++ b/Detectors/MUON/MCH/Status/include/MCHStatus/StatusMap.h @@ -13,6 +13,8 @@ #define O2_MCH_CONDITIONS_STATUSMAP_H #include "MCHGlobalMapping/ChannelCode.h" +#include "MCHGlobalMapping/DsIndex.h" +#include "MCHRawElecMap/DsDetId.h" #include "DataFormatsMCH/DsChannelId.h" #include #include @@ -29,12 +31,13 @@ namespace o2::mch * Each potentially bad channel is ascribed a 32-bits mask that indicate * the source of information used to incriminate it. * - * So far only two sources exist : + * So far only three sources exist : * - kBadPedestal : the list generated at each pedestal run at Pt2 * - kRejectList : a (manual) list + * - kBadHV : the list derived from the DCS HV values * * In the future (based on our experience during Run1,2), we'll most probably - * need to add information from the DCS HV (and possibly LV) values as well. + * need to add information from the DCS LV values as well. * */ class StatusMap @@ -43,7 +46,8 @@ class StatusMap enum Status : uint32_t { kOK = 0, kBadPedestal = 1 << 0, - kRejectList = 1 << 1 + kRejectList = 1 << 1, + kBadHV = 1 << 2 }; using iterator = std::map::iterator; @@ -67,6 +71,24 @@ class StatusMap */ void add(gsl::span badchannels, uint32_t mask); + /** add all the channels of the badDS referenced using DsIndex + * to this status map, assigning them the corresponding mask. + * @throw runtime_error if the mask is invalid + */ + void addDS(DsIndex badDS, uint32_t mask); + + /** add all the channels of the badDS referenced using DsDetId + * to this status map, assigning them the corresponding mask. + * @throw runtime_error if the mask is invalid + */ + void addDS(raw::DsDetId badDS, uint32_t mask); + + /** add all the channels of the badDE referenced using DE Id + * to this status map, assigning them the corresponding mask. + * @throw runtime_error if the mask is invalid + */ + void addDE(uint16_t badDE, uint32_t mask); + /** whether or not this statusmap contains no (potentially) bad channels */ bool empty() const { return mStatus.empty(); } diff --git a/Detectors/MUON/MCH/Status/src/StatusMap.cxx b/Detectors/MUON/MCH/Status/src/StatusMap.cxx index 40957186ba244..3a4d3bee0d617 100644 --- a/Detectors/MUON/MCH/Status/src/StatusMap.cxx +++ b/Detectors/MUON/MCH/Status/src/StatusMap.cxx @@ -10,7 +10,12 @@ // or submit itself to any jurisdiction. #include "MCHStatus/StatusMap.h" + +#include + #include "Framework/Logger.h" +#include "MCHConstants/DetectionElements.h" +#include "MCHMappingInterface/Segmentation.h" #include @@ -21,7 +26,7 @@ namespace o2::mch void assertValidMask(uint32_t mask) { - uint32_t maxMask = StatusMap::kBadPedestal + StatusMap::kRejectList; + static constexpr uint32_t maxMask = StatusMap::kBadPedestal | StatusMap::kRejectList | StatusMap::kBadHV; if (mask > maxMask) { throw std::runtime_error(fmt::format("invalid mask {} (max allowed is {}", mask, maxMask)); @@ -36,8 +41,8 @@ void StatusMap::add(gsl::span badchannels, uint32_t mask) ChannelCode cc(id.getSolarId(), id.getElinkId(), id.getChannel()); mStatus[cc] |= mask; } catch (const std::exception& e) { - // Catch exceptions thrown by the ChannelCode constructor - LOGP(warning, "Error processing channel - SolarId: {} ElinkId: {} Channel: {}. Error: {}. This channel is skipped.", id.getSolarId(), id.getElinkId(), id.getChannel(), e.what()); + LOGP(warning, "Error processing channel - SolarId: {} ElinkId: {} Channel: {}. Error: {}. This channel is skipped.", + id.getSolarId(), id.getElinkId(), id.getChannel(), e.what()); } } } @@ -50,6 +55,54 @@ void StatusMap::add(gsl::span badchannels, uint32_t mask) } } +void StatusMap::addDS(DsIndex badDS, uint32_t mask) +{ + if (badDS >= NumberOfDualSampas) { + LOGP(warning, "Error processing Dual Sampa - index: {}. This DS is skipped.", badDS); + return; + } + addDS(getDsDetId(badDS), mask); +} + +void StatusMap::addDS(raw::DsDetId badDS, uint32_t mask) +{ + assertValidMask(mask); + auto deId = badDS.deId(); + if (!constants::isValidDetElemId(deId)) { + LOGP(warning, "Error processing Dual Sampa - {}. This DS is skipped.", raw::asString(badDS)); + return; + } + const auto& seg = mapping::segmentation(deId); + seg.forEachPadInDualSampa(badDS.dsId(), [&](int dePadIndex) { + try { + ChannelCode cc(deId, dePadIndex); + mStatus[cc] |= mask; + } catch (const std::exception& e) { + LOGP(warning, "Error processing channel - {} padIndex: {}. Error: {}. This channel is skipped.", + raw::asString(badDS), dePadIndex, e.what()); + } + }); +} + +void StatusMap::addDE(uint16_t badDE, uint32_t mask) +{ + assertValidMask(mask); + if (!constants::isValidDetElemId(badDE)) { + LOGP(warning, "Error processing DE - Id: {}. This DE is skipped.", badDE); + return; + } + const auto& seg = mapping::segmentation(badDE); + seg.forEachPad([&](int dePadIndex) { + try { + ChannelCode cc(badDE, dePadIndex); + mStatus[cc] |= mask; + } catch (const std::exception& e) { + LOGP(warning, "Error processing channel - deId: {} padIndex: {}. Error: {}. This channel is skipped.", + badDE, dePadIndex, e.what()); + } + }); +} + uint32_t StatusMap::status(const ChannelCode& id) const { auto s = mStatus.find(id); diff --git a/Detectors/MUON/MCH/Status/src/testStatusMap.cxx b/Detectors/MUON/MCH/Status/src/testStatusMap.cxx index 3fd737ad06ede..2ab7ebba79dab 100644 --- a/Detectors/MUON/MCH/Status/src/testStatusMap.cxx +++ b/Detectors/MUON/MCH/Status/src/testStatusMap.cxx @@ -18,6 +18,7 @@ #include #include "MCHGlobalMapping/ChannelCode.h" +#include "MCHGlobalMapping/DsIndex.h" #include "MCHStatus/StatusMap.h" #include @@ -39,6 +40,12 @@ std::vector cc{ {1025, 8}, {515, 1863}}; +o2::mch::DsIndex ds = 246; // 56 pads, contains chid[1] + +uint16_t de = 1025; // 6976 pads, contains cc[2] + +uint32_t badMask = 1 << 3; + BOOST_AUTO_TEST_CASE(ClearShouldGiveEmptyMap) { o2::mch::StatusMap statusMap; @@ -50,21 +57,35 @@ BOOST_AUTO_TEST_CASE(ClearShouldGiveEmptyMap) BOOST_AUTO_TEST_CASE(AddChannelIdWithInvalidMaskShouldThrow) { o2::mch::StatusMap statusMap; - BOOST_CHECK_THROW(statusMap.add(chid, 4), std::runtime_error); + BOOST_CHECK_THROW(statusMap.add(chid, badMask), std::runtime_error); } BOOST_AUTO_TEST_CASE(AddChannelCodeWithInvalidMaskShouldThrow) { o2::mch::StatusMap statusMap; - BOOST_CHECK_THROW(statusMap.add(cc, 4), std::runtime_error); + BOOST_CHECK_THROW(statusMap.add(cc, badMask), std::runtime_error); } -std::array maskList = { +BOOST_AUTO_TEST_CASE(AddDSWithInvalidMaskShouldThrow) +{ + o2::mch::StatusMap statusMap; + BOOST_CHECK_THROW(statusMap.addDS(0, badMask), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(AddDEWithInvalidMaskShouldThrow) +{ + o2::mch::StatusMap statusMap; + BOOST_CHECK_THROW(statusMap.addDE(100, badMask), std::runtime_error); +} + +std::array maskList = { o2::mch::StatusMap::kBadPedestal, o2::mch::StatusMap::kRejectList, - o2::mch::StatusMap::kRejectList + o2::mch::StatusMap::kBadPedestal}; + o2::mch::StatusMap::kBadHV, + o2::mch::StatusMap::kBadPedestal | o2::mch::StatusMap::kBadHV, + o2::mch::StatusMap::kRejectList | o2::mch::StatusMap::kBadPedestal | o2::mch::StatusMap::kBadHV}; -BOOST_DATA_TEST_CASE(CheckAddedChannelsGetTheRightMask, bdata::xrange(maskList.size() + 1), maskIndex) +BOOST_DATA_TEST_CASE(CheckAddedChannelsGetTheRightMask, bdata::xrange(maskList.size()), maskIndex) { o2::mch::StatusMap statusMap; auto mask = maskList[maskIndex]; @@ -74,15 +95,62 @@ BOOST_DATA_TEST_CASE(CheckAddedChannelsGetTheRightMask, bdata::xrange(maskList.s } } +BOOST_AUTO_TEST_CASE(CheckChannelStatusCombination) +{ + auto size = [](const o2::mch::StatusMap& statusMap) { + int n = 0; + for (const auto& status : statusMap) { + ++n; + } + return n; + }; + o2::mch::StatusMap statusMap; + statusMap.add(cc, o2::mch::StatusMap::kBadPedestal); + BOOST_CHECK_EQUAL(size(statusMap), 4); + statusMap.add(chid, o2::mch::StatusMap::kRejectList); + BOOST_CHECK_EQUAL(size(statusMap), 4); + statusMap.addDS(ds, o2::mch::StatusMap::kBadHV); + BOOST_CHECK_EQUAL(size(statusMap), 59); + statusMap.addDE(de, o2::mch::StatusMap::kBadHV); + BOOST_CHECK_EQUAL(size(statusMap), 7034); + BOOST_CHECK_EQUAL(statusMap.status(cc[0]), o2::mch::StatusMap::kBadPedestal | o2::mch::StatusMap::kRejectList); + BOOST_CHECK_EQUAL(statusMap.status(cc[1]), o2::mch::StatusMap::kBadPedestal | o2::mch::StatusMap::kRejectList | o2::mch::StatusMap::kBadHV); + BOOST_CHECK_EQUAL(statusMap.status(cc[2]), o2::mch::StatusMap::kBadPedestal | o2::mch::StatusMap::kBadHV); + BOOST_CHECK_EQUAL(statusMap.status(cc[3]), o2::mch::StatusMap::kBadPedestal); +} + BOOST_AUTO_TEST_CASE(ApplyMaskShouldReturnASubsetDependingOnMask) { + auto size = [](const std::map>& badChannels) { + int n = 0; + for (const auto& channels : badChannels) { + n += channels.second.size(); + } + return n; + }; o2::mch::StatusMap statusMap; statusMap.add(cc, o2::mch::StatusMap::kBadPedestal); statusMap.add(chid, o2::mch::StatusMap::kRejectList); + statusMap.addDS(ds, o2::mch::StatusMap::kBadHV); + statusMap.addDE(de, o2::mch::StatusMap::kBadHV); auto badPed = applyMask(statusMap, o2::mch::StatusMap::kBadPedestal); auto rejectList = applyMask(statusMap, o2::mch::StatusMap::kRejectList); - auto all = applyMask(statusMap, o2::mch::StatusMap::kBadPedestal | o2::mch::StatusMap::kRejectList); - BOOST_CHECK_EQUAL(badPed.size(), cc.size()); - BOOST_CHECK_EQUAL(rejectList.size(), chid.size()); - BOOST_CHECK_EQUAL(all.size(), 4); + auto badHV = applyMask(statusMap, o2::mch::StatusMap::kBadHV); + auto badHVOrRL = applyMask(statusMap, o2::mch::StatusMap::kBadHV | o2::mch::StatusMap::kRejectList); + auto any = applyMask(statusMap, o2::mch::StatusMap::kBadPedestal | o2::mch::StatusMap::kRejectList | o2::mch::StatusMap::kBadHV); + BOOST_CHECK_EQUAL(badPed.size(), 4); + BOOST_CHECK_EQUAL(size(badPed), 4); + BOOST_CHECK_EQUAL(badPed[1025][0], 8); + BOOST_CHECK_EQUAL(rejectList.size(), 2); + BOOST_CHECK_EQUAL(size(rejectList), 2); + BOOST_CHECK_EQUAL(rejectList[100][0], 15665); + BOOST_CHECK_EQUAL(badHV.size(), 2); + BOOST_CHECK_EQUAL(size(badHV), 7032); + BOOST_CHECK_EQUAL(badHV[1025].size(), 6976); + BOOST_CHECK_EQUAL(badHVOrRL.size(), 3); + BOOST_CHECK_EQUAL(size(badHVOrRL), 7033); + BOOST_CHECK_EQUAL(badHVOrRL[515].size(), 0); + BOOST_CHECK_EQUAL(any.size(), 4); + BOOST_CHECK_EQUAL(size(any), 7034); + BOOST_CHECK_EQUAL(any[302][0], 20117); } From b55b8bd78203a407bcff0f791602c6802bdb4652 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 1 Apr 2024 16:01:26 +0200 Subject: [PATCH 0027/2997] Fix in the RCT updater deployment --- Detectors/GRP/workflows/src/rct-updater-workflow.cxx | 2 +- prodtests/full-system-test/dpl-workflow.sh | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Detectors/GRP/workflows/src/rct-updater-workflow.cxx b/Detectors/GRP/workflows/src/rct-updater-workflow.cxx index 1e82db670e992..e5f64f32e2a7a 100644 --- a/Detectors/GRP/workflows/src/rct-updater-workflow.cxx +++ b/Detectors/GRP/workflows/src/rct-updater-workflow.cxx @@ -131,7 +131,7 @@ class RCTUpdaterSpec : public o2::framework::Task if (mCCDBApi) { int retValRCT = mCCDBApi->updateMetadata("RCT/Info/RunInformation", mdRCT, startValRCT); if (retValRCT == 0) { - LOGP(info, "Updated RCT object for run {} with TF start:{} end:{}", mRunNumber, mdRCT["STF"], mdRCT["ETF"]); + LOGP(info, "Updated {}/RCT/Info/RunInformation object for run {} with TF start:{} end:{}", mCCDBApi->getURL(), mRunNumber, mdRCT["STF"], mdRCT["ETF"]); } else { LOGP(alarm, "Update of RCT object for run {} with TF start:{} end:{} FAILED, returned with code {}", mRunNumber, mdRCT["STF"], mdRCT["ETF"], retValRCT); } diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index a9fc62a704b8e..c6e01a5ac9c3e 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -30,8 +30,6 @@ fi : ${CTF_FREE_DISK_WAIT:="10"} # if disk on EPNs is close to full, wait X seconds before retrying to write : ${CTF_MAX_FREE_DISK_WAIT:="600"} # if not enough disk space after this time throw error -export CALIB_RCT_UPDATER=0 - # entropy encoding/decoding mode, '' is equivalent to '--ans-version compat' (compatible with < 09/2023 data), # use '--ans-version 1.0 --ctf-dict none' for the new per-TF dictionary mode : ${RANS_OPT:="--ans-version 1.0 --ctf-dict none"} @@ -603,7 +601,6 @@ if has_processing_step ENTROPY_ENCODER && [[ ! -z "$WORKFLOW_DETECTORS_CTF" ]] & if [[ $CREATECTFDICT == 1 ]] && [[ $EXTINPUT == 1 ]]; then CONFIG_CTF+=" --save-dict-after $SAVE_CTFDICT_NTIMEFRAMES"; fi [[ $EPNSYNCMODE == 1 ]] && CONFIG_CTF+=" --require-free-disk 53687091200 --wait-for-free-disk $CTF_FREE_DISK_WAIT --max-wait-for-free-disk $CTF_MAX_FREE_DISK_WAIT" add_W o2-ctf-writer-workflow "$CONFIG_CTF" - [[ $SYNCMODE == 1 ]] && export CALIB_RCT_UPDATER=1 fi # --------------------------------------------------------------------------------------------------------------------- From fa06b8d46ef29fc34fefe95a050bd3dfad88f083 Mon Sep 17 00:00:00 2001 From: nicolovalle <35177278+nicolovalle@users.noreply.github.com> Date: Mon, 1 Apr 2024 21:50:52 +0200 Subject: [PATCH 0028/2997] ITS efficiency maps protection for digitization out of range (#12889) * ITS efficiency maps pretection for digitization out of range * ITS efficiency maps pretection for digitization out of range * ITS efficiency maps pretection for digitization out of range * typo in info message * sending message at EOR to infologger * fix formatting * fix * fix --------- Co-authored-by: Nicolo Valle --- .../include/DataFormatsITSMFT/TimeDeadMap.h | 21 +++++++++++-------- .../workflow/src/DeadMapBuilderSpec.cxx | 14 ++++++------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h index aaf7a1a95aa04..6afcb258e76b6 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h @@ -73,8 +73,8 @@ class TimeDeadMap } } - void decodeMap(unsigned long orbit, o2::itsmft::NoiseMap& noisemap, bool includeStaticMap = true) - { // for time-dependent and (optionally) static part + void decodeMap(unsigned long orbit, o2::itsmft::NoiseMap& noisemap, bool includeStaticMap = true, long orbitGapAllowed = 330000) + { // for time-dependent and (optionally) static part. Use orbitGapAllowed = -1 to ignore check on orbit difference if (mMAP_VERSION != "3" && mMAP_VERSION != "4") { LOG(error) << "Trying to decode time-dependent deadmap version " << mMAP_VERSION << ". Not implemented, doing nothing."; @@ -84,14 +84,16 @@ class TimeDeadMap if (mEvolvingDeadMap.empty()) { LOG(warning) << "Time-dependent dead map is empty. Doing nothing."; return; - } else if (orbit > mEvolvingDeadMap.rbegin()->first + 11000 * 300 || orbit < mEvolvingDeadMap.begin()->first - 11000 * 300) { - // the map should not leave several minutes uncovered. - LOG(warning) << "Time-dependent dead map: the requested orbit " << orbit << " seems to be out of the range stored in the map."; } std::vector closestVec; long dT = getMapAtOrbit(orbit, closestVec); + if (orbitGapAllowed >= 0 && std::abs(dT) > orbitGapAllowed) { + LOG(warning) << "Requested orbit " << orbit << ", found " << orbit - dT << ". Orbit gap is too high, skipping time-dependent map."; + closestVec.clear(); + } + // add static part if requested. something may be masked twice if (includeStaticMap && mMAP_VERSION != "3") { closestVec.insert(closestVec.end(), mStaticDeadMap.begin(), mStaticDeadMap.end()); @@ -125,18 +127,19 @@ class TimeDeadMap void getStaticMap(std::vector& mmap) { mmap = mStaticDeadMap; }; long getMapAtOrbit(unsigned long orbit, std::vector& mmap) - { // fills mmap and returns orbit - lower_bound + { // fills mmap and returns requested_orbit - found_orbit. Found orbit is the highest key lower or equal to the requested one if (mEvolvingDeadMap.empty()) { LOG(warning) << "Requested orbit " << orbit << "from an empty time-dependent map. Doing nothing"; return (long)orbit; } auto closest = mEvolvingDeadMap.lower_bound(orbit); - if (closest != mEvolvingDeadMap.end()) { + if (closest != mEvolvingDeadMap.begin()) { + --closest; mmap = closest->second; return (long)orbit - closest->first; } else { - mmap = mEvolvingDeadMap.rbegin()->second; - return (long)(orbit)-mEvolvingDeadMap.rbegin()->first; + mmap = mEvolvingDeadMap.begin()->second; + return (long)(orbit)-mEvolvingDeadMap.begin()->first; } } diff --git a/Detectors/ITSMFT/common/workflow/src/DeadMapBuilderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/DeadMapBuilderSpec.cxx index 3194a62d6b273..362787500a617 100644 --- a/Detectors/ITSMFT/common/workflow/src/DeadMapBuilderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/DeadMapBuilderSpec.cxx @@ -269,9 +269,9 @@ void ITSMFTDeadMapBuilder::PrepareOutputCcdb(EndOfStreamContext* ec, std::string if (ec != nullptr) { - LOG(info) << "Sending object " << info.getPath() << "/" << info.getFileName() - << "to ccdb-populator, of size " << image->size() << " bytes, valid for " - << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + LOG(important) << "Sending object " << info.getPath() << "/" << info.getFileName() + << "to ccdb-populator, of size " << image->size() << " bytes, valid for " + << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); if (mRunMFT) { ec->outputs().snapshot(Output{o2::calibration::Utils::gDataOriginCDBPayload, "TimeDeadMap", 1}, *image.get()); @@ -284,9 +284,9 @@ void ITSMFTDeadMapBuilder::PrepareOutputCcdb(EndOfStreamContext* ec, std::string else if (!ccdburl.empty()) { // send from this workflow - LOG(info) << mSelfName << "sending object " << ccdburl << "/browse/" << info.getFileName() - << " of size " << image->size() << " bytes, valid for " - << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); + LOG(important) << mSelfName << "sending object " << ccdburl << "/browse/" << info.getPath() << "/" << info.getFileName() + << " of size " << image->size() << " bytes, valid for " + << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); o2::ccdb::CcdbApi mApi; mApi.init(ccdburl); @@ -335,7 +335,7 @@ void ITSMFTDeadMapBuilder::stop() LOG(warning) << "endOfStream not processed. Sending output to ccdb from the " << detname << "deadmap builder workflow."; PrepareOutputCcdb(nullptr, mCCDBUrl); } else { - LOG(warning) << "endOfStream not processed. Nothing forwarded as output."; + LOG(alarm) << "endOfStream not processed. Nothing forwarded as output."; } isEnded = true; } From 13dccf66b68e5b606056915253173c660567eb30 Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Tue, 2 Apr 2024 09:44:55 +0200 Subject: [PATCH 0029/2997] [EMCAL-752] Fix number of LEDMON channel in Pedestal object (#12959) - In total, only 480 LEDMON channels are in the EMCal (was 17664 in the code) - Subsequently also modified the plotting of the 2D map of the object Co-authored-by: jokonig --- .../EMCAL/calib/include/EMCALCalib/Pedestal.h | 8 ++++---- Detectors/EMCAL/calib/src/Pedestal.cxx | 17 ++++++++++++----- Detectors/EMCAL/calib/test/testPedestal.cxx | 18 +++++++++++------- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/Detectors/EMCAL/calib/include/EMCALCalib/Pedestal.h b/Detectors/EMCAL/calib/include/EMCALCalib/Pedestal.h index 8b6e9ffbb0477..7a8983409d995 100644 --- a/Detectors/EMCAL/calib/include/EMCALCalib/Pedestal.h +++ b/Detectors/EMCAL/calib/include/EMCALCalib/Pedestal.h @@ -82,10 +82,10 @@ class Pedestal TH2* getHistogramRepresentation2D(bool isLowGain, bool isLEDMON) const; private: - std::array mPedestalValuesHG; ///< Container for the pedestal values (high gain) - std::array mPedestalValuesLG; ///< Container for the pedestal values (low gain) - std::array mPedestalValuesLEDMONHG; ///< Container for the LEDMON pedestal values (high gain) - std::array mPedestalValuesLEDMONLG; ///< Container for the LEDMON pedestal values (low gain) + std::array mPedestalValuesHG; ///< Container for the pedestal values (high gain) + std::array mPedestalValuesLG; ///< Container for the pedestal values (low gain) + std::array mPedestalValuesLEDMONHG; ///< Container for the LEDMON pedestal values (high gain) + std::array mPedestalValuesLEDMONLG; ///< Container for the LEDMON pedestal values (low gain) ClassDefNV(Pedestal, 1); }; diff --git a/Detectors/EMCAL/calib/src/Pedestal.cxx b/Detectors/EMCAL/calib/src/Pedestal.cxx index 1d628d3d0fb09..7d67205fc7943 100644 --- a/Detectors/EMCAL/calib/src/Pedestal.cxx +++ b/Detectors/EMCAL/calib/src/Pedestal.cxx @@ -124,15 +124,22 @@ TH2* Pedestal::getHistogramRepresentation2D(bool isLowGain, bool isLEDMON) const } } - const int MAXROWS = 208, - MAXCOLS = 96; + const int MAXROWS = isLEDMON ? 10 : 208, + MAXCOLS = isLEDMON ? 48 : 96; + auto hist = new TH2S(histname.data(), histtitle.data(), MAXCOLS, -0.5, double(MAXCOLS) - 0.5, MAXROWS, -0.5, double(MAXROWS) - 0.5); hist->SetDirectory(nullptr); try { auto geo = Geometry::GetInstance(); - for (size_t cellID = 0; cellID < data.size(); cellID++) { - auto position = geo->GlobalRowColFromIndex(cellID); - hist->Fill(std::get<1>(position), std::get<0>(position), data[cellID]); + for (size_t ichan = 0; ichan < data.size(); ichan++) { + if (isLEDMON) { + int col = ichan % 48, + row = ichan / 48; + hist->Fill(col, row, data[ichan]); + } else { + auto position = geo->GlobalRowColFromIndex(ichan); + hist->Fill(std::get<1>(position), std::get<0>(position), data[ichan]); + } } } catch (o2::emcal::GeometryNotInitializedException& e) { LOG(error) << "Geometry needs to be initialized"; diff --git a/Detectors/EMCAL/calib/test/testPedestal.cxx b/Detectors/EMCAL/calib/test/testPedestal.cxx index c22579c6db0ca..1adcfd8b9ea25 100644 --- a/Detectors/EMCAL/calib/test/testPedestal.cxx +++ b/Detectors/EMCAL/calib/test/testPedestal.cxx @@ -26,14 +26,14 @@ namespace o2 namespace emcal { -using pedestalarray = std::array; +using pedestalarray = std::vector; -pedestalarray createRandomPedestals() +pedestalarray createRandomPedestals(bool isLEDMON) { std::random_device rd{}; std::mt19937 gen{rd()}; std::normal_distribution gaussrand{40., 5.}; - pedestalarray pedestalcontainer; + pedestalarray pedestalcontainer(isLEDMON ? 480 : 17664); for (std::size_t ichan{0}; ichan < pedestalcontainer.size(); ++ichan) { pedestalcontainer[ichan] = std::round(gaussrand(gen)); } @@ -52,15 +52,17 @@ pedestalarray shiftPedestalValue(const pedestalarray& input, short shift = 1) BOOST_AUTO_TEST_CASE(testPedestal) { - auto pedestalsHG = createRandomPedestals(), - pedestalsLG = createRandomPedestals(), - pedestalsLEDMONHG = createRandomPedestals(), - pedestalsLEDMONLG = createRandomPedestals(); + auto pedestalsHG = createRandomPedestals(false), + pedestalsLG = createRandomPedestals(false), + pedestalsLEDMONHG = createRandomPedestals(true), + pedestalsLEDMONLG = createRandomPedestals(true); o2::emcal::Pedestal pedestalObject; for (std::size_t ichan{0}; ichan < pedestalsHG.size(); ++ichan) { pedestalObject.addPedestalValue(ichan, pedestalsHG[ichan], false, false); pedestalObject.addPedestalValue(ichan, pedestalsLG[ichan], true, false); + } + for (std::size_t ichan{0}; ichan < pedestalsLEDMONHG.size(); ++ichan) { pedestalObject.addPedestalValue(ichan, pedestalsLEDMONHG[ichan], false, true); pedestalObject.addPedestalValue(ichan, pedestalsLEDMONLG[ichan], true, true); } @@ -75,6 +77,8 @@ BOOST_AUTO_TEST_CASE(testPedestal) for (std::size_t ichan{0}; ichan < pedestalsHG.size(); ++ichan) { BOOST_CHECK_EQUAL(pedestalObject.getPedestalValue(ichan, false, false), pedestalsHG[ichan]); BOOST_CHECK_EQUAL(pedestalObject.getPedestalValue(ichan, true, false), pedestalsLG[ichan]); + } + for (std::size_t ichan{0}; ichan < pedestalsLEDMONHG.size(); ++ichan) { BOOST_CHECK_EQUAL(pedestalObject.getPedestalValue(ichan, false, true), pedestalsLEDMONHG[ichan]); BOOST_CHECK_EQUAL(pedestalObject.getPedestalValue(ichan, true, true), pedestalsLEDMONLG[ichan]); } From c328a12b8288f51917b85322e2cc5b7099c68706 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 2 Apr 2024 10:05:50 +0200 Subject: [PATCH 0030/2997] Mute stray debug log in o2-raw-tf-reader --- Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx index 32242f2cde350..594d26b5682c6 100644 --- a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx +++ b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx @@ -346,7 +346,7 @@ void TFReaderSpec::TFBuilder() bool waitAcknowledged = false; long startWait = 0; while (mRunning && mDevice) { - LOGP(info, "mTFQueue.size()={} mWaitSendingLast = {}", mTFQueue.size(), mWaitSendingLast); + LOGP(debug, "mTFQueue.size()={} mWaitSendingLast = {}", mTFQueue.size(), mWaitSendingLast); if (mTFQueue.size() >= size_t(mInput.maxTFCache)) { mWaitSendingLast = false; std::this_thread::sleep_for(sleepTime); From 4be913d826e4d965030bc635384b95774a2ed292 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 2 Apr 2024 14:55:42 +0200 Subject: [PATCH 0031/2997] Some fixes for onnxruntime in TRD, but disabling it since still broken and untested (#12964) * Fix TRD usage of onnxruntime * Disable ONNX in TRD for now --- Detectors/TRD/pid/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Detectors/TRD/pid/CMakeLists.txt b/Detectors/TRD/pid/CMakeLists.txt index 012fa642a3047..8894c4384b071 100644 --- a/Detectors/TRD/pid/CMakeLists.txt +++ b/Detectors/TRD/pid/CMakeLists.txt @@ -22,10 +22,11 @@ o2_add_library(TRDPID fmt::fmt TARGETVARNAME libname) -if(ONNXRuntime_FOUND) - target_compile_definitions(${libname} PRIVATE TRDPID_WITH_ONNX) - target_link_libraries(${libname} ONNXRuntime::ONNXRuntime) - target_sources(${libname} src/ML.cxx) +# if(onnxruntime_FOUND) # ONNXRuntime code in TRD currently disabled since it is not tested +if(0) + target_compile_definitions(${libname} PUBLIC TRDPID_WITH_ONNX) + target_link_libraries(${libname} PRIVATE onnxruntime::onnxruntime) + target_sources(${libname} PRIVATE src/ML.cxx) o2_target_root_dictionary(TRDPID HEADERS include/TRDPID/PIDBase.h include/TRDPID/PIDParameters.h From bccd76070550a52277fb733fd9d3790ab4bd3d2a Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 22 Mar 2024 17:11:02 +0100 Subject: [PATCH 0032/2997] More flexibel use of event setup from collisioncontext can now give --fromCollContext file[:prefix] on the command line to specify prefix to use (previously less flexible). --- .../SimConfig/include/SimConfig/SimConfig.h | 2 +- Common/SimConfig/src/SimConfig.cxx | 32 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Common/SimConfig/include/SimConfig/SimConfig.h b/Common/SimConfig/include/SimConfig/SimConfig.h index 36babc21592b3..b288083098d6c 100644 --- a/Common/SimConfig/include/SimConfig/SimConfig.h +++ b/Common/SimConfig/include/SimConfig/SimConfig.h @@ -180,7 +180,7 @@ class SimConfig SimConfigData mConfigData; //! // adjust/overwrite some option settings when collision context is used - void adjustFromCollContext(); + void adjustFromCollContext(std::string const& collcontextfile, std::string const& prefix); ClassDefNV(SimConfig, 1); }; diff --git a/Common/SimConfig/src/SimConfig.cxx b/Common/SimConfig/src/SimConfig.cxx index 016e6e05a6961..ce5d2687979e1 100644 --- a/Common/SimConfig/src/SimConfig.cxx +++ b/Common/SimConfig/src/SimConfig.cxx @@ -256,7 +256,17 @@ bool SimConfig::resetFromParsedMap(boost::program_options::variables_map const& mConfigData.mFilterNoHitEvents = true; } mConfigData.mFromCollisionContext = vm["fromCollContext"].as(); - adjustFromCollContext(); + // we decompose the argument to fetch + // (a) collision contextfilename + // (b) sim prefix to use from the context + auto pos = mConfigData.mFromCollisionContext.find(':'); + std::string collcontextfile{mConfigData.mFromCollisionContext}; + std::string simprefix{mConfigData.mOutputPrefix}; + if (pos != std::string::npos) { + collcontextfile = mConfigData.mFromCollisionContext.substr(0, pos); + simprefix = mConfigData.mFromCollisionContext.substr(pos + 1); + } + adjustFromCollContext(collcontextfile, simprefix); // analyse vertex options if (!parseVertexModeString(vm["vertexMode"].as(), mConfigData.mVertexMode)) { @@ -323,28 +333,28 @@ bool SimConfig::parseFieldString(std::string const& fieldstring, int& fieldvalue return true; } -void SimConfig::adjustFromCollContext() +void SimConfig::adjustFromCollContext(std::string const& collcontextfile, std::string const& prefix) { // When we use pregenerated collision contexts, some options // need to be auto-adjusted. Do so and inform about this in the logs. - if (mConfigData.mFromCollisionContext == "") { + if (collcontextfile == "") { return; } - auto context = o2::steer::DigitizationContext::loadFromFile(mConfigData.mFromCollisionContext); + auto context = o2::steer::DigitizationContext::loadFromFile(collcontextfile); if (context) { // find the events belonging to a source that corresponds to a sim prefix - LOG(info) << "Looking up simprefixes " << mConfigData.mOutputPrefix; - int sourceid = context->findSimPrefix(mConfigData.mOutputPrefix); + LOG(info) << "Looking up simprefixes " << prefix; + int sourceid = context->findSimPrefix(prefix); if (sourceid == -1) { - LOG(error) << "Could not find collisions with sim prefix " << mConfigData.mOutputPrefix << " in the collision context. The collision contet specifies the following prefixes:"; - for (auto& prefix : context->getSimPrefixes()) { - LOG(info) << prefix; + LOG(error) << "Could not find collisions with sim prefix " << prefix << " in the collision context. The collision context specifies the following prefixes:"; + for (auto& sp : context->getSimPrefixes()) { + LOG(info) << sp; } LOG(fatal) << "Aborting due to prefix error"; } else { auto collisionmap = context->getCollisionIndicesForSource(sourceid); - LOG(info) << "Found " << collisionmap.size() << " events in the collisioncontext for prefix " << mConfigData.mOutputPrefix; + LOG(info) << "Found " << collisionmap.size() << " events in the collisioncontext for prefix " << prefix; // check if collisionmap is dense (otherwise it will get screwed up with order/indexing in ROOT output) bool good = true; @@ -368,7 +378,7 @@ void SimConfig::adjustFromCollContext() LOG(info) << "Setting number of events to simulate to " << mConfigData.mNEvents; } } else { - LOG(fatal) << "Could not open collision context file " << mConfigData.mFromCollisionContext; + LOG(fatal) << "Could not open collision context file " << collcontextfile; } } From 44f08574c8a96e2a501085e953ac19bb9719cc95 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 2 Apr 2024 14:47:51 +0200 Subject: [PATCH 0033/2997] GPU: Fix AliRoot build without GPU --- GPU/GPUTracking/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index aa81f2e6a0cb7..6266d4962b88e 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -10,6 +10,7 @@ # or submit itself to any jurisdiction. set(MODULE GPUTracking) +cmake_minimum_required(VERSION 3.27 FATAL_ERROR) # set(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} -O0") # to uncomment if needed, tired of typing this... @@ -21,9 +22,10 @@ include(cmake/helpers.cmake) if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") if(ENABLE_CUDA OR ENABLE_OPENCL1 OR ENABLE_OPENCL2 OR ENABLE_HIP) - cmake_minimum_required(VERSION 3.13 FATAL_ERROR) include(FeatureSummary) find_package(O2GPU) + else() + include("cmake/kernel_helpers.cmake") endif() else() if((ALIGPU_BUILD_TYPE STREQUAL "Standalone" AND BUILD_EVENT_DISPLAY) OR (ALIGPU_BUILD_TYPE STREQUAL "O2" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND TARGET AliceO2::DebugGUI AND OPENGL_FOUND AND GLFW_FOUND)) From 4494b5bdeda630c7a773689c774f0c0bc5e475d4 Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Wed, 3 Apr 2024 08:52:07 +0200 Subject: [PATCH 0034/2997] [EMCAL-1116] Add possibility to push pedestals to DCS ccdb (#12971) - data to dcs ccdb has to be a vector - PedestalData is encoded as a string (in EMCALPedestalHelper) Co-authored-by: jokonig --- .../EMCAL/calib/include/EMCALCalib/CalibDB.h | 6 + Detectors/EMCAL/calibration/CMakeLists.txt | 2 + .../EMCALCalibration/EMCALPedestalHelper.h | 65 ++++++ .../EMCALCalibration/PedestalCalibDevice.h | 13 +- .../calibration/src/EMCALPedestalHelper.cxx | 192 ++++++++++++++++++ .../calibration/src/PedestalCalibDevice.cxx | 30 ++- .../emc-pedestal-calib-workflow.cxx | 6 +- 7 files changed, 305 insertions(+), 9 deletions(-) create mode 100644 Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h create mode 100644 Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx diff --git a/Detectors/EMCAL/calib/include/EMCALCalib/CalibDB.h b/Detectors/EMCAL/calib/include/EMCALCalib/CalibDB.h index a021b74ebc2a5..d4fc0329c0bf5 100644 --- a/Detectors/EMCAL/calib/include/EMCALCalib/CalibDB.h +++ b/Detectors/EMCAL/calib/include/EMCALCalib/CalibDB.h @@ -8,6 +8,10 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. + +#ifndef ALICEO2_EMCAL_CALIBDB +#define ALICEO2_EMCAL_CALIBDB + #include #include #include @@ -379,3 +383,5 @@ class CalibDB } // namespace emcal } // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/EMCAL/calibration/CMakeLists.txt b/Detectors/EMCAL/calibration/CMakeLists.txt index ce50192f5a232..68c8fd1eb69c7 100644 --- a/Detectors/EMCAL/calibration/CMakeLists.txt +++ b/Detectors/EMCAL/calibration/CMakeLists.txt @@ -16,6 +16,7 @@ o2_add_library(EMCALCalibration src/EMCALCalibExtractor.cxx src/EMCALCalibParams.cxx src/EMCDCSProcessor.cxx + src/EMCALPedestalHelper.cxx src/PedestalCalibDevice.cxx src/PedestalProcessorDevice.cxx src/PedestalProcessorData.cxx @@ -43,6 +44,7 @@ o2_target_root_dictionary(EMCALCalibration include/EMCALCalibration/EMCALTimeCalibData.h include/EMCALCalibration/EMCALCalibParams.h include/EMCALCalibration/EMCDCSProcessor.h + include/EMCALCalibration/EMCALPedestalHelper.h include/EMCALCalibration/PedestalProcessorData.h LINKDEF src/EMCALCalibrationLinkDef.h) diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h new file mode 100644 index 0000000000000..518508f316c70 --- /dev/null +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h @@ -0,0 +1,65 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef EMCAL_PEDESTAL_HELPER_H_ +#define EMCAL_PEDESTAL_HELPER_H_ + +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CCDBTimeStampUtils.h" +#include "EMCALReconstruction/Channel.h" +#include "EMCALBase/Geometry.h" +#include "EMCALBase/Mapper.h" +#include "EMCALCalib/CalibDB.h" +#include "EMCALCalib/Pedestal.h" + +#include +#include +#include +#include + +namespace o2::emcal +{ + +class EMCALPedestalHelper +{ + + public: + EMCALPedestalHelper() = default; + ~EMCALPedestalHelper() = default; + + /// \brief Encodes the pedestal object into a string. This function fills fMeanPed which is then converted to a string in createInstructionString + /// \param obj pedestal object as stored in production ccdb + std::vector createPedestalInstruction(const Pedestal& obj); + + /// \brief print the vector produced by createInstructionString in a textfile + void dumpInstructions(const std::string_view filename, const std::vector data, int mRun); + + private: + /// \brief initialize fMeanPed with zeros + void setZero(); + + /// \brief converts fMeanPed to a vector of char + std::vector createInstructionString(); + + static constexpr short kNSM = 20; ///< number of SuperModules + static constexpr short kNRCU = 2; ///< number of readout crates (and DDLs) per SM + static constexpr short kNDTC = 40; ///< links for full SRU + static constexpr short kNBranch = 2; ///< low gain/high gain + static constexpr short kNFEC = 10; ///< 0..9, when including LED Ref + static constexpr short kNChip = 5; ///< really 0,2..4, i.e. skip #1 + static constexpr short kNChan = 16; + short fMeanPed[kNSM][kNRCU][kNBranch][kNFEC][kNChip][kNChan]; +}; + +} // namespace o2::emcal + +#endif \ No newline at end of file diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/PedestalCalibDevice.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/PedestalCalibDevice.h index 7cf819aa25fa7..5859e9e0d34ff 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/PedestalCalibDevice.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/PedestalCalibDevice.h @@ -21,6 +21,7 @@ #include "EMCALBase/Geometry.h" #include "EMCALCalibration/PedestalProcessorData.h" #include "EMCALCalibration/EMCALCalibExtractor.h" +#include "EMCALCalibration/EMCALPedestalHelper.h" namespace o2::emcal { @@ -28,7 +29,7 @@ namespace o2::emcal class PedestalCalibDevice : o2::framework::Task { public: - PedestalCalibDevice() = default; + PedestalCalibDevice(bool dumpToFile) : mDumpToFile(dumpToFile){}; ~PedestalCalibDevice() final = default; void init(framework::InitContext& ctx) final; @@ -45,12 +46,14 @@ class PedestalCalibDevice : o2::framework::Task private: Geometry* mGeometry = nullptr; ///< pointer to the emcal geometry class - o2::emcal::EMCALCalibExtractor mCalibExtractor; // instance of the calibration extraction class ///< Calibration postprocessing - PedestalProcessorData mPedestalData; /// pedestal data to accumulate data - long int mStartTS = 0; + o2::emcal::EMCALCalibExtractor mCalibExtractor; ///< instance of the calibration extraction class ///< Calibration postprocessing + PedestalProcessorData mPedestalData; ///< pedestal data to accumulate data + long int mStartTS = 0; ///< timestamp at the start of run used for the object in the ccdb + bool mDumpToFile; ///< if output of pedestal calib (DCS ccdb) should be written to text file + int mRun = 0; ///< current run number }; -o2::framework::DataProcessorSpec getPedestalCalibDevice(); +o2::framework::DataProcessorSpec getPedestalCalibDevice(bool dumpToFile); } // end namespace o2::emcal diff --git a/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx b/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx new file mode 100644 index 0000000000000..0c1a45c9c62b1 --- /dev/null +++ b/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx @@ -0,0 +1,192 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "EMCALCalibration/EMCALPedestalHelper.h" +using namespace o2::emcal; + +std::vector EMCALPedestalHelper::createPedestalInstruction(const Pedestal& obj) +{ + + setZero(); + + o2::emcal::Geometry* geo = o2::emcal::Geometry::GetInstanceFromRunNumber(300000); + o2::emcal::MappingHandler mapper; + + for (int itower = 0; itower < 17664; itower++) { + auto [ddl, row, col] = geo->getOnlineID(itower); + auto [sm, mod, iphi, ieta] = geo->GetCellIndex(itower); + const auto& mapping = mapper.getMappingForDDL(ddl); + int ircu = ddl % 2; + auto addressLG = mapping.getHardwareAddress(row, col, o2::emcal::ChannelType_t::LOW_GAIN), + addressHG = mapping.getHardwareAddress(row, col, o2::emcal::ChannelType_t::HIGH_GAIN); + auto fecLG = o2::emcal::Channel::getFecIndexFromHwAddress(addressLG), + fecHG = o2::emcal::Channel::getFecIndexFromHwAddress(addressHG), + branchLG = o2::emcal::Channel::getBranchIndexFromHwAddress(addressLG), + branchHG = o2::emcal::Channel::getBranchIndexFromHwAddress(addressHG), + chipLG = o2::emcal::Channel::getAltroIndexFromHwAddress(addressLG), + chipHG = o2::emcal::Channel::getAltroIndexFromHwAddress(addressHG), + channelLG = o2::emcal::Channel::getChannelIndexFromHwAddress(addressLG), + channelHG = o2::emcal::Channel::getChannelIndexFromHwAddress(addressHG); + fMeanPed[sm][ircu][branchHG][fecHG][chipHG][channelHG] = obj.getPedestalValue(itower, false, false); + fMeanPed[sm][ircu][branchLG][fecLG][chipLG][channelLG] = obj.getPedestalValue(itower, true, false); + } + + for (int iledmon = 0; iledmon < 480; iledmon++) { + int sm = iledmon / 24, + col = sm % 24, + ircu = 0, // LEDMONS always on RCU 0 + iddl = 2 * sm + ircu; + const auto& mapping = mapper.getMappingForDDL(iddl); + auto addressLG = mapping.getHardwareAddress(0, col, o2::emcal::ChannelType_t::LEDMON), + addressHG = mapping.getHardwareAddress(1, col, o2::emcal::ChannelType_t::LEDMON); + auto fecLG = o2::emcal::Channel::getFecIndexFromHwAddress(addressLG), + fecHG = o2::emcal::Channel::getFecIndexFromHwAddress(addressHG), + branchLG = o2::emcal::Channel::getBranchIndexFromHwAddress(addressLG), + branchHG = o2::emcal::Channel::getBranchIndexFromHwAddress(addressHG), + chipLG = o2::emcal::Channel::getAltroIndexFromHwAddress(addressLG), + chipHG = o2::emcal::Channel::getAltroIndexFromHwAddress(addressHG), + channelLG = o2::emcal::Channel::getChannelIndexFromHwAddress(addressLG), + channelHG = o2::emcal::Channel::getChannelIndexFromHwAddress(addressHG); + fMeanPed[sm][ircu][branchHG][fecHG][chipHG][channelHG] = obj.getPedestalValue(iledmon, false, true); + fMeanPed[sm][ircu][branchLG][fecLG][chipLG][channelLG] = obj.getPedestalValue(iledmon, true, true); + } + + return createInstructionString(); +} + +void EMCALPedestalHelper::setZero() +{ + for (int ism = 0; ism < kNSM; ism++) { + for (int ircu = 0; ircu < kNRCU; ircu++) { + for (int ibranch = 0; ibranch < kNBranch; ibranch++) { + for (int ifec = 0; ifec < kNFEC; ifec++) { + for (int ichip = 0; ichip < kNChip; ichip++) { + for (int ichan = 0; ichan < kNChan; ichan++) { + fMeanPed[ism][ircu][ibranch][ifec][ichip][ichan] = 0; + } + } + } + } + } + } +} + +std::vector EMCALPedestalHelper::createInstructionString() +{ + std::stringstream fout; + + unsigned int lineValue = 0; + + const unsigned int FECheaderCode = 0xC0000000; + // const unsigned int FECwordCode = 0x80000000; + const unsigned int FEClineCode = 0x40000000; + + short iSM = 0; + short iRCU = 0; + short ibranch = 0; + short iFEC = 0; + short ichip = 0; + short ichan = 0; + short Ped = 0; + short iDTC = 0; + + for (iSM = 0; iSM < kNSM; iSM++) { + int iside = iSM % 2; + int isect = iSM / 2; + if (iSM > 11) { + isect += 3; // skip non-installed sectors + } + + int activeDTC[kNDTC] = {0}; + for (iDTC = 0; iDTC < kNDTC; iDTC++) { + if (iDTC == 10 || iDTC == 20 || iDTC == 30) { // skip TRU + activeDTC[iDTC] = 0; + } else { + if (iSM < 10) { // not special third SMs or DCal SMs + activeDTC[iDTC] = 1; + } else { + if (iSM == 10 || iSM == 19) { // SMA5 or SMC12 + if (iDTC < 14) { + activeDTC[iDTC] = 1; + } else { + activeDTC[iDTC] = 0; + } + } else if (iSM == 11 || iSM == 18) { // SMC5 or SMA12 + if (iDTC == 0 || iDTC >= 27) { + activeDTC[iDTC] = 1; + } else { + activeDTC[iDTC] = 0; + } + } else { + // DCal... no FECs in 9,11-13, 23-26, 36-39 + if ((iDTC >= 9 && iDTC <= 13) || (iDTC >= 23 && iDTC <= 26) || + (iDTC >= 36 && iDTC <= 39)) { + activeDTC[iDTC] = 0; + } else { + activeDTC[iDTC] = 1; + } + } // DCal + } // non-EMCal + } // non-TRU + } + + // OK, let's generate the files for all active FECs/DTCs + for (iDTC = 0; iDTC < kNDTC; iDTC++) { + if (activeDTC[iDTC] == 0) { + continue; + } + + lineValue = FECheaderCode | isect << 9 | iside << 8 | iDTC; + fout << lineValue << std::endl; + + iRCU = iDTC / 20; + ibranch = (iDTC % 20) / 10; + iFEC = iDTC % 10; + int ipos = iFEC + 10 * ibranch; + + int dtcselUpper = 0; + int dtcselLower = 0; + if (iRCU == 0) { + dtcselLower = (1 << ipos); + } else { // crate == 1 + dtcselUpper = (1 << ipos); + } + + for (ichip = 0; ichip < kNChip; ichip++) { // ALTRO 0,2,3,4 + if (ichip != 1) { + for (ichan = 0; ichan < kNChan; ichan++) { + if (iFEC != 0 || (ichan < 8 || ichan > 11)) { + Ped = fMeanPed[iSM][iRCU][ibranch][iFEC][ichip][ichan]; + int writeAddr = (ichip << 4) | ichan; + lineValue = FEClineCode | (writeAddr << 12) | Ped; + fout << lineValue << std::endl; + } + } + } + } // chip + + } // iDTC + } // iSM + + // std::vector output; + std::string instructionString(fout.str()); + // std::fill(instructionString.begin(), instructionString.end(), std::back_inserter(output)); + std::vector output(instructionString.begin(), instructionString.end()); + return output; +} + +void EMCALPedestalHelper::dumpInstructions(const std::string_view filename, const std::vector data, int mRun) +{ + std::ofstream fout(filename.data()); + fout << mRun << "\n"; + fout << data.data(); + fout.close(); +} \ No newline at end of file diff --git a/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx b/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx index a852dc8a79947..8220d95fa4400 100644 --- a/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx +++ b/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx @@ -12,6 +12,7 @@ #include "CommonUtils/VerbosityConfig.h" #include "DetectorsRaw/RDHUtils.h" #include "EMCALBase/Geometry.h" +#include "Framework/TimingInfo.h" #include "EMCALCalibration/PedestalCalibDevice.h" #include "EMCALReconstruction/AltroDecoder.h" #include "EMCALReconstruction/RawReaderMemory.h" @@ -39,6 +40,13 @@ void PedestalCalibDevice::init(o2::framework::InitContext& ctx) void PedestalCalibDevice::run(o2::framework::ProcessingContext& ctx) { + if (!mRun) { + const auto& tinfo = ctx.services().get(); + if (tinfo.runNumber != 0) { + mRun = tinfo.runNumber; + } + } + constexpr auto originEMC = o2::header::gDataOriginEMC; auto data = ctx.inputs().get(getPedDataBinding()); LOG(debug) << "adding pedestal data"; @@ -60,6 +68,21 @@ void PedestalCalibDevice::sendData(o2::framework::EndOfStreamContext& ec, const ec.outputs().snapshot(o2::framework::Output{o2::calibration::Utils::gDataOriginCDBPayload, "EMC_PEDCALIB", 0}, *image.get()); ec.outputs().snapshot(o2::framework::Output{o2::calibration::Utils::gDataOriginCDBWrapper, "EMC_PEDCALIB", 0}, objInfo); + + // the following goes to the DCS ccdb + EMCALPedestalHelper helper; + std::vector vecPedData = helper.createPedestalInstruction(data); + if (mDumpToFile) { + helper.dumpInstructions("EMCAL-Pedestals.txt", vecPedData, mRun); + } + + auto clNameDCS = o2::utils::MemFileHelper::getClassName(vecPedData); + auto flNameDCS = o2::ccdb::CcdbApi::generateFileName(clNameDCS); + o2::ccdb::CcdbObjectInfo objInfoDCS("EMC/Calib/PDData", clNameDCS, flNameDCS, md, mStartTS, o2::ccdb::CcdbObjectInfo::INFINITE_TIMESTAMP, true); + auto imageDCS = o2::ccdb::CcdbApi::createObjectImage(&vecPedData, &objInfoDCS); + + ec.outputs().snapshot(o2::framework::Output{o2::calibration::Utils::gDataOriginCDBPayload, "EMC_PEDCALIBSTR", 1}, *imageDCS.get()); + ec.outputs().snapshot(o2::framework::Output{o2::calibration::Utils::gDataOriginCDBWrapper, "EMC_PEDCALIBSTR", 1}, objInfoDCS); } //________________________________________________________________ @@ -72,7 +95,7 @@ void PedestalCalibDevice::endOfStream(o2::framework::EndOfStreamContext& ec) resetStartTS(); } -o2::framework::DataProcessorSpec o2::emcal::getPedestalCalibDevice() +o2::framework::DataProcessorSpec o2::emcal::getPedestalCalibDevice(bool dumpToFile) { std::vector inputs; @@ -81,10 +104,13 @@ o2::framework::DataProcessorSpec o2::emcal::getPedestalCalibDevice() outputs.emplace_back(o2::framework::ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBPayload, "EMC_PEDCALIB"}, o2::framework::Lifetime::Sporadic); outputs.emplace_back(o2::framework::ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBWrapper, "EMC_PEDCALIB"}, o2::framework::Lifetime::Sporadic); + outputs.emplace_back(o2::framework::ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBPayload, "EMC_PEDCALIBSTR"}, o2::framework::Lifetime::Sporadic); + outputs.emplace_back(o2::framework::ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBWrapper, "EMC_PEDCALIBSTR"}, o2::framework::Lifetime::Sporadic); + return o2::framework::DataProcessorSpec{ "PedestalCalibrator", inputs, outputs, - o2::framework::AlgorithmSpec{o2::framework::adaptFromTask()}, + o2::framework::AlgorithmSpec{o2::framework::adaptFromTask(dumpToFile)}, o2::framework::Options{}}; } \ No newline at end of file diff --git a/Detectors/EMCAL/calibration/testWorkflow/emc-pedestal-calib-workflow.cxx b/Detectors/EMCAL/calibration/testWorkflow/emc-pedestal-calib-workflow.cxx index 92817d232658c..d11e11135e5ef 100644 --- a/Detectors/EMCAL/calibration/testWorkflow/emc-pedestal-calib-workflow.cxx +++ b/Detectors/EMCAL/calibration/testWorkflow/emc-pedestal-calib-workflow.cxx @@ -31,7 +31,8 @@ using namespace o2::emcal; void customize(std::vector& workflowOptions) { std::vector options{ - {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}, + {"dumpToFile", VariantType::Bool, false, {"if output (that goes to DCS ccdb) should be stored in txt file for local debugging"}}}; std::swap(workflowOptions, options); } @@ -41,9 +42,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { o2::conf::ConfigurableParam::updateFromString(cfgc.options().get("configKeyValues")); + bool dumpToFile = cfgc.options().get("dumpToFile"); WorkflowSpec specs; - specs.emplace_back(o2::emcal::getPedestalCalibDevice()); + specs.emplace_back(o2::emcal::getPedestalCalibDevice(dumpToFile)); return specs; } From 3a81323d2339bcdc4dd50ab995c7af08b1258e99 Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Thu, 28 Mar 2024 17:28:08 +0100 Subject: [PATCH 0035/2997] Use ITSTrackingInterface in its-reco-wf --- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 9 + .../include/ITStracking/Configuration.h | 37 +- .../include/ITStracking/TrackingInterface.h | 82 ++++ .../ITS/tracking/src/TrackingInterface.cxx | 356 ++++++++++++++++++ Detectors/ITSMFT/ITS/workflow/CMakeLists.txt | 4 +- .../include/ITSWorkflow/CookedTrackerSpec.h | 4 +- .../include/ITSWorkflow/RecoWorkflow.h | 7 +- .../include/ITSWorkflow/TrackerSpec.h | 30 +- .../ITS/workflow/src/CookedTrackerSpec.cxx | 30 +- .../ITSMFT/ITS/workflow/src/RecoWorkflow.cxx | 3 +- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 349 +---------------- GPU/GPUTracking/Global/GPUChainITS.cxx | 1 - 12 files changed, 510 insertions(+), 402 deletions(-) create mode 100644 Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h create mode 100644 Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index 0b106235a5f67..3c631cda64a6e 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -36,6 +36,15 @@ o2_add_library(ITStracking O2::ITSMFTReconstruction O2::DataFormatsITS) + +o2_add_library(ITSTrackingInterface + TARGETVARNAME targetName + SOURCES src/TrackingInterface.cxx + PUBLIC_LINK_LIBRARIES + O2::ITStracking + O2::Framework + O2::GPUTracking) + if (OpenMP_CXX_FOUND) target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index fc8d128c6eec1..810257a38fd3d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -31,6 +31,12 @@ namespace o2 namespace its { +enum class TrackingMode { + Sync, + Async, + Cosmics +}; + template class Configuration : public Param { @@ -123,19 +129,11 @@ struct VertexingParameters { struct TimeFrameGPUParameters { TimeFrameGPUParameters() = default; - // TimeFrameGPUParameters(size_t cubBufferSize, - // size_t maxTrkClu, - // size_t cluLayCap, - // size_t cluROfCap, - // size_t maxTrkCap, - // size_t maxVertCap, - // size_t maxROFs); size_t tmpCUBBufferSize = 1e5; // In average in pp events there are required 4096 bytes size_t maxTrackletsPerCluster = 1e2; size_t clustersPerLayerCapacity = 2.5e5; size_t clustersPerROfCapacity = 1.5e3; - // size_t trackletsCapacity = maxTrackletsPerCluster * clustersPerROfCapacity; size_t validatedTrackletsCapacity = 1e3; size_t cellsLUTsize = validatedTrackletsCapacity; size_t maxNeighboursSize = 1e2; @@ -148,29 +146,6 @@ struct TimeFrameGPUParameters { int maxGPUMemoryGB = -1; }; -// inline TimeFrameGPUParameters::TimeFrameGPUParameters(size_t cubBufferSize, -// size_t maxTrkClu, -// size_t cluLayCap, -// size_t cluROfCap, -// size_t maxTrkCap, -// size_t maxVertCap, -// size_t maxROFs, -// size_t validatedTrackletsCapacity, -// size_t cellsLUTsize, -// size_t maxNeighboursSize, -// size_t neighboursLUTsize, -// size_t maxRoadPerRofSize, -// size_t maxLinesCapacity) : tmpCUBBufferSize{cubBufferSize}, -// maxTrackletsPerCluster{maxTrkClu}, -// clustersPerLayerCapacity{cluLayCap}, -// clustersPerROfCapacity{cluROfCap}, -// maxLinesCapacity{maxTrkCap}, -// maxVerticesCapacity{maxVertCap}, -// nMaxROFs{maxROFs} -// { -// trackletsCapacity = maxTrackletsPerCluster * clustersPerLayerCapacity; -// } - } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h new file mode 100644 index 0000000000000..d681a29aef1ba --- /dev/null +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h @@ -0,0 +1,82 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_ITS_TRACKINGINTERFACE +#define O2_ITS_TRACKINGINTERFACE + +#include "Framework/DataProcessorSpec.h" + +#include "ITStracking/TimeFrame.h" +#include "ITStracking/Tracker.h" +#include "ITStracking/TrackerTraits.h" +#include "ITStracking/Vertexer.h" +#include "ITStracking/VertexerTraits.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsITSMFT/TopologyDictionary.h" +#include "DataFormatsCalibration/MeanVertexObject.h" + +#include "DetectorsBase/GRPGeomHelper.h" + +#include "GPUDataTypes.h" +#include "GPUO2Interface.h" +#include "GPUChainITS.h" + +namespace o2::its +{ +class ITSTrackingInterface +{ + public: + ITSTrackingInterface(std::shared_ptr gr, + bool isMC, + int trgType, + const TrackingMode trMode, + const bool overrBeamEst) + : mGGCCDBRequest(gr), + mIsMC{isMC}, + mUseTriggers{trgType}, + mMode{trMode}, + mOverrideBeamEstimation{overrBeamEst} + { + } + + void setClusterDictionary(const o2::itsmft::TopologyDictionary* d) { mDict = d; } + void setMeanVertex(const o2::dataformats::MeanVertexObject* v) + { + if (!v) { + return; + } + mMeanVertex = v; + } + // Task handles + void initialise(); + void run(framework::ProcessingContext& pc); + void updateTimeDependentParams(framework::ProcessingContext& pc); + void finaliseCCDB(framework::ConcreteDataMatcher& matcher, void* obj); + // Custom + void setTraitsFromProvider(VertexerTraits*, TrackerTraits*, TimeFrame*); + + private: + bool mIsMC = false; + bool mRunVertexer = true; + bool mCosmicsProcessing = false; + int mUseTriggers = 0; + TrackingMode mMode = TrackingMode::Sync; + bool mOverrideBeamEstimation = false; + std::shared_ptr mGGCCDBRequest; + const o2::itsmft::TopologyDictionary* mDict = nullptr; + std::unique_ptr mTracker = nullptr; + std::unique_ptr mVertexer = nullptr; + TimeFrame* mTimeFrame = nullptr; + const o2::dataformats::MeanVertexObject* mMeanVertex; +}; + +} // namespace o2::its +#endif // O2_ITS_TRACKINGINTERFACE \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx new file mode 100644 index 0000000000000..b768f561f4dd6 --- /dev/null +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -0,0 +1,356 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "ITSMFTBase/DPLAlpideParam.h" +#include "ITSBase/GeometryTGeo.h" + +#include "ITSReconstruction/FastMultEstConfig.h" +#include "ITSReconstruction/FastMultEst.h" + +#include "ITStracking/TrackingInterface.h" + +#include "DataFormatsITSMFT/ROFRecord.h" +#include "DataFormatsITSMFT/PhysTrigger.h" +#include "DataFormatsTRD/TriggerRecord.h" +#include "CommonDataFormat/IRFrame.h" + +namespace o2 +{ +using namespace framework; +namespace its +{ + +std::string asString(TrackingMode mode) +{ + switch (mode) { + case TrackingMode::Sync: + return "sync"; + case TrackingMode::Async: + return "async"; + case TrackingMode::Cosmics: + return "cosmics"; + } + return "unknown"; +} + +std::ostream& operator<<(std::ostream& os, TrackingMode v) +{ + os << asString(v); + return os; +} + +void ITSTrackingInterface::initialise() +{ + o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); + std::vector trackParams; + + if (mMode == TrackingMode::Async) { + + trackParams.resize(3); + for (auto& param : trackParams) { + param.ZBins = 64; + param.PhiBins = 32; + param.CellsPerClusterLimit = 1.e3f; + param.TrackletsPerClusterLimit = 1.e3f; + } + trackParams[1].TrackletMinPt = 0.2f; + trackParams[1].CellDeltaTanLambdaSigma *= 2.; + trackParams[2].TrackletMinPt = 0.1f; + trackParams[2].CellDeltaTanLambdaSigma *= 4.; + trackParams[2].MinTrackLength = 4; + LOG(info) << "Initializing tracker in async. phase reconstruction with " << trackParams.size() << " passes"; + + } else if (mMode == TrackingMode::Sync) { + trackParams.resize(1); + trackParams[0].ZBins = 64; + trackParams[0].PhiBins = 32; + trackParams[0].MinTrackLength = 4; + LOG(info) << "Initializing tracker in sync. phase reconstruction with " << trackParams.size() << " passes"; + } else if (mMode == TrackingMode::Cosmics) { + mCosmicsProcessing = true; + mRunVertexer = false; + trackParams.resize(1); + trackParams[0].MinTrackLength = 4; + trackParams[0].CellDeltaTanLambdaSigma *= 10; + trackParams[0].PhiBins = 4; + trackParams[0].ZBins = 16; + trackParams[0].PVres = 1.e5f; + trackParams[0].MaxChi2ClusterAttachment = 60.; + trackParams[0].MaxChi2NDF = 40.; + trackParams[0].TrackletsPerClusterLimit = 100.; + trackParams[0].CellsPerClusterLimit = 100.; + LOG(info) << "Initializing tracker in reconstruction for cosmics with " << trackParams.size() << " passes"; + + } else { + throw std::runtime_error(fmt::format("Unsupported ITS tracking mode {:s} ", asString(mMode))); + } + + for (auto& params : trackParams) { + params.CorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT; + } + mTracker->setParameters(trackParams); +} + +void ITSTrackingInterface::run(framework::ProcessingContext& pc) +{ + updateTimeDependentParams(pc); + auto compClusters = pc.inputs().get>("compClusters"); + gsl::span patterns = pc.inputs().get>("patterns"); + gsl::span physTriggers; + std::vector fromTRD; + if (mUseTriggers == 2) { // use TRD triggers + o2::InteractionRecord ir{0, pc.services().get().firstTForbit}; + auto trdTriggers = pc.inputs().get>("phystrig"); + for (const auto& trig : trdTriggers) { + if (trig.getBCData() >= ir && trig.getNumberOfTracklets()) { + ir = trig.getBCData(); + fromTRD.emplace_back(o2::itsmft::PhysTrigger{ir, 0}); + } + } + physTriggers = gsl::span(fromTRD.data(), fromTRD.size()); + } else if (mUseTriggers == 1) { // use Phys triggers from ITS stream + physTriggers = pc.inputs().get>("phystrig"); + } + + auto rofsinput = pc.inputs().get>("ROframes"); + auto& rofs = pc.outputs().make>(Output{"ITS", "ITSTrackROF", 0}, rofsinput.begin(), rofsinput.end()); + auto& irFrames = pc.outputs().make>(Output{"ITS", "IRFRAMES", 0}); + const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); // RS: this should come from CCDB + + irFrames.reserve(rofs.size()); + int nBCPerTF = alpParams.roFrameLengthInBC; + + LOGP(info, "ITSTracker pulled {} clusters, {} RO frames", compClusters.size(), rofs.size()); + + const dataformats::MCTruthContainer* labels = nullptr; + gsl::span mc2rofs; + if (mIsMC) { + labels = pc.inputs().get*>("itsmclabels").release(); + // get the array as read-only span, a snapshot is sent forward + pc.outputs().snapshot(Output{"ITS", "ITSTrackMC2ROF", 0}, pc.inputs().get>("ITSMC2ROframes")); + LOG(info) << labels->getIndexedSize() << " MC label objects , in " << mc2rofs.size() << " MC events"; + } + + auto& allClusIdx = pc.outputs().make>(Output{"ITS", "TRACKCLSID", 0}); + auto& allTracks = pc.outputs().make>(Output{"ITS", "TRACKS", 0}); + auto& vertROFvec = pc.outputs().make>(Output{"ITS", "VERTICESROF", 0}); + auto& vertices = pc.outputs().make>(Output{"ITS", "VERTICES", 0}); + + // MC + static pmr::vector dummyMCLabTracks, dummyMCLabVerts; + auto& allTrackLabels = mIsMC ? pc.outputs().make>(Output{"ITS", "TRACKSMCTR", 0}) : dummyMCLabTracks; + auto& allVerticesLabels = mIsMC ? pc.outputs().make>(Output{"ITS", "VERTICESMCTR", 0}) : dummyMCLabVerts; + + std::uint32_t roFrame = 0; + + bool continuous = o2::base::GRPGeomHelper::instance().getGRPECS()->isDetContinuousReadOut(o2::detectors::DetID::ITS); + LOG(info) << "ITSTracker RO: continuous=" << continuous; + + if (mOverrideBeamEstimation) { + mTimeFrame->setBeamPosition(mMeanVertex->getX(), + mMeanVertex->getY(), + mMeanVertex->getSigmaY2(), + mTracker->getParameters()[0].LayerResolution[0], + mTracker->getParameters()[0].SystErrorY2[0]); + } + + mTracker->setBz(o2::base::Propagator::Instance()->getNominalBz()); + + gsl::span::iterator pattIt = patterns.begin(); + + gsl::span rofspan(rofs); + mTimeFrame->loadROFrameData(rofspan, compClusters, pattIt, mDict, labels); + pattIt = patterns.begin(); + std::vector savedROF; + auto logger = [&](std::string s) { LOG(info) << s; }; + auto fatalLogger = [&](std::string s) { LOG(fatal) << s; }; + auto errorLogger = [&](std::string s) { LOG(error) << s; }; + + FastMultEst multEst; // mult estimator + std::vector processingMask; + int cutVertexMult{0}, cutRandomMult = int(rofs.size()) - multEst.selectROFs(rofs, compClusters, physTriggers, processingMask); + mTimeFrame->setMultiplicityCutMask(processingMask); + float vertexerElapsedTime{0.f}; + if (mRunVertexer) { + vertROFvec.reserve(rofs.size()); + // Run seeding vertexer + vertexerElapsedTime = mVertexer->clustersToVertices(logger); + } else { // cosmics + mTimeFrame->resetRofPV(); + } + const auto& multEstConf = FastMultEstConfig::Instance(); // parameters for mult estimation and cuts + for (auto iRof{0}; iRof < rofspan.size(); ++iRof) { + std::vector vtxVecLoc; + auto& vtxROF = vertROFvec.emplace_back(rofspan[iRof]); + vtxROF.setFirstEntry(vertices.size()); + if (mRunVertexer) { + auto vtxSpan = mTimeFrame->getPrimaryVertices(iRof); + vtxROF.setNEntries(vtxSpan.size()); + bool selROF = vtxSpan.size() == 0; + for (auto iV{0}; iV < vtxSpan.size(); ++iV) { + auto& v = vtxSpan[iV]; + if (multEstConf.isVtxMultCutRequested() && !multEstConf.isPassingVtxMultCut(v.getNContributors())) { + continue; // skip vertex of unwanted multiplicity + } + selROF = true; + vertices.push_back(v); + if (mIsMC) { + auto vLabels = mTimeFrame->getPrimaryVerticesLabels(iRof)[iV]; + allVerticesLabels.reserve(allVerticesLabels.size() + vLabels.size()); + std::copy(vLabels.begin(), vLabels.end(), std::back_inserter(allVerticesLabels)); + } + } + if (processingMask[iRof] && !selROF) { // passed selection in clusters and not in vertex multiplicity + LOG(debug) << fmt::format("ROF {} rejected by the vertex multiplicity selection [{},{}]", + iRof, + multEstConf.cutMultVtxLow, + multEstConf.cutMultVtxHigh); + processingMask[iRof] = selROF; + cutVertexMult++; + } + } else { // cosmics + vtxVecLoc.emplace_back(Vertex()); + vtxVecLoc.back().setNContributors(1); + vtxROF.setNEntries(vtxVecLoc.size()); + for (auto& v : vtxVecLoc) { + vertices.push_back(v); + } + mTimeFrame->addPrimaryVertices(vtxVecLoc); + } + } + LOG(info) << fmt::format(" - rejected {}/{} ROFs: random/mult.sel:{} (seed {}), vtx.sel:{}", cutRandomMult + cutVertexMult, rofspan.size(), cutRandomMult, multEst.lastRandomSeed, cutVertexMult); + LOG(info) << fmt::format(" - Vertex seeding total elapsed time: {} ms for {} vertices found in {} ROFs", vertexerElapsedTime, mTimeFrame->getPrimaryVerticesNum(), rofspan.size()); + + if (mOverrideBeamEstimation) { + LOG(info) << fmt::format(" - Beam position set to: {}, {} from meanvertex object", mTimeFrame->getBeamX(), mTimeFrame->getBeamY()); + } else { + LOG(info) << fmt::format(" - Beam position computed for the TF: {}, {}", mTimeFrame->getBeamX(), mTimeFrame->getBeamY()); + } + if (mCosmicsProcessing && compClusters.size() > 1500 * rofspan.size()) { + LOG(error) << "Cosmics processing was requested with an average detector occupancy exceeding 1.e-7, skipping TF processing."; + } else { + + mTimeFrame->setMultiplicityCutMask(processingMask); + // Run CA tracker + if (mMode == o2::its::TrackingMode::Async) { + mTracker->clustersToTracks(logger, fatalLogger); + } else { + mTracker->clustersToTracks(logger, errorLogger); + } + size_t totTracks{mTimeFrame->getNumberOfTracks()}, totClusIDs{mTimeFrame->getNumberOfUsedClusters()}; + allTracks.reserve(totTracks); + allClusIdx.reserve(totClusIDs); + + if (mTimeFrame->hasBogusClusters()) { + LOG(warning) << fmt::format(" - The processed timeframe had {} clusters with wild z coordinates, check the dictionaries", mTimeFrame->hasBogusClusters()); + } + + for (unsigned int iROF{0}; iROF < rofs.size(); ++iROF) { + auto& rof{rofs[iROF]}; + auto& tracks = mTimeFrame->getTracks(iROF); + auto number{tracks.size()}; + auto first{allTracks.size()}; + int offset = -rof.getFirstEntry(); // cluster entry!!! + rof.setFirstEntry(first); + rof.setNEntries(number); + + if (processingMask[iROF]) { + irFrames.emplace_back(rof.getBCData(), rof.getBCData() + nBCPerTF - 1).info = tracks.size(); + } + allTrackLabels.reserve(mTimeFrame->getTracksLabel(iROF).size()); // should be 0 if not MC + std::copy(mTimeFrame->getTracksLabel(iROF).begin(), mTimeFrame->getTracksLabel(iROF).end(), std::back_inserter(allTrackLabels)); + // Some conversions that needs to be moved in the tracker internals + for (unsigned int iTrk{0}; iTrk < tracks.size(); ++iTrk) { + auto& trc{tracks[iTrk]}; + trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices + int ncl = trc.getNumberOfClusters(), nclf = 0; + for (int ic = TrackITSExt::MaxClusters; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! + auto clid = trc.getClusterIndex(ic); + if (clid >= 0) { + trc.setClusterSize(ic, mTimeFrame->getClusterSize(clid)); + allClusIdx.push_back(clid); + nclf++; + } + } + assert(ncl == nclf); + allTracks.emplace_back(trc); + } + } + LOGP(info, "ITSTracker pushed {} tracks and {} vertices", allTracks.size(), vertices.size()); + if (mIsMC) { + LOGP(info, "ITSTracker pushed {} track labels", allTrackLabels.size()); + LOGP(info, "ITSTracker pushed {} vertex labels", allVerticesLabels.size()); + } + } +} + +void ITSTrackingInterface::updateTimeDependentParams(framework::ProcessingContext& pc) +{ + o2::base::GRPGeomHelper::instance().checkUpdates(pc); + static bool initOnceDone = false; + if (!initOnceDone) { // this params need to be queried only once + initOnceDone = true; + pc.inputs().get("cldict"); // just to trigger the finaliseCCDB + pc.inputs().get*>("alppar"); + if (pc.inputs().getPos("itsTGeo") >= 0) { + pc.inputs().get("itsTGeo"); + } + GeometryTGeo* geom = GeometryTGeo::Instance(); + geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2G)); + mVertexer->getGlobalConfiguration(); + mTracker->getGlobalConfiguration(); + if (mOverrideBeamEstimation) { + pc.inputs().get("meanvtx"); + } + } +} + +void ITSTrackingInterface::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) +{ + if (o2::base::GRPGeomHelper::instance().finaliseCCDB(matcher, obj)) { + return; + } + if (matcher == ConcreteDataMatcher("ITS", "CLUSDICT", 0)) { + LOG(info) << "cluster dictionary updated"; + setClusterDictionary((const o2::itsmft::TopologyDictionary*)obj); + return; + } + // Note: strictly speaking, for Configurable params we don't need finaliseCCDB check, the singletons are updated at the CCDB fetcher level + if (matcher == ConcreteDataMatcher("ITS", "ALPIDEPARAM", 0)) { + LOG(info) << "Alpide param updated"; + const auto& par = o2::itsmft::DPLAlpideParam::Instance(); + par.printKeyValues(); + return; + } + if (matcher == ConcreteDataMatcher("GLO", "MEANVERTEX", 0)) { + LOGP(info, "mean vertex acquired"); + setMeanVertex((const o2::dataformats::MeanVertexObject*)obj); + return; + } + if (matcher == ConcreteDataMatcher("ITS", "GEOMTGEO", 0)) { + LOG(info) << "ITS GeomtetryTGeo loaded from ccdb"; + o2::its::GeometryTGeo::adopt((o2::its::GeometryTGeo*)obj); + return; + } +} + +void ITSTrackingInterface::setTraitsFromProvider(VertexerTraits* vertexerTraits, + TrackerTraits* trackerTraits, + TimeFrame* frame) +{ + mVertexer = std::make_unique(vertexerTraits); + mTracker = std::make_unique(trackerTraits); + mTimeFrame = frame; + mVertexer->adoptTimeFrame(*mTimeFrame); + mTracker->adoptTimeFrame(*mTimeFrame); +} +} // namespace its +} // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt b/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt index 785417d915a67..f221a41691f71 100644 --- a/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt @@ -28,7 +28,7 @@ o2_add_library(ITSWorkflow src/DCSAdaposParserWorkflow.cxx src/DCSAdaposParserSpec.cxx src/DCSDataGeneratorWorkflow.cxx - src/DCSGeneratorSpec.cxx + src/DCSGeneratorSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::SimConfig O2::DetectorsDCS @@ -37,7 +37,7 @@ o2_add_library(ITSWorkflow O2::DataFormatsTRD O2::DataFormatsGlobalTracking O2::SimulationDataFormat - O2::ITStracking + O2::ITSTrackingInterface O2::ITSReconstruction O2::ITSMFTReconstruction O2::ITSMFTWorkflow diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h index 68ef7f0c022b2..02e278eeedda9 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h @@ -35,7 +35,7 @@ namespace its class CookedTrackerDPL : public Task { public: - CookedTrackerDPL(std::shared_ptr gr, bool useMC, int trgType, const std::string& trMode); + CookedTrackerDPL(std::shared_ptr gr, bool useMC, int trgType, const TrackingMode& trMode); ~CookedTrackerDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -51,7 +51,7 @@ class CookedTrackerDPL : public Task bool mUseMC = true; bool mRunVertexer = true; int mUseTriggers = 0; - std::string mMode = "async"; + TrackingMode mMode = TrackingMode::Sync; const o2::itsmft::TopologyDictionary* mDict = nullptr; std::unique_ptr mGRP = nullptr; o2::its::CookedTracker mTracker; diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h index 9106881139a3e..169e8009c5275 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h @@ -16,9 +16,10 @@ #include "Framework/WorkflowSpec.h" -#include "GPUO2Interface.h" -#include "GPUReconstruction.h" -#include "GPUChainITS.h" +// #include "GPUO2Interface.h" +// #include "GPUReconstruction.h" +// #include "GPUChainITS.h" +#include "GPUDataTypes.h" namespace o2 { diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h index 10a9a9d7c0bee..6eedca2a459b4 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h @@ -21,11 +21,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" -#include "ITStracking/TimeFrame.h" -#include "ITStracking/Tracker.h" -#include "ITStracking/TrackerTraits.h" -#include "ITStracking/Vertexer.h" -#include "ITStracking/VertexerTraits.h" +#include "ITStracking/TrackingInterface.h" #include "GPUO2Interface.h" #include "GPUReconstruction.h" @@ -45,7 +41,7 @@ class TrackerDPL : public framework::Task TrackerDPL(std::shared_ptr gr, bool isMC, int trgType, - const std::string& trModeS, + const TrackingMode& trModeS, const bool overrBeamEst = false, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU); ~TrackerDPL() override = default; @@ -54,32 +50,12 @@ class TrackerDPL : public framework::Task void endOfStream(framework::EndOfStreamContext& ec) final; void finaliseCCDB(framework::ConcreteDataMatcher& matcher, void* obj) final; void stop() final; - void setClusterDictionary(const o2::itsmft::TopologyDictionary* d) { mDict = d; } - void setMeanVertex(const o2::dataformats::MeanVertexObject* v) - { - if (!v) { - return; - } - mMeanVertex = v; - } private: void updateTimeDependentParams(framework::ProcessingContext& pc); - - bool mIsMC = false; - bool mRunVertexer = true; - bool mCosmicsProcessing = false; - int mUseTriggers = 0; - std::string mMode = "sync"; - bool mOverrideBeamEstimation = false; - std::shared_ptr mGGCCDBRequest; - const o2::itsmft::TopologyDictionary* mDict = nullptr; std::unique_ptr mRecChain = nullptr; std::unique_ptr mChainITS = nullptr; - std::unique_ptr mTracker = nullptr; - std::unique_ptr mVertexer = nullptr; - TimeFrame* mTimeFrame = nullptr; - const o2::dataformats::MeanVertexObject* mMeanVertex; + ITSTrackingInterface mITSTrackingInterface; TStopwatch mTimer; }; diff --git a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx index 463932dc9294c..a534479b90085 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx @@ -51,8 +51,26 @@ namespace its { using Vertex = o2::dataformats::Vertex>; +std::string asString(TrackingMode mode) +{ + switch (mode) { + case TrackingMode::Sync: + return "sync"; + case TrackingMode::Async: + return "async"; + case TrackingMode::Cosmics: + return "cosmics"; + } + return "unknown"; +} + +std::ostream& operator<<(std::ostream& os, TrackingMode v) +{ + os << asString(v); + return os; +} -CookedTrackerDPL::CookedTrackerDPL(std::shared_ptr gr, bool useMC, int trgType, const std::string& trMode) : mGGCCDBRequest(gr), mUseMC(useMC), mUseTriggers{trgType}, mMode(trMode) +CookedTrackerDPL::CookedTrackerDPL(std::shared_ptr gr, bool useMC, int trgType, const TrackingMode& trMode) : mGGCCDBRequest(gr), mUseMC(useMC), mUseTriggers{trgType}, mMode(trMode) { mVertexerTraitsPtr = std::make_unique(); mVertexerPtr = std::make_unique(mVertexerTraitsPtr.get()); @@ -232,7 +250,7 @@ void CookedTrackerDPL::updateTimeDependentParams(ProcessingContext& pc) mTracker.setGeometry(geom); mTracker.setConfigParams(); LOG(info) << "Tracking mode " << mMode; - if (mMode == "cosmics") { + if (mMode == TrackingMode::Cosmics) { LOG(info) << "Setting cosmics parameters..."; mTracker.setParametersCosmics(); mRunVertexer = false; @@ -269,7 +287,7 @@ void CookedTrackerDPL::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) } } -DataProcessorSpec getCookedTrackerSpec(bool useMC, bool useGeom, int trgType, const std::string& trMode) +DataProcessorSpec getCookedTrackerSpec(bool useMC, bool useGeom, int trgType, const std::string& trModeS) { std::vector inputs; inputs.emplace_back("compClusters", "ITS", "COMPCLUSTERS", 0, Lifetime::Timeframe); @@ -312,7 +330,11 @@ DataProcessorSpec getCookedTrackerSpec(bool useMC, bool useGeom, int trgType, co "its-cooked-tracker", inputs, outputs, - AlgorithmSpec{adaptFromTask(ggRequest, useMC, trgType, trMode)}, + AlgorithmSpec{adaptFromTask(ggRequest, + useMC, + trgType, + trModeS == "sync" ? o2::its::TrackingMode::Sync : trModeS == "async" ? o2::its::TrackingMode::Async + : o2::its::TrackingMode::Cosmics)}, Options{{"nthreads", VariantType::Int, 1, {"Number of threads"}}}}; } diff --git a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx index 767651d731301..dfa958ccd5890 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx @@ -31,6 +31,7 @@ namespace o2 { namespace its { +// using ITSTrackReconstruction::TrackingMode; namespace reco_workflow { @@ -64,7 +65,7 @@ framework::WorkflowSpec getWorkflow(bool useMC, cfg.runITSTracking = true; cfg.itsTriggerType = useTrig; cfg.itsOverrBeamEst = overrideBeamPosition; - cfg.itsTrackingMode = trmode == "sync" ? 0 : (trmode == "async" ? 1 : 2); + cfg.itsTrackingMode = trmode == "sync" ? (int)TrackingMode::Sync : (trmode == "async" ? (int)TrackingMode::Async : (int)TrackingMode::Cosmics); Inputs ggInputs; auto ggRequest = std::make_shared(false, true, false, true, true, diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index f993187546de5..01fcbc064a265 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -9,39 +9,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// @file TrackerSpec.cxx - #include -#include "TGeoGlobalMagField.h" - #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/CCDBParamSpec.h" #include "ITSWorkflow/TrackerSpec.h" -#include "DataFormatsITSMFT/CompCluster.h" -#include "DataFormatsITS/TrackITS.h" -#include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" -#include "DataFormatsITSMFT/ROFRecord.h" -#include "DataFormatsITSMFT/PhysTrigger.h" - -#include "ITStracking/ROframe.h" -#include "ITStracking/IOUtils.h" -#include "ITStracking/TrackingConfigParam.h" -#include "ITSMFTBase/DPLAlpideParam.h" -#include "ITSMFTReconstruction/ClustererParam.h" - -#include "Field/MagneticField.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "ITSBase/GeometryTGeo.h" -#include "CommonDataFormat/IRFrame.h" -#include "DetectorsCommonDataFormats/DetectorNameConf.h" -#include "DataFormatsTRD/TriggerRecord.h" -#include "ITSReconstruction/FastMultEstConfig.h" -#include "ITSReconstruction/FastMultEst.h" -#include namespace o2 { @@ -53,78 +26,22 @@ using Vertex = o2::dataformats::Vertex>; TrackerDPL::TrackerDPL(std::shared_ptr gr, bool isMC, int trgType, - const std::string& trModeS, + const TrackingMode& trMode, const bool overrBeamEst, - o2::gpu::GPUDataTypes::DeviceType dType) : mGGCCDBRequest(gr), - mIsMC{isMC}, - mUseTriggers{trgType}, - mMode{trModeS}, - mOverrideBeamEstimation{overrBeamEst}, - mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)} + o2::gpu::GPUDataTypes::DeviceType dType) : mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)}, + mITSTrackingInterface{gr, isMC, trgType, trMode, overrBeamEst} { - std::transform(mMode.begin(), mMode.end(), mMode.begin(), [](unsigned char c) { return std::tolower(c); }); } void TrackerDPL::init(InitContext& ic) { mTimer.Stop(); mTimer.Reset(); - o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); mChainITS.reset(mRecChain->AddChain()); - mVertexer = std::make_unique(mChainITS->GetITSVertexerTraits()); - mTracker = std::make_unique(mChainITS->GetITSTrackerTraits()); - mTimeFrame = mChainITS->GetITSTimeframe(); - mVertexer->adoptTimeFrame(*mTimeFrame); - mTracker->adoptTimeFrame(*mTimeFrame); - mRunVertexer = true; - mCosmicsProcessing = false; - std::vector trackParams; - - if (mMode == "async") { - - trackParams.resize(3); - for (auto& param : trackParams) { - param.ZBins = 64; - param.PhiBins = 32; - param.CellsPerClusterLimit = 1.e3f; - param.TrackletsPerClusterLimit = 1.e3f; - } - trackParams[1].TrackletMinPt = 0.2f; - trackParams[1].CellDeltaTanLambdaSigma *= 2.; - trackParams[2].TrackletMinPt = 0.1f; - trackParams[2].CellDeltaTanLambdaSigma *= 4.; - trackParams[2].MinTrackLength = 4; - LOG(info) << "Initializing tracker in async. phase reconstruction with " << trackParams.size() << " passes"; - - } else if (mMode == "sync") { - trackParams.resize(1); - trackParams[0].ZBins = 64; - trackParams[0].PhiBins = 32; - trackParams[0].MinTrackLength = 4; - LOG(info) << "Initializing tracker in sync. phase reconstruction with " << trackParams.size() << " passes"; - } else if (mMode == "cosmics") { - mCosmicsProcessing = true; - mRunVertexer = false; - trackParams.resize(1); - trackParams[0].MinTrackLength = 4; - trackParams[0].CellDeltaTanLambdaSigma *= 10; - trackParams[0].PhiBins = 4; - trackParams[0].ZBins = 16; - trackParams[0].PVres = 1.e5f; - trackParams[0].MaxChi2ClusterAttachment = 60.; - trackParams[0].MaxChi2NDF = 40.; - trackParams[0].TrackletsPerClusterLimit = 100.; - trackParams[0].CellsPerClusterLimit = 100.; - LOG(info) << "Initializing tracker in reconstruction for cosmics with " << trackParams.size() << " passes"; - - } else { - throw std::runtime_error(fmt::format("Unsupported ITS tracking mode {:s} ", mMode)); - } - - for (auto& params : trackParams) { - params.CorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT; - } - mTracker->setParameters(trackParams); + mITSTrackingInterface.setTraitsFromProvider(mChainITS->GetITSVertexerTraits(), + mChainITS->GetITSTrackerTraits(), + mChainITS->GetITSTimeframe()); + mITSTrackingInterface.initialise(); } void TrackerDPL::stop() @@ -137,255 +54,19 @@ void TrackerDPL::run(ProcessingContext& pc) auto cput = mTimer.CpuTime(); auto realt = mTimer.RealTime(); mTimer.Start(false); - updateTimeDependentParams(pc); - auto compClusters = pc.inputs().get>("compClusters"); - gsl::span patterns = pc.inputs().get>("patterns"); - gsl::span physTriggers; - std::vector fromTRD; - if (mUseTriggers == 2) { // use TRD triggers - o2::InteractionRecord ir{0, pc.services().get().firstTForbit}; - auto trdTriggers = pc.inputs().get>("phystrig"); - for (const auto& trig : trdTriggers) { - if (trig.getBCData() >= ir && trig.getNumberOfTracklets()) { - ir = trig.getBCData(); - fromTRD.emplace_back(o2::itsmft::PhysTrigger{ir, 0}); - } - } - physTriggers = gsl::span(fromTRD.data(), fromTRD.size()); - } else if (mUseTriggers == 1) { // use Phys triggers from ITS stream - physTriggers = pc.inputs().get>("phystrig"); - } - - auto rofsinput = pc.inputs().get>("ROframes"); - auto& rofs = pc.outputs().make>(Output{"ITS", "ITSTrackROF", 0}, rofsinput.begin(), rofsinput.end()); - auto& irFrames = pc.outputs().make>(Output{"ITS", "IRFRAMES", 0}); - const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); // RS: this should come from CCDB - - irFrames.reserve(rofs.size()); - int nBCPerTF = alpParams.roFrameLengthInBC; - - LOGP(info, "ITSTracker pulled {} clusters, {} RO frames", compClusters.size(), rofs.size()); - - const dataformats::MCTruthContainer* labels = nullptr; - gsl::span mc2rofs; - if (mIsMC) { - labels = pc.inputs().get*>("itsmclabels").release(); - // get the array as read-only span, a snapshot is sent forward - pc.outputs().snapshot(Output{"ITS", "ITSTrackMC2ROF", 0}, pc.inputs().get>("ITSMC2ROframes")); - LOG(info) << labels->getIndexedSize() << " MC label objects , in " << mc2rofs.size() << " MC events"; - } - - auto& allClusIdx = pc.outputs().make>(Output{"ITS", "TRACKCLSID", 0}); - auto& allTracks = pc.outputs().make>(Output{"ITS", "TRACKS", 0}); - auto& vertROFvec = pc.outputs().make>(Output{"ITS", "VERTICESROF", 0}); - auto& vertices = pc.outputs().make>(Output{"ITS", "VERTICES", 0}); - - // MC - static pmr::vector dummyMCLabTracks, dummyMCLabVerts; - auto& allTrackLabels = mIsMC ? pc.outputs().make>(Output{"ITS", "TRACKSMCTR", 0}) : dummyMCLabTracks; - auto& allVerticesLabels = mIsMC ? pc.outputs().make>(Output{"ITS", "VERTICESMCTR", 0}) : dummyMCLabVerts; - - std::uint32_t roFrame = 0; - - bool continuous = o2::base::GRPGeomHelper::instance().getGRPECS()->isDetContinuousReadOut(o2::detectors::DetID::ITS); - LOG(info) << "ITSTracker RO: continuous=" << continuous; - - if (mOverrideBeamEstimation) { - mTimeFrame->setBeamPosition(mMeanVertex->getX(), - mMeanVertex->getY(), - mMeanVertex->getSigmaY2(), - mTracker->getParameters()[0].LayerResolution[0], - mTracker->getParameters()[0].SystErrorY2[0]); - } - - mTracker->setBz(o2::base::Propagator::Instance()->getNominalBz()); - - gsl::span::iterator pattIt = patterns.begin(); - - gsl::span rofspan(rofs); - mTimeFrame->loadROFrameData(rofspan, compClusters, pattIt, mDict, labels); - pattIt = patterns.begin(); - std::vector savedROF; - auto logger = [&](std::string s) { LOG(info) << s; }; - auto fatalLogger = [&](std::string s) { LOG(fatal) << s; }; - auto errorLogger = [&](std::string s) { LOG(error) << s; }; - - FastMultEst multEst; // mult estimator - std::vector processingMask; - int cutVertexMult{0}, cutRandomMult = int(rofs.size()) - multEst.selectROFs(rofs, compClusters, physTriggers, processingMask); - mTimeFrame->setMultiplicityCutMask(processingMask); - float vertexerElapsedTime{0.f}; - if (mRunVertexer) { - vertROFvec.reserve(rofs.size()); - // Run seeding vertexer - vertexerElapsedTime = mVertexer->clustersToVertices(logger); - } else { // cosmics - mTimeFrame->resetRofPV(); - } - const auto& multEstConf = FastMultEstConfig::Instance(); // parameters for mult estimation and cuts - for (auto iRof{0}; iRof < rofspan.size(); ++iRof) { - std::vector vtxVecLoc; - auto& vtxROF = vertROFvec.emplace_back(rofspan[iRof]); - vtxROF.setFirstEntry(vertices.size()); - if (mRunVertexer) { - auto vtxSpan = mTimeFrame->getPrimaryVertices(iRof); - vtxROF.setNEntries(vtxSpan.size()); - bool selROF = vtxSpan.size() == 0; - for (auto iV{0}; iV < vtxSpan.size(); ++iV) { - auto& v = vtxSpan[iV]; - if (multEstConf.isVtxMultCutRequested() && !multEstConf.isPassingVtxMultCut(v.getNContributors())) { - continue; // skip vertex of unwanted multiplicity - } - selROF = true; - vertices.push_back(v); - if (mIsMC) { - auto vLabels = mTimeFrame->getPrimaryVerticesLabels(iRof)[iV]; - allVerticesLabels.reserve(allVerticesLabels.size() + vLabels.size()); - std::copy(vLabels.begin(), vLabels.end(), std::back_inserter(allVerticesLabels)); - } - } - if (processingMask[iRof] && !selROF) { // passed selection in clusters and not in vertex multiplicity - LOG(debug) << fmt::format("ROF {} rejected by the vertex multiplicity selection [{},{}]", - iRof, - multEstConf.cutMultVtxLow, - multEstConf.cutMultVtxHigh); - processingMask[iRof] = selROF; - cutVertexMult++; - } - } else { // cosmics - vtxVecLoc.emplace_back(Vertex()); - vtxVecLoc.back().setNContributors(1); - vtxROF.setNEntries(vtxVecLoc.size()); - for (auto& v : vtxVecLoc) { - vertices.push_back(v); - } - mTimeFrame->addPrimaryVertices(vtxVecLoc); - } - } - LOG(info) << fmt::format(" - rejected {}/{} ROFs: random/mult.sel:{} (seed {}), vtx.sel:{}", cutRandomMult + cutVertexMult, rofspan.size(), cutRandomMult, multEst.lastRandomSeed, cutVertexMult); - LOG(info) << fmt::format(" - Vertex seeding total elapsed time: {} ms for {} vertices found in {} ROFs", vertexerElapsedTime, mTimeFrame->getPrimaryVerticesNum(), rofspan.size()); - - if (mOverrideBeamEstimation) { - LOG(info) << fmt::format(" - Beam position set to: {}, {} from meanvertex object", mTimeFrame->getBeamX(), mTimeFrame->getBeamY()); - } else { - LOG(info) << fmt::format(" - Beam position computed for the TF: {}, {}", mTimeFrame->getBeamX(), mTimeFrame->getBeamY()); - } - if (mCosmicsProcessing && compClusters.size() > 1500 * rofspan.size()) { - LOG(error) << "Cosmics processing was requested with an average detector occupancy exceeding 1.e-7, skipping TF processing."; - } else { - - mTimeFrame->setMultiplicityCutMask(processingMask); - // Run CA tracker - if (mMode == "async") { - mTracker->clustersToTracks(logger, fatalLogger); - } else { - mTracker->clustersToTracks(logger, errorLogger); - } - size_t totTracks{mTimeFrame->getNumberOfTracks()}, totClusIDs{mTimeFrame->getNumberOfUsedClusters()}; - allTracks.reserve(totTracks); - allClusIdx.reserve(totClusIDs); - - if (mTimeFrame->hasBogusClusters()) { - LOG(warning) << fmt::format(" - The processed timeframe had {} clusters with wild z coordinates, check the dictionaries", mTimeFrame->hasBogusClusters()); - } - - for (unsigned int iROF{0}; iROF < rofs.size(); ++iROF) { - auto& rof{rofs[iROF]}; - auto& tracks = mTimeFrame->getTracks(iROF); - auto number{tracks.size()}; - auto first{allTracks.size()}; - int offset = -rof.getFirstEntry(); // cluster entry!!! - rof.setFirstEntry(first); - rof.setNEntries(number); - - if (processingMask[iROF]) { - irFrames.emplace_back(rof.getBCData(), rof.getBCData() + nBCPerTF - 1).info = tracks.size(); - } - allTrackLabels.reserve(mTimeFrame->getTracksLabel(iROF).size()); // should be 0 if not MC - std::copy(mTimeFrame->getTracksLabel(iROF).begin(), mTimeFrame->getTracksLabel(iROF).end(), std::back_inserter(allTrackLabels)); - // Some conversions that needs to be moved in the tracker internals - for (unsigned int iTrk{0}; iTrk < tracks.size(); ++iTrk) { - auto& trc{tracks[iTrk]}; - trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices - int ncl = trc.getNumberOfClusters(), nclf = 0; - for (int ic = TrackITSExt::MaxClusters; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! - auto clid = trc.getClusterIndex(ic); - if (clid >= 0) { - trc.setClusterSize(ic, mTimeFrame->getClusterSize(clid)); - allClusIdx.push_back(clid); - nclf++; - } - } - assert(ncl == nclf); - allTracks.emplace_back(trc); - } - } - LOGP(info, "ITSTracker pushed {} tracks and {} vertices", allTracks.size(), vertices.size()); - if (mIsMC) { - LOGP(info, "ITSTracker pushed {} track labels", allTrackLabels.size()); - LOGP(info, "ITSTracker pushed {} vertex labels", allVerticesLabels.size()); - } - } + mITSTrackingInterface.run(pc); mTimer.Stop(); - LOG(info) << "CPU Reconstruction time for this TF " << mTimer.CpuTime() - cput << " s (cpu), " << mTimer.RealTime() - realt << " s (wall)"; -} - -///_______________________________________ -void TrackerDPL::updateTimeDependentParams(ProcessingContext& pc) -{ - o2::base::GRPGeomHelper::instance().checkUpdates(pc); - static bool initOnceDone = false; - if (!initOnceDone) { // this params need to be queried only once - initOnceDone = true; - pc.inputs().get("cldict"); // just to trigger the finaliseCCDB - pc.inputs().get*>("alppar"); - if (pc.inputs().getPos("itsTGeo") >= 0) { - pc.inputs().get("itsTGeo"); - } - GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2G)); - mVertexer->getGlobalConfiguration(); - mTracker->getGlobalConfiguration(); - if (mOverrideBeamEstimation) { - pc.inputs().get("meanvtx"); - } - } + LOGP(info, "CPU Reconstruction time for this TF {} s (cpu), {} s (wall)", mTimer.CpuTime() - cput, mTimer.RealTime() - realt); } -///_______________________________________ void TrackerDPL::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) { - if (o2::base::GRPGeomHelper::instance().finaliseCCDB(matcher, obj)) { - return; - } - if (matcher == ConcreteDataMatcher("ITS", "CLUSDICT", 0)) { - LOG(info) << "cluster dictionary updated"; - setClusterDictionary((const o2::itsmft::TopologyDictionary*)obj); - return; - } - // Note: strictly speaking, for Configurable params we don't need finaliseCCDB check, the singletons are updated at the CCDB fetcher level - if (matcher == ConcreteDataMatcher("ITS", "ALPIDEPARAM", 0)) { - LOG(info) << "Alpide param updated"; - const auto& par = o2::itsmft::DPLAlpideParam::Instance(); - par.printKeyValues(); - return; - } - if (matcher == ConcreteDataMatcher("GLO", "MEANVERTEX", 0)) { - LOGP(info, "mean vertex acquired"); - setMeanVertex((const o2::dataformats::MeanVertexObject*)obj); - return; - } - if (matcher == ConcreteDataMatcher("ITS", "GEOMTGEO", 0)) { - LOG(info) << "ITS GeomtetryTGeo loaded from ccdb"; - o2::its::GeometryTGeo::adopt((o2::its::GeometryTGeo*)obj); - return; - } + mITSTrackingInterface.finaliseCCDB(matcher, obj); } void TrackerDPL::endOfStream(EndOfStreamContext& ec) { - LOGF(info, "ITS CA-Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", - mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); + LOGF(info, "ITS CA-Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, const std::string& trModeS, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType) @@ -437,7 +118,13 @@ DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, const st "its-tracker", inputs, outputs, - AlgorithmSpec{adaptFromTask(ggRequest, useMC, trgType, trModeS, overrBeamEst, dType)}, + AlgorithmSpec{adaptFromTask(ggRequest, + useMC, + trgType, + trModeS == "sync" ? o2::its::TrackingMode::Sync : trModeS == "async" ? o2::its::TrackingMode::Async + : o2::its::TrackingMode::Cosmics, + overrBeamEst, + dType)}, Options{}}; } diff --git a/GPU/GPUTracking/Global/GPUChainITS.cxx b/GPU/GPUTracking/Global/GPUChainITS.cxx index 127bef6d92537..9e62b480bcac9 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.cxx +++ b/GPU/GPUTracking/Global/GPUChainITS.cxx @@ -90,7 +90,6 @@ o2::its::TimeFrame* GPUChainITS::GetITSTimeframe() mFrameworkAllocator.reset(new o2::its::GPUFrameworkExternalAllocator); mFrameworkAllocator->setReconstructionFramework(rec()); mITSTimeFrame->setExternalAllocator(mFrameworkAllocator.get()); - LOGP(info, "GPUChainITS is giving me allocator: {}", (void*)mFrameworkAllocator.get()); } #endif return mITSTimeFrame.get(); From 2ed51a9ba115c2db28a0ddc55820755e576ea10e Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Tue, 2 Apr 2024 17:52:19 +0200 Subject: [PATCH 0036/2997] Use ITSTrackingInterface for GPUReco --- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 3 +- .../ITSMFT/ITS/tracking/GPU/cuda/Utils.cu | 8 - .../include/ITStracking/Configuration.h | 3 + .../include/ITStracking/TrackingInterface.h | 14 +- .../ITSMFT/ITS/tracking/src/Configuration.cxx | 34 ++ .../ITS/tracking/src/TrackingInterface.cxx | 55 ++- .../include/ITSWorkflow/RecoWorkflow.h | 3 - .../include/ITSWorkflow/TrackerSpec.h | 5 +- .../ITS/workflow/src/CookedTrackerSpec.cxx | 20 +- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 11 +- GPU/Workflow/CMakeLists.txt | 3 +- .../include/GPUWorkflow/GPUWorkflowSpec.h | 8 +- GPU/Workflow/src/GPUWorkflowITS.cxx | 379 +----------------- GPU/Workflow/src/GPUWorkflowSpec.cxx | 8 +- 14 files changed, 101 insertions(+), 453 deletions(-) create mode 100644 Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index 3c631cda64a6e..d11660a116a2f 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -13,6 +13,7 @@ o2_add_library(ITStracking TARGETVARNAME targetName SOURCES src/ClusterLines.cxx src/Cluster.cxx + src/Configuration.cxx src/ROframe.cxx src/TimeFrame.cxx src/IOUtils.cxx @@ -40,7 +41,7 @@ o2_add_library(ITStracking o2_add_library(ITSTrackingInterface TARGETVARNAME targetName SOURCES src/TrackingInterface.cxx - PUBLIC_LINK_LIBRARIES + PRIVATE_LINK_LIBRARIES O2::ITStracking O2::Framework O2::GPUTracking) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu index 0ed5c58e29c43..99a24f347bd48 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/Utils.cu @@ -284,14 +284,6 @@ void utils::gpuMemcpyFromSymbol(void* dst, const void* symbol, int size) { checkGPUError(cudaMemcpyFromSymbol(dst, symbol, size, 0, cudaMemcpyDeviceToHost), __FILE__, __LINE__); } - -GPUd() int utils::getLaneIndex() -{ - uint32_t laneIndex; - asm volatile("mov.u32 %0, %%laneid;" - : "=r"(laneIndex)); - return static_cast(laneIndex); -} } // namespace gpu } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 810257a38fd3d..2a66bbd245e87 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -37,6 +37,9 @@ enum class TrackingMode { Cosmics }; +std::string asString(TrackingMode mode); +std::ostream& operator<<(std::ostream& os, TrackingMode v); + template class Configuration : public Param { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h index d681a29aef1ba..0700cfdf09885 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h @@ -23,8 +23,6 @@ #include "DataFormatsITSMFT/TopologyDictionary.h" #include "DataFormatsCalibration/MeanVertexObject.h" -#include "DetectorsBase/GRPGeomHelper.h" - #include "GPUDataTypes.h" #include "GPUO2Interface.h" #include "GPUChainITS.h" @@ -34,13 +32,11 @@ namespace o2::its class ITSTrackingInterface { public: - ITSTrackingInterface(std::shared_ptr gr, - bool isMC, + ITSTrackingInterface(bool isMC, int trgType, const TrackingMode trMode, const bool overrBeamEst) - : mGGCCDBRequest(gr), - mIsMC{isMC}, + : mIsMC{isMC}, mUseTriggers{trgType}, mMode{trMode}, mOverrideBeamEstimation{overrBeamEst} @@ -55,11 +51,14 @@ class ITSTrackingInterface } mMeanVertex = v; } - // Task handles + // Task callbacks void initialise(); + template void run(framework::ProcessingContext& pc); + void updateTimeDependentParams(framework::ProcessingContext& pc); void finaliseCCDB(framework::ConcreteDataMatcher& matcher, void* obj); + // Custom void setTraitsFromProvider(VertexerTraits*, TrackerTraits*, TimeFrame*); @@ -70,7 +69,6 @@ class ITSTrackingInterface int mUseTriggers = 0; TrackingMode mMode = TrackingMode::Sync; bool mOverrideBeamEstimation = false; - std::shared_ptr mGGCCDBRequest; const o2::itsmft::TopologyDictionary* mDict = nullptr; std::unique_ptr mTracker = nullptr; std::unique_ptr mVertexer = nullptr; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx new file mode 100644 index 0000000000000..3c22260901900 --- /dev/null +++ b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx @@ -0,0 +1,34 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "ITStracking/Configuration.h" + +namespace o2::its +{ +std::string asString(TrackingMode mode) +{ + switch (mode) { + case TrackingMode::Sync: + return "sync"; + case TrackingMode::Async: + return "async"; + case TrackingMode::Cosmics: + return "cosmics"; + } + return "unknown"; +} + +std::ostream& operator<<(std::ostream& os, TrackingMode v) +{ + os << asString(v); + return os; +} +} // namespace o2::its \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index b768f561f4dd6..066d400a17f19 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -21,35 +21,17 @@ #include "DataFormatsITSMFT/PhysTrigger.h" #include "DataFormatsTRD/TriggerRecord.h" #include "CommonDataFormat/IRFrame.h" +#include "DetectorsBase/GRPGeomHelper.h" namespace o2 { using namespace framework; namespace its { - -std::string asString(TrackingMode mode) -{ - switch (mode) { - case TrackingMode::Sync: - return "sync"; - case TrackingMode::Async: - return "async"; - case TrackingMode::Cosmics: - return "cosmics"; - } - return "unknown"; -} - -std::ostream& operator<<(std::ostream& os, TrackingMode v) -{ - os << asString(v); - return os; -} - void ITSTrackingInterface::initialise() { - o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); + mRunVertexer = true; + mCosmicsProcessing = false; std::vector trackParams; if (mMode == TrackingMode::Async) { @@ -99,9 +81,9 @@ void ITSTrackingInterface::initialise() mTracker->setParameters(trackParams); } +template void ITSTrackingInterface::run(framework::ProcessingContext& pc) { - updateTimeDependentParams(pc); auto compClusters = pc.inputs().get>("compClusters"); gsl::span patterns = pc.inputs().get>("patterns"); gsl::span physTriggers; @@ -182,7 +164,11 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) if (mRunVertexer) { vertROFvec.reserve(rofs.size()); // Run seeding vertexer - vertexerElapsedTime = mVertexer->clustersToVertices(logger); + if constexpr (isGPU) { + vertexerElapsedTime = mVertexer->clustersToVerticesHybrid(logger); + } else { + vertexerElapsedTime = mVertexer->clustersToVertices(logger); + } } else { // cosmics mTimeFrame->resetRofPV(); } @@ -240,10 +226,18 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) mTimeFrame->setMultiplicityCutMask(processingMask); // Run CA tracker - if (mMode == o2::its::TrackingMode::Async) { - mTracker->clustersToTracks(logger, fatalLogger); + if constexpr (isGPU) { + if (mMode == o2::its::TrackingMode::Async) { + mTracker->clustersToTracksHybrid(logger, fatalLogger); + } else { + mTracker->clustersToTracksHybrid(logger, errorLogger); + } } else { - mTracker->clustersToTracks(logger, errorLogger); + if (mMode == o2::its::TrackingMode::Async) { + mTracker->clustersToTracks(logger, fatalLogger); + } else { + mTracker->clustersToTracks(logger, errorLogger); + } } size_t totTracks{mTimeFrame->getNumberOfTracks()}, totClusIDs{mTimeFrame->getNumberOfUsedClusters()}; allTracks.reserve(totTracks); @@ -298,8 +292,8 @@ void ITSTrackingInterface::updateTimeDependentParams(framework::ProcessingContex static bool initOnceDone = false; if (!initOnceDone) { // this params need to be queried only once initOnceDone = true; - pc.inputs().get("cldict"); // just to trigger the finaliseCCDB - pc.inputs().get*>("alppar"); + pc.inputs().get("itscldict"); // just to trigger the finaliseCCDB + pc.inputs().get*>("itsalppar"); if (pc.inputs().getPos("itsTGeo") >= 0) { pc.inputs().get("itsTGeo"); } @@ -336,7 +330,7 @@ void ITSTrackingInterface::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) return; } if (matcher == ConcreteDataMatcher("ITS", "GEOMTGEO", 0)) { - LOG(info) << "ITS GeomtetryTGeo loaded from ccdb"; + LOG(info) << "ITS GeometryTGeo loaded from ccdb"; o2::its::GeometryTGeo::adopt((o2::its::GeometryTGeo*)obj); return; } @@ -352,5 +346,8 @@ void ITSTrackingInterface::setTraitsFromProvider(VertexerTraits* vertexerTraits, mVertexer->adoptTimeFrame(*mTimeFrame); mTracker->adoptTimeFrame(*mTimeFrame); } + +template void ITSTrackingInterface::run(framework::ProcessingContext& pc); +template void ITSTrackingInterface::run(framework::ProcessingContext& pc); } // namespace its } // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h index 169e8009c5275..7f9efa2098893 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h @@ -16,9 +16,6 @@ #include "Framework/WorkflowSpec.h" -// #include "GPUO2Interface.h" -// #include "GPUReconstruction.h" -// #include "GPUChainITS.h" #include "GPUDataTypes.h" namespace o2 diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h index 6eedca2a459b4..643511cbfc164 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h @@ -41,7 +41,7 @@ class TrackerDPL : public framework::Task TrackerDPL(std::shared_ptr gr, bool isMC, int trgType, - const TrackingMode& trModeS, + const TrackingMode& trMode, const bool overrBeamEst = false, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU); ~TrackerDPL() override = default; @@ -55,12 +55,11 @@ class TrackerDPL : public framework::Task void updateTimeDependentParams(framework::ProcessingContext& pc); std::unique_ptr mRecChain = nullptr; std::unique_ptr mChainITS = nullptr; + std::shared_ptr mGGCCDBRequest; ITSTrackingInterface mITSTrackingInterface; TStopwatch mTimer; }; -/// create a processor spec -/// run ITS CA tracker framework::DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int useTrig, const std::string& trModeS, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType); } // namespace its diff --git a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx index a534479b90085..01e649f982896 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx @@ -51,24 +51,6 @@ namespace its { using Vertex = o2::dataformats::Vertex>; -std::string asString(TrackingMode mode) -{ - switch (mode) { - case TrackingMode::Sync: - return "sync"; - case TrackingMode::Async: - return "async"; - case TrackingMode::Cosmics: - return "cosmics"; - } - return "unknown"; -} - -std::ostream& operator<<(std::ostream& os, TrackingMode v) -{ - os << asString(v); - return os; -} CookedTrackerDPL::CookedTrackerDPL(std::shared_ptr gr, bool useMC, int trgType, const TrackingMode& trMode) : mGGCCDBRequest(gr), mUseMC(useMC), mUseTriggers{trgType}, mMode(trMode) { @@ -281,7 +263,7 @@ void CookedTrackerDPL::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) return; } if (matcher == ConcreteDataMatcher("ITS", "GEOMTGEO", 0)) { - LOG(info) << "ITS GeomtetryTGeo loaded from ccdb"; + LOG(info) << "ITS GeometryTGeo loaded from ccdb"; o2::its::GeometryTGeo::adopt((o2::its::GeometryTGeo*)obj); return; } diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 01fcbc064a265..c26bc5171ddeb 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -28,8 +28,9 @@ TrackerDPL::TrackerDPL(std::shared_ptr gr, int trgType, const TrackingMode& trMode, const bool overrBeamEst, - o2::gpu::GPUDataTypes::DeviceType dType) : mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)}, - mITSTrackingInterface{gr, isMC, trgType, trMode, overrBeamEst} + o2::gpu::GPUDataTypes::DeviceType dType) : mGGCCDBRequest(gr), + mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)}, + mITSTrackingInterface{isMC, trgType, trMode, overrBeamEst} { } @@ -37,6 +38,7 @@ void TrackerDPL::init(InitContext& ic) { mTimer.Stop(); mTimer.Reset(); + o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); mChainITS.reset(mRecChain->AddChain()); mITSTrackingInterface.setTraitsFromProvider(mChainITS->GetITSVertexerTraits(), mChainITS->GetITSTrackerTraits(), @@ -54,6 +56,7 @@ void TrackerDPL::run(ProcessingContext& pc) auto cput = mTimer.CpuTime(); auto realt = mTimer.RealTime(); mTimer.Start(false); + mITSTrackingInterface.updateTimeDependentParams(pc); mITSTrackingInterface.run(pc); mTimer.Stop(); LOGP(info, "CPU Reconstruction time for this TF {} s (cpu), {} s (wall)", mTimer.CpuTime() - cput, mTimer.RealTime() - realt); @@ -81,8 +84,8 @@ DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, const st } else if (trgType == 2) { inputs.emplace_back("phystrig", "TRD", "TRKTRGRD", 0, Lifetime::Timeframe); } - inputs.emplace_back("cldict", "ITS", "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/ClusterDictionary")); - inputs.emplace_back("alppar", "ITS", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("ITS/Config/AlpideParam")); + inputs.emplace_back("itscldict", "ITS", "CLUSDICT", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/ClusterDictionary")); + inputs.emplace_back("itsalppar", "ITS", "ALPIDEPARAM", 0, Lifetime::Condition, ccdbParamSpec("ITS/Config/AlpideParam")); auto ggRequest = std::make_shared(false, // orbitResetTime true, // GRPECS=true false, // GRPLHCIF diff --git a/GPU/Workflow/CMakeLists.txt b/GPU/Workflow/CMakeLists.txt index 51494b1a1703e..aa725168b9db2 100644 --- a/GPU/Workflow/CMakeLists.txt +++ b/GPU/Workflow/CMakeLists.txt @@ -26,7 +26,8 @@ o2_add_library(GPUWorkflow O2::TPCReaderWorkflow O2::DataFormatsGlobalTracking O2::DataFormatsTRD - PRIVATE_LINK_LIBRARIES O2::GPUTracking) + PRIVATE_LINK_LIBRARIES O2::GPUTracking + O2::ITSTrackingInterface) o2_add_executable(reco-workflow COMPONENT_NAME gpu diff --git a/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h b/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h index 60567adc73e3d..65940b764f79c 100644 --- a/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h +++ b/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h @@ -58,9 +58,8 @@ class GeometryFlat; namespace its { -class Tracker; -class Vertexer; class TimeFrame; +class ITSTrackingInterface; } // namespace its namespace itsmft @@ -211,8 +210,7 @@ class GPURecoWorkflowSpec : public o2::framework::Task std::unique_ptr mQA; std::vector mClusterOutputIds; std::vector mTPCSectors; - std::unique_ptr mITSTracker; - std::unique_ptr mITSVertexer; + std::unique_ptr mITSTrackingInterface; std::unique_ptr mPipeline; o2::its::TimeFrame* mITSTimeFrame = nullptr; std::vector mRegionInfos; @@ -235,8 +233,6 @@ class GPURecoWorkflowSpec : public o2::framework::Task bool mITSGeometryCreated = false; bool mTRDGeometryCreated = false; bool mPropagatorInstanceCreated = false; - bool mITSRunVertexer = false; - bool mITSCosmicsProcessing = false; }; } // end namespace gpu diff --git a/GPU/Workflow/src/GPUWorkflowITS.cxx b/GPU/Workflow/src/GPUWorkflowITS.cxx index 8d3270eafd54b..72f466591d231 100644 --- a/GPU/Workflow/src/GPUWorkflowITS.cxx +++ b/GPU/Workflow/src/GPUWorkflowITS.cxx @@ -10,397 +10,48 @@ // or submit itself to any jurisdiction. /// @file GPUWorkflowITS.cxx -/// @author David Rohr +/// @author David Rohr, Matteo Concas #include "GPUWorkflow/GPUWorkflowSpec.h" -#include "Headers/DataHeader.h" #include "Framework/WorkflowSpec.h" // o2::framework::mergeInputs -#include "Framework/DataRefUtils.h" -#include "Framework/DataSpecUtils.h" -#include "Framework/DeviceSpec.h" #include "Framework/ControlService.h" #include "Framework/ConfigParamRegistry.h" -#include "Framework/InputRecordWalker.h" -#include "Framework/SerializationMethods.h" -#include "Framework/Logger.h" -#include "Framework/CallbackService.h" #include "Framework/CCDBParamSpec.h" -#include "DataFormatsTPC/TPCSectorHeader.h" -#include "DataFormatsTPC/ClusterNative.h" -#include "DataFormatsTPC/CompressedClusters.h" -#include "DataFormatsTPC/Helpers.h" -#include "DataFormatsTPC/ZeroSuppression.h" -#include "DataFormatsTPC/RawDataTypes.h" -#include "DataFormatsTPC/WorkflowHelper.h" -#include "DataFormatsGlobalTracking/TrackTuneParams.h" -#include "TPCReconstruction/TPCTrackingDigitsPreCheck.h" -#include "TPCReconstruction/TPCFastTransformHelperO2.h" -#include "DataFormatsTPC/Digit.h" -#include "TPCFastTransform.h" -#include "DetectorsBase/MatLayerCylSet.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsRaw/HBFUtils.h" -#include "DetectorsBase/GRPGeomHelper.h" -#include "CommonUtils/NameConf.h" -#include "TPCBase/RDHUtils.h" -#include "GPUO2InterfaceConfiguration.h" -#include "GPUO2InterfaceQA.h" -#include "GPUO2Interface.h" -#include "CalibdEdxContainer.h" -#include "GPUNewCalibValues.h" -#include "TPCPadGainCalib.h" -#include "TPCZSLinkMapping.h" -#include "display/GPUDisplayInterface.h" -#include "TPCBase/Sector.h" -#include "TPCBase/Utils.h" -#include "TPCBase/CDBInterface.h" -#include "TPCCalibration/VDriftHelper.h" -#include "CorrectionMapsHelper.h" -#include "TPCCalibration/CorrectionMapsLoader.h" -#include "SimulationDataFormat/ConstMCTruthContainer.h" -#include "SimulationDataFormat/MCCompLabel.h" -#include "Algorithm/Parser.h" -#include "DataFormatsGlobalTracking/RecoContainer.h" -#include "DataFormatsTRD/RecoInputContainer.h" -#include "TRDBase/Geometry.h" -#include "TRDBase/GeometryFlat.h" -#include "ITSBase/GeometryTGeo.h" -#include "CommonUtils/VerbosityConfig.h" -#include "CommonUtils/DebugStreamer.h" -#include -#include // for make_shared -#include -#include -#include -#include -#include -#include -#include -#include -#include "GPUReconstructionConvert.h" -#include "DetectorsRaw/RDHUtils.h" -#include -#include -#include -#include -#include -#include -#include "ITStracking/TimeFrame.h" -#include "ITStracking/Tracker.h" -#include "ITStracking/TrackerTraits.h" -#include "ITStracking/Vertexer.h" -#include "ITStracking/VertexerTraits.h" -#include "DataFormatsITSMFT/TopologyDictionary.h" -#include "ITSMFTBase/DPLAlpideParam.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsITSMFT/ROFRecord.h" -#include "DataFormatsITSMFT/PhysTrigger.h" -#include "CommonDataFormat/IRFrame.h" -#include "ITSReconstruction/FastMultEst.h" -#include "ITSReconstruction/FastMultEstConfig.h" - -using namespace o2::framework; -using namespace o2::header; -using namespace o2::gpu; -using namespace o2::base; -using namespace o2::dataformats; +#include "ITStracking/TrackingInterface.h" namespace o2::gpu { int GPURecoWorkflowSpec::runITSTracking(o2::framework::ProcessingContext& pc) { - using Vertex = o2::dataformats::Vertex>; - mITSTimeFrame->setDevicePropagator(mGPUReco->GetDeviceO2Propagator()); - LOGP(info, "GPUChainITS is giving me device propagator: {}", (void*)mGPUReco->GetDeviceO2Propagator()); - - auto compClusters = pc.inputs().get>("compClusters"); - gsl::span patterns = pc.inputs().get>("patterns"); - gsl::span physTriggers; - std::vector fromTRD; - if (mSpecConfig.itsTriggerType == 2) { // use TRD triggers - o2::InteractionRecord ir{0, pc.services().get().firstTForbit}; - auto trdTriggers = pc.inputs().get>("phystrig"); - for (const auto& trig : trdTriggers) { - if (trig.getBCData() >= ir && trig.getNumberOfTracklets()) { - ir = trig.getBCData(); - fromTRD.emplace_back(o2::itsmft::PhysTrigger{ir, 0}); - } - } - physTriggers = gsl::span(fromTRD.data(), fromTRD.size()); - } else if (mSpecConfig.itsTriggerType == 1) { // use Phys triggers from ITS stream - physTriggers = pc.inputs().get>("phystrig"); - } - - auto rofsinput = pc.inputs().get>("ROframes"); - - auto& rofs = pc.outputs().make>(Output{"ITS", "ITSTrackROF", 0}, rofsinput.begin(), rofsinput.end()); - auto& irFrames = pc.outputs().make>(Output{"ITS", "IRFRAMES", 0}); - irFrames.reserve(rofs.size()); - - const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); // RS: this should come from CCDB - int nBCPerTF = alpParams.roFrameLengthInBC; - - LOG(info) << "ITSTracker pulled " << compClusters.size() << " clusters, " << rofs.size() << " RO frames"; - - const dataformats::MCTruthContainer* labels = nullptr; - gsl::span mc2rofs; - if (mSpecConfig.processMC) { - labels = pc.inputs().get*>("itsmclabels").release(); - // get the array as read-only span, a snapshot is sent forward - pc.outputs().snapshot(Output{"ITS", "ITSTrackMC2ROF", 0}, pc.inputs().get>("ITSMC2ROframes")); - LOG(info) << labels->getIndexedSize() << " MC label objects , in " << mc2rofs.size() << " MC events"; - } - - auto& allClusIdx = pc.outputs().make>(Output{"ITS", "TRACKCLSID", 0}); - auto& allTracks = pc.outputs().make>(Output{"ITS", "TRACKS", 0}); - auto& vertROFvec = pc.outputs().make>(Output{"ITS", "VERTICESROF", 0}); - auto& vertices = pc.outputs().make>(Output{"ITS", "VERTICES", 0}); - - // MC - static pmr::vector dummyMCLabTracks, dummyMCLabVerts; - auto& allTrackLabels = mSpecConfig.processMC ? pc.outputs().make>(Output{"ITS", "TRACKSMCTR", 0}) : dummyMCLabTracks; - auto& allVerticesLabels = mSpecConfig.processMC ? pc.outputs().make>(Output{"ITS", "VERTICESMCTR", 0}) : dummyMCLabVerts; - - std::uint32_t roFrame = 0; - - bool continuous = o2::base::GRPGeomHelper::instance().getGRPECS()->isDetContinuousReadOut(o2::detectors::DetID::ITS); - LOG(info) << "ITSTracker RO: continuous=" << continuous; - - if (mSpecConfig.itsOverrBeamEst) { - mITSTimeFrame->setBeamPosition(mMeanVertex->getX(), - mMeanVertex->getY(), - mMeanVertex->getSigmaY2(), - mITSTracker->getParameters()[0].LayerResolution[0], - mITSTracker->getParameters()[0].SystErrorY2[0]); - } - - mITSTracker->setBz(o2::base::Propagator::Instance()->getNominalBz()); - - gsl::span::iterator pattIt = patterns.begin(); - - gsl::span rofspan(rofs); - mITSTimeFrame->loadROFrameData(rofspan, compClusters, pattIt, mITSDict, labels); - pattIt = patterns.begin(); - std::vector savedROF; - auto logger = [&](std::string s) { LOG(info) << s; }; - auto fatalLogger = [&](std::string s) { LOG(fatal) << s; }; - auto errorLogger = [&](std::string s) { LOG(error) << s; }; - - o2::its::FastMultEst multEst; // mult estimator - std::vector processingMask; - int cutVertexMult{0}, cutRandomMult = int(rofs.size()) - multEst.selectROFs(rofs, compClusters, physTriggers, processingMask); - mITSTimeFrame->setMultiplicityCutMask(processingMask); - float vertexerElapsedTime{0.f}; - if (mITSRunVertexer) { - // Run seeding vertexer - vertROFvec.reserve(rofs.size()); - vertexerElapsedTime = mITSVertexer->clustersToVerticesHybrid(logger); - } else { // cosmics - mITSTimeFrame->resetRofPV(); - } - const auto& multEstConf = o2::its::FastMultEstConfig::Instance(); // parameters for mult estimation and cuts - for (auto iRof{0}; iRof < rofspan.size(); ++iRof) { - std::vector vtxVecLoc; - auto& vtxROF = vertROFvec.emplace_back(rofspan[iRof]); - vtxROF.setFirstEntry(vertices.size()); - if (mITSRunVertexer) { - auto vtxSpan = mITSTimeFrame->getPrimaryVertices(iRof); - vtxROF.setNEntries(vtxSpan.size()); - bool selROF = vtxSpan.size() == 0; - for (auto iV{0}; iV < vtxSpan.size(); ++iV) { - auto& v = vtxSpan[iV]; - if (multEstConf.isVtxMultCutRequested() && !multEstConf.isPassingVtxMultCut(v.getNContributors())) { - continue; // skip vertex of unwanted multiplicity - } - selROF = true; - vertices.push_back(v); - if (mSpecConfig.processMC) { - auto vLabels = mITSTimeFrame->getPrimaryVerticesLabels(iRof)[iV]; - allVerticesLabels.reserve(allVerticesLabels.size() + vLabels.size()); - std::copy(vLabels.begin(), vLabels.end(), std::back_inserter(allVerticesLabels)); - } - } - if (processingMask[iRof] && !selROF) { // passed selection in clusters and not in vertex multiplicity - LOG(debug) << fmt::format("ROF {} rejected by the vertex multiplicity selection [{},{}]", - iRof, - multEstConf.cutMultVtxLow, - multEstConf.cutMultVtxHigh); - processingMask[iRof] = selROF; - cutVertexMult++; - } - } else { // cosmics - vtxVecLoc.emplace_back(Vertex()); - vtxVecLoc.back().setNContributors(1); - vtxROF.setNEntries(vtxVecLoc.size()); - for (auto& v : vtxVecLoc) { - vertices.push_back(v); - } - mITSTimeFrame->addPrimaryVertices(vtxVecLoc); - } - } - LOG(info) << fmt::format(" - rejected {}/{} ROFs: random/mult.sel:{} (seed {}), vtx.sel:{}", cutRandomMult + cutVertexMult, rofspan.size(), cutRandomMult, multEst.lastRandomSeed, cutVertexMult); - LOG(info) << fmt::format(" - Vertex seeding total elapsed time: {} ms for {} vertices found in {} ROFs", vertexerElapsedTime, mITSTimeFrame->getPrimaryVerticesNum(), rofspan.size()); - - if (mSpecConfig.itsOverrBeamEst) { - LOG(info) << fmt::format(" - Beam position set to: {}, {} from meanvertex object", mITSTimeFrame->getBeamX(), mITSTimeFrame->getBeamY()); - } else { - LOG(info) << fmt::format(" - Beam position computed for the TF: {}, {}", mITSTimeFrame->getBeamX(), mITSTimeFrame->getBeamY()); - } - if (mITSCosmicsProcessing && compClusters.size() > 1500 * rofspan.size()) { - LOG(error) << "Cosmics processing was requested with an average detector occupancy exceeding 1.e-7, skipping TF processing."; - } else { - - mITSTimeFrame->setMultiplicityCutMask(processingMask); - // Run CA tracker - if (!mSpecConfig.itsTrackingMode) { - mITSTracker->clustersToTracksHybrid(logger, errorLogger); - } else { - mITSTracker->clustersToTracksHybrid(logger, fatalLogger); - } - size_t totTracks{mITSTimeFrame->getNumberOfTracks()}, totClusIDs{mITSTimeFrame->getNumberOfUsedClusters()}; - allTracks.reserve(totTracks); - allClusIdx.reserve(totClusIDs); - - if (mITSTimeFrame->hasBogusClusters()) { - LOG(warning) << fmt::format(" - The processed timeframe had {} clusters with wild z coordinates, check the dictionaries", mITSTimeFrame->hasBogusClusters()); - } - - for (unsigned int iROF{0}; iROF < rofs.size(); ++iROF) { - auto& rof{rofs[iROF]}; - auto& tracks = mITSTimeFrame->getTracks(iROF); - auto number{tracks.size()}; - auto first{allTracks.size()}; - int offset = -rof.getFirstEntry(); // cluster entry!!! - rof.setFirstEntry(first); - rof.setNEntries(number); - - if (processingMask[iROF]) { - irFrames.emplace_back(rof.getBCData(), rof.getBCData() + nBCPerTF - 1).info = tracks.size(); - } - - allTrackLabels.reserve(mITSTimeFrame->getTracksLabel(iROF).size()); // should be 0 if not MC - std::copy(mITSTimeFrame->getTracksLabel(iROF).begin(), mITSTimeFrame->getTracksLabel(iROF).end(), std::back_inserter(allTrackLabels)); - // Some conversions that needs to be moved in the tracker internals - for (unsigned int iTrk{0}; iTrk < tracks.size(); ++iTrk) { - auto& trc{tracks[iTrk]}; - trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices - int ncl = trc.getNumberOfClusters(), nclf = 0; - for (int ic = o2::its::TrackITSExt::MaxClusters; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! - auto clid = trc.getClusterIndex(ic); - if (clid >= 0) { - allClusIdx.push_back(clid); - nclf++; - } - } - assert(ncl == nclf); - allTracks.emplace_back(trc); - } - } - LOGP(info, "ITSTracker pushed {} tracks and {} vertices", allTracks.size(), vertices.size()); - if (mSpecConfig.processMC) { - LOGP(info, "ITSTracker pushed {} track labels", allTrackLabels.size()); - LOGP(info, "ITSTracker pushed {} vertex labels", allVerticesLabels.size()); - } - } + LOGP(debug, "GPUChainITS is giving me device propagator: {}", (void*)mGPUReco->GetDeviceO2Propagator()); + mITSTrackingInterface->run(pc); return 0; } -void GPURecoWorkflowSpec::initFunctionITS(InitContext& ic) +void GPURecoWorkflowSpec::initFunctionITS(o2::framework::InitContext& ic) { o2::its::VertexerTraits* vtxTraits = nullptr; o2::its::TrackerTraits* trkTraits = nullptr; + mITSTrackingInterface = std::make_unique(mSpecConfig.processMC, + mSpecConfig.itsTriggerType, + static_cast(mSpecConfig.itsTrackingMode), + mSpecConfig.itsOverrBeamEst); mGPUReco->GetITSTraits(trkTraits, vtxTraits, mITSTimeFrame); - mITSVertexer = std::make_unique(vtxTraits); - mITSTracker = std::make_unique(trkTraits); - mITSVertexer->adoptTimeFrame(*mITSTimeFrame); - mITSTracker->adoptTimeFrame(*mITSTimeFrame); - mITSRunVertexer = true; - mITSCosmicsProcessing = false; - std::vector trackParams; - - if (mSpecConfig.itsTrackingMode == 1) { - trackParams.resize(3); - for (auto& param : trackParams) { - param.ZBins = 64; - param.PhiBins = 32; - param.CellsPerClusterLimit = 1.e3f; - param.TrackletsPerClusterLimit = 1.e3f; - } - trackParams[1].TrackletMinPt = 0.2f; - trackParams[1].CellDeltaTanLambdaSigma *= 2.; - trackParams[2].TrackletMinPt = 0.1f; - trackParams[2].CellDeltaTanLambdaSigma *= 4.; - trackParams[2].MinTrackLength = 4; - LOG(info) << "Initializing tracker in async. phase reconstruction with " << trackParams.size() << " passes"; - } else if (mSpecConfig.itsTrackingMode == 0) { - trackParams.resize(1); - trackParams[0].ZBins = 64; - trackParams[0].PhiBins = 32; - trackParams[0].MinTrackLength = 4; - LOG(info) << "Initializing tracker in sync. phase reconstruction with " << trackParams.size() << " passes"; - } else if (mSpecConfig.itsTrackingMode == 2) { - mITSCosmicsProcessing = true; - mITSRunVertexer = false; - trackParams.resize(1); - trackParams[0].MinTrackLength = 4; - trackParams[0].CellDeltaTanLambdaSigma *= 10; - trackParams[0].PhiBins = 4; - trackParams[0].ZBins = 16; - trackParams[0].PVres = 1.e5f; - trackParams[0].MaxChi2ClusterAttachment = 60.; - trackParams[0].MaxChi2NDF = 40.; - trackParams[0].TrackletsPerClusterLimit = 100.; - trackParams[0].CellsPerClusterLimit = 100.; - LOG(info) << "Initializing tracker in reconstruction for cosmics with " << trackParams.size() << " passes"; - } - - for (auto& params : trackParams) { - params.CorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT; - } - mITSTracker->setParameters(trackParams); + mITSTrackingInterface->setTraitsFromProvider(vtxTraits, trkTraits, mITSTimeFrame); + mITSTrackingInterface->initialise(); } -void GPURecoWorkflowSpec::finaliseCCDBITS(ConcreteDataMatcher& matcher, void* obj) +void GPURecoWorkflowSpec::finaliseCCDBITS(o2::framework::ConcreteDataMatcher& matcher, void* obj) { - if (matcher == ConcreteDataMatcher("ITS", "CLUSDICT", 0)) { - LOG(info) << "cluster dictionary updated"; - mITSDict = (const o2::itsmft::TopologyDictionary*)obj; - return; - } - // Note: strictly speaking, for Configurable params we don't need finaliseCCDB check, the singletons are updated at the CCDB fetcher level - if (matcher == ConcreteDataMatcher("ITS", "ALPIDEPARAM", 0)) { - LOG(info) << "Alpide param updated"; - const auto& par = o2::itsmft::DPLAlpideParam::Instance(); - par.printKeyValues(); - return; - } - if (matcher == ConcreteDataMatcher("GLO", "MEANVERTEX", 0)) { - LOGP(info, "mean vertex acquired"); - if (obj) { - mMeanVertex = (const o2::dataformats::MeanVertexObject*)obj; - } - return; - } + mITSTrackingInterface->finaliseCCDB(matcher, obj); } -bool GPURecoWorkflowSpec::fetchCalibsCCDBITS(ProcessingContext& pc) +bool GPURecoWorkflowSpec::fetchCalibsCCDBITS(o2::framework::ProcessingContext& pc) { - static bool initOnceDone = false; - if (!initOnceDone) { // this params need to be queried only once - initOnceDone = true; - pc.inputs().get("itscldict"); // just to trigger the finaliseCCDB - pc.inputs().get*>("itsalppar"); - mITSVertexer->getGlobalConfiguration(); - mITSTracker->getGlobalConfiguration(); - if (mSpecConfig.itsOverrBeamEst) { - pc.inputs().get("meanvtx"); - } - } + mITSTrackingInterface->updateTimeDependentParams(pc); return false; } - } // namespace o2::gpu diff --git a/GPU/Workflow/src/GPUWorkflowSpec.cxx b/GPU/Workflow/src/GPUWorkflowSpec.cxx index 5b219da31f9b9..29e0f2313e28b 100644 --- a/GPU/Workflow/src/GPUWorkflowSpec.cxx +++ b/GPU/Workflow/src/GPUWorkflowSpec.cxx @@ -76,8 +76,7 @@ #include "CommonUtils/DebugStreamer.h" #include "GPUReconstructionConvert.h" #include "DetectorsRaw/RDHUtils.h" -#include "ITStracking/Tracker.h" -#include "ITStracking/Vertexer.h" +#include "ITStracking/TrackingInterface.h" #include "GPUWorkflowInternal.h" // #include "Framework/ThreadPool.h" @@ -375,11 +374,6 @@ void GPURecoWorkflowSpec::finaliseCCDB(o2::framework::ConcreteDataMatcher& match mGRPGeomUpdated = true; return; } - if (matcher == ConcreteDataMatcher("ITS", "GEOMTGEO", 0)) { - LOG(info) << "ITS GeomtetryTGeo loaded from ccdb"; - o2::its::GeometryTGeo::adopt((o2::its::GeometryTGeo*)obj); - return; - } } template From dd4a55f8b35c08323a2329a5a0dfa763fdc257cb Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 3 Apr 2024 10:20:07 +0200 Subject: [PATCH 0037/2997] DPL: Improve warning message --- Framework/Core/src/DataProcessingDevice.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 35cc2524ed98b..d5a07a1ebfd52 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -122,7 +122,7 @@ void on_transition_requested_expired(uv_timer_t* handle) auto* state = (DeviceState*)handle->data; state->loopReason |= DeviceState::TIMER_EXPIRED; O2_SIGNPOST_ID_FROM_POINTER(cid, device, handle); - O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "callback", "Grace period for calibration expired. Exiting."); + O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "callback", "Exit transition timer expired. Exiting."); state->transitionHandling = TransitionHandlingState::Expired; } From 046c793ced0c97040ba213b89d25053c021715ed Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 3 Apr 2024 13:52:11 +0200 Subject: [PATCH 0038/2997] ClusterSharingMapSpec loads GRPECS for NHBFPerTF --- .../workflow/include/TPCWorkflow/ClusterSharingMapSpec.h | 2 ++ Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/ClusterSharingMapSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/ClusterSharingMapSpec.h index 1bade0eec9c4d..d1fb51c50c4e5 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/ClusterSharingMapSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/ClusterSharingMapSpec.h @@ -18,6 +18,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" +#include "Framework/CCDBParamSpec.h" namespace o2 { @@ -39,6 +40,7 @@ o2::framework::DataProcessorSpec getClusterSharingMapSpec() inputs.emplace_back("trackTPC", "TPC", "TRACKS", 0, o2::framework::Lifetime::Timeframe); inputs.emplace_back("trackTPCClRefs", "TPC", "CLUSREFS", 0, o2::framework::Lifetime::Timeframe); inputs.emplace_back("clusTPC", o2::framework::ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}, o2::framework::Lifetime::Timeframe); + inputs.emplace_back("grpecs", "GLO", "GRPECS", 0, o2::framework::Lifetime::Condition, o2::framework::ccdbParamSpec("GLO/Config/GRPECS", true)); outputs.emplace_back("TPC", "CLSHAREDMAP", 0, o2::framework::Lifetime::Timeframe); return o2::framework::DataProcessorSpec{ diff --git a/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx b/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx index 7b8259aa70377..d0e5aa121b543 100644 --- a/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx +++ b/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx @@ -20,6 +20,7 @@ #include "DataFormatsTPC/TrackTPC.h" #include "GPUO2InterfaceRefit.h" #include "TPCWorkflow/ClusterSharingMapSpec.h" +#include "DataFormatsParameters/GRPECSObject.h" using namespace o2::framework; using namespace o2::tpc; @@ -27,10 +28,15 @@ using namespace o2::tpc; void ClusterSharingMapSpec::run(ProcessingContext& pc) { TStopwatch timer; - + static int nHBPerTF = 0; const auto tracksTPC = pc.inputs().get>("trackTPC"); const auto tracksTPCClRefs = pc.inputs().get>("trackTPCClRefs"); const auto& clustersTPC = getWorkflowTPCInput(pc); + if (pc.services().get().globalRunNumberChanged) { // new run is starting + auto grp = pc.inputs().get("grpecs"); + nHBPerTF = grp->getNHBFPerTF(); + LOGP(info, "Will use {} HB per TF from GRPECS", nHBPerTF); + } auto& bufVec = pc.outputs().make>(Output{o2::header::gDataOriginTPC, "CLSHAREDMAP", 0}, clustersTPC->clusterIndex.nClustersTotal); o2::gpu::GPUO2InterfaceRefit::fillSharedClustersMap(&clustersTPC->clusterIndex, tracksTPC, tracksTPCClRefs.data(), bufVec.data()); From 10c6b4fe1ac2091685da1e49a8f710a11d761420 Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Wed, 3 Apr 2024 14:48:46 +0200 Subject: [PATCH 0039/2997] [EMCAL-1116] Add check for maximum RMS in pedestal calib (#12958) - In order to not use unreasaonable data for the pedestal extraction, the RMS for each cell is compared against a Maximum. If the RMS is larger, the channel is set to 1023 which essentially masks the channel - The maximum value is configurable in the CalibrationParams Co-authored-by: jokonig --- .../include/EMCALCalibration/EMCALCalibExtractor.h | 14 +++++++++++--- .../include/EMCALCalibration/EMCALCalibParams.h | 3 +++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h index e9b59e8afa2dc..6ba8479534a8b 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h @@ -431,6 +431,9 @@ class EMCALCalibExtractor for (const auto& isLG : {false, true}) { for (unsigned short iCell = 0; iCell < maxChannels; ++iCell) { auto [mean, rms] = obj.getValue(iCell, isLG, isLEDMON); // get mean and rms for pedestals + if (rms > EMCALCalibParams::Instance().maxPedestalRMS) { + mean = mMaxPedestalVal; + } pedestalData.addPedestalValue(iCell, mean, isLG, isLEDMON); } } @@ -455,6 +458,10 @@ class EMCALCalibExtractor continue; for (unsigned short iCell = 0; iCell < maxChannels; ++iCell) { short mean = static_cast(obj->GetBinContent(iCell + 1)); + short rms = static_cast(obj->GetBinError(iCell + 1) / obj->GetBinEntries(iCell + 1)); + if (rms > EMCALCalibParams::Instance().maxPedestalRMS) { + mean = mMaxPedestalVal; + } pedestalData.addPedestalValue(iCell, mean, isLG, isLEDMON); } } @@ -481,9 +488,10 @@ class EMCALCalibExtractor std::array mBadCellFracSM; ///< Fraction of bad+dead channels per SM std::array, 20> mBadCellFracFEC; ///< Fraction of bad+dead channels per FEC - o2::emcal::Geometry* mGeometry = nullptr; ///< pointer to the emcal geometry class - static constexpr int mNcells = 17664; ///< Number of total cells of EMCal + DCal - static constexpr int mLEDMONs = 480; ///< Number of total LEDMONS of EMCal + DCal + o2::emcal::Geometry* mGeometry = nullptr; ///< pointer to the emcal geometry class + static constexpr int mNcells = 17664; ///< Number of total cells of EMCal + DCal + static constexpr int mLEDMONs = 480; ///< Number of total LEDMONS of EMCal + DCal + static constexpr short mMaxPedestalVal = 1023; ///< Maximum value for pedestals ClassDefNV(EMCALCalibExtractor, 1); }; diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h index 0e44e886d02f1..0e9e6a4614f18 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h @@ -86,6 +86,9 @@ struct EMCALCalibParams : public o2::conf::ConfigurableParamHelper Date: Wed, 3 Apr 2024 15:36:56 +0200 Subject: [PATCH 0040/2997] Add new workflow enabling DPL level record file creation for muon alignment (#12877) * Add new workflow enabling DPL level record file creation for muon alignment This is a proposition of DPL level task for creating MillePede2 record file for muon alignment. Some adaptations have been made in ForwardAlign/ especially to disable the internal record writer. * Fix for Formatting * Fix CI build error * Fix for CI build error * Fix and optimisation regarding comments * Small fix for cluster number selection * Remove unused cluster index * Formatting * Fix regarding comments * Using `Sporadic` for output lifetime * Using reference for record member * Adding configuration for tracking parameters * Modifying destructor of aligner to free memory for pointers initialised with `new` * Cleaning-up * Fixing for track improvement cut definition and remove unused stat check * Same fix of track improvement cut for alignment spec --- Detectors/ForwardAlign/CMakeLists.txt | 10 + .../include/ForwardAlign/MillePede2.h | 5 + .../ForwardAlign/MilleRecordWriterSpec.h | 33 ++ .../ForwardAlign/src/ForwardAlignLinkDef.h | 1 + Detectors/ForwardAlign/src/MillePede2.cxx | 44 ++- .../ForwardAlign/src/MilleRecordReader.cxx | 2 +- .../ForwardAlign/src/MilleRecordWriter.cxx | 5 +- .../src/MilleRecordWriterSpec.cxx | 42 ++ .../src/millerecord-writer-workflow.cxx | 41 ++ Detectors/MUON/MCH/Align/CMakeLists.txt | 14 +- .../Align/include/MCHAlign/AlignRecordSpec.h | 35 ++ .../MUON/MCH/Align/include/MCHAlign/Aligner.h | 25 +- .../MUON/MCH/Align/src/AlignRecordSpec.cxx | 365 ++++++++++++++++++ Detectors/MUON/MCH/Align/src/Aligner.cxx | 108 +++--- .../MUON/MCH/Align/src/AlignmentSpec.cxx | 76 +--- .../MCH/Align/src/align-record-workflow.cxx | 76 ++++ 16 files changed, 724 insertions(+), 158 deletions(-) create mode 100644 Detectors/ForwardAlign/include/ForwardAlign/MilleRecordWriterSpec.h create mode 100644 Detectors/ForwardAlign/src/MilleRecordWriterSpec.cxx create mode 100644 Detectors/ForwardAlign/src/millerecord-writer-workflow.cxx create mode 100644 Detectors/MUON/MCH/Align/include/MCHAlign/AlignRecordSpec.h create mode 100644 Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx create mode 100644 Detectors/MUON/MCH/Align/src/align-record-workflow.cxx diff --git a/Detectors/ForwardAlign/CMakeLists.txt b/Detectors/ForwardAlign/CMakeLists.txt index 48acb71e2c658..bb7d35444e4ff 100644 --- a/Detectors/ForwardAlign/CMakeLists.txt +++ b/Detectors/ForwardAlign/CMakeLists.txt @@ -21,6 +21,7 @@ o2_add_library(ForwardAlign src/SymBDMatrix.cxx src/SymMatrix.cxx src/VectorSparse.cxx + src/MilleRecordWriterSpec.cxx PUBLIC_LINK_LIBRARIES O2::CCDB O2::Steer ROOT::TreePlayer) @@ -37,4 +38,13 @@ o2_target_root_dictionary(ForwardAlign include/ForwardAlign/SymBDMatrix.h include/ForwardAlign/SymMatrix.h include/ForwardAlign/VectorSparse.h + include/ForwardAlign/MilleRecordWriterSpec.h LINKDEF src/ForwardAlignLinkDef.h) + + + +o2_add_executable( + millerecord-writer-workflow + SOURCES src/MilleRecordWriterSpec.cxx src/millerecord-writer-workflow.cxx + COMPONENT_NAME fwdalign + PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::ReconstructionDataFormats O2::SimulationDataFormat O2::ForwardAlign) diff --git a/Detectors/ForwardAlign/include/ForwardAlign/MillePede2.h b/Detectors/ForwardAlign/include/ForwardAlign/MillePede2.h index f3707aa64dabf..2c5bb8ef6dd8d 100644 --- a/Detectors/ForwardAlign/include/ForwardAlign/MillePede2.h +++ b/Detectors/ForwardAlign/include/ForwardAlign/MillePede2.h @@ -156,6 +156,7 @@ class MillePede2 fNGroupsSet = grID; } } + void ResetRecord() { fRecord->Reset(); } void SetNGloPar(const int n) { fNGloPar = n; } void SetNLocPar(const int n) { fNLocPar = n; } void SetNMaxIterations(const int n = 10) { fMaxIter = n; } @@ -285,6 +286,9 @@ class MillePede2 fIsLinear[id] = !v; } + /// \brief Disable record writer for DPL process + void DisableRecordWriter() { fDisableRecordWriter = true; } + protected: /// \brief read data record (if any) at entry recID void ReadRecordData(const long recID, const bool doPrint = false); @@ -360,6 +364,7 @@ class MillePede2 long fCurrRecConstrID; ///< ID of the current constraint record bool fLocFitAdd; ///< Add contribution of carrent track (and not eliminate it) bool fUseRecordWeight; ///< force or ignore the record weight + bool fDisableRecordWriter; ///< disable record writer for DPL process int fMinRecordLength; ///< ignore shorter records int fSelFirst; ///< event selection start int fSelLast; ///< event selection end diff --git a/Detectors/ForwardAlign/include/ForwardAlign/MilleRecordWriterSpec.h b/Detectors/ForwardAlign/include/ForwardAlign/MilleRecordWriterSpec.h new file mode 100644 index 0000000000000..b10ab502dace8 --- /dev/null +++ b/Detectors/ForwardAlign/include/ForwardAlign/MilleRecordWriterSpec.h @@ -0,0 +1,33 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MilleRecordWriterSpec.h +/// \brief Implementation of a data processor to write MillePede record in a root file +/// +/// \author Chi Zhang, CEA-Saclay, chi.zhang@cern.ch + +#ifndef ALICEO2_FWDALIGN_MILLERECORDWRITERSPEC_H +#define ALICEO2_FWDALIGN_MILLERECORDWRITERSPEC_H + +#include "Framework/DataProcessorSpec.h" + +namespace o2 +{ +namespace fwdalign +{ + +framework::DataProcessorSpec getMilleRecordWriterSpec(bool useMC, const char* specName = "fwdalign-millerecord-writer", + const char* fileName = "millerecords.root"); + +} // namespace fwdalign +} // namespace o2 + +#endif // ALICEO2_FWDALIGN_MILLERECORDWRITERSPEC_H \ No newline at end of file diff --git a/Detectors/ForwardAlign/src/ForwardAlignLinkDef.h b/Detectors/ForwardAlign/src/ForwardAlignLinkDef.h index cfc895a101f8b..eb447d28e7868 100644 --- a/Detectors/ForwardAlign/src/ForwardAlignLinkDef.h +++ b/Detectors/ForwardAlign/src/ForwardAlignLinkDef.h @@ -19,6 +19,7 @@ #pragma link C++ class o2::fwdalign::MatrixSq + ; #pragma link C++ class o2::fwdalign::MillePede2 + ; #pragma link C++ class o2::fwdalign::MillePedeRecord + ; +#pragma link C++ class std::vector < o2::fwdalign::MillePedeRecord> + ; #pragma link C++ class o2::fwdalign::MilleRecordReader + ; #pragma link C++ class o2::fwdalign::MilleRecordWriter + ; #pragma link C++ class o2::fwdalign::MinResSolve + ; diff --git a/Detectors/ForwardAlign/src/MillePede2.cxx b/Detectors/ForwardAlign/src/MillePede2.cxx index d66786d658c5c..5ad475d893271 100644 --- a/Detectors/ForwardAlign/src/MillePede2.cxx +++ b/Detectors/ForwardAlign/src/MillePede2.cxx @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// @file MillePede2.cxx - +#include #include "ForwardAlign/MillePede2.h" #include "Framework/Logger.h" #include @@ -147,7 +147,8 @@ MillePede2::MillePede2(const MillePede2& src) fRecordWriter(nullptr), fConstraintsRecWriter(nullptr), fRecordReader(nullptr), - fConstraintsRecReader(nullptr) + fConstraintsRecReader(nullptr), + fDisableRecordWriter(false) { fWghScl[0] = src.fWghScl[0]; fWghScl[1] = src.fWghScl[1]; @@ -314,16 +315,17 @@ void MillePede2::EndChi2Storage() void MillePede2::SetLocalEquation(std::vector& dergb, std::vector& derlc, const double lMeas, const double lSigma) { - if (!fRecordWriter) { - LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: null pointer to record writer"; - return; - } - if (!fRecordWriter->isInitOk()) { - LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: unintialised record writer"; - return; + if (!fDisableRecordWriter) { + if (!fRecordWriter) { + LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: null pointer to record writer"; + return; + } + if (!fRecordWriter->isInitOk()) { + LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: unintialised record writer"; + return; + } + SetRecord(fRecordWriter->getRecord()); } - SetRecord(fRecordWriter->getRecord()); - // write data of single measurement if (lSigma <= 0.0) { // If parameter is fixed, then no equation for (int i = fNLocPar; i--;) { @@ -336,7 +338,6 @@ void MillePede2::SetLocalEquation(std::vector& dergb, std::vectorAddResidual(lMeas); - // Retrieve local param interesting indices for (int i = 0; i < fNLocPar; i++) { if (!IsZero(derlc[i])) { @@ -364,16 +365,17 @@ void MillePede2::SetLocalEquation(std::vector& indgb, std::vector& std::vector& derlc, const int nlc, const double lMeas, const double lSigma) { - if (!fRecordWriter) { - LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: null pointer to record writer"; - return; - } - if (!fRecordWriter->isInitOk()) { - LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: unintialised record writer"; - return; + if (!fDisableRecordWriter) { + if (!fRecordWriter) { + LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: null pointer to record writer"; + return; + } + if (!fRecordWriter->isInitOk()) { + LOG(fatal) << "MillePede2::SetLocalEquation() - aborted: unintialised record writer"; + return; + } + SetRecord(fRecordWriter->getRecord()); } - SetRecord(fRecordWriter->getRecord()); - if (lSigma <= 0.0) { // If parameter is fixed, then no equation for (int i = nlc; i--;) { derlc[i] = 0.0; diff --git a/Detectors/ForwardAlign/src/MilleRecordReader.cxx b/Detectors/ForwardAlign/src/MilleRecordReader.cxx index a169ba77b6e0d..927e7972c222b 100644 --- a/Detectors/ForwardAlign/src/MilleRecordReader.cxx +++ b/Detectors/ForwardAlign/src/MilleRecordReader.cxx @@ -25,7 +25,7 @@ MilleRecordReader::MilleRecordReader() mIsSuccessfulInit(false), mIsConstraintsRec(false), mIsReadEntryOk(false), - mDataTreeName("milleRecords"), + mDataTreeName("o2sim"), mDataBranchName("data"), mRecord(nullptr), mCurrentDataID(-1), diff --git a/Detectors/ForwardAlign/src/MilleRecordWriter.cxx b/Detectors/ForwardAlign/src/MilleRecordWriter.cxx index 8dbe31e91744c..e36c47562c81e 100644 --- a/Detectors/ForwardAlign/src/MilleRecordWriter.cxx +++ b/Detectors/ForwardAlign/src/MilleRecordWriter.cxx @@ -29,8 +29,8 @@ MilleRecordWriter::MilleRecordWriter() mIsSuccessfulInit(false), mIsConstraintsRec(false), mNEntriesAutoSave(10000), - mDataFileName("mft_mille_records.root"), - mDataTreeName("milleRecords"), + mDataFileName("millerecords.root"), + mDataTreeName("o2sim"), mDataBranchName("data"), mRecord(nullptr), mCurrentDataID(-1) @@ -135,6 +135,7 @@ void MilleRecordWriter::terminate() mDataTree->Write(); LOG(info) << "MilleRecordWriter::terminate() - wrote tree " << mDataTreeName.Data(); + mDataFile->Close(); } } diff --git a/Detectors/ForwardAlign/src/MilleRecordWriterSpec.cxx b/Detectors/ForwardAlign/src/MilleRecordWriterSpec.cxx new file mode 100644 index 0000000000000..e3fe8c12a9ad0 --- /dev/null +++ b/Detectors/ForwardAlign/src/MilleRecordWriterSpec.cxx @@ -0,0 +1,42 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MilleRecordWriterSpec.cxx +/// \brief Implementation of a data processor to write MillePede record in a root file +/// +/// \author Chi Zhang, CEA-Saclay, chi.zhang@cern.ch + +#include "ForwardAlign/MilleRecordWriterSpec.h" + +#include +#include "DPLUtils/MakeRootTreeWriterSpec.h" +#include "ForwardAlign/MillePedeRecord.h" + +namespace o2 +{ +namespace fwdalign +{ + +using namespace o2::framework; + +template +using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition; + +DataProcessorSpec getMilleRecordWriterSpec(bool useMC, const char* specName, const char* fileName) +{ + return MakeRootTreeWriterSpec(specName, + fileName, + MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Tree MillePede records for MCH-MID tracks"}, + BranchDefinition{InputSpec{"data", "MUON", "RECORD_MCHMID", Lifetime::Sporadic}, "data"})(); +} + +} // namespace fwdalign +} // namespace o2 \ No newline at end of file diff --git a/Detectors/ForwardAlign/src/millerecord-writer-workflow.cxx b/Detectors/ForwardAlign/src/millerecord-writer-workflow.cxx new file mode 100644 index 0000000000000..9144ef1cb1025 --- /dev/null +++ b/Detectors/ForwardAlign/src/millerecord-writer-workflow.cxx @@ -0,0 +1,41 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file millerecord-writer-workflow.cxx +/// \brief Implementation of a DPL device to run the MillePede record writer +/// +/// \author Chi Zhang, CEA-Saclay, chi.zhang@cern.ch + +#include "ForwardAlign/MilleRecordWriterSpec.h" +#include "Framework/CompletionPolicyHelpers.h" + +using namespace o2::framework; + +void customize(std::vector& policies) +{ + // ordered policies for the writers + policies.push_back(CompletionPolicyHelpers::consumeWhenAllOrdered(".*(?:FWDALIGN|fwdalign).*[W,w]riter.*")); +} + +void customize(std::vector& workflowOptions) +{ + // option allowing to set parameters + workflowOptions.emplace_back("disable-mc", VariantType::Bool, false, + ConfigParamSpec::HelpString{"disable MC propagation even if available"}); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(const ConfigContext& configcontext) +{ + auto useMC = !configcontext.options().get("disable-mc"); + return WorkflowSpec{o2::fwdalign::getMilleRecordWriterSpec(useMC)}; +} \ No newline at end of file diff --git a/Detectors/MUON/MCH/Align/CMakeLists.txt b/Detectors/MUON/MCH/Align/CMakeLists.txt index 4f9c3cd7f35b8..15ab93353eaa2 100644 --- a/Detectors/MUON/MCH/Align/CMakeLists.txt +++ b/Detectors/MUON/MCH/Align/CMakeLists.txt @@ -13,16 +13,20 @@ o2_add_library(MCHAlign SOURCES src/Aligner.cxx src/AlignmentSpec.cxx + src/AlignRecordSpec.cxx PUBLIC_LINK_LIBRARIES O2::MathUtils O2::CCDB O2::DataFormatsMCH O2::ForwardAlign O2::MCHTracking + O2::GlobalTracking + O2::GlobalTrackingWorkflow O2::MCHGeometryTransformer O2::CommonUtils O2::DataFormatsParameters O2::DetectorsBase + O2::DetectorsRaw O2::Framework O2::DetectorsRaw O2::Headers @@ -32,7 +36,8 @@ o2_add_library(MCHAlign o2_target_root_dictionary(MCHAlign HEADERS include/MCHAlign/Aligner.h - include/MCHAlign/AlignmentSpec.h) + include/MCHAlign/AlignmentSpec.h + include/MCHAlign/AlignRecordSpec.h) o2_add_executable( alignment-workflow @@ -43,5 +48,12 @@ o2_add_executable( O2::MCHAlign Boost::program_options) +o2_add_executable( + align-record-workflow + SOURCES src/align-record-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES + O2::MCHAlign) + diff --git a/Detectors/MUON/MCH/Align/include/MCHAlign/AlignRecordSpec.h b/Detectors/MUON/MCH/Align/include/MCHAlign/AlignRecordSpec.h new file mode 100644 index 0000000000000..7d4415fed040f --- /dev/null +++ b/Detectors/MUON/MCH/Align/include/MCHAlign/AlignRecordSpec.h @@ -0,0 +1,35 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file AlignRecordSpec.h +/// \brief Definition of the process for creating alignment record during reconstruction +/// +/// \author Chi ZHANG, CEA-Saclay, chi.zhang@cern.ch + +#ifndef O2_MCH_ALIGNRECORD_H_ +#define O2_MCH_ALIGNRECORD_H_ + +#include "Framework/DataProcessorSpec.h" +#include "ReconstructionDataFormats/GlobalTrackID.h" + +using GID = o2::dataformats::GlobalTrackID; + +namespace o2 +{ +namespace mch +{ + +o2::framework::DataProcessorSpec getAlignRecordSpec(bool useMC, bool disableCCDB = false); + +} // end namespace mch +} // end namespace o2 + +#endif // O2_MCH_ALIGNRECORD_H_ \ No newline at end of file diff --git a/Detectors/MUON/MCH/Align/include/MCHAlign/Aligner.h b/Detectors/MUON/MCH/Align/include/MCHAlign/Aligner.h index fe18c337cbe9a..450c860dba7d9 100644 --- a/Detectors/MUON/MCH/Align/include/MCHAlign/Aligner.h +++ b/Detectors/MUON/MCH/Align/include/MCHAlign/Aligner.h @@ -107,13 +107,13 @@ class Aligner : public TObject public: Aligner(); - ~Aligner() = default; + ~Aligner(); // initialize - void init(TString DataRecFName = "recDataFile.root", TString ConsRecFName = "recConsFile.root"); + void init(TString DataRecFName = "millerecords.root", TString ConsRecFName = "milleconstraints.root"); // terminate - void terminate(void); + void terminate(); // array dimendions enum { @@ -184,9 +184,7 @@ class Aligner : public TObject AllSides = SideTop | SideBottom | SideLeft | SideRight }; - o2::fwdalign::MillePedeRecord* ProcessTrack(Track& track, const o2::mch::geo::TransformationCreator& transformation, Bool_t doAlignment, Double_t weight = 1); - - void ProcessTrack(o2::fwdalign::MillePedeRecord*); + void ProcessTrack(Track& track, const o2::mch::geo::TransformationCreator& transformation, Bool_t doAlignment, Double_t weight = 1); //@name modifiers //@{ @@ -302,6 +300,8 @@ class Aligner : public TObject /// get error on a given parameter double GetParError(int iPar) const; + o2::fwdalign::MillePedeRecord& GetRecord() { return fTrackRecord; } + void ReAlign(std::vector& params, std::vector& misAlignments); void SetAlignmentResolution(const TClonesArray* misAlignArray, int chId, double chResX, double chResY, double deResX, double deResY); @@ -316,6 +316,11 @@ class Aligner : public TObject mRead = true; } + void DisableRecordWriter() + { + fDisableRecordWriter = true; + } + private: /// Not implemented Aligner(const Aligner& right); @@ -396,9 +401,6 @@ class Aligner : public TObject /// Detector independent alignment class o2::fwdalign::MillePede2* fMillepede; // AliMillePede2 implementation - /// MCH cluster class - o2::mch::Cluster* fCluster; - /// Number of standard deviations for chi2 cut int fNStdDev; @@ -452,9 +454,8 @@ class Aligner : public TObject /// preform evaluation bool fDoEvaluation; - /// original local track params - LocalTrackParam* fTrackParamOrig; - LocalTrackParam* fTrackParamNew; + /// disable record saving + bool fDisableRecordWriter; LocalTrackClusterResidual* fTrkClRes; diff --git a/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx b/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx new file mode 100644 index 0000000000000..e31968ae3de8d --- /dev/null +++ b/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx @@ -0,0 +1,365 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#include + +#include "MCHAlign/AlignRecordSpec.h" + +#include "DataFormatsMCH/TrackMCH.h" +#include "DataFormatsMCH/Cluster.h" +#include "DataFormatsParameters/GRPECSObject.h" +#include "MathUtils/Utils.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/GRPGeomHelper.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/DataTypes.h" +#include "Framework/TableBuilder.h" +#include "Framework/CCDBParamSpec.h" +#include "Framework/CallbackService.h" +#include "Framework/Task.h" +#include "FT0Base/Geometry.h" +#include "GlobalTracking/MatchTOF.h" +#include "ReconstructionDataFormats/Cascade.h" +#include "GlobalTracking/MatchGlobalFwd.h" +#include "MCHTracking/TrackExtrap.h" +#include "MCHTracking/TrackFitter.h" +#include "MCHTracking/TrackParam.h" +#include "MCHAlign/Aligner.h" +#include "MCHBase/TrackerParam.h" +#include "ForwardAlign/MillePedeRecord.h" +#include "DetectorsCommonDataFormats/AlignParam.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsCommonDataFormats/DetectorNameConf.h" +#include "MCHGeometryTransformer/Transformations.h" +#include "ReconstructionDataFormats/GlobalFwdTrack.h" +#include "ReconstructionDataFormats/GlobalTrackID.h" +#include "ReconstructionDataFormats/PrimaryVertex.h" +#include "ReconstructionDataFormats/StrangeTrack.h" +#include "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "ReconstructionDataFormats/TrackMCHMID.h" + +#include +#include + +const int fgNCh = 10; +const int fgNDetElemCh[fgNCh] = {4, 4, 4, 4, 18, 18, 26, 26, 26, 26}; +const int fgSNDetElemCh[fgNCh + 1] = {0, 4, 8, 12, 16, 34, 52, 78, 104, 130, 156}; + +namespace o2 +{ +namespace mch +{ + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using namespace std; +using std::cout; +using std::endl; +using DataRequest = o2::globaltracking::DataRequest; +using GID = o2::dataformats::GlobalTrackID; + +class AlignRecordTask +{ + public: + //_________________________________________________________________________________________________ + AlignRecordTask(std::shared_ptr dataRequest, std::shared_ptr ccdbRequest, bool useMC = true) + : mDataRequest(dataRequest), mCCDBRequest(ccdbRequest), mUseMC(useMC) {} + + //_________________________________________________________________________________________________ + void init(framework::InitContext& ic) + { + + LOG(info) << "initializing align record maker"; + mTrackCount = 0; + mTrackMatched = 0; + if (mCCDBRequest) { + base::GRPGeomHelper::instance().setRequest(mCCDBRequest); + } else { + auto grpFile = ic.options().get("grp-file"); + if (std::filesystem::exists(grpFile)) { + const auto grp = parameters::GRPObject::loadFrom(grpFile); + base::Propagator::initFieldFromGRP(grp); + TrackExtrap::setField(); + TrackExtrap::useExtrapV2(); + mAlign.SetBFieldOn(mch::TrackExtrap::isFieldON()); + } else { + LOG(fatal) << "GRP file doesn't exist!"; + } + } + + // Configuration for alignment object + mAlign.SetDoEvaluation(false); + mAlign.DisableRecordWriter(); + mAlign.SetAllowedVariation(0, 2.0); + mAlign.SetAllowedVariation(1, 0.3); + mAlign.SetAllowedVariation(2, 0.002); + mAlign.SetAllowedVariation(3, 2.0); + + // Configuration for track fitter + const auto& trackerParam = TrackerParam::Instance(); + trackFitter.setBendingVertexDispersion(trackerParam.bendingVertexDispersion); + trackFitter.setChamberResolution(trackerParam.chamberResolutionX, trackerParam.chamberResolutionY); + trackFitter.smoothTracks(true); + trackFitter.useChamberResolution(); + mImproveCutChi2 = 2. * trackerParam.sigmaCutForImprovement * trackerParam.sigmaCutForImprovement; + + // Configuration for chamber fixing + auto chambers = ic.options().get("fix-chamber"); + for (int i = 0; i < chambers.length(); ++i) { + if (chambers[i] == ',') { + continue; + } + int chamber = chambers[i] - '0'; + LOG(info) << Form("%s%d", "Fixing chamber: ", chamber); + mAlign.FixChamber(chamber); + } + + // Init for output saving + auto OutputRecFileName = ic.options().get("output-record-data"); + auto OutputConsFileName = ic.options().get("output-record-constraint"); + mAlign.init(OutputRecFileName, OutputConsFileName); + + ic.services().get().set([this]() { + LOG(info) << "Saving records into ROOT file"; + LOG(info) << "Nb of records to be saved: " << mTrackCount; + LOG(info) << "Nb of matched MCH-MID tracks: " << mTrackMatched; + mAlign.terminate(); + }); + } + + //_________________________________________________________________________________________________ + void finaliseCCDB(framework::ConcreteDataMatcher& matcher, void* obj) + { + /// finalize the track extrapolation setting + if (mCCDBRequest && base::GRPGeomHelper::instance().finaliseCCDB(matcher, obj)) { + if (matcher == framework::ConcreteDataMatcher("GLO", "GRPMAGFIELD", 0)) { + TrackExtrap::setField(); + TrackExtrap::useExtrapV2(); + mAlign.SetBFieldOn(mch::TrackExtrap::isFieldON()); + } + + if (matcher == framework::ConcreteDataMatcher("GLO", "GEOMALIGN", 0)) { + LOG(info) << "Loading reference geometry from CCDB"; + transformation = geo::transformationFromTGeoManager(*gGeoManager); + for (int i = 0; i < 156; i++) { + int iDEN = GetDetElemId(i); + transform[iDEN] = transformation(iDEN); + } + } + } + } + + //_________________________________________________________________________________________________ + void run(framework::ProcessingContext& pc) + { + if (mCCDBRequest) { + base::GRPGeomHelper::instance().checkUpdates(pc); + } + + o2::globaltracking::RecoContainer recoData; + recoData.collectData(pc, *mDataRequest.get()); + + const auto& mchTracks = recoData.getMCHTracks(); + const auto& mchmidMatches = recoData.getMCHMIDMatches(); + const auto& mchClusters = recoData.getMCHTrackClusters(); + mTrackMatched += mchmidMatches.size(); + + for (auto const& mchmidMatch : mchmidMatches) { + + int mchTrackID = mchmidMatch.getMCHRef().getIndex(); + const auto& mchTrack = mchTracks[mchTrackID]; + int first = mchTrack.getFirstClusterIdx(); + int last = mchTrack.getLastClusterIdx(); + int Ncluster = last - first + 1; + + if (Ncluster <= 9) { + continue; + } + + mch::Track convertedTrack; + + for (int i = first; i <= last; i++) { + const auto& cluster = mchClusters[i]; + convertedTrack.createParamAtCluster(cluster); + } + + // Erase removable track + if (!RemoveTrack(convertedTrack)) { + mAlign.ProcessTrack(convertedTrack, transformation, false, weightRecord); + mTrackCount += 1; + pc.outputs().snapshot(Output{"MUON", "RECORD_MCHMID", 0}, mAlign.GetRecord()); + } + } + } + + private: + //_________________________________________________________________________________________________ + bool RemoveTrack(mch::Track& track) + { + bool removeTrack = false; + + try { + trackFitter.fit(track, false); + } catch (exception const& e) { + removeTrack = true; + return removeTrack; + } + + auto itStartingParam = std::prev(track.rend()); + + while (true) { + try { + trackFitter.fit(track, true, false, (itStartingParam == track.rbegin()) ? nullptr : &itStartingParam); + } catch (exception const&) { + removeTrack = true; + break; + } + + double worstLocalChi2 = -1.0; + + track.tagRemovableClusters(0x1F, false); + auto itWorstParam = track.end(); + + for (auto itParam = track.begin(); itParam != track.end(); ++itParam) { + if (itParam->getLocalChi2() > worstLocalChi2) { + worstLocalChi2 = itParam->getLocalChi2(); + itWorstParam = itParam; + } + } + + if (worstLocalChi2 < mImproveCutChi2) { + break; + } + + if (!itWorstParam->isRemovable()) { + removeTrack = true; + track.removable(); + break; + } + + auto itNextParam = track.removeParamAtCluster(itWorstParam); + auto itNextToNextParam = (itNextParam == track.end()) ? itNextParam : std::next(itNextParam); + itStartingParam = track.rbegin(); + + if (track.getNClusters() < 10) { + removeTrack = true; + break; + } else { + while (itNextToNextParam != track.end()) { + if (itNextToNextParam->getClusterPtr()->getChamberId() != itNextParam->getClusterPtr()->getChamberId()) { + itStartingParam = std::make_reverse_iterator(++itNextParam); + break; + } + ++itNextToNextParam; + } + } + } + + if (!removeTrack) { + for (auto& param : track) { + param.setParameters(param.getSmoothParameters()); + param.setCovariances(param.getSmoothCovariances()); + } + } + + return removeTrack; + } + + //_________________________________________________________________________________________________ + Int_t GetDetElemId(Int_t iDetElemNumber) + { + // make sure detector number is valid + if (!(iDetElemNumber >= fgSNDetElemCh[0] && + iDetElemNumber < fgSNDetElemCh[fgNCh])) { + LOG(fatal) << "Invalid detector element number: " << iDetElemNumber; + } + /// get det element number from ID + // get chamber and element number in chamber + int iCh = 0; + int iDet = 0; + for (int i = 1; i <= fgNCh; i++) { + if (iDetElemNumber < fgSNDetElemCh[i]) { + iCh = i; + iDet = iDetElemNumber - fgSNDetElemCh[i - 1]; + break; + } + } + + // make sure detector index is valid + if (!(iCh > 0 && iCh <= fgNCh && iDet < fgNDetElemCh[iCh - 1])) { + LOG(fatal) << "Invalid detector element id: " << 100 * iCh + iDet; + } + + // add number of detectors up to this chamber + return 100 * iCh + iDet; + } + + std::shared_ptr mCCDBRequest; ///< pointer to the CCDB requests + std::shared_ptr mDataRequest; + GID::mask_t mInputSources; + bool mUseMC = true; + parameters::GRPMagField* grpmag; + TGeoManager* geo; + + mch::TrackFitter trackFitter; + double mImproveCutChi2{}; + int mTrackCount{}; + int mTrackMatched{}; + mch::Aligner mAlign{}; + Double_t weightRecord{1.0}; + std::vector mRecords; + + map transform; + mch::geo::TransformationCreator transformation; +}; + +//_________________________________________________________________________________________________ +o2::framework::DataProcessorSpec getAlignRecordSpec(bool useMC, bool disableCCDB) +{ + auto dataRequest = std::make_shared(); + o2::dataformats::GlobalTrackID::mask_t src = o2::dataformats::GlobalTrackID::getSourcesMask("MCH-MID"); + dataRequest->requestMCHClusters(false); + dataRequest->requestTracks(src, useMC); + + vector outputSpecs{}; + auto ccdbRequest = disableCCDB ? nullptr : std::make_shared(false, // orbitResetTime + false, // GRPECS=true + false, // GRPLHCIF + true, // GRPMagField + false, // askMatLUT + base::GRPGeomRequest::Aligned, // geometry + dataRequest->inputs, + true); // query only once all objects except mag.field + + outputSpecs.emplace_back("MUON", "RECORD_MCHMID", 0, Lifetime::Sporadic); + + return DataProcessorSpec{ + "mch-align-record", + dataRequest->inputs, + outputSpecs, + AlgorithmSpec{adaptFromTask(dataRequest, ccdbRequest, useMC)}, + Options{{"geo-file", VariantType::String, o2::base::NameConf::getAlignedGeomFileName(), {"Name of the reference geometry file"}}, + {"grp-file", VariantType::String, o2::base::NameConf::getGRPFileName(), {"Name of the grp file"}}, + {"fix-chamber", VariantType::String, "", {"Chamber fixing, ex 1,2,3"}}, + {"output-record-data", VariantType::String, "recDataFile.root", {"Option for name of output record file for data"}}, + {"output-record-constraint", VariantType::String, "recConsFile.root", {"Option for name of output record file for constraint"}}}}; +} + +} // namespace mch +} // namespace o2 \ No newline at end of file diff --git a/Detectors/MUON/MCH/Align/src/Aligner.cxx b/Detectors/MUON/MCH/Align/src/Aligner.cxx index 39a00cdd893d9..71bafad5b9ff3 100644 --- a/Detectors/MUON/MCH/Align/src/Aligner.cxx +++ b/Detectors/MUON/MCH/Align/src/Aligner.cxx @@ -29,6 +29,7 @@ #include "ForwardAlign/MillePedeRecord.h" #include "Framework/Logger.h" #include "MCHAlign/Aligner.h" +#include "MathUtils/Cartesian.h" #include "MCHTracking/Track.h" #include "MCHTracking/TrackParam.h" #include "MCHGeometryTransformer/Transformations.h" @@ -131,8 +132,7 @@ Aligner::Aligner() fStartFac(65536), fResCutInitial(1000), fResCut(100), - fMillepede(nullptr), // to be modified - fCluster(nullptr), + fMillepede(nullptr), fNStdDev(3), fDetElemNumber(0), fGlobalParameterStatus(std::vector(fNGlobal)), @@ -147,11 +147,9 @@ Aligner::Aligner() mWithConstraintsRecReader(false), mConstraintsRecReader(nullptr), fTransformCreator(), - // fGeoCombiTransInverse(), fDoEvaluation(false), + fDisableRecordWriter(false), mRead(false), - fTrackParamOrig(nullptr), - fTrackParamNew(nullptr), fTrkClRes(nullptr), fTFile(nullptr), fTTree(nullptr) @@ -185,6 +183,14 @@ Aligner::Aligner() } } +//________________________________________________________________________ +Aligner::~Aligner() +{ + delete mRecordWriter; + delete mRecordReader; + delete fMillepede; +} + //_____________________________________________________________________ void Aligner::init(TString DataRecFName, TString ConsRecFName) { @@ -200,15 +206,18 @@ void Aligner::init(TString DataRecFName, TString ConsRecFName) } if (!mRead) { - - mRecordWriter->setCyclicAutoSave(mNEntriesAutoSave); - mRecordWriter->setDataFileName(DataRecFName); - fMillepede->SetRecordWriter(mRecordWriter); - - if (mWithConstraintsRecWriter) { - mConstraintsRecWriter->setCyclicAutoSave(mNEntriesAutoSave); - mConstraintsRecWriter->setDataFileName(ConsRecFName); - fMillepede->SetConstraintsRecWriter(mConstraintsRecWriter); + if (!fDisableRecordWriter) { + mRecordWriter->setCyclicAutoSave(mNEntriesAutoSave); + mRecordWriter->setDataFileName(DataRecFName); + fMillepede->SetRecordWriter(mRecordWriter); + + if (mWithConstraintsRecWriter) { + mConstraintsRecWriter->setCyclicAutoSave(mNEntriesAutoSave); + mConstraintsRecWriter->setDataFileName(ConsRecFName); + fMillepede->SetConstraintsRecWriter(mConstraintsRecWriter); + } + } else { + fMillepede->SetRecord(&fTrackRecord); } } else { @@ -283,7 +292,11 @@ void Aligner::init(TString DataRecFName, TString ConsRecFName) fMillepede->InitMille(fNGlobal, fNLocal, fNStdDev, fResCut, fResCutInitial, fGlobalParameterStatus); if (!mRead) { - mRecordWriter->init(); + if (!fDisableRecordWriter) { + mRecordWriter->init(); + } else { + fMillepede->DisableRecordWriter(); + } } fInitialized = true; @@ -315,12 +328,6 @@ void Aligner::init(TString DataRecFName, TString ConsRecFName) const int kSplitlevel = 98; const int kBufsize = 32000; - // fTrackParamOrig = new LocalTrackParam(); - // fTTree->Branch("fTrackParamOrig", "LocalTrackParam", &fTrackParamOrig, kBufsize, kSplitlevel); - - // fTrackParamNew = new LocalTrackParam(); - // fTTree->Branch("fTrackParamNew", "LocalTrackParam", &fTrackParamNew, kBufsize, kSplitlevel); - fTrkClRes = new o2::mch::LocalTrackClusterResidual(); fTTree->Branch("fClDetElem", &(fTrkClRes->fClDetElem), "fClDetElem/I"); fTTree->Branch("fClDetElemNumber", &(fTrkClRes->fClDetElemNumber), "fClDetElemNumber/I"); @@ -351,24 +358,24 @@ void Aligner::init(TString DataRecFName, TString ConsRecFName) //_____________________________________________________ void Aligner::terminate() { - mRecordWriter->terminate(); fInitialized = kFALSE; LOG(info) << "Closing Evaluation TFile"; - if (fTFile && fTTree) { - fTFile->cd(); - fTTree->Write(); - fTFile->Close(); + if (fDoEvaluation) { + if (fTFile && fTTree) { + fTFile->cd(); + fTTree->Write(); + fTFile->Close(); + } } } //_____________________________________________________ -o2::fwdalign::MillePedeRecord* Aligner::ProcessTrack(Track& track, const o2::mch::geo::TransformationCreator& transformation, bool doAlignment, double weight) +void Aligner::ProcessTrack(Track& track, const o2::mch::geo::TransformationCreator& transformation, bool doAlignment, double weight) { /// process track for alignment minimization - // reset track records - fTrackRecord.Reset(); + if (fMillepede->GetRecord()) { fMillepede->GetRecord()->Reset(); } @@ -436,8 +443,7 @@ o2::fwdalign::MillePedeRecord* Aligner::ProcessTrack(Track& track, const o2::mch // 'inverse' (GlobalToLocal) rotation matrix // const double* r(fGeoCombiTransInverse.GetRotationMatrix()); - - auto trans = transformation(cluster->getDEId()); + o2::math_utils::Transform3D trans = transformation(cluster->getDEId()); // LOG(info) << Form("cluster ID: %i", cluster->getDEId()); TMatrixD transMat(3, 4); trans.GetTransformMatrix(transMat); @@ -455,7 +461,6 @@ o2::fwdalign::MillePedeRecord* Aligner::ProcessTrack(Track& track, const o2::mch r[9] = transMat(0, 3); r[10] = transMat(1, 3); r[11] = transMat(2, 3); - // calculate measurements if (fBFieldOn) { @@ -529,42 +534,17 @@ o2::fwdalign::MillePedeRecord* Aligner::ProcessTrack(Track& track, const o2::mch } // copy track record - mRecordWriter->setRecordRun(fRunNumber); - mRecordWriter->setRecordWeight(weight); - fTrackRecord = *fMillepede->GetRecord(); + if (!fDisableRecordWriter) { + mRecordWriter->setRecordRun(fRunNumber); + mRecordWriter->setRecordWeight(weight); + } // save record data if (doAlignment) { - mRecordWriter->fillRecordTree(); - } - - // return record - return &fTrackRecord; -} - -//______________________________________________________________________________ -void Aligner::ProcessTrack(o2::fwdalign::MillePedeRecord* trackRecord) -{ - LOG(fatal) << __PRETTY_FUNCTION__ << " is disabled"; - - /// process track record - if (!trackRecord) { - return; - } - - // // make sure record storage is initialized - if (!fMillepede->GetRecord()) { - mRecordWriter->init(); + if (!fDisableRecordWriter) { + mRecordWriter->fillRecordTree(); + } } - // // copy content - *fMillepede->GetRecord() = *trackRecord; - - // save record - mRecordWriter->fillRecordTree(); - // write to local file - // mRecordWriter->terminate(); - - return; } //_____________________________________________________________________ diff --git a/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx b/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx index 2d50a8235bc0c..6a3ed06a6b403 100644 --- a/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx +++ b/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx @@ -74,6 +74,7 @@ #include "MCHTracking/TrackExtrap.h" #include "MCHTracking/TrackParam.h" #include "MCHTracking/TrackFitter.h" +#include "MCHBase/TrackerParam.h" #include "ReconstructionDataFormats/TrackMCHMID.h" namespace o2 @@ -88,15 +89,6 @@ using namespace o2; class AlignmentTask { public: - double Reso_X{0.4}; - double Reso_Y{0.4}; - double ImproveCut{6.0}; - - int tracksGood = 0; - int tracksGoodwithoutFit = 0; - int tracksAll = 0; - int trackMCHMID = 0; - const int fgNDetElemCh[10] = {4, 4, 4, 4, 18, 18, 26, 26, 26, 26}; const int fgSNDetElemCh[11] = {0, 4, 8, 12, 16, 34, 52, 78, 104, 130, 156}; const int fgNDetElemHalfCh[20] = {2, 2, 2, 2, 2, 2, 2, 2, 9, @@ -170,22 +162,6 @@ class AlignmentTask LOG(info) << "Re-alignment mode"; } - auto param_config = ic.options().get("fitter-config"); - if (param_config == "PbPb") { - Reso_X = 0.2; - Reso_Y = 0.2; - ImproveCut = 4.0; - LOG(info) << "Using PbPb parameter set for TrackFitter"; - } else if (param_config == "pp") { - Reso_X = 0.4; - Reso_Y = 0.4; - ImproveCut = 6.0; - LOG(info) << "Using pp parameter set for TrackFitter"; - } else { - LOG(fatal) << "Please enter a correct parameter configuration option"; - exit(-1); - } - if (mCCDBRequest) { LOG(info) << "Loading magnetic field and reference geometry from CCDB"; base::GRPGeomHelper::instance().setRequest(mCCDBRequest); @@ -229,17 +205,22 @@ class AlignmentTask } } - trackFitter.smoothTracks(true); - trackFitter.setChamberResolution(Reso_X, Reso_Y); - trackFitter.useChamberResolution(); - - mAlign.SetDoEvaluation(true); + auto doEvaluation = ic.options().get("do-evaluation"); + mAlign.SetDoEvaluation(doEvaluation); // Variation range for parameters mAlign.SetAllowedVariation(0, 2.0); mAlign.SetAllowedVariation(1, 0.3); mAlign.SetAllowedVariation(2, 0.002); mAlign.SetAllowedVariation(3, 2.0); + // Configuration for track fitter + const auto& trackerParam = TrackerParam::Instance(); + trackFitter.setBendingVertexDispersion(trackerParam.bendingVertexDispersion); + trackFitter.setChamberResolution(trackerParam.chamberResolutionX, trackerParam.chamberResolutionY); + trackFitter.smoothTracks(true); + trackFitter.useChamberResolution(); + mImproveCutChi2 = 2. * trackerParam.sigmaCutForImprovement * trackerParam.sigmaCutForImprovement; + // Fix chambers auto chambers = ic.options().get("fix-chamber"); for (int i = 0; i < chambers.length(); ++i) { @@ -298,12 +279,10 @@ class AlignmentTask for (int iMCHTrack = mchROF.getFirstIdx(); iMCHTrack <= mchROF.getLastIdx(); ++iMCHTrack) { - tracksAll += 1; // MCH-MID matching if (!FindMuon(iMCHTrack, muonTracks)) { continue; } - trackMCHMID += 1; auto mchTrack = mchTracks.at(iMCHTrack); int id_track = iMCHTrack; @@ -313,21 +292,17 @@ class AlignmentTask if (nb_clusters <= 9) { continue; } - tracksGoodwithoutFit += 1; // Format conversion from TrackMCH to Track(MCH internal use) mch::Track convertedTrack = MCHFormatConvert(mchTrack, mchClusters, doReAlign); // Erase removable track - if (RemoveTrack(convertedTrack, ImproveCut)) { + if (RemoveTrack(convertedTrack)) { continue; - } else { - tracksGood += 1; } // Track processing, saving residuals - o2::fwdalign::MillePedeRecord* mchRecord = mAlign.ProcessTrack(convertedTrack, transformation, - doAlign, weightRecord); + mAlign.ProcessTrack(convertedTrack, transformation, doAlign, weightRecord); } } } @@ -345,27 +320,22 @@ class AlignmentTask auto mchTrack = mchTracks.at(iMCHTrack); int id_track = iMCHTrack; int nb_clusters = mchTrack.getNClusters(); - tracksAll += 1; // Track selection, saving only tracks having exactly 10 clusters if (nb_clusters <= 9) { continue; } - tracksGoodwithoutFit += 1; // Format conversion from TrackMCH to Track(MCH internal use) Track convertedTrack = MCHFormatConvert(mchTrack, mchClusters, doReAlign); // Erase removable track - if (RemoveTrack(convertedTrack, ImproveCut)) { + if (RemoveTrack(convertedTrack)) { continue; - } else { - tracksGood += 1; } // Track processing, saving residuals - o2::fwdalign::MillePedeRecord* mchRecord = mAlign.ProcessTrack(convertedTrack, transformation, - doAlign, weightRecord); + mAlign.ProcessTrack(convertedTrack, transformation, doAlign, weightRecord); } } } @@ -445,14 +415,6 @@ class AlignmentTask } auto tEnd = std::chrono::high_resolution_clock::now(); mElapsedTime = tEnd - tStart; - // Evaluation for track removing and selection - LOG(info) << Form("%s%d", "Number of good tracks used in alignment process: ", tracksGood); - LOG(info) << Form("%s%d", "Number of good tracks without fit processing: ", tracksGoodwithoutFit); - LOG(info) << Form("%s%d", "Number of MCH-MID tracks: ", trackMCHMID); - LOG(info) << Form("%s%d", "Total number of tracks loaded: ", tracksAll); - LOG(info) << Form("%s%f", "Ratio of MCH-MID track: ", double(trackMCHMID) / tracksAll); - LOG(info) << Form("%s%f", "Ratio before fit: ", double(tracksGoodwithoutFit) / tracksAll); - LOG(info) << Form("%s%f", "Ratio after fit: ", double(tracksGood) / tracksAll); // Generate new geometry w.r.t alignment results if (doAlign) { @@ -573,10 +535,9 @@ class AlignmentTask } //_________________________________________________________________________________________________ - bool RemoveTrack(Track& track, double ImproveCut) + bool RemoveTrack(Track& track) { - double maxChi2Cluster = 2 * ImproveCut * ImproveCut; bool removeTrack = false; try { @@ -610,7 +571,7 @@ class AlignmentTask } } - if (worstLocalChi2 < maxChi2Cluster) { + if (worstLocalChi2 < mImproveCutChi2) { break; } @@ -905,6 +866,7 @@ class AlignmentTask geo::TransformationCreator transformation{}; TrackFitter trackFitter{}; + double mImproveCutChi2{}; std::chrono::duration mElapsedTime{}; }; @@ -933,8 +895,8 @@ o2::framework::DataProcessorSpec getAlignmentSpec(bool disableCCDB) Options{{"geo-file-ref", VariantType::String, o2::base::NameConf::getAlignedGeomFileName(), {"Name of the reference geometry file"}}, {"geo-file-ideal", VariantType::String, o2::base::NameConf::getGeomFileName(), {"Name of the ideal geometry file"}}, {"grp-file", VariantType::String, o2::base::NameConf::getGRPFileName(), {"Name of the grp file"}}, - {"fitter-config", VariantType::String, "", {"Option of parameter set for TrackFitter, pp or PbPb"}}, {"do-align", VariantType::Bool, false, {"Switch for alignment, otherwise only residuals will be stored"}}, + {"do-evaluation", VariantType::Bool, false, {"Option for saving residuals for evaluation"}}, {"do-realign", VariantType::Bool, false, {"Switch for re-alignment using another geometry"}}, {"matched", VariantType::Bool, false, {"Switch for using MCH-MID matched tracks"}}, {"fix-chamber", VariantType::String, "", {"Chamber fixing, ex 1,2,3"}}, diff --git a/Detectors/MUON/MCH/Align/src/align-record-workflow.cxx b/Detectors/MUON/MCH/Align/src/align-record-workflow.cxx new file mode 100644 index 0000000000000..5640fcfb205b4 --- /dev/null +++ b/Detectors/MUON/MCH/Align/src/align-record-workflow.cxx @@ -0,0 +1,76 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file align-record-workflow.cxx +/// \brief Implementation of a DPL device to create MillePede record for muon alignment +/// +/// \author Chi ZHANG, CEA-Saclay, chi.zhang@cern.ch + +#include "MCHAlign/AlignRecordSpec.h" + +#include "Framework/CompletionPolicy.h" +#include "ReconstructionDataFormats/GlobalTrackID.h" +#include "CommonUtils/ConfigurableParam.h" +#include "GlobalTrackingWorkflowHelpers/InputHelper.h" +#include "DetectorsRaw/HBFUtilsInitializer.h" +#include "Framework/CallbacksPolicy.h" +#include "ForwardAlign/MilleRecordWriterSpec.h" + +using namespace o2::framework; +using namespace std; + +using GID = o2::dataformats::GlobalTrackID; + +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + +void customize(std::vector& workflowOptions) +{ + // option allowing to set parameters + std::vector options{ + {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation"}}, + {"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}}, + {"disable-root-output", o2::framework::VariantType::Bool, false, {"do not write output root files"}}, + {"disable-ccdb", VariantType::Bool, false, {"disable input files from CCDB"}}, + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::raw::HBFUtilsInitializer::addConfigOption(options); + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" +WorkflowSpec defineDataProcessing(const ConfigContext& configcontext) +{ + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); + o2::conf::ConfigurableParam::writeINI("o2mchalignrecord-workflow_configuration.ini"); + + auto useMC = !configcontext.options().get("disable-mc"); + bool disableCCDB = configcontext.options().get("disable-ccdb"); + bool disableRootOutput = configcontext.options().get("disable-root-output"); + + WorkflowSpec specs; + specs.emplace_back(o2::mch::getAlignRecordSpec(useMC, disableCCDB)); + auto srcTracks = GID::getSourcesMask("MCH"); + auto srcClusters = GID::getSourcesMask("MCH"); + auto matchMask = GID::getSourcesMask("MCH-MID"); + + if (!disableRootOutput) { + specs.emplace_back(o2::fwdalign::getMilleRecordWriterSpec(useMC)); + } + + o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, srcClusters, matchMask, srcTracks, useMC, srcClusters, srcTracks); + + // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit + o2::raw::HBFUtilsInitializer hbfIni(configcontext, specs); + + return std::move(specs); +} \ No newline at end of file From 7ee330fa57fdadd374c574d05cdc9e121113dcc6 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Wed, 3 Apr 2024 12:12:05 +0200 Subject: [PATCH 0041/2997] print function for MCEventHeader --- .../include/SimulationDataFormat/MCEventHeader.h | 2 ++ DataFormats/simulation/src/MCEventHeader.cxx | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h b/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h index 6b4c192cd68ab..efaf46806a89a 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCEventHeader.h @@ -142,6 +142,8 @@ class MCEventHeader : public FairMCEventHeader return ref; }; + void print() const; + /// prints a summary of info keys/types attached to this header void printInfo() const { diff --git a/DataFormats/simulation/src/MCEventHeader.cxx b/DataFormats/simulation/src/MCEventHeader.cxx index 41597f889fe48..8a46d84805507 100644 --- a/DataFormats/simulation/src/MCEventHeader.cxx +++ b/DataFormats/simulation/src/MCEventHeader.cxx @@ -15,6 +15,7 @@ #include "FairRootManager.h" #include #include +#include namespace o2 { @@ -61,6 +62,21 @@ void MCEventHeader::extractFileFromKinematics(std::string_view kinefilename, std } } +void MCEventHeader::print() const +{ + // print some used parts from FairMCEventHeader + std::cout << "RunID " << fRunId << "\n"; + std::cout << "EventID " << fEventId << "\n"; + std::cout << "Vertex-X " << fX << "\n"; + std::cout << "Vertex-Y " << fY << "\n"; + std::cout << "Vertex-Z " << fZ << "\n"; + std::cout << "Vertex-T " << fT << "\n"; + std::cout << "Impact-B " << fB << "\n"; + std::cout << "NPrim " << fNPrim << "\n"; + // print meta-fields + printInfo(); +} + /** alternative implementations below void MCEventHeader::extractFileFromKinematics(std::string_view kinefilename, std::string_view targetfilename) { From 7ed58e9da7fc414ac273e113c64288126a5e784a Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 28 Mar 2024 14:58:13 +0100 Subject: [PATCH 0042/2997] More consistent MCHeader forwarding when using GeneratorFromFile --- .../include/CommonUtils/RootSerializableKeyValueStore.h | 8 +++----- Generators/src/GeneratorFromFile.cxx | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h index e3261f8b9659d..c29a3024de6e1 100644 --- a/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h +++ b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h @@ -144,13 +144,11 @@ class RootSerializableKeyValueStore /// print list of keys, values (and optionally type information) void print(bool includetypeinfo = false) const; + /// resets store to the store of another object void copyFrom(RootSerializableKeyValueStore const& other) { - for (auto& p : other.mStore) { - if (mStore.find(p.first) == mStore.end()) { - mStore.insert(std::pair(p.first, SerializedInfo(p.second))); - } - } + mStore.clear(); + mStore = other.mStore; } private: diff --git a/Generators/src/GeneratorFromFile.cxx b/Generators/src/GeneratorFromFile.cxx index ee0709f00f8a1..069c92ec86c70 100644 --- a/Generators/src/GeneratorFromFile.cxx +++ b/Generators/src/GeneratorFromFile.cxx @@ -298,6 +298,8 @@ void GeneratorFromO2Kine::updateHeader(o2::dataformats::MCEventHeader* eventHead if (mOrigMCEventHeader.get()) { eventHeader->copyInfoFrom(*mOrigMCEventHeader.get()); } + // we forward also the original basic vertex information contained in FairMCEventHeader + static_cast(*eventHeader) = static_cast(*mOrigMCEventHeader.get()); // put additional information about input file and event number of the current event eventHeader->putInfo("forwarding-generator", "generatorFromO2Kine"); From 6d67309505318bb7f07c8ae93fdaf4b71914f94e Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 29 Mar 2024 23:52:41 +0100 Subject: [PATCH 0043/2997] ONNXRuntime: some fixes to use onnxruntime >= 1.16 --- Detectors/TRD/pid/include/TRDPID/ML.h | 1 + Detectors/TRD/pid/src/ML.cxx | 17 +++++++++++++---- .../fastsimulation/include/FastSimulations.h | 4 ++-- .../ZDC/fastsimulation/src/FastSimulations.cxx | 16 ++++++++++++---- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Detectors/TRD/pid/include/TRDPID/ML.h b/Detectors/TRD/pid/include/TRDPID/ML.h index 0b8d8ea8ea97b..7c72edc30ae3c 100644 --- a/Detectors/TRD/pid/include/TRDPID/ML.h +++ b/Detectors/TRD/pid/include/TRDPID/ML.h @@ -72,6 +72,7 @@ class ML : public PIDBase const OrtApi& mApi{Ort::GetApi()}; ///< ONNX api std::unique_ptr mSession; ///< ONNX session Ort::SessionOptions mSessionOptions; ///< ONNX session options + Ort::AllocatorWithDefaultOptions mAllocator; // Input/Output std::vector mInputNames; ///< model input names diff --git a/Detectors/TRD/pid/src/ML.cxx b/Detectors/TRD/pid/src/ML.cxx index 2ce3b6876a893..488bf055a7f6c 100644 --- a/Detectors/TRD/pid/src/ML.cxx +++ b/Detectors/TRD/pid/src/ML.cxx @@ -68,16 +68,25 @@ void ML::init(o2::framework::ProcessingContext& pc) LOG(info) << "ONNX runtime session created"; // print name/shape of inputs - mInputNames = mSession->GetInputNames(); - mInputShapes = mSession->GetInputShapes(); + for (size_t i = 0; i < mSession->GetInputCount(); ++i) { + mInputNames.push_back(mSession->GetInputNameAllocated(i, mAllocator).get()); + } + for (size_t i = 0; i < mSession->GetInputCount(); ++i) { + mInputShapes.emplace_back(mSession->GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); + } + for (size_t i = 0; i < mSession->GetOutputCount(); ++i) { + mOutputNames.push_back(mSession->GetOutputNameAllocated(i, mAllocator).get()); + } + for (size_t i = 0; i < mSession->GetOutputCount(); ++i) { + mOutputShapes.emplace_back(mSession->GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); + } + LOG(info) << "Input Node Name/Shape (" << mInputNames.size() << "):"; for (size_t i = 0; i < mInputNames.size(); i++) { LOG(info) << "\t" << mInputNames[i] << " : " << printShape(mInputShapes[i]); } // print name/shape of outputs - mOutputNames = mSession->GetOutputNames(); - mOutputShapes = mSession->GetOutputShapes(); LOG(info) << "Output Node Name/Shape (" << mOutputNames.size() << "):"; for (size_t i = 0; i < mOutputNames.size(); i++) { LOG(info) << "\t" << mOutputNames[i] << " : " << printShape(mOutputShapes[i]); diff --git a/Detectors/ZDC/fastsimulation/include/FastSimulations.h b/Detectors/ZDC/fastsimulation/include/FastSimulations.h index 9ac2216ba05bb..9244ceb894b0a 100644 --- a/Detectors/ZDC/fastsimulation/include/FastSimulations.h +++ b/Detectors/ZDC/fastsimulation/include/FastSimulations.h @@ -78,8 +78,8 @@ class NeuralFastSimulation Ort::MemoryInfo mMemoryInfo; /// Input/Output names and input shape - std::vector mInputNames; - std::vector mOutputNames; + std::vector mInputNames; + std::vector mOutputNames; std::vector> mInputShapes; /// If model has dynamic axis (for batch processing) this will tell ONNX expected size of those axis /// otherwise mBatchSize has no effect during runtime diff --git a/Detectors/ZDC/fastsimulation/src/FastSimulations.cxx b/Detectors/ZDC/fastsimulation/src/FastSimulations.cxx index 4d3a887ea4e9b..5351eca66e1a3 100644 --- a/Detectors/ZDC/fastsimulation/src/FastSimulations.cxx +++ b/Detectors/ZDC/fastsimulation/src/FastSimulations.cxx @@ -48,13 +48,13 @@ size_t NeuralFastSimulation::getBatchSize() const void NeuralFastSimulation::setInputOutputData() { for (size_t i = 0; i < mSession->GetInputCount(); ++i) { - mInputNames.push_back(mSession->GetInputName(i, mAllocator)); + mInputNames.push_back(mSession->GetInputNameAllocated(i, mAllocator).get()); } for (size_t i = 0; i < mSession->GetInputCount(); ++i) { mInputShapes.emplace_back(mSession->GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } for (size_t i = 0; i < mSession->GetOutputCount(); ++i) { - mOutputNames.push_back(mSession->GetOutputName(i, mAllocator)); + mOutputNames.push_back(mSession->GetOutputNameAllocated(i, mAllocator).get()); } // Prevent negative values from being passed as tensor shape @@ -96,11 +96,19 @@ bool ConditionalModelSimulation::setInput(std::vector>& input void ConditionalModelSimulation::run() { // Run simulation (single event) with default run options + std::vector tmpInputs; + std::vector tmpOutputs; + for (unsigned int i = 0; i < mInputNames.size(); i++) { + tmpInputs.emplace_back(mInputNames[i].c_str()); + } + for (unsigned int i = 0; i < mOutputNames.size(); i++) { + tmpOutputs.emplace_back(mOutputNames[i].c_str()); + } mModelOutput = mSession->Run(Ort::RunOptions{nullptr}, - mInputNames.data(), + tmpInputs.data(), mInputTensors.data(), mInputTensors.size(), - mOutputNames.data(), + tmpOutputs.data(), mOutputNames.size()); mInputTensors.clear(); } From d093072a0078b7dd3fbf61e91f0a05d26bcba6ac Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 3 Apr 2024 16:45:50 +0200 Subject: [PATCH 0044/2997] GPU: Do not run pipeline finalization (e.g. fractional QC) when terminating --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index ce6592988e55b..9246fc5df348f 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -1049,7 +1049,11 @@ int GPUReconstruction::EnqueuePipeline(bool terminate) if (q->retVal) { return q->retVal; } - return mChains[0]->FinalizePipelinedProcessing(); + if (terminate) { + return 0; + } else { + return mChains[0]->FinalizePipelinedProcessing(); + } } GPUChain* GPUReconstruction::GetNextChainInQueue() From a54ee7f74f2c41972fe4f4f46be0a70d1a11159b Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Thu, 4 Apr 2024 15:09:09 +0200 Subject: [PATCH 0045/2997] [EMCAL-1116] Fix in mapping for pedestal calibration (#12983) * [EMCAL-1116] Fix in mapping for pedestal calibration - As discussed on https://its.cern.ch/jira/browse/EMCAL-1120 * [EMCAL-1116] Add option to add runnumber to ccdb output string - For debugging purposes, the runnumber is added to the string stored in the ccdb - Can be enabled with workflow argument --addRunNumber - Off by default --------- Co-authored-by: jokonig --- .../include/EMCALCalibration/EMCALPedestalHelper.h | 6 ++++-- .../include/EMCALCalibration/PedestalCalibDevice.h | 5 +++-- .../EMCAL/calibration/src/EMCALPedestalHelper.cxx | 12 ++++++++---- .../EMCAL/calibration/src/PedestalCalibDevice.cxx | 6 +++--- .../testWorkflow/emc-pedestal-calib-workflow.cxx | 6 ++++-- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h index 518508f316c70..174714b9e8dcb 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h @@ -38,7 +38,8 @@ class EMCALPedestalHelper /// \brief Encodes the pedestal object into a string. This function fills fMeanPed which is then converted to a string in createInstructionString /// \param obj pedestal object as stored in production ccdb - std::vector createPedestalInstruction(const Pedestal& obj); + /// \param runNum current runnumber. If -1, will not be added to string that goes in the ccdb, otherwise runNum is the first entrey in the string + std::vector createPedestalInstruction(const Pedestal& obj, const int runNum = -1); /// \brief print the vector produced by createInstructionString in a textfile void dumpInstructions(const std::string_view filename, const std::vector data, int mRun); @@ -48,7 +49,8 @@ class EMCALPedestalHelper void setZero(); /// \brief converts fMeanPed to a vector of char - std::vector createInstructionString(); + /// \param runNum current runnumber. If -1, will not be added to string that goes in the ccdb, otherwise runNum is the first entrey in the string + std::vector createInstructionString(const int runNum = -1); static constexpr short kNSM = 20; ///< number of SuperModules static constexpr short kNRCU = 2; ///< number of readout crates (and DDLs) per SM diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/PedestalCalibDevice.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/PedestalCalibDevice.h index 5859e9e0d34ff..6d4cfa8ff2775 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/PedestalCalibDevice.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/PedestalCalibDevice.h @@ -29,7 +29,7 @@ namespace o2::emcal class PedestalCalibDevice : o2::framework::Task { public: - PedestalCalibDevice(bool dumpToFile) : mDumpToFile(dumpToFile){}; + PedestalCalibDevice(bool dumpToFile, bool addRunNum) : mDumpToFile(dumpToFile), mAddRunNumber(addRunNum){}; ~PedestalCalibDevice() final = default; void init(framework::InitContext& ctx) final; @@ -51,9 +51,10 @@ class PedestalCalibDevice : o2::framework::Task long int mStartTS = 0; ///< timestamp at the start of run used for the object in the ccdb bool mDumpToFile; ///< if output of pedestal calib (DCS ccdb) should be written to text file int mRun = 0; ///< current run number + bool mAddRunNumber = false; ///< if true, runNumber will be added to ccdb string }; -o2::framework::DataProcessorSpec getPedestalCalibDevice(bool dumpToFile); +o2::framework::DataProcessorSpec getPedestalCalibDevice(bool dumpToFile, bool addRunNum); } // end namespace o2::emcal diff --git a/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx b/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx index 0c1a45c9c62b1..b25f89be7ace9 100644 --- a/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx +++ b/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx @@ -12,7 +12,7 @@ #include "EMCALCalibration/EMCALPedestalHelper.h" using namespace o2::emcal; -std::vector EMCALPedestalHelper::createPedestalInstruction(const Pedestal& obj) +std::vector EMCALPedestalHelper::createPedestalInstruction(const Pedestal& obj, const int runNum) { setZero(); @@ -41,7 +41,7 @@ std::vector EMCALPedestalHelper::createPedestalInstruction(const Pedestal& for (int iledmon = 0; iledmon < 480; iledmon++) { int sm = iledmon / 24, - col = sm % 24, + col = iledmon % 24, ircu = 0, // LEDMONS always on RCU 0 iddl = 2 * sm + ircu; const auto& mapping = mapper.getMappingForDDL(iddl); @@ -59,7 +59,7 @@ std::vector EMCALPedestalHelper::createPedestalInstruction(const Pedestal& fMeanPed[sm][ircu][branchLG][fecLG][chipLG][channelLG] = obj.getPedestalValue(iledmon, true, true); } - return createInstructionString(); + return createInstructionString(runNum); } void EMCALPedestalHelper::setZero() @@ -79,10 +79,14 @@ void EMCALPedestalHelper::setZero() } } -std::vector EMCALPedestalHelper::createInstructionString() +std::vector EMCALPedestalHelper::createInstructionString(const int runNum) { std::stringstream fout; + if (runNum > 0) { + fout << runNum << "\n"; + } + unsigned int lineValue = 0; const unsigned int FECheaderCode = 0xC0000000; diff --git a/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx b/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx index 8220d95fa4400..83ff921611adf 100644 --- a/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx +++ b/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx @@ -71,7 +71,7 @@ void PedestalCalibDevice::sendData(o2::framework::EndOfStreamContext& ec, const // the following goes to the DCS ccdb EMCALPedestalHelper helper; - std::vector vecPedData = helper.createPedestalInstruction(data); + std::vector vecPedData = helper.createPedestalInstruction(data, mAddRunNumber ? mRun : -1); if (mDumpToFile) { helper.dumpInstructions("EMCAL-Pedestals.txt", vecPedData, mRun); } @@ -95,7 +95,7 @@ void PedestalCalibDevice::endOfStream(o2::framework::EndOfStreamContext& ec) resetStartTS(); } -o2::framework::DataProcessorSpec o2::emcal::getPedestalCalibDevice(bool dumpToFile) +o2::framework::DataProcessorSpec o2::emcal::getPedestalCalibDevice(bool dumpToFile, bool addRunNum) { std::vector inputs; @@ -111,6 +111,6 @@ o2::framework::DataProcessorSpec o2::emcal::getPedestalCalibDevice(bool dumpToFi "PedestalCalibrator", inputs, outputs, - o2::framework::AlgorithmSpec{o2::framework::adaptFromTask(dumpToFile)}, + o2::framework::AlgorithmSpec{o2::framework::adaptFromTask(dumpToFile, addRunNum)}, o2::framework::Options{}}; } \ No newline at end of file diff --git a/Detectors/EMCAL/calibration/testWorkflow/emc-pedestal-calib-workflow.cxx b/Detectors/EMCAL/calibration/testWorkflow/emc-pedestal-calib-workflow.cxx index d11e11135e5ef..c624dbaa89784 100644 --- a/Detectors/EMCAL/calibration/testWorkflow/emc-pedestal-calib-workflow.cxx +++ b/Detectors/EMCAL/calibration/testWorkflow/emc-pedestal-calib-workflow.cxx @@ -32,7 +32,8 @@ void customize(std::vector& workflowOptions) { std::vector options{ {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}, - {"dumpToFile", VariantType::Bool, false, {"if output (that goes to DCS ccdb) should be stored in txt file for local debugging"}}}; + {"dumpToFile", VariantType::Bool, false, {"if output (that goes to DCS ccdb) should be stored in txt file for local debugging"}}, + {"addRunNumber", VariantType::Bool, false, {"if true, run number will be added to ccdb file as first element of the string"}}}; std::swap(workflowOptions, options); } @@ -43,9 +44,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) o2::conf::ConfigurableParam::updateFromString(cfgc.options().get("configKeyValues")); bool dumpToFile = cfgc.options().get("dumpToFile"); + bool addRunNumber = cfgc.options().get("addRunNumber"); WorkflowSpec specs; - specs.emplace_back(o2::emcal::getPedestalCalibDevice(dumpToFile)); + specs.emplace_back(o2::emcal::getPedestalCalibDevice(dumpToFile, addRunNumber)); return specs; } From be6b559a233b8dc02c0f5615a1e30ef5fc1fa5e3 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 4 Apr 2024 13:46:22 +0200 Subject: [PATCH 0046/2997] SV study: fix in eta cut application, store matching info --- .../study/src/SVStudy.cxx | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx index 813efc3ed27a6..150e4ab88a1b2 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx @@ -142,6 +142,7 @@ void SVStudySpec::process(o2::globaltracking::RecoContainer& recoData) o2::track::TrackParCov dummyTr{}; const o2::track::TrackParCov* tpcTracks[2] = {&dummyTr, &dummyTr}; int nclTPC[2] = {0, 0}, nclITS[2] = {0, 0}, itsPatt[2] = {0, 0}; + float chi2ITSTPC[2] = {-1., -1.}; static int tfID = 0; for (int iv = 0; iv < nv0; iv++) { @@ -150,7 +151,7 @@ void SVStudySpec::process(o2::globaltracking::RecoContainer& recoData) continue; } const auto& v0 = mRefit ? v0ref : v0s[iv]; - if (mMaxEta > std::abs(v0.getEta())) { + if (mMaxEta < std::abs(v0.getEta())) { continue; } if (mSelK0 && std::abs(std::sqrt(v0.calcMass2AsK0()) - 0.497) > 0.1) { @@ -158,12 +159,12 @@ void SVStudySpec::process(o2::globaltracking::RecoContainer& recoData) } for (int ip = 0; ip < 2; ip++) { auto gid = v0id.getProngID(ip); - + auto gidset = recoData.getSingleDetectorRefs(gid); // get TPC tracks, if any tpcTracks[ip] = &dummyTr; nclTPC[ip] = 0; - if (gid.includesDet(DetID::TPC)) { - const auto& tpcTr = recoData.getTPCTrack(recoData.getTPCContributorGID(gid)); + if (gidset[GTrackID::TPC].isSourceSet()) { + const auto& tpcTr = recoData.getTPCTrack(gidset[GTrackID::TPC]); tpcTracks[ip] = &tpcTr; nclTPC[ip] = tpcTr.getNClusters(); } @@ -171,7 +172,7 @@ void SVStudySpec::process(o2::globaltracking::RecoContainer& recoData) nclITS[ip] = itsPatt[ip] = 0; if (gid.includesDet(DetID::ITS)) { auto gidITS = recoData.getITSContributorGID(gid); - if (gidITS.getSource() == GTrackID::ITS) { + if (gidset[GTrackID::ITS].isSourceSet()) { const auto& itsTr = recoData.getITSTrack(recoData.getITSContributorGID(gid)); nclITS[ip] = itsTr.getNClusters(); for (int il = 0; il < 7; il++) { @@ -180,7 +181,7 @@ void SVStudySpec::process(o2::globaltracking::RecoContainer& recoData) } } } else { - const auto& itsTrf = recoData.getITSABRefs()[gidITS]; + const auto& itsTrf = recoData.getITSABRefs()[gidset[GTrackID::ITSAB]]; nclITS[ip] = itsTrf.getNClusters(); for (int il = 0; il < 7; il++) { if (itsTrf.hasHitOnLayer(il)) { @@ -189,12 +190,17 @@ void SVStudySpec::process(o2::globaltracking::RecoContainer& recoData) } } } + if (gidset[GTrackID::ITSTPC].isSourceSet()) { + auto mtc = recoData.getTPCITSTrack(gidset[GTrackID::ITSTPC]); + chi2ITSTPC[ip] = mtc.getChi2Match(); + } } (*mDBGOut) << "tfinfo" << "orbit=" << recoData.startIR.orbit << "tfID=" << tfID << "\n"; (*mDBGOut) << "v0s" << "v0=" << v0 << "v0ID=" << v0id << "tpc0=" << *tpcTracks[0] << "tpc1=" << *tpcTracks[1] - << "nclTPC0=" << nclTPC[0] << "nclTPC1=" << nclTPC[1] << "nclITS0=" << nclITS[0] << "nclITS1=" << nclITS[1] << "itsPatt0=" << itsPatt[0] << "itsPatt1=" << itsPatt[1] << "\n"; + << "nclTPC0=" << nclTPC[0] << "nclTPC1=" << nclTPC[1] << "nclITS0=" << nclITS[0] << "nclITS1=" << nclITS[1] << "itsPatt0=" << itsPatt[0] << "itsPatt1=" << itsPatt[1] + << "chi2ITSTPC0=" << chi2ITSTPC[0] << "chi2ITSTPC1=" << chi2ITSTPC[1] << "\n"; } tfID++; } From 64df6c6b2c4b658f71a03cac02216b0ea007df71 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 2 Apr 2024 13:49:05 +0200 Subject: [PATCH 0047/2997] Providing an box generator natively for ALICEO2. This is useful for: * testing (building gap and cocktail generators) * better status code propagation --- Generators/CMakeLists.txt | 2 + Generators/include/Generators/BoxGenerator.h | 113 +++++++++++++++++++ Generators/include/Generators/Generator.h | 4 +- Generators/src/BoxGenerator.cxx | 78 +++++++++++++ Generators/src/Generator.cxx | 5 + Generators/src/GeneratorsLinkDef.h | 2 + 6 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 Generators/include/Generators/BoxGenerator.h create mode 100644 Generators/src/BoxGenerator.cxx diff --git a/Generators/CMakeLists.txt b/Generators/CMakeLists.txt index ec9e7af0756e2..3f6509b7db408 100644 --- a/Generators/CMakeLists.txt +++ b/Generators/CMakeLists.txt @@ -32,6 +32,7 @@ o2_add_library(Generators src/TriggerExternalParam.cxx src/TriggerParticleParam.cxx src/BoxGunParam.cxx + src/BoxGenerator.cxx src/QEDGenParam.cxx src/GenCosmicsParam.cxx src/GeneratorFactory.cxx @@ -80,6 +81,7 @@ set(headers include/Generators/GeneratorTParticle.h include/Generators/GeneratorTParticleParam.h include/Generators/GeneratorService.h + include/Generators/BoxGenerator.h ) if(pythia_FOUND) diff --git a/Generators/include/Generators/BoxGenerator.h b/Generators/include/Generators/BoxGenerator.h new file mode 100644 index 0000000000000..4198a1ac4ccb3 --- /dev/null +++ b/Generators/include/Generators/BoxGenerator.h @@ -0,0 +1,113 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \author Sandro Wenzel - April 2024 + +#ifndef ALICEO2_EVENTGEN_BOX +#define ALICEO2_EVENTGEN_BOX + +#include "Generators/Generator.h" +#include "TParticle.h" +#include + +namespace o2::eventgen +{ + +/* + * A simple mono-pdg "BoxGenerator". Or particle gun. + * Re-implements FairBoxGenerator for more convenient O2-processing. + */ +class BoxGenerator : public Generator +{ + public: + BoxGenerator() = default; + BoxGenerator(int pdgid, int mult = 1); + + BoxGenerator(int pdgid, + int mult, + double etamin, + double etamax, + double pmin, + double pmax, + double phimin, + double phimax) : mPDG{pdgid}, mMult{mult} + { + SetEtaRange(etamin, etamax); + SetPRange(pmin, pmax); + SetPhiRange(phimin, phimax); + } + + void SetPRange(Double32_t pmin = 0, Double32_t pmax = 10) + { + mPMin = pmin; + mPMax = pmax; + mPRangeIsSet = true; + } + + void SetPhiRange(double phimin = 0, double phimax = 360) + { + mPhiMin = phimin; + mPhiMax = phimax; + } + + void SetEtaRange(double etamin = -5, double etamax = 5) + { + mEtaMin = etamin; + mEtaMax = etamax; + mEtaRangeIsSet = true; + } + + /// generates a single particle conforming to particle gun parameters + TParticle sampleParticle() const; + + /// implements the main O2 generator interfaces + bool generateEvent() override + { + mEvent.clear(); + for (int i = 0; i < mMult; ++i) { + mEvent.push_back(sampleParticle()); + } + return true; + } + bool importParticles() override + { + mParticles.clear(); + std::copy(mEvent.begin(), mEvent.end(), std::back_insert_iterator(mParticles)); + return true; + } + + private: + double mPtMin{0.}, mPtMax{0.}; // Transverse momentum range [GeV] + double mPhiMin{0.}, mPhiMax{360.}; // Azimuth angle range [degree] + double mEtaMin{0.}, mEtaMax{0.}; // Pseudorapidity range in lab system + double mYMin{0.}, mYMax{0.}; // Rapidity range in lab system + double mPMin{0.}, mPMax{0.}; // Momentum range in lab system + double mThetaMin{0.}, mThetaMax{0.}; // Polar angle range in lab system [degree] + double mEkinMin{0.}, mEkinMax{0.}; // Kinetic Energy range in lab system [GeV] + + int mPDG{0}; + int mMult{1}; + + bool mEtaRangeIsSet{false}; // True if eta range is set + bool mYRangeIsSet{false}; // True if rapidity range is set + bool mThetaRangeIsSet{false}; // True if theta range is set + bool mCosThetaIsSet{false}; // True if uniform distribution in + // cos(theta) is set (default -> not set) + bool mPtRangeIsSet{false}; // True if transverse momentum range is set + bool mPRangeIsSet{false}; // True if abs.momentum range is set + bool mEkinRangeIsSet{false}; // True if kinetic energy range is set + + std::vector mEvent; // internal event container +}; + +} // namespace o2::eventgen + +#endif diff --git a/Generators/include/Generators/Generator.h b/Generators/include/Generators/Generator.h index 3b3e056efe3ae..a488e31ace2b9 100644 --- a/Generators/include/Generators/Generator.h +++ b/Generators/include/Generators/Generator.h @@ -71,8 +71,8 @@ class Generator : public FairGenerator Bool_t ReadEvent(FairPrimaryGenerator* primGen) final; /** methods to override **/ - virtual Bool_t generateEvent() = 0; - virtual Bool_t importParticles() = 0; + virtual Bool_t generateEvent() = 0; // generates event (in structure internal to generator) + virtual Bool_t importParticles() = 0; // fills the mParticles vector (transfer from generator state) /** setters **/ void setMomentumUnit(double val) { mMomentumUnit = val; }; diff --git a/Generators/src/BoxGenerator.cxx b/Generators/src/BoxGenerator.cxx new file mode 100644 index 0000000000000..478934d98c621 --- /dev/null +++ b/Generators/src/BoxGenerator.cxx @@ -0,0 +1,78 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \author Sandro Wenzel - April 2024 + +#include "Generators/BoxGenerator.h" +#include "TRandom.h" +#include "TDatabasePDG.h" + +using namespace o2::eventgen; + +double GetPDGMass(int pdg) +{ + static TDatabasePDG* pid = TDatabasePDG::Instance(); + TParticlePDG* p = pid->GetParticle(pdg); + if (p != nullptr) { + // LOG(info) << this->ClassName() << ": particle with PDG =" << GetPDGType() << " Found"; + return p->Mass(); // fPDGMass = p->Mass(); + } + // LOG(warn) << "pdg not known"; + return 0.; +} + +TParticle o2::eventgen::BoxGenerator::sampleParticle() const +{ + // Primary particles are distributed uniformly along + // those kinematics variables which were limitted by setters. + // if SetCosTheta() function is used, the distribution will be uniform in + // cos(theta) + + static double mass = GetPDGMass(mPDG); + + double pabs = 0, phi, pt = 0, theta = 0, eta, y, mt, px, py, pz = 0; + phi = gRandom->Uniform(mPhiMin, mPhiMax) * TMath::DegToRad(); + if (mPRangeIsSet) { + pabs = gRandom->Uniform(mPMin, mPMax); + } else if (mPtRangeIsSet) { + pt = gRandom->Uniform(mPtMin, mPtMax); + } + if (mThetaRangeIsSet) { + if (mCosThetaIsSet) { + theta = acos(gRandom->Uniform(cos(mThetaMin * TMath::DegToRad()), cos(mThetaMax * TMath::DegToRad()))); + } else { + theta = gRandom->Uniform(mThetaMin, mThetaMax) * TMath::DegToRad(); + } + } else if (mEtaRangeIsSet) { + eta = gRandom->Uniform(mEtaMin, mEtaMax); + theta = 2 * TMath::ATan(TMath::Exp(-eta)); + } else if (mYRangeIsSet) { + y = gRandom->Uniform(mYMin, mYMax); + mt = TMath::Sqrt(mass * mass + pt * pt); + pz = mt * TMath::SinH(y); + } + + if (mThetaRangeIsSet || mEtaRangeIsSet) { + if (mPRangeIsSet) { + pz = pabs * TMath::Cos(theta); + pt = pabs * TMath::Sin(theta); + } else if (mPtRangeIsSet) { + pz = pt / TMath::Tan(theta); + } + } + px = pt * TMath::Cos(phi); + py = pt * TMath::Sin(phi); + + double vx = 0., vy = 0., vz = 0.; + double etot = TMath::Sqrt(px * px + py * py + pz * pz + mass * mass); + return TParticle(mPDG, 1 /*status*/, -1 /* mother1 */, -1 /* mother2 */, + -1 /* daughter1 */, -1 /* daughter2 */, px, py, pz, etot, vx, vy, vz, 0. /*time*/); +} diff --git a/Generators/src/Generator.cxx b/Generators/src/Generator.cxx index 99a00f154c268..530e418add7c4 100644 --- a/Generators/src/Generator.cxx +++ b/Generators/src/Generator.cxx @@ -75,19 +75,23 @@ Bool_t /** generate event **/ if (!generateEvent()) { + LOG(error) << "ReadEvent failed in generateEvent"; return kFALSE; } /** import particles **/ if (!importParticles()) { + LOG(error) << "ReadEvent failed in importParticles"; return kFALSE; } if (mSubGeneratorsIdToDesc.empty() && mSubGeneratorId > -1) { + LOG(error) << "ReadEvent failed because no SubGenerator description given"; return kFALSE; } if (!mSubGeneratorsIdToDesc.empty() && mSubGeneratorId < 0) { + LOG(error) << "ReadEvent failed because SubGenerator description given but sub-generator not set"; return kFALSE; } @@ -102,6 +106,7 @@ Bool_t /** add tracks **/ if (!addTracks(primGen)) { + LOG(error) << "ReadEvent failed in addTracks"; return kFALSE; } diff --git a/Generators/src/GeneratorsLinkDef.h b/Generators/src/GeneratorsLinkDef.h index 35e77febee172..537b012cee2b2 100644 --- a/Generators/src/GeneratorsLinkDef.h +++ b/Generators/src/GeneratorsLinkDef.h @@ -73,4 +73,6 @@ #pragma link C++ class o2::eventgen::GeneratorFileOrCmdParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::eventgen::GeneratorFileOrCmdParam> + ; +#pragma link C++ class o2::eventgen::BoxGenerator + ; + #endif From 2ead385b63e0ce3ff93c261d9c1608beca92b842 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Thu, 4 Apr 2024 20:50:53 +0200 Subject: [PATCH 0048/2997] TPC cluster finder: Fix off-by-one error in scan. --- GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx index 2477593600812..442f17f73d5d9 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx @@ -167,7 +167,7 @@ GPUdii() void GPUTPCCFStreamCompaction::compactImpl(int nBlocks, int nThreads, i } if (idx == lastItem) { - newIdx[idx] = compIdx; // TODO: Eventually, we can just return the last value, no need to store to memory + newIdx[idx] = compIdx + pred; // TODO: Eventually, we can just return the last value, no need to store to memory } } From 394aba9b02f661fd4c55b2bc483ec64cbdde3508 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 5 Apr 2024 10:31:49 +0200 Subject: [PATCH 0049/2997] EPN Stderr monitor: Prepend messages from syslog with [GLOBAL SYSLOG] --- Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx b/Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx index 57d8bab96e398..b0b0f96ad9af3 100644 --- a/Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx +++ b/Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx @@ -126,7 +126,7 @@ void EPNMonitor::sendLog(const std::string& file, const std::string& message) mLoggerContext->setField(InfoLogger::InfoLoggerContext::FieldName::Facility, ("stderr/" + file).substr(0, 31)); mLoggerContext->setField(InfoLogger::InfoLoggerContext::FieldName::Run, mRunNumber != 0 ? std::to_string(mRunNumber) : "unspecified"); static const InfoLogger::InfoLogger::InfoLoggerMessageOption opt = {InfoLogger::InfoLogger::Severity::Error, 3, InfoLogger::InfoLogger::undefinedMessageOption.errorCode, InfoLogger::InfoLogger::undefinedMessageOption.sourceFile, InfoLogger::InfoLogger::undefinedMessageOption.sourceLine}; - mLogger->log(opt, *mLoggerContext, "stderr: %s", message.c_str()); + mLogger->log(opt, *mLoggerContext, "stderr: %s", file == "SYSLOG" ? (std::string("[GLOBAL SYSLOG]: ") + message).c_str() : message.c_str()); } else { printf("stderr: %s: %s\n", file.c_str(), message.c_str()); } From 06ea442e8e4d8727252e5124defb9160cafe10cd Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 3 Apr 2024 17:37:50 +0200 Subject: [PATCH 0050/2997] Add standalone TRD calib reader for isolated QC mode --- Detectors/TRD/workflow/io/CMakeLists.txt | 4 ++ .../TRDWorkflowIO/TRDCalibReaderSpec.h | 5 ++ .../workflow/io/src/TRDCalibReaderSpec.cxx | 16 +++++- .../io/src/trd-calib-reader-workflow.cxx | 49 +++++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 Detectors/TRD/workflow/io/src/trd-calib-reader-workflow.cxx diff --git a/Detectors/TRD/workflow/io/CMakeLists.txt b/Detectors/TRD/workflow/io/CMakeLists.txt index 4405d12b4f987..a3aea1ce87795 100644 --- a/Detectors/TRD/workflow/io/CMakeLists.txt +++ b/Detectors/TRD/workflow/io/CMakeLists.txt @@ -34,6 +34,10 @@ o2_add_executable(track-reader COMPONENT_NAME trd SOURCES src/trd-track-reader-workflow.cxx PUBLIC_LINK_LIBRARIES O2::TRDWorkflowIO) +o2_add_executable(calib-reader-workflow + COMPONENT_NAME trd + SOURCES src/trd-calib-reader-workflow.cxx + PUBLIC_LINK_LIBRARIES O2::TRDWorkflowIO) o2_add_executable(digittracklet-writer COMPONENT_NAME trd SOURCES src/trd-digittracklet-writer-workflow.cxx diff --git a/Detectors/TRD/workflow/io/include/TRDWorkflowIO/TRDCalibReaderSpec.h b/Detectors/TRD/workflow/io/include/TRDWorkflowIO/TRDCalibReaderSpec.h index afa6bec992795..05d09b3d9cc81 100644 --- a/Detectors/TRD/workflow/io/include/TRDWorkflowIO/TRDCalibReaderSpec.h +++ b/Detectors/TRD/workflow/io/include/TRDWorkflowIO/TRDCalibReaderSpec.h @@ -20,6 +20,9 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "DataFormatsTRD/AngularResidHistos.h" +#include "DataFormatsTRD/GainCalibHistos.h" +#include "DataFormatsTRD/PHData.h" +#include namespace o2 { @@ -41,6 +44,8 @@ class TRDCalibReader : public o2::framework::Task std::string mInFileName{"trdangreshistos.root"}; std::string mInTreeName{"calibdata"}; o2::trd::AngularResidHistos mAngResids, *mAngResidPtr = &mAngResids; + std::vector mPHData, *mPHDataPtr = &mPHData; + std::vector mGainData, *mGainDataPtr = &mGainData; }; /// create a processor spec diff --git a/Detectors/TRD/workflow/io/src/TRDCalibReaderSpec.cxx b/Detectors/TRD/workflow/io/src/TRDCalibReaderSpec.cxx index cb76bb8bbad69..26445f3ef6329 100644 --- a/Detectors/TRD/workflow/io/src/TRDCalibReaderSpec.cxx +++ b/Detectors/TRD/workflow/io/src/TRDCalibReaderSpec.cxx @@ -43,7 +43,17 @@ void TRDCalibReader::connectTree() assert(mFile && !mFile->IsZombie()); mTree.reset((TTree*)mFile->Get(mInTreeName.c_str())); assert(mTree); - mTree->SetBranchAddress("AngularResids", &mAngResidPtr); + auto attachBranch = [this](const char* brName, void* add) { + auto br = this->mTree->GetBranch(brName); + if (!br) { + LOGP(warn, "Branch {} is absent, will send empty output", std::string(brName)); + return; + } + br->SetAddress(add); + }; + attachBranch("AngularResids", &mAngResidPtr); + attachBranch("PulseHeight", &mPHDataPtr); + attachBranch("calibdatagain", &mGainData); LOG(info) << "Loaded tree from " << mInFileName << " with " << mTree->GetEntries() << " entries"; } @@ -54,6 +64,8 @@ void TRDCalibReader::run(ProcessingContext& pc) mTree->GetEntry(currEntry); LOG(info) << "Pushing angular residual histograms filled with " << mAngResids.getNEntries() << " entries at tree entry " << currEntry; pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "ANGRESHISTS", 0}, mAngResids); + pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "PULSEHEIGHT", 0}, mPHData); + pc.outputs().snapshot(Output{o2::header::gDataOriginTRD, "GAINCALIBHISTS", 0}, mGainData); if (mTree->GetReadEntry() + 1 >= mTree->GetEntries()) { pc.services().get().endOfStream(); @@ -65,6 +77,8 @@ DataProcessorSpec getTRDCalibReaderSpec() { std::vector outputs; outputs.emplace_back(o2::header::gDataOriginTRD, "ANGRESHISTS", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTRD, "PULSEHEIGHT", 0, Lifetime::Timeframe); + outputs.emplace_back(o2::header::gDataOriginTRD, "GAINCALIBHISTS", 0, Lifetime::Timeframe); return DataProcessorSpec{ "TRDCalibReader", diff --git a/Detectors/TRD/workflow/io/src/trd-calib-reader-workflow.cxx b/Detectors/TRD/workflow/io/src/trd-calib-reader-workflow.cxx new file mode 100644 index 0000000000000..d45f840d76790 --- /dev/null +++ b/Detectors/TRD/workflow/io/src/trd-calib-reader-workflow.cxx @@ -0,0 +1,49 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "CommonUtils/ConfigurableParam.h" +#include "Framework/CompletionPolicy.h" +#include "Framework/ConfigParamSpec.h" +#include "TRDWorkflowIO/TRDCalibReaderSpec.h" +#include "DetectorsRaw/HBFUtilsInitializer.h" + +using namespace o2::framework; + +// ------------------------------------------------------------------ + +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector& workflowOptions) +{ + // option allowing to set parameters + std::vector options{ + {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::raw::HBFUtilsInitializer::addConfigOption(options); + std::swap(workflowOptions, options); +} + +// ------------------------------------------------------------------ + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + // Update the (declared) parameters if changed from the command line + o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); + + WorkflowSpec specs{{o2::trd::getTRDCalibReaderSpec()}}; + o2::raw::HBFUtilsInitializer hbfIni(configcontext, specs); + return specs; +} From 3ff06783aadf11eb9f6595631b8826baba7f048b Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 1 Apr 2024 19:23:10 +0200 Subject: [PATCH 0051/2997] check for all track sources in global reader request before adding matchers --- prodtests/full-system-test/dpl-workflow.sh | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index c6e01a5ac9c3e..71de02d8ffa65 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -5,7 +5,6 @@ set -o pipefail # Abort in case any variable is not bound if [[ ${IGNORE_UNBOUND_VARIABLES:-} != 1 ]]; then set -u; fi - # --------------------------------------------------------------------------------------------------------------------- # Get this script's directory and load common settings : ${GEN_TOPO_MYDIR:=$(dirname $(realpath $0))} @@ -356,6 +355,9 @@ WORKFLOW= # Make sure we start with an empty workflow # --------------------------------------------------------------------------------------------------------------------- # Input workflow INPUT_DETECTOR_LIST=$WORKFLOW_DETECTORS +: ${GLOBAL_READER_OPTIONS:=} +: ${GLOBAL_READER_NEEDS_PV:=} +: ${GLOBAL_READER_NEEDS_SV:=} if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS} ]]; then for i in ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS//,/ }; do export INPUT_DETECTOR_LIST=$(echo $INPUT_DETECTOR_LIST | sed -e "s/,$i,/,/g" -e "s/^$i,//" -e "s/,$i"'$'"//" -e "s/^$i"'$'"//") @@ -364,8 +366,9 @@ if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ ! -z ${WORKFL export INPUT_DETECTOR_LIST=$(echo $INPUT_DETECTOR_LIST | sed -e "s/,$i,/,/g" -e "s/^$i,//" -e "s/,$i"'$'"//" -e "s/^$i"'$'"//") done - GLOBAL_READER_OPTIONS= has_detector ITS && SYNCMODE==1 && GLOBAL_READER_OPTIONS+=" --ir-frames-its" + [[ $GLOBAL_READER_NEEDS_PV == 1 ]] && GLOBAL_READER_OPTIONS+=" --primary-vertices" + [[ $GLOBAL_READER_NEEDS_SV == 1 ]] && GLOBAL_READER_OPTIONS+=" --secondary-vertices" if [[ ! -z ${TIMEFRAME_RATE_LIMIT:-} ]] && [[ $TIMEFRAME_RATE_LIMIT != 0 ]]; then HBFINI_OPTIONS=" --hbfutils-config o2_tfidinfo.root,upstream " @@ -382,6 +385,7 @@ if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ ! -z ${WORKFL has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-clusters-reader-workflow "$HBFINI_OPTIONS" "" 0 has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-preclusters-reader-workflow "$HBFINI_OPTIONS" "" 0 has_detector TRD && has_detector_from_global_reader TRD && add_W o2-trd-digit-reader-workflow "$DISABLE_MC --digit-subspec 0 --disable-trigrec $HBFINI_OPTIONS" + has_detector TRD && has_detector_from_global_reader TRD && [[ ! -z "$TRD_SOURCES" ]] && has_detector_from_global_reader_tracks "$(echo "$TRD_SOURCES" | cut -d',' -f1)-TRD" && add_W o2-trd-calib-reader-workflow "--trd-calib-infile trdcaliboutput.root $HBFINI_OPTIONS" has_detector TOF && has_detector_from_global_reader TOF && add_W o2-tof-reco-workflow "$DISABLE_MC --input-type digits --output-type NONE $HBFINI_OPTIONS" fi @@ -511,9 +515,9 @@ fi has_detector_reco ITS && ! has_detector_from_global_reader ITS && add_W o2-its-reco-workflow "--trackerCA $ITS_CONFIG $DISABLE_MC $DISABLE_DIGIT_CLUSTER_INPUT $DISABLE_ROOT_OUTPUT --pipeline $(get_N its-tracker ITS REST 1 ITSTRK),$(get_N its-clusterer ITS REST 1 ITSCL)" "$ITS_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR" has_detector_reco FT0 && ! has_detector_from_global_reader FT0 && add_W o2-ft0-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N ft0-reconstructor FT0 REST 1)" has_detector_reco TRD && ! has_detector_from_global_reader TRD && add_W o2-trd-tracklet-transformer "--disable-irframe-reader $DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TRD_FILTER_CONFIG --pipeline $(get_N TRDTRACKLETTRANSFORMER TRD REST 1 TRDTRKTRANS)" -has_detectors_reco ITS TPC && has_detector_matching ITSTPC && add_W o2-tpcits-match-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $SEND_ITSTPC_DTGL $TPC_CORR_OPT --nthreads $ITSTPC_THREADS --pipeline $(get_N itstpc-track-matcher MATCH REST $ITSTPC_THREADS TPCITS)" "$ITSTPC_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" -has_detector_reco TRD && [[ ! -z "$TRD_SOURCES" ]] && add_W o2-trd-global-tracking "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TRD_CONFIG $TRD_FILTER_CONFIG $TPC_CORR_OPT --track-sources $TRD_SOURCES --pipeline $(get_N trd-globaltracking_TPC_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_CTP_ TRD REST 1 TRDTRK)" "$TRD_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" -has_detector_reco TOF && [[ ! -z "$TOF_SOURCES" ]] && add_W o2-tof-matcher-workflow "$TOF_MATCH_OPT $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TPC_CORR_OPT ${TOFMATCH_THREADS:+--tof-lanes ${TOFMATCH_THREADS}} --track-sources $TOF_SOURCES --pipeline $(get_N tof-matcher TOF REST 1 TOFMATCH)" "$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" +has_detectors_reco ITS TPC && ! has_detector_from_global_reader_tracks ITS-TPC && has_detector_matching ITSTPC && add_W o2-tpcits-match-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $SEND_ITSTPC_DTGL $TPC_CORR_OPT --nthreads $ITSTPC_THREADS --pipeline $(get_N itstpc-track-matcher MATCH REST $ITSTPC_THREADS TPCITS)" "$ITSTPC_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" +has_detector_reco TRD && [[ ! -z "$TRD_SOURCES" ]] && ! has_detector_from_global_reader_tracks "$(echo "$TRD_SOURCES" | cut -d',' -f1)-TRD" && add_W o2-trd-global-tracking "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TRD_CONFIG $TRD_FILTER_CONFIG $TPC_CORR_OPT --track-sources $TRD_SOURCES --pipeline $(get_N trd-globaltracking_TPC_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_CTP_ TRD REST 1 TRDTRK)" "$TRD_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" +has_detector_reco TOF && [[ ! -z "$TOF_SOURCES" ]] && ! has_detector_from_global_reader_tracks "$(echo "$TOF_SOURCES" | cut -d',' -f1)-TOF" && add_W o2-tof-matcher-workflow "$TOF_MATCH_OPT $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TPC_CORR_OPT ${TOFMATCH_THREADS:+--tof-lanes ${TOFMATCH_THREADS}} --track-sources $TOF_SOURCES --pipeline $(get_N tof-matcher TOF REST 1 TOFMATCH)" "$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" has_detectors TPC && [[ -z "$DISABLE_ROOT_OUTPUT" && "${SKIP_TPC_CLUSTERSTRACKS_OUTPUT:-}" != 1 ]] && ! has_detector_from_global_reader TPC && add_W o2-tpc-reco-workflow "--input-type pass-through --output-type clusters,tpc-triggers,tracks,send-clusters-per-sector $DISABLE_MC" # --------------------------------------------------------------------------------------------------------------------- @@ -525,9 +529,9 @@ has_detector FDD && ! has_detector_from_global_reader FDD && has_processing_step has_detector FV0 && ! has_detector_from_global_reader FV0 && has_processing_step FV0_RECO && add_W o2-fv0-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector ZDC && ! has_detector_from_global_reader ZDC && has_processing_step ZDC_RECO && add_W o2-zdc-digits-reco "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector HMP && ! has_detector_from_global_reader HMP && has_processing_step HMP_RECO && add_W o2-hmpid-digits-to-clusters-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT --pipeline $(get_N HMP-Clusterization HMP REST 1 HMPCLUS)" -has_detector HMP && has_detector_matching HMP && ! has_detector_from_global_reader_tracks HMP && has_processing_step HMP_RECO && add_W o2-hmpid-matcher-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --track-sources ${HMP_SOURCES:-all} --pipeline $(get_N hmp-matcher HMP REST 1 HMPMATCH)" -has_detectors_reco MCH MID && has_detector_matching MCHMID && add_W o2-muon-tracks-matcher-workflow "$DISABLE_ROOT_INPUT $DISABLE_MC $DISABLE_ROOT_OUTPUT --pipeline $(get_N muon-track-matcher MATCH REST 1)" -has_detectors_reco MFT MCH && has_detector_matching MFTMCH && add_W o2-globalfwd-matcher-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N globalfwd-track-matcher MATCH REST 1 FWDMATCH)" "$MFTMCHConf" +has_detector HMP && [[ ! -z "$HMP_SOURCES" ]] && has_detector_matching HMP && ! has_detector_from_global_reader_tracks HMP && add_W o2-hmpid-matcher-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --track-sources $HMP_SOURCES --pipeline $(get_N hmp-matcher HMP REST 1 HMPMATCH)" +has_detectors_reco MCH MID && has_detector_matching MCHMID && ! has_detector_from_global_reader_tracks "MCH-MID" && add_W o2-muon-tracks-matcher-workflow "$DISABLE_ROOT_INPUT $DISABLE_MC $DISABLE_ROOT_OUTPUT --pipeline $(get_N muon-track-matcher MATCH REST 1)" +has_detectors_reco MFT MCH && has_detector_matching MFTMCH && ! has_detector_from_global_reader_tracks "MFT-MCH" && add_W o2-globalfwd-matcher-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N globalfwd-track-matcher MATCH REST 1 FWDMATCH)" "$MFTMCHConf" # --------------------------------------------------------------------------------------------------------------------- # Reconstruction workflows needed only in case QC or CALIB was requested @@ -555,10 +559,10 @@ has_detector_reco MCH && ( [[ -z "$DISABLE_ROOT_OUTPUT" ]] || needs_root_output # always run vertexing if requested and if there are some sources, but in cosmic mode we work in pass-trough mode (create record for non-associated tracks) ( [[ $BEAMTYPE == "cosmic" ]] || ! has_detector_reco ITS) && PVERTEX_CONFIG+=" --skip" -has_detector_matching PRIMVTX && [[ ! -z "$VERTEXING_SOURCES" ]] && add_W o2-primary-vertexing-workflow "$DISABLE_MC $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $PVERTEX_CONFIG --pipeline $(get_N primary-vertexing MATCH REST 1 PRIMVTX),$(get_N pvertex-track-matching MATCH REST 1 PRIMVTXMATCH)" "${PVERTEXING_CONFIG_KEY};${INTERACTION_TAG_CONFIG_KEY};" +has_detector_matching PRIMVTX && [[ ! -z "$VERTEXING_SOURCES" ]] && [[ $GLOBAL_READER_NEEDS_PV != 1 ]] && add_W o2-primary-vertexing-workflow "$DISABLE_MC $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $PVERTEX_CONFIG --pipeline $(get_N primary-vertexing MATCH REST 1 PRIMVTX),$(get_N pvertex-track-matching MATCH REST 1 PRIMVTXMATCH)" "${PVERTEXING_CONFIG_KEY};${INTERACTION_TAG_CONFIG_KEY};" if [[ $BEAMTYPE != "cosmic" ]] && has_detectors_reco ITS && has_detector_matching SECVTX && [[ ! -z "$SVERTEXING_SOURCES" ]]; then - add_W o2-secondary-vertexing-workflow "$DISABLE_MC $STRTRACKING $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $TPC_CORR_OPT --vertexing-sources $SVERTEXING_SOURCES --threads $SVERTEX_THREADS --pipeline $(get_N secondary-vertexing MATCH REST $SVERTEX_THREADS SECVTX)" "$TPC_CORR_KEY" + [[ $GLOBAL_READER_NEEDS_SV != 1 ]] && add_W o2-secondary-vertexing-workflow "$DISABLE_MC $STRTRACKING $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $TPC_CORR_OPT --vertexing-sources $SVERTEXING_SOURCES --threads $SVERTEX_THREADS --pipeline $(get_N secondary-vertexing MATCH REST $SVERTEX_THREADS SECVTX)" "$TPC_CORR_KEY" SECTVTX_ON="1" else SECTVTX_ON="0" From 9146d7167db544fba79fbb949795b8fac0fe6d47 Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Fri, 5 Apr 2024 14:54:43 +0200 Subject: [PATCH 0052/2997] [EMCAL-1116] Minor improvemts to pedestal calibrator (#12985) - In case the runnumber is added to the output, also add an end of file marker (0xFFFFFFFF) - Use span instead of vector - Use endl instead of \n Co-authored-by: jokonig --- .../include/EMCALCalibration/EMCALPedestalHelper.h | 3 ++- .../EMCAL/calibration/src/EMCALPedestalHelper.cxx | 13 +++++++------ .../EMCAL/calibration/src/PedestalCalibDevice.cxx | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h index 174714b9e8dcb..109fa795fd43a 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALPedestalHelper.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace o2::emcal { @@ -42,7 +43,7 @@ class EMCALPedestalHelper std::vector createPedestalInstruction(const Pedestal& obj, const int runNum = -1); /// \brief print the vector produced by createInstructionString in a textfile - void dumpInstructions(const std::string_view filename, const std::vector data, int mRun); + void dumpInstructions(const std::string_view filename, const gsl::span& data); private: /// \brief initialize fMeanPed with zeros diff --git a/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx b/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx index b25f89be7ace9..ef10423a2c97d 100644 --- a/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx +++ b/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx @@ -109,7 +109,7 @@ std::vector EMCALPedestalHelper::createInstructionString(const int runNum) isect += 3; // skip non-installed sectors } - int activeDTC[kNDTC] = {0}; + std::bitset activeDTC; for (iDTC = 0; iDTC < kNDTC; iDTC++) { if (iDTC == 10 || iDTC == 20 || iDTC == 30) { // skip TRU activeDTC[iDTC] = 0; @@ -180,17 +180,18 @@ std::vector EMCALPedestalHelper::createInstructionString(const int runNum) } // iDTC } // iSM - // std::vector output; - std::string instructionString(fout.str()); - // std::fill(instructionString.begin(), instructionString.end(), std::back_inserter(output)); + if (runNum > 0) { + fout << 0xFFFFFFFF << std::endl; + } + + const std::string instructionString(fout.str()); std::vector output(instructionString.begin(), instructionString.end()); return output; } -void EMCALPedestalHelper::dumpInstructions(const std::string_view filename, const std::vector data, int mRun) +void EMCALPedestalHelper::dumpInstructions(const std::string_view filename, const gsl::span& data) { std::ofstream fout(filename.data()); - fout << mRun << "\n"; fout << data.data(); fout.close(); } \ No newline at end of file diff --git a/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx b/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx index 83ff921611adf..2f4c6ee204a31 100644 --- a/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx +++ b/Detectors/EMCAL/calibration/src/PedestalCalibDevice.cxx @@ -73,7 +73,7 @@ void PedestalCalibDevice::sendData(o2::framework::EndOfStreamContext& ec, const EMCALPedestalHelper helper; std::vector vecPedData = helper.createPedestalInstruction(data, mAddRunNumber ? mRun : -1); if (mDumpToFile) { - helper.dumpInstructions("EMCAL-Pedestals.txt", vecPedData, mRun); + helper.dumpInstructions("EMCAL-Pedestals.txt", vecPedData); } auto clNameDCS = o2::utils::MemFileHelper::getClassName(vecPedData); From 303387b923b6d2e4db46aae937aada71c664b123 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 8 Mar 2024 09:30:37 +0100 Subject: [PATCH 0053/2997] O2Sim move to new ROOT serialization --- .../Base/include/DetectorsBase/Detector.h | 17 +++------ Detectors/Base/src/Detector.cxx | 35 ++++++++++--------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/Detector.h b/Detectors/Base/include/DetectorsBase/Detector.h index 6acfa4f5cc46c..1432d93c53821 100644 --- a/Detectors/Base/include/DetectorsBase/Detector.h +++ b/Detectors/Base/include/DetectorsBase/Detector.h @@ -29,7 +29,6 @@ #include #include #include -#include #include "CommonUtils/ShmManager.h" #include "CommonUtils/ShmAllocator.h" #include @@ -42,9 +41,7 @@ #include -namespace o2 -{ -namespace base +namespace o2::base { /// This is the basic class for any AliceO2 detector module, whether it is @@ -260,17 +257,12 @@ T decodeShmMessage(fair::mq::Parts& dataparts, int index, bool*& busy) } // this goes into the source -void attachMessageBufferToParts(fair::mq::Parts& parts, fair::mq::Channel& channel, - void* data, size_t size, void (*func_ptr)(void* data, void* hint), void* hint); +void attachMessageBufferToParts(fair::mq::Parts& parts, fair::mq::Channel& channel, void* data, TClass* cl); template void attachTMessage(Container const& hits, fair::mq::Channel& channel, fair::mq::Parts& parts) { - TMessage* tmsg = new TMessage(); - tmsg->WriteObjectAny((void*)&hits, TClass::GetClass(typeid(hits))); - attachMessageBufferToParts( - parts, channel, tmsg->Buffer(), tmsg->BufferSize(), - [](void* data, void* hint) { delete static_cast(hint); }, tmsg); + attachMessageBufferToParts(parts, channel, (void*)&hits, TClass::GetClass(typeid(hits))); } void* decodeTMessageCore(fair::mq::Parts& dataparts, int index); @@ -746,7 +738,6 @@ class DetImpl : public o2::base::Detector ClassDefOverride(DetImpl, 0); }; -} // namespace base -} // namespace o2 +} // namespace o2::base #endif diff --git a/Detectors/Base/src/Detector.cxx b/Detectors/Base/src/Detector.cxx index 3168e0e84e1f2..f2b790ffccd5b 100644 --- a/Detectors/Base/src/Detector.cxx +++ b/Detectors/Base/src/Detector.cxx @@ -17,6 +17,7 @@ #include "DetectorsBase/MaterialManager.h" #include "DetectorsCommonDataFormats/DetID.h" #include "Field/MagneticField.h" +#include "Framework/TMessageSerializer.h" #include "TString.h" // for TString #include "TGeoManager.h" @@ -196,16 +197,19 @@ int Detector::registerSensitiveVolumeAndGetVolID(std::string const& name) #include #include #include -namespace o2 -{ -namespace base +namespace o2::base { // this goes into the source -void attachMessageBufferToParts(fair::mq::Parts& parts, fair::mq::Channel& channel, void* data, size_t size, - void (*free_func)(void* data, void* hint), void* hint) +void attachMessageBufferToParts(fair::mq::Parts& parts, fair::mq::Channel& channel, void* data, TClass* cl) { - std::unique_ptr message(channel.NewMessage(data, size, free_func, hint)); - parts.AddPart(std::move(message)); + auto msg = channel.Transport()->CreateMessage(4096, fair::mq::Alignment{64}); + // This will serialize the data directly into the message buffer, without any further + // buffer or copying. Notice how the message will have 8 bytes of header and then + // the serialized data as TBufferFile. In principle one could construct a serialized TMessage payload + // however I did not manage to get it to work for every case. + o2::framework::FairOutputTBuffer buffer(*msg); + o2::framework::TMessageSerializer::serialize(buffer, data, cl); + parts.AddPart(std::move(msg)); } void attachDetIDHeaderMessage(int id, fair::mq::Channel& channel, fair::mq::Parts& parts) { @@ -246,17 +250,14 @@ void* decodeShmCore(fair::mq::Parts& dataparts, int index, bool*& busy) void* decodeTMessageCore(fair::mq::Parts& dataparts, int index) { - class TMessageWrapper : public TMessage - { - public: - TMessageWrapper(void* buf, Int_t len) : TMessage(buf, len) { ResetBit(kIsOwner); } - ~TMessageWrapper() override = default; - }; auto rawmessage = std::move(dataparts.At(index)); - auto message = std::make_unique(rawmessage->GetData(), rawmessage->GetSize()); - return message.get()->ReadObjectAny(message.get()->GetClass()); + o2::framework::FairInputTBuffer buffer((char*)rawmessage->GetData(), rawmessage->GetSize()); + buffer.InitMap(); + auto* cl = buffer.ReadClass(); + buffer.SetBufferOffset(0); + buffer.ResetMap(); + return buffer.ReadObjectAny(cl); } -} // namespace base -} // namespace o2 +} // namespace o2::base ClassImp(o2::base::Detector); From 72cc135e900a5cd7c23bec22a46bc39303fbcd1c Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Thu, 4 Apr 2024 21:36:58 +0200 Subject: [PATCH 0054/2997] TPC cluster finder: Refactor device wide scan function. --- .../GPUTPCCFStreamCompaction.cxx | 156 +++++++----------- .../GPUTPCCFStreamCompaction.h | 19 +-- .../TPCClusterFinder/GPUTPCClusterFinder.h | 2 + 3 files changed, 61 insertions(+), 116 deletions(-) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx index 442f17f73d5d9..f4489146f583d 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx @@ -24,106 +24,101 @@ using namespace GPUCA_NAMESPACE::gpu::tpccf; template <> GPUdii() void GPUTPCCFStreamCompaction::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, int iBuf, int stage) { - int nElems = compactionElems(clusterer, stage); - nativeScanUpStartImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, clusterer.mPisPeak, clusterer.mPbuf + (iBuf - 1) * clusterer.mBufSize, clusterer.mPbuf + iBuf * clusterer.mBufSize, nElems); -} + int nElems = CompactionElems(clusterer, stage); -GPUdii() void GPUTPCCFStreamCompaction::nativeScanUpStartImpl(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, - const uchar* predicate, - int* sums, - int* incr, int nElems) -{ - int idx = get_global_id(0); + const auto* predicate = clusterer.mPisPeak; + auto* scanOffset = clusterer.GetScanBuffer(iBuf); + + int iThreadGlobal = get_global_id(0); int pred = 0; - if (idx < nElems) { - pred = predicate[idx]; + if (iThreadGlobal < nElems) { + pred = predicate[iThreadGlobal]; } - int scanRes = CfUtils::blockPredicateSum(smem, pred); + int nElemsInBlock = CfUtils::blockPredicateSum(smem, pred); - int lid = get_local_id(0); - int lastItem = get_local_size(0) - 1; - int gid = get_group_id(0); - - if (lid == lastItem) { - incr[gid] = scanRes; + int lastThread = nThreads - 1; + if (iThread == lastThread) { + scanOffset[iBlock] = nElemsInBlock; } } template <> GPUdii() void GPUTPCCFStreamCompaction::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, int iBuf, int nElems) { - nativeScanUpImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, clusterer.mPbuf + (iBuf - 1) * clusterer.mBufSize, clusterer.mPbuf + iBuf * clusterer.mBufSize, nElems); -} - -GPUdii() void GPUTPCCFStreamCompaction::nativeScanUpImpl(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, - int* sums, - int* incr, int nElems) -{ - int idx = get_global_id(0); - int scanRes = work_group_scan_inclusive_add((idx < nElems) ? sums[idx] : 0); - - /* DBGPR_2("ScanUp: idx = %d, res = %d", idx, scanRes); */ - - sums[idx] = scanRes; + auto* scanOffset = clusterer.GetScanBuffer(iBuf - 1); + auto* scanOffsetNext = clusterer.GetScanBuffer(iBuf); - int lid = get_local_id(0); - int lastItem = get_local_size(0) - 1; - int gid = get_group_id(0); + int iThreadGlobal = get_global_id(0); + int offsetInBlock = work_group_scan_inclusive_add((iThreadGlobal < nElems) ? scanOffset[iThreadGlobal] : 0); - /* DBGPR_1("ScanUp: idx = %d", idx); */ + // TODO: This write isn't needed?? + scanOffset[iThreadGlobal] = offsetInBlock; - if (lid == lastItem) { - incr[gid] = scanRes; + int lastThread = nThreads - 1; + if (iThread == lastThread) { + scanOffsetNext[iBlock] = offsetInBlock; } } template <> GPUdii() void GPUTPCCFStreamCompaction::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, int iBuf, int nElems) { - nativeScanTopImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, clusterer.mPbuf + (iBuf - 1) * clusterer.mBufSize, nElems); -} + int iThreadGlobal = get_global_id(0); + int* scanOffset = clusterer.GetScanBuffer(iBuf - 1); -GPUdii() void GPUTPCCFStreamCompaction::nativeScanTopImpl(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, int* incr, int nElems) -{ - int idx = get_global_id(0); + bool inBounds = (iThreadGlobal < nElems); - /* DBGPR_1("ScanTop: idx = %d", idx); */ + int offsetInBlock = work_group_scan_inclusive_add(inBounds ? scanOffset[iThreadGlobal] : 0); - int scanRes = work_group_scan_inclusive_add((idx < nElems) ? incr[idx] : 0); - incr[idx] = scanRes; + if (inBounds) { + scanOffset[iThreadGlobal] = offsetInBlock; + } } template <> -GPUdii() void GPUTPCCFStreamCompaction::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, int iBuf, unsigned int offset, int nElems) +GPUdii() void GPUTPCCFStreamCompaction::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& /*smem*/, processorType& clusterer, int iBuf, unsigned int offset, int nElems) { - nativeScanDownImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, clusterer.mPbuf + (iBuf - 1) * clusterer.mBufSize, clusterer.mPbuf + iBuf * clusterer.mBufSize, offset, nElems); -} + int iThreadGlobal = get_global_id(0) + offset; -GPUdii() void GPUTPCCFStreamCompaction::nativeScanDownImpl(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, - int* sums, - const int* incr, - unsigned int offset, int nElems) -{ - int gid = get_group_id(0); - int idx = get_global_id(0) + offset; + int* scanOffsetPrev = clusterer.GetScanBuffer(iBuf - 1); + const int* scanOffset = clusterer.GetScanBuffer(iBuf); - int shift = incr[gid]; + int shift = scanOffset[iBlock]; - if (idx < nElems) { - sums[idx] += shift; + if (iThreadGlobal < nElems) { + scanOffsetPrev[iThreadGlobal] += shift; } } template <> GPUdii() void GPUTPCCFStreamCompaction::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, int iBuf, int stage, ChargePos* in, ChargePos* out) { - unsigned int nElems = compactionElems(clusterer, stage); + unsigned int nElems = CompactionElems(clusterer, stage); SizeT bufferSize = (stage) ? clusterer.mNMaxClusters : clusterer.mNMaxPeaks; - compactImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, in, out, clusterer.mPisPeak, clusterer.mPbuf + (iBuf - 1) * clusterer.mBufSize, clusterer.mPbuf + iBuf * clusterer.mBufSize, nElems, bufferSize); + + unsigned int iThreadGlobal = get_global_id(0); + + const auto* predicate = clusterer.mPisPeak; + const auto* scanOffset = clusterer.GetScanBuffer(iBuf); + + bool iAmDummy = (iThreadGlobal >= nElems); + + int pred = (iAmDummy) ? 0 : predicate[iThreadGlobal]; + int offsetInBlock = CfUtils::blockPredicateScan(smem, pred); + + SizeT globalOffsetOut = offsetInBlock; + if (iBlock > 0) { + globalOffsetOut += scanOffset[iBlock - 1]; + } + + if (pred && globalOffsetOut < bufferSize) { + out[globalOffsetOut] = in[iThreadGlobal]; + } + unsigned int lastId = get_global_size(0) - 1; - if ((unsigned int)get_global_id(0) == lastId) { - SizeT nFinal = clusterer.mPbuf[lastId]; + if (iThreadGlobal == lastId) { + SizeT nFinal = globalOffsetOut + pred; if (nFinal > bufferSize) { clusterer.raiseError(stage ? GPUErrors::ERROR_CF_CLUSTER_OVERFLOW : GPUErrors::ERROR_CF_PEAK_OVERFLOW, clusterer.mISlice, nFinal, bufferSize); nFinal = bufferSize; @@ -136,42 +131,7 @@ GPUdii() void GPUTPCCFStreamCompaction::Thread= nElems); - - int pred = (iAmDummy) ? 0 : predicate[idx]; - int scanRes = CfUtils::blockPredicateScan(smem, pred); - - SizeT compIdx = scanRes; - if (gid) { - compIdx += incr[gid - 1]; - } - - // SizeT tgtIdx = compIdx - 1; - SizeT tgtIdx = compIdx; - if (pred && tgtIdx < bufferSize) { - out[tgtIdx] = in[idx]; - } - - if (idx == lastItem) { - newIdx[idx] = compIdx + pred; // TODO: Eventually, we can just return the last value, no need to store to memory - } -} - -GPUdii() int GPUTPCCFStreamCompaction::compactionElems(processorType& clusterer, int stage) +GPUdii() int GPUTPCCFStreamCompaction::CompactionElems(processorType& clusterer, int stage) { return (stage) ? clusterer.mPmemory->counters.nPeaks : clusterer.mPmemory->counters.nPositions; } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.h index 8a2d3034db95c..207c9075ba444 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.h @@ -55,24 +55,7 @@ class GPUTPCCFStreamCompaction : public GPUKernelTemplate GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); private: - static GPUd() void nativeScanUpStartImpl(int, int, int, int, GPUSharedMemory&, - const uchar*, int*, int*, - int); - - static GPUd() void nativeScanUpImpl(int, int, int, int, GPUSharedMemory&, - int*, int*, int); - - static GPUd() void nativeScanTopImpl(int, int, int, int, GPUSharedMemory&, - int*, int); - - static GPUd() void nativeScanDownImpl(int, int, int, int, GPUSharedMemory&, - int*, const int*, unsigned int, int); - - static GPUd() void compactImpl(int, int, int, int, GPUSharedMemory&, - const ChargePos*, ChargePos*, - const uchar*, int*, const int*, - int, tpccf::SizeT); - static GPUd() int compactionElems(processorType& clusterer, int stage); + static GPUd() int CompactionElems(processorType& clusterer, int stage); }; } // namespace GPUCA_NAMESPACE::gpu diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index 4cdd05802694c..4488d7cd1a711 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -116,6 +116,8 @@ class GPUTPCClusterFinder : public GPUProcessor int* mPbuf = nullptr; Memory* mPmemory = nullptr; + GPUdi() int* GetScanBuffer(int iBuf) const { return mPbuf + iBuf * mBufSize; } + o2::dataformats::ConstMCTruthContainerView const* mPinputLabels = nullptr; unsigned int* mPlabelsInRow = nullptr; unsigned int mPlabelsHeaderGlobalOffset = 0; From 832d7c2c26454276991de5a3d47c8989622397fd Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 2 Apr 2024 15:07:30 +0200 Subject: [PATCH 0055/2997] TPC: Use qmax/time contributions to cluster error and occupancy estimators in refit --- Detectors/GlobalTracking/src/MatchCosmics.cxx | 4 ++-- Detectors/GlobalTracking/src/MatchTOF.cxx | 4 ++-- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 2 +- .../study/src/TPCTrackStudy.cxx | 2 +- .../TPC/calibration/src/CalculatedEdx.cxx | 2 +- .../calibration/src/CalibPadGainTracks.cxx | 4 ++-- Detectors/TPC/qc/src/TrackClusters.cxx | 2 +- .../workflow/src/ClusterSharingMapSpec.cxx | 2 +- Detectors/TPC/workflow/src/TPCRefitter.cxx | 2 +- .../workflow/src/TRDGlobalTrackingSpec.cxx | 2 +- Detectors/Vertexing/src/SVertexer.cxx | 2 +- .../DataTypes/GPUTPCClusterOccupancyMap.cxx | 3 +++ GPU/GPUTracking/Definitions/GPUSettingsList.h | 2 +- .../Global/GPUChainTrackingSliceTracker.cxx | 15 +++++++++------ .../Global/GPUTrackingInputProvider.cxx | 4 ++-- .../Interface/GPUO2InterfaceRefit.cxx | 19 ++++++++++++++++--- .../Interface/GPUO2InterfaceRefit.h | 10 ++++++++-- GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 14 ++++++++++++-- macro/runTPCRefit.C | 2 +- 19 files changed, 66 insertions(+), 31 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchCosmics.cxx b/Detectors/GlobalTracking/src/MatchCosmics.cxx index 3d9453bca3f1d..ac07b24ed622f 100644 --- a/Detectors/GlobalTracking/src/MatchCosmics.cxx +++ b/Detectors/GlobalTracking/src/MatchCosmics.cxx @@ -93,8 +93,8 @@ void MatchCosmics::refitWinners(const o2::globaltracking::RecoContainer& data) if (data.inputsTPCclusters) { tpcRefitter = std::make_unique(&data.inputsTPCclusters->clusterIndex, mTPCCorrMapsHelper, mBz, - tpcClusRefs.data(), tpcClusShMap.data(), - nullptr, o2::base::Propagator::Instance()); + tpcClusRefs.data(), 0, tpcClusShMap.data(), + nullptr, nullptr, o2::base::Propagator::Instance()); } const auto& itsClusters = prepareITSClusters(data); diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index fa1b0c3a3d07a..3c4dfe60a0139 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -1797,7 +1797,7 @@ void MatchTOF::checkRefitter() { if (mTPCClusterIdxStruct) { mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, - mTPCTrackClusIdx.data(), mTPCRefitterShMap.data(), - nullptr, o2::base::Propagator::Instance()); + mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), + nullptr, nullptr, o2::base::Propagator::Instance()); } } diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 5bfc9df56369b..555421cae1448 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -572,7 +572,7 @@ bool MatchTPCITS::prepareTPCData() mITSROFofTPCBin[ib] = itsROF; } */ - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), mTPCRefitterShMap.data(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), nullptr, nullptr, o2::base::Propagator::Instance()); mInteractionMUSLUT.clear(); mInteractionMUSLUT.resize(maxTime + 3 * o2::constants::lhc::LHCOrbitMUS, -1); mTimer[SWPrepTPC].Stop(); diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx index 3abcfe583f670..9e1bb1804c4e5 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx @@ -181,7 +181,7 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) mTPCTrkLabels = recoData.getTPCTracksMCLabels(); } - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), mTPCRefitterShMap.data(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), nullptr, nullptr, o2::base::Propagator::Instance()); float vdriftTB = mTPCVDriftHelper.getVDriftObject().getVDrift() * o2::tpc::ParameterElectronics::Instance().ZbinWidth; // VDrift expressed in cm/TimeBin float tpcTBBias = mTPCVDriftHelper.getVDriftObject().getTimeOffset() / (8 * o2::constants::lhc::LHCBunchSpacingMUS); diff --git a/Detectors/TPC/calibration/src/CalculatedEdx.cxx b/Detectors/TPC/calibration/src/CalculatedEdx.cxx index 31bd7677b4449..fb23611416f3c 100644 --- a/Detectors/TPC/calibration/src/CalculatedEdx.cxx +++ b/Detectors/TPC/calibration/src/CalculatedEdx.cxx @@ -45,7 +45,7 @@ void CalculatedEdx::setMembers(std::vector* tpcTrackClIdx void CalculatedEdx::setRefit() { - mRefit = std::make_unique(mClusterIndex, &mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), nullptr, mTracks); + mRefit = std::make_unique(mClusterIndex, &mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), 0, nullptr, nullptr, mTracks); } void CalculatedEdx::fillMissingClusters(int missingClusters[4], float minChargeTot, float minChargeMax, int method) diff --git a/Detectors/TPC/calibration/src/CalibPadGainTracks.cxx b/Detectors/TPC/calibration/src/CalibPadGainTracks.cxx index bab84a446d205..bd9dfe3214203 100644 --- a/Detectors/TPC/calibration/src/CalibPadGainTracks.cxx +++ b/Detectors/TPC/calibration/src/CalibPadGainTracks.cxx @@ -38,9 +38,9 @@ void CalibPadGainTracks::processTracks(const int nMaxTracks) std::unique_ptr refit; if (!mPropagateTrack) { mBufVec.resize(mClusterIndex->nClustersTotal); - o2::gpu::GPUO2InterfaceRefit::fillSharedClustersMap(mClusterIndex, *mTracks, mTPCTrackClIdxVecInput->data(), mBufVec.data()); + o2::gpu::GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(mClusterIndex, *mTracks, mTPCTrackClIdxVecInput->data(), mBufVec.data()); mClusterShMapTPC = mBufVec.data(); - refit = std::make_unique(mClusterIndex, mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), mClusterShMapTPC); + refit = std::make_unique(mClusterIndex, mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), 0, mClusterShMapTPC); } const size_t loopEnd = (nMaxTracks < 0) ? mTracks->size() : ((nMaxTracks > mTracks->size()) ? mTracks->size() : size_t(nMaxTracks)); diff --git a/Detectors/TPC/qc/src/TrackClusters.cxx b/Detectors/TPC/qc/src/TrackClusters.cxx index 2c039f070b702..bcc071920e2e9 100644 --- a/Detectors/TPC/qc/src/TrackClusters.cxx +++ b/Detectors/TPC/qc/src/TrackClusters.cxx @@ -64,7 +64,7 @@ bool TrackClusters::processTrackAndClusters(const std::vector std::vector mBufVec; mBufVec.resize(clusterIndex->nClustersTotal); - o2::gpu::GPUO2InterfaceRefit::fillSharedClustersMap(clusterIndex, *tracks, clusRefs->data(), mBufVec.data()); + o2::gpu::GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(clusterIndex, *tracks, clusRefs->data(), mBufVec.data()); for (auto const& track : (*tracks)) { const auto dEdxTot = track.getdEdx().dEdxTotTPC; diff --git a/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx b/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx index d0e5aa121b543..2625e5dc2c6c6 100644 --- a/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx +++ b/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx @@ -39,7 +39,7 @@ void ClusterSharingMapSpec::run(ProcessingContext& pc) } auto& bufVec = pc.outputs().make>(Output{o2::header::gDataOriginTPC, "CLSHAREDMAP", 0}, clustersTPC->clusterIndex.nClustersTotal); - o2::gpu::GPUO2InterfaceRefit::fillSharedClustersMap(&clustersTPC->clusterIndex, tracksTPC, tracksTPCClRefs.data(), bufVec.data()); + o2::gpu::GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(&clustersTPC->clusterIndex, tracksTPC, tracksTPCClRefs.data(), bufVec.data()); timer.Stop(); LOGF(info, "Timing for TPC clusters sharing map creation: Cpu: %.3e Real: %.3e s", timer.CpuTime(), timer.RealTime()); diff --git a/Detectors/TPC/workflow/src/TPCRefitter.cxx b/Detectors/TPC/workflow/src/TPCRefitter.cxx index bf32925585366..7a71305683d8c 100644 --- a/Detectors/TPC/workflow/src/TPCRefitter.cxx +++ b/Detectors/TPC/workflow/src/TPCRefitter.cxx @@ -189,7 +189,7 @@ void TPCRefitterSpec::process(o2::globaltracking::RecoContainer& recoData) mTPCTrkLabels = recoData.getTPCTracksMCLabels(); } - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), mTPCRefitterShMap.data(), nullptr, prop); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), nullptr, nullptr, prop); float vdriftTB = mTPCVDriftHelper.getVDriftObject().getVDrift() * o2::tpc::ParameterElectronics::Instance().ZbinWidth; // VDrift expressed in cm/TimeBin float tpcTBBias = mTPCVDriftHelper.getVDriftObject().getTimeOffset() / (8 * o2::constants::lhc::LHCBunchSpacingMUS); diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index 707cd2d961cf3..665b5595adc5b 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -275,7 +275,7 @@ void TRDGlobalTracking::run(ProcessingContext& pc) mChainTracking->ClearIOPointers(); mTPCClusterIdxStruct = &inputTracks.inputsTPCclusters->clusterIndex; - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(), inputTracks.getTPCTracksClusterRefs().data(), inputTracks.clusterShMapTPC.data(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(), inputTracks.getTPCTracksClusterRefs().data(), 0, inputTracks.clusterShMapTPC.data(), nullptr, nullptr, o2::base::Propagator::Instance()); auto tmpInputContainer = getRecoInputContainer(pc, &mChainTracking->mIOPtrs, &inputTracks, mUseMC); auto tmpContainer = GPUWorkflowHelper::fillIOPtr(mChainTracking->mIOPtrs, inputTracks, mUseMC, nullptr, GTrackID::getSourcesMask("TRD"), mTrkMask, GTrackID::mask_t{GTrackID::MASK_NONE}); mTrackletsRaw = inputTracks.getTRDTracklets(); diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx index 5da94b76f56b1..c7335f4ed0e73 100644 --- a/Detectors/Vertexing/src/SVertexer.cxx +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -448,7 +448,7 @@ void SVertexer::buildT2V(const o2::globaltracking::RecoContainer& recoData) // a mTPCTrackClusIdx = recoData.getTPCTracksClusterRefs(); mTPCClusterIdxStruct = &recoData.inputsTPCclusters->clusterIndex; mTPCRefitterShMap = recoData.clusterShMapTPC; - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, o2::base::Propagator::Instance()->getNominalBz(), mTPCTrackClusIdx.data(), mTPCRefitterShMap.data(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, o2::base::Propagator::Instance()->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), nullptr, nullptr, o2::base::Propagator::Instance()); } std::unordered_map> tmap; diff --git a/GPU/GPUTracking/DataTypes/GPUTPCClusterOccupancyMap.cxx b/GPU/GPUTracking/DataTypes/GPUTPCClusterOccupancyMap.cxx index b0ea414f9ff87..96c288d86b23d 100644 --- a/GPU/GPUTracking/DataTypes/GPUTPCClusterOccupancyMap.cxx +++ b/GPU/GPUTracking/DataTypes/GPUTPCClusterOccupancyMap.cxx @@ -19,6 +19,9 @@ using namespace GPUCA_NAMESPACE::gpu; GPUd() unsigned int GPUTPCClusterOccupancyMapBin::getNBins(const GPUParam& param) { + if (param.rec.tpc.occupancyMapTimeBins == 0) { + return 0; + } unsigned int maxTimeBin = param.par.continuousTracking ? param.par.continuousMaxTimeBin : TPC_MAX_TIME_BIN_TRIGGERED; return (maxTimeBin + param.rec.tpc.occupancyMapTimeBins) / param.rec.tpc.occupancyMapTimeBins; // Not -1, since maxTimeBin is allowed } diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 92ead6858c85e..cb4d0ed729069 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -47,7 +47,7 @@ AddOptionRTC(clusterError2AdditionalZ, float, 0.f, "", 0, "correction (additive) AddOptionRTC(clusterRejectChi2TolleranceY, float, 1.f, "", 0, "Multiplicative factor multiplied onto chi2 in Y direction for cluster rejection check during track fit") AddOptionRTC(clusterRejectChi2TolleranceZ, float, 1.f, "", 0, "Multiplicative factor multiplied onto chi2 in Z direction for cluster rejection check during track fit") AddOptionRTC(clusterErrorOccupancyScaler, float, 0.f, "", 0, "Scaling factor applied to occupancy histogram bin in cluster error estimation") -AddOptionRTC(clusterErrorChargeScaler, float, 0.f, "", 0, "Scaling factor applied to cluster charge bin in cluster error estimation") +AddOptionRTC(clusterErrorChargeScaler, float, 0.f, "", 0, "Scaling factor applied to cluster charge in cluster error estimation") AddOptionRTC(sysClusErrorNormIFCCE, float, 1.f, "", 0, "Systematic cluster error parameterization IFCCE clInner[0]") AddOptionRTC(sysClusErrorSlopeIFCCE, float, 1.f / 5.f, "", 0, "Systematic cluster error parameterization IFCCE clInner[1]") AddOptionRTC(sysClusErrorIFCCEZRegion, float, -5.f, "", 0, "Systematic cluster error parameterization IFCCE z Region") diff --git a/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx b/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx index ca6d0dd970e27..0df42e20ac77f 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx @@ -146,23 +146,26 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() } int streamOccMap = mRec->NStreams() - 1; - if (param().rec.tpc.occupancyMapTimeBins) { + if (param().rec.tpc.occupancyMapTimeBins || param().rec.tpc.sysClusErrorC12Norm) { AllocateRegisteredMemory(mInputsHost->mResourceOccupancyMap, mSubOutputControls[GPUTrackingOutputs::getIndex(&GPUTrackingOutputs::tpcOccupancyMap)]); + } + if (param().rec.tpc.occupancyMapTimeBins) { ReleaseEvent(mEvents->init); - auto* ptr = doGPU ? mInputsShadow->mTPCClusterOccupancyMap : mInputsHost->mTPCClusterOccupancyMap; + unsigned int* ptr = doGPU ? mInputsShadow->mTPCClusterOccupancyMap : mInputsHost->mTPCClusterOccupancyMap; auto* ptrTmp = (GPUTPCClusterOccupancyMapBin*)mRec->AllocateVolatileMemory(GPUTPCClusterOccupancyMapBin::getTotalSize(param()), doGPU); runKernel(GetGridAutoStep(streamOccMap, RecoStep::TPCSliceTracking), ptrTmp, GPUTPCClusterOccupancyMapBin::getTotalSize(param())); runKernel(GetGridBlk(GPUCA_NSLICES * GPUCA_ROW_COUNT, streamOccMap), ptrTmp); - runKernel(GetGridBlk(GPUTPCClusterOccupancyMapBin::getNBins(param()), streamOccMap), ptrTmp, ptr); + runKernel(GetGridBlk(GPUTPCClusterOccupancyMapBin::getNBins(param()), streamOccMap), ptrTmp, ptr + 1); mRec->ReturnVolatileMemory(); if (doGPU) { - TransferMemoryResourceLinkToHost(RecoStep::TPCSliceTracking, mInputsHost->mResourceOccupancyMap, streamOccMap, &mEvents->init); + GPUMemCpy(RecoStep::TPCSliceTracking, mInputsHost->mTPCClusterOccupancyMap + 1, mInputsShadow->mTPCClusterOccupancyMap + 1, sizeof(*ptr) * GPUTPCClusterOccupancyMapBin::getNBins(mRec->GetParam()), streamOccMap, false, &mEvents->init); } else { TransferMemoryResourceLinkToGPU(RecoStep::TPCSliceTracking, mInputsHost->mResourceOccupancyMap, streamOccMap, &mEvents->init); } } - unsigned int occupancyTotal = CAMath::Float2UIntRn(mRec->MemoryScalers()->nTPCHits / (mIOPtrs.settingsTF && mIOPtrs.settingsTF->hasNHBFPerTF ? mIOPtrs.settingsTF->nHBFPerTF : 128)); - mRec->UpdateParamOccupancyMap(param().rec.tpc.occupancyMapTimeBins ? mInputsHost->mTPCClusterOccupancyMap : nullptr, param().rec.tpc.occupancyMapTimeBins ? mInputsShadow->mTPCClusterOccupancyMap : nullptr, occupancyTotal, streamOccMap); + unsigned int& occupancyTotal = *mInputsHost->mTPCClusterOccupancyMap; + occupancyTotal = CAMath::Float2UIntRn(mRec->MemoryScalers()->nTPCHits / (mIOPtrs.settingsTF && mIOPtrs.settingsTF->hasNHBFPerTF ? mIOPtrs.settingsTF->nHBFPerTF : 128)); + mRec->UpdateParamOccupancyMap(param().rec.tpc.occupancyMapTimeBins ? mInputsHost->mTPCClusterOccupancyMap + 1 : nullptr, param().rec.tpc.occupancyMapTimeBins ? mInputsShadow->mTPCClusterOccupancyMap + 1 : nullptr, occupancyTotal, streamOccMap); int streamMap[NSLICES]; diff --git a/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx b/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx index bd066ce100a36..cb0dc7cfe698c 100644 --- a/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx +++ b/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx @@ -79,7 +79,7 @@ void* GPUTrackingInputProvider::SetPointersInputTRD(void* mem) void* GPUTrackingInputProvider::SetPointersTPCOccupancyMap(void* mem) { if (mHoldTPCOccupancyMap) { - computePointerWithAlignment(mem, mTPCClusterOccupancyMap, GPUTPCClusterOccupancyMapBin::getNBins(mRec->GetParam())); + computePointerWithAlignment(mem, mTPCClusterOccupancyMap, (mRec->GetParam().rec.tpc.occupancyMapTimeBins ? GPUTPCClusterOccupancyMapBin::getNBins(mRec->GetParam()) : 0) + 1); // +1 for total occupancy estimator } return mem; } @@ -99,6 +99,6 @@ void GPUTrackingInputProvider::SetMaxData(const GPUTrackingInOutPointers& io) { mHoldTPCZS = io.tpcZS && (mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCClusterFinding); mHoldTPCClusterNative = (io.tpcZS || io.tpcPackedDigits || io.clustersNative || io.tpcCompressedClusters) && (mRec->IsGPU() || io.tpcCompressedClusters); - mHoldTPCOccupancyMap = (io.tpcZS || io.tpcPackedDigits || io.clustersNative || io.tpcCompressedClusters) && mRec->GetParam().rec.tpc.occupancyMapTimeBins; + mHoldTPCOccupancyMap = (io.tpcZS || io.tpcPackedDigits || io.clustersNative || io.tpcCompressedClusters) && (mRec->GetParam().rec.tpc.occupancyMapTimeBins || mRec->GetParam().rec.tpc.sysClusErrorC12Norm); mHoldTPCClusterNativeOutput = io.tpcZS || io.tpcPackedDigits || io.tpcCompressedClusters; } diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx index 5f1edc1a30fcb..11ffbcffa3b30 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx @@ -23,7 +23,7 @@ using namespace o2::gpu; using namespace o2::tpc; -void GPUO2InterfaceRefit::fillSharedClustersMap(const ClusterNativeAccess* cl, const gsl::span trks, const TPCClRefElem* trackRef, unsigned char* shmap) +void GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(const ClusterNativeAccess* cl, const gsl::span trks, const TPCClRefElem* trackRef, unsigned char* shmap, unsigned int* ocmap, unsigned int nHbfPerTf, const GPUParam* param) { if (!cl || (!shmap && cl->nClustersTotal > 0)) { throw std::runtime_error("Must provide clusters access and preallocated recepient for shared map"); @@ -38,9 +38,16 @@ void GPUO2InterfaceRefit::fillSharedClustersMap(const ClusterNativeAccess* cl, c for (unsigned int i = 0; i < cl->nClustersTotal; i++) { shmap[i] = (shmap[i] > 1 ? GPUTPCGMMergedTrackHit::flagShared : 0) | cl->clustersLinear[i].getFlags(); } + if (ocmap && param) { + } +} + +size_t GPUO2InterfaceRefit::fillOccupancyMapGetSize(unsigned int nHbfPerTf) +{ + return 0; } -GPUO2InterfaceRefit::GPUO2InterfaceRefit(const ClusterNativeAccess* cl, const CorrectionMapsHelper* trans, float bzNominalGPU, const TPCClRefElem* trackRef, const unsigned char* sharedmap, const std::vector* trks, o2::base::Propagator* p) : mParam(new GPUParam) +GPUO2InterfaceRefit::GPUO2InterfaceRefit(const ClusterNativeAccess* cl, const CorrectionMapsHelper* trans, float bzNominalGPU, const TPCClRefElem* trackRef, unsigned int nHbfPerTf, const unsigned char* sharedmap, const unsigned int* occupancymap, const std::vector* trks, o2::base::Propagator* p) : mParam(new GPUParam) { if (cl->nClustersTotal) { if (sharedmap == nullptr && trks == nullptr) { @@ -49,11 +56,17 @@ GPUO2InterfaceRefit::GPUO2InterfaceRefit(const ClusterNativeAccess* cl, const Co if (sharedmap == nullptr) { mSharedMap.resize(cl->nClustersTotal); sharedmap = mSharedMap.data(); - fillSharedClustersMap(cl, *trks, trackRef, mSharedMap.data()); + fillSharedClustersAndOccupancyMap(cl, *trks, trackRef, mSharedMap.data()); } } mRefit = std::make_unique(); mParam->SetDefaults(bzNominalGPU); + if (occupancymap) { + mParam->occupancyTotal = *occupancymap; + if (mParam->rec.tpc.occupancyMapTimeBins) { + mParam->occupancyMap = occupancymap + 1; + } + } mRefit->SetGPUParam(mParam.get()); mRefit->SetClusterStateArray(sharedmap); mRefit->SetPropagator(p); diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index e6805ade1377f..3470dd674ce9b 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -68,8 +68,9 @@ class GPUO2InterfaceRefit // - In any case: Cluster Native access structure (cl), TPC Fast Transformation helper instance (trans), solenoid field (bz), TPC Track hit references (trackRef) // - Either the shared cluster map (sharedmap) or the vector of tpc tracks (trks) to build the shared cluster map internally // - o2::base::Propagator (p) in case RefitTrackAsTrackParCov is to be used + // - In case the --configKeyValues defining GPUParam settings require an occupancy map for TPC error estimation, the map must either be provided as occupancymap, or nHbfPerTf must be set non-zero - GPUO2InterfaceRefit(const o2::tpc::ClusterNativeAccess* cl, const o2::gpu::CorrectionMapsHelper* trans, float bzNominalGPU, const o2::tpc::TPCClRefElem* trackRef, const unsigned char* sharedmap = nullptr, const std::vector* trks = nullptr, o2::base::Propagator* p = nullptr); + GPUO2InterfaceRefit(const o2::tpc::ClusterNativeAccess* cl, const o2::gpu::CorrectionMapsHelper* trans, float bzNominalGPU, const o2::tpc::TPCClRefElem* trackRef, unsigned int nHbfPerTf = 0, const unsigned char* sharedmap = nullptr, const unsigned int* occupancymap = nullptr, const std::vector* trks = nullptr, o2::base::Propagator* p = nullptr); ~GPUO2InterfaceRefit(); int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false); @@ -81,7 +82,12 @@ class GPUO2InterfaceRefit void setIgnoreErrorsAtTrackEnds(bool v); void updateCalib(const o2::gpu::CorrectionMapsHelper* trans, float bzNominalGPU); - static void fillSharedClustersMap(const o2::tpc::ClusterNativeAccess* cl, const gsl::span trks, const o2::tpc::TPCClRefElem* trackRef, unsigned char* shmap); + // To create shared cluster maps and occupancy maps. + // param is an optional parameter to override the param object, by default a default object from --configKeyValues is used. + // If the param object / default object requires an occupancy map, an occupancy map ptr and nHbfPerTf value must be provided. + // You can use the function fillOccupancyMapGetSize(...) to get the required size of the occupancy map. If 0 is returned, no map is required. + static void fillSharedClustersAndOccupancyMap(const o2::tpc::ClusterNativeAccess* cl, const gsl::span trks, const o2::tpc::TPCClRefElem* trackRef, unsigned char* shmap, unsigned int* ocmap = nullptr, unsigned int nHbfPerTf = 0, const GPUParam* param = nullptr); + static size_t fillOccupancyMapGetSize(unsigned int nHbfPerTf); private: std::unique_ptr mRefit; diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index 9cb0a485f99ff..c66a0e07297c1 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -249,9 +249,13 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) int lastSector = -1, currentSector = -1, currentRow = -1; short clusterState = 0, nextState = 0; int nFitted = 0; + float sumInvSqrtCharge = 0.f; + int nAvgCharge = 0; + for (int i = start; i != stop; i += cl ? 0 : direction) { float x = 0, y = 0, z = 0, charge = 0; // FIXME: initialization unneeded, but GCC incorrectly produces uninitialized warnings otherwise int clusters = 0; + float time, invCharge, invSqrtCharge; while (true) { if (!cl) { CADEBUG(ii = i); @@ -292,6 +296,9 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) currentSector = sector; charge = cl->qTot; clusterState = nextState; + time = cl->getTime(); + invSqrtCharge = CAMath::InvSqrt(cl->qMax); + invCharge = (1.f / cl->qMax); } else { float xx, yy, zz; mPfastTransformHelper->Transform(sector, row, cl->getPad(), cl->getTime(), xx, yy, zz, tOffset); @@ -320,6 +327,9 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) CADEBUG(printf("\tMerged Hit Row %3d: Cluster Alpha %8.3f %3d, X %8.3f - Y %8.3f, Z %8.3f - State %d\n", row, mPparam->Alpha(sector), (int)sector, x, y, z, (int)clusterState)); } + float invAvgCharge = (sumInvSqrtCharge += invSqrtCharge) / ++nAvgCharge; + invAvgCharge *= invAvgCharge; + if constexpr (std::is_same_v) { if (prop.PropagateToXAlpha(x, mPparam->Alpha(currentSector), !outward)) { IgnoreErrors(trk.GetSinPhi()); @@ -341,7 +351,7 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) } CADEBUG(printf("\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", prop.GetAlpha(), x, trk.Par()[0], trk.Par()[1], trk.Par()[4], prop.GetQPt0(), trk.Par()[2], prop.GetSinPhi0(), trk.Par()[0] - y, trk.Par()[1] - z, sqrtf(trk.Cov()[0]), sqrtf(trk.Cov()[2]), sqrtf(trk.Cov()[5]), sqrtf(trk.Cov()[14]), trk.Cov()[10])); lastSector = sector; - if (prop.Update(y, z, row, *mPparam, clusterState, 0, nullptr, true, sector, -1.f, 0.f, 0.f)) { // TODO: Use correct time, avgCharge + if (prop.Update(y, z, row, *mPparam, clusterState, 0, nullptr, true, sector, time, invAvgCharge, invCharge)) { IgnoreErrors(trk.GetSinPhi()); return -3; } @@ -374,7 +384,7 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) CADEBUG(printf("\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", trk.getAlpha(), x, trk.getParams()[0], trk.getParams()[1], trk.getParams()[4], trk.getParams()[4], trk.getParams()[2], trk.getParams()[2], trk.getParams()[0] - y, trk.getParams()[1] - z, sqrtf(trk.getCov()[0]), sqrtf(trk.getCov()[2]), sqrtf(trk.getCov()[5]), sqrtf(trk.getCov()[14]), trk.getCov()[10])); gpu::gpustd::array p = {y, z}; gpu::gpustd::array c = {0, 0, 0}; - GPUTPCGMPropagator::GetErr2(c[0], c[2], *mPparam, getPar(trk)[2], getPar(trk)[3], z, x, y, currentRow, clusterState, sector, -1.f, 0.f, 0.f, false); // Use correct time / avergage cluster charge + GPUTPCGMPropagator::GetErr2(c[0], c[2], *mPparam, getPar(trk)[2], getPar(trk)[3], z, x, y, currentRow, clusterState, sector, time, invAvgCharge, invCharge, false); TrackParCovChi2 += trk.getPredictedChi2(p, c); if (!trk.update(p, c)) { IgnoreErrors(trk.getSnp()); diff --git a/macro/runTPCRefit.C b/macro/runTPCRefit.C index ab1b141d86143..fa5af2eb6fda0 100644 --- a/macro/runTPCRefit.C +++ b/macro/runTPCRefit.C @@ -87,7 +87,7 @@ int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc std::cout << "Error reading clusters (code " << retVal << ")\n"; return 1; } - GPUO2InterfaceRefit refit(&clusterIndex, &transHelper, bz, trackHitRefs->data(), nullptr, tracks, prop); + GPUO2InterfaceRefit refit(&clusterIndex, &transHelper, bz, trackHitRefs->data(), 0, nullptr, nullptr, tracks, prop); //refit.setGPUTrackFitInProjections(false); // Enable full 3D fit without assuming y and Z are uncorrelated for (unsigned int i = 0; i < tracks->size(); i++) { TrackTPC trk = (*tracks)[i]; From ac908718f02f0bb5b568b04fc126e03eee580793 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 2 Apr 2024 23:21:59 +0200 Subject: [PATCH 0056/2997] Propagate/use TPC occupancy histo via RecoContainer --- .../DataFormatsGlobalTracking/RecoContainer.h | 3 +- .../GlobalTracking/src/RecoContainer.cxx | 10 ++++- .../include/GlobalTracking/MatchTOF.h | 1 + .../include/GlobalTracking/MatchTPCITS.h | 1 + Detectors/GlobalTracking/src/MatchCosmics.cxx | 3 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 3 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 4 +- .../study/src/TPCTrackStudy.cxx | 4 +- .../TPCCalibration/CalibPadGainTracks.h | 5 ++- .../calibration/src/CalibPadGainTracks.cxx | 9 ++--- .../TPCWorkflow/TPCCalibPadGainTracksSpec.h | 38 ++++++++++--------- .../workflow/src/ClusterSharingMapSpec.cxx | 5 ++- .../TPC/workflow/src/FileReaderWorkflow.cxx | 7 +++- Detectors/TPC/workflow/src/TPCRefitter.cxx | 4 +- .../workflow/src/TRDGlobalTrackingSpec.cxx | 2 +- .../include/DetectorsVertexing/SVertexer.h | 1 + Detectors/Vertexing/src/SVertexer.cxx | 3 +- 17 files changed, 66 insertions(+), 37 deletions(-) diff --git a/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h b/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h index a766b7d72bd9d..3f063c8b8509d 100644 --- a/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h +++ b/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h @@ -340,6 +340,7 @@ struct RecoContainer { o2::ctp::LumiInfo mCTPLumi; gsl::span clusterShMapTPC; ///< externally set TPC clusters sharing map + gsl::span occupancyMapTPC; ///< externally set TPC clusters occupancy map std::unique_ptr inputsTPCclusters; // special struct for TPC clusters access std::unique_ptr inputsTRD; // special struct for TRD tracklets, trigger records @@ -371,7 +372,7 @@ struct RecoContainer { void addITSClusters(o2::framework::ProcessingContext& pc, bool mc); void addMFTClusters(o2::framework::ProcessingContext& pc, bool mc); - void addTPCClusters(o2::framework::ProcessingContext& pc, bool mc, bool shmap); + void addTPCClusters(o2::framework::ProcessingContext& pc, bool mc, bool shmap, bool occmap); void addTPCTriggers(o2::framework::ProcessingContext& pc); void addTOFClusters(o2::framework::ProcessingContext& pc, bool mc); void addHMPClusters(o2::framework::ProcessingContext& pc, bool mc); diff --git a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx index fdfdf1e18fd96..a79e2736dde60 100644 --- a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx +++ b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx @@ -119,6 +119,7 @@ void DataRequest::requestTPCTracks(bool mc) addInput({"trackTPCClRefs", "TPC", "CLUSREFS", 0, Lifetime::Timeframe}); if (requestMap.find("clusTPC") != requestMap.end()) { addInput({"clusTPCshmap", "TPC", "CLSHAREDMAP", 0, Lifetime::Timeframe}); + addInput({"clusTPCoccmap", "TPC", "TPCOCCUPANCYMAP", 0, Lifetime::Timeframe}); } if (mc) { addInput({"trackTPCMCTR", "TPC", "TRACKSMCLBL", 0, Lifetime::Timeframe}); @@ -255,6 +256,7 @@ void DataRequest::requestTPCClusters(bool mc) } if (requestMap.find("trackTPC") != requestMap.end()) { addInput({"clusTPCshmap", "TPC", "CLSHAREDMAP", 0, Lifetime::Timeframe}); + addInput({"clusTPCoccmap", "TPC", "TPCOCCUPANCYMAP", 0, Lifetime::Timeframe}); } if (mc) { addInput({"clusTPCMC", ConcreteDataTypeMatcher{"TPC", "CLNATIVEMCLBL"}, Lifetime::Timeframe}); @@ -678,7 +680,8 @@ void RecoContainer::collectData(ProcessingContext& pc, const DataRequest& reques req = reqMap.find("clusTPC"); if (req != reqMap.end()) { - addTPCClusters(pc, req->second, reqMap.find("trackTPC") != reqMap.end()); + auto tracksON = reqMap.find("trackTPC") != reqMap.end(); + addTPCClusters(pc, req->second, tracksON, tracksON); } req = reqMap.find("trigTPC"); @@ -1060,12 +1063,15 @@ void RecoContainer::addMFTClusters(ProcessingContext& pc, bool mc) } //__________________________________________________________ -void RecoContainer::addTPCClusters(ProcessingContext& pc, bool mc, bool shmap) +void RecoContainer::addTPCClusters(ProcessingContext& pc, bool mc, bool shmap, bool occmap) { inputsTPCclusters = o2::tpc::getWorkflowTPCInput(pc, 0, mc); if (shmap) { clusterShMapTPC = pc.inputs().get>("clusTPCshmap"); } + if (occmap) { + occupancyMapTPC = pc.inputs().get>("clusTPCoccmap"); + } } //__________________________________________________________ diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h index 879fb7f8049b1..0d0e2f40f5fbb 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h @@ -287,6 +287,7 @@ class MatchTOF /// data needed for refit of time-constrained TPC tracks gsl::span mTPCTrackClusIdx; ///< input TPC track cluster indices span gsl::span mTPCRefitterShMap; ///< externally set TPC clusters sharing map + gsl::span mTPCRefitterOccMap; ///< externally set TPC clusters occupancy map const o2::tpc::ClusterNativeAccess* mTPCClusterIdxStruct = nullptr; ///< struct holding the TPC cluster indices o2::gpu::CorrectionMapsHelper* mTPCCorrMapsHelper = nullptr; ///< TPC cluster transformation diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index 190a00ce4f3bc..a2cb21bdaf04f 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -636,6 +636,7 @@ class MatchTPCITS gsl::span mFITInfo; ///< optional input FIT info span gsl::span mTPCRefitterShMap; ///< externally set TPC clusters sharing map + gsl::span mTPCRefitterOccMap; ///< externally set TPC clusters occupancy map const o2::itsmft::TopologyDictionary* mITSDict{nullptr}; // cluster patterns dictionary diff --git a/Detectors/GlobalTracking/src/MatchCosmics.cxx b/Detectors/GlobalTracking/src/MatchCosmics.cxx index ac07b24ed622f..bc10fe1c2725b 100644 --- a/Detectors/GlobalTracking/src/MatchCosmics.cxx +++ b/Detectors/GlobalTracking/src/MatchCosmics.cxx @@ -89,12 +89,13 @@ void MatchCosmics::refitWinners(const o2::globaltracking::RecoContainer& data) auto tpcTBinMUSInv = 1. / mTPCTBinMUS; const auto& tpcClusRefs = data.getTPCTracksClusterRefs(); const auto& tpcClusShMap = data.clusterShMapTPC; + const auto& tpcClusOccMap = data.occupancyMapTPC; std::unique_ptr tpcRefitter; if (data.inputsTPCclusters) { tpcRefitter = std::make_unique(&data.inputsTPCclusters->clusterIndex, mTPCCorrMapsHelper, mBz, tpcClusRefs.data(), 0, tpcClusShMap.data(), - nullptr, nullptr, o2::base::Propagator::Instance()); + tpcClusOccMap.data(), nullptr, o2::base::Propagator::Instance()); } const auto& itsClusters = prepareITSClusters(data); diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 3c4dfe60a0139..ce113ecaa673e 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -490,6 +490,7 @@ bool MatchTOF::prepareTPCData() mTPCTracksArray = mRecoCont->getTPCTracks(); mTPCTrackClusIdx = mRecoCont->getTPCTracksClusterRefs(); mTPCRefitterShMap = mRecoCont->clusterShMapTPC; + mTPCRefitterOccMap = mRecoCont->occupancyMapTPC; } return true; @@ -1798,6 +1799,6 @@ void MatchTOF::checkRefitter() if (mTPCClusterIdxStruct) { mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), - nullptr, nullptr, o2::base::Propagator::Instance()); + mTPCRefitterOccMap.data(), nullptr, o2::base::Propagator::Instance()); } } diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 555421cae1448..0e7700928b0e3 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -467,6 +467,8 @@ bool MatchTPCITS::prepareTPCData() mTPCTrackClusIdx = inp.getTPCTracksClusterRefs(); mTPCClusterIdxStruct = &inp.inputsTPCclusters->clusterIndex; mTPCRefitterShMap = inp.clusterShMapTPC; + mTPCRefitterOccMap = inp.occupancyMapTPC; + if (mMCTruthON) { mTPCTrkLabels = inp.getTPCTracksMCLabels(); } @@ -572,7 +574,7 @@ bool MatchTPCITS::prepareTPCData() mITSROFofTPCBin[ib] = itsROF; } */ - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), nullptr, nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), nullptr, o2::base::Propagator::Instance()); mInteractionMUSLUT.clear(); mInteractionMUSLUT.resize(maxTime + 3 * o2::constants::lhc::LHCOrbitMUS, -1); mTimer[SWPrepTPC].Stop(); diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx index 9e1bb1804c4e5..6c51525e67d6a 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx @@ -87,6 +87,7 @@ class TPCTrackStudySpec : public Task gsl::span mTPCTrackClusIdx; ///< input TPC track cluster indices span gsl::span mTPCTracksArray; ///< input TPC tracks span gsl::span mTPCRefitterShMap; ///< externally set TPC clusters sharing map + gsl::span mTPCRefitterOccMap; ///< externally set TPC clusters occupancy map const o2::tpc::ClusterNativeAccess* mTPCClusterIdxStruct = nullptr; ///< struct holding the TPC cluster indices gsl::span mTPCTrkLabels; ///< input TPC Track MC labels std::unique_ptr mTPCRefitter; ///< TPC refitter used for TPC tracks refit during the reconstruction @@ -169,6 +170,7 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) mTPCTrackClusIdx = recoData.getTPCTracksClusterRefs(); mTPCClusterIdxStruct = &recoData.inputsTPCclusters->clusterIndex; mTPCRefitterShMap = recoData.clusterShMapTPC; + mTPCRefitterOccMap = recoData.occupancyMapTPC; std::vector intRecs; if (mUseMC) { // extract MC tracks @@ -181,7 +183,7 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) mTPCTrkLabels = recoData.getTPCTracksMCLabels(); } - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), nullptr, nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), nullptr, o2::base::Propagator::Instance()); float vdriftTB = mTPCVDriftHelper.getVDriftObject().getVDrift() * o2::tpc::ParameterElectronics::Instance().ZbinWidth; // VDrift expressed in cm/TimeBin float tpcTBBias = mTPCVDriftHelper.getVDriftObject().getTimeOffset() / (8 * o2::constants::lhc::LHCBunchSpacingMUS); diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CalibPadGainTracks.h b/Detectors/TPC/calibration/include/TPCCalibration/CalibPadGainTracks.h index 827beb7a51263..b3fd532c06b8e 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CalibPadGainTracks.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CalibPadGainTracks.h @@ -104,7 +104,7 @@ class CalibPadGainTracks : public CalibPadGainTracksBase /// \param vTPCTracksArrayInp vector of tpc tracks /// \param tpcTrackClIdxVecInput set the TPCClRefElem member variable /// \param clIndex set the ClusterNativeAccess member variable - void setMembers(gsl::span* vTPCTracksArrayInp, gsl::span* tpcTrackClIdxVecInput, const o2::tpc::ClusterNativeAccess& clIndex); + void setMembers(gsl::span* vTPCTracksArrayInp, gsl::span* tpcTrackClIdxVecInput, const o2::tpc::ClusterNativeAccess& clIndex, gsl::span TPCRefitterShMap, gsl::span TPCRefitterOccMap); /// this function sets the mode of the class. /// e.g. mode=0 -> use the truncated mean from the track for normalizing the dedx @@ -220,8 +220,9 @@ class CalibPadGainTracks : public CalibPadGainTracksBase gsl::span* mTracks{nullptr}; ///* mTPCTrackClIdxVecInput{nullptr}; /// mTPCRefitterShMap; /// mTPCRefitterOccMap; /// mBufVec; /// refit; if (!mPropagateTrack) { - mBufVec.resize(mClusterIndex->nClustersTotal); - o2::gpu::GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(mClusterIndex, *mTracks, mTPCTrackClIdxVecInput->data(), mBufVec.data()); - mClusterShMapTPC = mBufVec.data(); - refit = std::make_unique(mClusterIndex, mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), 0, mClusterShMapTPC); + refit = std::make_unique(mClusterIndex, mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data()); } const size_t loopEnd = (nMaxTracks < 0) ? mTracks->size() : ((nMaxTracks > mTracks->size()) ? mTracks->size() : size_t(nMaxTracks)); @@ -310,11 +307,13 @@ void CalibPadGainTracks::dumpToFile(const char* outFileName, const char* outName fOut.Close(); } -void CalibPadGainTracks::setMembers(gsl::span* vTPCTracksArrayInp, gsl::span* tpcTrackClIdxVecInput, const o2::tpc::ClusterNativeAccess& clIndex) +void CalibPadGainTracks::setMembers(gsl::span* vTPCTracksArrayInp, gsl::span* tpcTrackClIdxVecInput, const o2::tpc::ClusterNativeAccess& clIndex, gsl::span TPCRefitterShMap, gsl::span TPCRefitterOccMap) { mTracks = vTPCTracksArrayInp; mTPCTrackClIdxVecInput = tpcTrackClIdxVecInput; mClusterIndex = &clIndex; + mTPCRefitterShMap = TPCRefitterShMap; + mTPCRefitterOccMap = TPCRefitterOccMap; } void CalibPadGainTracks::setMomentumRange(const float momMin, const float momMax) diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPadGainTracksSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPadGainTracksSpec.h index da0a302125760..7afc973d7a3ab 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPadGainTracksSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPadGainTracksSpec.h @@ -30,7 +30,7 @@ #include "TPCCalibration/CorrectionMapsLoader.h" #include "DetectorsBase/GRPGeomHelper.h" #include "GPUO2InterfaceUtils.h" - +#include "DataFormatsGlobalTracking/RecoContainer.h" #include using namespace o2::framework; @@ -45,7 +45,7 @@ namespace tpc class TPCCalibPadGainTracksDevice : public o2::framework::Task { public: - TPCCalibPadGainTracksDevice(std::shared_ptr req, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts, const uint32_t publishAfterTFs, const bool debug, const bool useLastExtractedMapAsReference, const std::string polynomialsFile, const bool disablePolynomialsCCDB) : mPublishAfter(publishAfterTFs), mDebug(debug), mUseLastExtractedMapAsReference(useLastExtractedMapAsReference), mDisablePolynomialsCCDB(disablePolynomialsCCDB), mCCDBRequest(req) + TPCCalibPadGainTracksDevice(std::shared_ptr dr, std::shared_ptr req, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts, const uint32_t publishAfterTFs, const bool debug, const bool useLastExtractedMapAsReference, const std::string polynomialsFile, const bool disablePolynomialsCCDB) : mDataRequest(dr), mPublishAfter(publishAfterTFs), mDebug(debug), mUseLastExtractedMapAsReference(useLastExtractedMapAsReference), mDisablePolynomialsCCDB(disablePolynomialsCCDB), mCCDBRequest(req) { if (!polynomialsFile.empty()) { LOGP(info, "Loading polynomials from file {}", polynomialsFile); @@ -167,10 +167,12 @@ class TPCCalibPadGainTracksDevice : public o2::framework::Task return; } o2::base::GRPGeomHelper::instance().checkUpdates(pc); + o2::globaltracking::RecoContainer recoData; + recoData.collectData(pc, *mDataRequest.get()); - auto tracks = pc.inputs().get>("trackTPC"); - auto clRefs = pc.inputs().get>("trackTPCClRefs"); - const auto& clusters = getWorkflowTPCInput(pc); + auto tracks = recoData.getTPCTracks(); + auto clRefs = recoData.getTPCTracksClusterRefs(); + const auto& clusters = recoData.inputsTPCclusters; const auto nTracks = tracks.size(); if (nTracks == 0) { return; @@ -206,7 +208,7 @@ class TPCCalibPadGainTracksDevice : public o2::framework::Task mTPCCorrMapsLoader.updateVDrift(mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift, mTPCVDriftHelper.getVDriftObject().getTimeOffset()); } - mPadGainTracks.setMembers(&tracks, &clRefs, clusters->clusterIndex); + mPadGainTracks.setMembers(&tracks, &clRefs, clusters->clusterIndex, recoData.clusterShMapTPC, recoData.occupancyMapTPC); mPadGainTracks.processTracks(mMaxTracksPerTF); ++mProcessedTFs; if ((mFirstTFSend == mProcessedTFs) || (mPublishAfter && (mProcessedTFs % mPublishAfter) == 0)) { @@ -225,6 +227,7 @@ class TPCCalibPadGainTracksDevice : public o2::framework::Task const bool mDebug{false}; ///< create debug output const bool mUseLastExtractedMapAsReference{false}; ///< using the last extracted gain map as the reference map which will be applied bool mDisablePolynomialsCCDB{false}; ///< do not load the polynomials from the CCDB + std::shared_ptr mDataRequest; ///< reco container data request std::shared_ptr mCCDBRequest; ///< for accessing the b-field uint32_t mProcessedTFs{0}; ///< counter to keep track of the processed TFs uint32_t mTFCounter{0}; ///< counter to keep track of the TFs @@ -246,11 +249,12 @@ class TPCCalibPadGainTracksDevice : public o2::framework::Task DataProcessorSpec getTPCCalibPadGainTracksSpec(const uint32_t publishAfterTFs, const bool debug, const bool useLastExtractedMapAsReference, const std::string polynomialsFile, bool disablePolynomialsCCDB, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts) { std::vector inputs; - inputs.emplace_back("trackTPC", gDataOriginTPC, "TRACKS", 0, Lifetime::Timeframe); - inputs.emplace_back("trackTPCClRefs", gDataOriginTPC, "CLUSREFS", 0, Lifetime::Timeframe); - inputs.emplace_back("clusTPC", ConcreteDataTypeMatcher{gDataOriginTPC, "CLUSTERNATIVE"}, Lifetime::Timeframe); + auto dataRequest = std::make_shared(); + dataRequest->requestTracks(o2::dataformats::GlobalTrackID::getSourceMask(o2::dataformats::GlobalTrackID::TPC), false); + dataRequest->requestClusters(o2::dataformats::GlobalTrackID::getSourceMask(o2::dataformats::GlobalTrackID::TPC), false); + if (sclOpts.lumiType == 1) { - inputs.emplace_back("CTPLumi", "CTP", "LUMI", 0, Lifetime::Timeframe); + dataRequest->inputs.emplace_back("CTPLumi", "CTP", "LUMI", 0, Lifetime::Timeframe); } if (!polynomialsFile.empty()) { @@ -258,14 +262,14 @@ DataProcessorSpec getTPCCalibPadGainTracksSpec(const uint32_t publishAfterTFs, c } if (!disablePolynomialsCCDB) { - inputs.emplace_back("tpctopologygain", gDataOriginTPC, "TOPOLOGYGAIN", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalTopologyGain))); + dataRequest->inputs.emplace_back("tpctopologygain", gDataOriginTPC, "TOPOLOGYGAIN", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalTopologyGain))); } if (useLastExtractedMapAsReference) { - inputs.emplace_back("tpcresidualgainmap", gDataOriginTPC, "RESIDUALGAINMAP", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalPadGainResidual))); + dataRequest->inputs.emplace_back("tpcresidualgainmap", gDataOriginTPC, "RESIDUALGAINMAP", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalPadGainResidual))); } - o2::tpc::VDriftHelper::requestCCDBInputs(inputs); + o2::tpc::VDriftHelper::requestCCDBInputs(dataRequest->inputs); Options opts{ {"nBins", VariantType::Int, 20, {"Number of bins per histogram"}}, {"reldEdxMin", VariantType::Int, 0, {"Minimum x coordinate of the histogram for Q/(dE/dx)"}}, @@ -288,7 +292,7 @@ DataProcessorSpec getTPCCalibPadGainTracksSpec(const uint32_t publishAfterTFs, c {"useEveryNthTF", VariantType::Int, 10, {"Using only a fraction of the data: 1: Use every TF, 10: Use only every tenth TF."}}, {"maxTracksPerTF", VariantType::Int, 10000, {"Maximum number of processed tracks per TF (-1 for processing all tracks)"}}, }; - o2::tpc::CorrectionMapsLoader::requestCCDBInputs(inputs, opts, sclOpts); + o2::tpc::CorrectionMapsLoader::requestCCDBInputs(dataRequest->inputs, opts, sclOpts); auto ccdbRequest = std::make_shared(false, // orbitResetTime false, // GRPECS=true @@ -296,16 +300,16 @@ DataProcessorSpec getTPCCalibPadGainTracksSpec(const uint32_t publishAfterTFs, c true, // GRPMagField true, // askMatLUT o2::base::GRPGeomRequest::None, // geometry - inputs); + dataRequest->inputs); std::vector outputs; outputs.emplace_back(gDataOriginTPC, "TRACKGAINHISTOS", 0, o2::framework::Lifetime::Sporadic); return DataProcessorSpec{ "calib-tpc-gainmap-tracks", - inputs, + dataRequest->inputs, outputs, - AlgorithmSpec{adaptFromTask(ccdbRequest, sclOpts, publishAfterTFs, debug, useLastExtractedMapAsReference, polynomialsFile, disablePolynomialsCCDB)}, + AlgorithmSpec{adaptFromTask(dataRequest, ccdbRequest, sclOpts, publishAfterTFs, debug, useLastExtractedMapAsReference, polynomialsFile, disablePolynomialsCCDB)}, opts}; // end DataProcessorSpec } diff --git a/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx b/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx index 2625e5dc2c6c6..b4a34ce040b99 100644 --- a/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx +++ b/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx @@ -38,8 +38,9 @@ void ClusterSharingMapSpec::run(ProcessingContext& pc) LOGP(info, "Will use {} HB per TF from GRPECS", nHBPerTF); } - auto& bufVec = pc.outputs().make>(Output{o2::header::gDataOriginTPC, "CLSHAREDMAP", 0}, clustersTPC->clusterIndex.nClustersTotal); - o2::gpu::GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(&clustersTPC->clusterIndex, tracksTPC, tracksTPCClRefs.data(), bufVec.data()); + auto& bufVecSh = pc.outputs().make>(Output{o2::header::gDataOriginTPC, "CLSHAREDMAP", 0}, clustersTPC->clusterIndex.nClustersTotal); + auto& bufVecOcc = pc.outputs().make>(Output{o2::header::gDataOriginTPC, "TPCOCCUPANCYMAP", 0}, 0u); + o2::gpu::GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(&clustersTPC->clusterIndex, tracksTPC, tracksTPCClRefs.data(), bufVecSh.data()); timer.Stop(); LOGF(info, "Timing for TPC clusters sharing map creation: Cpu: %.3e Real: %.3e s", timer.CpuTime(), timer.RealTime()); diff --git a/Detectors/TPC/workflow/src/FileReaderWorkflow.cxx b/Detectors/TPC/workflow/src/FileReaderWorkflow.cxx index 0d2b4a649dccb..a65b4ccdf3a6d 100644 --- a/Detectors/TPC/workflow/src/FileReaderWorkflow.cxx +++ b/Detectors/TPC/workflow/src/FileReaderWorkflow.cxx @@ -14,9 +14,9 @@ #include "TPCReaderWorkflow/ClusterReaderSpec.h" #include "TPCReaderWorkflow/TriggerReaderSpec.h" #include "TPCReaderWorkflow/TrackReaderSpec.h" +#include "TPCWorkflow/ClusterSharingMapSpec.h" #include "DetectorsRaw/HBFUtilsInitializer.h" #include "Framework/CallbacksPolicy.h" - #include "Algorithm/RangeTokenizer.h" #include "SimulationDataFormat/IOMCTruthContainerView.h" @@ -85,6 +85,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) specs.push_back(o2::tpc::getTPCTrackReaderSpec(doMC)); } + + if (isEnabled(InputType::Tracks) && isEnabled(InputType::Clusters)) { // create shared clusters and occupancy maps + specs.emplace_back(o2::tpc::getClusterSharingMapSpec()); + } + o2::raw::HBFUtilsInitializer hbfIni(cfgc, specs); return std::move(specs); } diff --git a/Detectors/TPC/workflow/src/TPCRefitter.cxx b/Detectors/TPC/workflow/src/TPCRefitter.cxx index 7a71305683d8c..0911f9dae3798 100644 --- a/Detectors/TPC/workflow/src/TPCRefitter.cxx +++ b/Detectors/TPC/workflow/src/TPCRefitter.cxx @@ -92,6 +92,7 @@ class TPCRefitterSpec final : public Task gsl::span mTPCTrackClusIdx; ///< input TPC track cluster indices span gsl::span mTPCTracksArray; ///< input TPC tracks span gsl::span mTPCRefitterShMap; ///< externally set TPC clusters sharing map + gsl::span mTPCRefitterOccMap; ///< externally set TPC clusters occupancy map const o2::tpc::ClusterNativeAccess* mTPCClusterIdxStruct = nullptr; ///< struct holding the TPC cluster indices gsl::span mTPCTrkLabels; ///< input TPC Track MC labels std::unique_ptr mTPCRefitter; ///< TPC refitter used for TPC tracks refit during the reconstruction @@ -177,6 +178,7 @@ void TPCRefitterSpec::process(o2::globaltracking::RecoContainer& recoData) mTPCTrackClusIdx = recoData.getTPCTracksClusterRefs(); mTPCClusterIdxStruct = &recoData.inputsTPCclusters->clusterIndex; mTPCRefitterShMap = recoData.clusterShMapTPC; + mTPCRefitterOccMap = recoData.occupancyMapTPC; std::vector intRecs; if (mUseMC) { // extract MC tracks @@ -189,7 +191,7 @@ void TPCRefitterSpec::process(o2::globaltracking::RecoContainer& recoData) mTPCTrkLabels = recoData.getTPCTracksMCLabels(); } - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), nullptr, nullptr, prop); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), nullptr, prop); float vdriftTB = mTPCVDriftHelper.getVDriftObject().getVDrift() * o2::tpc::ParameterElectronics::Instance().ZbinWidth; // VDrift expressed in cm/TimeBin float tpcTBBias = mTPCVDriftHelper.getVDriftObject().getTimeOffset() / (8 * o2::constants::lhc::LHCBunchSpacingMUS); diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index 665b5595adc5b..7215265b794eb 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -275,7 +275,7 @@ void TRDGlobalTracking::run(ProcessingContext& pc) mChainTracking->ClearIOPointers(); mTPCClusterIdxStruct = &inputTracks.inputsTPCclusters->clusterIndex; - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(), inputTracks.getTPCTracksClusterRefs().data(), 0, inputTracks.clusterShMapTPC.data(), nullptr, nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(), inputTracks.getTPCTracksClusterRefs().data(), 0, inputTracks.clusterShMapTPC.data(), inputTracks.occupancyMapTPC.data(), nullptr, o2::base::Propagator::Instance()); auto tmpInputContainer = getRecoInputContainer(pc, &mChainTracking->mIOPtrs, &inputTracks, mUseMC); auto tmpContainer = GPUWorkflowHelper::fillIOPtr(mChainTracking->mIOPtrs, inputTracks, mUseMC, nullptr, GTrackID::getSourcesMask("TRD"), mTrkMask, GTrackID::mask_t{GTrackID::MASK_NONE}); mTrackletsRaw = inputTracks.getTRDTracklets(); diff --git a/Detectors/Vertexing/include/DetectorsVertexing/SVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/SVertexer.h index 0d7453d96086a..9d0823a04e625 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/SVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/SVertexer.h @@ -172,6 +172,7 @@ class SVertexer gsl::span mTPCTracksArray; ///< input TPC tracks span gsl::span mTPCTrackClusIdx; ///< input TPC track cluster indices span gsl::span mTPCRefitterShMap; ///< externally set TPC clusters sharing map + gsl::span mTPCRefitterOccMap; ///< externally set TPC clusters occupancy map o2::gpu::CorrectionMapsHelper* mTPCCorrMapsHelper = nullptr; std::unique_ptr mTPCRefitter; ///< TPC refitter used for TPC tracks refit during the reconstruction o2::strangeness_tracking::StrangenessTracker* mStrTracker = nullptr; diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx index c7335f4ed0e73..2294c390eed1f 100644 --- a/Detectors/Vertexing/src/SVertexer.cxx +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -448,7 +448,8 @@ void SVertexer::buildT2V(const o2::globaltracking::RecoContainer& recoData) // a mTPCTrackClusIdx = recoData.getTPCTracksClusterRefs(); mTPCClusterIdxStruct = &recoData.inputsTPCclusters->clusterIndex; mTPCRefitterShMap = recoData.clusterShMapTPC; - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, o2::base::Propagator::Instance()->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), nullptr, nullptr, o2::base::Propagator::Instance()); + mTPCRefitterOccMap = mRecoCont->occupancyMapTPC; + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, o2::base::Propagator::Instance()->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), nullptr, o2::base::Propagator::Instance()); } std::unordered_map> tmap; From 96c9952303f7a3261179642a8e29fae744c99f86 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 3 Apr 2024 00:41:13 +0200 Subject: [PATCH 0057/2997] GPU Workflow: Clean up sending of empty dummy messages for missing outputs --- GPU/Workflow/src/GPUWorkflowSpec.cxx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/GPU/Workflow/src/GPUWorkflowSpec.cxx b/GPU/Workflow/src/GPUWorkflowSpec.cxx index 29e0f2313e28b..36ce6da419d4b 100644 --- a/GPU/Workflow/src/GPUWorkflowSpec.cxx +++ b/GPU/Workflow/src/GPUWorkflowSpec.cxx @@ -97,6 +97,7 @@ #include #include #include +#include using namespace o2::framework; using namespace o2::header; @@ -678,21 +679,23 @@ void GPURecoWorkflowSpec::run(ProcessingContext& pc) using outputBufferUninitializedVector = std::decay_t>(Output{"", "", 0}))>; using outputBufferType = std::pair>, outputDataType*>; std::vector outputBuffers(GPUInterfaceOutputs::count(), {std::nullopt, nullptr}); + std::unordered_set outputsCreated; - auto setOutputAllocator = [this, &outputBuffers, &outputRegions, &pc](const char* name, bool condition, GPUOutputControl& region, auto&& outputSpec, size_t offset = 0) { + auto setOutputAllocator = [this, &outputBuffers, &outputRegions, &pc, &outputsCreated](const char* name, bool condition, GPUOutputControl& region, auto&& outputSpec, size_t offset = 0) { if (condition) { auto& buffer = outputBuffers[outputRegions.getIndex(region)]; if (mConfParam->allocateOutputOnTheFly) { - region.allocator = [this, name, &buffer, &pc, outputSpec = std::move(outputSpec), offset](size_t size) -> void* { + region.allocator = [this, name, &buffer, &pc, outputSpec = std::move(outputSpec), offset, &outputsCreated](size_t size) -> void* { size += offset; if (mVerbosity) { - LOG(info) << "ALLOCATING " << size << " bytes for " << std::get(outputSpec).template as() << "/" << std::get(outputSpec).template as() << "/" << std::get<2>(outputSpec); + LOG(info) << "ALLOCATING " << size << " bytes for " << name << ": " << std::get(outputSpec).template as() << "/" << std::get(outputSpec).template as() << "/" << std::get<2>(outputSpec); } std::chrono::time_point start, end; if (mVerbosity) { start = std::chrono::high_resolution_clock::now(); } buffer.first.emplace(pc.outputs().make>(std::make_from_tuple(outputSpec), size)); + outputsCreated.insert(name); if (mVerbosity) { end = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed_seconds = end - start; @@ -705,6 +708,7 @@ void GPURecoWorkflowSpec::run(ProcessingContext& pc) buffer.first.emplace(pc.outputs().make>(std::make_from_tuple(outputSpec), mConfParam->outputBufferSize)); region.ptrBase = (buffer.second = buffer.first->get().data()) + offset; region.size = buffer.first->get().size() - offset; + outputsCreated.insert(name); } } }; @@ -842,10 +846,6 @@ void GPURecoWorkflowSpec::run(ProcessingContext& pc) } } - if (mConfig->configReconstruction.tpc.occupancyMapTimeBins == 0) { - pc.outputs().make>({gDataOriginTPC, "TPCOCCUPANCYMAP", 0}, 0u); - } - std::unique_ptr tmpEmptyClNative; if (createEmptyOutput) { memset(&ptrs, 0, sizeof(ptrs)); @@ -971,7 +971,10 @@ void GPURecoWorkflowSpec::run(ProcessingContext& pc) pc.outputs().snapshot({gDataOriginGPU, "ERRORQA", 0}, mErrorQA); mErrorQA.clear(); // FIXME: This is a race condition once we run multi-threaded! } - if (mSpecConfig.tpcTriggerHandling && !mSpecConfig.caClusterer) { + if (mSpecConfig.outputSharedClusterMap && !outputsCreated.contains("TPCOCCUPANCYMAP")) { + pc.outputs().make>({gDataOriginTPC, "TPCOCCUPANCYMAP", 0}, 0u); + } + if (mSpecConfig.tpcTriggerHandling && !outputsCreated.contains("TRIGGERWORDS")) { pc.outputs().make>(Output{gDataOriginTPC, "TRIGGERWORDS", 0}, 0u); } mTimer->Stop(); From 6d828521616f3d7a0eb7f6c67fb640c5b31dc5aa Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 3 Apr 2024 14:55:26 +0200 Subject: [PATCH 0058/2997] GPU Interface: Add unified function to obtain all GPU paramters from --configKeyValues --- .../Workflow/src/BarrelAlignmentSpec.cxx | 1 + .../TPC/workflow/src/EntropyEncoderSpec.cxx | 11 +----- GPU/GPUTracking/Base/GPUParam.cxx | 31 ++++++++-------- GPU/GPUTracking/Base/GPUParam.h | 1 + .../Interface/GPUO2InterfaceUtils.cxx | 36 +++++++++++++++++++ .../Interface/GPUO2InterfaceUtils.h | 3 ++ 6 files changed, 58 insertions(+), 25 deletions(-) diff --git a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx index 5c64b23315eb7..38ebed8fac9c6 100644 --- a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx +++ b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx @@ -38,6 +38,7 @@ #include "TPCCalibration/VDriftHelper.h" #include "TPCCalibration/CorrectionMapsLoader.h" #include "GPUO2Interface.h" +#include "GPUO2InterfaceUtils.h" #include "GPUParam.h" #include "Headers/DataHeader.h" #include "Framework/ConfigParamRegistry.h" diff --git a/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx b/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx index ca024c1e26f60..fc707f433c8c5 100644 --- a/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx +++ b/Detectors/TPC/workflow/src/EntropyEncoderSpec.cxx @@ -69,18 +69,9 @@ void EntropyEncoderSpec::init(o2::framework::InitContext& ic) mCTFCoder.init(ic); mCTFCoder.setCombineColumns(!ic.options().get("no-ctf-columns-combining")); - mConfig.reset(new o2::gpu::GPUO2InterfaceConfiguration); - mConfig->configGRP.solenoidBzNominalGPU = 0; - mConfParam.reset(new o2::gpu::GPUSettingsO2(mConfig->ReadConfigurableParam())); - mAutoContinuousMaxTimeBin = mConfig->configGRP.continuousMaxTimeBin == -1; - if (mAutoContinuousMaxTimeBin) { - mConfig->configGRP.continuousMaxTimeBin = (256 * o2::constants::lhc::LHCMaxBunches + 2 * o2::tpc::constants::LHCBCPERTIMEBIN - 2) / o2::tpc::constants::LHCBCPERTIMEBIN; - } - mFastTransform = std::move(TPCFastTransformHelperO2::instance()->create(0)); - mParam.reset(new o2::gpu::GPUParam); - mParam->SetDefaults(&mConfig->configGRP, &mConfig->configReconstruction, &mConfig->configProcessing, nullptr); + mParam = GPUO2InterfaceUtils::getFullParam(0.f, 0, &mConfig, &mConfParam, &mAutoContinuousMaxTimeBin); if (mSelIR) { mTPCVDriftHelper.reset(new VDriftHelper); diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index 3865010000566..5b9dcd7e82ebc 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -91,9 +91,7 @@ void GPUParam::SetDefaults(float solenoidBz) #endif par.dAlpha = 0.349066f; - bzkG = solenoidBz; - bzCLight = bzkG * GPUCA_NAMESPACE::gpu::gpu_common_constants::kCLight; - qptB5Scaler = CAMath::Abs(bzkG) > 0.1f ? CAMath::Abs(bzkG) / 5.006680f : 1.f; + UpdateBzOnly(solenoidBz); par.dodEdx = 0; constexpr float plusZmin = 0.0529937; @@ -125,29 +123,19 @@ void GPUParam::SetDefaults(float solenoidBz) par.debugLevel = 0; par.resetTimers = false; par.earlyTpcTransform = false; - - polynomialField.Reset(); // set very wrong initial value in order to see if the field was not properly initialised - GPUTPCGMPolynomialFieldManager::GetPolynomialField(bzkG, polynomialField); } void GPUParam::UpdateSettings(const GPUSettingsGRP* g, const GPUSettingsProcessing* p, const GPURecoStepConfiguration* w) { if (g) { - bzkG = g->solenoidBzNominalGPU; - bzCLight = bzkG * GPUCA_NAMESPACE::gpu::gpu_common_constants::kCLight; + UpdateBzOnly(g->solenoidBzNominalGPU); par.assumeConstantBz = g->constBz; par.toyMCEventsFlag = g->homemadeEvents; par.continuousTracking = g->continuousMaxTimeBin != 0; par.continuousMaxTimeBin = g->continuousMaxTimeBin == -1 ? GPUSettings::TPC_MAX_TF_TIME_BIN : g->continuousMaxTimeBin; - polynomialField.Reset(); - if (par.assumeConstantBz) { - GPUTPCGMPolynomialFieldManager::GetPolynomialField(GPUTPCGMPolynomialFieldManager::kUniform, bzkG, polynomialField); - } else { - GPUTPCGMPolynomialFieldManager::GetPolynomialField(bzkG, polynomialField); - } } par.earlyTpcTransform = rec.tpc.forceEarlyTransform == -1 ? (!par.continuousTracking) : rec.tpc.forceEarlyTransform; - qptB5Scaler = CAMath::Abs(bzkG) > 0.1f ? CAMath::Abs(bzkG) / 5.006680f : 1.f; + qptB5Scaler = CAMath::Abs(bzkG) > 0.1f ? CAMath::Abs(bzkG) / 5.006680f : 1.f; // Repeat here, since passing in g is optional if (p) { par.debugLevel = p->debugLevel; par.resetTimers = p->resetTimers; @@ -161,6 +149,19 @@ void GPUParam::UpdateSettings(const GPUSettingsGRP* g, const GPUSettingsProcessi } } +void GPUParam::UpdateBzOnly(float newSolenoidBz) +{ + bzkG = newSolenoidBz; + bzCLight = bzkG * GPUCA_NAMESPACE::gpu::gpu_common_constants::kCLight; + polynomialField.Reset(); + if (par.assumeConstantBz) { + GPUTPCGMPolynomialFieldManager::GetPolynomialField(GPUTPCGMPolynomialFieldManager::kUniform, bzkG, polynomialField); + } else { + GPUTPCGMPolynomialFieldManager::GetPolynomialField(bzkG, polynomialField); + } + qptB5Scaler = CAMath::Abs(bzkG) > 0.1f ? CAMath::Abs(bzkG) / 5.006680f : 1.f; +} + void GPUParam::SetDefaults(const GPUSettingsGRP* g, const GPUSettingsRec* r, const GPUSettingsProcessing* p, const GPURecoStepConfiguration* w) { SetDefaults(g->solenoidBzNominalGPU); diff --git a/GPU/GPUTracking/Base/GPUParam.h b/GPU/GPUTracking/Base/GPUParam.h index a6c61d4a1c132..a8aed7111aa6b 100644 --- a/GPU/GPUTracking/Base/GPUParam.h +++ b/GPU/GPUTracking/Base/GPUParam.h @@ -82,6 +82,7 @@ struct GPUParam : public internal::GPUParam_t void SetDefaults(float solenoidBz); void SetDefaults(const GPUSettingsGRP* g, const GPUSettingsRec* r = nullptr, const GPUSettingsProcessing* p = nullptr, const GPURecoStepConfiguration* w = nullptr); void UpdateSettings(const GPUSettingsGRP* g, const GPUSettingsProcessing* p = nullptr, const GPURecoStepConfiguration* w = nullptr); + void UpdateBzOnly(float newSolenoidBz); void LoadClusterErrors(bool Print = 0); void UpdateRun3ClusterErrors(const float* yErrorParam, const float* zErrorParam); #endif diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceUtils.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceUtils.cxx index e974704ea9d0b..cc4254f7156cf 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceUtils.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceUtils.cxx @@ -77,3 +77,39 @@ void GPUO2InterfaceUtils::GPUReconstructionZSDecoder::DecodePage(std::vectorversion](outputBuffer, page, tfFirstOrbit, triggerBC); } + +std::unique_ptr GPUO2InterfaceUtils::getFullParam(float solenoidBz, unsigned int nHbfPerTf, std::unique_ptr* pConfiguration, std::unique_ptr* pO2Settings, bool* autoMaxTimeBin) +{ + std::unique_ptr retVal = std::make_unique(); + std::unique_ptr tmpConfig; + if (!pConfiguration) { + tmpConfig = std::make_unique(); + pConfiguration = &tmpConfig; + } else if (!*pConfiguration) { + *pConfiguration = std::make_unique(); + } + (*pConfiguration)->configGRP.solenoidBzNominalGPU = solenoidBz; + if (pO2Settings && *pO2Settings) { + **pO2Settings = (*pConfiguration)->ReadConfigurableParam(); + } else if (pO2Settings) { + *pO2Settings = std::make_unique((*pConfiguration)->ReadConfigurableParam()); + } else { + (*pConfiguration)->ReadConfigurableParam(); + } + if (nHbfPerTf == 0) { + nHbfPerTf = 256; + } + if (autoMaxTimeBin) { + *autoMaxTimeBin = (*pConfiguration)->configGRP.continuousMaxTimeBin == -1; + } + if ((*pConfiguration)->configGRP.continuousMaxTimeBin == -1) { + (*pConfiguration)->configGRP.continuousMaxTimeBin = (nHbfPerTf * o2::constants::lhc::LHCMaxBunches + 2 * o2::tpc::constants::LHCBCPERTIMEBIN - 2) / o2::tpc::constants::LHCBCPERTIMEBIN; + } + retVal->SetDefaults(&(*pConfiguration)->configGRP, &(*pConfiguration)->configReconstruction, &(*pConfiguration)->configProcessing, nullptr); + return retVal; +} + +std::shared_ptr GPUO2InterfaceUtils::getFullParamShared(float solenoidBz, unsigned int nHbfPerTf, std::unique_ptr* pConfiguration, std::unique_ptr* pO2Settings, bool* autoMaxTimeBin) +{ + return std::move(getFullParam(solenoidBz, nHbfPerTf, pConfiguration, pO2Settings, autoMaxTimeBin)); +} diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceUtils.h b/GPU/GPUTracking/Interface/GPUO2InterfaceUtils.h index f5be1f2d991d0..c375f4d646a00 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceUtils.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceUtils.h @@ -38,6 +38,7 @@ namespace o2::gpu { struct GPUParam; struct GPUO2InterfaceConfiguration; +struct GPUSettingsO2; struct TPCPadGainCalib; class GPUO2InterfaceUtils { @@ -54,6 +55,8 @@ class GPUO2InterfaceUtils { return (5.00668f / 30000.f) * src.getL3Current(); } + static std::unique_ptr getFullParam(float solenoidBz, unsigned int nHbfPerTf = 0, std::unique_ptr* pConfiguration = nullptr, std::unique_ptr* pO2Settings = nullptr, bool* autoMaxTimeBin = nullptr); + static std::shared_ptr getFullParamShared(float solenoidBz, unsigned int nHbfPerTf = 0, std::unique_ptr* pConfiguration = nullptr, std::unique_ptr* pO2Settings = nullptr, bool* autoMaxTimeBin = nullptr); // Return owning pointer class GPUReconstructionZSDecoder { From ace4e5ed78b88717981867cb2d0fc5288a2db679 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 3 Apr 2024 22:42:40 +0200 Subject: [PATCH 0059/2997] TPC: Create occupancy map in shared map creator workflow --- .../TPCWorkflow/ClusterSharingMapSpec.h | 1 + .../workflow/src/ClusterSharingMapSpec.cxx | 7 +- GPU/GPUTracking/Definitions/GPUSettingsList.h | 2 +- .../Interface/GPUO2InterfaceRefit.cxx | 70 ++++++++++++++++--- .../Interface/GPUO2InterfaceRefit.h | 4 +- 5 files changed, 69 insertions(+), 15 deletions(-) diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/ClusterSharingMapSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/ClusterSharingMapSpec.h index d1fb51c50c4e5..e6c6939a2c70b 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/ClusterSharingMapSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/ClusterSharingMapSpec.h @@ -42,6 +42,7 @@ o2::framework::DataProcessorSpec getClusterSharingMapSpec() inputs.emplace_back("clusTPC", o2::framework::ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}, o2::framework::Lifetime::Timeframe); inputs.emplace_back("grpecs", "GLO", "GRPECS", 0, o2::framework::Lifetime::Condition, o2::framework::ccdbParamSpec("GLO/Config/GRPECS", true)); outputs.emplace_back("TPC", "CLSHAREDMAP", 0, o2::framework::Lifetime::Timeframe); + outputs.emplace_back("TPC", "TPCOCCUPANCYMAP", 0, o2::framework::Lifetime::Timeframe); return o2::framework::DataProcessorSpec{ "tpc-clusters-sharing-map-producer", diff --git a/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx b/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx index b4a34ce040b99..eef3061bc47c3 100644 --- a/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx +++ b/Detectors/TPC/workflow/src/ClusterSharingMapSpec.cxx @@ -19,6 +19,7 @@ #include "DataFormatsTPC/WorkflowHelper.h" #include "DataFormatsTPC/TrackTPC.h" #include "GPUO2InterfaceRefit.h" +#include "GPUO2InterfaceUtils.h" #include "TPCWorkflow/ClusterSharingMapSpec.h" #include "DataFormatsParameters/GRPECSObject.h" @@ -38,9 +39,11 @@ void ClusterSharingMapSpec::run(ProcessingContext& pc) LOGP(info, "Will use {} HB per TF from GRPECS", nHBPerTF); } + std::shared_ptr param = o2::gpu::GPUO2InterfaceUtils::getFullParamShared(0.f, nHBPerTF); auto& bufVecSh = pc.outputs().make>(Output{o2::header::gDataOriginTPC, "CLSHAREDMAP", 0}, clustersTPC->clusterIndex.nClustersTotal); - auto& bufVecOcc = pc.outputs().make>(Output{o2::header::gDataOriginTPC, "TPCOCCUPANCYMAP", 0}, 0u); - o2::gpu::GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(&clustersTPC->clusterIndex, tracksTPC, tracksTPCClRefs.data(), bufVecSh.data()); + size_t occupancyMapSize = o2::gpu::GPUO2InterfaceRefit::fillOccupancyMapGetSize(nHBPerTF, param.get()); + auto& bufVecOcc = pc.outputs().make>(Output{o2::header::gDataOriginTPC, "TPCOCCUPANCYMAP", 0}, occupancyMapSize); + o2::gpu::GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(&clustersTPC->clusterIndex, tracksTPC, tracksTPCClRefs.data(), bufVecSh.data(), bufVecOcc.data(), nHBPerTF, param.get()); timer.Stop(); LOGF(info, "Timing for TPC clusters sharing map creation: Cpu: %.3e Real: %.3e s", timer.CpuTime(), timer.RealTime()); diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index cb4d0ed729069..88d433703c0fa 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -179,7 +179,7 @@ AddOptionRTC(maxTrackQPtB5, float, 1.f / GPUCA_MIN_TRACK_PTB5_DEFAULT, "", 0, "r AddOptionRTC(nonConsecutiveIDs, char, false, "", 0, "Non-consecutive cluster IDs as in HLT, disables features that need access to slice data in TPC merger") AddOptionRTC(fwdTPCDigitsAsClusters, unsigned char, 0, "", 0, "Forward TPC digits as clusters (if they pass the ZS threshold)") AddOptionRTC(bz0Pt10MeV, unsigned char, 60, "", 0, "Nominal Pt to set when bz = 0 (in 10 MeV)") -AddOptionRTC(fitInProjections, char, -1, "", 0, "Fit in projection, -1 to enable for all but passes but the first one") +AddOptionRTC(fitInProjections, char, -1, "", 0, "Fit in projection, -1 to enable full fit for all but passes but the first one") AddOptionRTC(fitPropagateBzOnly, char, -1, "", 0, "Propagate using Bz only for n passes") AddOptionRTC(useMatLUT, char, 0, "", 0, "Use material lookup table for TPC refit") AddOptionRTC(trackingRefitGPUModel, char, 1, "", 0, "Use GPU track model for the Global Track Refit") diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx index 11ffbcffa3b30..3f184129df76b 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx @@ -13,12 +13,14 @@ /// \author David Rohr #include "GPUO2InterfaceRefit.h" +#include "GPUO2InterfaceUtils.h" #include "DataFormatsTPC/ClusterNative.h" #include "DataFormatsTPC/TrackTPC.h" #include "GPUParam.h" #include "GPUTPCGMMergedTrackHit.h" #include "GPUTrackingRefit.h" #include "CorrectionMapsHelper.h" +#include "GPUTPCClusterOccupancyMap.h" using namespace o2::gpu; using namespace o2::tpc; @@ -26,7 +28,15 @@ using namespace o2::tpc; void GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(const ClusterNativeAccess* cl, const gsl::span trks, const TPCClRefElem* trackRef, unsigned char* shmap, unsigned int* ocmap, unsigned int nHbfPerTf, const GPUParam* param) { if (!cl || (!shmap && cl->nClustersTotal > 0)) { - throw std::runtime_error("Must provide clusters access and preallocated recepient for shared map"); + throw std::runtime_error("Must provide clusters access and preallocated buffer for shared map"); + } + std::unique_ptr tmpParam; + if (param == nullptr) { + tmpParam = GPUO2InterfaceUtils::getFullParam(0.f, nHbfPerTf); + param = tmpParam.get(); + } + if ((param->rec.tpc.occupancyMapTimeBins || param->rec.tpc.sysClusErrorC12Norm) && (!ocmap || !nHbfPerTf)) { + throw std::runtime_error("Must provide nHbfPerTf and preallocated buffer for occupancy map"); } memset(shmap, 0, sizeof(char) * cl->nClustersTotal); for (unsigned int i = 0; i < trks.size(); i++) { @@ -35,32 +45,74 @@ void GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(const ClusterNativeA shmap[idx] = shmap[idx] ? 2 : 1; } } + std::vector tmp; + unsigned int* binmap = nullptr; + if (ocmap && nHbfPerTf) { + tmp.resize(param->rec.tpc.occupancyMapTimeBinsAverage ? GPUTPCClusterOccupancyMapBin::getNBins(*param) : 0, 0); + binmap = param->rec.tpc.occupancyMapTimeBinsAverage ? tmp.data() : (ocmap + 1); + *ocmap = cl->nClustersTotal / nHbfPerTf; + } + for (unsigned int i = 0; i < cl->nClustersTotal; i++) { shmap[i] = (shmap[i] > 1 ? GPUTPCGMMergedTrackHit::flagShared : 0) | cl->clustersLinear[i].getFlags(); + if (binmap) { + binmap[(unsigned int)(cl->clustersLinear[i].getTime() / param->rec.tpc.occupancyMapTimeBins)]++; + } } - if (ocmap && param) { + + if (ocmap && nHbfPerTf && param->rec.tpc.occupancyMapTimeBinsAverage) { + for (unsigned int bin = 0; bin < GPUTPCClusterOccupancyMapBin::getNBins(*param); bin++) { + int binmin = CAMath::Max(0, bin - param->rec.tpc.occupancyMapTimeBinsAverage); + int binmax = CAMath::Min(GPUTPCClusterOccupancyMapBin::getNBins(*param), bin + param->rec.tpc.occupancyMapTimeBinsAverage + 1); + unsigned int sum = 0; + for (int i = binmin; i < binmax; i++) { + sum += binmap[i]; + } + sum /= binmax - binmin; + ocmap[1 + bin] = sum; + } } } -size_t GPUO2InterfaceRefit::fillOccupancyMapGetSize(unsigned int nHbfPerTf) +size_t GPUO2InterfaceRefit::fillOccupancyMapGetSize(unsigned int nHbfPerTf, const GPUParam* param) { - return 0; + std::unique_ptr tmpParam; + if (param == nullptr) { + tmpParam = GPUO2InterfaceUtils::getFullParam(0.f, nHbfPerTf); + param = tmpParam.get(); + } + if ((param->rec.tpc.occupancyMapTimeBins || param->rec.tpc.sysClusErrorC12Norm) && !nHbfPerTf) { + throw std::runtime_error("nHbfPerTf must not be zero for creation of the occupancy map"); + } + if (param->rec.tpc.occupancyMapTimeBins) { + return (GPUTPCClusterOccupancyMapBin::getNBins(*param) + 1) * sizeof(unsigned int); + } else if (param->rec.tpc.sysClusErrorC12Norm) { + return sizeof(unsigned int); + } else { + return 0; + } } -GPUO2InterfaceRefit::GPUO2InterfaceRefit(const ClusterNativeAccess* cl, const CorrectionMapsHelper* trans, float bzNominalGPU, const TPCClRefElem* trackRef, unsigned int nHbfPerTf, const unsigned char* sharedmap, const unsigned int* occupancymap, const std::vector* trks, o2::base::Propagator* p) : mParam(new GPUParam) +GPUO2InterfaceRefit::GPUO2InterfaceRefit(const ClusterNativeAccess* cl, const CorrectionMapsHelper* trans, float bzNominalGPU, const TPCClRefElem* trackRef, unsigned int nHbfPerTf, const unsigned char* sharedmap, const unsigned int* occupancymap, const std::vector* trks, o2::base::Propagator* p) { + mParam = GPUO2InterfaceUtils::getFullParam(bzNominalGPU, nHbfPerTf); + size_t expectedSharedMapSize = fillOccupancyMapGetSize(nHbfPerTf, mParam.get()); if (cl->nClustersTotal) { if (sharedmap == nullptr && trks == nullptr) { throw std::runtime_error("Must provide either shared cluster map or vector of tpc tracks to build the map"); } + if ((sharedmap == nullptr) ^ (expectedSharedMapSize && occupancymap == nullptr)) { + throw std::runtime_error("Must provide either both shared cluster map and occupancy map or none of them"); + } if (sharedmap == nullptr) { mSharedMap.resize(cl->nClustersTotal); sharedmap = mSharedMap.data(); - fillSharedClustersAndOccupancyMap(cl, *trks, trackRef, mSharedMap.data()); + mOccupancyMap.resize(expectedSharedMapSize / sizeof(*mOccupancyMap.data())); + occupancymap = mOccupancyMap.data(); + fillSharedClustersAndOccupancyMap(cl, *trks, trackRef, mSharedMap.data(), mOccupancyMap.data(), nHbfPerTf, mParam.get()); } } mRefit = std::make_unique(); - mParam->SetDefaults(bzNominalGPU); if (occupancymap) { mParam->occupancyTotal = *occupancymap; if (mParam->rec.tpc.occupancyMapTimeBins) { @@ -77,8 +129,7 @@ GPUO2InterfaceRefit::GPUO2InterfaceRefit(const ClusterNativeAccess* cl, const Co void GPUO2InterfaceRefit::updateCalib(const CorrectionMapsHelper* trans, float bzNominalGPU) { - mParam->SetDefaults(bzNominalGPU); - mRefit->SetGPUParam(mParam.get()); + mParam->UpdateBzOnly(bzNominalGPU); mRefit->SetFastTransformHelper(trans); } @@ -87,7 +138,6 @@ int GPUO2InterfaceRefit::RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool ou int GPUO2InterfaceRefit::RefitTrackAsGPU(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, float* chi2, bool outward, bool resetCov) { return mRefit->RefitTrackAsGPU(trk, clusRef, time0, chi2, outward, resetCov); } int GPUO2InterfaceRefit::RefitTrackAsTrackParCov(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, float* chi2, bool outward, bool resetCov) { return mRefit->RefitTrackAsTrackParCov(trk, clusRef, time0, chi2, outward, resetCov); } void GPUO2InterfaceRefit::setIgnoreErrorsAtTrackEnds(bool v) { mRefit->mIgnoreErrorsOnTrackEnds = v; } -void GPUO2InterfaceRefit::setGPUTrackFitInProjections(bool v) { mParam->rec.fitInProjections = v; } void GPUO2InterfaceRefit::setTrackReferenceX(float v) { mParam->rec.tpc.trackReferenceX = v; } GPUO2InterfaceRefit::~GPUO2InterfaceRefit() = default; diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index 3470dd674ce9b..42e243fda8558 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -77,7 +77,6 @@ class GPUO2InterfaceRefit int RefitTrackAsTrackParCov(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false); int RefitTrackAsGPU(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, float* chi2 = nullptr, bool outward = false, bool resetCov = false); int RefitTrackAsTrackParCov(o2::track::TrackParCov& trk, const o2::tpc::TrackTPCClusRef& clusRef, float time0, float* chi2 = nullptr, bool outward = false, bool resetCov = false); - void setGPUTrackFitInProjections(bool v = true); void setTrackReferenceX(float v); void setIgnoreErrorsAtTrackEnds(bool v); void updateCalib(const o2::gpu::CorrectionMapsHelper* trans, float bzNominalGPU); @@ -87,12 +86,13 @@ class GPUO2InterfaceRefit // If the param object / default object requires an occupancy map, an occupancy map ptr and nHbfPerTf value must be provided. // You can use the function fillOccupancyMapGetSize(...) to get the required size of the occupancy map. If 0 is returned, no map is required. static void fillSharedClustersAndOccupancyMap(const o2::tpc::ClusterNativeAccess* cl, const gsl::span trks, const o2::tpc::TPCClRefElem* trackRef, unsigned char* shmap, unsigned int* ocmap = nullptr, unsigned int nHbfPerTf = 0, const GPUParam* param = nullptr); - static size_t fillOccupancyMapGetSize(unsigned int nHbfPerTf); + static size_t fillOccupancyMapGetSize(unsigned int nHbfPerTf, const GPUParam* param = nullptr); private: std::unique_ptr mRefit; std::unique_ptr mParam; std::vector mSharedMap; + std::vector mOccupancyMap; }; } // namespace o2::gpu From e01c2a38a4f76af8f7cdd0fd082d13f3b4e5a7d3 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 3 Apr 2024 21:50:50 +0200 Subject: [PATCH 0060/2997] TPC: Update default cluster error settings --- GPU/GPUTracking/Base/GPUParam.cxx | 2 +- GPU/GPUTracking/Base/GPUParam.inc | 14 ++++++------- GPU/GPUTracking/Definitions/GPUSettingsList.h | 20 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUParam.cxx b/GPU/GPUTracking/Base/GPUParam.cxx index 5b9dcd7e82ebc..e7a1232e1c070 100644 --- a/GPU/GPUTracking/Base/GPUParam.cxx +++ b/GPU/GPUTracking/Base/GPUParam.cxx @@ -184,7 +184,7 @@ void GPUParam::UpdateRun3ClusterErrors(const float* yErrorParam, const float* zE ParamErrors[yz][rowType][0] = param[0] * param[0]; ParamErrors[yz][rowType][1] = param[1] * param[1] * tpcGeometry.PadHeightByRegion(regionMap[rowType]); ParamErrors[yz][rowType][2] = param[2] * param[2] / tpcGeometry.TPCLength() / tpcGeometry.PadHeightByRegion(regionMap[rowType]); - ParamErrors[yz][rowType][3] = param[3] * param[3]; + ParamErrors[yz][rowType][3] = param[3] * param[3] * rec.tpc.clusterErrorOccupancyScaler * rec.tpc.clusterErrorOccupancyScaler; } } #endif diff --git a/GPU/GPUTracking/Base/GPUParam.inc b/GPU/GPUTracking/Base/GPUParam.inc index d5b4e9bc77810..886b4c82274f0 100644 --- a/GPU/GPUTracking/Base/GPUParam.inc +++ b/GPU/GPUTracking/Base/GPUParam.inc @@ -53,10 +53,10 @@ GPUdi() void MEM_LG(GPUParam)::GetClusterErrorsSeeding2(char sector, int iRow, f } MEM_CLASS_PRE() -GPUdi() float MEM_LG(GPUParam)::GetClusterError2(int yz, int type, float zDiff, float angle2, float scaledMult, float scaledInvAvgCharge, float scaledInvCharge) const +GPUdi() float MEM_LG(GPUParam)::GetClusterError2(int yz, int type, float zDiff, float angle2, float unscaledMult, float scaledInvAvgCharge, float scaledInvCharge) const { MakeType(const float*) c = ParamErrors[yz][type]; // Note: c[0] = p[0]^2, c[1] = p[1]^2 * padHeight, c[2] = p[2]^2 / tpcLength / padHeight, c[3] = p[3]^2 - float v = c[0] + c[1] * angle2 * scaledInvAvgCharge + c[2] * zDiff * scaledInvCharge + c[3] * (scaledMult * scaledMult) * (scaledInvAvgCharge * scaledInvAvgCharge); + float v = c[0] + c[1] * angle2 * scaledInvAvgCharge + c[2] * zDiff * scaledInvCharge + c[3] * (unscaledMult * unscaledMult) * (scaledInvAvgCharge * scaledInvAvgCharge); v = CAMath::Abs(v); v *= yz ? rec.tpc.clusterError2CorrectionZ : rec.tpc.clusterError2CorrectionY; v += yz ? rec.tpc.clusterError2AdditionalZ : rec.tpc.clusterError2AdditionalY; @@ -141,7 +141,7 @@ GPUdi() void MEM_LG(GPUParam)::GetClusterErrorsSeeding2(char sector, int iRow, f } MEM_CLASS_PRE() -GPUdi() float MEM_LG(GPUParam)::GetClusterError2(int yz, int type, float zDiff, float angle2, float time, float avgInvCharge, float invCharge) const +GPUdi() float MEM_LG(GPUParam)::GetClusterError2(int yz, int type, float zDiff, float angle2, float unscaledMult, float avgInvCharge, float invCharge) const { MakeType(const float*) c = ParamS0Par[yz][type]; float v = c[0] + c[1] * zDiff + c[2] * angle2 + c[3] * zDiff * zDiff + c[4] * angle2 * angle2 + c[5] * zDiff * angle2; @@ -182,12 +182,12 @@ GPUdi() void MEM_LG(GPUParam)::GetClusterErrors2(char sector, int iRow, float z, const float angleY2 = s2 * sec2; // dy/dx const float angleZ2 = DzDs * DzDs * sec2; // dz/dx - const float mult = time >= 0.f ? GetScaledMult(time) / tpcGeometry.Row2X(iRow) : 0.f; + const float unscaledMult = time >= 0.f ? GetScaledMult(time) / tpcGeometry.Row2X(iRow) : 0.f; const float scaledInvAvgCharge = avgInvCharge * rec.tpc.clusterErrorChargeScaler > 0.f ? avgInvCharge * rec.tpc.clusterErrorChargeScaler : 1.f; const float scaledInvCharge = invCharge * rec.tpc.clusterErrorChargeScaler > 0.f ? invCharge * rec.tpc.clusterErrorChargeScaler : 1.f; - ErrY2 = GetClusterError2(0, rowType, z, angleY2, mult, scaledInvAvgCharge, scaledInvCharge); - ErrZ2 = GetClusterError2(1, rowType, z, angleZ2, mult, scaledInvAvgCharge, scaledInvCharge); + ErrY2 = GetClusterError2(0, rowType, z, angleY2, unscaledMult, scaledInvAvgCharge, scaledInvCharge); + ErrZ2 = GetClusterError2(1, rowType, z, angleZ2, unscaledMult, scaledInvAvgCharge, scaledInvCharge); } MEM_CLASS_PRE() @@ -219,7 +219,7 @@ GPUdi() float MEM_LG(GPUParam)::GetScaledMult(float time) const return 0.f; } const unsigned int bin = CAMath::Max(0.f, time / rec.tpc.occupancyMapTimeBins); - return occupancyMap[bin] * rec.tpc.clusterErrorOccupancyScaler; + return occupancyMap[bin]; #else return 0.f; #endif diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 88d433703c0fa..fb92d92716956 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -46,18 +46,18 @@ AddOptionRTC(clusterError2AdditionalY, float, 0.f, "", 0, "correction (additive) AddOptionRTC(clusterError2AdditionalZ, float, 0.f, "", 0, "correction (additive) for the squared cluster error during tracking") AddOptionRTC(clusterRejectChi2TolleranceY, float, 1.f, "", 0, "Multiplicative factor multiplied onto chi2 in Y direction for cluster rejection check during track fit") AddOptionRTC(clusterRejectChi2TolleranceZ, float, 1.f, "", 0, "Multiplicative factor multiplied onto chi2 in Z direction for cluster rejection check during track fit") -AddOptionRTC(clusterErrorOccupancyScaler, float, 0.f, "", 0, "Scaling factor applied to occupancy histogram bin in cluster error estimation") -AddOptionRTC(clusterErrorChargeScaler, float, 0.f, "", 0, "Scaling factor applied to cluster charge in cluster error estimation") +AddOptionRTC(clusterErrorOccupancyScaler, float, 9.95e-04f, "", 0, "Scaling factor applied to occupancy histogram bin in cluster error estimation") +AddOptionRTC(clusterErrorChargeScaler, float, 20.f, "", 0, "Scaling factor applied to cluster charge in cluster error estimation") AddOptionRTC(sysClusErrorNormIFCCE, float, 1.f, "", 0, "Systematic cluster error parameterization IFCCE clInner[0]") AddOptionRTC(sysClusErrorSlopeIFCCE, float, 1.f / 5.f, "", 0, "Systematic cluster error parameterization IFCCE clInner[1]") AddOptionRTC(sysClusErrorIFCCEZRegion, float, -5.f, "", 0, "Systematic cluster error parameterization IFCCE z Region") AddOptionRTC(sysClusErrorslopeIFCCEZ, float, 1.f / 2.0f, "", 0, "Systematic cluster error parameterization IFCCE z Region Sigma Inverse") -AddOptionRTC(sysClusErrorNormIFC, float, 0.f, "", 0, "Systematic cluster error parameterization IFC normalization") -AddOptionRTC(sysClusErrorSlopeIFC, float, 0.f, "", 0, "Systematic cluster error parameterization IFC slope") +AddOptionRTC(sysClusErrorNormIFC, float, 0.5f, "", 0, "Systematic cluster error parameterization IFC normalization") +AddOptionRTC(sysClusErrorSlopeIFC, float, 0.2f, "", 0, "Systematic cluster error parameterization IFC slope") AddOptionRTC(sysClusErrorMinDist, float, 2.f, "", 0, "Systematic cluster error parameterization IFC Minimum Distance") AddOptionRTC(sysClusErrorMaskError, float, 5.f, "", 0, "Systematic cluster error parameterization IFC Large Error for masking") -AddOptionRTC(sysClusErrorC12Norm, float, 0.f, "", 0, "Systematic cluster for Sector C1/2 normalization") -AddOptionRTC(sysClusErrorC12Box, float, 0.f, "", 0, "Systematic cluster for Sector C1/2 box size") +AddOptionRTC(sysClusErrorC12Norm, float, 5.3333333e-06f, "", 0, "Systematic cluster for Sector C1/2 normalization") +AddOptionRTC(sysClusErrorC12Box, float, 1.1e-05f, "", 0, "Systematic cluster for Sector C1/2 box size") AddOptionRTC(minNClustersTrackSeed, int, -1, "", 0, "required min number of clusters on the track after track following (before merging)") AddOptionRTC(minNClustersFinalTrack, int, -1, "", 0, "required min number of clusters on the final track") AddOptionRTC(searchWindowDZDR, float, 2.5f, "", 0, "Use DZDR window for seeding instead of neighboursSearchArea") @@ -81,8 +81,8 @@ AddOptionRTC(minTrackdEdxMax, float, 20.0f, "", 0, "min accepted dEdxMaxTPC of t AddOptionRTC(minTrackdEdxMax2Tot, float, 0.67f, "", 0, "min accepted dEdxMaxTPC/dEdxTotTPC of the track") AddOptionRTC(extraClusterErrorEdgeY2, float, 0.35f, "", 0, "Additive extra cluster error for Y2 if edge flag set") AddOptionRTC(extraClusterErrorEdgeZ2, float, 0.15f, "", 0, "Additive extra cluster error for Z2 if edge flag set") -AddOptionRTC(extraClusterErrorSingleY2, float, 0.2f, "", 0, "Additive extra cluster error for Y2 if edge single set") -AddOptionRTC(extraClusterErrorSingleZ2, float, 0.2f, "", 0, "Additive extra cluster error for Z2 if edge single set") +AddOptionRTC(extraClusterErrorSingleY2, float, 0.04f, "", 0, "Additive extra cluster error for Y2 if single set") +AddOptionRTC(extraClusterErrorSingleZ2, float, 0.04f, "", 0, "Additive extra cluster error for Z2 if single set") AddOptionRTC(extraClusterErrorSplitPadSharedSingleY2, float, 0.03f, "", 0, "Additive extra cluster error for Y2 if splitpad, shared, or single set") AddOptionRTC(extraClusterErrorFactorSplitPadSharedSingleY2, float, 3.0f, "", 0, "Multiplicative extra cluster error for Y2 if splitpad, shared, or single set") AddOptionRTC(extraClusterErrorSplitTimeSharedSingleZ2, float, 0.03f, "", 0, "Additive extra cluster error for Z2 if splittime, shared, or single set") @@ -100,8 +100,8 @@ AddOptionRTC(rejectEdgeClustersSigmaMargin, float, 0.f, "", 0, "Margin factor fo AddOptionRTC(maxTimeBinAboveThresholdIn1000Bin, unsigned short, 500, "", 0, "Except pad from cluster finding if total number of charges in a fragment is above this baseline (disable = 0)") AddOptionRTC(maxConsecTimeBinAboveThreshold, unsigned short, 200, "", 0, "Except pad from cluster finding if number of consecutive charges in a fragment is above this baseline (disable = 0)") AddOptionRTC(noisyPadSaturationThreshold, unsigned short, 700, "", 0, "Threshold where a timebin is considered saturated, disabling the noisy pad check for that pad") -AddOptionRTC(occupancyMapTimeBins, unsigned short, 100, "", 0, "Number of timebins per histogram bin of occupancy map (0 = disable occupancy map)") -AddOptionRTC(occupancyMapTimeBinsAverage, unsigned short, 2, "", 0, "Number of timebins +/- to use for the averaging") +AddOptionRTC(occupancyMapTimeBins, unsigned short, 16, "", 0, "Number of timebins per histogram bin of occupancy map (0 = disable occupancy map)") +AddOptionRTC(occupancyMapTimeBinsAverage, unsigned short, 0, "", 0, "Number of timebins +/- to use for the averaging") AddOptionRTC(trackFitCovLimit, unsigned short, 1000, "", 0, "Abort fit when y/z cov exceed the limit") AddOptionRTC(addErrorsCECrossing, unsigned char, 0, "", 0, "Add additional custom track errors when crossing CE, 0 = no custom errors but att 0.5 to sigma_z^2, 1 = only to cov diagonal, 2 = preserve correlations") AddOptionRTC(trackMergerMinPartHits, unsigned char, 10, "", 0, "Minimum hits of track part during track merging") From 36f0b9cdf2ed923204b52029520fc754e82de5a5 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 4 Apr 2024 14:08:09 +0200 Subject: [PATCH 0061/2997] GPU: Silence some compiler warnings --- GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 2 +- dependencies/FindO2GPU.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index c66a0e07297c1..6f8450385ea54 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -254,8 +254,8 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) for (int i = start; i != stop; i += cl ? 0 : direction) { float x = 0, y = 0, z = 0, charge = 0; // FIXME: initialization unneeded, but GCC incorrectly produces uninitialized warnings otherwise + float time = 0.f, invCharge = 0.f, invSqrtCharge = 0.f; // Same here... int clusters = 0; - float time, invCharge, invSqrtCharge; while (true) { if (!cl) { CADEBUG(ii = i); diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 14d1e77838597..302f5ab93209f 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -111,7 +111,7 @@ if(ENABLE_CUDA) endif() endif() if(CMAKE_CUDA_COMPILER) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler \"${O2_GPU_CMAKE_CXX_FLAGS_NOSTD}\" --expt-relaxed-constexpr --extended-lambda --allow-unsupported-compiler -Xptxas -v") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler \"${O2_GPU_CMAKE_CXX_FLAGS_NOSTD}\" --expt-relaxed-constexpr --extended-lambda --allow-unsupported-compiler -Xptxas -v -Wno-attributes") if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "12.3") string(APPEND CMAKE_CUDA_FLAGS " -Xcudafe --diag_suppress=20257") # TODO: Cleanup endif() From db9935a3ccc6b68d5f0ff1dfbd666b5120d88110 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 5 Apr 2024 14:00:37 +0200 Subject: [PATCH 0062/2997] TPC: Check that occupancy map received from DPL has correct size, and throw instead of segfault --- Detectors/GlobalTracking/src/MatchCosmics.cxx | 2 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 2 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 2 +- .../study/src/TPCTrackStudy.cxx | 2 +- .../TPC/calibration/src/CalculatedEdx.cxx | 2 +- .../calibration/src/CalibPadGainTracks.cxx | 2 +- Detectors/TPC/workflow/src/TPCRefitter.cxx | 2 +- .../workflow/src/TRDGlobalTrackingSpec.cxx | 2 +- Detectors/Vertexing/src/SVertexer.cxx | 2 +- .../Global/GPUChainTrackingSliceTracker.cxx | 7 +++--- .../Global/GPUTrackingInputProvider.cxx | 2 +- .../Interface/GPUO2InterfaceRefit.cxx | 25 +++++++++++++------ .../Interface/GPUO2InterfaceRefit.h | 3 ++- macro/runTPCRefit.C | 2 +- 14 files changed, 34 insertions(+), 23 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchCosmics.cxx b/Detectors/GlobalTracking/src/MatchCosmics.cxx index bc10fe1c2725b..3c20ecad2f36c 100644 --- a/Detectors/GlobalTracking/src/MatchCosmics.cxx +++ b/Detectors/GlobalTracking/src/MatchCosmics.cxx @@ -95,7 +95,7 @@ void MatchCosmics::refitWinners(const o2::globaltracking::RecoContainer& data) tpcRefitter = std::make_unique(&data.inputsTPCclusters->clusterIndex, mTPCCorrMapsHelper, mBz, tpcClusRefs.data(), 0, tpcClusShMap.data(), - tpcClusOccMap.data(), nullptr, o2::base::Propagator::Instance()); + tpcClusOccMap.data(), tpcClusOccMap.size(), nullptr, o2::base::Propagator::Instance()); } const auto& itsClusters = prepareITSClusters(data); diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index ce113ecaa673e..3a0ee70570f53 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -1799,6 +1799,6 @@ void MatchTOF::checkRefitter() if (mTPCClusterIdxStruct) { mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), - mTPCRefitterOccMap.data(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); } } diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 0e7700928b0e3..2a6e8efd9ed03 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -574,7 +574,7 @@ bool MatchTPCITS::prepareTPCData() mITSROFofTPCBin[ib] = itsROF; } */ - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); mInteractionMUSLUT.clear(); mInteractionMUSLUT.resize(maxTime + 3 * o2::constants::lhc::LHCOrbitMUS, -1); mTimer[SWPrepTPC].Stop(); diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx index 6c51525e67d6a..51c1a521fc5cc 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx @@ -183,7 +183,7 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) mTPCTrkLabels = recoData.getTPCTracksMCLabels(); } - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); float vdriftTB = mTPCVDriftHelper.getVDriftObject().getVDrift() * o2::tpc::ParameterElectronics::Instance().ZbinWidth; // VDrift expressed in cm/TimeBin float tpcTBBias = mTPCVDriftHelper.getVDriftObject().getTimeOffset() / (8 * o2::constants::lhc::LHCBunchSpacingMUS); diff --git a/Detectors/TPC/calibration/src/CalculatedEdx.cxx b/Detectors/TPC/calibration/src/CalculatedEdx.cxx index fb23611416f3c..b70be764078b8 100644 --- a/Detectors/TPC/calibration/src/CalculatedEdx.cxx +++ b/Detectors/TPC/calibration/src/CalculatedEdx.cxx @@ -45,7 +45,7 @@ void CalculatedEdx::setMembers(std::vector* tpcTrackClIdx void CalculatedEdx::setRefit() { - mRefit = std::make_unique(mClusterIndex, &mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), 0, nullptr, nullptr, mTracks); + mRefit = std::make_unique(mClusterIndex, &mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), 0, nullptr, nullptr, -1, mTracks); } void CalculatedEdx::fillMissingClusters(int missingClusters[4], float minChargeTot, float minChargeMax, int method) diff --git a/Detectors/TPC/calibration/src/CalibPadGainTracks.cxx b/Detectors/TPC/calibration/src/CalibPadGainTracks.cxx index 24c002328bf35..93cdb7c47ee37 100644 --- a/Detectors/TPC/calibration/src/CalibPadGainTracks.cxx +++ b/Detectors/TPC/calibration/src/CalibPadGainTracks.cxx @@ -37,7 +37,7 @@ void CalibPadGainTracks::processTracks(const int nMaxTracks) { std::unique_ptr refit; if (!mPropagateTrack) { - refit = std::make_unique(mClusterIndex, mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data()); + refit = std::make_unique(mClusterIndex, mTPCCorrMapsHelper, mFieldNominalGPUBz, mTPCTrackClIdxVecInput->data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size()); } const size_t loopEnd = (nMaxTracks < 0) ? mTracks->size() : ((nMaxTracks > mTracks->size()) ? mTracks->size() : size_t(nMaxTracks)); diff --git a/Detectors/TPC/workflow/src/TPCRefitter.cxx b/Detectors/TPC/workflow/src/TPCRefitter.cxx index 0911f9dae3798..6a41f487f40b3 100644 --- a/Detectors/TPC/workflow/src/TPCRefitter.cxx +++ b/Detectors/TPC/workflow/src/TPCRefitter.cxx @@ -191,7 +191,7 @@ void TPCRefitterSpec::process(o2::globaltracking::RecoContainer& recoData) mTPCTrkLabels = recoData.getTPCTracksMCLabels(); } - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), nullptr, prop); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, prop); float vdriftTB = mTPCVDriftHelper.getVDriftObject().getVDrift() * o2::tpc::ParameterElectronics::Instance().ZbinWidth; // VDrift expressed in cm/TimeBin float tpcTBBias = mTPCVDriftHelper.getVDriftObject().getTimeOffset() / (8 * o2::constants::lhc::LHCBunchSpacingMUS); diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index 7215265b794eb..2f365ebe4935a 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -275,7 +275,7 @@ void TRDGlobalTracking::run(ProcessingContext& pc) mChainTracking->ClearIOPointers(); mTPCClusterIdxStruct = &inputTracks.inputsTPCclusters->clusterIndex; - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(), inputTracks.getTPCTracksClusterRefs().data(), 0, inputTracks.clusterShMapTPC.data(), inputTracks.occupancyMapTPC.data(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(), inputTracks.getTPCTracksClusterRefs().data(), 0, inputTracks.clusterShMapTPC.data(), inputTracks.occupancyMapTPC.data(), inputTracks.occupancyMapTPC.size(), nullptr, o2::base::Propagator::Instance()); auto tmpInputContainer = getRecoInputContainer(pc, &mChainTracking->mIOPtrs, &inputTracks, mUseMC); auto tmpContainer = GPUWorkflowHelper::fillIOPtr(mChainTracking->mIOPtrs, inputTracks, mUseMC, nullptr, GTrackID::getSourcesMask("TRD"), mTrkMask, GTrackID::mask_t{GTrackID::MASK_NONE}); mTrackletsRaw = inputTracks.getTRDTracklets(); diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx index 2294c390eed1f..252d14c16c7a5 100644 --- a/Detectors/Vertexing/src/SVertexer.cxx +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -449,7 +449,7 @@ void SVertexer::buildT2V(const o2::globaltracking::RecoContainer& recoData) // a mTPCClusterIdxStruct = &recoData.inputsTPCclusters->clusterIndex; mTPCRefitterShMap = recoData.clusterShMapTPC; mTPCRefitterOccMap = mRecoCont->occupancyMapTPC; - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, o2::base::Propagator::Instance()->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, o2::base::Propagator::Instance()->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); } std::unordered_map> tmap; diff --git a/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx b/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx index 0df42e20ac77f..221d722878d1d 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingSliceTracker.cxx @@ -155,17 +155,18 @@ int GPUChainTracking::RunTPCTrackingSlices_internal() auto* ptrTmp = (GPUTPCClusterOccupancyMapBin*)mRec->AllocateVolatileMemory(GPUTPCClusterOccupancyMapBin::getTotalSize(param()), doGPU); runKernel(GetGridAutoStep(streamOccMap, RecoStep::TPCSliceTracking), ptrTmp, GPUTPCClusterOccupancyMapBin::getTotalSize(param())); runKernel(GetGridBlk(GPUCA_NSLICES * GPUCA_ROW_COUNT, streamOccMap), ptrTmp); - runKernel(GetGridBlk(GPUTPCClusterOccupancyMapBin::getNBins(param()), streamOccMap), ptrTmp, ptr + 1); + runKernel(GetGridBlk(GPUTPCClusterOccupancyMapBin::getNBins(param()), streamOccMap), ptrTmp, ptr + 2); mRec->ReturnVolatileMemory(); + mInputsHost->mTPCClusterOccupancyMap[1] = param().rec.tpc.occupancyMapTimeBins * 0x10000 + param().rec.tpc.occupancyMapTimeBinsAverage; if (doGPU) { - GPUMemCpy(RecoStep::TPCSliceTracking, mInputsHost->mTPCClusterOccupancyMap + 1, mInputsShadow->mTPCClusterOccupancyMap + 1, sizeof(*ptr) * GPUTPCClusterOccupancyMapBin::getNBins(mRec->GetParam()), streamOccMap, false, &mEvents->init); + GPUMemCpy(RecoStep::TPCSliceTracking, mInputsHost->mTPCClusterOccupancyMap + 2, mInputsShadow->mTPCClusterOccupancyMap + 2, sizeof(*ptr) * GPUTPCClusterOccupancyMapBin::getNBins(mRec->GetParam()), streamOccMap, false, &mEvents->init); } else { TransferMemoryResourceLinkToGPU(RecoStep::TPCSliceTracking, mInputsHost->mResourceOccupancyMap, streamOccMap, &mEvents->init); } } unsigned int& occupancyTotal = *mInputsHost->mTPCClusterOccupancyMap; occupancyTotal = CAMath::Float2UIntRn(mRec->MemoryScalers()->nTPCHits / (mIOPtrs.settingsTF && mIOPtrs.settingsTF->hasNHBFPerTF ? mIOPtrs.settingsTF->nHBFPerTF : 128)); - mRec->UpdateParamOccupancyMap(param().rec.tpc.occupancyMapTimeBins ? mInputsHost->mTPCClusterOccupancyMap + 1 : nullptr, param().rec.tpc.occupancyMapTimeBins ? mInputsShadow->mTPCClusterOccupancyMap + 1 : nullptr, occupancyTotal, streamOccMap); + mRec->UpdateParamOccupancyMap(param().rec.tpc.occupancyMapTimeBins ? mInputsHost->mTPCClusterOccupancyMap + 2 : nullptr, param().rec.tpc.occupancyMapTimeBins ? mInputsShadow->mTPCClusterOccupancyMap + 2 : nullptr, occupancyTotal, streamOccMap); int streamMap[NSLICES]; diff --git a/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx b/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx index cb0dc7cfe698c..bf6cd029a981b 100644 --- a/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx +++ b/GPU/GPUTracking/Global/GPUTrackingInputProvider.cxx @@ -79,7 +79,7 @@ void* GPUTrackingInputProvider::SetPointersInputTRD(void* mem) void* GPUTrackingInputProvider::SetPointersTPCOccupancyMap(void* mem) { if (mHoldTPCOccupancyMap) { - computePointerWithAlignment(mem, mTPCClusterOccupancyMap, (mRec->GetParam().rec.tpc.occupancyMapTimeBins ? GPUTPCClusterOccupancyMapBin::getNBins(mRec->GetParam()) : 0) + 1); // +1 for total occupancy estimator + computePointerWithAlignment(mem, mTPCClusterOccupancyMap, (mRec->GetParam().rec.tpc.occupancyMapTimeBins ? GPUTPCClusterOccupancyMapBin::getNBins(mRec->GetParam()) + 1 : 0) + 1); // +1 for total occupancy estimator, +1 for sanity check information } return mem; } diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx index 3f184129df76b..f81da3b52ad1b 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.cxx @@ -35,8 +35,8 @@ void GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(const ClusterNativeA tmpParam = GPUO2InterfaceUtils::getFullParam(0.f, nHbfPerTf); param = tmpParam.get(); } - if ((param->rec.tpc.occupancyMapTimeBins || param->rec.tpc.sysClusErrorC12Norm) && (!ocmap || !nHbfPerTf)) { - throw std::runtime_error("Must provide nHbfPerTf and preallocated buffer for occupancy map"); + if ((param->rec.tpc.occupancyMapTimeBins || param->rec.tpc.sysClusErrorC12Norm) && ocmap && !nHbfPerTf) { + throw std::runtime_error("Must provide nHbfPerTf for occupancy map"); } memset(shmap, 0, sizeof(char) * cl->nClustersTotal); for (unsigned int i = 0; i < trks.size(); i++) { @@ -49,8 +49,11 @@ void GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(const ClusterNativeA unsigned int* binmap = nullptr; if (ocmap && nHbfPerTf) { tmp.resize(param->rec.tpc.occupancyMapTimeBinsAverage ? GPUTPCClusterOccupancyMapBin::getNBins(*param) : 0, 0); - binmap = param->rec.tpc.occupancyMapTimeBinsAverage ? tmp.data() : (ocmap + 1); + binmap = param->rec.tpc.occupancyMapTimeBinsAverage ? tmp.data() : (ocmap + 2); *ocmap = cl->nClustersTotal / nHbfPerTf; + if (param->rec.tpc.occupancyMapTimeBins) { + ocmap[1] = param->rec.tpc.occupancyMapTimeBins * 0x10000 + param->rec.tpc.occupancyMapTimeBinsAverage; + } } for (unsigned int i = 0; i < cl->nClustersTotal; i++) { @@ -69,7 +72,7 @@ void GPUO2InterfaceRefit::fillSharedClustersAndOccupancyMap(const ClusterNativeA sum += binmap[i]; } sum /= binmax - binmin; - ocmap[1 + bin] = sum; + ocmap[2 + bin] = sum; } } } @@ -85,7 +88,7 @@ size_t GPUO2InterfaceRefit::fillOccupancyMapGetSize(unsigned int nHbfPerTf, cons throw std::runtime_error("nHbfPerTf must not be zero for creation of the occupancy map"); } if (param->rec.tpc.occupancyMapTimeBins) { - return (GPUTPCClusterOccupancyMapBin::getNBins(*param) + 1) * sizeof(unsigned int); + return (GPUTPCClusterOccupancyMapBin::getNBins(*param) + 2) * sizeof(unsigned int); } else if (param->rec.tpc.sysClusErrorC12Norm) { return sizeof(unsigned int); } else { @@ -93,10 +96,10 @@ size_t GPUO2InterfaceRefit::fillOccupancyMapGetSize(unsigned int nHbfPerTf, cons } } -GPUO2InterfaceRefit::GPUO2InterfaceRefit(const ClusterNativeAccess* cl, const CorrectionMapsHelper* trans, float bzNominalGPU, const TPCClRefElem* trackRef, unsigned int nHbfPerTf, const unsigned char* sharedmap, const unsigned int* occupancymap, const std::vector* trks, o2::base::Propagator* p) +GPUO2InterfaceRefit::GPUO2InterfaceRefit(const ClusterNativeAccess* cl, const CorrectionMapsHelper* trans, float bzNominalGPU, const TPCClRefElem* trackRef, unsigned int nHbfPerTf, const unsigned char* sharedmap, const unsigned int* occupancymap, int occupancyMapSize, const std::vector* trks, o2::base::Propagator* p) { mParam = GPUO2InterfaceUtils::getFullParam(bzNominalGPU, nHbfPerTf); - size_t expectedSharedMapSize = fillOccupancyMapGetSize(nHbfPerTf, mParam.get()); + size_t expectedSharedMapSize = nHbfPerTf ? fillOccupancyMapGetSize(nHbfPerTf, mParam.get()) : 0; if (cl->nClustersTotal) { if (sharedmap == nullptr && trks == nullptr) { throw std::runtime_error("Must provide either shared cluster map or vector of tpc tracks to build the map"); @@ -112,11 +115,17 @@ GPUO2InterfaceRefit::GPUO2InterfaceRefit(const ClusterNativeAccess* cl, const Co fillSharedClustersAndOccupancyMap(cl, *trks, trackRef, mSharedMap.data(), mOccupancyMap.data(), nHbfPerTf, mParam.get()); } } + if (occupancymap && occupancyMapSize > sizeof(*occupancymap) && occupancymap[1] != (mParam->rec.tpc.occupancyMapTimeBins * 0x10000 + mParam->rec.tpc.occupancyMapTimeBinsAverage)) { + throw std::runtime_error("Occupancy map has invalid paramters occupancyMapTimeBins and occupancyMapTimeBinsAverage"); + } + if (occupancyMapSize != -1 && nHbfPerTf && (size_t)occupancyMapSize != expectedSharedMapSize) { + throw std::runtime_error("Received occupancy map of wrong size, most likely --configKeyValues or HBperTF of map creator and map consumer are different"); + } mRefit = std::make_unique(); if (occupancymap) { mParam->occupancyTotal = *occupancymap; if (mParam->rec.tpc.occupancyMapTimeBins) { - mParam->occupancyMap = occupancymap + 1; + mParam->occupancyMap = occupancymap + 2; } } mRefit->SetGPUParam(mParam.get()); diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index 42e243fda8558..5803dfbd68943 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -70,7 +70,7 @@ class GPUO2InterfaceRefit // - o2::base::Propagator (p) in case RefitTrackAsTrackParCov is to be used // - In case the --configKeyValues defining GPUParam settings require an occupancy map for TPC error estimation, the map must either be provided as occupancymap, or nHbfPerTf must be set non-zero - GPUO2InterfaceRefit(const o2::tpc::ClusterNativeAccess* cl, const o2::gpu::CorrectionMapsHelper* trans, float bzNominalGPU, const o2::tpc::TPCClRefElem* trackRef, unsigned int nHbfPerTf = 0, const unsigned char* sharedmap = nullptr, const unsigned int* occupancymap = nullptr, const std::vector* trks = nullptr, o2::base::Propagator* p = nullptr); + GPUO2InterfaceRefit(const o2::tpc::ClusterNativeAccess* cl, const o2::gpu::CorrectionMapsHelper* trans, float bzNominalGPU, const o2::tpc::TPCClRefElem* trackRef, unsigned int nHbfPerTf = 0, const unsigned char* sharedmap = nullptr, const unsigned int* occupancymap = nullptr, int occupancyMapSize = -1, const std::vector* trks = nullptr, o2::base::Propagator* p = nullptr); ~GPUO2InterfaceRefit(); int RefitTrackAsGPU(o2::tpc::TrackTPC& trk, bool outward = false, bool resetCov = false); @@ -85,6 +85,7 @@ class GPUO2InterfaceRefit // param is an optional parameter to override the param object, by default a default object from --configKeyValues is used. // If the param object / default object requires an occupancy map, an occupancy map ptr and nHbfPerTf value must be provided. // You can use the function fillOccupancyMapGetSize(...) to get the required size of the occupancy map. If 0 is returned, no map is required. + // Providing only the shmap ptr but no ocmap ptr will create only the shared map, but no occupancy map. static void fillSharedClustersAndOccupancyMap(const o2::tpc::ClusterNativeAccess* cl, const gsl::span trks, const o2::tpc::TPCClRefElem* trackRef, unsigned char* shmap, unsigned int* ocmap = nullptr, unsigned int nHbfPerTf = 0, const GPUParam* param = nullptr); static size_t fillOccupancyMapGetSize(unsigned int nHbfPerTf, const GPUParam* param = nullptr); diff --git a/macro/runTPCRefit.C b/macro/runTPCRefit.C index fa5af2eb6fda0..02c79a8b369ed 100644 --- a/macro/runTPCRefit.C +++ b/macro/runTPCRefit.C @@ -87,7 +87,7 @@ int runTPCRefit(TString trackFile = "tpctracks.root", TString clusterFile = "tpc std::cout << "Error reading clusters (code " << retVal << ")\n"; return 1; } - GPUO2InterfaceRefit refit(&clusterIndex, &transHelper, bz, trackHitRefs->data(), 0, nullptr, nullptr, tracks, prop); + GPUO2InterfaceRefit refit(&clusterIndex, &transHelper, bz, trackHitRefs->data(), 0, nullptr, nullptr, -1, tracks, prop); //refit.setGPUTrackFitInProjections(false); // Enable full 3D fit without assuming y and Z are uncorrelated for (unsigned int i = 0; i < tracks->size(); i++) { TrackTPC trk = (*tracks)[i]; From aa33d26f81941dd82945e351937572d023201774 Mon Sep 17 00:00:00 2001 From: Mario Ciacco Date: Sat, 6 Apr 2024 22:42:42 +0200 Subject: [PATCH 0063/2997] reserve bit of mc particle flag for OOB pileup tagging (#12993) --- Framework/Core/include/Framework/DataTypes.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Framework/Core/include/Framework/DataTypes.h b/Framework/Core/include/Framework/DataTypes.h index 423a05a221776..011c71fa27b38 100644 --- a/Framework/Core/include/Framework/DataTypes.h +++ b/Framework/Core/include/Framework/DataTypes.h @@ -79,8 +79,9 @@ namespace o2::aod::mcparticle::enums { enum MCParticleFlags : uint8_t { ProducedByTransport = 0x1, - FromBackgroundEvent = 0x2, // Particle from background event (may have been used several times) - PhysicalPrimary = 0x4 // Particle is a physical primary according to ALICE definition + FromBackgroundEvent = 0x2, // Particle from background event (may have been used several times) + PhysicalPrimary = 0x4, // Particle is a physical primary according to ALICE definition + FromOutOfBunchPileUpCollision = 0x8 // Particle from out-of-bunch pile up collision (currently Run 2 only) }; } // namespace o2::aod::mcparticle::enums From 5defaad1c8d73613052040e81d59a0b7b160794a Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 5 Apr 2024 19:13:23 +0200 Subject: [PATCH 0064/2997] Group refitted V0s per PV, add extra info --- .../study/CMakeLists.txt | 6 + .../study/include/GlobalTrackingStudy/V0Ext.h | 44 +++++ .../study/src/GlobalTrackingStudyLinkDef.h | 5 + .../study/src/SVStudy.cxx | 151 +++++++++++------- .../study/src/V0Ext.cxx | 14 ++ 5 files changed, 161 insertions(+), 59 deletions(-) create mode 100644 Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/V0Ext.h create mode 100644 Detectors/GlobalTrackingWorkflow/study/src/V0Ext.cxx diff --git a/Detectors/GlobalTrackingWorkflow/study/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/study/CMakeLists.txt index c632b7ae72cb0..3d04a12ed7dfd 100644 --- a/Detectors/GlobalTrackingWorkflow/study/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/study/CMakeLists.txt @@ -19,6 +19,7 @@ o2_add_library(GlobalTrackingStudy src/TPCDataFilter.cxx src/ITSOffsStudy.cxx src/DumpTracks.cxx + src/V0Ext.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTracking O2::GlobalTrackingWorkflowReaders O2::GlobalTrackingWorkflowHelpers @@ -27,6 +28,11 @@ o2_add_library(GlobalTrackingStudy O2::TPCWorkflow O2::SimulationDataFormat) +o2_target_root_dictionary( + GlobalTrackingStudy + HEADERS include/GlobalTrackingStudy/V0Ext.h +) + o2_add_executable(study-workflow COMPONENT_NAME sv SOURCES src/sv-study-workflow.cxx diff --git a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/V0Ext.h b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/V0Ext.h new file mode 100644 index 0000000000000..1beddf693c458 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/V0Ext.h @@ -0,0 +1,44 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// class for extended V0 info (for debugging) + +#ifndef ALICEO2_V0EXT_H +#define ALICEO2_V0EXT_H + +#include "ReconstructionDataFormats/V0.h" + +namespace o2 +{ +namespace dataformats +{ + +struct ProngInfoExt { + o2::track::TrackParCov trackTPC; + int nClTPC = 0; + int nClITS = 0; + int pattITS = 0; + float chi2ITSTPC = 0.f; + ClassDefNV(ProngInfoExt, 1); +}; + +struct V0Ext { + V0 v0; + V0Index v0ID; + std::array prInfo{}; + const ProngInfoExt& getPrInfo(int i) const { return prInfo[i]; } + ClassDefNV(V0Ext, 1); +}; + +} // namespace dataformats +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/study/src/GlobalTrackingStudyLinkDef.h b/Detectors/GlobalTrackingWorkflow/study/src/GlobalTrackingStudyLinkDef.h index c85dd2d378ccb..9fa684f316e46 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/GlobalTrackingStudyLinkDef.h +++ b/Detectors/GlobalTrackingWorkflow/study/src/GlobalTrackingStudyLinkDef.h @@ -15,4 +15,9 @@ #pragma link off all classes; #pragma link off all functions; +#pragma link C++ class o2::dataformats::ProngInfoExt + ; +#pragma link C++ class o2::dataformats::V0Ext + ; +#pragma link C++ class std::vector < o2::dataformats::ProngInfoExt> + ; +#pragma link C++ class std::vector < o2::dataformats::V0Ext> + ; + #endif diff --git a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx index 150e4ab88a1b2..9ea30577dc579 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx @@ -42,6 +42,7 @@ #include "Steer/MCKinematicsReader.h" #include "DCAFitter/DCAFitterN.h" #include "MathUtils/fit.h" +#include "GlobalTrackingStudy/V0Ext.h" namespace o2::svstudy { @@ -70,6 +71,7 @@ class SVStudySpec : public Task void endOfStream(EndOfStreamContext& ec) final; void finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) final; void process(o2::globaltracking::RecoContainer& recoData); + o2::dataformats::V0Ext processV0(int iv, o2::globaltracking::RecoContainer& recoData); private: void updateTimeDependentParams(ProcessingContext& pc); @@ -78,7 +80,7 @@ class SVStudySpec : public Task std::shared_ptr mGGCCDBRequest; bool mUseMC{false}; ///< MC flag std::unique_ptr mDBGOut; - bool mSelK0 = false; + float mSelK0 = -1; bool mRefit = false; float mMaxEta = 0.8; float mBz = 0; @@ -92,7 +94,7 @@ void SVStudySpec::init(InitContext& ic) o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); mDBGOut = std::make_unique("svStudy.root", "recreate"); mRefit = ic.options().get("refit"); - mSelK0 = ic.options().get("sel-k0"); + mSelK0 = ic.options().get("sel-k0"); mMaxEta = ic.options().get("max-eta"); } @@ -132,77 +134,108 @@ void SVStudySpec::updateTimeDependentParams(ProcessingContext& pc) mFitterV0.setBz(mBz); } -void SVStudySpec::process(o2::globaltracking::RecoContainer& recoData) +o2::dataformats::V0Ext SVStudySpec::processV0(int iv, o2::globaltracking::RecoContainer& recoData) { + o2::dataformats::V0Ext v0ext; + auto invalidate = [&v0ext]() { v0ext.v0ID.setVertexID(-1); }; + auto v0s = recoData.getV0s(); auto v0IDs = recoData.getV0sIdx(); - bool refit = mRefit || (v0s.size() < v0IDs.size()); - int nv0 = v0IDs.size(); - o2::dataformats::V0 v0ref; - o2::track::TrackParCov dummyTr{}; - const o2::track::TrackParCov* tpcTracks[2] = {&dummyTr, &dummyTr}; - int nclTPC[2] = {0, 0}, nclITS[2] = {0, 0}, itsPatt[2] = {0, 0}; - float chi2ITSTPC[2] = {-1., -1.}; static int tfID = 0; - for (int iv = 0; iv < nv0; iv++) { - const auto& v0id = v0IDs[iv]; - if (mRefit && !refitV0(v0id, v0ref, recoData)) { - continue; - } - const auto& v0 = mRefit ? v0ref : v0s[iv]; - if (mMaxEta < std::abs(v0.getEta())) { - continue; - } - if (mSelK0 && std::abs(std::sqrt(v0.calcMass2AsK0()) - 0.497) > 0.1) { - continue; + const auto& v0id = v0IDs[iv]; + if (mRefit && !refitV0(v0id, v0ext.v0, recoData)) { + invalidate(); + return v0ext; + } + const auto& v0sel = mRefit ? v0ext.v0 : v0s[iv]; + if (mMaxEta < std::abs(v0sel.getEta())) { + invalidate(); + return v0ext; + } + if (mSelK0 > 0 && std::abs(std::sqrt(v0sel.calcMass2AsK0()) - 0.497) > mSelK0) { + invalidate(); + return v0ext; + } + v0ext.v0ID = v0id; + for (int ip = 0; ip < 2; ip++) { + auto& prInfo = v0ext.prInfo[ip]; + auto gid = v0ext.v0ID.getProngID(ip); + auto gidset = recoData.getSingleDetectorRefs(gid); + // get TPC tracks, if any + if (gidset[GTrackID::TPC].isSourceSet()) { + const auto& tpcTr = recoData.getTPCTrack(gidset[GTrackID::TPC]); + prInfo.trackTPC = tpcTr; + prInfo.nClTPC = tpcTr.getNClusters(); } - for (int ip = 0; ip < 2; ip++) { - auto gid = v0id.getProngID(ip); - auto gidset = recoData.getSingleDetectorRefs(gid); - // get TPC tracks, if any - tpcTracks[ip] = &dummyTr; - nclTPC[ip] = 0; - if (gidset[GTrackID::TPC].isSourceSet()) { - const auto& tpcTr = recoData.getTPCTrack(gidset[GTrackID::TPC]); - tpcTracks[ip] = &tpcTr; - nclTPC[ip] = tpcTr.getNClusters(); - } - // get ITS tracks, if any - nclITS[ip] = itsPatt[ip] = 0; - if (gid.includesDet(DetID::ITS)) { - auto gidITS = recoData.getITSContributorGID(gid); - if (gidset[GTrackID::ITS].isSourceSet()) { - const auto& itsTr = recoData.getITSTrack(recoData.getITSContributorGID(gid)); - nclITS[ip] = itsTr.getNClusters(); - for (int il = 0; il < 7; il++) { - if (itsTr.hasHitOnLayer(il)) { - itsPatt[ip] |= 0x1 << il; - } + // get ITS tracks, if any + if (gid.includesDet(DetID::ITS)) { + auto gidITS = recoData.getITSContributorGID(gid); + if (gidset[GTrackID::ITS].isSourceSet()) { + const auto& itsTr = recoData.getITSTrack(recoData.getITSContributorGID(gid)); + prInfo.nClITS = itsTr.getNClusters(); + for (int il = 0; il < 7; il++) { + if (itsTr.hasHitOnLayer(il)) { + prInfo.pattITS |= 0x1 << il; } - } else { - const auto& itsTrf = recoData.getITSABRefs()[gidset[GTrackID::ITSAB]]; - nclITS[ip] = itsTrf.getNClusters(); - for (int il = 0; il < 7; il++) { - if (itsTrf.hasHitOnLayer(il)) { - itsPatt[ip] |= 0x1 << il; - } + } + } else { + const auto& itsTrf = recoData.getITSABRefs()[gidset[GTrackID::ITSAB]]; + prInfo.nClITS = itsTrf.getNClusters(); + for (int il = 0; il < 7; il++) { + if (itsTrf.hasHitOnLayer(il)) { + prInfo.pattITS |= 0x1 << il; } } + prInfo.pattITS |= 0x1 << 31; // flag AB } if (gidset[GTrackID::ITSTPC].isSourceSet()) { auto mtc = recoData.getTPCITSTrack(gidset[GTrackID::ITSTPC]); - chi2ITSTPC[ip] = mtc.getChi2Match(); + prInfo.chi2ITSTPC = mtc.getChi2Match(); + } + } + } + return v0ext; +} + +void SVStudySpec::process(o2::globaltracking::RecoContainer& recoData) +{ + auto v0IDs = recoData.getV0sIdx(); + auto nv0 = v0IDs.size(); + if (nv0 > recoData.getV0s().size()) { + mRefit = true; + } + std::map> pv2sv; + static int tfID = 0; + for (int iv = 0; iv < nv0; iv++) { + const auto v0id = v0IDs[iv]; + pv2sv[v0id.getVertexID()].push_back(iv); + } + std::vector v0extVec; + for (auto it : pv2sv) { + int pvID = it.first; + auto& vv = it.second; + if (pvID < 0 || vv.size() == 0) { + continue; + } + v0extVec.clear(); + for (int iv0 : vv) { + auto v0ext = processV0(iv0, recoData); + if (v0ext.v0ID.getVertexID() < 0) { + continue; } + v0extVec.push_back(v0ext); + } + if (v0extVec.size()) { + const auto& pv = recoData.getPrimaryVertex(pvID); + (*mDBGOut) << "v0" + << "orbit=" << recoData.startIR.orbit << "tfID=" << tfID + << "v0Ext=" << v0extVec + << "pv=" << pv + << "\n"; } - (*mDBGOut) << "tfinfo" - << "orbit=" << recoData.startIR.orbit << "tfID=" << tfID << "\n"; - (*mDBGOut) << "v0s" - << "v0=" << v0 << "v0ID=" << v0id << "tpc0=" << *tpcTracks[0] << "tpc1=" << *tpcTracks[1] - << "nclTPC0=" << nclTPC[0] << "nclTPC1=" << nclTPC[1] << "nclITS0=" << nclITS[0] << "nclITS1=" << nclITS[1] << "itsPatt0=" << itsPatt[0] << "itsPatt1=" << itsPatt[1] - << "chi2ITSTPC0=" << chi2ITSTPC[0] << "chi2ITSTPC1=" << chi2ITSTPC[1] << "\n"; + tfID++; } - tfID++; } bool SVStudySpec::refitV0(const V0ID& id, o2::dataformats::V0& v0, o2::globaltracking::RecoContainer& recoData) @@ -286,7 +319,7 @@ DataProcessorSpec getSVStudySpec(GTrackID::mask_t srcTracks, bool useMC) AlgorithmSpec{adaptFromTask(dataRequest, ggRequest, srcTracks, useMC)}, Options{ {"refit", VariantType::Bool, false, {"refit SVertices"}}, - {"sel-k0", VariantType::Bool, false, {"select K0s only"}}, + {"sel-k0", VariantType::Float, -1.f, {"If positive, select K0s with this mass margin"}}, {"max-eta", VariantType::Float, 1.2f, {"Cut on track eta"}}, }}; } diff --git a/Detectors/GlobalTrackingWorkflow/study/src/V0Ext.cxx b/Detectors/GlobalTrackingWorkflow/study/src/V0Ext.cxx new file mode 100644 index 0000000000000..0ae0fd3bda96a --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/study/src/V0Ext.cxx @@ -0,0 +1,14 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// class for extended V0 info (for debugging) + +#include "GlobalTrackingStudy/V0Ext.h" From b658daea988741481edd5428d1f4e022460a3174 Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 7 Apr 2024 22:01:50 +0200 Subject: [PATCH 0065/2997] Do not create RCT entry at EOR, update only SOR version --- Detectors/GRP/workflows/src/create-grp-ecs.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/GRP/workflows/src/create-grp-ecs.cxx b/Detectors/GRP/workflows/src/create-grp-ecs.cxx index 9b93bbf00a4ea..95bfb878cee9d 100644 --- a/Detectors/GRP/workflows/src/create-grp-ecs.cxx +++ b/Detectors/GRP/workflows/src/create-grp-ecs.cxx @@ -134,7 +134,7 @@ int createGRPECSObject(const std::string& dataPeriod, } else { LOGP(alarm, "Upload to {}/{} with validity {}:{} for SOR:{}/EOR:{} FAILED, returned with code {}", ccdbServer, objPath, tstart, tendVal, tstart, tend, retValGLO); } - if (runType == GRPECSObject::RunType::PHYSICS || runType == GRPECSObject::RunType::COSMICS) { // also create the RCT/Info/RunInformation entry in case the run type is PHYSICS, to be finalized at EOR + if ((runType == GRPECSObject::RunType::PHYSICS || runType == GRPECSObject::RunType::COSMICS) && tstart >= tend) { // also create the RCT/Info/RunInformation entry in case the run type is PHYSICS, to be finalized at EOR char tempChar{}; std::map mdRCT; mdRCT["SOR"] = std::to_string(tstart); From 11e254b26cedcdaa2afb1291a3fa71a1c24cbb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Tue, 2 Apr 2024 16:05:23 +0200 Subject: [PATCH 0066/2997] Add missing energy column in StoredTracksIU --- Framework/Core/include/Framework/AnalysisDataModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index a4a8b38b36c19..634cc490d857a 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -153,7 +153,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, //! Momentum in z-direction in GeV/c auto pt = 1.f / std::abs(signed1Pt); return pt * tgl; }); - DECLARE_SOA_EXPRESSION_COLUMN(P, p, float, //! Momentum in Gev/c ifnode(nabs(aod::track::signed1Pt) <= o2::constants::math::Almost0, o2::constants::math::VeryBig, 0.5f * (ntan(o2::constants::math::PIQuarter - 0.5f * natan(aod::track::tgl)) + 1.f / ntan(o2::constants::math::PIQuarter - 0.5f * natan(aod::track::tgl))) / nabs(aod::track::signed1Pt))); DECLARE_SOA_DYNAMIC_COLUMN(Energy, energy, //! Track energy, computed under the mass assumption given as input @@ -386,6 +385,7 @@ DECLARE_SOA_TABLE_FULL(StoredTracksIU, "Tracks_IU", "AOD", "TRACK_IU", //! On di track::Px, track::Py, track::Pz, + track::Energy, track::Rapidity, track::Sign, o2::soa::Marker<2>); From 6cc4911bd808429d5b1721189dfa9cbca1a6029f Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 9 Apr 2024 13:23:42 +0200 Subject: [PATCH 0067/2997] Optionally store ref.track together with moved one. --- .../GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx index 51c1a521fc5cc..8ab2696b7e168 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx @@ -77,6 +77,7 @@ class TPCTrackStudySpec : public Task int mTFEnd = 999999999; int mTFCount = -1; bool mUseR = false; + bool mRepRef = false; std::unique_ptr mDBGOut; std::unique_ptr mDBGOutCl; float mITSROFrameLengthMUS = 0.; @@ -99,6 +100,7 @@ void TPCTrackStudySpec::init(InitContext& ic) mXRef = ic.options().get("target-x"); mNMoves = std::max(2, ic.options().get("n-moves")); mUseR = ic.options().get("use-r-as-x"); + mRepRef = ic.options().get("repeat-ini-ref"); mUseGPUModel = ic.options().get("use-gpu-fitter"); mTFStart = ic.options().get("tf-start"); mTFEnd = ic.options().get("tf-end"); @@ -378,7 +380,12 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) << "counter=" << counter << "copy=" << it << "maxCopy=" << mnm - << "movTrackRef=" << trfm + << "movTrackRef=" << trfm; + if (mRepRef) { + (*mDBGOut) << "tpcMov" + << "iniTrackRef=" << trf << "time=" << tr.getTime0(); + } + (*mDBGOut) << "tpcMov" << "imposedTB=" << tb << "dz=" << dz << "clX=" << clX @@ -418,6 +425,7 @@ DataProcessorSpec getTPCTrackStudySpec(GTrackID::mask_t srcTracks, GTrackID::mas {"tf-start", VariantType::Int, 0, {"1st TF to process"}}, {"tf-end", VariantType::Int, 999999999, {"last TF to process"}}, {"use-gpu-fitter", VariantType::Bool, false, {"use GPU track model for refit instead of TrackParCov"}}, + {"repeat-ini-ref", VariantType::Bool, false, {"store ini-refit param with every moved track"}}, {"use-r-as-x", VariantType::Bool, false, {"Use radius instead of target sector X"}}}; auto dataRequest = std::make_shared(); From b05bf82e8df4ea4c552bba780d2ca962b98df240 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Tue, 9 Apr 2024 13:37:21 +0200 Subject: [PATCH 0068/2997] Add Michal to the codeowners of QC-related code --- CODEOWNERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 7eb5c0e544f15..144380ff96161 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -49,7 +49,7 @@ #/DataFormats/Legacy #/DataFormats/MemoryResources /DataFormats/Parameters @shahor02 -/DataFormats/QualityControl @knopers8 @Barthelemy @chiarazampolli +/DataFormats/QualityControl @knopers8 @Barthelemy @justonedev1 @chiarazampolli /DataFormats/Reconstruction @shahor02 #/DataFormats/TimeFrame /DataFormats/common @shahor02 @@ -121,8 +121,8 @@ /Testing /Utilities @AliceO2Group/framework-admins -/Utilities/Mergers @Barthelemy @knopers8 -/Utilities/DataSampling @Barthelemy @knopers8 +/Utilities/Mergers @Barthelemy @knopers8 @justonedev1 +/Utilities/DataSampling @Barthelemy @knopers8 @justonedev1 #/Utilities/DataCompression #/Utilities/DataFlow #/Utilities/MCStepLogger From 433dad6c3c2cfd9fdcbbf9401c690d7e5d79bfe6 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 9 Apr 2024 17:13:48 +0200 Subject: [PATCH 0069/2997] Digitization: Fix timestamps for querying CCDB when using BasicCCDBManager This was wrong, especially for anchoredMC productions where timeframes are sampled from the whole run. --- .../src/SimpleDigitizerWorkflow.cxx | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx index 523c1f2cf6af7..a30294a240fb0 100644 --- a/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx +++ b/Steer/DigitizerWorkflow/src/SimpleDigitizerWorkflow.cxx @@ -228,6 +228,18 @@ void customize(std::vector& policies) policies.push_back({"prompt-for-simreader", matcher, DispatchOp::WhenReady}); } +void setTimingInfoInHeaders(o2::header::DataHeader& dh, o2::framework::DataProcessingHeader& dph) +{ + const auto& hbfu = o2::raw::HBFUtils::Instance(); + const auto offset = int64_t(hbfu.getFirstIRofTF({0, hbfu.orbitFirstSampled}).orbit); + const auto increment = int64_t(hbfu.nHBFPerTF); + const auto startTime = hbfu.startTime; + const auto orbitFirst = hbfu.orbitFirst; + dh.firstTForbit = offset + increment * dh.tfCounter; + dh.runNumber = hbfu.runNumber; + dph.creation = startTime + (dh.firstTForbit - orbitFirst) * o2::constants::lhc::LHCOrbitMUS * 1.e-3; +} + void customize(std::vector& policies) { // we customize the time information sent in DPL headers @@ -239,17 +251,10 @@ void customize(std::vector& policies) // simple linear enumeration from already updated HBFUtils (set via config key values) service.set( [](o2::header::DataHeader& dh, o2::framework::DataProcessingHeader& dph) { - const auto& hbfu = o2::raw::HBFUtils::Instance(); - const auto offset = int64_t(hbfu.getFirstIRofTF({0, hbfu.orbitFirstSampled}).orbit); - const auto increment = int64_t(hbfu.nHBFPerTF); - const auto startTime = hbfu.startTime; - const auto orbitFirst = hbfu.orbitFirst; - dh.firstTForbit = offset + increment * dh.tfCounter; - LOG(info) << "Setting firstTForbit to " << dh.firstTForbit; - dh.runNumber = hbfu.runNumber; - LOG(info) << "Setting runNumber to " << dh.runNumber; - dph.creation = startTime + (dh.firstTForbit - orbitFirst) * o2::constants::lhc::LHCOrbitMUS * 1.e-3; - LOG(info) << "Setting timeframe creation time to " << dph.creation; + setTimingInfoInHeaders(dh, dph); + LOG(info) << "Setting DPL-header firstTForbit to " << dh.firstTForbit; + LOG(info) << "Setting DPL-header runNumber to " << dh.runNumber; + LOG(info) << "Setting DPL-header timeframe creation time to " << dph.creation; }); }} // end of struct ); @@ -486,7 +491,13 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // init on a high level, the time for the CCDB queries // we expect that digitizers do not play with the manager themselves // this will only be needed until digitizers take CCDB objects via DPL mechanism - o2::ccdb::BasicCCDBManager::instance().setTimestamp(hbfu.startTime); + + // fix the timestamp for CCDB manager in the same way as for DPL-CCDB-fetcher + o2::header::DataHeader dh; + o2::framework::DataProcessingHeader dph; + setTimingInfoInHeaders(dh, dph); + LOG(info) << "Setting timestamp of BasicCCDBManager to " << dph.creation; + o2::ccdb::BasicCCDBManager::instance().setTimestamp(dph.creation); // activate caching o2::ccdb::BasicCCDBManager::instance().setCaching(true); // this is asking the manager to check validity only locally - no further query to server done From 7122851fe557266c96d7f12ef430f352a4f192d8 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Wed, 10 Apr 2024 15:05:57 +0200 Subject: [PATCH 0070/2997] DPL Analysis: add ability to have ConfigurableGroup produce prefixed options (#13006) --- Framework/Core/include/Framework/AnalysisManagers.h | 9 +++++++++ Framework/Core/test/test_AnalysisTask.cxx | 2 ++ 2 files changed, 11 insertions(+) diff --git a/Framework/Core/include/Framework/AnalysisManagers.h b/Framework/Core/include/Framework/AnalysisManagers.h index 36a5d7819682c..c8daac1c5edb5 100644 --- a/Framework/Core/include/Framework/AnalysisManagers.h +++ b/Framework/Core/include/Framework/AnalysisManagers.h @@ -532,6 +532,15 @@ struct OptionManager { { /// Recurse, in case we are brace constructible if constexpr (std::is_base_of_v) { + if constexpr (requires { x.prefix; }) { + homogeneous_apply_refs([prefix = x.prefix](C& y) { // apend group prefix if set + if constexpr (requires { y.name; }) { + y.name = prefix + "." + y.name; + } + return true; + }, + x); + } homogeneous_apply_refs([&options](auto& y) { return OptionManager>::appendOption(options, y); }, x); return true; } else { diff --git a/Framework/Core/test/test_AnalysisTask.cxx b/Framework/Core/test/test_AnalysisTask.cxx index dc550ccf3b776..87c8e655d1330 100644 --- a/Framework/Core/test/test_AnalysisTask.cxx +++ b/Framework/Core/test/test_AnalysisTask.cxx @@ -132,9 +132,11 @@ struct TestCCDBObject { struct KTask { struct : public ConfigurableGroup { + std::string prefix = "foo"; Configurable anInt{"someConfigurable", {}, "Some Configurable Object"}; Configurable anotherInt{"someOtherConfigurable", {}, "Some Configurable Object"}; } foo; + Configurable anThirdInt{"someThirdConfigurable", {}, "Some Configurable Object"}; struct : public ConditionGroup { Condition test{"path"}; From 517aa2b62ff9b40a8518d91595572b4d8713295e Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 9 Apr 2024 18:22:41 +0200 Subject: [PATCH 0071/2997] Fix in passing TPC t0 to vdrift calibrations --- .../TPCCalibration/TPCVDriftTglCalibration.h | 2 +- .../TPC/calibration/src/VDriftHelper.cxx | 21 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/TPCVDriftTglCalibration.h b/Detectors/TPC/calibration/include/TPCCalibration/TPCVDriftTglCalibration.h index 2db4cb241eeb9..4964154732aea 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/TPCVDriftTglCalibration.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/TPCVDriftTglCalibration.h @@ -66,7 +66,7 @@ struct TPCVDTglContainer { } driftVFullMean = (driftVFullMean * nTFProc + vfull) / (nTFProc + 1); if (tOffsetRef == 0.f) { - tOffsetRef = data[0].first; // assign 1st full toffset as a reference + tOffsetRef = data[1].first; // assign 1st full toffset as a reference } nTFProc++; } diff --git a/Detectors/TPC/calibration/src/VDriftHelper.cxx b/Detectors/TPC/calibration/src/VDriftHelper.cxx index eca0a6c8e384f..12b43c255d0b3 100644 --- a/Detectors/TPC/calibration/src/VDriftHelper.cxx +++ b/Detectors/TPC/calibration/src/VDriftHelper.cxx @@ -69,6 +69,7 @@ void VDriftHelper::accountLaserCalibration(const LtrCalibData* calib, long fallB mVDLaser.refVDrift = ref; mVDLaser.corrFact = 1. / corr; mVDLaser.creationTime = calib->creationTime; + mVDLaser.refTimeOffset = calib->refTimeOffset; mUpdated = true; mSource = Source::Laser; if (mMayRenormSrc & (0x1U << Source::Laser)) { // this was 1st setting? @@ -79,7 +80,7 @@ void VDriftHelper::accountLaserCalibration(const LtrCalibData* calib, long fallB mMayRenormSrc &= ~(0x1U << Source::Laser); // unset MayRenorm } else if (ref != prevRef) { // we want to keep the same reference over the run, this may happen if run-time laser calibration is supplied LOGP(warn, "VDriftHelper: renorming updated TPC refVDrift={}/correction={} previous refVDrift {}, source: {}", mVDLaser.refVDrift, mVDLaser.corrFact, prevRef, getSourceName(mSource)); - mVDLaser.normalizeOffset(prevRef); + mVDLaser.normalize(prevRef); } } } @@ -134,6 +135,8 @@ void VDriftHelper::extractCCDBInputs(ProcessingContext& pc, bool laser, bool its // prefer among laser and tgl VDrift the one with the latest update time auto saveVD = mVD; mVD = mVDTPCITSTgl.creationTime < mVDLaser.creationTime ? mVDLaser : mVDTPCITSTgl; + auto& loserVD = mVDTPCITSTgl.creationTime < mVDLaser.creationTime ? mVDTPCITSTgl : mVDLaser; + if (mForceParamDrift) { mVD.refVDrift = saveVD.refVDrift; mVD.corrFact = saveVD.corrFact; @@ -144,13 +147,19 @@ void VDriftHelper::extractCCDBInputs(ProcessingContext& pc, bool laser, bool its mVD.timeOffsetCorr = 0.f; } mSource = mVDTPCITSTgl.creationTime < mVDLaser.creationTime ? Source::Laser : Source::ITSTPCTgl; - LOGP(info, "Will prefer TPC Drift from {} with time {} to {} with time {}", - SourceNames[int(mSource)], mVD.creationTime, - mSource == Source::Laser ? SourceNames[int(Source::ITSTPCTgl)] : SourceNames[int(Source::Laser)], - mSource == Source::Laser ? mVDTPCITSTgl.creationTime : mVDLaser.creationTime); + auto loseCTime = loserVD.creationTime; + loserVD = mVD; // override alternative VD to avoid normalization problems later + std::string rep = fmt::format("Prefer TPC Drift from {} with time {} to {} with time {}", + SourceNames[int(mSource)], mVD.creationTime, mSource == Source::Laser ? SourceNames[int(Source::ITSTPCTgl)] : SourceNames[int(Source::Laser)], + mSource == Source::Laser ? mVDTPCITSTgl.creationTime : mVDLaser.creationTime); if (mForceParamDrift || mForceParamOffset) { - LOGP(info, "but {} is imposed from the command line", mForceParamDrift ? "VDrift" : "DriftTimeOffset"); + std::string impos = mForceParamDrift ? "VDrift" : ""; + if (mForceParamOffset) { + impos += mForceParamDrift ? " and DriftTimeOffset" : "DriftTimeOffset"; + } + rep += fmt::format(" but {} imposed from command line", impos); } + LOGP(info, "{}", rep); } } From b19308836abe9d594433adaf53e15470235cd6d3 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 9 Apr 2024 19:40:55 +0200 Subject: [PATCH 0072/2997] Warn about current and TPC scaler object runNumbers only once --- Detectors/TPC/workflow/src/TPCScalerSpec.cxx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Detectors/TPC/workflow/src/TPCScalerSpec.cxx b/Detectors/TPC/workflow/src/TPCScalerSpec.cxx index b184502dfc945..6065079c05e96 100644 --- a/Detectors/TPC/workflow/src/TPCScalerSpec.cxx +++ b/Detectors/TPC/workflow/src/TPCScalerSpec.cxx @@ -85,10 +85,12 @@ class TPCScalerSpec : public Task const auto orbitResetTimeMS = o2::base::GRPGeomHelper::instance().getOrbitResetTimeMS(); const auto firstTFOrbit = pc.services().get().firstTForbit; const double timestamp = orbitResetTimeMS + firstTFOrbit * o2::constants::lhc::LHCOrbitMUS * 0.001; - + int currRun = pc.services().get().runNumber; if (mEnableMShape) { - if ((mMShapeTPCScaler.getRun() != -1) && pc.services().get().runNumber != mMShapeTPCScaler.getRun()) { - LOGP(error, "Run number {} of processed data and run number {} of loaded TPC M-shape scaler doesnt match!", pc.services().get().runNumber, mMShapeTPCScaler.getRun()); + static int runWarningMS = -1; + if ((mMShapeTPCScaler.getRun() != -1) && currRun != mMShapeTPCScaler.getRun() && runWarningMS != currRun) { + LOGP(alarm, "Run number {} of processed data and run number {} of loaded TPC M-shape scaler doesnt match!", pc.services().get().runNumber, mMShapeTPCScaler.getRun()); + runWarningMS = currRun; } const auto& boundaryPotential = mMShapeTPCScaler.getBoundaryPotential(timestamp); @@ -139,8 +141,10 @@ class TPCScalerSpec : public Task } if (mEnableIDCs) { - if (pc.services().get().runNumber != mTPCScaler.getRun()) { - LOGP(error, "Run number {} of processed data and run number {} of loaded TPC scaler doesnt match!", pc.services().get().runNumber, mTPCScaler.getRun()); + static int runWarningIDC = -1; + if (pc.services().get().runNumber != mTPCScaler.getRun() && runWarningIDC != currRun) { + LOGP(alarm, "Run number {} of processed data and run number {} of loaded TPC scaler doesnt match!", pc.services().get().runNumber, mTPCScaler.getRun()); + runWarningIDC = currRun; } float scalerA = mTPCScaler.getMeanScaler(timestamp, o2::tpc::Side::A); float scalerC = mTPCScaler.getMeanScaler(timestamp, o2::tpc::Side::C); From 3e5abd904a3021df0357a1e6cd37a1bb98b445e4 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 9 Apr 2024 15:41:54 +0200 Subject: [PATCH 0073/2997] Group tracks per vertex in the TrackingStudy output, extra info --- .../PrimaryVertexExt.h | 15 +- .../study/CMakeLists.txt | 2 + .../GlobalTrackingStudy/TrackInfoExt.h | 49 ++++++ .../study/src/GlobalTrackingStudyLinkDef.h | 2 + .../study/src/TrackInfoExt.cxx | 14 ++ .../study/src/TrackingStudy.cxx | 166 +++++------------- 6 files changed, 118 insertions(+), 130 deletions(-) create mode 100644 Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackInfoExt.h create mode 100644 Detectors/GlobalTrackingWorkflow/study/src/TrackInfoExt.cxx diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertexExt.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertexExt.h index df807e5a99021..bf47ed03f3b39 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertexExt.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/PrimaryVertexExt.h @@ -27,18 +27,11 @@ struct PrimaryVertexExt : public PrimaryVertex { std::array nSrc{}; // N contributors for each source type std::array nSrcA{}; // N associated and passing cuts for each source type std::array nSrcAU{}; // N ambgous associated and passing cuts for each source type - int VtxID = -1; // original vtx ID + double FT0Time = -1.; // time of closest FT0 trigger float FT0A = -1; // amplitude of closest FT0 A side float FT0C = -1; // amplitude of closest FT0 C side - float FT0Time = -1.; // time of closest FT0 trigger - float rmsT = 0; - float rmsZ = 0; - float rmsTW = 0; - float rmsZW = 0; - float rmsT0 = 0; // w/o ITS - float rmsTW0 = 0; // w/o ITS - float tMAD = 0; - float zMAD = 0; + int VtxID = -1; // original vtx ID + int getNSrc(int i) const { return nSrc[i]; } int getNSrcA(int i) const { return nSrcA[i]; } int getNSrcAU(int i) const { return nSrcAU[i]; } @@ -48,7 +41,7 @@ struct PrimaryVertexExt : public PrimaryVertex { std::string asString() const; #endif - ClassDefNV(PrimaryVertexExt, 5); + ClassDefNV(PrimaryVertexExt, 6); }; #ifndef GPUCA_ALIGPUCODE diff --git a/Detectors/GlobalTrackingWorkflow/study/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/study/CMakeLists.txt index 3d04a12ed7dfd..17bad37b3c14e 100644 --- a/Detectors/GlobalTrackingWorkflow/study/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/study/CMakeLists.txt @@ -20,6 +20,7 @@ o2_add_library(GlobalTrackingStudy src/ITSOffsStudy.cxx src/DumpTracks.cxx src/V0Ext.cxx + src/TrackInfoExt.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTracking O2::GlobalTrackingWorkflowReaders O2::GlobalTrackingWorkflowHelpers @@ -31,6 +32,7 @@ o2_add_library(GlobalTrackingStudy o2_target_root_dictionary( GlobalTrackingStudy HEADERS include/GlobalTrackingStudy/V0Ext.h + include/GlobalTrackingStudy/TrackInfoExt.h ) o2_add_executable(study-workflow diff --git a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackInfoExt.h b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackInfoExt.h new file mode 100644 index 0000000000000..90db0ca4ee37c --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackInfoExt.h @@ -0,0 +1,49 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// class for extended Track info (for debugging) + +#ifndef ALICEO2_TRINFOEXT_H +#define ALICEO2_TRINFOEXT_H + +#include "ReconstructionDataFormats/MatchInfoTOF.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/VtxTrackIndex.h" +#include "ReconstructionDataFormats/Track.h" + +namespace o2 +{ +namespace dataformats +{ + +struct TrackInfoExt { + o2::track::TrackParCov track; + DCA dca{}; + VtxTrackIndex gid; + MatchInfoTOF infoTOF; + float ttime = 0; + float ttimeE = 0; + float xmin = 0; + float chi2ITSTPC = 0.f; + float q2ptITS = 0.f; + float q2ptTPC = 0.f; + float q2ptITSTPC = 0.f; + float q2ptITSTPCTRD = 0.f; + int nClTPC = 0; + int nClITS = 0; + int pattITS = 0; + ClassDefNV(TrackInfoExt, 1); +}; + +} // namespace dataformats +} // namespace o2 + +#endif diff --git a/Detectors/GlobalTrackingWorkflow/study/src/GlobalTrackingStudyLinkDef.h b/Detectors/GlobalTrackingWorkflow/study/src/GlobalTrackingStudyLinkDef.h index 9fa684f316e46..9b14e24d03cb4 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/GlobalTrackingStudyLinkDef.h +++ b/Detectors/GlobalTrackingWorkflow/study/src/GlobalTrackingStudyLinkDef.h @@ -17,6 +17,8 @@ #pragma link C++ class o2::dataformats::ProngInfoExt + ; #pragma link C++ class o2::dataformats::V0Ext + ; +#pragma link C++ class o2::dataformats::TrackInfoExt + ; +#pragma link C++ class std::vector < o2::dataformats::TrackInfoExt> + ; #pragma link C++ class std::vector < o2::dataformats::ProngInfoExt> + ; #pragma link C++ class std::vector < o2::dataformats::V0Ext> + ; diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackInfoExt.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackInfoExt.cxx new file mode 100644 index 0000000000000..f1415e73c10b6 --- /dev/null +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackInfoExt.cxx @@ -0,0 +1,14 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// class for extended track info (for debugging) + +#include "GlobalTrackingStudy/TrackInfoExt.h" diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx index 09e44fe8b36b9..9a0957c1038d2 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx @@ -12,6 +12,7 @@ #include #include #include "DataFormatsGlobalTracking/RecoContainer.h" +#include "DataFormatsITSMFT/TrkClusRef.h" #include "DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h" #include "ReconstructionDataFormats/TrackTPCITS.h" #include "ReconstructionDataFormats/GlobalTrackID.h" @@ -30,6 +31,7 @@ #include "DetectorsCommonDataFormats/DetID.h" #include "DetectorsBase/GRPGeomHelper.h" #include "GlobalTrackingStudy/TrackingStudy.h" +#include "GlobalTrackingStudy/TrackInfoExt.h" #include "TPCBase/ParameterElectronics.h" #include "ReconstructionDataFormats/PrimaryVertex.h" #include "ReconstructionDataFormats/PrimaryVertexExt.h" @@ -80,7 +82,7 @@ class TrackingStudySpec : public Task float mMaxVTTimeDiff = 80.; // \mus float mTPCDCAYCut = 2.; float mTPCDCAZCut = 2.; - float mMinX = 6.; + float mMinX = 46.; float mMaxEta = 0.8; float mMinPt = 0.1; int mMinTPCClusters = 60; @@ -144,23 +146,19 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) static int TFCount = 0; int nv = vtxRefs.size(); o2::dataformats::PrimaryVertexExt pveDummy; - o2::dataformats::PrimaryVertex vtxDummy(mMeanVtx.getPos(), {}, {}, 0); - std::vector pveVec(nv - 1); + o2::dataformats::PrimaryVertexExt vtxDummy(mMeanVtx.getPos(), {}, {}, 0); + std::vector pveVec(nv); + pveVec.back() = vtxDummy; const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); float tBiasITS = alpParams.roFrameBiasInBC * o2::constants::lhc::LHCBunchSpacingMUS; - std::vector dtvec, dzvec; const o2::ft0::InteractionTag& ft0Params = o2::ft0::InteractionTag::Instance(); - + std::vector trcExtVec; for (int iv = 0; iv < nv; iv++) { LOGP(debug, "processing PV {} of {}", iv, nv); const auto& vtref = vtxRefs[iv]; if (iv != nv - 1) { auto& pve = pveVec[iv]; static_cast(pve) = pvvec[iv]; - dtvec.clear(); - dzvec.clear(); - dtvec.reserve(pve.getNContributors()); - dzvec.reserve(pve.getNContributors()); float bestTimeDiff = 1000, bestTime = -999; int bestFTID = -1; if (mTracksSrc[GTrackID::FT0]) { @@ -180,16 +178,11 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) if (bestFTID >= 0) { pve.FT0A = FITInfo[bestFTID].getTrigger().getAmplA(); pve.FT0C = FITInfo[bestFTID].getTrigger().getAmplC(); - pve.FT0Time = FITInfo[bestFTID].getInteractionRecord().differenceInBCMUS(recoData.startIR); + pve.FT0Time = double(FITInfo[bestFTID].getInteractionRecord().differenceInBCMUS(recoData.startIR)) + FITInfo[bestFTID].getCollisionTimeMean() * 1e-6; // time in \mus } pve.VtxID = iv; } - float meanT = 0, meanZ = 0, rmsT = 0, rmsZ = 0; - float meanTW = 0, meanZW = 0, rmsTW = 0, rmsZW = 0, WT = 0, WZ = 0; - float meanT0 = 0, rmsT0 = 0; - float meanTW0 = 0, rmsTW0 = 0, WT0 = 0; - int nContAdd = 0, nContAdd0 = 0, ntITS = 0; - int nAdjusted = 0; + trcExtVec.clear(); float q2ptITS, q2ptTPC, q2ptITSTPC, q2ptITSTPCTRD; for (int is = 0; is < GTrackID::NSources; is++) { DetID::mask_t dm = GTrackID::getSourceDetectorsMask(is); @@ -213,6 +206,7 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) } bool hasITS = GTrackID::getSourceDetectorsMask(is)[GTrackID::ITS]; bool acceptGlo = true; + int nclTPC = 0, nclITS = 0, pattITS = 0; while (1) { // do we cound this track for global multiplicity? if (!(acceptGlo = abs(trc.getEta()) < mMaxEta && trc.getPt() > mMinPt)) { @@ -224,7 +218,7 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) GTrackID tpcTrID; if (GTrackID::getSourceDetectorsMask(is)[GTrackID::TPC] && recoData.isTrackSourceLoaded(GTrackID::TPC) && (tpcTrID = recoData.getTPCContributorGID(vid))) { auto& tpcTr = recoData.getTPCTrack(tpcTrID); - if (!(acceptGlo = tpcTr.getNClusters() >= mMinTPCClusters)) { + if (!(acceptGlo = (nclTPC = tpcTr.getNClusters()) >= mMinTPCClusters)) { break; } } @@ -236,124 +230,58 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) } break; } - if (!hasITS) { continue; } - float ttime = 0, ttimeE = 0; - recoData.getTrackTime(vid, ttime, ttimeE); - bool acceptForPV0 = pvCont; - if (vid.getSource() == GTrackID::ITS) { - ttimeE *= mITSROFrameLengthMUS; - ttime += ttimeE + tBiasITS; - ttimeE *= 1. / sqrt(3); - if (++ntITS > 0) { // do not allow ITS in the MAD - acceptForPV0 = false; - } - } else if (vid.getSource() == GTrackID::ITSTPC) { - float bcf = ttime / o2::constants::lhc::LHCBunchSpacingMUS + o2::constants::lhc::LHCMaxBunches; - int bcWrtROF = int(bcf - alpParams.roFrameBiasInBC) % alpParams.roFrameLengthInBC; - if (bcWrtROF == 0) { - float dbc = bcf - (int(bcf / alpParams.roFrameBiasInBC)) * alpParams.roFrameBiasInBC; - if (std::abs(dbc) < 1e-6 && (++nAdjusted) > 1) { - acceptForPV0 = false; // do not allow more than 1 adjusted track MAD - } - } - } else if (vid.getSource() == GTrackID::TPC) { - ttimeE *= o2::constants::lhc::LHCBunchSpacingMUS * 8; - } - if (pvCont) { - float dt = ttime - pveVec[iv].getTimeStamp().getTimeStamp(); - float tW = 1. / (ttimeE * ttimeE), zW = 1. / trc.getSigmaZ2(); - dzvec.push_back(dca.getZ()); - WT += tW; - WZ += zW; - meanT += dt; - meanTW += dt * tW; - meanZ += dca.getZ(); - meanZW += dca.getZ() * zW; - - rmsT += dt * dt; - rmsTW += dt * dt * tW; - rmsZ += dca.getZ() * dca.getZ(); - rmsZW += dca.getZ() * dca.getZ() * zW; - nContAdd++; - if (acceptForPV0) { - dtvec.push_back(dt); - WT0 += tW; - meanT0 += dt; - meanTW0 += dt * tW; - rmsT0 += dt * dt; - rmsTW0 += dt * dt * tW; - nContAdd0++; - } - LOGP(debug, "dt={} dz={}, tW={}, zW={} t={} tE={} {}", dt, dca.getZ(), tW, zW, ttime, ttimeE, vid.asString()); - } if (acceptGlo) { - q2ptITS = q2ptTPC = q2ptITSTPC = q2ptITSTPCTRD = 0.; + auto& trcExt = trcExtVec.emplace_back(); + recoData.getTrackTime(vid, trcExt.ttime, trcExt.ttimeE); + trcExt.track = trc; + trcExt.dca = dca; + trcExt.gid = vid; + trcExt.xmin = xmin; auto gidRefs = recoData.getSingleDetectorRefs(vid); if (gidRefs[GTrackID::ITS].isIndexSet()) { - q2ptITS = recoData.getTrackParam(gidRefs[GTrackID::ITS]).getQ2Pt(); + const auto& itsTr = recoData.getITSTrack(gidRefs[GTrackID::ITS]); + trcExt.q2ptITS = itsTr.getQ2Pt(); + trcExt.nClITS = itsTr.getNClusters(); + for (int il = 0; il < 7; il++) { + if (itsTr.hasHitOnLayer(il)) { + trcExt.pattITS |= 0x1 << il; + } + } + } else if (gidRefs[GTrackID::ITSAB].isIndexSet()) { + const auto& itsTrf = recoData.getITSABRefs()[gidRefs[GTrackID::ITSAB]]; + trcExt.nClITS = itsTrf.getNClusters(); + for (int il = 0; il < 7; il++) { + if (itsTrf.hasHitOnLayer(il)) { + trcExt.pattITS |= 0x1 << il; + } + } } if (gidRefs[GTrackID::TPC].isIndexSet()) { - q2ptTPC = recoData.getTrackParam(gidRefs[GTrackID::TPC]).getQ2Pt(); + trcExt.q2ptTPC = recoData.getTrackParam(gidRefs[GTrackID::TPC]).getQ2Pt(); + trcExt.nClTPC = nclTPC; } if (gidRefs[GTrackID::ITSTPC].isIndexSet()) { - q2ptITSTPC = recoData.getTrackParam(gidRefs[GTrackID::ITSTPC]).getQ2Pt(); + const auto& trTPCITS = recoData.getTPCITSTrack(gidRefs[GTrackID::ITSTPC]); + trcExt.q2ptITSTPC = trTPCITS.getQ2Pt(); + trcExt.chi2ITSTPC = trTPCITS.getChi2Match(); } if (gidRefs[GTrackID::TRD].isIndexSet()) { - q2ptITSTPCTRD = recoData.getTrackParam(gidRefs[GTrackID::TRD]).getQ2Pt(); + trcExt.q2ptITSTPCTRD = recoData.getTrackParam(gidRefs[GTrackID::TRD]).getQ2Pt(); + } + if (gidRefs[GTrackID::TOF].isIndexSet()) { + trcExt.infoTOF = recoData.getTOFMatch(vid); } - - (*mDBGOut) << "dca" - << "tfID=" << TFCount << "ttime=" << ttime << "ttimeE=" << ttimeE - << "gid=" << vid << "pvid=" << (iv == nv - 1 ? -1 : iv) << "pv=" << (iv == nv - 1 ? vtxDummy : pvvec[iv]) - << "trc=" << trc << "pvCont=" << pvCont << "ambig=" << ambig << "dca=" << dca << "xmin=" << xmin - << "q2ptITS=" << q2ptITS << "q2ptTPC=" << q2ptTPC << "q2ptITSTPC=" << q2ptITSTPC << "q2ptITSTPCTRD=" << q2ptITSTPCTRD - << "\n"; } } } - - if (iv != nv - 1) { - auto& pve = pveVec[iv]; - if (nContAdd) { - rmsT /= nContAdd; - rmsZ /= nContAdd; - meanT /= nContAdd; - meanZ /= nContAdd; - pve.rmsT = (rmsT - meanT * meanT); - pve.rmsT = pve.rmsT > 0 ? std::sqrt(pve.rmsT) : 0; - pve.rmsZ = rmsZ - meanZ * meanZ; - pve.rmsZ = pve.rmsZ > 0 ? std::sqrt(pve.rmsZ) : 0; - } - if (nContAdd0) { - rmsT0 /= nContAdd0; - meanT0 /= nContAdd0; - pve.rmsT0 = (rmsT0 - meanT0 * meanT0); - pve.rmsT0 = pve.rmsT0 > 0 ? std::sqrt(pve.rmsT0) : 0; - } - if (WT0 > 0) { - rmsTW0 /= WT0; - meanTW0 /= WT0; - pve.rmsTW0 = (rmsTW0 - meanTW0 * meanTW0); - pve.rmsTW0 = pve.rmsTW0 > 0 ? std::sqrt(pve.rmsTW0) : 0; - } - // - if (WT > 0 && WZ > 0) { - rmsTW /= WT; - meanTW /= WT; - pve.rmsTW = (rmsTW - meanTW * meanTW); - pve.rmsTW = pve.rmsTW > 0 ? std::sqrt(pve.rmsTW) : 0; - rmsZW /= WZ; - meanZW /= WZ; - pve.rmsZW = rmsZW - meanZW * meanZW; - pve.rmsZW = pve.rmsZ > 0 ? std::sqrt(pve.rmsZ) : 0; - } - pve.tMAD = o2::math_utils::MAD2Sigma(dtvec.size(), dtvec.data()); - pve.zMAD = o2::math_utils::MAD2Sigma(dzvec.size(), dzvec.data()); - } + (*mDBGOut) << "trpv" + << "orbit=" << recoData.startIR.orbit << "tfID=" << TFCount + << "pve=" << pveVec[iv] << "trc=" << trcExtVec << "\n"; } + int nvtot = mMaxNeighbours < 0 ? -1 : (int)pveVec.size(); auto insSlot = [maxSlots = mMaxNeighbours](std::vector& vc, float v, int slot, std::vector& vid, int id) { @@ -499,7 +427,7 @@ DataProcessorSpec getTrackingStudySpec(GTrackID::mask_t srcTracks, GTrackID::mas {"max-tpc-dcaz", VariantType::Float, 2.f, {"Cut on TPC dcaZ"}}, {"max-eta", VariantType::Float, 0.8f, {"Cut on track eta"}}, {"min-pt", VariantType::Float, 0.1f, {"Cut on track pT"}}, - {"min-x-prop", VariantType::Float, 6.f, {"track should be propagated to this X at least"}}, + {"min-x-prop", VariantType::Float, 46.f, {"track should be propagated to this X at least"}}, }}; } From 87b41988273524bbacea6c83cb9d21d656a9c40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Thu, 11 Apr 2024 09:15:21 +0200 Subject: [PATCH 0074/2997] Add momentum vector in track tables (#12991) Allows faster calculation of px, py, pz in one go and reduces code operating with arrays. --- .../Core/include/Framework/AnalysisDataModel.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 634cc490d857a..3f3dab4f01b3c 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -12,9 +12,12 @@ #define O2_FRAMEWORK_ANALYSISDATAMODEL_H_ #include "Framework/ASoA.h" + #include #include #include +#include // std::move + #include "Framework/DataTypes.h" #include "CommonConstants/MathConstants.h" #include "CommonConstants/PhysicsConstants.h" @@ -153,6 +156,17 @@ DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, //! Momentum in z-direction in GeV/c auto pt = 1.f / std::abs(signed1Pt); return pt * tgl; }); +DECLARE_SOA_DYNAMIC_COLUMN(PVector, pVector, //! Momentum vector in x,y,z-directions in GeV/c + [](float signed1Pt, float snp, float alpha, float tgl) -> std::array { + const auto pt = 1.f / std::abs(signed1Pt); + // FIXME: GCC & clang should optimize to sincosf + const float cs = cosf(alpha), sn = sinf(alpha); + const auto r = std::sqrt((1.f - snp) * (1.f + snp)); + const auto px = pt * (r * cs - snp * sn); + const auto py = pt * (snp * cs + r * sn); + const auto pz = pt * tgl; + return std::move(std::array{std::move(px), std::move(py), std::move(pz)}); + }); DECLARE_SOA_EXPRESSION_COLUMN(P, p, float, //! Momentum in Gev/c ifnode(nabs(aod::track::signed1Pt) <= o2::constants::math::Almost0, o2::constants::math::VeryBig, 0.5f * (ntan(o2::constants::math::PIQuarter - 0.5f * natan(aod::track::tgl)) + 1.f / ntan(o2::constants::math::PIQuarter - 0.5f * natan(aod::track::tgl))) / nabs(aod::track::signed1Pt))); DECLARE_SOA_DYNAMIC_COLUMN(Energy, energy, //! Track energy, computed under the mass assumption given as input @@ -366,6 +380,7 @@ DECLARE_SOA_TABLE_FULL(StoredTracks, "Tracks", "AOD", "TRACK", //! On disk versi track::Px, track::Py, track::Pz, + track::PVector, track::Energy, track::Rapidity, track::Sign, @@ -385,6 +400,7 @@ DECLARE_SOA_TABLE_FULL(StoredTracksIU, "Tracks_IU", "AOD", "TRACK_IU", //! On di track::Px, track::Py, track::Pz, + track::PVector, track::Energy, track::Rapidity, track::Sign, From 38140b65b73b1c777b8fa79b388c32aa8fdf7e96 Mon Sep 17 00:00:00 2001 From: Jan Fiete Date: Thu, 11 Apr 2024 09:16:48 +0200 Subject: [PATCH 0075/2997] Add comment to labelledArray types (#13007) --- Framework/Core/include/Framework/Variant.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index d9ef196f56e0d..b8be3a780547e 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -41,16 +41,16 @@ enum class VariantType : int { Int = 0, Array2DInt, Array2DFloat, Array2DDouble, - LabeledArrayInt, - LabeledArrayFloat, - LabeledArrayDouble, + LabeledArrayInt, // 2D array + LabeledArrayFloat, // 2D array + LabeledArrayDouble, // 2D array UInt8, UInt16, UInt32, UInt64, Int8, Int16, - LabeledArrayString, + LabeledArrayString, // 2D array Empty, Dict, Unknown }; From 73179de226a39c6a80ff2cd39f068dfc1b247624 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 11 Apr 2024 09:33:50 +0200 Subject: [PATCH 0076/2997] QC-1143 Merge objects before publishing at End Of Stream (#12998) and make sure it is tested --- .../include/Mergers/IntegratingMerger.h | 1 + Utilities/Mergers/src/FullHistoryMerger.cxx | 1 + Utilities/Mergers/src/IntegratingMerger.cxx | 44 +++++++++++-------- Utilities/Mergers/test/common.h | 21 +++++++++ Utilities/Mergers/test/customTopologyCommon.h | 20 +++++++-- Utilities/Mergers/test/histosTopologyCommon.h | 10 ++++- .../test_MergerTopologyHistosFullHistory.cxx | 2 +- Utilities/Mergers/test/vectorTopologyCommon.h | 9 +++- 8 files changed, 80 insertions(+), 28 deletions(-) diff --git a/Utilities/Mergers/include/Mergers/IntegratingMerger.h b/Utilities/Mergers/include/Mergers/IntegratingMerger.h index 2fedcda0f3b44..8a6cecc437d1e 100644 --- a/Utilities/Mergers/include/Mergers/IntegratingMerger.h +++ b/Utilities/Mergers/include/Mergers/IntegratingMerger.h @@ -55,6 +55,7 @@ class IntegratingMerger : public framework::Task void endOfStream(framework::EndOfStreamContext& eosContext) override; private: + void finishCycle(framework::DataAllocator& outputs); void publishIntegral(framework::DataAllocator& allocator); void publishMovingWindow(framework::DataAllocator& allocator); static void merge(ObjectStore& mMergedDelta, ObjectStore&& other); diff --git a/Utilities/Mergers/src/FullHistoryMerger.cxx b/Utilities/Mergers/src/FullHistoryMerger.cxx index a2836e63732e0..2ed05d46c0e8a 100644 --- a/Utilities/Mergers/src/FullHistoryMerger.cxx +++ b/Utilities/Mergers/src/FullHistoryMerger.cxx @@ -90,6 +90,7 @@ void FullHistoryMerger::run(framework::ProcessingContext& ctx) void FullHistoryMerger::endOfStream(framework::EndOfStreamContext& eosContext) { + mergeCache(); publish(eosContext.outputs()); } diff --git a/Utilities/Mergers/src/IntegratingMerger.cxx b/Utilities/Mergers/src/IntegratingMerger.cxx index f935628ff94b5..749becd463a5d 100644 --- a/Utilities/Mergers/src/IntegratingMerger.cxx +++ b/Utilities/Mergers/src/IntegratingMerger.cxx @@ -69,31 +69,37 @@ void IntegratingMerger::run(framework::ProcessingContext& ctx) } if (ctx.inputs().isValid("timer-publish")) { - mCyclesSinceReset++; + finishCycle(ctx.outputs()); + } +} - if (mConfig.publishMovingWindow.value == PublishMovingWindow::Yes) { - publishMovingWindow(ctx.outputs()); - } +void IntegratingMerger::finishCycle(DataAllocator& outputs) +{ + mCyclesSinceReset++; - if (!std::holds_alternative(mMergedObjectLastCycle)) { - merge(mMergedObjectIntegral, std::move(mMergedObjectLastCycle)); - } - mMergedObjectLastCycle = std::monostate{}; - mTotalDeltasMerged += mDeltasMerged; + if (mConfig.publishMovingWindow.value == PublishMovingWindow::Yes) { + publishMovingWindow(outputs); + } - publishIntegral(ctx.outputs()); + if (!std::holds_alternative(mMergedObjectLastCycle)) { + merge(mMergedObjectIntegral, std::move(mMergedObjectLastCycle)); + } + mMergedObjectLastCycle = std::monostate{}; + mTotalDeltasMerged += mDeltasMerged; - if (mConfig.mergedObjectTimespan.value == MergedObjectTimespan::LastDifference || - mConfig.mergedObjectTimespan.value == MergedObjectTimespan::NCycles && mConfig.mergedObjectTimespan.param == mCyclesSinceReset) { - clear(); - } + publishIntegral(outputs); - mCollector->send({mTotalDeltasMerged, "total_deltas_merged"}, monitoring::DerivedMetricMode::RATE); - mCollector->send({mDeltasMerged, "deltas_merged_since_last_publication"}); - mCollector->send({mCyclesSinceReset, "cycles_since_reset"}); - mDeltasMerged = 0; + if (mConfig.mergedObjectTimespan.value == MergedObjectTimespan::LastDifference || + mConfig.mergedObjectTimespan.value == MergedObjectTimespan::NCycles && mConfig.mergedObjectTimespan.param == mCyclesSinceReset) { + clear(); } + + mCollector->send({mTotalDeltasMerged, "total_deltas_merged"}, monitoring::DerivedMetricMode::RATE); + mCollector->send({mDeltasMerged, "deltas_merged_since_last_publication"}); + mCollector->send({mCyclesSinceReset, "cycles_since_reset"}); + mDeltasMerged = 0; } + void IntegratingMerger::merge(ObjectStore& target, ObjectStore&& other) { if (std::holds_alternative(target)) { @@ -121,7 +127,7 @@ void IntegratingMerger::merge(ObjectStore& target, ObjectStore&& other) void IntegratingMerger::endOfStream(framework::EndOfStreamContext& eosContext) { - publishIntegral(eosContext.outputs()); + finishCycle(eosContext.outputs()); } // I am not calling it reset(), because it does not have to be performed during the FairMQs reset. diff --git a/Utilities/Mergers/test/common.h b/Utilities/Mergers/test/common.h index e85e256cd513a..c2726959bb8ac 100644 --- a/Utilities/Mergers/test/common.h +++ b/Utilities/Mergers/test/common.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace o2::mergers::test { @@ -22,6 +23,26 @@ inline auto to_span(const TH1F& histo) { return gsl::span(histo.GetArray(), histo.GetSize()); } + +void registerCallbacksForTestFailure(framework::CallbackService& cb, std::shared_ptr success) +{ + cb.set([success](framework::EndOfStreamContext& ctx) { + if (*success == false) { + LOG(fatal) << "Received an EndOfStream without having received the expected object"; + } + }); + cb.set([success]() { + if (*success == false) { + LOG(fatal) << "STOP transition without having received the expected object"; + } + }); + cb.set([success](framework::ServiceRegistryRef) { + if (*success == false) { + LOG(fatal) << "EXIT transition without having received the expected object"; + } + }); +} + } // namespace o2::mergers::test namespace std diff --git a/Utilities/Mergers/test/customTopologyCommon.h b/Utilities/Mergers/test/customTopologyCommon.h index 13c745d6f8a91..6233cb53bd215 100644 --- a/Utilities/Mergers/test/customTopologyCommon.h +++ b/Utilities/Mergers/test/customTopologyCommon.h @@ -24,6 +24,7 @@ #include #include #include +#include "common.h" void customize(std::vector& policies) { @@ -109,9 +110,12 @@ class CustomMergerTestGenerator }, Outputs{}, AlgorithmSpec{ - AlgorithmSpec::InitCallback{[expectedResult = mExpectedResult](InitContext&) { + AlgorithmSpec::InitCallback{[expectedResult = mExpectedResult](InitContext& initContext) { + auto success = std::make_shared(false); + mergers::test::registerCallbacksForTestFailure(initContext.services().get(), success); + return AlgorithmSpec::ProcessCallback{ - [expectedResult, numberOfCalls = 0, numberOfObjects = 0, numberOfMovingWindows = 0, lastObjectValue = 0, retries = 5](ProcessingContext& processingContext) mutable { + [expectedResult, numberOfCalls = 0, numberOfObjects = 0, numberOfMovingWindows = 0, lastObjectValue = 0, retries = 5, success](ProcessingContext& processingContext) mutable { numberOfCalls++; if (processingContext.inputs().isValid("custom")) { @@ -139,7 +143,10 @@ class CustomMergerTestGenerator if (lastObjectValue != expectedResult) { LOG(fatal) << "got wrong secret from object: " << lastObjectValue << ", expected: " << expectedResult; } + return; } + LOG(info) << "Received the expected objects, test successful"; + *success = true; } }}; }}}}); @@ -154,12 +161,17 @@ class CustomMergerTestGenerator }, Outputs{}, AlgorithmSpec{ - AlgorithmSpec::InitCallback{[expectedResult = mExpectedResult](InitContext&) { + AlgorithmSpec::InitCallback{[expectedResult = mExpectedResult](InitContext& initContext) { + auto success = std::make_shared(false); + mergers::test::registerCallbacksForTestFailure(initContext.services().get(), success); + return AlgorithmSpec::ProcessCallback{ - [expectedResult, retryNumber = 0, numberOfRetries = 5](ProcessingContext& processingContext) mutable { + [expectedResult, retryNumber = 0, numberOfRetries = 5, success](ProcessingContext& processingContext) mutable { const auto obj = processingContext.inputs().get("custom"); if (obj->getSecret() == expectedResult) { + LOG(info) << "Received the expected object, test successful"; + *success = true; processingContext.services().get().readyToQuit(QuitRequest::All); return; } diff --git a/Utilities/Mergers/test/histosTopologyCommon.h b/Utilities/Mergers/test/histosTopologyCommon.h index 7c713b3409747..d2305e3f6e6f2 100644 --- a/Utilities/Mergers/test/histosTopologyCommon.h +++ b/Utilities/Mergers/test/histosTopologyCommon.h @@ -71,6 +71,7 @@ class HistosMergerTestGenerator "histo", "histo", histoBinsCount, histoMin, histoMax); histo.Fill(5); histo.Fill(producerIdx); + processingContext.services().get().endOfStream(); processingContext.services().get().readyToQuit(QuitRequest::Me); })}}); } @@ -103,14 +104,19 @@ class HistosMergerTestGenerator Inputs{{"histo", origin, description, 0, Lifetime::Sporadic}}, Outputs{}, AlgorithmSpec{ - AlgorithmSpec::InitCallback{[expectedResult = mExpectedResult](InitContext&) { + AlgorithmSpec::InitCallback{[expectedResult = mExpectedResult](InitContext& initContext) { + auto success = std::make_shared(false); + mergers::test::registerCallbacksForTestFailure(initContext.services().get(), success); + // reason for this crude retry is that multiple layers are not synchronized between each other and publish on their own timers, // number of retries is chosen arbitrarily as we need to retry at least twice - return AlgorithmSpec::ProcessCallback{[expectedResult, retryNumber = 1, retries = 5](ProcessingContext& processingContext) mutable { + return AlgorithmSpec::ProcessCallback{[expectedResult, retryNumber = 1, retries = 5, success](ProcessingContext& processingContext) mutable { const auto histo = processingContext.inputs().get("histo"); LOG(info) << "RETRY: " << retryNumber << ": comparing: " << std::to_string(histo) << " to the expected: " << std::to_string(expectedResult); if (std::equal(expectedResult.begin(), expectedResult.end(), histo->GetArray(), histo->GetArray() + histo->GetSize())) { + LOG(info) << "Received the expected object, test successful"; + *success = true; processingContext.services().get().readyToQuit(QuitRequest::All); return; } diff --git a/Utilities/Mergers/test/test_MergerTopologyHistosFullHistory.cxx b/Utilities/Mergers/test/test_MergerTopologyHistosFullHistory.cxx index d08f6ee077edf..5ac18f998d444 100644 --- a/Utilities/Mergers/test/test_MergerTopologyHistosFullHistory.cxx +++ b/Utilities/Mergers/test/test_MergerTopologyHistosFullHistory.cxx @@ -32,7 +32,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const&) const auto mergersInputs = generator.generateHistoProducers(specs, producersCount); - generator.generateMergers(specs, mergersInputs, InputObjectsTimespan::LastDifference); + generator.generateMergers(specs, mergersInputs, InputObjectsTimespan::FullHistory); generator.generateChecker(specs); diff --git a/Utilities/Mergers/test/vectorTopologyCommon.h b/Utilities/Mergers/test/vectorTopologyCommon.h index d98576fd094f1..34dcc8515a04a 100644 --- a/Utilities/Mergers/test/vectorTopologyCommon.h +++ b/Utilities/Mergers/test/vectorTopologyCommon.h @@ -127,15 +127,20 @@ class VectorMergerTestGenerator Inputs{{"vec", origin, description, 0, Lifetime::Sporadic}}, Outputs{}, AlgorithmSpec{ - AlgorithmSpec::InitCallback{[expectedResult = mExpectedResult](InitContext&) { + AlgorithmSpec::InitCallback{[expectedResult = mExpectedResult](InitContext& initContext) { + auto success = std::make_shared(false); + mergers::test::registerCallbacksForTestFailure(initContext.services().get(), success); + // reason for this crude retry is that multiple layers are not synchronized between each other and publish on their own timers. // number of retries was chosen a bit randomly, as we need to have at least 2 runs through this function because of publish // timers inside of the mergers - return AlgorithmSpec::ProcessCallback{[expectedResult, retryNumber = 1, retries = 5](ProcessingContext& processingContext) mutable { + return AlgorithmSpec::ProcessCallback{[expectedResult, retryNumber = 1, retries = 5, success](ProcessingContext& processingContext) mutable { const auto vectorOfHistos = processingContext.inputs().get*>("vec"); LOG(info) << "RETRY: " << retryNumber << ": comparing: " << std::to_string(vectorOfHistos) << " to the expected: " << std::to_string(expectedResult); if (vectorOfHistos == expectedResult) { + LOG(info) << "Received the expected object, test successful"; + *success = true; processingContext.services().get().readyToQuit(QuitRequest::All); return; } From 2e6feb6bc9fa8bd5cfe0d719feecb76a6e0456ee Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 10 Apr 2024 23:56:07 +0200 Subject: [PATCH 0077/2997] rct-updater defines dummy output to bind ccdb-populator --- Detectors/GRP/workflows/CMakeLists.txt | 1 + Detectors/GRP/workflows/src/rct-updater-workflow.cxx | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Detectors/GRP/workflows/CMakeLists.txt b/Detectors/GRP/workflows/CMakeLists.txt index 5de19f9061d8b..ea56cf8270335 100644 --- a/Detectors/GRP/workflows/CMakeLists.txt +++ b/Detectors/GRP/workflows/CMakeLists.txt @@ -37,6 +37,7 @@ o2_add_executable(workflow PUBLIC_LINK_LIBRARIES O2::Framework O2::CCDB O2::DetectorsBase + O2::DetectorsCalibration O2::DataFormatsParameters) o2_add_executable(grp-create diff --git a/Detectors/GRP/workflows/src/rct-updater-workflow.cxx b/Detectors/GRP/workflows/src/rct-updater-workflow.cxx index e5f64f32e2a7a..3020f236aff53 100644 --- a/Detectors/GRP/workflows/src/rct-updater-workflow.cxx +++ b/Detectors/GRP/workflows/src/rct-updater-workflow.cxx @@ -15,6 +15,7 @@ #include "Framework/InputSpec.h" #include "Framework/Task.h" #include "CommonUtils/ConfigurableParam.h" +#include "DetectorsCalibration/Utils.h" using namespace o2::framework; @@ -164,6 +165,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) WorkflowSpec specs; o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); std::vector inputs{{"ctfdone", "CTF", "DONE", 0, Lifetime::Timeframe}}; + std::vector outputs; + outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBPayload, "RCTUPD_DUMMY"}, Lifetime::Sporadic); + outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBWrapper, "RCTUPD_DUMMY"}, Lifetime::Sporadic); auto ggRequest = std::make_shared(true, // orbitResetTime true, // GRPECS=true false, // GRPLHCIF @@ -175,7 +179,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) specs.push_back(DataProcessorSpec{ "rct-updater", inputs, - {}, + outputs, AlgorithmSpec{adaptFromTask(ggRequest)}, Options{ {"update-interval", VariantType::Float, 1.f, {"update every ... seconds"}}, From 42c85865cc27ef2acb8f97d81c82a9ee24f238ec Mon Sep 17 00:00:00 2001 From: JianLIUhep Date: Thu, 28 Mar 2024 13:44:41 +0100 Subject: [PATCH 0078/2997] Added check on STROBE_LENGTH parameter --- .../ITSMFT/common/workflow/src/STFDecoderSpec.cxx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index 2b80a5ffcac01..f4b71cbf0a0b8 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -159,7 +159,8 @@ void STFDecoder::run(ProcessingContext& pc) mDecoder->setDecodeNextAuto(false); o2::InteractionRecord lastIR{}, firstIR{0, pc.services().get().firstTForbit}; - while (mDecoder->decodeNextTrigger() >= 0) { + int nTriggersProcessed =0; + while (mDecoder->decodeNextTrigger() >= 0) { if ((!lastIR.isDummy() && lastIR >= mDecoder->getInteractionRecord()) || firstIR > mDecoder->getInteractionRecord()) { const int MaxErrLog = 2; static int errLocCount = 0; @@ -171,6 +172,7 @@ void STFDecoder::run(ProcessingContext& pc) lastIR = mDecoder->getInteractionRecord(); if (mDoDigits || mClusterer->getMaxROFDepthToSquash()) { // call before clusterization, since the latter will hide the digits mDecoder->fillDecodedDigits(digVec, digROFVec, chipStatus); // lot of copying involved + if (mDoCalibData) { mDecoder->fillCalibData(calVec); } @@ -180,8 +182,14 @@ void STFDecoder::run(ProcessingContext& pc) if (mDoClusters && !mClusterer->getMaxROFDepthToSquash()) { // !!! THREADS !!! mClusterer->process(mNThreads, *mDecoder.get(), &clusCompVec, mDoPatterns ? &clusPattVec : nullptr, &clusROFVec); } + nTriggersProcessed++; } + const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); + std::cout<<"mTFCounter= "<< mTFCounter << " from params: "<< 3564*32/alpParams.roFrameLengthInBC << " from redout: "<< nTriggersProcessed<< " number from geometry: "<< o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF()<(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); + if ( (expectedValue != nTriggersProcessed) && mTFCounter > 1) LOG(fatal)<< "Inconsistant size of ROF and Strobbing rate, from parameters: "<< 3564*32/alpParams.roFrameLengthInBC << " from readout: "<< nTriggersProcessed; + if (mDoClusters && mClusterer->getMaxROFDepthToSquash()) { // Digits squashing require to run on a batch of digits and uses a digit reader, cannot (?) run with decoder // - Setup decoder for running on a batch of digits From c909fc577c8b398dee8f5f7c27a2f584107c2478 Mon Sep 17 00:00:00 2001 From: JianLIUhep Date: Thu, 28 Mar 2024 13:53:09 +0100 Subject: [PATCH 0079/2997] Clang --- .../ITSMFT/common/workflow/src/STFDecoderSpec.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index f4b71cbf0a0b8..c4fe2afee8a17 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -159,8 +159,8 @@ void STFDecoder::run(ProcessingContext& pc) mDecoder->setDecodeNextAuto(false); o2::InteractionRecord lastIR{}, firstIR{0, pc.services().get().firstTForbit}; - int nTriggersProcessed =0; - while (mDecoder->decodeNextTrigger() >= 0) { + int nTriggersProcessed = 0; + while (mDecoder->decodeNextTrigger() >= 0) { if ((!lastIR.isDummy() && lastIR >= mDecoder->getInteractionRecord()) || firstIR > mDecoder->getInteractionRecord()) { const int MaxErrLog = 2; static int errLocCount = 0; @@ -170,7 +170,7 @@ void STFDecoder::run(ProcessingContext& pc) continue; } lastIR = mDecoder->getInteractionRecord(); - if (mDoDigits || mClusterer->getMaxROFDepthToSquash()) { // call before clusterization, since the latter will hide the digits + if (mDoDigits || mClusterer->getMaxROFDepthToSquash()) { // call before clusterization, since the latter will hide the digits mDecoder->fillDecodedDigits(digVec, digROFVec, chipStatus); // lot of copying involved if (mDoCalibData) { @@ -186,9 +186,9 @@ void STFDecoder::run(ProcessingContext& pc) } const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); - std::cout<<"mTFCounter= "<< mTFCounter << " from params: "<< 3564*32/alpParams.roFrameLengthInBC << " from redout: "<< nTriggersProcessed<< " number from geometry: "<< o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF()<(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); - if ( (expectedValue != nTriggersProcessed) && mTFCounter > 1) LOG(fatal)<< "Inconsistant size of ROF and Strobbing rate, from parameters: "<< 3564*32/alpParams.roFrameLengthInBC << " from readout: "<< nTriggersProcessed; + int expectedTFSize = static_cast(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); // 3564*32 / ROF Length in BS = number of ROFs per TF + if ((expectedTFSize != nTriggersProcessed) && mTFCounter > 1) + LOG(fatal) << "Inconsistent number of ROF per TF. From parameters: " << expectedTFSize << " from readout: " << nTriggersProcessed; if (mDoClusters && mClusterer->getMaxROFDepthToSquash()) { // Digits squashing require to run on a batch of digits and uses a digit reader, cannot (?) run with decoder From 8cbe46ed54c57b5db9733349e42ae2dbdc5f4483 Mon Sep 17 00:00:00 2001 From: JianLIUhep Date: Thu, 28 Mar 2024 14:56:39 +0100 Subject: [PATCH 0080/2997] Changed LOG level from FATAL to ERROR --- Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index c4fe2afee8a17..f665209d86094 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -188,7 +188,7 @@ void STFDecoder::run(ProcessingContext& pc) const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); int expectedTFSize = static_cast(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); // 3564*32 / ROF Length in BS = number of ROFs per TF if ((expectedTFSize != nTriggersProcessed) && mTFCounter > 1) - LOG(fatal) << "Inconsistent number of ROF per TF. From parameters: " << expectedTFSize << " from readout: " << nTriggersProcessed; + LOG(error) << "Inconsistent number of ROF per TF. From parameters: " << expectedTFSize << " from readout: " << nTriggersProcessed; if (mDoClusters && mClusterer->getMaxROFDepthToSquash()) { // Digits squashing require to run on a batch of digits and uses a digit reader, cannot (?) run with decoder From b13ad43b322193a1bb8ec0e597934315228ed9a4 Mon Sep 17 00:00:00 2001 From: JianLIUhep Date: Thu, 4 Apr 2024 10:30:49 +0200 Subject: [PATCH 0081/2997] Fixed cases when nROFs could be calculated wrongly --- .../include/ITSMFTReconstruction/RawPixelDecoder.h | 1 + .../ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx | 3 ++- Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index 0047f8311ba29..a6f44a984ce01 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -120,6 +120,7 @@ class RawPixelDecoder final : public PixelReader void setSkipRampUpData(bool v = true) { mSkipRampUpData = v; } bool getSkipRampUpData() const { return mSkipRampUpData; } + auto getNROFsProcessed() const { return mROFCounter; } struct LinkEntry { int entry = -1; diff --git a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx index 1443744c5ce79..b0db826fd30b1 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx @@ -95,6 +95,8 @@ int RawPixelDecoder::decodeNextTrigger() collectROFCableData(iru); } + mROFCounter++; + if (!doIRMajorityPoll()) { continue; // no links with data } @@ -114,7 +116,6 @@ int RawPixelDecoder::decodeNextTrigger() if (mNChipsFiredROF || (mAlloEmptyROFs && mNLinksDone < mNLinksInTF)) { // fill some statistics mTrigger = mLinkForTriggers ? mLinkForTriggers->trigger : 0; - mROFCounter++; mNChipsFired += mNChipsFiredROF; mNPixelsFired += mNPixelsFiredROF; mCurRUDecodeID = 0; // getNextChipData will start from here diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index f665209d86094..a098f82f3cd1e 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -159,7 +159,7 @@ void STFDecoder::run(ProcessingContext& pc) mDecoder->setDecodeNextAuto(false); o2::InteractionRecord lastIR{}, firstIR{0, pc.services().get().firstTForbit}; - int nTriggersProcessed = 0; + int nTriggersProcessed = mDecoder->getNROFsProcessed(); while (mDecoder->decodeNextTrigger() >= 0) { if ((!lastIR.isDummy() && lastIR >= mDecoder->getInteractionRecord()) || firstIR > mDecoder->getInteractionRecord()) { const int MaxErrLog = 2; @@ -167,6 +167,7 @@ void STFDecoder::run(ProcessingContext& pc) if (errLocCount++ < MaxErrLog) { LOGP(warn, "Impossible ROF IR {}, previous was {}, TF 1st IR was {}, discarding in decoding", mDecoder->getInteractionRecord().asString(), lastIR.asString(), firstIR.asString()); } + nTriggersProcessed = 0x7fffffff; // to account for a problem with event continue; } lastIR = mDecoder->getInteractionRecord(); @@ -182,8 +183,8 @@ void STFDecoder::run(ProcessingContext& pc) if (mDoClusters && !mClusterer->getMaxROFDepthToSquash()) { // !!! THREADS !!! mClusterer->process(mNThreads, *mDecoder.get(), &clusCompVec, mDoPatterns ? &clusPattVec : nullptr, &clusROFVec); } - nTriggersProcessed++; } + nTriggersProcessed = mDecoder->getNROFsProcessed() - nTriggersProcessed - 1; const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); int expectedTFSize = static_cast(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); // 3564*32 / ROF Length in BS = number of ROFs per TF From 85c29619b33ebd57e6a880bcb3ff50444a5dcbb8 Mon Sep 17 00:00:00 2001 From: JianLIUhep Date: Thu, 4 Apr 2024 10:38:05 +0200 Subject: [PATCH 0082/2997] small fix for condition --- Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index a098f82f3cd1e..6b4f30a8ff29b 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -188,7 +188,7 @@ void STFDecoder::run(ProcessingContext& pc) const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); int expectedTFSize = static_cast(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); // 3564*32 / ROF Length in BS = number of ROFs per TF - if ((expectedTFSize != nTriggersProcessed) && mTFCounter > 1) + if ((expectedTFSize != nTriggersProcessed) && mTFCounter > 1 && nTriggersProcessed > 0) LOG(error) << "Inconsistent number of ROF per TF. From parameters: " << expectedTFSize << " from readout: " << nTriggersProcessed; if (mDoClusters && mClusterer->getMaxROFDepthToSquash()) { From ec3ea8f47ec4e56b9611136136359b70639c335e Mon Sep 17 00:00:00 2001 From: JianLIUhep Date: Wed, 10 Apr 2024 12:06:23 +0200 Subject: [PATCH 0083/2997] Fixed clang suggestion --- Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index 6b4f30a8ff29b..cf605d3c0ce33 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -188,7 +188,7 @@ void STFDecoder::run(ProcessingContext& pc) const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); int expectedTFSize = static_cast(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); // 3564*32 / ROF Length in BS = number of ROFs per TF - if ((expectedTFSize != nTriggersProcessed) && mTFCounter > 1 && nTriggersProcessed > 0) + if ((expectedTFSize != nTriggersProcessed) && (mTFCounter > 1) && (nTriggersProcessed > 0)) LOG(error) << "Inconsistent number of ROF per TF. From parameters: " << expectedTFSize << " from readout: " << nTriggersProcessed; if (mDoClusters && mClusterer->getMaxROFDepthToSquash()) { From f23fabe857a06446f7d12f24bdae54408e9fafba Mon Sep 17 00:00:00 2001 From: Ruben Shahoyan Date: Wed, 10 Apr 2024 17:13:08 +0200 Subject: [PATCH 0084/2997] Fix braces --- Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index cf605d3c0ce33..0e0b0dabaa070 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -188,9 +188,9 @@ void STFDecoder::run(ProcessingContext& pc) const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); int expectedTFSize = static_cast(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); // 3564*32 / ROF Length in BS = number of ROFs per TF - if ((expectedTFSize != nTriggersProcessed) && (mTFCounter > 1) && (nTriggersProcessed > 0)) + if ((expectedTFSize != nTriggersProcessed) && mTFCounter > 1 && nTriggersProcessed > 0) { LOG(error) << "Inconsistent number of ROF per TF. From parameters: " << expectedTFSize << " from readout: " << nTriggersProcessed; - + } if (mDoClusters && mClusterer->getMaxROFDepthToSquash()) { // Digits squashing require to run on a batch of digits and uses a digit reader, cannot (?) run with decoder // - Setup decoder for running on a batch of digits From 8690200036b5e284f77f7aac7cb70239a6b2368c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Wed, 20 Mar 2024 18:30:17 +0100 Subject: [PATCH 0085/2997] Add missing std namespace specifier in AnalysisDataModel --- Framework/Core/include/Framework/AnalysisDataModel.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 3f3dab4f01b3c..34fe8ddf5dd2d 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -172,16 +172,16 @@ DECLARE_SOA_EXPRESSION_COLUMN(P, p, float, //! Momentum in Gev/c DECLARE_SOA_DYNAMIC_COLUMN(Energy, energy, //! Track energy, computed under the mass assumption given as input [](float signed1Pt, float tgl, float mass) -> float { const auto pt = 1.f / std::abs(signed1Pt); - const auto p = 0.5f * (tan(o2::constants::math::PIQuarter - 0.5f * atan(tgl)) + 1.f / tan(o2::constants::math::PIQuarter - 0.5f * atan(tgl))) * pt; - return sqrt(p * p + mass * mass); + const auto p = 0.5f * (std::tan(o2::constants::math::PIQuarter - 0.5f * std::atan(tgl)) + 1.f / std::tan(o2::constants::math::PIQuarter - 0.5f * std::atan(tgl))) * pt; + return std::sqrt(p * p + mass * mass); }); DECLARE_SOA_DYNAMIC_COLUMN(Rapidity, rapidity, //! Track rapidity, computed under the mass assumption given as input [](float signed1Pt, float tgl, float mass) -> float { const auto pt = 1.f / std::abs(signed1Pt); const auto pz = pt * tgl; - const auto p = 0.5f * (tan(o2::constants::math::PIQuarter - 0.5f * atan(tgl)) + 1.f / tan(o2::constants::math::PIQuarter - 0.5f * atan(tgl))) * pt; - const auto energy = sqrt(p * p + mass * mass); - return 0.5f * log((energy + pz) / (energy - pz)); + const auto p = 0.5f * (std::tan(o2::constants::math::PIQuarter - 0.5f * std::atan(tgl)) + 1.f / std::tan(o2::constants::math::PIQuarter - 0.5f * std::atan(tgl))) * pt; + const auto energy = std::sqrt(p * p + mass * mass); + return 0.5f * std::log((energy + pz) / (energy - pz)); }); // TRACKPARCOV TABLE definition From 87d05f3c11b27835ea85b99cad50df4d7fce4cc3 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Thu, 11 Apr 2024 11:20:45 +0200 Subject: [PATCH 0086/2997] [EMCAL-1120] Encode trailer in decimal format instead of hex format. (#12996) Since working with plain text all instructions must be encoded in decimal format, as the decoder requires decimal format as well. --- Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx b/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx index ef10423a2c97d..38a6e386c9ca6 100644 --- a/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx +++ b/Detectors/EMCAL/calibration/src/EMCALPedestalHelper.cxx @@ -84,7 +84,7 @@ std::vector EMCALPedestalHelper::createInstructionString(const int runNum) std::stringstream fout; if (runNum > 0) { - fout << runNum << "\n"; + fout << runNum << std::endl; } unsigned int lineValue = 0; @@ -93,6 +93,8 @@ std::vector EMCALPedestalHelper::createInstructionString(const int runNum) // const unsigned int FECwordCode = 0x80000000; const unsigned int FEClineCode = 0x40000000; + const unsigned int TrailerLineCode = 0xFFFFFFFF; + short iSM = 0; short iRCU = 0; short ibranch = 0; @@ -181,7 +183,7 @@ std::vector EMCALPedestalHelper::createInstructionString(const int runNum) } // iSM if (runNum > 0) { - fout << 0xFFFFFFFF << std::endl; + fout << TrailerLineCode << std::endl; } const std::string instructionString(fout.str()); From 933b3e3d50546f097a368b9e2aa762a536313b5d Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Thu, 11 Apr 2024 15:19:00 +0200 Subject: [PATCH 0087/2997] Alice3: add minimal documentation + Magnetic field macro (#13011) --- Detectors/Upgrades/ALICE3/README.md | 69 +++++++++++++++++++ .../Upgrades/ALICE3/macros/ALICE3Field.C | 66 ++++++++++++++++++ cmake/O2RootMacroExclusionList.cmake | 3 +- 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 Detectors/Upgrades/ALICE3/README.md create mode 100644 Detectors/Upgrades/ALICE3/macros/ALICE3Field.C diff --git a/Detectors/Upgrades/ALICE3/README.md b/Detectors/Upgrades/ALICE3/README.md new file mode 100644 index 0000000000000..50789a546377f --- /dev/null +++ b/Detectors/Upgrades/ALICE3/README.md @@ -0,0 +1,69 @@ +# ALICE 3 full simulation + +## Simulation +### Simulation software for Run 5 +Current simulation approach for ALICE 3 is a specification of what it is used in the main O2 simulation package. +It shares the same structure and possibly inherits all the features in place already. +For all of the features that are not really Run-5 specific please refer to the official [O2 Simulation Documentation](https://aliceo2group.github.io/simulation/docs/). + +### Rationale for the "Upgrades" codebase +Run 5 code for the detectors is stored in the `Detectors/Upgrades/ALICE3` directory and its suboflder strucure mimicks the same we have in `Detectors`. +For specific data formats the plan is to keep the same approach in `DataFormats/Upgrades`. + +### Available modules +Run 5 executable is called `o2-sim-run5` and accepts the same syntax as `o2-sim`. +There is also the serial vertsion `o2-sim-serial-run5` that is the serial implementation. +The specific modules for Run 5 are enabled by passing their their IDs to the `-m` parameter of the `o2-sim`. +A list of the available DetIDs is reproted in the table below: + +| Detector ID | Detector description | +|-------------|----------------------------------| +| `A3IP` | Beam pipe | +| `TRK` | Barrel Tracker | +| `TF3` | Time Of Flight detectors | +| `FT3` | Forward endcaps | +| `RCH` | Ring Imaging Cherenkov detectors | +| `ECL` | Electromagnetic Calorimeter | +| `MI3` | Muon Identification | +| `FCT` | Forward Conversion Tracker | +| `A3ABSO` | Absorber | +| `A3MAG` | Magnet | + +Names are arbitrarily chosen and are such as to be orthogonal to any Run 3+ other DetID. +The detector IDs of sensitive modules are mapped to the corresponding `o2::detector::DetID` class definition for convenience, so to be consistent with output names of the hit files. + +### Use the ALICE 3 magnetic field +By definition the `o2-sim-run5` will use the Run 3 magnetic field configurations. +Field description can be overridden with a custom macro with a path exported in the `ALICE3_MAGFIELD_MACRO` environment variable. +The env var `ALICE3_SIM_FIELD` needs also to be set to `ON`. +Example: + +```bash +export ALICE3_SIM_FIELD=ON +export ALICE3_MAGFIELD_MACRO=../ALICE3Field.C +``` + +An exampling macro for a custom magnetic field is stored in `Detectors/Upgrades/macros/ALICE3Field.C`. + +### Run a simple simulation for run 5 +The simplest command to be run to test the simulation is working is: + +```bash +o2-sim-run5 -n 0 +``` +This will not produce any events but will spin the machinery and will produce the `o2sim_geometry.root` file with the whole geometry description. +To enable a specific set of modules, e.g. the beampipe and the TOFs one can specify which modules to enable, e.g.: + +```bash +o2-sim-run5 -n 10 -m A3IP TF3 +``` +### Output of the simulation +The simulation will produce a `o2sim_Hits.root` file with a tree with the hits related to that detector. +Currently, hits are produced for: `TRK`, `FT3`, and `TF3`. +More detectors will be included. + +## Reconstruction +WIP + +## Analysis +WIP \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/macros/ALICE3Field.C b/Detectors/Upgrades/ALICE3/macros/ALICE3Field.C new file mode 100644 index 0000000000000..a721a91ed2dcc --- /dev/null +++ b/Detectors/Upgrades/ALICE3/macros/ALICE3Field.C @@ -0,0 +1,66 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// Author: J. E. Munoz Mendez jesus.munoz@cern.ch + +std::function field() +{ + return [](const double* x, double* b) { + double Rc; + double R1; + double R2; + double B1; + double B2; + double beamStart = 500.; //[cm] + double tokGauss = 1. / 0.1; // conversion from Tesla to kGauss + + bool isMagAbs = true; + + // *********************** + // LAYOUT 1 + // *********************** + + // RADIUS + Rc = 185.; //[cm] + R1 = 220.; //[cm] + R2 = 290.; //[cm] + + // To set the B2 + B1 = 2.; //[T] + B2 = -Rc * Rc / ((R2 * R2 - R1 * R1) * B1); //[T] + + if ((abs(x[2]) <= beamStart) && (sqrt(x[0] * x[0] + x[1] * x[1]) < Rc)) { + b[0] = 0.; + b[1] = 0.; + b[2] = B1 * tokGauss; + } else if ((abs(x[2]) <= beamStart) && + (sqrt(x[0] * x[0] + x[1] * x[1]) >= Rc && + sqrt(x[0] * x[0] + x[1] * x[1]) < R1)) { + b[0] = 0.; + b[1] = 0.; + b[2] = 0.; + } else if ((abs(x[2]) <= beamStart) && + (sqrt(x[0] * x[0] + x[1] * x[1]) >= R1 && + sqrt(x[0] * x[0] + x[1] * x[1]) < R2)) { + b[0] = 0.; + b[1] = 0.; + if (isMagAbs) { + b[2] = B2 * tokGauss; + } else { + b[2] = 0.; + } + } else { + b[0] = 0.; + b[1] = 0.; + b[2] = 0.; + } + }; +} \ No newline at end of file diff --git a/cmake/O2RootMacroExclusionList.cmake b/cmake/O2RootMacroExclusionList.cmake index 84b03472b365c..e079ea8cc6909 100644 --- a/cmake/O2RootMacroExclusionList.cmake +++ b/cmake/O2RootMacroExclusionList.cmake @@ -60,7 +60,8 @@ list(APPEND O2_ROOT_MACRO_EXCLUSION_LIST macro/load_all_libs.C macro/putCondition.C macro/rootlogon.C - Detectors/FIT/FT0/calibration/macros/makeChannelOffsetCalibObjectInCCDB.C) + Detectors/FIT/FT0/calibration/macros/makeChannelOffsetCalibObjectInCCDB.C + Detectors/Upgrades/ALICE3/macros/ALICE3Field.C) if(NOT BUILD_SIMULATION) From 6b844f16436ab82163e6fd017861e98c0a7d72c0 Mon Sep 17 00:00:00 2001 From: Ole Schmidt Date: Thu, 11 Apr 2024 11:20:07 +0200 Subject: [PATCH 0088/2997] Send CTF size report for QC monitoring --- Detectors/CTF/workflow/src/CTFWriterSpec.cxx | 39 +++++++++++--------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx index 96f07261b26d8..ba4542969a712 100644 --- a/Detectors/CTF/workflow/src/CTFWriterSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFWriterSpec.cxx @@ -62,6 +62,7 @@ #include #include #include +#include using namespace o2::framework; @@ -477,22 +478,24 @@ void CTFWriterSpec::run(ProcessingContext& pc) CTFHeader header{mTimingInfo.runNumber, mTimingInfo.creation, mTimingInfo.firstTForbit, mTimingInfo.tfCounter}; size_t szCTF = 0; mSizeReport = ""; - szCTF += processDet(pc, DetID::ITS, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::TPC, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::TRD, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::TOF, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::PHS, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::CPV, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::EMC, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::HMP, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::MFT, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::MCH, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::MID, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::ZDC, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::FT0, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::FV0, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::FDD, header, mCTFTreeOut.get()); - szCTF += processDet(pc, DetID::CTP, header, mCTFTreeOut.get()); + std::array szCTFperDet{0}; // DetID::TST is between FDD and CTP and remains empty + szCTFperDet[DetID::ITS] = processDet(pc, DetID::ITS, header, mCTFTreeOut.get()); + szCTFperDet[DetID::TPC] = processDet(pc, DetID::TPC, header, mCTFTreeOut.get()); + szCTFperDet[DetID::TRD] = processDet(pc, DetID::TRD, header, mCTFTreeOut.get()); + szCTFperDet[DetID::TOF] = processDet(pc, DetID::TOF, header, mCTFTreeOut.get()); + szCTFperDet[DetID::PHS] = processDet(pc, DetID::PHS, header, mCTFTreeOut.get()); + szCTFperDet[DetID::CPV] = processDet(pc, DetID::CPV, header, mCTFTreeOut.get()); + szCTFperDet[DetID::EMC] = processDet(pc, DetID::EMC, header, mCTFTreeOut.get()); + szCTFperDet[DetID::HMP] = processDet(pc, DetID::HMP, header, mCTFTreeOut.get()); + szCTFperDet[DetID::MFT] = processDet(pc, DetID::MFT, header, mCTFTreeOut.get()); + szCTFperDet[DetID::MCH] = processDet(pc, DetID::MCH, header, mCTFTreeOut.get()); + szCTFperDet[DetID::MID] = processDet(pc, DetID::MID, header, mCTFTreeOut.get()); + szCTFperDet[DetID::ZDC] = processDet(pc, DetID::ZDC, header, mCTFTreeOut.get()); + szCTFperDet[DetID::FT0] = processDet(pc, DetID::FT0, header, mCTFTreeOut.get()); + szCTFperDet[DetID::FV0] = processDet(pc, DetID::FV0, header, mCTFTreeOut.get()); + szCTFperDet[DetID::FDD] = processDet(pc, DetID::FDD, header, mCTFTreeOut.get()); + szCTFperDet[DetID::CTP] = processDet(pc, DetID::CTP, header, mCTFTreeOut.get()); + szCTF = std::accumulate(szCTFperDet.begin(), szCTFperDet.end(), 0); if (mReportInterval > 0 && (mTimingInfo.tfCounter % mReportInterval) == 0) { LOGP(important, "CTF {} size report:{} - Total:{}", mTimingInfo.tfCounter, mSizeReport, fmt::group_digits(szCTF)); } @@ -532,6 +535,7 @@ void CTFWriterSpec::run(ProcessingContext& pc) } int dummy = 0; pc.outputs().snapshot({"ctfdone", 0}, dummy); + pc.outputs().snapshot(Output{"CTF", "SIZES", 0}, szCTFperDet); } //___________________________________________________________________ @@ -797,7 +801,8 @@ DataProcessorSpec getCTFWriterSpec(DetID::mask_t dets, const std::string& outTyp return DataProcessorSpec{ "ctf-writer", inputs, - Outputs{{OutputLabel{"ctfdone"}, "CTF", "DONE", 0, Lifetime::Timeframe}}, + Outputs{{OutputLabel{"ctfdone"}, "CTF", "DONE", 0, Lifetime::Timeframe}, + {"CTF", "SIZES", 0, Lifetime::Timeframe}}, AlgorithmSpec{adaptFromTask(dets, outType, verbosity, reportInterval)}, // RS FIXME once global/local options clash is solved, --output-type will become device option Options{ //{"output-type", VariantType::String, "ctf", {"output types: ctf (per TF) or dict (create dictionaries) or both or none"}}, {"save-ctf-after", VariantType::Int64, 0ll, {"autosave CTF tree with multiple CTFs after every N CTFs if >0 or every -N MBytes if < 0"}}, From dd35564e99c31680a21965d737aec569e6855d40 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:18:42 +0200 Subject: [PATCH 0089/2997] Use C++14 namespaces --- Detectors/TRD/pid/include/TRDPID/ML.h | 7 ++----- .../ZDC/fastsimulation/include/Processors.h | 2 +- .../include/ZDCSimulation/Detector.h | 19 ++++++++----------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/Detectors/TRD/pid/include/TRDPID/ML.h b/Detectors/TRD/pid/include/TRDPID/ML.h index 7c72edc30ae3c..367c33bef682b 100644 --- a/Detectors/TRD/pid/include/TRDPID/ML.h +++ b/Detectors/TRD/pid/include/TRDPID/ML.h @@ -27,9 +27,7 @@ #include #include -namespace o2 -{ -namespace trd +namespace o2::trd { /// This is the ML Base class which defines the interface all machine learning @@ -123,7 +121,6 @@ class PY final : public ML ClassDefNV(PY, 1); }; -} // namespace trd -} // namespace o2 +} // namespace o2::trd #endif diff --git a/Detectors/ZDC/fastsimulation/include/Processors.h b/Detectors/ZDC/fastsimulation/include/Processors.h index e389bcd42c271..b9836484fe871 100644 --- a/Detectors/ZDC/fastsimulation/include/Processors.h +++ b/Detectors/ZDC/fastsimulation/include/Processors.h @@ -81,4 +81,4 @@ std::vector readClassifier(const Ort::Value& value, size_t batchSize); std::vector> calculateChannels(const Ort::Value& value, size_t batchSize); } // namespace o2::zdc::fastsim::processors -#endif // O2_ZDC_FAST_SIMULATIONS_PROCESSORS_H \ No newline at end of file +#endif // O2_ZDC_FAST_SIMULATIONS_PROCESSORS_H diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h b/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h index a0a9722a9d2f9..0f00f53d9f217 100644 --- a/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h @@ -42,9 +42,7 @@ class StandardScaler; class FairVolume; -namespace o2 -{ -namespace zdc +namespace o2::zdc { class Detector : public o2::base::DetImpl @@ -197,10 +195,10 @@ class Detector : public o2::base::DetImpl /// Container for hit data std::vector* mHits; - float mLumiLength = 0; //TODO: make part of configurable params - float mTCLIAAPERTURE = 3.5; //TODO: make part of configurable params - float mTCLIAAPERTURENEG = 3.5; //TODO: make part of configurable params - float mVCollSideCCentreY = 0.; //TODO: make part of configurable params + float mLumiLength = 0; // TODO: make part of configurable params + float mTCLIAAPERTURE = 3.5; // TODO: make part of configurable params + float mTCLIAAPERTURENEG = 3.5; // TODO: make part of configurable params + float mVCollSideCCentreY = 0.; // TODO: make part of configurable params int mZNENVVolID = -1; // the volume id for the neutron det envelope volume int mZPENVVolID = -1; // the volume id for the proton det envelope volume @@ -240,12 +238,12 @@ class Detector : public o2::base::DetImpl // fastsim model wrapper #ifdef ZDC_FASTSIM_ONNX - fastsim::NeuralFastSimulation* mFastSimClassifier = nullptr; //! no ROOT serialization + fastsim::NeuralFastSimulation* mFastSimClassifier = nullptr; //! no ROOT serialization fastsim::NeuralFastSimulation* mFastSimModelNeutron = nullptr; //! fastsim::NeuralFastSimulation* mFastSimModelProton = nullptr; //! // Scalers for models inputs - fastsim::processors::StandardScaler* mClassifierScaler = nullptr; //! + fastsim::processors::StandardScaler* mClassifierScaler = nullptr; //! fastsim::processors::StandardScaler* mModelScalerNeutron = nullptr; //! fastsim::processors::StandardScaler* mModelScalerProton = nullptr; //! @@ -273,8 +271,7 @@ class Detector : public o2::base::DetImpl friend class o2::base::DetImpl; ClassDefOverride(Detector, 1); }; -} // namespace zdc -} // namespace o2 +} // namespace o2::zdc #ifdef USESHM namespace o2 From 9da1a8c931c2b78fc17c34fe390e3e714aea4bec Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 11 Apr 2024 14:34:19 +0200 Subject: [PATCH 0090/2997] Add support for ONNXRuntime 1.17.1 Notice that this includes a fix to give precedence to the old ONNXRuntime. Without this, it will currently prefer (non-working) local installations. --- Detectors/TRD/pid/include/TRDPID/ML.h | 4 ++++ Detectors/TRD/pid/src/ML.cxx | 4 ++++ .../ZDC/fastsimulation/include/FastSimulations.h | 4 ++++ Detectors/ZDC/fastsimulation/include/Processors.h | 4 ++++ .../simulation/include/ZDCSimulation/Detector.h | 6 ++++++ dependencies/FindONNXRuntime.cmake | 15 ++++++++------- 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Detectors/TRD/pid/include/TRDPID/ML.h b/Detectors/TRD/pid/include/TRDPID/ML.h index 367c33bef682b..c43de8921630a 100644 --- a/Detectors/TRD/pid/include/TRDPID/ML.h +++ b/Detectors/TRD/pid/include/TRDPID/ML.h @@ -21,7 +21,11 @@ #include "DataFormatsTRD/PID.h" #include "Framework/ProcessingContext.h" #include "Framework/InputRecord.h" +#if __has_include() #include +#else +#include +#endif #include #include #include diff --git a/Detectors/TRD/pid/src/ML.cxx b/Detectors/TRD/pid/src/ML.cxx index 488bf055a7f6c..785f3b05cc112 100644 --- a/Detectors/TRD/pid/src/ML.cxx +++ b/Detectors/TRD/pid/src/ML.cxx @@ -28,7 +28,11 @@ #include "DetectorsBase/Propagator.h" #include +#if __has_include() #include +#else +#include +#endif #include #include diff --git a/Detectors/ZDC/fastsimulation/include/FastSimulations.h b/Detectors/ZDC/fastsimulation/include/FastSimulations.h index 9244ceb894b0a..9fd89c8fb5838 100644 --- a/Detectors/ZDC/fastsimulation/include/FastSimulations.h +++ b/Detectors/ZDC/fastsimulation/include/FastSimulations.h @@ -17,7 +17,11 @@ #ifndef O2_ZDC_FAST_SIMULATIONS_H #define O2_ZDC_FAST_SIMULATIONS_H +#if __has_include() #include +#else +#include +#endif #include #include diff --git a/Detectors/ZDC/fastsimulation/include/Processors.h b/Detectors/ZDC/fastsimulation/include/Processors.h index b9836484fe871..4ae4d0786bdd9 100644 --- a/Detectors/ZDC/fastsimulation/include/Processors.h +++ b/Detectors/ZDC/fastsimulation/include/Processors.h @@ -17,7 +17,11 @@ #ifndef O2_ZDC_FAST_SIMULATIONS_PROCESSORS_H #define O2_ZDC_FAST_SIMULATIONS_PROCESSORS_H +#if __has_include() #include +#else +#include +#endif #include #include diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h b/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h index 0f00f53d9f217..40e4babe8d760 100644 --- a/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h @@ -26,7 +26,13 @@ // inclusions and forward decl for fast sim #ifdef ZDC_FASTSIM_ONNX + +#if __has_include() #include +#else +#include +#endif + namespace o2::zdc { namespace fastsim diff --git a/dependencies/FindONNXRuntime.cmake b/dependencies/FindONNXRuntime.cmake index b34782e99050f..0983d44644a6c 100644 --- a/dependencies/FindONNXRuntime.cmake +++ b/dependencies/FindONNXRuntime.cmake @@ -9,11 +9,12 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -find_package(onnxruntime CONFIG) -if (NOT onnxruntime_FOUND) - find_package(ONNXRuntime::ONNXRuntime CONFIG) - if (ONNXRuntime::ONNXRuntime_FOUND) - set(onnxruntime_FOUND 1) - add_library(onnxruntime::onnxruntime ALIAS ONNXRuntime::ONNXRuntime) - endif() +find_package(ONNXRuntime::ONNXRuntime CONFIG) +if (ONNXRuntime::ONNXRuntime_FOUND) + set(onnxruntime_FOUND 1) + add_library(onnxruntime::onnxruntime ALIAS ONNXRuntime::ONNXRuntime) +endif() + +if (NOT ONNXRuntime::ONNXRuntime_FOUND) + find_package(onnxruntime CONFIG) endif() From a56ade526b3fa2c24548cadc58864f8b996d3345 Mon Sep 17 00:00:00 2001 From: Ole Schmidt Date: Fri, 12 Apr 2024 15:51:23 +0200 Subject: [PATCH 0091/2997] Fix RCTUpdater warning message --- Detectors/GRP/workflows/src/rct-updater-workflow.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/GRP/workflows/src/rct-updater-workflow.cxx b/Detectors/GRP/workflows/src/rct-updater-workflow.cxx index 3020f236aff53..8b75091520724 100644 --- a/Detectors/GRP/workflows/src/rct-updater-workflow.cxx +++ b/Detectors/GRP/workflows/src/rct-updater-workflow.cxx @@ -69,7 +69,7 @@ class RCTUpdaterSpec : public o2::framework::Task if (grp->getRunType() == o2::parameters::GRPECS::PHYSICS || grp->getRunType() == o2::parameters::GRPECS::COSMICS) { mEnabled = true; } else { - LOGP(warning, "Run {} type is {}, disabling RCT update", mRunNumber, o2::parameters::GRPECS::RunTypeNames[mRunNumber]); + LOGP(warning, "Run {} type is {}, disabling RCT update", mRunNumber, o2::parameters::GRPECS::RunTypeNames[grp->getRunType()]); mEnabled = false; } if (mEnabled) { From 23ec08d87aeee0bb93ccc9b91324668f790f76f8 Mon Sep 17 00:00:00 2001 From: noferini <9963644+noferini@users.noreply.github.com> Date: Fri, 12 Apr 2024 09:42:57 +0200 Subject: [PATCH 0092/2997] TOF matching debug mode improvements --- .../MatchInfoTOFReco.h | 5 ++- Detectors/GlobalTracking/src/MatchTOF.cxx | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h index b1d3830e8083c..aa955ca81c1c6 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h @@ -42,6 +42,8 @@ class MatchInfoTOFReco : public MatchInfoTOF void setFakeMatch() { mFakeMC = true; } void resetFakeMatch() { mFakeMC = false; } bool isFake() const { return mFakeMC; } + float pt() const { return mPt; } + void setPt(float pt) { mPt = pt; } void setTrackType(TrackType value) { mTrackType = value; } TrackType getTrackType() const { return mTrackType; } @@ -49,7 +51,8 @@ class MatchInfoTOFReco : public MatchInfoTOF private: TrackType mTrackType; ///< track type (TPC, ITSTPC, TPCTRD, ITSTPCTRD) bool mFakeMC = false; - ClassDefNV(MatchInfoTOFReco, 3); + float mPt = 0; + ClassDefNV(MatchInfoTOFReco, 4); }; } // namespace dataformats } // namespace o2 diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 3a0ee70570f53..099eb12d1f28f 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -185,12 +185,44 @@ void MatchTOF::run(const o2::globaltracking::RecoContainer& inp, unsigned long f matchingPair.setFakeMatch(); } } + } else { + for (auto& matchingPair : mMatchedTracksPairsSec[sec]) { + int bct0 = int((matchingPair.getSignal() - 10000) * Geo::BC_TIME_INPS_INV); + float tof = matchingPair.getSignal() - bct0 * Geo::BC_TIME_INPS; + if (abs(tof - matchingPair.getLTIntegralOut().getTOF(2)) < 600) { + } else if (abs(tof - matchingPair.getLTIntegralOut().getTOF(3)) < 600) { + } else if (abs(tof - matchingPair.getLTIntegralOut().getTOF(4)) < 600) { + } else if (abs(tof - matchingPair.getLTIntegralOut().getTOF(0)) < 600) { + } else if (abs(tof - matchingPair.getLTIntegralOut().getTOF(1)) < 600) { + } else if (abs(tof - matchingPair.getLTIntegralOut().getTOF(5)) < 600) { + } else if (abs(tof - matchingPair.getLTIntegralOut().getTOF(6)) < 600) { + } else if (abs(tof - matchingPair.getLTIntegralOut().getTOF(7)) < 600) { + } else if (abs(tof - matchingPair.getLTIntegralOut().getTOF(8)) < 600) { + } else { // no pion, kaon, proton, electron, muon, deuteron, triton, 3He, 4He + matchingPair.setFakeMatch(); + } + } } } LOG(debug) << "...done. Now check the best matches"; nMatches[sec] = mMatchedTracksPairsSec[sec].size(); selectBestMatches(sec); + + if (mStoreMatchable) { + for (auto& matchingPair : mMatchedTracksPairsSec[sec]) { + trkType trkTypeSplitted = trkType::TPC; + auto sourceID = matchingPair.getTrackRef().getSource(); + if (sourceID == o2::dataformats::GlobalTrackID::ITSTPC) { + trkTypeSplitted = trkType::ITSTPC; + } else if (sourceID == o2::dataformats::GlobalTrackID::TPCTRD) { + trkTypeSplitted = trkType::TPCTRD; + } else if (sourceID == o2::dataformats::GlobalTrackID::ITSTPCTRD) { + trkTypeSplitted = trkType::ITSTPCTRD; + } + matchingPair.setTrackType(trkTypeSplitted); + } + } } std::string nMatchesStr = "Number of pairs matched per sector: "; for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { @@ -801,6 +833,7 @@ void MatchTOF::doMatching(int sec) int nStripsCrossedInPropagation = 0; // how many strips were hit during the propagation auto& trackWork = mTracksWork[sec][type][cacheTrk[itrk]]; auto& trefTrk = trackWork.first; + float pt = trefTrk.getPt(); auto& intLT = mLTinfos[sec][type][cacheTrk[itrk]]; float timeShift = intLT.getL() * 33.35641; // integrated time for 0.75 beta particles in ps, to take into account the t.o.f. delay with respect the interaction BC // using beta=0.75 to cover beta range [0.59 , 1.04] also for a 8 m track lenght with a 10 ns track resolution (TRD) @@ -1003,6 +1036,7 @@ void MatchTOF::doMatching(int sec) // set event indexes (to be checked) int eventIndexTOFCluster = mTOFClusSectIndexCache[indices[0]][itof]; mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[iPropagation], mTrackGid[sec][type][cacheTrk[itrk]], type, (trefTOF.getTime() - (minTrkTime + maxTrkTime - 100E3) * 0.5) * 1E-6, trefTOF.getZ(), resX, resZ); // subracting 100 ns to max track which was artificially added + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setPt(pt); } } } @@ -1048,6 +1082,7 @@ void MatchTOF::doMatchingForTPC(int sec) for (int itrk = 0; itrk < cacheTrk.size(); itrk++) { auto& trackWork = mTracksWork[sec][trkType::UNCONS][cacheTrk[itrk]]; auto& trefTrk = trackWork.first; + float pt = trefTrk.getPt(); auto& intLT = mLTinfos[sec][trkType::UNCONS][cacheTrk[itrk]]; float timeShift = intLT.getL() * 33.35641; // integrated time for 0.75 beta particles in ps, to take into account the t.o.f. delay with respect the interaction BC @@ -1333,6 +1368,7 @@ void MatchTOF::doMatchingForTPC(int sec) // set event indexes (to be checked) int eventIndexTOFCluster = mTOFClusSectIndexCache[indices[0]][itof]; mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[ibc][iPropagation], mTrackGid[sec][trkType::UNCONS][cacheTrk[itrk]], trkType::UNCONS, trefTOF.getTime() * 1E-6 - tpctime, trefTOF.getZ(), resX, resZ); // TODO: check if this is correct! + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setPt(pt); } } } From 53182e3f0f2658a4f59425d298f6dc18724205fe Mon Sep 17 00:00:00 2001 From: shahoian Date: Sat, 13 Apr 2024 18:20:25 +0200 Subject: [PATCH 0093/2997] Use detectror-specific AlpideParam for ROF-rate check --- Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index 0e0b0dabaa070..33b4597b9b420 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -186,7 +186,7 @@ void STFDecoder::run(ProcessingContext& pc) } nTriggersProcessed = mDecoder->getNROFsProcessed() - nTriggersProcessed - 1; - const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); + const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); int expectedTFSize = static_cast(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); // 3564*32 / ROF Length in BS = number of ROFs per TF if ((expectedTFSize != nTriggersProcessed) && mTFCounter > 1 && nTriggersProcessed > 0) { LOG(error) << "Inconsistent number of ROF per TF. From parameters: " << expectedTFSize << " from readout: " << nTriggersProcessed; From 667733d5faf6aa6216c374013f5e863fd5d5cbdb Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 14 Apr 2024 15:53:10 +0200 Subject: [PATCH 0094/2997] Skip empty ROFs only with no-empty-rof option in digi2raw --- Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx | 12 +++++++----- Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx b/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx index 0998272f745d0..a82ad4001aff3 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/digi2raw.cxx @@ -42,7 +42,7 @@ constexpr int DefRDHVersion = o2::raw::RDHUtils::getVersion& m2r, std::string_view outDir, std::string_view outPrefix, std::string_view fileFor); void digi2raw(std::string_view inpName, std::string_view outDir, std::string_view fileFor, int verbosity, uint32_t rdhV = DefRDHVersion, bool enablePadding = false, - bool noEmptyHBF = false, int superPageSizeInB = 1024 * 1024); + bool noEmptyHBF = false, bool noEmptyROF = false, int superPageSizeInB = 1024 * 1024); int main(int argc, char** argv) { @@ -63,6 +63,7 @@ int main(int argc, char** argv) add_option("rdh-version,r", bpo::value()->default_value(DefRDHVersion), "RDH version to use"); add_option("enable-padding", bpo::value()->default_value(false)->implicit_value(true), "enable GBT word padding to 128 bits even for RDH V7"); add_option("no-empty-hbf,e", bpo::value()->default_value(false)->implicit_value(true), "do not create empty HBF pages (except for HBF starting TF)"); + add_option("no-empty-rof", bpo::value()->default_value(false)->implicit_value(true), "do not create empty ROF blocks"); add_option("hbfutils-config,u", bpo::value()->default_value(std::string(o2::base::NameConf::DIGITIZATIONCONFIGFILE)), "config file for HBFUtils (or none)"); add_option("configKeyValues", bpo::value()->default_value(""), "comma-separated configKeyValues"); @@ -96,7 +97,8 @@ int main(int argc, char** argv) vm["verbosity"].as(), vm["rdh-version"].as(), vm["enable-padding"].as(), - vm["no-empty-hbf"].as()); + vm["no-empty-hbf"].as(), + vm["no-empty-rof"].as()); LOG(info) << "HBFUtils settings used for conversion:"; o2::raw::HBFUtils::Instance().print(); @@ -104,7 +106,7 @@ int main(int argc, char** argv) return 0; } -void digi2raw(std::string_view inpName, std::string_view outDir, std::string_view fileFor, int verbosity, uint32_t rdhV, bool enablePadding, bool noEmptyHBF, int superPageSizeInB) +void digi2raw(std::string_view inpName, std::string_view outDir, std::string_view fileFor, int verbosity, uint32_t rdhV, bool enablePadding, bool noEmptyHBF, bool noEmptyROF, int superPageSizeInB) { TStopwatch swTot; swTot.Start(); @@ -178,9 +180,9 @@ void digi2raw(std::string_view inpName, std::string_view outDir, std::string_vie LOG(info) << "Processing ROF:" << rofRec.getROFrame() << " with " << nDigROF << " entries"; rofRec.print(); } - if (!nDigROF) { + if (!nDigROF && noEmptyROF) { if (verbosity) { - LOG(info) << "Frame is empty"; // ?? + LOG(info) << "Frame is empty"; } continue; } diff --git a/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx b/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx index 452832d6e74ab..00f49ce81bb02 100644 --- a/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx +++ b/Detectors/ITSMFT/MFT/simulation/src/digi2raw.cxx @@ -42,7 +42,7 @@ constexpr int DefRDHVersion = o2::raw::RDHUtils::getVersion& m2r, std::string_view outDir, std::string_view outPrefix, std::string_view fileFor); void digi2raw(std::string_view inpName, std::string_view outDir, std::string_view fileFor, int verbosity, uint32_t rdhV = DefRDHVersion, bool enablePadding = false, - bool noEmptyHBF = false, int superPageSizeInB = 1024 * 1024); + bool noEmptyHBF = false, bool noEmptyROF = false, int superPageSizeInB = 1024 * 1024); int main(int argc, char** argv) { @@ -63,6 +63,7 @@ int main(int argc, char** argv) add_option("rdh-version,r", bpo::value()->default_value(DefRDHVersion), "RDH version to use"); add_option("enable-padding", bpo::value()->default_value(false)->implicit_value(true), "enable GBT word padding to 128 bits even for RDH V7"); add_option("no-empty-hbf,e", bpo::value()->default_value(false)->implicit_value(true), "do not create empty HBF pages (except for HBF starting TF)"); + add_option("no-empty-rof", bpo::value()->default_value(false)->implicit_value(true), "do not create empty ROF blocks"); add_option("hbfutils-config,u", bpo::value()->default_value(std::string(o2::base::NameConf::DIGITIZATIONCONFIGFILE)), "config file for HBFUtils (or none)"); add_option("configKeyValues", bpo::value()->default_value(""), "comma-separated configKeyValues"); @@ -96,7 +97,8 @@ int main(int argc, char** argv) vm["verbosity"].as(), vm["rdh-version"].as(), vm["enable-padding"].as(), - vm["no-empty-hbf"].as()); + vm["no-empty-hbf"].as(), + vm["no-empty-rof"].as()); LOG(info) << "HBFUtils settings used for conversion:"; o2::raw::HBFUtils::Instance().print(); @@ -104,7 +106,7 @@ int main(int argc, char** argv) return 0; } -void digi2raw(std::string_view inpName, std::string_view outDir, std::string_view fileFor, int verbosity, uint32_t rdhV, bool enablePadding, bool noEmptyHBF, int superPageSizeInB) +void digi2raw(std::string_view inpName, std::string_view outDir, std::string_view fileFor, int verbosity, uint32_t rdhV, bool enablePadding, bool noEmptyHBF, bool noEmptyROF, int superPageSizeInB) { TStopwatch swTot; swTot.Start(); @@ -178,9 +180,9 @@ void digi2raw(std::string_view inpName, std::string_view outDir, std::string_vie LOG(info) << "Processing ROF:" << rofRec.getROFrame() << " with " << nDigROF << " entries"; rofRec.print(); } - if (!nDigROF) { + if (!nDigROF && noEmptyROF) { if (verbosity) { - LOG(info) << "Frame is empty"; // ?? + LOG(info) << "Frame is empty"; } continue; } From 01670f961773396f359fe9a1bf19ea2b1fda36ae Mon Sep 17 00:00:00 2001 From: noferini <9963644+noferini@users.noreply.github.com> Date: Sat, 13 Apr 2024 10:47:41 +0200 Subject: [PATCH 0095/2997] trivial fix in one TOF setter --- .../include/ReconstructionDataFormats/MatchInfoTOF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h index 9f6b2f00bb37c..29442325e2f66 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h @@ -38,7 +38,7 @@ class MatchInfoTOF int getTOFClIndex() const { return mIdxTOFCl; } int getTrackIndex() const { return mIdxTrack.getIndex(); } - void setChi2(int chi2) { mChi2 = chi2; } + void setChi2(float chi2) { mChi2 = chi2; } float getChi2() const { return mChi2; } o2::track::TrackLTIntegral& getLTIntegralOut() { return mIntLT; } From 0b1223a24ad8140fc5d307dc5e2aa84cebb497b9 Mon Sep 17 00:00:00 2001 From: Chiara Oppedisano Date: Wed, 10 Apr 2024 12:03:27 +0200 Subject: [PATCH 0096/2997] Uniform A-side X coordinate sign with the reconstructed one --- Detectors/ZDC/simulation/src/Detector.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/ZDC/simulation/src/Detector.cxx b/Detectors/ZDC/simulation/src/Detector.cxx index 54c97a28dea89..c6f91d9c2164f 100644 --- a/Detectors/ZDC/simulation/src/Detector.cxx +++ b/Detectors/ZDC/simulation/src/Detector.cxx @@ -271,7 +271,7 @@ void Detector::getDetIDandSecID(TString const& volname, math_utils::Vector3D 0) { detector = ZNA; - xDet = x - math_utils::Vector3D(Geometry::ZNAPOSITION[0], Geometry::ZNAPOSITION[1], Geometry::ZNAPOSITION[2]); + xDet = -(x - math_utils::Vector3D(Geometry::ZNAPOSITION[0], Geometry::ZNAPOSITION[1], Geometry::ZNAPOSITION[2])); } else if (x.Z() < 0) { detector = ZNC; @@ -297,7 +297,7 @@ void Detector::getDetIDandSecID(TString const& volname, math_utils::Vector3D 0) { detector = ZPA; // (NB -> DIFFERENT FROM AliRoot!!!) - xDet = x - math_utils::Vector3D(Geometry::ZPAPOSITION[0], Geometry::ZPAPOSITION[1], Geometry::ZPAPOSITION[2]); + xDet = -(x - math_utils::Vector3D(Geometry::ZPAPOSITION[0], Geometry::ZPAPOSITION[1], Geometry::ZPAPOSITION[2])); } else if (x.Z() < 0) { detector = ZPC; // (NB -> DIFFERENT FROM AliRoot!!!) xDet = x - math_utils::Vector3D(Geometry::ZPCPOSITION[0], Geometry::ZPCPOSITION[1], Geometry::ZPCPOSITION[2]); From 07cc2dbe3232dc8d124e433f2dc6413f3f467d1f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 11 Apr 2024 14:51:49 +0200 Subject: [PATCH 0097/2997] GPU QA: Improve track dump to root files --- .../GPUTrackingLinkDef_Standalone.h | 6 +++ GPU/GPUTracking/qa/GPUQA.cxx | 47 ++++++++++++------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/GPU/GPUTracking/GPUTrackingLinkDef_Standalone.h b/GPU/GPUTracking/GPUTrackingLinkDef_Standalone.h index b2cb2105a1df9..a7b91cc37ba4a 100644 --- a/GPU/GPUTracking/GPUTrackingLinkDef_Standalone.h +++ b/GPU/GPUTracking/GPUTrackingLinkDef_Standalone.h @@ -22,5 +22,11 @@ #pragma link off all functions; #pragma link C++ class o2::tpc::ClusterNative + ; +#pragma link C++ class o2::tpc::TrackTPC + ; +#pragma link C++ class o2::track::TrackParametrization < float> + ; +#pragma link C++ class o2::track::TrackParametrizationWithError < float> + ; +#pragma link C++ class o2::dataformats::RangeReference < unsigned int, unsigned short> + ; +#pragma link C++ class o2::tpc::dEdxInfo + ; +#pragma link C++ class o2::track::PID + ; #endif diff --git a/GPU/GPUTracking/qa/GPUQA.cxx b/GPU/GPUTracking/qa/GPUQA.cxx index 95de3f3430e52..f4978a80801ab 100644 --- a/GPU/GPUTracking/qa/GPUQA.cxx +++ b/GPU/GPUTracking/qa/GPUQA.cxx @@ -1742,46 +1742,61 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx if (!clNative || !mTracking || !mTracking->mIOPtrs.mergedTrackHitAttachment || !mTracking->mIOPtrs.mergedTracks) { throw std::runtime_error("Cannot dump non o2::tpc::clusterNative clusters, need also hit attachmend and GPU tracks"); } - static auto cldump = GPUROOTDump::getNew("cluster", "track", "trackHit", "attach", "extState", "x", "y", "z", "sector", "row", "nEv", "clusterTree"); unsigned int clid = 0; for (unsigned int i = 0; i < GPUChainTracking::NSLICES; i++) { for (unsigned int j = 0; j < GPUCA_ROW_COUNT; j++) { for (unsigned int k = 0; k < mClNative->nClusters[i][j]; k++) { const auto& cl = mClNative->clusters[i][j][k]; unsigned int attach = mTracking->mIOPtrs.mergedTrackHitAttachment[clid]; - GPUTPCGMMergedTrack trk; - GPUTPCGMMergedTrackHit trkHit; - memset((void*)&trk, 0, sizeof(trk)); - memset((void*)&trkHit, 0, sizeof(trkHit)); float x = 0, y = 0, z = 0; if (attach & gputpcgmmergertypes::attachFlagMask) { unsigned int track = attach & gputpcgmmergertypes::attachTrackMask; - trk = mTracking->mIOPtrs.mergedTracks[track]; - for (unsigned int l = 0; l < trk.NClusters(); l++) { - const auto& tmp = mTracking->mIOPtrs.mergedTrackHits[trk.FirstClusterRef() + l]; - if (tmp.num == clid) { - trkHit = tmp; - break; - } - } + const auto& trk = mTracking->mIOPtrs.mergedTracks[track]; mTracking->GetTPCTransformHelper()->Transform(i, j, cl.getPad(), cl.getTime(), x, y, z, trk.GetParam().GetTZOffset()); mTracking->GetParam().Slice2Global(i, x, y, z, &x, &y, &z); } - unsigned int extState = mTracking->mIOPtrs.mergedTrackHitStates ? mTracking->mIOPtrs.mergedTrackHitStates[clid] : 0; - cldump.Fill(cl, trk, trkHit, attach, extState, x, y, z, i, j, mNEvents - 1); + if (mConfig.dumpToROOT >= 2) { + GPUTPCGMMergedTrack trk; + GPUTPCGMMergedTrackHit trkHit; + memset((void*)&trk, 0, sizeof(trk)); + memset((void*)&trkHit, 0, sizeof(trkHit)); + if (attach & gputpcgmmergertypes::attachFlagMask) { + unsigned int track = attach & gputpcgmmergertypes::attachTrackMask; + trk = mTracking->mIOPtrs.mergedTracks[track]; + for (unsigned int l = 0; l < trk.NClusters(); l++) { + const auto& tmp = mTracking->mIOPtrs.mergedTrackHits[trk.FirstClusterRef() + l]; + if (tmp.num == clid) { + trkHit = tmp; + break; + } + } + } + static auto cldump = GPUROOTDump::getNew("cluster", "track", "trackHit", "attach", "extState", "x", "y", "z", "sector", "row", "nEv", "clusterTree"); + cldump.Fill(cl, trk, trkHit, attach, extState, x, y, z, i, j, mNEvents - 1); + } else { + static auto cldump = GPUROOTDump::getNew("cluster", "attach", "extState", "x", "y", "z", "sector", "row", "nEv", "clusterTree"); + cldump.Fill(cl, attach, extState, x, y, z, i, j, mNEvents - 1); + } clid++; } } } - static auto trkdump = GPUROOTDump::getNew("nEv", "tracks"); + static auto trkdump = GPUROOTDump::getNew("nEv", "track", "tracksTree"); for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { if (mTracking->mIOPtrs.mergedTracks[i].OK()) { trkdump.Fill(mNEvents - 1, mTracking->mIOPtrs.mergedTracks[i]); } } + + if (mTracking && mTracking->GetProcessingSettings().createO2Output) { + static auto o2trkdump = GPUROOTDump::getNew("nEv", "track", "tracksO2Tree"); + for (unsigned int i = 0; i < mTracking->mIOPtrs.nOutputTracksTPCO2; i++) { + o2trkdump.Fill(mNEvents - 1, mTracking->mIOPtrs.outputTracksTPCO2[i]); + } + } } mTrackingScratchBuffer.clear(); mTrackingScratchBuffer.shrink_to_fit(); From f9b1d32ea8c993b1dfeb86565cccb4e686f3bc37 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Fri, 12 Apr 2024 17:03:51 +0200 Subject: [PATCH 0098/2997] TPC Cluster Finder: Fix invalid write in peak finder. --- GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx index fc8a2fcf20d4e..cc7e0daed1476 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFPeakFinder.cxx @@ -121,5 +121,7 @@ GPUd() void GPUTPCCFPeakFinder::findPeaksImpl(int nBlocks, int nThreads, int iBl isPeakPredicate[idx] = peak; - peakMap[pos] = (uchar(charge > calib.tpc.cfInnerThreshold) << 1) | peak; + if (pos.valid()) { + peakMap[pos] = (uchar(charge > calib.tpc.cfInnerThreshold) << 1) | peak; + } } From 15e83e41d7a5c14aa65e38e8a23bec7531e5e5aa Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Sat, 13 Apr 2024 16:36:51 +0200 Subject: [PATCH 0099/2997] TPC Cluster Finder: Fix invalid write during deconvolution. --- GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx index 3fa5b2ac265eb..18fffd46d707f 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx @@ -50,7 +50,8 @@ GPUdii() void GPUTPCCFDeconvolution::deconvolutionImpl(int nBlocks, int nThreads ushort partId = ll; ushort in3x3 = 0; - partId = CfUtils::partition(smem, ll, iamPeak, SCRATCH_PAD_WORK_GROUP_SIZE, &in3x3); + bool exclude3x3 = iamPeak || !pos.valid(); + partId = CfUtils::partition(smem, ll, exclude3x3, SCRATCH_PAD_WORK_GROUP_SIZE, &in3x3); if (partId < in3x3) { smem.posBcast1[partId] = pos; @@ -74,7 +75,7 @@ GPUdii() void GPUTPCCFDeconvolution::deconvolutionImpl(int nBlocks, int nThreads } ushort in5x5 = 0; - partId = CfUtils::partition(smem, partId, peakCount > 0 && !iamPeak, in3x3, &in5x5); + partId = CfUtils::partition(smem, partId, peakCount > 0 && !exclude3x3, in3x3, &in5x5); if (partId < in5x5) { smem.posBcast1[partId] = pos; @@ -99,7 +100,7 @@ GPUdii() void GPUTPCCFDeconvolution::deconvolutionImpl(int nBlocks, int nThreads peakCount *= -1; } - if (iamDummy) { + if (iamDummy || !pos.valid()) { return; } From d27cf269f1ef16d24ac80fc04676238462bdf7c3 Mon Sep 17 00:00:00 2001 From: Ole Schmidt Date: Mon, 15 Apr 2024 09:50:16 +0200 Subject: [PATCH 0100/2997] Allow specifying different track source for TPC map extraction (#12992) * Allow specifying different track source for TPC map extraction Track type(s) A can be used to extract residuals for vDrift calibration and track type(s) B can be use to extract residuals for the creation of the map. E.g. use ITS-TPC-TRD-TOF tracks for vDrift and ITS-TPC for the map creation. * Make sure mAddTracksForMapPerTF are taken from best possible seeds --- .../TPCInterpolationSpec.h | 5 +- .../src/TPCInterpolationSpec.cxx | 17 ++++--- .../src/tpc-interpolation-workflow.cxx | 13 ++++- .../SpacePoints/SpacePointsCalibConfParam.h | 4 +- .../include/SpacePoints/TrackInterpolation.h | 14 +++--- .../SpacePoints/src/TrackInterpolation.cxx | 47 ++++++++++++++----- 6 files changed, 71 insertions(+), 29 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/include/TPCInterpolationWorkflow/TPCInterpolationSpec.h b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/include/TPCInterpolationWorkflow/TPCInterpolationSpec.h index 520f5779c1d06..86064f84d881f 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/include/TPCInterpolationWorkflow/TPCInterpolationSpec.h +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/include/TPCInterpolationWorkflow/TPCInterpolationSpec.h @@ -38,7 +38,7 @@ namespace tpc class TPCInterpolationDPL : public Task { public: - TPCInterpolationDPL(std::shared_ptr dr, o2::dataformats::GlobalTrackID::mask_t src, std::shared_ptr gr, bool useMC, bool processITSTPConly, bool sendTrackData, bool debugOutput) : mDataRequest(dr), mSources(src), mGGCCDBRequest(gr), mUseMC(useMC), mProcessITSTPConly(processITSTPConly), mSendTrackData(sendTrackData), mDebugOutput(debugOutput) {} + TPCInterpolationDPL(std::shared_ptr dr, o2::dataformats::GlobalTrackID::mask_t src, o2::dataformats::GlobalTrackID::mask_t srcMap, std::shared_ptr gr, bool useMC, bool processITSTPConly, bool sendTrackData, bool debugOutput) : mDataRequest(dr), mSources(src), mSourcesMap(srcMap), mGGCCDBRequest(gr), mUseMC(useMC), mProcessITSTPConly(processITSTPConly), mSendTrackData(sendTrackData), mDebugOutput(debugOutput) {} ~TPCInterpolationDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -53,6 +53,7 @@ class TPCInterpolationDPL : public Task o2::tpc::VDriftHelper mTPCVDriftHelper{}; const o2::itsmft::TopologyDictionary* mITSDict = nullptr; ///< cluster patterns dictionary o2::dataformats::GlobalTrackID::mask_t mSources{}; ///< which input sources are configured + o2::dataformats::GlobalTrackID::mask_t mSourcesMap{}; ///< possible subset of mSources specifically for map creation bool mUseMC{false}; ///< MC flag bool mProcessITSTPConly{false}; ///< should also tracks without outer point (ITS-TPC only) be processed? bool mProcessSeeds{false}; ///< process not only most complete track, but also its shorter parts @@ -64,7 +65,7 @@ class TPCInterpolationDPL : public Task }; /// create a processor spec -framework::DataProcessorSpec getTPCInterpolationSpec(o2::dataformats::GlobalTrackID::mask_t srcCls, o2::dataformats::GlobalTrackID::mask_t srcVtx, o2::dataformats::GlobalTrackID::mask_t srcTrk, bool useMC, bool processITSTPConly, bool sendTrackData, bool debugOutput); +framework::DataProcessorSpec getTPCInterpolationSpec(o2::dataformats::GlobalTrackID::mask_t srcCls, o2::dataformats::GlobalTrackID::mask_t srcVtx, o2::dataformats::GlobalTrackID::mask_t srcTrk, o2::dataformats::GlobalTrackID::mask_t srcTrkMap, bool useMC, bool processITSTPConly, bool sendTrackData, bool debugOutput); } // namespace tpc } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx index 89e3ae19cf65b..ac1ad304caba4 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx @@ -52,6 +52,9 @@ void TPCInterpolationDPL::init(InitContext& ic) mSlotLength = ic.options().get("sec-per-slot"); mProcessSeeds = ic.options().get("process-seeds"); mMatCorr = ic.options().get("matCorrType"); + if (mProcessSeeds && mSources != mSourcesMap) { + LOG(fatal) << "process-seeds option is not compatible with using different track sources for vDrift and map extraction"; + } } void TPCInterpolationDPL::updateTimeDependentParams(ProcessingContext& pc) @@ -63,7 +66,7 @@ void TPCInterpolationDPL::updateTimeDependentParams(ProcessingContext& pc) initOnceDone = true; // other init-once stuff const auto& param = SpacePointsCalibConfParam::Instance(); - mInterpolation.init(mSources); + mInterpolation.init(mSources, mSourcesMap); if (mProcessITSTPConly) { mInterpolation.setProcessITSTPConly(); } @@ -74,10 +77,10 @@ void TPCInterpolationDPL::updateTimeDependentParams(ProcessingContext& pc) if (nTracksPerTfMax > 0) { LOGP(info, "We will stop processing tracks after validating {} tracks per TF, since we want to accumulate {} tracks for a slot with {} TFs", nTracksPerTfMax, param.maxTracksPerCalibSlot, nTfs); - if (param.additionalTracksITSTPC > 0) { - int nITSTPCadd = param.additionalTracksITSTPC / nTfs; - LOGP(info, "In addition up to {} ITS-TPC tracks are processed per TF", nITSTPCadd); - mInterpolation.setAddITSTPCTracksPerTF(nITSTPCadd); + if (param.additionalTracksMap > 0) { + int nTracksAdditional = param.additionalTracksMap / nTfs; + LOGP(info, "In addition up to {} additional tracks are processed per TF", nTracksAdditional); + mInterpolation.setAddTracksForMapPerTF(nTracksAdditional); } } else if (nTracksPerTfMax < 0) { LOG(info) << "The number of processed tracks per TF is not limited"; @@ -155,7 +158,7 @@ void TPCInterpolationDPL::endOfStream(EndOfStreamContext& ec) mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getTPCInterpolationSpec(GTrackID::mask_t srcCls, GTrackID::mask_t srcVtx, GTrackID::mask_t srcTrk, bool useMC, bool processITSTPConly, bool sendTrackData, bool debugOutput) +DataProcessorSpec getTPCInterpolationSpec(GTrackID::mask_t srcCls, GTrackID::mask_t srcVtx, GTrackID::mask_t srcTrk, GTrackID::mask_t srcTrkMap, bool useMC, bool processITSTPConly, bool sendTrackData, bool debugOutput) { auto dataRequest = std::make_shared(); std::vector outputs; @@ -196,7 +199,7 @@ DataProcessorSpec getTPCInterpolationSpec(GTrackID::mask_t srcCls, GTrackID::mas "tpc-track-interpolation", dataRequest->inputs, outputs, - AlgorithmSpec{adaptFromTask(dataRequest, srcTrk, ggRequest, useMC, processITSTPConly, sendTrackData, debugOutput)}, + AlgorithmSpec{adaptFromTask(dataRequest, srcTrk, srcTrkMap, ggRequest, useMC, processITSTPConly, sendTrackData, debugOutput)}, Options{ {"matCorrType", VariantType::Int, 2, {"material correction type (definition in Propagator.h)"}}, {"sec-per-slot", VariantType::UInt32, 600u, {"number of seconds per calibration time slot (put 0 for infinite slot length)"}}, diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-interpolation-workflow.cxx b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-interpolation-workflow.cxx index f124cd965c796..0905942c956a4 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-interpolation-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-interpolation-workflow.cxx @@ -39,6 +39,7 @@ void customize(std::vector& workflowOptions) {"disable-mc", VariantType::Bool, false, {"disable MC propagation even if available"}}, {"vtx-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of sources used for the vertex finding"}}, {"tracking-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of sources to use for track inter-/extrapolation"}}, + {"tracking-sources-map-extraction", VariantType::String, std::string{GID::ALL}, {"can be subset of \"tracking-sources\""}}, {"send-track-data", VariantType::Bool, false, {"Send also the track information to the aggregator"}}, {"debug-output", VariantType::Bool, false, {"Dump extended tracking information for debugging"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; @@ -69,14 +70,24 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) GID::mask_t allowedSources = GID::getSourcesMask("ITS-TPC,ITS-TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD-TOF"); GID::mask_t srcVtx = allowedSources & GID::getSourcesMask(configcontext.options().get("vtx-sources")); GID::mask_t srcTracks = allowedSources & GID::getSourcesMask(configcontext.options().get("tracking-sources")); + GID::mask_t srcTracksMap = allowedSources & GID::getSourcesMask(configcontext.options().get("tracking-sources-map-extraction")); if (srcTracks.count() > srcVtx.count()) { LOGP(error, "More sources configured for inter-/extrapolation: {} than for vertexing: {}. Additional sources will be ignored", GID::getSourcesNames(srcTracks), GID::getSourcesNames(srcVtx)); srcTracks &= srcVtx; } + srcTracksMap &= srcVtx; + if (((srcTracksMap | srcTracks) ^ srcTracks).any()) { + LOGP(fatal, "tracking-sources-map-extraction ({}) must be a subset of tracking-sources ({}).", GID::getSourcesNames(srcTracksMap), GID::getSourcesNames(srcTracks)); + } else if (srcTracksMap != srcTracks) { + LOGP(info, "Will extract residual from different track types. For vDrift from {} and for distortion map from {}", GID::getSourcesNames(srcTracks), GID::getSourcesNames(srcTracksMap)); + } else { + LOGP(info, "Only a single track source is defined for residuals extraction: {}", GID::getSourcesNames(srcTracks)); + } LOG(debug) << "Data sources for inter-/extrapolation: " << GID::getSourcesNames(srcTracks); // check first if ITS-TPC tracks were specifically requested from command line bool processITSTPConly = srcTracks[GID::ITSTPC]; srcTracks |= GID::getSourcesMask("ITS,TPC,ITS-TPC"); // now add them in any case + srcTracksMap |= GID::getSourcesMask("ITS,TPC,ITS-TPC"); srcVtx |= srcTracks; GID::mask_t srcClusters = srcTracks; if (srcTracks[GID::ITSTPCTRD] || srcTracks[GID::ITSTPCTRDTOF]) { @@ -94,7 +105,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto sendTrackData = configcontext.options().get("send-track-data"); auto debugOutput = configcontext.options().get("debug-output"); - specs.emplace_back(o2::tpc::getTPCInterpolationSpec(srcClusters, srcVtx, srcTracks, useMC, processITSTPConly, sendTrackData, debugOutput)); + specs.emplace_back(o2::tpc::getTPCInterpolationSpec(srcClusters, srcVtx, srcTracks, srcTracksMap, useMC, processITSTPConly, sendTrackData, debugOutput)); if (!configcontext.options().get("disable-root-output")) { specs.emplace_back(o2::tpc::getTPCResidualWriterSpec(sendTrackData, debugOutput)); } diff --git a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h index 1c5d88dbb67c6..604a9e4adcde4 100644 --- a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h +++ b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h @@ -25,8 +25,8 @@ namespace tpc // These are configurable params for the TPC space point calibration struct SpacePointsCalibConfParam : public o2::conf::ConfigurableParamHelper { - int maxTracksPerCalibSlot = 3'500'000; ///< the number of tracks which is required to obtain an average correction map - int additionalTracksITSTPC = 2'000'000; ///< will be added to maxTracksPerCalibSlot for track sample with uniform acceptance (no PHOS hole) + int maxTracksPerCalibSlot = 500'000; ///< the number of tracks which is required to obtain an average correction map + int additionalTracksMap = 3'500'000; ///< will be added to maxTracksPerCalibSlot for track sample with uniform acceptance (no PHOS hole) // define track cuts for track interpolation int minTPCNCls = 70; ///< min number of TPC clusters diff --git a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h index c58c3154b6d2d..c9b37263389bd 100644 --- a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h +++ b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h @@ -189,13 +189,13 @@ class TrackInterpolation // -------------------------------------- processing functions -------------------------------------------------- /// Initialize everything, set the requested track sources - void init(o2::dataformats::GlobalTrackID::mask_t src); + void init(o2::dataformats::GlobalTrackID::mask_t src, o2::dataformats::GlobalTrackID::mask_t srcMap); /// Check if input track passes configured cuts bool isInputTrackAccepted(const o2::dataformats::GlobalTrackID& gid, const o2::globaltracking::RecoContainer::GlobalIDSet& gidTable, const o2::dataformats::PrimaryVertex& pv) const; /// For given vertex track source which is not in mSourcesConfigured find the seeding source which is enabled - o2::dataformats::GlobalTrackID::Source findValidSource(o2::dataformats::GlobalTrackID::Source src) const; + o2::dataformats::GlobalTrackID::Source findValidSource(const o2::dataformats::GlobalTrackID::mask_t mask, const o2::dataformats::GlobalTrackID::Source src) const; /// Prepare input track sample (not relying on CreateTracksVariadic functionality) void prepareInputTrackSample(const o2::globaltracking::RecoContainer& inp); @@ -252,8 +252,8 @@ class TrackInterpolation /// Sets the maximum number of tracks to be processed (successfully) per TF void setMaxTracksPerTF(int n) { mMaxTracksPerTF = n; } - /// In addition to mMaxTracksPerTF up to the set number of ITS-TPC only tracks can be processed - void setAddITSTPCTracksPerTF(int n) { mAddTracksITSTPC = n; } + /// In addition to mMaxTracksPerTF up to the set number of additional tracks can be processed + void setAddTracksForMapPerTF(int n) { mAddTracksForMapPerTF = n; } /// Enable full output void setDumpTrackPoints() { mDumpTrackPoints = true; } @@ -288,11 +288,13 @@ class TrackInterpolation float mSqrtS{13600.f}; ///< centre of mass energy set from LHC IF MatCorrType mMatCorr{MatCorrType::USEMatCorrNONE}; ///< if material correction should be done int mMaxTracksPerTF{-1}; ///< max number of tracks to be processed per TF (-1 means there is no limit) - int mAddTracksITSTPC{0}; ///< number of ITS-TPC tracks which can be processed in addition to mMaxTracksPerTF + int mAddTracksForMapPerTF{0}; ///< in case residuals from different track types are used for vDrift calibration and map creation this defines the statistics for the latter bool mDumpTrackPoints{false}; ///< dump also track points in ITS, TRD and TOF bool mProcessSeeds{false}; ///< in case for global tracks also their shorter parts are processed separately bool mProcessITSTPConly{false}; ///< flag, whether or not to extrapolate ITS-only through TPC - o2::dataformats::GlobalTrackID::mask_t mSourcesConfigured; ///< keep only the matches here, not the individual detector contributors + o2::dataformats::GlobalTrackID::mask_t mSourcesConfigured; ///< the track sources taken into account for extra-/interpolation + o2::dataformats::GlobalTrackID::mask_t mSourcesConfiguredMap; ///< possible subset of mSourcesConfigured + bool mSingleSourcesConfigured{true}; ///< whether mSourcesConfigured == mSourcesConfiguredMap // input const o2::globaltracking::RecoContainer* mRecoCont = nullptr; ///< input reco container diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index ea6fda70d92b9..3eb748a921cff 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -38,7 +38,7 @@ using namespace o2::tpc; using GTrackID = o2::dataformats::GlobalTrackID; using DetID = o2::detectors::DetID; -void TrackInterpolation::init(o2::dataformats::GlobalTrackID::mask_t src) +void TrackInterpolation::init(o2::dataformats::GlobalTrackID::mask_t src, o2::dataformats::GlobalTrackID::mask_t srcMap) { // perform initialization LOG(info) << "Start initializing TrackInterpolation"; @@ -58,13 +58,16 @@ void TrackInterpolation::init(o2::dataformats::GlobalTrackID::mask_t src) mParams = &SpacePointsCalibConfParam::Instance(); mSourcesConfigured = src; + mSourcesConfiguredMap = srcMap; + mSingleSourcesConfigured = (mSourcesConfigured == mSourcesConfiguredMap); mTrackTypes.insert({GTrackID::ITSTPC, 0}); mTrackTypes.insert({GTrackID::ITSTPCTRD, 1}); mTrackTypes.insert({GTrackID::ITSTPCTOF, 2}); mTrackTypes.insert({GTrackID::ITSTPCTRDTOF, 3}); mInitDone = true; - LOGP(info, "Done initializing TrackInterpolation. Configured track input: {}", GTrackID::getSourcesNames(mSourcesConfigured)); + LOGP(info, "Done initializing TrackInterpolation. Configured track input: {}. Track input specifically for map: {}", + GTrackID::getSourcesNames(mSourcesConfigured), mSingleSourcesConfigured ? "identical" : GTrackID::getSourcesNames(mSourcesConfiguredMap)); } bool TrackInterpolation::isInputTrackAccepted(const GTrackID& gid, const o2::globaltracking::RecoContainer::GlobalIDSet& gidTable, const o2::dataformats::PrimaryVertex& pv) const @@ -114,19 +117,19 @@ bool TrackInterpolation::isInputTrackAccepted(const GTrackID& gid, const o2::glo return true; } -GTrackID::Source TrackInterpolation::findValidSource(GTrackID::Source src) const +GTrackID::Source TrackInterpolation::findValidSource(const GTrackID::mask_t mask, const GTrackID::Source src) const { - LOGP(debug, "Trying to find valid source for {}", GTrackID::getSourcesNames(src)); + LOGP(debug, "Trying to find valid source for {} in {}", GTrackID::getSourceName(src), GTrackID::getSourcesNames(mask)); if (src == GTrackID::ITSTPCTRDTOF) { - if (mSourcesConfigured[GTrackID::ITSTPCTRD]) { + if (mask[GTrackID::ITSTPCTRD]) { return GTrackID::ITSTPCTRD; - } else if (mSourcesConfigured[GTrackID::ITSTPC]) { + } else if (mask[GTrackID::ITSTPC]) { return GTrackID::ITSTPC; } else { return GTrackID::NSources; } } else if (src == GTrackID::ITSTPCTRD || src == GTrackID::ITSTPCTOF) { - if (mSourcesConfigured[GTrackID::ITSTPC]) { + if (mask[GTrackID::ITSTPC]) { return GTrackID::ITSTPC; } else { return GTrackID::NSources; @@ -169,9 +172,9 @@ void TrackInterpolation::prepareInputTrackSample(const o2::globaltracking::RecoC } auto gidTable = mRecoCont->getSingleDetectorRefs(vid); if (!mSourcesConfigured[is]) { - auto src = findValidSource(static_cast(vid.getSource())); + auto src = findValidSource(mSourcesConfigured, static_cast(vid.getSource())); if (src == GTrackID::ITSTPCTRD || src == GTrackID::ITSTPC) { - LOGP(debug, "Found valid source {}", GTrackID::getSourcesNames(src)); + LOGP(debug, "prepareInputTrackSample: Found valid source {}", GTrackID::getSourceName(src)); vid = gidTable[src]; gidTable = mRecoCont->getSingleDetectorRefs(vid); } else { @@ -252,12 +255,12 @@ void TrackInterpolation::process() trackIndices.insert(trackIndices.end(), mTrackIndices[mTrackTypes[GTrackID::ITSTPC]].begin(), mTrackIndices[mTrackTypes[GTrackID::ITSTPC]].end()); int nSeeds = mSeeds.size(); - int maxOutputTracks = (mMaxTracksPerTF >= 0) ? mMaxTracksPerTF + mAddTracksITSTPC : nSeeds; + int maxOutputTracks = (mMaxTracksPerTF >= 0) ? mMaxTracksPerTF + mAddTracksForMapPerTF : nSeeds; mTrackData.reserve(maxOutputTracks); mClRes.reserve(maxOutputTracks * param::NPadRows); bool maxTracksReached = false; for (int iSeed = 0; iSeed < nSeeds; ++iSeed) { - if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksITSTPC) { + if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) { LOG(info) << "Maximum number of tracks per TF reached. Skipping the remaining " << nSeeds - iSeed << " tracks."; break; } @@ -265,6 +268,20 @@ void TrackInterpolation::process() if (mParams->enableTrackDownsampling && !isTrackSelected(mSeeds[seedIndex])) { continue; } + if (!mSingleSourcesConfigured && !mSourcesConfiguredMap[mGIDs[seedIndex].getSource()]) { + auto src = findValidSource(mSourcesConfiguredMap, static_cast(mGIDs[seedIndex].getSource())); + if (src == GTrackID::ITSTPCTRD || src == GTrackID::ITSTPC) { + LOGP(debug, "process: Found valid source {}", GTrackID::getSourceName(src)); + mGIDs.push_back(mGIDtables[seedIndex][src]); + mGIDtables.push_back(mRecoCont->getSingleDetectorRefs(mGIDs.back())); + mTrackTimes.push_back(mTrackTimes[seedIndex]); + mSeeds.push_back(mSeeds[seedIndex]); + } + } + if (mMaxTracksPerTF >= 0 && mTrackDataCompact.size() >= mMaxTracksPerTF) { + LOG(debug) << "We already have reached mMaxTracksPerTF, but we continue to create seeds until mAddTracksForMapPerTF is also reached"; + continue; + } if (mGIDs[seedIndex].includesDet(DetID::TRD) || mGIDs[seedIndex].includesDet(DetID::TOF)) { interpolateTrack(seedIndex); if (mProcessSeeds) { @@ -283,8 +300,16 @@ void TrackInterpolation::process() extrapolateTrack(seedIndex); } } + if (mSeeds.size() > nSeeds) { + LOGP(info, "Up to {} tracks out of {} additional seeds will be processed", mAddTracksForMapPerTF, mSeeds.size() - nSeeds); + } for (int iSeed = nSeeds; iSeed < (int)mSeeds.size(); ++iSeed) { + if (!mProcessSeeds && mAddTracksForMapPerTF > 0 && mTrackDataCompact.size() >= mMaxTracksPerTF + mAddTracksForMapPerTF) { + LOG(info) << "Maximum number of additional tracks per TF reached. Skipping the remaining " << mSeeds.size() - iSeed << " tracks."; + break; + } // this loop will only be entered in case mProcessSeeds is set + LOGP(debug, "Processing additional track {}", mGIDs[iSeed].asString()); if (mGIDs[iSeed].includesDet(DetID::TRD) || mGIDs[iSeed].includesDet(DetID::TOF)) { interpolateTrack(iSeed); } else { From aecee1b2d155e7f8f889aad11117c87f15532c70 Mon Sep 17 00:00:00 2001 From: shahoian Date: Sat, 13 Apr 2024 15:15:45 +0200 Subject: [PATCH 0101/2997] Do not store failed laser calib, ignore in VDriftHelper --- .../Detectors/TPC/include/DataFormatsTPC/LtrCalibData.h | 5 +++++ Detectors/TPC/calibration/src/VDriftHelper.cxx | 4 ++++ .../workflow/include/TPCWorkflow/CalibLaserTracksSpec.h | 8 ++++---- .../include/TPCWorkflow/LaserTracksCalibratorSpec.h | 4 ++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/LtrCalibData.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/LtrCalibData.h index 87b8b3d6c7130..e410cd00dd3f6 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/LtrCalibData.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/LtrCalibData.h @@ -43,6 +43,11 @@ struct LtrCalibData { std::vector nTrackTF; ///< number of laser tracks per TF std::vector dEdx; ///< dE/dx of each track + bool isValid() const + { + return (std::abs(dvCorrectionA - 1.f) < 0.2) || (std::abs(dvCorrectionC - 1.f) < 0.2); + } + float getDriftVCorrection() const { float correction = 0; diff --git a/Detectors/TPC/calibration/src/VDriftHelper.cxx b/Detectors/TPC/calibration/src/VDriftHelper.cxx index 12b43c255d0b3..eb36ee4351168 100644 --- a/Detectors/TPC/calibration/src/VDriftHelper.cxx +++ b/Detectors/TPC/calibration/src/VDriftHelper.cxx @@ -57,6 +57,10 @@ void VDriftHelper::accountLaserCalibration(const LtrCalibData* calib, long fallB if (!calib || mForceParamDrift) { // laser may set only DriftParam (the offset is 0) return; } + if (!calib->isValid()) { + LOGP(warn, "Ignoring invalid laser calibration (corrections: A-side={}, C-side={}, NTracks: A-side={} C-side={})", calib->dvCorrectionA, calib->dvCorrectionC, calib->nTracksA, calib->nTracksC); + return; + } // old entries of laser calib have no update time assigned long updateTS = calib->creationTime > 0 ? calib->creationTime : fallBackTimeStamp; LOG(info) << "accountLaserCalibration " << calib->refVDrift << " / " << calib->getDriftVCorrection() << " t " << updateTS << " vs " << mVDLaser.creationTime; diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/CalibLaserTracksSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/CalibLaserTracksSpec.h index 3222d24667760..207bea0e7fa42 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/CalibLaserTracksSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/CalibLaserTracksSpec.h @@ -121,15 +121,15 @@ class CalibLaserTracksDevice : public o2::framework::Task using clbUtils = o2::calibration::Utils; auto ltrCalib = mCalib.getCalibData(); + if (!ltrCalib.isValid()) { + LOGP(error, "Invalid Laser calibration (corrections: A-side={}, C-side={}, NTracks: A-side={} C-side={}), will NOT upload to CCDB", ltrCalib.dvCorrectionA, ltrCalib.dvCorrectionC, ltrCalib.nTracksA, ltrCalib.nTracksC); + return; + } if (mNormalize) { ltrCalib.normalize(0.); LOGP(info, "After normalization: correction factors: {} / {} for A- / C-Side, reference: {}, vdrift correction: {}", ltrCalib.dvCorrectionA, ltrCalib.dvCorrectionC, ltrCalib.refVDrift, ltrCalib.getDriftVCorrection()); } - if (ltrCalib.getDriftVCorrection() == 0) { - LOG(error) << "Extracted drift correction is 0, something is wrong, will not upload the object"; - return; - } o2::ccdb::CcdbObjectInfo w; auto image = o2::ccdb::CcdbApi::createObjectImage(<rCalib, &w); diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/LaserTracksCalibratorSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/LaserTracksCalibratorSpec.h index dad23046c2578..9d8ca28447db7 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/LaserTracksCalibratorSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/LaserTracksCalibratorSpec.h @@ -88,6 +88,10 @@ class LaserTracksCalibratorDevice : public o2::framework::Task const long timeEnd = o2::ccdb::CcdbObjectInfo::INFINITE_TIMESTAMP; for (uint32_t iCalib = 0; iCalib < calibrations.size(); ++iCalib) { const auto& object = calibrations[iCalib]; + if (!object.isValid()) { + LOGP(error, "Invalid Laser calibration (corrections: A-side={}, C-side={}, NTracks: A-side={} C-side={}), will NOT upload to CCDB", object.dvCorrectionA, object.dvCorrectionC, object.nTracksA, object.nTracksC); + continue; + } o2::ccdb::CcdbObjectInfo w; auto image = o2::ccdb::CcdbApi::createObjectImage(&object, &w); From 3d8d171d83a345b6e6f6f669116da3582feda9ec Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 18 Jan 2024 22:43:29 +0100 Subject: [PATCH 0102/2997] macro to dump volumes ideal and real origins in lab frame --- Detectors/Align/macro/CMakeLists.txt | 5 ++ Detectors/Align/macro/algDump.C | 93 ++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 Detectors/Align/macro/algDump.C diff --git a/Detectors/Align/macro/CMakeLists.txt b/Detectors/Align/macro/CMakeLists.txt index 49106e647c412..54c8715b074b2 100644 --- a/Detectors/Align/macro/CMakeLists.txt +++ b/Detectors/Align/macro/CMakeLists.txt @@ -10,6 +10,7 @@ # or submit itself to any jurisdiction. install(FILES algconf.C + algDump.C MPRec2Mille.C DESTINATION share/Detectors/Align/macro) @@ -17,6 +18,10 @@ o2_add_test_root_macro(algconf.C PUBLIC_LINK_LIBRARIES O2::Align LABELS align COMPILE_ONLY) +o2_add_test_root_macro(algDump.C + PUBLIC_LINK_LIBRARIES O2::Align + LABELS align COMPILE_ONLY) + o2_add_test_root_macro(MPRec2Mille.C PUBLIC_LINK_LIBRARIES O2::Align LABELS align COMPILE_ONLY) diff --git a/Detectors/Align/macro/algDump.C b/Detectors/Align/macro/algDump.C new file mode 100644 index 0000000000000..865f8a0bbf6a0 --- /dev/null +++ b/Detectors/Align/macro/algDump.C @@ -0,0 +1,93 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "DetectorsBase/GeometryManager.h" +#include "CommonUtils/TreeStreamRedirector.h" +#include "ITSMFTReconstruction/ChipMappingITS.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DataFormatsTRD/Constants.h" +#include "TRDBase/Geometry.h" +#include "TOFBase/Geo.h" +#include +#endif + +using DetID = o2::detectors::DetID; + +void algDump(const std::string& geom = "", const std::string& outname = "algdump.root") +{ + o2::base::GeometryManager::loadGeometry(geom.c_str()); + o2::utils::TreeStreamRedirector outstream(outname.c_str(), "recreate"); + TGeoHMatrix* matAlg = nullptr; + TGeoHMatrix matOrig; + TVector3 pos0, pos; + DetID det; + + auto procSens = [](TGeoHMatrix& mat) { + double loc[3] = {0., 0., 0.}, glo[3]; + mat.LocalToMaster(loc, glo); + return TVector3(glo[0], glo[1], glo[2]); + }; + + auto store = [&outstream, &det, &pos, &pos0](int lr, int sid, int sidLr) { + outstream << "gm" + << "det=" << det.getID() << "lr=" << lr << "sid=" << sid << "sidlr=" << sidLr << "pos0=" << pos0 << "pos=" << pos << "\n"; + // printf("xx %d %d %d %f %f %f\n", det.getID(), lr, sid, pos0[0], pos0[1], pos0[1]); + }; + + det = DetID("ITS"); + o2::itsmft::ChipMappingITS mpits; + for (int ic = 0; ic < mpits.getNChips(); ic++) { + int lr = mpits.getLayer(ic); + int ic0 = ic - mpits.getFirstChipsOnLayer(lr); + matAlg = o2::base::GeometryManager::getMatrix(det, ic); + o2::base::GeometryManager::getOriginalMatrix(det, ic, matOrig); + pos0 = procSens(matOrig); + pos = procSens(*matAlg); + store(lr, ic, ic0); + } + + det = DetID("TRD"); + for (int ilr = 0; ilr < o2::trd::constants::NLAYER; ilr++) { // layer + for (int ich = 0; ich < o2::trd::constants::NSTACK * o2::trd::constants::NSECTOR; ich++) { // chamber + int isector = ich / o2::trd::constants::NSTACK; + int istack = ich % o2::trd::constants::NSTACK; + uint16_t sid = o2::trd::Geometry::getDetector(ilr, istack, isector); + const char* symname = Form("TRD/sm%02d/st%d/pl%d", isector, istack, ilr); + if (!gGeoManager->GetAlignableEntry(symname)) { + continue; + } + matAlg = o2::base::GeometryManager::getMatrix(det, sid); + o2::base::GeometryManager::getOriginalMatrix(det, sid, matOrig); + pos0 = procSens(matOrig); + pos = procSens(*matAlg); + store(ilr, sid, ich); + } + } + + det = DetID("TOF"); + int cnt = -1; + for (int isc = 0; isc < 18; isc++) { + for (int istr = 1; istr <= o2::tof::Geo::NSTRIPXSECTOR; istr++) { // strip + const char* symname = Form("TOF/sm%02d/strip%02d", isc, istr); + cnt++; + if (!gGeoManager->GetAlignableEntry(symname)) { + continue; + } + matAlg = o2::base::GeometryManager::getMatrix(det, cnt); + o2::base::GeometryManager::getOriginalMatrix(det, cnt, matOrig); + pos0 = procSens(matOrig); + pos = procSens(*matAlg); + store(0, cnt, cnt); + } + } + outstream.Close(); +} From f7351c9c3d019702e033e4bc96c92e6b016ae9f8 Mon Sep 17 00:00:00 2001 From: Ole Schmidt Date: Mon, 15 Apr 2024 16:47:52 +0200 Subject: [PATCH 0103/2997] Add debug output to TRD gain calibration (#13026) --- Detectors/TRD/calibration/src/CalibratorGain.cxx | 1 + Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/TRD/calibration/src/CalibratorGain.cxx b/Detectors/TRD/calibration/src/CalibratorGain.cxx index 028fcdc2bdc23..6b5ff2bdc7674 100644 --- a/Detectors/TRD/calibration/src/CalibratorGain.cxx +++ b/Detectors/TRD/calibration/src/CalibratorGain.cxx @@ -104,6 +104,7 @@ void CalibratorGain::retrievePrev(o2::framework::ProcessingContext& pc) void CalibratorGain::finalizeSlot(Slot& slot) { LOG(info) << "Finalizing gain calibration"; + print(); // to see current number of slots and their entries // do actual calibration for the data provided in the given slot TStopwatch timer; timer.Start(); diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h index eb6641e05adf2..295ce0bf1d0ac 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h @@ -72,7 +72,7 @@ class GainCalibDevice : public o2::framework::Task o2::base::GRPGeomHelper::instance().checkUpdates(pc); auto dataGainCalib = pc.inputs().get>("input"); o2::base::TFIDInfoHelper::fillTFIDInfo(pc, mCalibrator->getCurrentTFInfo()); - LOG(info) << "Processing TF " << mCalibrator->getCurrentTFInfo().tfCounter << " with " << dataGainCalib.size() << " GainCalibHistos entries"; + LOG(debug) << "Processing TF " << mCalibrator->getCurrentTFInfo().tfCounter << " with " << dataGainCalib.size() << " GainCalibHistos entries"; mCalibrator->process(dataGainCalib); if (pc.transitionState() == TransitionHandlingState::Requested) { LOG(info) << "Run stop requested, finalizing"; From af60a6759561ccf7e12013b19d25c5ae7bd99bb6 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 11 Apr 2024 13:29:22 +0200 Subject: [PATCH 0104/2997] Account EmptyChips in active chips status --- .../ITSMFTReconstruction/AlpideCoder.h | 6 ++++- .../ITSMFTReconstruction/RUDecodeData.h | 4 +++- .../ITSMFTReconstruction/RawPixelDecoder.h | 22 +++++++++---------- .../ITSMFTReconstruction/RawPixelReader.h | 3 ++- .../common/workflow/src/STFDecoderSpec.cxx | 6 ++--- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h index 8a4139a9c3bfe..74798b04a3b39 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/AlpideCoder.h @@ -122,7 +122,7 @@ class AlpideCoder /// decode alpide data for the next non-empty chip from the buffer template - static int decodeChip(ChipPixelData& chipData, T& buffer, CG cidGetter) + static int decodeChip(ChipPixelData& chipData, T& buffer, std::vector& seenChips, CG cidGetter) { // read record for single non-empty chip, updating on change module and cycle. // return number of records filled (>0), EOFFlag or Error @@ -198,6 +198,7 @@ class AlpideCoder #endif return unexpectedEOF("CHIP_EMPTY:Timestamp"); // abandon cable data } + seenChips.push_back(chipIDGlo); chipData.resetChipID(); expectInp = ExpectChipHeader | ExpectChipEmpty; continue; @@ -438,6 +439,9 @@ class AlpideCoder prevPix = currPix++; } } + if (chipData.getData().size()) { + seenChips.push_back(chipData.getChipID()); + } return chipData.getData().size(); } diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h index ddc4db51fe2a8..0f2725821b1f8 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h @@ -36,6 +36,7 @@ struct RUDecodeData { std::array cableData{}; // cable data in compressed ALPIDE format std::vector chipsData{}; // fully decoded data in 1st nChipsFired chips + std::vector seenChipIDs{}; // IDs of all chips seen during ROF decoding, including empty ones std::array links{}; // link entry RSTODO: consider removing this and using pointer std::array cableHWID{}; // HW ID of cable whose data is in the corresponding slot of cableData std::array cableLinkID{}; // ID of the GBT link transmitting this cable data @@ -79,6 +80,7 @@ int RUDecodeData::decodeROF(const Mapping& mp, const o2::InteractionRecord ir) std::array doneChips{}; auto* chipData = &chipsData[0]; + seenChipIDs.clear(); for (int icab = 0; icab < ruInfo->nCables; icab++) { // cableData is ordered in such a way to have chipIDs in increasing order if (!cableData[icab].getSize()) { continue; @@ -95,7 +97,7 @@ int RUDecodeData::decodeROF(const Mapping& mp, const o2::InteractionRecord ir) int ret = 0; // dumpcabledata(icab); - while ((ret = AlpideCoder::decodeChip(*chipData, cableData[icab], chIdGetter)) || chipData->isErrorSet()) { // we register only chips with hits or errors flags set + while ((ret = AlpideCoder::decodeChip(*chipData, cableData[icab], seenChipIDs, chIdGetter)) || chipData->isErrorSet()) { // we register only chips with hits or errors flags set setROFInfo(chipData, cableLinkPtr[icab]); auto nhits = chipData->getData().size(); if (nhits && doneChips[chipData->getChipID()]) { diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index a6f44a984ce01..e4f83a5b31b28 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -60,8 +60,8 @@ class RawPixelDecoder final : public PixelReader void collectROFCableData(int iru); int decodeNextTrigger() final; - template - int fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs, STATVEC& chipStatus); + template + int fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs); template void fillChipsStatus(STATVEC& chipStatus); @@ -128,6 +128,7 @@ class RawPixelDecoder final : public PixelReader uint16_t getSquashingDepth() { return 0; } bool doIRMajorityPoll(); + bool isRampUpStage() const { return mROFRampUpStage; } void reset(); private: @@ -179,8 +180,8 @@ class RawPixelDecoder final : public PixelReader ///______________________________________________________________ /// Fill decoded digits to global vector template -template -int RawPixelDecoder::fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs, STATVEC& chipStatus) +template +int RawPixelDecoder::fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs) { if (mInteractionRecord.isDummy()) { return 0; // nothing was decoded @@ -190,7 +191,6 @@ int RawPixelDecoder::fillDecodedDigits(DigitContainer& digits, ROFConta for (unsigned int iru = 0; iru < mRUDecodeVec.size(); iru++) { for (int ic = 0; ic < mRUDecodeVec[iru].nChipsFired; ic++) { const auto& chip = mRUDecodeVec[iru].chipsData[ic]; - chipStatus[chip.getChipID()] = 1; for (const auto& hit : mRUDecodeVec[iru].chipsData[ic].getData()) { digits.emplace_back(chip.getChipID(), hit.getRow(), hit.getCol()); } @@ -205,8 +205,8 @@ int RawPixelDecoder::fillDecodedDigits(DigitContainer& digits, ROFConta ///______________________________________________________________ /// Fill decoded digits to global vector template <> -template -int RawPixelDecoder::fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs, STATVEC& chipStatus) +template +int RawPixelDecoder::fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs) { if (mInteractionRecord.isDummy()) { return 0; // nothing was decoded @@ -216,7 +216,6 @@ int RawPixelDecoder::fillDecodedDigits(DigitContainer& digits, R for (auto chipData = mOrderedChipsPtr.rbegin(); chipData != mOrderedChipsPtr.rend(); ++chipData) { assert(mLastReadChipID < (*chipData)->getChipID()); mLastReadChipID = (*chipData)->getChipID(); - chipStatus[mLastReadChipID] = 1; for (const auto& hit : (*chipData)->getData()) { digits.emplace_back(mLastReadChipID, hit.getRow(), hit.getCol()); } @@ -233,13 +232,12 @@ template template void RawPixelDecoder::fillChipsStatus(STATVEC& chipStatus) { - if (mInteractionRecord.isDummy()) { + if (mInteractionRecord.isDummy() || mROFRampUpStage) { return; // nothing was decoded } for (unsigned int iru = 0; iru < mRUDecodeVec.size(); iru++) { - for (int ic = 0; ic < mRUDecodeVec[iru].nChipsFired; ic++) { - const auto& chip = mRUDecodeVec[iru].chipsData[ic]; - chipStatus[chip.getChipID()] = 1; + for (auto chID : mRUDecodeVec[iru].seenChipIDs) { + chipStatus[chID] = 1; } } } diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h index b1fefcdb91b63..97716059f12d6 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h @@ -1256,7 +1256,8 @@ class RawPixelReader : public PixelReader auto chIdGetter = [this, cabHW, ri](int cid) { return this->mMAP.getGlobalChipID(cid, cabHW, *ri); }; - while ((res = mCoder.decodeChip(*chipData, cableData, chIdGetter))) { // we register only chips with hits or errors flags set + std::vector dummyStat; + while ((res = mCoder.decodeChip(*chipData, cableData, dummyStat, chIdGetter))) { // we register only chips with hits or errors flags set if (res > 0) { #ifdef _RAW_READER_ERROR_CHECKS_ // for the IB staves check if the cable ID is the same as the chip ID on the module diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index 33b4597b9b420..3976f8277aa59 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -171,14 +171,12 @@ void STFDecoder::run(ProcessingContext& pc) continue; } lastIR = mDecoder->getInteractionRecord(); + mDecoder->fillChipsStatus(chipStatus); if (mDoDigits || mClusterer->getMaxROFDepthToSquash()) { // call before clusterization, since the latter will hide the digits - mDecoder->fillDecodedDigits(digVec, digROFVec, chipStatus); // lot of copying involved - + mDecoder->fillDecodedDigits(digVec, digROFVec); // lot of copying involved if (mDoCalibData) { mDecoder->fillCalibData(calVec); } - } else { - mDecoder->fillChipsStatus(chipStatus); } if (mDoClusters && !mClusterer->getMaxROFDepthToSquash()) { // !!! THREADS !!! mClusterer->process(mNThreads, *mDecoder.get(), &clusCompVec, mDoPatterns ? &clusPattVec : nullptr, &clusROFVec); From 9d3b9a0901b8fbd2476e28c58d48c6503a457f56 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Tue, 16 Apr 2024 01:55:29 +0200 Subject: [PATCH 0105/2997] [EMCAL-710] Fix namespace in stream operator (#13027) Stream operator for ErrorTypeFEE must be put explicitly into namespace o2::emcal, otherwise it is part of the global namespace. --- DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx b/DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx index c1c933eaba92e..25d1addf4b41b 100644 --- a/DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx +++ b/DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx @@ -111,7 +111,7 @@ const char* ErrorTypeFEE::getErrorTypeTitle(unsigned int errorTypeID) }; } -std::ostream& operator<<(std::ostream& stream, const ErrorTypeFEE& error) +std::ostream& o2::emcal::operator<<(std::ostream& stream, const ErrorTypeFEE& error) { error.PrintStream(stream); return stream; From 4344c807a80948f1694a1af7e0f6f23e4ee00565 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Mon, 15 Apr 2024 14:34:12 +0200 Subject: [PATCH 0106/2997] TPC Cluster finder: Update debug mode. - Adjust debug masks, ensure only clusters are dumped with default masks. - Dump peak map in debug mode. - Some code cleanup --- .../Global/GPUChainTrackingClusterizer.cxx | 25 ++--- .../TPCClusterFinder/GPUTPCClusterFinder.h | 4 +- .../GPUTPCClusterFinderDump.cxx | 96 ++++++++++++++----- 3 files changed, 86 insertions(+), 39 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index 29bbf34b46135..c26968513611a 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -711,7 +711,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) if (fragment.index == 0) { runKernel({GetGridAutoStep(lane, RecoStep::TPCClusterFinding)}, clustererShadow.mPpadIsNoisy, TPC_PADS_IN_SECTOR * sizeof(*clustererShadow.mPpadIsNoisy)); } - DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Zeroed Charges", doGPU); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Zeroed Charges"); if (doGPU) { if (mIOPtrs.tpcZS && mCFContext->nPagesSector[iSlice] && mCFContext->zsVersion != -1) { @@ -799,8 +799,8 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) if (!mIOPtrs.tpcZS) { runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}}); } - if (DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpDigits, *mDebugFile)) { - clusterer.DumpChargeMap(*mDebugFile, "Charges", doGPU); + if (DoDebugAndDump(RecoStep::TPCClusterFinding, 262144 << 1, clusterer, &GPUTPCClusterFinder::DumpDigits, *mDebugFile)) { + clusterer.DumpChargeMap(*mDebugFile, "Charges"); } if (propagateMCLabels) { @@ -818,11 +818,13 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}}); - DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpPeaks, *mDebugFile); + if (DoDebugAndDump(RecoStep::TPCClusterFinding, 262144 << 2, clusterer, &GPUTPCClusterFinder::DumpPeaks, *mDebugFile)) { + clusterer.DumpPeakMap(*mDebugFile, "Peaks"); + } RunTPCClusterizer_compactPeaks(clusterer, clustererShadow, 0, doGPU, lane); TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); - DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpPeaksCompacted, *mDebugFile); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144 << 2, clusterer, &GPUTPCClusterFinder::DumpPeaksCompacted, *mDebugFile); } GPUCA_OPENMP(parallel for if(!doGPU && GetProcessingSettings().ompKernels != 1) num_threads(mRec->SetAndGetNestedLoopOmpFactor(!doGPU, GetProcessingSettings().nTPCClustererLanes))) for (int lane = 0; lane < maxLane; lane++) { @@ -837,11 +839,13 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } runKernel({GetGrid(clusterer.mPmemory->counters.nPeaks, lane), {iSlice}}); runKernel({GetGrid(clusterer.mPmemory->counters.nPeaks, lane), {iSlice}}); - DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpSuppressedPeaks, *mDebugFile); + if (DoDebugAndDump(RecoStep::TPCClusterFinding, 262144 << 3, clusterer, &GPUTPCClusterFinder::DumpSuppressedPeaks, *mDebugFile)) { + clusterer.DumpPeakMap(*mDebugFile, "Suppressed Peaks"); + } RunTPCClusterizer_compactPeaks(clusterer, clustererShadow, 1, doGPU, lane); TransferMemoryResourceLinkToHost(RecoStep::TPCClusterFinding, clusterer.mMemoryId, lane); - DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpSuppressedPeaksCompacted, *mDebugFile); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144 << 3, clusterer, &GPUTPCClusterFinder::DumpSuppressedPeaksCompacted, *mDebugFile); } GPUCA_OPENMP(parallel for if(!doGPU && GetProcessingSettings().ompKernels != 1) num_threads(mRec->SetAndGetNestedLoopOmpFactor(!doGPU, GetProcessingSettings().nTPCClustererLanes))) for (int lane = 0; lane < maxLane; lane++) { @@ -862,7 +866,7 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSlice}}); - DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges", doGPU); + DoDebugAndDump(RecoStep::TPCClusterFinding, 262144 << 4, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges"); runKernel({GetGrid(clusterer.mPmemory->counters.nClusters, lane), {iSlice}}, 0); if (doGPU && propagateMCLabels) { @@ -878,9 +882,8 @@ int GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) TransferMemoryResourcesToHost(RecoStep::TPCClusterFinding, &clusterer, lane); laneHasData[lane] = true; - if (DoDebugAndDump(RecoStep::TPCClusterFinding, 262144, clusterer, &GPUTPCClusterFinder::DumpCountedPeaks, *mDebugFile)) { - clusterer.DumpClusters(*mDebugFile); - } + // Include clusters in default debug mask, exclude other debug output by default + DoDebugAndDump(RecoStep::TPCClusterFinding, 131072, clusterer, &GPUTPCClusterFinder::DumpClusters, *mDebugFile); } mRec->SetNestedLoopOmpFactor(1); } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h index 4488d7cd1a711..ca89053797a47 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.h @@ -143,12 +143,12 @@ class GPUTPCClusterFinder : public GPUProcessor #ifndef GPUCA_GPUCODE void DumpDigits(std::ostream& out); - void DumpChargeMap(std::ostream& out, std::string_view, bool doGPU); + void DumpChargeMap(std::ostream& out, std::string_view); + void DumpPeakMap(std::ostream& out, std::string_view); void DumpPeaks(std::ostream& out); void DumpPeaksCompacted(std::ostream& out); void DumpSuppressedPeaks(std::ostream& out); void DumpSuppressedPeaksCompacted(std::ostream& out); - void DumpCountedPeaks(std::ostream& out); void DumpClusters(std::ostream& out); #endif }; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinderDump.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinderDump.cxx index de8583f8cd9e7..389209d9bb884 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinderDump.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinderDump.cxx @@ -22,23 +22,29 @@ using namespace GPUCA_NAMESPACE::gpu::tpccf; void GPUTPCClusterFinder::DumpDigits(std::ostream& out) { - out << "\nClusterer - Digits - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << ": " << mPmemory->counters.nPositions << "\n"; + const auto nPositions = mPmemory->counters.nPositions; + + out << "\nClusterer - Digits - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << ": " << nPositions << "\n"; out << std::hex; for (size_t i = 0; i < mPmemory->counters.nPositions; i++) { - out << mPpositions[i].time() << " " << mPpositions[i].gpad << '\n'; + const auto& pos = mPpositions[i]; + out << pos.time() << " " << pos.gpad << '\n'; } out << std::dec; } -void GPUTPCClusterFinder::DumpChargeMap(std::ostream& out, std::string_view title, bool doGPU) +void GPUTPCClusterFinder::DumpChargeMap(std::ostream& out, std::string_view title) { out << "\nClusterer - " << title << " - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << "\n"; Array2D map(mPchargeMap); out << std::hex; - for (TPCFragmentTime i = 0; i < TPC_MAX_FRAGMENT_LEN_PADDED(mRec->GetProcessingSettings().overrideClusterizerFragmentLen); i++) { + TPCFragmentTime start = 0; + TPCFragmentTime end = TPC_MAX_FRAGMENT_LEN_PADDED(mRec->GetProcessingSettings().overrideClusterizerFragmentLen); + + for (TPCFragmentTime i = start; i < end; i++) { int zeros = 0; for (GlobalPad j = 0; j < TPC_NUM_OF_PADS; j++) { ushort q = map[{j, i}]; @@ -61,11 +67,47 @@ void GPUTPCClusterFinder::DumpChargeMap(std::ostream& out, std::string_view titl out << std::dec; } +void GPUTPCClusterFinder::DumpPeakMap(std::ostream& out, std::string_view title) +{ + out << "\nClusterer - " << title << " - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << "\n"; + + Array2D map(mPpeakMap); + + out << std::hex; + + TPCFragmentTime start = 0; + TPCFragmentTime end = TPC_MAX_FRAGMENT_LEN_PADDED(mRec->GetProcessingSettings().overrideClusterizerFragmentLen); + + for (TPCFragmentTime i = start; i < end; i++) { + int zeros = 0; + + out << i << ":"; + for (GlobalPad j = 0; j < TPC_NUM_OF_PADS; j++) { + uchar q = map[{j, i}]; + zeros += (q == 0); + if (q != 0) { + if (zeros > 0) { + out << " z" << zeros; + zeros = 0; + } + + out << " p" << int{q}; + } + } + if (zeros > 0) { + out << " z" << zeros; + } + out << '\n'; + } + + out << std::dec; +} + void GPUTPCClusterFinder::DumpPeaks(std::ostream& out) { out << "\nClusterer - Peaks - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << "\n"; for (unsigned int i = 0; i < mPmemory->counters.nPositions; i++) { - out << (int)mPisPeak[i] << " "; + out << int{mPisPeak[i]}; if ((i + 1) % 100 == 0) { out << "\n"; } @@ -74,17 +116,23 @@ void GPUTPCClusterFinder::DumpPeaks(std::ostream& out) void GPUTPCClusterFinder::DumpPeaksCompacted(std::ostream& out) { - out << "\nClusterer - Compacted Peaks - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << ": " << mPmemory->counters.nPeaks << "\n"; - for (size_t i = 0; i < mPmemory->counters.nPeaks; i++) { - out << mPpeakPositions[i].time() << ", " << (int)mPpeakPositions[i].pad() << ", " << (int)mPpeakPositions[i].row() << "\n"; + const auto nPeaks = mPmemory->counters.nPeaks; + + out << "\nClusterer - Compacted Peaks - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << ": " << nPeaks << "\n"; + for (size_t i = 0; i < nPeaks; i++) { + const auto& pos = mPpeakPositions[i]; + out << pos.time() << " " << int{pos.pad()} << " " << int{pos.row()} << "\n"; } } void GPUTPCClusterFinder::DumpSuppressedPeaks(std::ostream& out) { - out << "\nClusterer - NoiseSuppression - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << mISlice << "\n"; - for (unsigned int i = 0; i < mPmemory->counters.nPeaks; i++) { - out << (int)mPisPeak[i] << " "; + const auto& fragment = mPmemory->fragment; + const auto nPeaks = mPmemory->counters.nPeaks; + + out << "\nClusterer - NoiseSuppression - Slice " << mISlice << " - Fragment " << fragment.index << mISlice << "\n"; + for (unsigned int i = 0; i < nPeaks; i++) { + out << int{mPisPeak[i]}; if ((i + 1) % 100 == 0) { out << "\n"; } @@ -93,17 +141,13 @@ void GPUTPCClusterFinder::DumpSuppressedPeaks(std::ostream& out) void GPUTPCClusterFinder::DumpSuppressedPeaksCompacted(std::ostream& out) { - out << "\nClusterer - Noise Suppression Peaks Compacted - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << ": " << mPmemory->counters.nClusters << "\n"; - for (size_t i = 0; i < mPmemory->counters.nClusters; i++) { - out << i << ": " << mPfilteredPeakPositions[i].time() << ", " << (int)mPfilteredPeakPositions[i].pad() << ", " << (int)mPfilteredPeakPositions[i].row() << "\n"; - } -} + const auto& fragment = mPmemory->fragment; + const auto nPeaks = mPmemory->counters.nClusters; -void GPUTPCClusterFinder::DumpCountedPeaks(std::ostream& out) -{ - out << "\nClusterer - Peak Counts - Slice " << mISlice << " - Fragment " << mPmemory->fragment.index << "\n"; - for (int i = 0; i < GPUCA_ROW_COUNT; i++) { - out << i << ": " << mPclusterInRow[i] << "\n"; + out << "\nClusterer - Noise Suppression Peaks Compacted - Slice " << mISlice << " - Fragment " << fragment.index << ": " << nPeaks << "\n"; + for (size_t i = 0; i < nPeaks; i++) { + const auto& peak = mPfilteredPeakPositions[i]; + out << peak.time() << " " << int{peak.pad()} << " " << int{peak.row()} << "\n"; } } @@ -113,15 +157,15 @@ void GPUTPCClusterFinder::DumpClusters(std::ostream& out) for (int i = 0; i < GPUCA_ROW_COUNT; i++) { size_t N = mPclusterInRow[i]; - out << "Row: " << i << ": " << N << "\n"; - std::vector sortedCluster(N); - tpc::ClusterNative* row = &mPclusterByRow[i * mNMaxClusterPerRow]; - std::copy(row, &row[N], sortedCluster.begin()); + const tpc::ClusterNative* row = &mPclusterByRow[i * mNMaxClusterPerRow]; + std::vector sortedCluster; + sortedCluster.insert(sortedCluster.end(), row, row + N); std::sort(sortedCluster.begin(), sortedCluster.end()); + out << "Row: " << i << ": " << N << "\n"; for (const auto& cl : sortedCluster) { - out << std::hex << cl.timeFlagsPacked << std::dec << ", " << cl.padPacked << ", " << (int)cl.sigmaTimePacked << ", " << (int)cl.sigmaPadPacked << ", " << cl.qMax << ", " << cl.qTot << "\n"; + out << std::hex << cl.timeFlagsPacked << std::dec << " " << cl.padPacked << " " << int{cl.sigmaTimePacked} << " " << int{cl.sigmaPadPacked} << " " << cl.qMax << " " << cl.qTot << "\n"; } } } From 7a9ed8cce90611b1def5aa4fce358c11ed5d8e14 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 16 Apr 2024 12:32:25 +0200 Subject: [PATCH 0107/2997] DPL: Fix debug message, which was showing the previous slot --- Framework/Core/src/TimesliceIndex.cxx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Framework/Core/src/TimesliceIndex.cxx b/Framework/Core/src/TimesliceIndex.cxx index 843ef55ead060..2ddf2007d0100 100644 --- a/Framework/Core/src/TimesliceIndex.cxx +++ b/Framework/Core/src/TimesliceIndex.cxx @@ -208,14 +208,16 @@ TimesliceIndex::OldestOutputInfo TimesliceIndex::updateOldestPossibleOutput() } } O2_SIGNPOST_ID_GENERATE(tid, timeslice_index); - if (changed && mOldestPossibleOutput.timeslice.value != result.timeslice.value) { - O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "updateOldestPossibleOutput", "Oldest possible output %zu due to %{public}s %zu", - result.timeslice.value, - result.channel.value == -1 ? "slot" : "channel", - result.channel.value == -1 ? mOldestPossibleOutput.slot.index : mOldestPossibleOutput.channel.value); - } else if (mOldestPossibleOutput.timeslice.value != result.timeslice.value) { - O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "updateOldestPossibleOutput", "Oldest possible output updated from oldest Input : %zu --> %zu", - mOldestPossibleOutput.timeslice.value, result.timeslice.value); + if (mOldestPossibleOutput.timeslice.value != result.timeslice.value) { + if (changed) { + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "updateOldestPossibleOutput", "Oldest possible output %zu (before %zu) due to %s %zu", + result.timeslice.value, mOldestPossibleOutput.timeslice.value, + result.channel.value == -1 ? "slot" : "channel", + result.channel.value == -1 ? result.slot.index : result.channel.value); + } else { + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "updateOldestPossibleOutput", "Oldest possible output updated from oldest Input : %zu --> %zu", + mOldestPossibleOutput.timeslice.value, result.timeslice.value); + } } mOldestPossibleOutput = result; From ad0592970b04e6e5f7b65212812b9f833fd7e76b Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 16 Apr 2024 12:31:08 +0200 Subject: [PATCH 0108/2997] DPL: Fix orderedCompletionPolicy getting stuck when oldestPossibleTimeslice message jumps by > 1 at once, and any but the last TF in the jump range is missing --- Framework/Core/src/CommonServices.cxx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index d7f6538310cb4..028ed6e8e6806 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -676,17 +676,21 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() } } decongestion.lastTimeslice = oldestPossibleOutput.timeslice.value; - if (decongestion.orderedCompletionPolicyActive) { - + }, + TimesliceId{oldestPossibleTimeslice}, -1); + if (decongestion.orderedCompletionPolicyActive) { + AsyncQueueHelpers::post( + queue, decongestion.oldestPossibleTimesliceTask, [ref = services, oldestPossibleOutput, &decongestion, &proxy, &spec, device, ×liceIndex](size_t id) { + O2_SIGNPOST_ID_GENERATE(cid, async_queue); int64_t oldNextTimeslice = decongestion.nextTimeslice; decongestion.nextTimeslice = std::max(decongestion.nextTimeslice, (int64_t)oldestPossibleOutput.timeslice.value); if (oldNextTimeslice != decongestion.nextTimeslice) { O2_SIGNPOST_EVENT_EMIT_ERROR(async_queue, cid, "oldest_possible_timeslice", "Some Lifetime::Timeframe data got dropped starting at %" PRIi64, oldNextTimeslice); timesliceIndex.rescan(); } - } }, - TimesliceId{oldestPossibleTimeslice}, -1); }, + TimesliceId{oldestPossibleOutput.timeslice.value}, -1); + } }, .kind = ServiceKind::Serial}; } From 65e6d3625eda060a93db74d99498199940925379 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 16 Apr 2024 14:49:54 +0200 Subject: [PATCH 0109/2997] decrease verbosity of RootTreeReader --- Framework/Utils/include/DPLUtils/RootTreeReader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Utils/include/DPLUtils/RootTreeReader.h b/Framework/Utils/include/DPLUtils/RootTreeReader.h index 109d79f9fad78..bc743d713b520 100644 --- a/Framework/Utils/include/DPLUtils/RootTreeReader.h +++ b/Framework/Utils/include/DPLUtils/RootTreeReader.h @@ -321,7 +321,7 @@ class GenericRootTreeReader mSizeBranch->GetEntry(entry); auto* buffer = reinterpret_cast(data); if (buffer->size() == datasize) { - LOG(info) << "branch " << mName << ": publishing binary chunk of " << datasize << " bytes(s)"; + LOG(debug) << "branch " << mName << ": publishing binary chunk of " << datasize << " bytes(s)"; snapshot(mKey, std::move(*buffer)); } else { LOG(error) << "branch " << mName << ": inconsitent size of binary chunk " From 9d0acdcdb0376d656135a13bbcc99799d3593305 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 16 Apr 2024 18:45:58 +0200 Subject: [PATCH 0110/2997] Check for ITS clusters ordering --- Detectors/Align/src/AlignableDetectorITS.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Detectors/Align/src/AlignableDetectorITS.cxx b/Detectors/Align/src/AlignableDetectorITS.cxx index 67a68fe50dc26..7387ae4620bf3 100644 --- a/Detectors/Align/src/AlignableDetectorITS.cxx +++ b/Detectors/Align/src/AlignableDetectorITS.cxx @@ -156,8 +156,19 @@ int AlignableDetectorITS::processPoints(GIndex gid, int npntCut, bool inv) const auto& clusIdx = recoData->getITSTracksClusterRefs(); // do we want to apply some cuts? int clEntry = track.getFirstClusterEntry(); + int preevSensID = -1; + bool errReported = false; for (int icl = track.getNumberOfClusters(); icl--;) { // clusters refs are stored from outer to inner layers, we loop in inner -> outer direction const auto& clus = mITSClustersArray[(clusIDs[npoints] = clusIdx[clEntry + icl])]; + if (clus.getSensorID() < preevSensID && !errReported) { // clusters are ordered from outer to inner layer, hence decreasing sensorID + std::string errstr{}; + for (int ie = track.getNumberOfClusters(); ie--;) { + errstr += fmt::format(" {}", mITSClustersArray[clusIdx[clEntry + ie]].getSensorID()); + } + LOGP(error, "wrong ITS clusters order? : chips {}", errstr); + errReported = true; + } + preevSensID = clus.getSensorID(); if (clus.getBits()) { // overlapping clusters will have bit set if (clus.isBitSet(EdgeFlags::Biased)) { continue; From 5153ad719b3066483f63ace8747177148480e899 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 16 Apr 2024 18:48:12 +0200 Subject: [PATCH 0111/2997] Fix TPC clusters extraction for millepede --- Detectors/Align/src/AlignableDetectorTPC.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Align/src/AlignableDetectorTPC.cxx b/Detectors/Align/src/AlignableDetectorTPC.cxx index 86bad838f8273..ca4cbbaaffcdd 100644 --- a/Detectors/Align/src/AlignableDetectorTPC.cxx +++ b/Detectors/Align/src/AlignableDetectorTPC.cxx @@ -134,7 +134,7 @@ int AlignableDetectorTPC::processPoints(GIndex gid, int npntCut, bool inv) break; } } - mController->getTPCCorrMaps()->Transform(sector, row, cl->getPad(), cl->getTime(), xTmp, yTmp, zTmp, tOffset); + mController->getTPCCorrMaps()->Transform(sector, row, clTmp->getPad(), clTmp->getTime(), xTmp, yTmp, zTmp, tOffset); if (algConf.discardSectorEdgeDepth > 0) { if (std::abs(yTmp) + algConf.discardSectorEdgeDepth > xTmp * TAN10) { if (i + direction != stop) { From 94eca0d384abb764422bd773557fe2f40c1a6139 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Mon, 18 Dec 2023 14:30:38 +0100 Subject: [PATCH 0112/2997] [EMCAL-788] EMCAL cell selection, on-the-fly calibration - Seletion of good EMCAL cells - Require FEE readout (HG and LG cells) - Time cut around trigger peak - Min. cell energy - On-the-fly recalibration - Optional - Only in synchronous workflow --- EventVisualisation/Workflow/CMakeLists.txt | 3 ++ .../include/EveWorkflow/EveWorkflowHelper.h | 9 +++- .../include/EveWorkflow/O2DPLDisplay.h | 11 ++++- .../Workflow/src/EveWorkflowHelper.cxx | 27 +++++++++++- .../Workflow/src/O2DPLDisplay.cxx | 43 ++++++++++++++++++- 5 files changed, 88 insertions(+), 5 deletions(-) diff --git a/EventVisualisation/Workflow/CMakeLists.txt b/EventVisualisation/Workflow/CMakeLists.txt index 469d502a2a06c..76266dca57a28 100644 --- a/EventVisualisation/Workflow/CMakeLists.txt +++ b/EventVisualisation/Workflow/CMakeLists.txt @@ -40,6 +40,8 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2" O2::TOFBase O2::PHOSBase O2::EMCALBase + O2::EMCALCalib + O2::EMCALWorkflow O2::MIDBase O2::TOFWorkflowIO O2::TPCReconstruction @@ -74,6 +76,7 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2" O2::TOFBase O2::PHOSBase O2::EMCALBase + O2::EMCALCalib O2::MIDBase O2::TOFWorkflowIO O2::TPCReconstruction diff --git a/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h b/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h index 83b448568bbff..f8bef1100227f 100644 --- a/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h +++ b/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h @@ -55,7 +55,8 @@ class Geometry; namespace o2::emcal { class Geometry; -} +class CellRecalibrator; +} // namespace o2::emcal namespace o2::event_visualisation { @@ -207,6 +208,9 @@ class EveWorkflowHelper const o2::globaltracking::RecoContainer* mRecoCont = nullptr; const o2::globaltracking::RecoContainer* getRecoContainer() const { return mRecoCont; } void setRecoContainer(const o2::globaltracking::RecoContainer* rc) { mRecoCont = rc; } + void setEMCALCellRecalibrator(o2::emcal::CellRecalibrator* calibrator) { mEMCALCalib = calibrator; } + void setMaxEMCALCellTime(float maxtime) { mEMCALMaxCellTime = maxtime; } + void setMinEMCALCellEnergy(float minenergy) { mEMCALMinCellEnergy = minenergy; } TracksSet mTrackSet; o2::event_visualisation::VisualisationEvent mEvent; std::unordered_map mTotalDataTypes; @@ -221,11 +225,14 @@ class EveWorkflowHelper o2::its::GeometryTGeo* mITSGeom; o2::phos::Geometry* mPHOSGeom; o2::emcal::Geometry* mEMCALGeom; + o2::emcal::CellRecalibrator* mEMCALCalib = nullptr; float mMUS2TPCTimeBins = 5.0098627; float mITSROFrameLengthMUS = 0; ///< ITS RO frame in mus float mMFTROFrameLengthMUS = 0; ///< MFT RO frame in mus float mTPCBin2MUS = 0; + float mEMCALMaxCellTime = 100.; ///< EMCAL cell time cut (in ns) + float mEMCALMinCellEnergy = 0.3; ///< EMCAL cell energy cut (in GeV) static int BCDiffErrCount; const o2::vertexing::PVertexerParams* mPVParams = nullptr; }; diff --git a/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h b/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h index b3431951ed41f..2ea64cab1ff3c 100644 --- a/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h +++ b/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h @@ -19,6 +19,8 @@ #include "ReconstructionDataFormats/GlobalTrackID.h" #include "DataFormatsGlobalTracking/RecoContainer.h" #include "DetectorsBase/GRPGeomHelper.h" +#include "EMCALCalib/CellRecalibrator.h" +#include "EMCALWorkflow/CalibLoader.h" #include "EveWorkflow/DetectorData.h" #include "Framework/Task.h" #include @@ -54,12 +56,13 @@ class O2DPLDisplaySpec : public o2::framework::Task o2::dataformats::GlobalTrackID::mask_t clMask, std::shared_ptr dataRequest, std::shared_ptr gr, + std::shared_ptr emcCalibLoader, const std::string& jsonPath, const std::string& ext, std::chrono::milliseconds timeInterval, int numberOfFiles, int numberOfTracks, bool eveHostNameMatch, int minITSTracks, int minTracks, bool filterITSROF, bool filterTime, const EveWorkflowHelper::Bracket& timeBracket, bool removeTPCEta, - const EveWorkflowHelper::Bracket& etaBracket, bool trackSorting, int onlyNthEvent, bool primaryVertex, int maxPrimaryVertices, bool primaryVertexTriggers, float primaryVertexMinZ, float primaryVertexMaxZ, float primaryVertexMinX, float primaryVertexMaxX, float primaryVertexMinY, float primaryVertexMaxY) - : mDisableWrite(disableWrite), mUseMC(useMC), mTrkMask(trkMask), mClMask(clMask), mDataRequest(dataRequest), mGGCCDBRequest(gr), mJsonPath(jsonPath), mExt(ext), mTimeInterval(timeInterval), mNumberOfFiles(numberOfFiles), mNumberOfTracks(numberOfTracks), mEveHostNameMatch(eveHostNameMatch), mMinITSTracks(minITSTracks), mMinTracks(minTracks), mFilterITSROF(filterITSROF), mFilterTime(filterTime), mTimeBracket(timeBracket), mRemoveTPCEta(removeTPCEta), mEtaBracket(etaBracket), mTrackSorting(trackSorting), mOnlyNthEvent(onlyNthEvent), mPrimaryVertexMode(primaryVertex), mMaxPrimaryVertices(maxPrimaryVertices), mPrimaryVertexTriggers(primaryVertexTriggers), mPrimaryVertexMinZ(primaryVertexMinZ), mPrimaryVertexMaxZ(primaryVertexMaxZ), mPrimaryVertexMinX(primaryVertexMinX), mPrimaryVertexMaxX(primaryVertexMaxX), mPrimaryVertexMinY(primaryVertexMinY), mPrimaryVertexMaxY(primaryVertexMaxY), mRunType(o2::parameters::GRPECS::NONE) + const EveWorkflowHelper::Bracket& etaBracket, bool trackSorting, int onlyNthEvent, bool primaryVertex, int maxPrimaryVertices, bool primaryVertexTriggers, float primaryVertexMinZ, float primaryVertexMaxZ, float primaryVertexMinX, float primaryVertexMaxX, float primaryVertexMinY, float primaryVertexMaxY, float maxEMCALCellTime, float minEMCALCellEnergy) + : mDisableWrite(disableWrite), mUseMC(useMC), mTrkMask(trkMask), mClMask(clMask), mDataRequest(dataRequest), mGGCCDBRequest(gr), mEMCALCalibLoader(emcCalibLoader), mJsonPath(jsonPath), mExt(ext), mTimeInterval(timeInterval), mNumberOfFiles(numberOfFiles), mNumberOfTracks(numberOfTracks), mEveHostNameMatch(eveHostNameMatch), mMinITSTracks(minITSTracks), mMinTracks(minTracks), mFilterITSROF(filterITSROF), mFilterTime(filterTime), mTimeBracket(timeBracket), mRemoveTPCEta(removeTPCEta), mEtaBracket(etaBracket), mTrackSorting(trackSorting), mOnlyNthEvent(onlyNthEvent), mPrimaryVertexMode(primaryVertex), mMaxPrimaryVertices(maxPrimaryVertices), mPrimaryVertexTriggers(primaryVertexTriggers), mPrimaryVertexMinZ(primaryVertexMinZ), mPrimaryVertexMaxZ(primaryVertexMaxZ), mPrimaryVertexMinX(primaryVertexMinX), mPrimaryVertexMaxX(primaryVertexMaxX), mPrimaryVertexMinY(primaryVertexMinY), mPrimaryVertexMaxY(primaryVertexMaxY), mEMCALMaxCellTime(maxEMCALCellTime), mEMCALMinCellEnergy(minEMCALCellEnergy), mRunType(o2::parameters::GRPECS::NONE) { this->mTimeStamp = std::chrono::high_resolution_clock::now() - timeInterval; // first run meets condition @@ -99,6 +102,8 @@ class O2DPLDisplaySpec : public o2::framework::Task float mPrimaryVertexMaxX; // maximum x position of the primary vertex float mPrimaryVertexMinY; // minimum y position of the primary vertex float mPrimaryVertexMaxY; // maximum y position of the primary vertex + float mEMCALMaxCellTime; // max abs EMCAL cell time (in ns) + float mEMCALMinCellEnergy; // min EMCAL cell energy (in GeV) int mEventCounter = 0; std::chrono::time_point mTimeStamp; @@ -108,6 +113,8 @@ class O2DPLDisplaySpec : public o2::framework::Task o2::parameters::GRPECS::RunType mRunType; std::shared_ptr mDataRequest; std::shared_ptr mGGCCDBRequest; + std::shared_ptr mEMCALCalibLoader; + std::unique_ptr mEMCALCalibrator; }; } // namespace o2::event_visualisation diff --git a/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx b/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx index 3b1b40df9aba3..51a8a44634142 100644 --- a/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx +++ b/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx @@ -35,6 +35,7 @@ #include "ITSBase/GeometryTGeo.h" #include "PHOSBase/Geometry.h" #include "EMCALBase/Geometry.h" +#include "EMCALCalib/CellRecalibrator.h" #include #include #include @@ -644,6 +645,30 @@ void EveWorkflowHelper::drawEMC(GID gid) const gsl::span cellsForTrigger(cells.data() + trig.getFirstEntry(), trig.getNumberOfObjects()); for (const auto& cell : cellsForTrigger) { + if (!(cell.getType() == o2::emcal::ChannelType_t::HIGH_GAIN || cell.getType() == o2::emcal::ChannelType_t::LOW_GAIN)) { + // Select FEE cells (excluding LEDMON or TRU cells) + continue; + } + auto cellTime = cell.getTimeStamp(); + auto cellEnergy = cell.getEnergy(); + if (mEMCALCalib) { + // try to recalibrate cell in case calibration is available (bad channel removal, energy calibration, time calibration) + auto calibCell = mEMCALCalib->getCalibratedCell(cell); + if (!calibCell) { + // cell was rejected by bad channel calib + continue; + } + cellTime = calibCell->getTimeStamp(); + cellEnergy = calibCell->getEnergy(); + } + if (std::abs(cellTime) > mEMCALMaxCellTime) { + // cell rejected by time cut (pileup or noise) + continue; + } + if (cellEnergy < mEMCALMinCellEnergy) { + // cell rejected by energy cut (rejection of soft cells) + continue; + } const auto id = cell.getTower(); // Point3D with x,y,z coordinates of cell with absId inside SM const auto relPosCell = this->mEMCALGeom->RelPosCellInSModule(id); @@ -657,7 +682,7 @@ void EveWorkflowHelper::drawEMC(GID gid) TVector3 vPos(gPos.data()); auto vCalo = mEvent.addCalo({.time = static_cast(time), - .energy = cell.getEnergy(), + .energy = cellEnergy, .phi = (float)vPos.Phi(), .eta = (float)vPos.Eta(), .PID = 0, diff --git a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx index 3885bbce959a8..068390f0e22ea 100644 --- a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx +++ b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx @@ -26,6 +26,8 @@ #include "TOFBase/Geo.h" #include "TPCFastTransform.h" #include "TRDBase/Geometry.h" +#include "EMCALCalib/CellRecalibrator.h" +#include "EMCALWorkflow/CalibLoader.h" #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "ReconstructionDataFormats/GlobalTrackID.h" #include "ReconstructionDataFormats/PrimaryVertex.h" @@ -76,6 +78,9 @@ void customize(std::vector& workflowOptions) {"primary-vertex-mode", VariantType::Bool, false, {"produce jsons with individual primary vertices, not total time frame data"}}, {"max-primary-vertices", VariantType::Int, 5, {"maximum number of primary vertices to draw per time frame"}}, {"primary-vertex-triggers", VariantType::Bool, false, {"instead of drawing vertices with tracks (and maybe calorimeter triggers), draw vertices with calorimeter triggers (and maybe tracks)"}}, + {"no-calibrate-emcal", VariantType::Bool, false, {"Do not apply on-the-fly EMCAL calibration"}}, + {"emcal-max-celltime", VariantType::Float, 100.f, {"Max. EMCAL cell time (in ns)"}}, + {"emcal-min-cellenergy", VariantType::Float, 0.3f, {"Min. EMCAL cell energy (in GeV)"}}, {"primary-vertex-min-z", VariantType::Float, -o2::constants::math::VeryBig, {"minimum z position for primary vertex"}}, {"primary-vertex-max-z", VariantType::Float, o2::constants::math::VeryBig, {"maximum z position for primary vertex"}}, {"primary-vertex-min-x", VariantType::Float, -o2::constants::math::VeryBig, {"minimum x position for primary vertex"}}, @@ -93,6 +98,9 @@ void O2DPLDisplaySpec::init(InitContext& ic) LOGF(info, "------------------------ O2DPLDisplay::init version ", o2_eve_version, " ------------------------------------"); mData.mConfig.configProcessing.runMC = mUseMC; o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); + if (mEMCALCalibLoader) { + mEMCALCalibrator = std::make_unique(); + } } void O2DPLDisplaySpec::run(ProcessingContext& pc) @@ -114,6 +122,19 @@ void O2DPLDisplaySpec::run(ProcessingContext& pc) o2::globaltracking::RecoContainer recoCont; recoCont.collectData(pc, *mDataRequest); updateTimeDependentParams(pc); // Make sure that this is called after the RecoContainer collect data, since some condition objects are fetched there + if (mEMCALCalibLoader) { + mEMCALCalibLoader->checkUpdates(pc); + if (mEMCALCalibLoader->hasUpdateBadChannelMap()) { + mEMCALCalibrator->setBadChannelMap(mEMCALCalibLoader->getBadChannelMap()); + } + if (mEMCALCalibLoader->hasUpdateTimeCalib()) { + mEMCALCalibrator->setTimeCalibration(mEMCALCalibLoader->getTimeCalibration()); + } + if (mEMCALCalibLoader->hasUpdateGainCalib()) { + mEMCALCalibrator->setGainCalibration(mEMCALCalibLoader->getGainCalibration()); + } + } + EveWorkflowHelper::FilterSet enabledFilters; enabledFilters.set(EveWorkflowHelper::Filter::ITSROF, this->mFilterITSROF); @@ -122,6 +143,12 @@ void O2DPLDisplaySpec::run(ProcessingContext& pc) enabledFilters.set(EveWorkflowHelper::Filter::TotalNTracks, this->mNumberOfTracks != -1); EveWorkflowHelper helper(enabledFilters, this->mNumberOfTracks, this->mTimeBracket, this->mEtaBracket, this->mPrimaryVertexMode); helper.setRecoContainer(&recoCont); + if (mEMCALCalibrator) { + helper.setEMCALCellRecalibrator(mEMCALCalibrator.get()); + } + helper.setMaxEMCALCellTime(mEMCALMaxCellTime); + helper.setMinEMCALCellEnergy(mEMCALMinCellEnergy); + helper.setITSROFs(); helper.selectTracks(&(mData.mConfig.configCalib), mClMask, mTrkMask, mTrkMask); helper.selectTowers(); @@ -240,6 +267,9 @@ void O2DPLDisplaySpec::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) if (o2::base::GRPGeomHelper::instance().finaliseCCDB(matcher, obj)) { return; } + if (mEMCALCalibLoader && mEMCALCalibLoader->finalizeCCDB(matcher, obj)) { + return; + } if (matcher == ConcreteDataMatcher("ITS", "CLUSDICT", 0)) { LOGF(info, "ITS cluster dictionary updated"); mData.setITSDict((const o2::itsmft::TopologyDictionary*)obj); @@ -372,6 +402,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) auto primaryVertexMaxX = cfgc.options().get("primary-vertex-max-x"); auto primaryVertexMinY = cfgc.options().get("primary-vertex-min-y"); auto primaryVertexMaxY = cfgc.options().get("primary-vertex-max-y"); + auto maxEMCALCellTime = cfgc.options().get("emcal-max-celltime"); + auto minEMCALCellEnergy = cfgc.options().get("emcal-min-cellenergy"); if (numberOfTracks == -1) { tracksSorting = false; // do not sort if all tracks are allowed @@ -385,11 +417,20 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) dataRequest->inputs, true); // query only once all objects except mag.field + std::shared_ptr emcalCalibLoader; + if (!cfgc.options().get("no-calibrate-emcal")) { + emcalCalibLoader = std::make_shared(); + emcalCalibLoader->enableTimeCalib(true); + emcalCalibLoader->enableBadChannelMap(true); + emcalCalibLoader->enableGainCalib(true); + emcalCalibLoader->defineInputSpecs(dataRequest->inputs); + } + specs.emplace_back(DataProcessorSpec{ "o2-eve-export", dataRequest->inputs, {}, - AlgorithmSpec{adaptFromTask(disableWrite, useMC, srcTrk, srcCl, dataRequest, ggRequest, jsonFolder, ext, timeInterval, numberOfFiles, numberOfTracks, eveHostNameMatch, minITSTracks, minTracks, filterITSROF, filterTime, timeBracket, removeTPCEta, etaBracket, tracksSorting, onlyNthEvent, primaryVertexMode, maxPrimaryVertices, primaryVertexTriggers, primaryVertexMinZ, primaryVertexMaxZ, primaryVertexMinX, primaryVertexMaxX, primaryVertexMinY, primaryVertexMaxY)}}); + AlgorithmSpec{adaptFromTask(disableWrite, useMC, srcTrk, srcCl, dataRequest, ggRequest, emcalCalibLoader, jsonFolder, ext, timeInterval, numberOfFiles, numberOfTracks, eveHostNameMatch, minITSTracks, minTracks, filterITSROF, filterTime, timeBracket, removeTPCEta, etaBracket, tracksSorting, onlyNthEvent, primaryVertexMode, maxPrimaryVertices, primaryVertexTriggers, primaryVertexMinZ, primaryVertexMaxZ, primaryVertexMinX, primaryVertexMaxX, primaryVertexMinY, primaryVertexMaxY, maxEMCALCellTime, minEMCALCellEnergy)}}); // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(cfgc, specs); From 2c4262969eb53799fa90f42f23627caf90e6ea32 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 17 Apr 2024 11:03:11 +0200 Subject: [PATCH 0113/2997] Option to manage ROF length reporting Option --rof-lenght-error-freq will set the interval between successive error reports (if any) about the wrong ROF length. No reporting is done if negative or 0 (to be used in calibration runs). Default interval is 60s. --- .../workflow/include/ITSMFTWorkflow/STFDecoderSpec.h | 1 + .../ITSMFT/common/workflow/src/STFDecoderSpec.cxx | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h index f521341d120bb..d0b64f2a678ac 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/STFDecoderSpec.h @@ -82,6 +82,7 @@ class STFDecoder : public Task int mDumpOnError = 0; int mNThreads = 1; int mVerbosity = 0; + long mROFErrRepIntervalMS = 0; size_t mTFCounter = 0; size_t mEstNDig = 0; size_t mEstNClus = 0; diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index 3976f8277aa59..92ad20129c36f 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -81,6 +81,8 @@ void STFDecoder::init(InitContext& ic) mApplyNoiseMap = !ic.options().get("ignore-noise-map"); mUseClusterDictionary = !ic.options().get("ignore-cluster-dictionary"); try { + float fr = ic.options().get("rof-lenght-error-freq"); + mROFErrRepIntervalMS = fr <= 0. ? -1 : long(fr * 1e3); mNThreads = std::max(1, ic.options().get("nthreads")); mDecoder->setNThreads(mNThreads); mUnmutExtraLanes = ic.options().get("unmute-extra-lanes"); @@ -160,6 +162,7 @@ void STFDecoder::run(ProcessingContext& pc) mDecoder->setDecodeNextAuto(false); o2::InteractionRecord lastIR{}, firstIR{0, pc.services().get().firstTForbit}; int nTriggersProcessed = mDecoder->getNROFsProcessed(); + static long lastErrReportTS = 0; while (mDecoder->decodeNextTrigger() >= 0) { if ((!lastIR.isDummy() && lastIR >= mDecoder->getInteractionRecord()) || firstIR > mDecoder->getInteractionRecord()) { const int MaxErrLog = 2; @@ -186,8 +189,12 @@ void STFDecoder::run(ProcessingContext& pc) const auto& alpParams = o2::itsmft::DPLAlpideParam::Instance(); int expectedTFSize = static_cast(o2::constants::lhc::LHCMaxBunches * o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF() / alpParams.roFrameLengthInBC); // 3564*32 / ROF Length in BS = number of ROFs per TF - if ((expectedTFSize != nTriggersProcessed) && mTFCounter > 1 && nTriggersProcessed > 0) { - LOG(error) << "Inconsistent number of ROF per TF. From parameters: " << expectedTFSize << " from readout: " << nTriggersProcessed; + if ((expectedTFSize != nTriggersProcessed) && mROFErrRepIntervalMS > 0 && mTFCounter > 1 && nTriggersProcessed > 0) { + long currTS = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); + if (currTS - lastErrReportTS > mROFErrRepIntervalMS) { + LOGP(error, "Inconsistent number of ROF per TF. From parameters: {} from readout: {} (muting further reporting for {} ms)", expectedTFSize, nTriggersProcessed, mROFErrRepIntervalMS); + lastErrReportTS = currTS; + } } if (mDoClusters && mClusterer->getMaxROFDepthToSquash()) { // Digits squashing require to run on a batch of digits and uses a digit reader, cannot (?) run with decoder @@ -413,6 +420,7 @@ DataProcessorSpec getSTFDecoderSpec(const STFDecoderInp& inp) {"allow-empty-rofs", VariantType::Bool, false, {"record ROFs w/o any hit"}}, {"ignore-noise-map", VariantType::Bool, false, {"do not mask pixels flagged in the noise map"}}, {"accept-rof-rampup-data", VariantType::Bool, false, {"do not discard data during ROF ramp up"}}, + {"rof-lenght-error-freq", VariantType::Float, 60.f, {"do not report ROF lenght error more frequently than this value, disable if negative"}}, {"ignore-cluster-dictionary", VariantType::Bool, false, {"do not use cluster dictionary, always store explicit patterns"}}}}; } From 3fe2068607a0ce6084291b0465266e3e62d391aa Mon Sep 17 00:00:00 2001 From: Ole Schmidt Date: Wed, 17 Apr 2024 17:23:53 +0200 Subject: [PATCH 0114/2997] EMCAL increase check interval for bad channel and time calibrations (#13032) --- .../calibration/testWorkflow/EMCALChannelCalibratorSpec.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Detectors/EMCAL/calibration/testWorkflow/EMCALChannelCalibratorSpec.h b/Detectors/EMCAL/calibration/testWorkflow/EMCALChannelCalibratorSpec.h index e643baf3eb5c8..8c801a993625f 100644 --- a/Detectors/EMCAL/calibration/testWorkflow/EMCALChannelCalibratorSpec.h +++ b/Detectors/EMCAL/calibration/testWorkflow/EMCALChannelCalibratorSpec.h @@ -426,6 +426,10 @@ class EMCALChannelCalibDevice : public o2::framework::Task if (mTimeCalibrator) { LOG(info) << "Configuring time calibrator"; mTimeCalibrator->setSlotLength(EMCALCalibParams::Instance().slotLength_tc); + if (EMCALCalibParams::Instance().slotLength_tc == 0) { + // for infinite slot length do not check if there is enough statistics after every TF + mTimeCalibrator->setCheckIntervalInfiniteSlot(1e5); + } if (EMCALCalibParams::Instance().UpdateAtEndOfRunOnly_tc) { mTimeCalibrator->setUpdateAtTheEndOfRunOnly(); } @@ -437,6 +441,10 @@ class EMCALChannelCalibDevice : public o2::framework::Task if (mBadChannelCalibrator) { LOG(info) << "Configuring bad channel calibrator"; mBadChannelCalibrator->setSlotLength(EMCALCalibParams::Instance().slotLength_bc); + if (EMCALCalibParams::Instance().slotLength_bc == 0) { + // for infinite slot length do not check if there is enough statistics after every TF + mBadChannelCalibrator->setCheckIntervalInfiniteSlot(1e5); + } if (EMCALCalibParams::Instance().UpdateAtEndOfRunOnly_bc) { mBadChannelCalibrator->setUpdateAtTheEndOfRunOnly(); } From 5a496c967c60894ec31b3e0c81e5f7d202a9f715 Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Wed, 17 Apr 2024 17:58:23 +0200 Subject: [PATCH 0115/2997] [EMCAL-565] Add cut on pre and post trigger pile-up (#13018) - The EMCal QC observed a few runs with cells, which have a significant contribution of pre-trigger pile-up. These come from FECs that loose the correct timeing signal during a run and then fire too early or too late, resulting in a second peak - A new cut is introduced that calculates the fraction of pre trigger (-500 - -25ns before the main time peak) and post trigger (25 - 500ns) after the main timing peak - The distribution of this post and pre-trigger pile-up fraction is then used to calculate the mean and sigma. - The cut is chosen quite loose (defined in the CalibParams) in order to only capture the extreme cases --- .../include/CommonUtils/BoostHistogramUtils.h | 23 +++++++++ .../EMCALCalibration/EMCALCalibExtractor.h | 49 +++++++++++++++---- .../EMCALCalibration/EMCALCalibParams.h | 2 + 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/Common/Utils/include/CommonUtils/BoostHistogramUtils.h b/Common/Utils/include/CommonUtils/BoostHistogramUtils.h index 85ff950aa2717..9b61bc839ddec 100644 --- a/Common/Utils/include/CommonUtils/BoostHistogramUtils.h +++ b/Common/Utils/include/CommonUtils/BoostHistogramUtils.h @@ -714,6 +714,29 @@ auto ReduceBoostHistoFastSliceByValue(boost::histogram::histogram& hist return ReduceBoostHistoFastSlice(hist2d, binXLow, binXHigh, binYLow, binYHigh, includeOverflowUnderflow); } +/// \brief Function to integrate 1d boost histogram in specified range +/// \param hist 1d boost histogram +/// \param min lower integration range +/// \param max upper integration range +/// \return sum of bin contents in specified range +template +double getIntegralBoostHist(boost::histogram::histogram& hist, double min, double max) +{ + // find bins for min and max values + std::array axisLimitsIndex = {hist.axis(0).index(min), hist.axis(0).index(max)}; + // over/underflow bin have to be protected + for (auto& bin : axisLimitsIndex) { + if (bin < 0) { + bin = 0; + } else if (bin >= hist.axis(0).size()) { + bin = hist.axis(0).size() - 1; + } + } + // Reduce histogram to desired range + auto slicedHist = ReduceBoostHistoFastSlice1D(hist, axisLimitsIndex[0], axisLimitsIndex[1], false); + return boost::histogram::algorithm::sum(slicedHist); +} + } // namespace utils } // end namespace o2 diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h index 6ba8479534a8b..1571f29670368 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h @@ -58,8 +58,12 @@ class EMCALCalibExtractor }; struct BadChannelCalibTimeInfo { - std::array sigmaCell; // sigma value of time distribution for single cells - double goodCellWindow; // cut value for good cells + std::array sigmaCell; // sigma value of time distribution for single cells + double goodCellWindow; // cut value for good cells + std::array fracHitsPreTrigg; // fraction of hits before the main time peak (pre-trigger pile-up) + double goodCellWindowFracHitsPreTrigg; // cut value for good cells for pre-trigger pile-up + std::array fracHitsPostTrigg; // fraction of hits after the main time peak (post-trigger pile-up) + double goodCellWindowFracHitsPostTrigg; // cut value for good cells for post-trigger pile-up }; public: @@ -191,6 +195,12 @@ class EMCALCalibExtractor if (calibrationTimeInfo.sigmaCell[cellID] > calibrationTimeInfo.goodCellWindow) { LOG(debug) << "Cell " << cellID << " is flagged due to time distribution"; failed = true; + } else if (calibrationTimeInfo.fracHitsPreTrigg[cellID] > calibrationTimeInfo.goodCellWindowFracHitsPreTrigg) { + LOG(debug) << "Cell " << cellID << " is flagged due to time distribution (pre-trigger)"; + failed = true; + } else if (calibrationTimeInfo.fracHitsPostTrigg[cellID] > calibrationTimeInfo.goodCellWindowFracHitsPostTrigg) { + LOG(debug) << "Cell " << cellID << " is flagged due to time distribution (post-trigger)"; + failed = true; } } } @@ -321,7 +331,7 @@ class EMCALCalibExtractor template BadChannelCalibTimeInfo buildTimeMeanAndSigma(const boost::histogram::histogram& histCellTime) { - std::array meanSigma; + BadChannelCalibTimeInfo timeInfo; for (int i = 0; i < mNcells; ++i) { // calculate sigma per cell const int indexLow = histCellTime.axis(1).index(i); @@ -333,24 +343,45 @@ class EMCALCalibExtractor maxElementIndex = 0; } float maxElementCenter = 0.5 * (boostHistCellSlice.axis(0).bin(maxElementIndex).upper() + boostHistCellSlice.axis(0).bin(maxElementIndex).lower()); - meanSigma[i] = std::sqrt(o2::utils::getVarianceBoost1D(boostHistCellSlice, -999999, maxElementCenter - 50, maxElementCenter + 50)); + timeInfo.sigmaCell[i] = std::sqrt(o2::utils::getVarianceBoost1D(boostHistCellSlice, -999999, maxElementCenter - 50, maxElementCenter + 50)); + + // get number of hits within mean+-25ns (trigger bunch), from -500ns to -25ns before trigger bunch (pre-trigger), and for 25ns to 500ns (post-trigger) + double sumTrigg = o2::utils::getIntegralBoostHist(boostHistCellSlice, maxElementCenter - 25, maxElementCenter + 25); + double sumPreTrigg = o2::utils::getIntegralBoostHist(boostHistCellSlice, maxElementCenter - 500, maxElementCenter - 25); + double sumPostTrigg = o2::utils::getIntegralBoostHist(boostHistCellSlice, maxElementCenter + 25, maxElementCenter + 500); + + // calculate fraction of hits of post and pre-trigger to main trigger bunch + timeInfo.fracHitsPreTrigg[i] = sumTrigg == 0 ? 0. : sumPreTrigg / sumTrigg; + timeInfo.fracHitsPostTrigg[i] = sumTrigg == 0 ? 0. : sumPostTrigg / sumTrigg; } // get the mean sigma and the std. deviation of the sigma distribution // those will be the values we cut on double avMean = 0, avSigma = 0; TRobustEstimator robustEstimator; - robustEstimator.EvaluateUni(meanSigma.size(), meanSigma.data(), avMean, avSigma, 0.5 * meanSigma.size()); + robustEstimator.EvaluateUni(timeInfo.sigmaCell.size(), timeInfo.sigmaCell.data(), avMean, avSigma, 0.5 * timeInfo.sigmaCell.size()); // protection for the following case: For low statistics cases, it can happen that more than half of the cells is in one bin // in that case the sigma will be close to zero. In that case, we take 95% of the data to calculate the truncated mean if (std::abs(avMean) < 0.001 && std::abs(avSigma) < 0.001) { - robustEstimator.EvaluateUni(meanSigma.size(), meanSigma.data(), avMean, avSigma, 0.95 * meanSigma.size()); + robustEstimator.EvaluateUni(timeInfo.sigmaCell.size(), timeInfo.sigmaCell.data(), avMean, avSigma, 0.95 * timeInfo.sigmaCell.size()); } - - BadChannelCalibTimeInfo timeInfo; - timeInfo.sigmaCell = meanSigma; + // timeInfo.sigmaCell = meanSigma; timeInfo.goodCellWindow = avMean + (avSigma * o2::emcal::EMCALCalibParams::Instance().sigmaTime_bc); // only upper limit needed + double avMeanPre = 0, avSigmaPre = 0; + robustEstimator.EvaluateUni(timeInfo.fracHitsPreTrigg.size(), timeInfo.fracHitsPreTrigg.data(), avMeanPre, avSigmaPre, 0.5 * timeInfo.fracHitsPreTrigg.size()); + if (std::abs(avMeanPre) < 0.001 && std::abs(avSigmaPre) < 0.001) { + robustEstimator.EvaluateUni(timeInfo.fracHitsPreTrigg.size(), timeInfo.fracHitsPreTrigg.data(), avMeanPre, avSigmaPre, 0.95 * timeInfo.fracHitsPreTrigg.size()); + } + timeInfo.goodCellWindowFracHitsPreTrigg = avMeanPre + (avSigmaPre * o2::emcal::EMCALCalibParams::Instance().sigmaTimePreTrigg_bc); // only upper limit needed + + double avMeanPost = 0, avSigmaPost = 0; + robustEstimator.EvaluateUni(timeInfo.fracHitsPostTrigg.size(), timeInfo.fracHitsPostTrigg.data(), avMeanPost, avSigmaPost, 0.5 * timeInfo.fracHitsPostTrigg.size()); + if (std::abs(avMeanPost) < 0.001 && std::abs(avSigmaPost) < 0.001) { + robustEstimator.EvaluateUni(timeInfo.fracHitsPostTrigg.size(), timeInfo.fracHitsPostTrigg.data(), avMeanPost, avSigmaPost, 0.95 * timeInfo.fracHitsPostTrigg.size()); + } + timeInfo.goodCellWindowFracHitsPostTrigg = avMeanPost + (avSigmaPost * o2::emcal::EMCALCalibParams::Instance().sigmaTimePostTrigg_bc); // only upper limit needed + return timeInfo; } diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h index 0e9e6a4614f18..5f40443bf233c 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h @@ -43,6 +43,8 @@ struct EMCALCalibParams : public o2::conf::ConfigurableParamHelper Date: Wed, 17 Apr 2024 19:43:13 +0200 Subject: [PATCH 0116/2997] [EMCAL-565] Fix axis for time histogram in bad channel calibration (#13039) - min and max values were swapped. This was not an issue for the calibration itself but when converting from boost to root histograms Co-authored-by: jokonig --- .../calibration/include/EMCALCalibration/EMCALChannelData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALChannelData.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALChannelData.h index e8f7716601f06..0919c157c6610 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALChannelData.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALChannelData.h @@ -73,7 +73,7 @@ class EMCALChannelData mHistoTime.resize(mNThreads); for (size_t i = 0; i < mNThreads; ++i) { mHisto[i] = boost::histogram::make_histogram(boost::histogram::axis::regular<>(mNBins, 0., mRange), boost::histogram::axis::regular<>(NCELLS, -0.5, NCELLS - 0.5)); - mHistoTime[i] = boost::histogram::make_histogram(boost::histogram::axis::regular<>(mNBinsTime, mRangeTimeHigh, mRangeTimeLow), boost::histogram::axis::regular<>(NCELLS, -0.5, NCELLS - 0.5)); + mHistoTime[i] = boost::histogram::make_histogram(boost::histogram::axis::regular<>(mNBinsTime, mRangeTimeLow, mRangeTimeHigh), boost::histogram::axis::regular<>(NCELLS, -0.5, NCELLS - 0.5)); mVecNEntriesInHisto[i] = 0; } } From 5fa35b2110c34107a1db3dc5584e4d8674b26c8c Mon Sep 17 00:00:00 2001 From: pillot Date: Wed, 17 Apr 2024 22:01:26 +0200 Subject: [PATCH 0117/2997] new options to add channels from DE Ids and HV/LV DCS aliases (#13034) --- Detectors/MUON/MCH/Conditions/README.md | 7 +- .../MCH/Conditions/src/bad-channels-ccdb.cxx | 119 ++++++++++++------ 2 files changed, 85 insertions(+), 41 deletions(-) diff --git a/Detectors/MUON/MCH/Conditions/README.md b/Detectors/MUON/MCH/Conditions/README.md index d2475900d4d31..dcea47d201867 100644 --- a/Detectors/MUON/MCH/Conditions/README.md +++ b/Detectors/MUON/MCH/Conditions/README.md @@ -21,7 +21,7 @@ The BadChannel and RejectList objects can be uploaded, e.g. for debug purposes, ```shell $ o2-mch-bad-channels-ccdb --help -This program dump MCH bad channels CCDB object +This program get/set MCH bad channels CCDB object Usage: -h [ --help ] produce help message -c [ --ccdb ] arg (=http://localhost:6464) @@ -37,6 +37,9 @@ Usage: -q [ --query ] dump bad channel object from CCDB -v [ --verbose ] verbose output -s [ --solar ] arg solar ids to reject + -d [ --ds ] arg dual sampas indices to reject + -e [ --de ] arg DE ids to reject + -a [ --alias ] arg DCS alias (HV or LV) to reject ``` @@ -44,5 +47,5 @@ For instance, to create a debug RejectList object which declares solar number 32 ```shell $ o2-mch-bad-channels-ccdb -p -s 32 -t RejectList --starttimestamp 1667260801000 --endtimestamp 1672531199000 -storing default MCH bad channels (valid from 1667260801000to 1672531199000) to MCH/Calib/RejectList +storing default MCH bad channels (valid from 1667260801000 to 1672531199000) to MCH/Calib/RejectList ``` diff --git a/Detectors/MUON/MCH/Conditions/src/bad-channels-ccdb.cxx b/Detectors/MUON/MCH/Conditions/src/bad-channels-ccdb.cxx index e3d2ca9c3e7de..db1cb53f51c5a 100644 --- a/Detectors/MUON/MCH/Conditions/src/bad-channels-ccdb.cxx +++ b/Detectors/MUON/MCH/Conditions/src/bad-channels-ccdb.cxx @@ -17,9 +17,12 @@ #include #include #include "DataFormatsMCH/DsChannelId.h" -#include "MCHRawElecMap/Mapper.h" -#include "MCHMappingInterface/Segmentation.h" +#include "MCHConditions/DCSAliases.h" +#include "MCHConstants/DetectionElements.h" #include "MCHGlobalMapping/DsIndex.h" +#include "MCHGlobalMapping/Mapper.h" +#include "MCHMappingInterface/Segmentation.h" +#include "MCHRawElecMap/Mapper.h" namespace po = boost::program_options; @@ -46,50 +49,81 @@ void queryBadChannels(const std::string ccdbUrl, } } -void uploadBadChannels(const std::string ccdbUrl, - const std::string badChannelType, - uint64_t startTimestamp, - uint64_t endTimestamp, - std::vector solarsToReject, - std::vector dsToReject, - bool makeDefault) +void rejectDS(const o2::mch::raw::DsDetId& dsDetId, BadChannelsVector& bv) { - BadChannelsVector bv; - - auto det2elec = o2::mch::raw::createDet2ElecMapper(); + static auto det2elec = o2::mch::raw::createDet2ElecMapper(); + const auto& seg = o2::mch::mapping::segmentation(dsDetId.deId()); + auto dsElecId = det2elec(dsDetId); + seg.forEachPadInDualSampa(dsDetId.dsId(), [&](int pad) { + uint8_t channel = seg.padDualSampaChannel(pad); + const auto c = o2::mch::DsChannelId(dsElecId->solarId(), dsElecId->elinkId(), channel); + bv.emplace_back(c); + }); +} - for (auto solar : solarsToReject) { +void rejectSolars(const std::vector solarIds, BadChannelsVector& bv) +{ + for (auto solar : solarIds) { auto ds = o2::mch::raw::getDualSampas(solar); for (const auto& dsDetId : ds) { - o2::mch::mapping::Segmentation seg(dsDetId.deId()); - for (uint8_t channel = 0; channel < 64; channel++) { - auto dsElecId = det2elec(dsDetId); - auto padId = seg.findPadByFEE(dsDetId.dsId(), channel); - if (seg.isValid(padId)) { - const auto c = o2::mch::DsChannelId(solar, dsElecId->elinkId(), channel); - bv.emplace_back(c); - } - } + rejectDS(dsDetId, bv); } } +} - for (auto ds : dsToReject) { +void rejectDSs(const std::vector dsIdxs, BadChannelsVector& bv) +{ + for (auto ds : dsIdxs) { if (ds >= o2::mch::NumberOfDualSampas) { - std::cout << "Error: invalid DS index" << std::endl; + std::cout << "Error: invalid DS index " << ds << std::endl; continue; } o2::mch::raw::DsDetId dsDetId = o2::mch::getDsDetId(ds); - o2::mch::mapping::Segmentation seg(dsDetId.deId()); - for (uint8_t channel = 0; channel < 64; channel++) { - auto dsElecId = det2elec(dsDetId); - auto padId = seg.findPadByFEE(dsDetId.dsId(), channel); - if (seg.isValid(padId)) { - const auto c = o2::mch::DsChannelId(dsElecId->solarId(), dsElecId->elinkId(), channel); - bv.emplace_back(c); - } + rejectDS(dsDetId, bv); + } +} + +void rejectHVLVs(const std::vector dcsAliases, BadChannelsVector& bv) +{ + for (auto alias : dcsAliases) { + if (!o2::mch::dcs::isValid(alias)) { + std::cout << "Error: invalid alias " << alias << std::endl; + continue; + } + for (auto ds : o2::mch::dcs::aliasToDsIndices(alias)) { + o2::mch::raw::DsDetId dsDetId = o2::mch::getDsDetId(ds); + rejectDS(dsDetId, bv); } } +} + +void rejectDEs(const std::vector deIds, BadChannelsVector& bv) +{ + static auto det2elec = o2::mch::raw::createDet2ElecMapper(); + for (auto de : deIds) { + if (!o2::mch::constants::isValidDetElemId(de)) { + std::cout << "Error: invalid DE ID " << de << std::endl; + continue; + } + const auto& seg = o2::mch::mapping::segmentation(de); + seg.forEachPad([&](int pad) { + auto ds = seg.padDualSampaId(pad); + o2::mch::raw::DsDetId dsDetId(de, ds); + auto dsElecId = det2elec(dsDetId); + uint8_t channel = seg.padDualSampaChannel(pad); + const auto c = o2::mch::DsChannelId(dsElecId->solarId(), dsElecId->elinkId(), channel); + bv.emplace_back(c); + }); + } +} +void uploadBadChannels(const std::string ccdbUrl, + const std::string badChannelType, + uint64_t startTimestamp, + uint64_t endTimestamp, + const BadChannelsVector& bv, + bool makeDefault) +{ o2::ccdb::CcdbApi api; api.init(ccdbUrl); std::map md; @@ -139,7 +173,9 @@ int main(int argc, char** argv) ("query,q",po::bool_switch(&query),"dump bad channel object from CCDB") ("verbose,v",po::bool_switch(&verbose),"verbose output") ("solar,s",po::value>()->multitoken(),"solar ids to reject") - ("dsToReject,d", po::value>()->multitoken(), "dual sampas indices to reject") + ("ds,d", po::value>()->multitoken(), "dual sampas indices to reject") + ("de,e", po::value>()->multitoken(), "DE ids to reject") + ("alias,a", po::value>()->multitoken(), "DCS alias (HV or LV) to reject") ; // clang-format on @@ -171,16 +207,21 @@ int main(int argc, char** argv) } if (put) { - std::vector solarsToReject; - std::vector dsToReject; + BadChannelsVector bv; if (vm.count("solar")) { - solarsToReject = vm["solar"].as>(); + rejectSolars(vm["solar"].as>(), bv); + } + if (vm.count("ds")) { + rejectDSs(vm["ds"].as>(), bv); + } + if (vm.count("de")) { + rejectDEs(vm["de"].as>(), bv); } - if (vm.count("dsToReject")) { - dsToReject = vm["dsToReject"].as>(); + if (vm.count("alias")) { + rejectHVLVs(vm["alias"].as>(), bv); } - uploadBadChannels(ccdbUrl, badChannelType, startTimestamp, endTimestamp, solarsToReject, dsToReject, uploadDefault); + uploadBadChannels(ccdbUrl, badChannelType, startTimestamp, endTimestamp, bv, uploadDefault); } return 0; } From be4f97ac0faad7b47cbea5d85b70d1bdbfb19615 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 17 Apr 2024 17:21:45 +0200 Subject: [PATCH 0118/2997] o2-sim: Ability to focus/select a particular chunk to transport For debugging purposes, it is sometimes of advantage to skip to a particular event chunk for debugging. This commit allows to select an event-ID + event-Part for transport. Everything else will be skipped. This is useful in situations where we know of a bug in certain event and we'd would like to study this-and-only-this event (under same seeding). The event-part selection is done via env variable `O2SIM_RESTRICT_EVENTPART=event:part` --- run/O2SimDevice.h | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/run/O2SimDevice.h b/run/O2SimDevice.h index 1d1b769bcb5fd..07f7e9f82e249 100644 --- a/run/O2SimDevice.h +++ b/run/O2SimDevice.h @@ -205,6 +205,28 @@ class O2SimDevice final : public fair::mq::Device reproducibleSim = false; } + // Mainly for debugging reasons, we allow to transport + // a specific event + eventpart. This allows to reproduce and debug bugs faster, once + // we know in which precise chunk they occur. The expected format for the environment variable + // is "eventnum:partid". + auto eventselection = getenv("O2SIM_RESTRICT_EVENTPART"); + int focus_on_event = -1; + int focus_on_part = -1; + if (eventselection) { + auto splitString = [](const std::string& str) { + std::pair parts; + size_t pos = str.find(':'); + if (pos != std::string::npos) { + parts.first = str.substr(0, pos); + parts.second = str.substr(pos + 1); + } + return parts; + }; + auto p = splitString(eventselection); + focus_on_event = std::atoi(p.first.c_str()); + focus_on_part = std::atoi(p.second.c_str()); + } + fair::mq::MessagePtr request(requestchannel.NewSimpleMessage(PrimaryChunkRequest{workerID, -1, counter++})); // <-- don't need content; channel means -> give primaries fair::mq::Parts reply; @@ -252,14 +274,22 @@ class O2SimDevice final : public fair::mq::Device } if (goon) { - mVMCApp->setPrimaries(chunk->mParticles); auto info = chunk->mSubEventInfo; - mVMCApp->setSubEventInfo(&info); - LOG(info) << workerStr() << " Processing " << chunk->mParticles.size() << " primary particles " << "for event " << info.eventID << "/" << info.maxEvents << " " << "part " << info.part << "/" << info.nparts; + + if (eventselection == nullptr || (focus_on_event == info.eventID && focus_on_part == info.part)) { + mVMCApp->setPrimaries(chunk->mParticles); + } else { + // nothing to transport here + mVMCApp->setPrimaries(std::vector{}); + LOG(info) << workerStr() << " This chunk will be skipped"; + } + + mVMCApp->setSubEventInfo(&info); + if (reproducibleSim) { LOG(info) << workerStr() << " Setting seed for this sub-event to " << chunk->mSubEventInfo.seed; gRandom->SetSeed(chunk->mSubEventInfo.seed); From 9f26ea19b2c3bb58c6cdb3925a30f897fa2daada Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 17 Apr 2024 14:01:07 +0200 Subject: [PATCH 0119/2997] FST: default seed should be 0 to indicate random --- prodtests/full_system_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index f1c40f4194143..dd2d71f76c6c0 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -50,7 +50,7 @@ GPUMEMSIZE=${GPUMEMSIZE:-6000000000} # Size of GPU memory to use in case ENABBLE NTIMEFRAMES=${NTIMEFRAMES:-1} # Number of time frames to process TFDELAY=${TFDELAY:-100} # Delay in seconds between publishing time frames [[ -z ${NOMCLABELS+x} ]] && NOMCLABELS="--disable-mc" -O2SIMSEED=${O2SIMSEED:--1} +O2SIMSEED=${O2SIMSEED:-0} SPLITTRDDIGI=${SPLITTRDDIGI:-1} DIGITDOWNSCALINGTRD=${DIGITDOWNSCALINGTRD:-1000} NHBPERTF=${NHBPERTF:-128} From 4a639b3497d30bced962aed1ed9e6b9657847dd5 Mon Sep 17 00:00:00 2001 From: gvolpe Date: Mon, 15 Apr 2024 18:23:41 +0200 Subject: [PATCH 0120/2997] fix missing fitting of HV in HMPIDDCSProcessor --- Detectors/HMPID/calibration/src/HMPIDDCSProcessor.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/HMPID/calibration/src/HMPIDDCSProcessor.cxx b/Detectors/HMPID/calibration/src/HMPIDDCSProcessor.cxx index 7b3a88bf27385..02852a3213b30 100644 --- a/Detectors/HMPID/calibration/src/HMPIDDCSProcessor.cxx +++ b/Detectors/HMPID/calibration/src/HMPIDDCSProcessor.cxx @@ -708,6 +708,7 @@ std::unique_ptr HMPIDDCSProcessor::finalizeHv(int iCh, int iSec) } else { (pHvTF).reset(new TF1(Form("HV%i%i", iCh, iSec), "[0]+x*[1]", hvFirstTime, hvLastTime)); + pGrHV->Fit(Form("HV%i%i", iCh, iSec), "Q"); // ef added } } else { LOGP(warn, "No entries in High Voltage for HV{}{}", iCh, iSec); From 0b719d9e1c708dd2b69bc8902b35055a2f42c987 Mon Sep 17 00:00:00 2001 From: gvolpe79 <39517882+gvolpe79@users.noreply.github.com> Date: Thu, 18 Apr 2024 12:59:26 +0200 Subject: [PATCH 0121/2997] Simdigitizer (#13015) * Fixing sim digitizer * Updating busy time --- .../include/HMPIDSimulation/HMPIDDigitizer.h | 4 +- .../src/HMPIDDigitizerSpec.cxx | 49 +++++++++---------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/Detectors/HMPID/simulation/include/HMPIDSimulation/HMPIDDigitizer.h b/Detectors/HMPID/simulation/include/HMPIDSimulation/HMPIDDigitizer.h index 9d843feda64bc..b01935f4cac5d 100644 --- a/Detectors/HMPID/simulation/include/HMPIDSimulation/HMPIDDigitizer.h +++ b/Detectors/HMPID/simulation/include/HMPIDSimulation/HMPIDDigitizer.h @@ -59,7 +59,7 @@ class HMPIDDigitizer } } } - + // void setOrbit(double timeNS) {mOrbit = } uint32_t getOrbit() { return mOrbit; }; uint16_t getBc() { return mBc; }; @@ -99,7 +99,7 @@ class HMPIDDigitizer std::vector mDigits; // internal store for digits constexpr static double TRACKHOLDTIME = 1200; // defines the window for pile-up after a trigger received in nanoseconds - constexpr static double BUSYTIME = 22000; // the time for which no new trigger can be received in nanoseconds + constexpr static double BUSYTIME = 40000; // the time for which no new trigger can be received in nanoseconds std::map mIndexForPad; //! logarithmic mapping of pad to digit index diff --git a/Steer/DigitizerWorkflow/src/HMPIDDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/HMPIDDigitizerSpec.cxx index 0adb9eb0a90df..2e888166d16fc 100644 --- a/Steer/DigitizerWorkflow/src/HMPIDDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/HMPIDDigitizerSpec.cxx @@ -34,7 +34,6 @@ using namespace o2::framework; using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType; - namespace o2 { namespace hmpid @@ -102,34 +101,32 @@ class HMPIDDPLDigitizerTask : public o2::base::BaseDPLDigitizer // try to start new readout cycle by setting the trigger time auto triggeraccepted = mDigitizer.setTriggerTime(irecords[collID].getTimeNS()); if (triggeraccepted) { - flushDigitsAndLabels(); // flush previous readout cycle - } - auto withinactivetime = mDigitizer.setEventTime(irecords[collID].getTimeNS()); - if (withinactivetime) { - // for each collision, loop over the constituents event and source IDs - // (background signal merging is basically taking place here) - for (auto& part : eventParts[collID]) { - mDigitizer.setEventID(part.entryID); - mDigitizer.setSrcID(part.sourceID); - - // get the hits for this event and this source - std::vector hits; - context->retrieveHits(mSimChains, "HMPHit", part.sourceID, part.entryID, &hits); - LOG(info) << "For collision " << collID << " eventID " << part.entryID << " found HMP " << hits.size() << " hits "; - - mDigitizer.setLabelContainer(&mLabels); - mLabels.clear(); - mDigits.clear(); - - mDigitizer.process(hits, mDigits); + auto withinactivetime = mDigitizer.setEventTime(irecords[collID].getTimeNS()); + if (withinactivetime) { + // for each collision, loop over the constituents event and source IDs + // (background signal merging is basically taking place here) + for (auto& part : eventParts[collID]) { + mDigitizer.setEventID(part.entryID); + mDigitizer.setSrcID(part.sourceID); + + // get the hits for this event and this source + std::vector hits; + context->retrieveHits(mSimChains, "HMPHit", part.sourceID, part.entryID, &hits); + LOG(info) << "For collision " << collID << " eventID " << part.entryID << " found HMP " << hits.size() << " hits "; + + mDigitizer.setLabelContainer(&mLabels); + mLabels.clear(); + mDigits.clear(); + + mDigitizer.process(hits, mDigits); + } + + flushDigitsAndLabels(); // flush previous readout cycle + } else { + LOG(info) << "COLLISION " << collID << "FALLS WITHIN A DEAD TIME"; } - - } else { - LOG(info) << "COLLISION " << collID << "FALLS WITHIN A DEAD TIME"; } } - // final flushing step; getting everything not yet written out - flushDigitsAndLabels(); // send out to next stage pc.outputs().snapshot(Output{"HMP", "DIGITS", 0}, digitsAccum); From ebfd56d5ba1a1cf410b977188fcdbd73dcd7161a Mon Sep 17 00:00:00 2001 From: noferini <9963644+noferini@users.noreply.github.com> Date: Mon, 15 Apr 2024 17:01:02 +0200 Subject: [PATCH 0122/2997] add protection in TOF geo --- Detectors/TOF/base/src/Geo.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/TOF/base/src/Geo.cxx b/Detectors/TOF/base/src/Geo.cxx index e4ea7045d3884..655addbb3007e 100644 --- a/Detectors/TOF/base/src/Geo.cxx +++ b/Detectors/TOF/base/src/Geo.cxx @@ -755,12 +755,12 @@ Int_t Geo::fromPlateToStrip(Float_t* pos, Int_t iplate, Int_t isector) int firstStripToCheck = stripFound; int lastStripToCheck = stripFound; if (stripFound != 0) { - while (std::abs(pos[2] + getGeoDistances(isector, iplate, firstStripToCheck - 1)) < 10) { + while (firstStripToCheck != 0 && std::abs(pos[2] + getGeoDistances(isector, iplate, firstStripToCheck - 1)) < 10) { --firstStripToCheck; } } if (stripFound != nstrips - 1) { - while (std::abs(pos[2] + getGeoDistances(isector, iplate, lastStripToCheck + 1)) < 10) { + while (lastStripToCheck != nstrips - 1 && std::abs(pos[2] + getGeoDistances(isector, iplate, lastStripToCheck + 1)) < 10) { ++lastStripToCheck; } } From cab2644b37815e9a501773e5dbb8bacdd4af2d64 Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Thu, 18 Apr 2024 20:49:24 +0200 Subject: [PATCH 0123/2997] Set ITS PbPb params as O2DPG ones for async mode (#13044) --- prodtests/full-system-test/dpl-workflow.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 71de02d8ffa65..f67c5c01e81f1 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -140,6 +140,8 @@ if [[ $SYNCMODE == 1 ]]; then else if [[ $BEAMTYPE == "pp" ]]; then ITS_CONFIG_KEY+="ITSVertexerParam.phiCut=0.5;ITSVertexerParam.clusterContributorsCut=3;ITSVertexerParam.tanLambdaCut=0.2;" + elif [[ $BEAMTYPE == "PbPb" ]]; then + ITS_CONFIG_KEY+="ITSVertexerParam.lowMultBeamDistCut=0;ITSCATrackerParam.nROFsPerIterations=12;ITSCATrackerParam.perPrimaryVertexProcessing=true;" fi fi [[ $CTFINPUT == 1 ]] && GPU_CONFIG_KEY+="GPU_proc.tpcInputWithClusterRejection=1;" From 776e342721014422c49d63f1bb9a197f460d0b64 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Thu, 18 Apr 2024 22:35:44 +0100 Subject: [PATCH 0124/2997] ctpdev (#12974) * dev: suppressing error from rpcnts * dev:getConfigFromCCDB fix * clang * clang * dev: py macro for watching scalers * dev: keeping old function for compaitibility with QC * clang --- .../CTP/include/DataFormatsCTP/RunManager.h | 1 + DataFormats/Detectors/CTP/src/RunManager.cxx | 24 +++- Detectors/CTP/macro/TestConfig.C | 6 +- .../CTP/workflowScalers/py/watchProcess.py | 117 ++++++++++++++++++ .../workflowScalers/src/ctp-ccdb-orbit.cxx | 6 +- 5 files changed, 149 insertions(+), 5 deletions(-) create mode 100755 Detectors/CTP/workflowScalers/py/watchProcess.py diff --git a/DataFormats/Detectors/CTP/include/DataFormatsCTP/RunManager.h b/DataFormats/Detectors/CTP/include/DataFormatsCTP/RunManager.h index fcb5b8734b179..2df164474e4c4 100644 --- a/DataFormats/Detectors/CTP/include/DataFormatsCTP/RunManager.h +++ b/DataFormats/Detectors/CTP/include/DataFormatsCTP/RunManager.h @@ -39,6 +39,7 @@ class CTPRunManager void printActiveRuns() const; int saveRunScalersToCCDB(int i); int saveRunConfigToCCDB(CTPConfiguration* cfg, long timeStart); + static CTPConfiguration getConfigFromCCDB(long timestamp, std::string run, bool& ok); static CTPConfiguration getConfigFromCCDB(long timestamp, std::string run); CTPRunScalers getScalersFromCCDB(long timestamp, std::string, bool& ok); int loadScalerNames(); diff --git a/DataFormats/Detectors/CTP/src/RunManager.cxx b/DataFormats/Detectors/CTP/src/RunManager.cxx index 2916fba924883..a41af579d84e6 100644 --- a/DataFormats/Detectors/CTP/src/RunManager.cxx +++ b/DataFormats/Detectors/CTP/src/RunManager.cxx @@ -186,6 +186,14 @@ int CTPRunManager::processMessage(std::string& topic, const std::string& message LOG(info) << "EOX received"; mEOX = 1; } + static int nerror = 0; + if (topic == "rocnts") { + if (nerror < 1) { + LOG(warning) << "Skipping topic rocnts"; + nerror++; + } + return 0; + } // std::vector tokens; if (firstcounters.size() > 0) { @@ -198,7 +206,7 @@ int CTPRunManager::processMessage(std::string& topic, const std::string& message mNew = 0; LOG(warning) << "v2 scaler size"; } else { - LOG(error) << "Scalers size wrong:" << tokens.size() << " expected:" << CTPRunScalers::NCOUNTERS + 1 << " or " << CTPRunScalers::NCOUNTERSv2 + 1; + LOG(warning) << "Scalers size wrong:" << tokens.size() << " expected:" << CTPRunScalers::NCOUNTERS + 1 << " or " << CTPRunScalers::NCOUNTERSv2 + 1; return 1; } } @@ -298,7 +306,7 @@ int CTPRunManager::saveRunConfigToCCDB(CTPConfiguration* cfg, long timeStart) LOG(info) << "CTP config saved in ccdb:" << mCCDBHost << " run:" << cfg->getRunNumber() << " tmin:" << tmin << " tmax:" << tmax; return 0; } -CTPConfiguration CTPRunManager::getConfigFromCCDB(long timestamp, std::string run) +CTPConfiguration CTPRunManager::getConfigFromCCDB(long timestamp, std::string run, bool& ok) { auto& mgr = o2::ccdb::BasicCCDBManager::instance(); mgr.setURL(mCCDBHost); @@ -307,12 +315,24 @@ CTPConfiguration CTPRunManager::getConfigFromCCDB(long timestamp, std::string ru auto ctpconfigdb = mgr.getSpecific(CCDBPathCTPConfig, timestamp, metadata); if (ctpconfigdb == nullptr) { LOG(info) << "CTP config not in database, timestamp:" << timestamp; + ok = 0; } else { // ctpconfigdb->printStream(std::cout); LOG(info) << "CTP config found. Run:" << run; + ok = 1; } return *ctpconfigdb; } +CTPConfiguration CTPRunManager::getConfigFromCCDB(long timestamp, std::string run) +{ + bool ok; + auto ctpconfig = getConfigFromCCDB(timestamp, run, ok); + if (ok == 0) { + LOG(error) << "CTP config not in CCDB"; + return CTPConfiguration(); + } + return ctpconfig; +} CTPRunScalers CTPRunManager::getScalersFromCCDB(long timestamp, std::string run, bool& ok) { auto& mgr = o2::ccdb::BasicCCDBManager::instance(); diff --git a/Detectors/CTP/macro/TestConfig.C b/Detectors/CTP/macro/TestConfig.C index 0ff91c514ee93..48360996d3439 100644 --- a/Detectors/CTP/macro/TestConfig.C +++ b/Detectors/CTP/macro/TestConfig.C @@ -23,7 +23,11 @@ void TestConfig(bool test = 0) uint64_t timestamp = 1660196771632; std::string run = "523148"; o2::ctp::CTPRunManager::setCCDBHost("https://alice-ccdb.cern.ch"); - auto ctpcfg = o2::ctp::CTPRunManager::getConfigFromCCDB(timestamp, run); + bool ok; + auto ctpcfg = o2::ctp::CTPRunManager::getConfigFromCCDB(timestamp, run, ok); + if (ok == 0) { + std::cout << "Can not get config for run:" << run << std::endl; + } CTPConfiguration ctpconfig; ctpconfig.loadConfigurationRun3(ctpcfg.getConfigString()); // ctpconfig.printStream(std::cout); diff --git a/Detectors/CTP/workflowScalers/py/watchProcess.py b/Detectors/CTP/workflowScalers/py/watchProcess.py new file mode 100755 index 0000000000000..5ac9a98833706 --- /dev/null +++ b/Detectors/CTP/workflowScalers/py/watchProcess.py @@ -0,0 +1,117 @@ +#!/usr/bin/python3 +import requests,re +import os,sys,time,math +import time +from subprocess import Popen, PIPE +def send2(text = "ahoj"): + headers = { 'Content-Type':'application/json',} + data = { + 'text':text, + 'username':'alicetrg', + } + response = requests.post('https://mattermost.web.cern.ch/hooks/75949oimoinr9b47uhp8c1oomh',headers=headers,json=data) + print(response) +# +def send(): + """ + does not work always return can not parse data + """ + Hpar = '\\"Content-Type:application/json\\"' + texth = '\\"text\\"' + text = '\\"lalal\\"' + usernameh = '\\"username\\"' + username = '\\"alicetrg\\"' + dpar = '{}:{},{}:{}'.format(texth,text,usernameh,username) + dpar = "{"+dpar+"}" + dpar = '"'+dpar+'"' + #print(dpar) + cmd = 'curl -g -i -X POST -H {} -d {} https://mattermost.web.cern.ch/hooks/75949oimoinr9b47uhp8c1oomh'.format(Hpar,dpar) + #cmd = 'curl -i -X POST -H {} https://mattermost.web.cern.ch/hooks/75949oimoinr9b47uhp8c1oomh'.format(Hpar) + #cmd='curl -s -o /dev/null {} -F blob=@datafile.root {}/CTP/Calib/{}/{}/{}'.format(wpar, ccdb, actid, tval_s, tval_e) + process = Popen(cmd.split(), stdout = PIPE, stderr = PIPE) + stdo, stde = process.communicate() + print(cmd) + print(stdo) + print("====") + print(stde) +def getLog(service): + #cmd = "journalctl --no-hostname --user-unit "+service + cmd = 'journalctl --no-hostname --user-unit --since "1 day ago" '+service + print(cmd,cmd.split()) + process = Popen(cmd.split(), stdout = PIPE, stderr = PIPE) + stdo, stde= process.communicate() + stdo_str = stdo.decode("utf-8") + if stdo_str.find("No entries") != -1: + print("No entries for service:",service) + return None + #print(stdo) + return stdo_str +NMAX = 3 +def parseLog(log): + nsent = 0 + lines = log.split('\n') + print("# lines:",len(lines)) + print(lines[len(lines)-2]) + for line in lines: + if line.find("ERROR") != -1: + print(line) + if nsent < NMAX: + send2(line) + nsent += 1 + if line.find("ALARM") != -1: + print(line) + if nsent < NMAX: + send2(line) + nsent += 1 +# +nWarn = 0 +nAlarm = 0 +nError = 0 +def printNew(list,n,send = 0): + print(n,len(list)) + sendnow = 0 + if len(list) > n : + sendnow = 1 + for i in list[n:]: + print(i) + n = len(list) + if sendnow and send: + print("sending to mm:",line) + send2(line) + return n +def getLogFile(): + global nWarn, nAlarm,nError + nWarnList = [] + nAlarmList = [] + nErrorList = [] + MAX = 3 + file = "/home/rl/WORK/ctpproxy110424.log" + f = open(file,"r") + nsent = 0 + for line in f: + if line.find("ERROR") != -1: + print(line) + if line.find("ALARM") != -1: + #print(line) + nAlarmList.append(line) + #send2(line) + #nsent += 1 + if line.find("WARN") != -1: + #print(line) + #items = line.split("\]\[") + #items = re.split('\[|\]',line) + nWarnList.append(line) + #print(nWarn) + nWarn = printNew(nWarnList,nWarn) + nAlarm = printNew(nAlarmList,nAlarm,1) + f.close() +if __name__ =="__main__": + #send2("uj0"); + while 1: + now = time.localtime() + current_time = time.strftime("%H:%M:%S",now) + print("===> Time =", current_time) + log = getLogFile() + time.sleep(15) + + #parseLog(log) diff --git a/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx b/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx index b77f2d6c16e1a..13c06730d18ce 100644 --- a/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx +++ b/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx @@ -33,8 +33,10 @@ #include namespace bpo = boost::program_options; // -// get object from ccdb auto pp = ccdbMgr.getSpecific>("CTP/Calib/OrbitResetTest") -// std::cout << (*pp3)[0] << std::endl; +// get object from ccdb +// auto & cc = o2::ccdb::BasicCCDNManager::instance(); +// auto pp = ccdbMgr.getSpecific>("CTP/Calib/OrbitResetTest") +// std::cout << (*pp)[0] << std::endl; int main(int argc, char** argv) { const std::string testCCDB = "http://ccdb-test.cern.ch:8080"; From 9ef74a0edcb65c735fff3f1bfb80285fee6044be Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Fri, 19 Apr 2024 02:38:25 +0200 Subject: [PATCH 0125/2997] [EMCAL-565, EMCAL-566] Prevent saving/overwriting calib multiple times at EOR (#13045) - At the EOR the state of the calibration is saved in a root file, to be loaded in the next run - However, in the online case, several EOR signals reach the calibration after the initial EOR - This leads to the original root file being overwritten by another one, containing only a few (~1-20) events - Now, 2 checks are in place that should circumvent that the calibration files are overwritten: The variable mRunStopRequested was introduced in the CalibSpec which is set to true after the initial EOR signal, preventing further data processing A check on the minimum number of events for the calibration (minNEventsSaveSlot, configurable in the calibParams) that only allows saving the calibration file if a reasonable statistics is reached Co-authored-by: jokonig --- .../include/EMCALCalibration/EMCALCalibParams.h | 1 + .../EMCALCalibration/EMCALChannelCalibrator.h | 11 ++++++++--- .../testWorkflow/EMCALChannelCalibratorSpec.h | 15 ++++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h index 5f40443bf233c..2a13fb8ca569e 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h @@ -87,6 +87,7 @@ struct EMCALCalibParams : public o2::conf::ConfigurableParamHelper::finalizeSlot(o2::calibration // Extract results for the single slot DataInput* c = slot.getContainer(); LOG(info) << "Finalize slot " << slot.getTFStart() << " <= TF <= " << slot.getTFEnd(); + // check if slot contains a minimum amount of data + if (c->getNEvents() < EMCALCalibParams::Instance().minNEventsSaveSlot) { + LOG(info) << "Slot only contains " << c->getNEvents() << " events. Not saving this slot. " << EMCALCalibParams::Instance().minNEventsSaveSlot << " required"; + return; + } if constexpr (std::is_same::value) { if (c->getNEvents() < EMCALCalibParams::Instance().minNEvents_bc) { @@ -260,7 +265,7 @@ template bool EMCALChannelCalibrator::saveLastSlotData(TFile& fl) { LOG(info) << "EMC calib histos are saved in " << fl.GetName(); - // does this work? + // we only have 1 slot auto& cont = o2::calibration::TimeSlotCalibration::getSlots(); auto& slot = cont.at(0); DataInput* c = slot.getContainer(); @@ -279,7 +284,7 @@ bool EMCALChannelCalibrator::saveLastSlotData(TFile& fl) TH1I hGlobalProperties("hGlobalProperties", "hGlobalProperties", 3, -0.5, 2.5); hGlobalProperties.GetXaxis()->SetBinLabel(1, "Fill nr."); hGlobalProperties.GetXaxis()->SetBinLabel(2, "run type"); - hGlobalProperties.GetXaxis()->SetBinLabel(2, "ts in hours"); + hGlobalProperties.GetXaxis()->SetBinLabel(3, "ts in hours"); hGlobalProperties.SetBinContent(1, mFillNr); hGlobalProperties.SetBinContent(2, mRunType); hGlobalProperties.SetBinContent(3, timeNow); @@ -297,7 +302,7 @@ bool EMCALChannelCalibrator::saveLastSlotData(TFile& fl) TH1I hGlobalProperties("hGlobalProperties", "hGlobalProperties", 3, -0.5, 2.5); hGlobalProperties.GetXaxis()->SetBinLabel(1, "Fill nr."); hGlobalProperties.GetXaxis()->SetBinLabel(2, "run type"); - hGlobalProperties.GetXaxis()->SetBinLabel(2, "ts in hours"); + hGlobalProperties.GetXaxis()->SetBinLabel(3, "ts in hours"); hGlobalProperties.SetBinContent(1, mFillNr); hGlobalProperties.SetBinContent(2, mRunType); hGlobalProperties.SetBinContent(3, timeNow); diff --git a/Detectors/EMCAL/calibration/testWorkflow/EMCALChannelCalibratorSpec.h b/Detectors/EMCAL/calibration/testWorkflow/EMCALChannelCalibratorSpec.h index 8c801a993625f..2d6a9dc6c9d01 100644 --- a/Detectors/EMCAL/calibration/testWorkflow/EMCALChannelCalibratorSpec.h +++ b/Detectors/EMCAL/calibration/testWorkflow/EMCALChannelCalibratorSpec.h @@ -172,6 +172,14 @@ class EMCALChannelCalibDevice : public o2::framework::Task timeMeas[0] = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); } + const auto& tinfo = pc.services().get(); + if (tinfo.globalRunNumberChanged) { // new run is starting + mRunStopRequested = false; + } + if (mRunStopRequested) { + return; + } + o2::base::GRPGeomHelper::instance().checkUpdates(pc); if (mTimeCalibrator) { o2::base::TFIDInfoHelper::fillTFIDInfo(pc, mTimeCalibrator->getCurrentTFInfo()); @@ -314,7 +322,7 @@ class EMCALChannelCalibDevice : public o2::framework::Task if (pc.transitionState() == TransitionHandlingState::Requested) { LOG(debug) << "Run stop requested, finalizing"; - // mRunStopRequested = true; + mRunStopRequested = true; if (isBadChannelCalib) { mBadChannelCalibrator->setSaveAtEOR(true); mBadChannelCalibrator->checkSlotsToFinalize(o2::calibration::INFINITE_TF); @@ -337,6 +345,9 @@ class EMCALChannelCalibDevice : public o2::framework::Task void endOfStream(o2::framework::EndOfStreamContext& ec) final { + if (mRunStopRequested) { + return; + } if (isBadChannelCalib) { mBadChannelCalibrator->setSaveAtEOR(true); mBadChannelCalibrator->checkSlotsToFinalize(o2::calibration::INFINITE_TF); @@ -346,6 +357,7 @@ class EMCALChannelCalibDevice : public o2::framework::Task mTimeCalibrator->checkSlotsToFinalize(o2::calibration::INFINITE_TF); sendOutput(ec.outputs()); } + mRunStopRequested = true; } static const char* getCellBinding() { return "EMCCells"; } @@ -368,6 +380,7 @@ class EMCALChannelCalibDevice : public o2::framework::Task bool mRejectL0Triggers = true; ///! reject EMCal Gamma and Jet triggers in the online calibration bool mApplyGainCalib = true; ///! switch if gain calibration should be applied during filling of histograms or not bool mGainCalibFactorsInitialized = false; ///! Gain calibration init status + bool mRunStopRequested = false; ///< flag that the run has stopped std::array timeMeas; ///! Used for time measurement and holds the start and end time in the run function std::vector mSelectedClassMasks = {}; ///! EMCal minimum bias trigger bit. Only this bit will be used for calibration std::unique_ptr mDownsampler; From a60bdb7f112c050570da8dbad4c8a456393f2a15 Mon Sep 17 00:00:00 2001 From: czhang Date: Thu, 18 Apr 2024 23:02:53 +0200 Subject: [PATCH 0126/2997] Fix bug when reading input string for chamber fixing --- .../MUON/MCH/Align/src/AlignRecordSpec.cxx | 17 +++++++++-------- Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx | 17 +++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx b/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx index e31968ae3de8d..0a61d38a36b2a 100644 --- a/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx +++ b/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx @@ -9,6 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include +#include #include "MCHAlign/AlignRecordSpec.h" @@ -120,14 +121,14 @@ class AlignRecordTask mImproveCutChi2 = 2. * trackerParam.sigmaCutForImprovement * trackerParam.sigmaCutForImprovement; // Configuration for chamber fixing - auto chambers = ic.options().get("fix-chamber"); - for (int i = 0; i < chambers.length(); ++i) { - if (chambers[i] == ',') { - continue; - } - int chamber = chambers[i] - '0'; - LOG(info) << Form("%s%d", "Fixing chamber: ", chamber); - mAlign.FixChamber(chamber); + auto input_fixchambers = ic.options().get("fix-chamber"); + std::stringstream string_chambers(input_fixchambers); + string_chambers >> std::ws; + while (string_chambers.good()) { + string substr; + std::getline(string_chambers, substr, ','); + LOG(info) << Form("%s%d", "Fixing chamber: ", std::stoi(substr)); + mAlign.FixChamber(std::stoi(substr)); } // Init for output saving diff --git a/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx b/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx index 6a3ed06a6b403..948ac1bda9117 100644 --- a/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx +++ b/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -222,14 +223,14 @@ class AlignmentTask mImproveCutChi2 = 2. * trackerParam.sigmaCutForImprovement * trackerParam.sigmaCutForImprovement; // Fix chambers - auto chambers = ic.options().get("fix-chamber"); - for (int i = 0; i < chambers.length(); ++i) { - if (chambers[i] == ',') { - continue; - } - int chamber = chambers[i] - '0'; - LOG(info) << Form("%s%d", "Fixing chamber: ", chamber); - mAlign.FixChamber(chamber); + auto input_fixchambers = ic.options().get("fix-chamber"); + std::stringstream string_chambers(input_fixchambers); + string_chambers >> std::ws; + while (string_chambers.good()) { + string substr; + std::getline(string_chambers, substr, ','); + LOG(info) << Form("%s%d", "Fixing chamber: ", std::stoi(substr)); + mAlign.FixChamber(std::stoi(substr)); } doMatched = ic.options().get("matched"); From 1858e31b3c14fd6b9d41020990eb715461aa8e67 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 18 Apr 2024 12:21:50 +0200 Subject: [PATCH 0127/2997] GPU: Simplify TPC cluster error functions and remove unused parameters --- GPU/GPUTracking/Base/GPUParam.h | 2 +- GPU/GPUTracking/Base/GPUParam.inc | 16 +++++----------- .../GPUTPCCompressionTrackModel.cxx | 2 +- GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 2 +- GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx | 4 ++-- .../SliceTracker/GPUTPCGlobalTracking.cxx | 2 +- GPU/GPUTracking/SliceTracker/GPUTPCTracker.h | 18 +++++++++--------- .../SliceTracker/GPUTPCTrackletConstructor.cxx | 8 ++++---- 8 files changed, 24 insertions(+), 30 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUParam.h b/GPU/GPUTracking/Base/GPUParam.h index a8aed7111aa6b..8f0277a8a9ff3 100644 --- a/GPU/GPUTracking/Base/GPUParam.h +++ b/GPU/GPUTracking/Base/GPUParam.h @@ -98,7 +98,7 @@ struct GPUParam : public internal::GPUParam_t return 0.174533f + par.dAlpha * iSlice; } GPUd() float GetClusterErrorSeeding(int yz, int type, float zDiff, float angle2) const; - GPUd() void GetClusterErrorsSeeding2(char sector, int row, float z, float sinPhi, float DzDs, float time, float avgInvCharge, float invCharge, float& ErrY2, float& ErrZ2) const; + GPUd() void GetClusterErrorsSeeding2(char sector, int row, float z, float sinPhi, float DzDs, float time, float& ErrY2, float& ErrZ2) const; GPUd() float GetSystematicClusterErrorIFC2(float trackX, float trackY, float z, bool sideC) const; GPUd() float GetSystematicClusterErrorC122(float trackX, float trackY, char sector) const; diff --git a/GPU/GPUTracking/Base/GPUParam.inc b/GPU/GPUTracking/Base/GPUParam.inc index 886b4c82274f0..2c6538f09b4ee 100644 --- a/GPU/GPUTracking/Base/GPUParam.inc +++ b/GPU/GPUTracking/Base/GPUParam.inc @@ -47,9 +47,9 @@ GPUdi() void MEM_LG(GPUParam)::Global2Slice(int iSlice, float X, float Y, float #ifdef GPUCA_TPC_GEOMETRY_O2 MEM_CLASS_PRE() -GPUdi() void MEM_LG(GPUParam)::GetClusterErrorsSeeding2(char sector, int iRow, float z, float sinPhi, float DzDs, float time, float avgInvCharge, float invCharge, float& ErrY2, float& ErrZ2) const +GPUdi() void MEM_LG(GPUParam)::GetClusterErrorsSeeding2(char sector, int iRow, float z, float sinPhi, float DzDs, float time, float& ErrY2, float& ErrZ2) const { - GetClusterErrors2(sector, iRow, z, sinPhi, DzDs, time, avgInvCharge, invCharge, ErrY2, ErrZ2); + GetClusterErrors2(sector, iRow, z, sinPhi, DzDs, time, 0.f, 0.f, ErrY2, ErrZ2); } MEM_CLASS_PRE() @@ -122,14 +122,11 @@ GPUdi() float MEM_LG(GPUParam)::GetClusterErrorSeeding(int yz, int type, float z } MEM_CLASS_PRE() -GPUdi() void MEM_LG(GPUParam)::GetClusterErrorsSeeding2(char sector, int iRow, float z, float sinPhi, float DzDs, float time, float avgInvCharge, float invCharge, float& ErrY2, float& ErrZ2) const +GPUdi() void MEM_LG(GPUParam)::GetClusterErrorsSeeding2(char sector, int iRow, float z, float sinPhi, float DzDs, float time, float& ErrY2, float& ErrZ2) const { int rowType = tpcGeometry.GetROC(iRow); z = CAMath::Abs(tpcGeometry.TPCLength() - CAMath::Abs(z)); - float s2 = sinPhi * sinPhi; - if (s2 > 0.95f * 0.95f) { - s2 = 0.95f * 0.95f; - } + const float s2 = CAMath::Min(sinPhi * sinPhi, 0.95f * 0.95f); float sec2 = 1.f / (1.f - s2); float angleY2 = s2 * sec2; // dy/dx float angleZ2 = DzDs * DzDs * sec2; // dz/dx @@ -174,10 +171,7 @@ GPUdi() void MEM_LG(GPUParam)::GetClusterErrors2(char sector, int iRow, float z, // Calibrated cluster error from OCDB for Y and Z const int rowType = tpcGeometry.GetROC(iRow); z = CAMath::Abs(tpcGeometry.TPCLength() - CAMath::Abs(z)); - float s2 = sinPhi * sinPhi; - if (s2 > 0.95f * 0.95f) { - s2 = 0.95f * 0.95f; - } + const float s2 = CAMath::Min(sinPhi * sinPhi, 0.95f * 0.95f); const float sec2 = 1.f / (1.f - s2); const float angleY2 = s2 * sec2; // dy/dx const float angleZ2 = DzDs * DzDs * sec2; // dz/dx diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx index 9ab00abe8500b..69b0d70f9ea88 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionTrackModel.cxx @@ -100,7 +100,7 @@ GPUd() int GPUTPCCompressionTrackModel::Filter(float y, float z, int iRow) { mTrk.ConstrainSinPhi(); float err2Y, err2Z; - GPUTPCTracker::GetErrors2Seeding(*mParam, iRow, mTrk, 0.f, err2Y, err2Z); + GPUTPCTracker::GetErrors2Seeding(*mParam, iRow, mTrk, -1.f, err2Y, err2Z); int retVal = !mTrk.Filter(y, z, err2Y, err2Z, GPUCA_MAX_SIN_PHI, false); // GPUInfo("Filtered with %f %f: y %f z %f qPt %f", y, z, mTrk.Y(), mTrk.Z(), mTrk.QPt()); return retVal; diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index 334b2f9f0b98e..2362213d52fb0 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -607,7 +607,7 @@ GPUd() void GPUTPCGMPropagator::GetErr2(float& GPUrestrict() err2Y, float& GPUre { #ifndef GPUCA_TPC_GEOMETRY_O2 if (seedingErrors) { - param.GetClusterErrorsSeeding2(sector, iRow, posZ, snp, tgl, time, avgCharge, charge, err2Y, err2Z); + param.GetClusterErrorsSeeding2(sector, iRow, posZ, snp, tgl, time, err2Y, err2Z); } else #endif { diff --git a/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx b/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx index b8ee68939b457..b6f2c72a209e0 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMSliceTrack.cxx @@ -130,7 +130,7 @@ GPUd() bool GPUTPCGMSliceTrack::FilterErrors(const GPUTPCGMMerger* merger, int i merger->Param().GetClusterErrors2(iSlice, 0, mParam.mZ, mParam.mSinPhi, mParam.mDzDs, -1.f, 0.f, 0.f, mParam.mC0, mParam.mC2); // TODO: provide correct time and row #ifndef GPUCA_TPC_GEOMETRY_O2 float C0a, C2a; - merger->Param().GetClusterErrorsSeeding2(iSlice, 0, mParam.mZ, mParam.mSinPhi, mParam.mDzDs, -1.f, 0.f, 0.f, C0a, C2a); + merger->Param().GetClusterErrorsSeeding2(iSlice, 0, mParam.mZ, mParam.mSinPhi, mParam.mDzDs, -1.f, C0a, C2a); if (C0a > mParam.mC0) { mParam.mC0 = C0a; } @@ -190,7 +190,7 @@ GPUd() bool GPUTPCGMSliceTrack::FilterErrors(const GPUTPCGMMerger* merger, int i merger->Param().GetClusterErrors2(iSlice, 0, mParam.mZ, mParam.mSinPhi, mParam.mDzDs, -1.f, 0.f, 0.f, err2Y, err2Z); // TODO: Provide correct time / row #ifndef GPUCA_TPC_GEOMETRY_O2 float C0a, C2a; - merger->Param().GetClusterErrorsSeeding2(iSlice, 0, mParam.mZ, mParam.mSinPhi, mParam.mDzDs, -1.f, 0.f, 0.f, C0a, C2a); + merger->Param().GetClusterErrorsSeeding2(iSlice, 0, mParam.mZ, mParam.mSinPhi, mParam.mDzDs, -1.f, C0a, C2a); if (C0a > err2Y) { err2Y = C0a; } diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx index 33e0bea7191a1..9ce30210b975a 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCGlobalTracking.cxx @@ -61,7 +61,7 @@ GPUd() int GPUTPCGlobalTracking::PerformGlobalTrackingRun(GPUTPCTracker& tracker } while (CAMath::Abs(tParam.Y()) > tracker.Row(rowIndex).MaxY()); float err2Y, err2Z; - tracker.GetErrors2Seeding(rowIndex, tParam.Z(), tParam.SinPhi(), tParam.DzDs(), -1.f, 0.f, 0.f, err2Y, err2Z); // TODO: Use correct time for multiplicity part of error estimation + tracker.GetErrors2Seeding(rowIndex, tParam.Z(), tParam.SinPhi(), tParam.DzDs(), -1.f, err2Y, err2Z); // TODO: Use correct time for multiplicity part of error estimation if (tParam.GetCov(0) < err2Y) { tParam.SetCov(0, err2Y); } diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.h b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.h index c02ae069e0115..9e35800d13517 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTracker.h +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTracker.h @@ -108,22 +108,22 @@ class GPUTPCTracker : public GPUProcessor } MEM_CLASS_PRE2() - GPUdi() static void GetErrors2Seeding(const MEM_CONSTANT(GPUParam) & param, char sector, int iRow, const MEM_LG2(GPUTPCTrackParam) & t, float time, float avgCharge, float charge, float& ErrY2, float& ErrZ2) + GPUdi() static void GetErrors2Seeding(const MEM_CONSTANT(GPUParam) & param, char sector, int iRow, const MEM_LG2(GPUTPCTrackParam) & t, float time, float& ErrY2, float& ErrZ2) { - // param.GetClusterErrors2(sector, iRow, param.GetContinuousTracking() != 0. ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), time, avgCharge, ErrY2, ErrZ2); - param.GetClusterErrorsSeeding2(sector, iRow, param.par.continuousTracking != 0.f ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), time, avgCharge, charge, ErrY2, ErrZ2); + // param.GetClusterErrors2(sector, iRow, param.GetContinuousTracking() != 0. ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), time, 0.f, 0.f, ErrY2, ErrZ2); + param.GetClusterErrorsSeeding2(sector, iRow, param.par.continuousTracking != 0.f ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), time, ErrY2, ErrZ2); } MEM_CLASS_PRE2() - GPUdi() void GetErrors2Seeding(int iRow, const MEM_LG2(GPUTPCTrackParam) & t, float time, float avgCharge, float charge, float& ErrY2, float& ErrZ2) const + GPUdi() void GetErrors2Seeding(int iRow, const MEM_LG2(GPUTPCTrackParam) & t, float time, float& ErrY2, float& ErrZ2) const { - // Param().GetClusterErrors2(mISlice, iRow, Param().GetContinuousTracking() != 0. ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), time, avgCharge, ErrY2, ErrZ2); - Param().GetClusterErrorsSeeding2(mISlice, iRow, Param().par.continuousTracking != 0.f ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), time, avgCharge, charge, ErrY2, ErrZ2); + // Param().GetClusterErrors2(mISlice, iRow, Param().GetContinuousTracking() != 0. ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), time, 0.f, 0.f, ErrY2, ErrZ2); + Param().GetClusterErrorsSeeding2(mISlice, iRow, Param().par.continuousTracking != 0.f ? 125.f : t.Z(), t.SinPhi(), t.DzDs(), time, ErrY2, ErrZ2); } - GPUdi() void GetErrors2Seeding(int iRow, float z, float sinPhi, float DzDs, float time, float avgCharge, float charge, float& ErrY2, float& ErrZ2) const + GPUdi() void GetErrors2Seeding(int iRow, float z, float sinPhi, float DzDs, float time, float& ErrY2, float& ErrZ2) const { - // Param().GetClusterErrors2(mISlice, iRow, Param().GetContinuousTracking() != 0. ? 125.f : z, sinPhi, DzDs, time, avgCharge, ErrY2, ErrZ2); - Param().GetClusterErrorsSeeding2(mISlice, iRow, Param().par.continuousTracking != 0.f ? 125.f : z, sinPhi, DzDs, time, avgCharge, charge, ErrY2, ErrZ2); + // Param().GetClusterErrors2(mISlice, iRow, Param().GetContinuousTracking() != 0. ? 125.f : z, sinPhi, DzDs, time, 0.f, 0.f, ErrY2, ErrZ2); + Param().GetClusterErrorsSeeding2(mISlice, iRow, Param().par.continuousTracking != 0.f ? 125.f : z, sinPhi, DzDs, time, ErrY2, ErrZ2); } void SetupCommonMemory(); diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx index b66e0341b91aa..79623c6f66c32 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletConstructor.cxx @@ -183,7 +183,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int tParam.SetSignCosPhi(dx); tParam.SetDzDs(dz * ri); float err2Y, err2Z; - tracker.GetErrors2Seeding(iRow, tParam, -1.f, 0.f, 0.f, err2Y, err2Z); // Use correct time + tracker.GetErrors2Seeding(iRow, tParam, -1.f, err2Y, err2Z); // Use correct time tParam.SetCov(0, err2Y); tParam.SetCov(2, err2Z); } @@ -202,7 +202,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int } CADEBUG(printf("%5s hits %3d: FIT PROP ROW %3d X %8.3f -", "", r.mNHits, iRow, tParam.X()); for (int i = 0; i < 5; i++) { printf(" %8.3f", tParam.Par()[i]); } printf(" -"); for (int i = 0; i < 15; i++) { printf(" %8.3f", tParam.Cov()[i]); } printf("\n")); float err2Y, err2Z; - tracker.GetErrors2Seeding(iRow, tParam.GetZ(), sinPhi, tParam.GetDzDs(), -1.f, 0.f, 0.f, err2Y, err2Z); // TODO: Use correct time + tracker.GetErrors2Seeding(iRow, tParam.GetZ(), sinPhi, tParam.GetDzDs(), -1.f, err2Y, err2Z); // TODO: Use correct time if (r.mNHits >= 10) { const float sErr2 = tracker.Param().GetSystematicClusterErrorIFC2(x, tParam.GetY(), tParam.GetZ(), tracker.ISlice() >= 18); @@ -310,7 +310,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::UpdateTracklet(int /*nBlocks*/, int calink best = CALINK_INVAL; float err2Y, err2Z; - tracker.GetErrors2Seeding(iRow, *((MEM_LG2(GPUTPCTrackParam)*)&tParam), -1.f, 0.f, 0.f, err2Y, err2Z); // TODO: Use correct time + tracker.GetErrors2Seeding(iRow, *((MEM_LG2(GPUTPCTrackParam)*)&tParam), -1.f, err2Y, err2Z); // TODO: Use correct time if (r.mNHits >= 10) { const float sErr2 = tracker.Param().GetSystematicClusterErrorIFC2(x, tParam.GetY(), tParam.GetZ(), tracker.ISlice() >= 18); err2Y += sErr2; @@ -480,7 +480,7 @@ GPUdic(2, 1) void GPUTPCTrackletConstructor::DoTracklet(GPUconstantref() MEM_GLO if ((r.mGo = (tParam.TransportToX(x, tracker.Param().bzCLight, GPUCA_MAX_SIN_PHI) && tParam.Filter(r.mLastY, r.mLastZ, tParam.Err2Y() * 0.5f, tParam.Err2Z() * 0.5f, GPUCA_MAX_SIN_PHI_LOW, true)))) { CADEBUG(printf("%14s: SEA BACK ROW %3d X %8.3f -", "", iRow, tParam.X()); for (int i = 0; i < 5; i++) { printf(" %8.3f", tParam.Par()[i]); } printf(" -"); for (int i = 0; i < 15; i++) { printf(" %8.3f", tParam.Cov()[i]); } printf("\n")); float err2Y, err2Z; - tracker.GetErrors2Seeding(r.mEndRow, tParam, -1.f, 0.f, 0.f, err2Y, err2Z); // TODO: Use correct time + tracker.GetErrors2Seeding(r.mEndRow, tParam, -1.f, err2Y, err2Z); // TODO: Use correct time if (tParam.GetCov(0) < err2Y) { tParam.SetCov(0, err2Y); } From f9672ee4945530ab631b0a34d9db1fd56db69c2b Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 18 Apr 2024 12:39:50 +0200 Subject: [PATCH 0128/2997] GPU: Add clusterError2AdditionalY/ZSeeding for separate errors during seeding, and simplify error formula during seeding without charge parts --- GPU/GPUTracking/Base/GPUParam.h | 6 ++-- GPU/GPUTracking/Base/GPUParam.inc | 36 ++++++++++++++----- GPU/GPUTracking/Definitions/GPUSettingsList.h | 6 ++-- GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx | 4 +-- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUParam.h b/GPU/GPUTracking/Base/GPUParam.h index 8f0277a8a9ff3..852f52bf68862 100644 --- a/GPU/GPUTracking/Base/GPUParam.h +++ b/GPU/GPUTracking/Base/GPUParam.h @@ -97,15 +97,15 @@ struct GPUParam : public internal::GPUParam_t } return 0.174533f + par.dAlpha * iSlice; } - GPUd() float GetClusterErrorSeeding(int yz, int type, float zDiff, float angle2) const; + GPUd() float GetClusterErrorSeeding(int yz, int type, float zDiff, float angle2, float unscaledMult) const; GPUd() void GetClusterErrorsSeeding2(char sector, int row, float z, float sinPhi, float DzDs, float time, float& ErrY2, float& ErrZ2) const; GPUd() float GetSystematicClusterErrorIFC2(float trackX, float trackY, float z, bool sideC) const; GPUd() float GetSystematicClusterErrorC122(float trackX, float trackY, char sector) const; - GPUd() float GetClusterError2(int yz, int type, float zDiff, float angle2, float scaledMult, float scaledAvgInvCharge, float scaledInvCharge) const; + GPUd() float GetClusterError2(int yz, int type, float zDiff, float angle2, float unscaledMult, float scaledAvgInvCharge, float scaledInvCharge) const; GPUd() void GetClusterErrors2(char sector, int row, float z, float sinPhi, float DzDs, float time, float avgInvCharge, float invCharge, float& ErrY2, float& ErrZ2) const; GPUd() void UpdateClusterError2ByState(short clusterState, float& ErrY2, float& ErrZ2) const; - GPUd() float GetScaledMult(float time) const; + GPUd() float GetUnscaledMult(float time) const; GPUd() void Slice2Global(int iSlice, float x, float y, float z, float* X, float* Y, float* Z) const; GPUd() void Global2Slice(int iSlice, float x, float y, float z, float* X, float* Y, float* Z) const; diff --git a/GPU/GPUTracking/Base/GPUParam.inc b/GPU/GPUTracking/Base/GPUParam.inc index 2c6538f09b4ee..f9e3059a1afce 100644 --- a/GPU/GPUTracking/Base/GPUParam.inc +++ b/GPU/GPUTracking/Base/GPUParam.inc @@ -49,13 +49,34 @@ GPUdi() void MEM_LG(GPUParam)::Global2Slice(int iSlice, float X, float Y, float MEM_CLASS_PRE() GPUdi() void MEM_LG(GPUParam)::GetClusterErrorsSeeding2(char sector, int iRow, float z, float sinPhi, float DzDs, float time, float& ErrY2, float& ErrZ2) const { - GetClusterErrors2(sector, iRow, z, sinPhi, DzDs, time, 0.f, 0.f, ErrY2, ErrZ2); + const int rowType = tpcGeometry.GetROC(iRow); + z = CAMath::Abs(tpcGeometry.TPCLength() - CAMath::Abs(z)); + const float s2 = CAMath::Min(sinPhi * sinPhi, 0.95f * 0.95f); + const float sec2 = 1.f / (1.f - s2); + const float angleY2 = s2 * sec2; // dy/dx + const float angleZ2 = DzDs * DzDs * sec2; // dz/dx + + const float unscaledMult = time >= 0.f ? GetUnscaledMult(time) / tpcGeometry.Row2X(iRow) : 0.f; + + ErrY2 = GetClusterErrorSeeding(0, rowType, z, angleY2, unscaledMult); // Returns Err2 + ErrZ2 = GetClusterErrorSeeding(1, rowType, z, angleZ2, unscaledMult); // Returns Err2 +} + +MEM_CLASS_PRE() +GPUdi() float MEM_LG(GPUParam)::GetClusterErrorSeeding(int yz, int type, float zDiff, float angle2, float unscaledMult) const // Note, returns Err2 despite the name not containing 2 +{ + MakeType(const float*) c = ParamErrors[yz][type]; // Note: c[0] = p[0]^2, c[1] = p[1]^2 * padHeight, c[2] = p[2]^2 / tpcLength / padHeight, c[3] = p[3]^2 * clusterErrorOccupancyScaler^2 + float v = c[0] + c[1] * angle2 + c[2] * zDiff + c[3] * (unscaledMult * unscaledMult); + v = CAMath::Abs(v); + v *= yz ? rec.tpc.clusterError2CorrectionZ : rec.tpc.clusterError2CorrectionY; + v += yz ? rec.tpc.clusterError2AdditionalZSeeding : rec.tpc.clusterError2AdditionalYSeeding; + return v; } MEM_CLASS_PRE() GPUdi() float MEM_LG(GPUParam)::GetClusterError2(int yz, int type, float zDiff, float angle2, float unscaledMult, float scaledInvAvgCharge, float scaledInvCharge) const { - MakeType(const float*) c = ParamErrors[yz][type]; // Note: c[0] = p[0]^2, c[1] = p[1]^2 * padHeight, c[2] = p[2]^2 / tpcLength / padHeight, c[3] = p[3]^2 + MakeType(const float*) c = ParamErrors[yz][type]; // Note: c[0] = p[0]^2, c[1] = p[1]^2 * padHeight, c[2] = p[2]^2 / tpcLength / padHeight, c[3] = p[3]^2 * clusterErrorOccupancyScaler^2 float v = c[0] + c[1] * angle2 * scaledInvAvgCharge + c[2] * zDiff * scaledInvCharge + c[3] * (unscaledMult * unscaledMult) * (scaledInvAvgCharge * scaledInvAvgCharge); v = CAMath::Abs(v); v *= yz ? rec.tpc.clusterError2CorrectionZ : rec.tpc.clusterError2CorrectionY; @@ -113,7 +134,7 @@ GPUdi() float MEM_LG(GPUParam)::GetSystematicClusterErrorC122(float x, float y, #else // GPUCA_TPC_GEOMETRY_O2 MEM_CLASS_PRE() -GPUdi() float MEM_LG(GPUParam)::GetClusterErrorSeeding(int yz, int type, float zDiff, float angle2) const +GPUdi() float MEM_LG(GPUParam)::GetClusterErrorSeeding(int yz, int type, float zDiff, float angle2, float scaledMult) const { MakeType(const float*) c = ParamErrorsSeeding0[yz][type]; float v = c[0] + c[1] * zDiff + c[2] * angle2; @@ -131,8 +152,8 @@ GPUdi() void MEM_LG(GPUParam)::GetClusterErrorsSeeding2(char sector, int iRow, f float angleY2 = s2 * sec2; // dy/dx float angleZ2 = DzDs * DzDs * sec2; // dz/dx - ErrY2 = GetClusterErrorSeeding(0, rowType, z, angleY2); - ErrZ2 = GetClusterErrorSeeding(1, rowType, z, angleZ2); + ErrY2 = GetClusterErrorSeeding(0, rowType, z, angleY2, 0.f); + ErrZ2 = GetClusterErrorSeeding(1, rowType, z, angleZ2, 0.f); ErrY2 = ErrY2 * ErrY2 * rec.tpc.clusterError2CorrectionY + rec.tpc.clusterError2AdditionalY; ErrZ2 = ErrZ2 * ErrZ2 * rec.tpc.clusterError2CorrectionZ + rec.tpc.clusterError2AdditionalZ; } @@ -168,7 +189,6 @@ GPUdi() float MEM_LG(GPUParam)::GetSystematicClusterErrorC122(float trackX, floa MEM_CLASS_PRE() GPUdi() void MEM_LG(GPUParam)::GetClusterErrors2(char sector, int iRow, float z, float sinPhi, float DzDs, float time, float avgInvCharge, float invCharge, float& ErrY2, float& ErrZ2) const { - // Calibrated cluster error from OCDB for Y and Z const int rowType = tpcGeometry.GetROC(iRow); z = CAMath::Abs(tpcGeometry.TPCLength() - CAMath::Abs(z)); const float s2 = CAMath::Min(sinPhi * sinPhi, 0.95f * 0.95f); @@ -176,7 +196,7 @@ GPUdi() void MEM_LG(GPUParam)::GetClusterErrors2(char sector, int iRow, float z, const float angleY2 = s2 * sec2; // dy/dx const float angleZ2 = DzDs * DzDs * sec2; // dz/dx - const float unscaledMult = time >= 0.f ? GetScaledMult(time) / tpcGeometry.Row2X(iRow) : 0.f; + const float unscaledMult = time >= 0.f ? GetUnscaledMult(time) / tpcGeometry.Row2X(iRow) : 0.f; const float scaledInvAvgCharge = avgInvCharge * rec.tpc.clusterErrorChargeScaler > 0.f ? avgInvCharge * rec.tpc.clusterErrorChargeScaler : 1.f; const float scaledInvCharge = invCharge * rec.tpc.clusterErrorChargeScaler > 0.f ? invCharge * rec.tpc.clusterErrorChargeScaler : 1.f; @@ -206,7 +226,7 @@ GPUdi() void MEM_LG(GPUParam)::UpdateClusterError2ByState(short clusterState, fl } MEM_CLASS_PRE() -GPUdi() float MEM_LG(GPUParam)::GetScaledMult(float time) const +GPUdi() float MEM_LG(GPUParam)::GetUnscaledMult(float time) const { #if !defined(__OPENCL__) || defined(__OPENCLCPP__) if (!occupancyMap) { diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index fb92d92716956..982aaaa5ed69d 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -42,8 +42,10 @@ AddOptionRTC(hitSearchArea2, float, 2.f, "", 0, "square of maximum search road o AddOptionRTC(neighboursSearchArea, float, 3.f, "", 0, "area in cm for the search of neighbours, only used if searchWindowDZDR = 0") AddOptionRTC(clusterError2CorrectionY, float, 1.f, "", 0, "correction (multiplicative) for the squared cluster error during tracking") AddOptionRTC(clusterError2CorrectionZ, float, 1.f, "", 0, "correction (multiplicative) for the squared cluster error during tracking") -AddOptionRTC(clusterError2AdditionalY, float, 0.f, "", 0, "correction (additive) for the squared cluster error during tracking") -AddOptionRTC(clusterError2AdditionalZ, float, 0.f, "", 0, "correction (additive) for the squared cluster error during tracking") +AddOptionRTC(clusterError2AdditionalY, float, 0.f, "", 0, "correction (additive) for the squared cluster error during track fitting") +AddOptionRTC(clusterError2AdditionalZ, float, 0.f, "", 0, "correction (additive) for the squared cluster error during track fitting") +AddOptionRTC(clusterError2AdditionalYSeeding, float, 0.f, "", 0, "correction (additive) for the squared cluster error during track seeding") +AddOptionRTC(clusterError2AdditionalZSeeding, float, 0.f, "", 0, "correction (additive) for the squared cluster error during track seeding") AddOptionRTC(clusterRejectChi2TolleranceY, float, 1.f, "", 0, "Multiplicative factor multiplied onto chi2 in Y direction for cluster rejection check during track fit") AddOptionRTC(clusterRejectChi2TolleranceZ, float, 1.f, "", 0, "Multiplicative factor multiplied onto chi2 in Z direction for cluster rejection check during track fit") AddOptionRTC(clusterErrorOccupancyScaler, float, 9.95e-04f, "", 0, "Scaling factor applied to occupancy histogram bin in cluster error estimation") diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx index 00c1641e79f46..19d56b62ba490 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMergerDump.cxx @@ -360,7 +360,7 @@ void GPUTPCGMMerger::DebugStreamerUpdate(int iTrk, int ihit, float xx, float yy, auto uncorrectedYZ = StreamerUncorrectedZY(cluster.slice, cluster.row, track, prop); float invCharge = 1.f / clusterNative.qMax; int iRow = cluster.row; - float scaledMult = (time >= 0.f ? Param().GetScaledMult(time) / Param().tpcGeometry.Row2X(iRow) : 0.f); + float unscaledMult = (time >= 0.f ? Param().GetUnscaledMult(time) / Param().tpcGeometry.Row2X(iRow) : 0.f); const float clAlpha = Param().Alpha(cluster.slice); unsigned int occupancyTotal = Param().occupancyTotal; o2::utils::DebugStreamer::instance()->getStreamer("debug_update_track", "UPDATE") << o2::utils::DebugStreamer::instance()->getUniqueTreeName("tree_update_track").data() @@ -381,7 +381,7 @@ void GPUTPCGMMerger::DebugStreamerUpdate(int iTrk, int ihit, float xx, float yy, << "trackUncorrectedYZ=" << uncorrectedYZ << "avgInvCharge=" << avgInvCharge << "invCharge=" << invCharge - << "scaledMultiplicity=" << scaledMult + << "unscaledMultiplicity=" << unscaledMult << "alpha=" << clAlpha << "iRow=" << iRow << "posY=" << posY From 60ca7f911d4b999ebe7e6bb676746bdd1106dedb Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 19 Apr 2024 13:53:46 +0200 Subject: [PATCH 0129/2997] GPU: Fix missing CMake target dependency for on-the-fly include file creation --- GPU/GPUTracking/Base/hip/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index 7044a8f7210eb..1f50cdc19d053 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -262,4 +262,7 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") target_link_options(GPUTrackingHIPExternalProvider PRIVATE $<$:-fgpu-rdc>) target_compile_definitions(GPUTrackingHIPExternalProvider PRIVATE $) target_include_directories(GPUTrackingHIPExternalProvider PRIVATE $) + if(NOT DEFINED GPUCA_HIP_HIPIFY_FROM_CUDA OR "${GPUCA_HIP_HIPIFY_FROM_CUDA}") + add_dependencies(GPUTrackingHIPExternalProvider ${MODULE}_HIPIFIED) + endif() endif() From 192ccdf20ee5778b7c43b8ec69b7dd4db73a7f7f Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Fri, 19 Apr 2024 21:52:38 +0200 Subject: [PATCH 0130/2997] [EMCAL-710] Fix number of error types after adding STU decoder errors (#13052) --- .../Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h index d8e750c9ad0ba..fb7538bee9694 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h @@ -191,7 +191,7 @@ class ErrorTypeFEE /// \brief Get the number of error types /// \return Number of error types (including undefined) - static constexpr int getNumberOfErrorTypes() { return 7; } + static constexpr int getNumberOfErrorTypes() { return 9; } /// \brief Get the name of the error type /// \param errorTypeID ID of the error type From 834ca8590da2ac8fe55d9b3fda5148cb6b0b6628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Sat, 20 Apr 2024 00:27:26 +0200 Subject: [PATCH 0131/2997] Add pVector in McParticles (#13043) --- Framework/Core/include/Framework/AnalysisDataModel.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 34fe8ddf5dd2d..0df1186f4d04e 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -165,7 +165,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(PVector, pVector, //! Momentum vector in x,y,z-direct const auto px = pt * (r * cs - snp * sn); const auto py = pt * (snp * cs + r * sn); const auto pz = pt * tgl; - return std::move(std::array{std::move(px), std::move(py), std::move(pz)}); + return std::array{px, py, pz}; }); DECLARE_SOA_EXPRESSION_COLUMN(P, p, float, //! Momentum in Gev/c ifnode(nabs(aod::track::signed1Pt) <= o2::constants::math::Almost0, o2::constants::math::VeryBig, 0.5f * (ntan(o2::constants::math::PIQuarter - 0.5f * natan(aod::track::tgl)) + 1.f / ntan(o2::constants::math::PIQuarter - 0.5f * natan(aod::track::tgl))) / nabs(aod::track::signed1Pt))); @@ -1580,6 +1580,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(GetHepMCStatusCode, getHepMCStatusCode, //! The HepMC [](uint8_t flags, int statusCode) -> int { if ((flags & o2::aod::mcparticle::enums::ProducedByTransport) == 0x0) { return o2::mcgenstatus::getHepMCStatusCode(statusCode); } else { return -1; } }); DECLARE_SOA_DYNAMIC_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, //! True if particle is considered a physical primary according to the ALICE definition [](uint8_t flags) -> bool { return (flags & o2::aod::mcparticle::enums::PhysicalPrimary) == o2::aod::mcparticle::enums::PhysicalPrimary; }); +DECLARE_SOA_DYNAMIC_COLUMN(PVector, pVector, //! Momentum vector in x,y,z-directions in GeV/c + [](float px, float py, float pz) -> std::array { return std::array{px, py, pz}; }); DECLARE_SOA_EXPRESSION_COLUMN(Phi, phi, float, //! Phi in the range [0, 2pi) o2::constants::math::PI + natan2(-1.0f * aod::mcparticle::py, -1.0f * aod::mcparticle::px)); @@ -1618,6 +1620,7 @@ DECLARE_SOA_TABLE_FULL(StoredMcParticles_000, "McParticles", "AOD", "MCPARTICLE" mcparticle::Daughter0Id, mcparticle::Daughter1Id, mcparticle::Weight, mcparticle::Px, mcparticle::Py, mcparticle::Pz, mcparticle::E, mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, mcparticle::Vt, + mcparticle::PVector, mcparticle::ProducedByGenerator, mcparticle::FromBackgroundEvent, mcparticle::GetGenStatusCode, @@ -1631,6 +1634,7 @@ DECLARE_SOA_TABLE_FULL_VERSIONED(StoredMcParticles_001, "McParticles", "AOD", "M mcparticle::MothersIds, mcparticle::DaughtersIdSlice, mcparticle::Weight, mcparticle::Px, mcparticle::Py, mcparticle::Pz, mcparticle::E, mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, mcparticle::Vt, + mcparticle::PVector, mcparticle::ProducedByGenerator, mcparticle::FromBackgroundEvent, mcparticle::GetGenStatusCode, From 2365dd506d0ee2998addd8d429bd03d5184bca24 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 19 Apr 2024 17:52:21 +0200 Subject: [PATCH 0132/2997] Add clear method to AbstractRef --- DataFormats/common/include/CommonDataFormat/AbstractRef.h | 1 + 1 file changed, 1 insertion(+) diff --git a/DataFormats/common/include/CommonDataFormat/AbstractRef.h b/DataFormats/common/include/CommonDataFormat/AbstractRef.h index cdc65f6c412d6..8dce94d502ffb 100644 --- a/DataFormats/common/include/CommonDataFormat/AbstractRef.h +++ b/DataFormats/common/include/CommonDataFormat/AbstractRef.h @@ -79,6 +79,7 @@ class AbstractRef GPUdi() bool operator==(const AbstractRef& o) const { return getRawWOFlags() == o.getRawWOFlags(); } GPUdi() bool operator!=(const AbstractRef& o) const { return !operator==(o); } + GPUdi() void clear() { setRaw((Base_t(SrcMask & ((0x1 << NBSrc) - 1)) << NBIdx) | Base_t(IdxMask & ((0x1 << NBIdx) - 1))); } protected: Base_t mRef = IdxMask | (SrcMask << NBIdx); // packed reference, dummy by default From 9a1c156e88b70033f26fb6b44636388cd0abc094 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 18 Apr 2024 19:02:31 +0200 Subject: [PATCH 0133/2997] Add debug output for tracks/points + multiple fixes Add debug track/points --- Detectors/Align/CMakeLists.txt | 4 + .../Workflow/src/BarrelAlignmentSpec.cxx | 6 ++ Detectors/Align/include/Align/AlgPntDbg.h | 91 +++++++++++++++++++ Detectors/Align/include/Align/AlgTrcDbg.h | 90 ++++++++++++++++++ Detectors/Align/include/Align/AlignConfig.h | 11 ++- .../include/Align/AlignableSensorHMPID.h | 2 +- .../Align/include/Align/AlignableSensorITS.h | 2 +- .../Align/include/Align/AlignableSensorTOF.h | 2 +- .../Align/include/Align/AlignableSensorTPC.h | 2 +- .../Align/include/Align/AlignableSensorTRD.h | 2 +- Detectors/Align/include/Align/Controller.h | 13 ++- .../include/Align/ResidualsControllerFast.h | 2 +- Detectors/Align/src/AlgPntDbg.cxx | 22 +++++ Detectors/Align/src/AlgTrcDbg.cxx | 23 +++++ Detectors/Align/src/AlignLinkDef.h | 4 + Detectors/Align/src/AlignableDetectorTPC.cxx | 10 +- Detectors/Align/src/AlignableDetectorTRD.cxx | 11 ++- Detectors/Align/src/AlignmentTrack.cxx | 22 ++++- Detectors/Align/src/Controller.cxx | 41 ++++++++- .../include/TRDBase/TrackletTransformer.h | 1 + 20 files changed, 336 insertions(+), 25 deletions(-) create mode 100644 Detectors/Align/include/Align/AlgPntDbg.h create mode 100644 Detectors/Align/include/Align/AlgTrcDbg.h create mode 100644 Detectors/Align/src/AlgPntDbg.cxx create mode 100644 Detectors/Align/src/AlgTrcDbg.cxx diff --git a/Detectors/Align/CMakeLists.txt b/Detectors/Align/CMakeLists.txt index 9c47167c28a6b..d99e1a803612f 100644 --- a/Detectors/Align/CMakeLists.txt +++ b/Detectors/Align/CMakeLists.txt @@ -36,6 +36,8 @@ o2_add_library(Align src/EventVertex.cxx src/AlignConfig.cxx src/Mille.cxx + src/AlgPntDbg.cxx + src/AlgTrcDbg.cxx PUBLIC_LINK_LIBRARIES O2::FrameworkLogger O2::Steer O2::ReconstructionDataFormats @@ -82,6 +84,8 @@ o2_target_root_dictionary( include/Align/GeometricalConstraint.h include/Align/utils.h include/Align/AlignConfig.h + include/Align/AlgPntDbg.h + include/Align/AlgTrcDbg.h ) add_subdirectory(Workflow) diff --git a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx index 38ebed8fac9c6..22e237fc4c059 100644 --- a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx +++ b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx @@ -192,6 +192,12 @@ void BarrelAlignmentSpec::init(InitContext& ic) if (ic.options().get("apply-xor")) { mTRDTransformer->setApplyXOR(); } + auto prevShift = mTRDTransformer->isShiftApplied(); + if (getenv("ALIEN_JDL_LPMPRODUCTIONTYPE") && std::strcmp(getenv("ALIEN_JDL_LPMPRODUCTIONTYPE"), "MC") == 0) { + // apply artificial pad shift in case non-ideal alignment is used to compensate for shift in current alignment from real data + mTRDTransformer->setApplyShift(false); + } + LOGP(info, "Old TRD shift : {} new : {}", prevShift, mTRDTransformer->isShiftApplied()); mController->setTRDTransformer(mTRDTransformer.get()); } mController->setAllowAfterburnerTracks(ic.options().get("allow-afterburner-tracks")); diff --git a/Detectors/Align/include/Align/AlgPntDbg.h b/Detectors/Align/include/Align/AlgPntDbg.h new file mode 100644 index 0000000000000..12e8205f6b614 --- /dev/null +++ b/Detectors/Align/include/Align/AlgPntDbg.h @@ -0,0 +1,91 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @file AlignmentPoint.h +/// @author ruben.shahoyan@cern.ch, michael.lettrich@cern.ch +/// @since 2021-02-01 +/// @brief Meausered point in the sensor. + +/** + * Compact alignment point info for debugging + */ + +#ifndef ALGPNTDBG_H +#define ALGPNTDBG_H + +#include "Align/AlignmentPoint.h" + +namespace o2 +{ +namespace align +{ + +struct AlgPntDbg { + public: + using DetID = o2::detectors::DetID; + // + enum { + UpperLeg = 0 + }; + // + AlgPntDbg() = default; + AlgPntDbg(const AlgPntDbg&) = default; + ~AlgPntDbg() = default; + AlgPntDbg& operator=(const AlgPntDbg& other) = default; + AlgPntDbg(const AlignmentPoint* point) : mDetID(point->getDetID()), mSID(point->getSID()), mAlpha(point->getAlphaSens()), mX(point->getXTracking()), mY(point->getYTracking()), mZ(point->getZTracking()), mErrYY(point->getYZErrTracking()[0]), mErrZZ(point->getYZErrTracking()[2]), mErrYZ(point->getYZErrTracking()[1]) + { + mSinAlp = std::sin(mAlpha); + mCosAlp = std::cos(mAlpha); + mSnp = point->getTrParamWSA()[2]; // track Snp at the sensor + if (point->isInvDir()) { + setUpperLeg(); + } + } + + float getR() const { return std::sqrt(mX * mX + mY * mY); } + float getYTrack() const { return mY + mYRes; } + float getZTrack() const { return mZ + mZRes; } + float getXTrack() const { return mX; } + float getXLab() const { return mX * mCosAlp - mY * mSinAlp; } + float getYLab() const { return mX * mSinAlp + mY * mCosAlp; } + float getZLap() const { return mZ; } + float getXTrackLab() const { return mX * mCosAlp - getYTrack() * mSinAlp; } + float getYTrackLab() const { return mX * mSinAlp + getYTrack() * mCosAlp; } + float getZTrackLab() const { return getZTrack(); } + float getPhi() const { return std::atan2(getYLab(), getXLab()); } + void setFlag(int i) { mFlags |= 0x1 << i; } + bool getFlag(int i) const { return (mFlags & (0x1 << i)) != 0; } + + void setUpperLeg() { setFlag(int(UpperLeg)); } + bool isUpperLeg() const { return getFlag(int(UpperLeg)); } + + int mDetID{}; // DetectorID + int16_t mSID = -1; // sensor ID in the detector + uint16_t mFlags = 0; // flags + float mAlpha = 0.f; // Alpha of tracking frame + float mSinAlp = 0.f; + float mCosAlp = 0.f; + float mX = 0.f; // tracking X + float mY = 0.f; // tracking Y + float mZ = 0.f; // Z + float mYRes = 0.f; // tracking Y residual (track - point) + float mZRes = 0.f; // Z residual + float mErrYY = 0.f; + float mErrZZ = 0.f; + float mErrYZ = 0.f; + float mSnp = 0.f; + + ClassDefNV(AlgPntDbg, 1); +}; + +} // namespace align +} // namespace o2 +#endif diff --git a/Detectors/Align/include/Align/AlgTrcDbg.h b/Detectors/Align/include/Align/AlgTrcDbg.h new file mode 100644 index 0000000000000..cb179dd8b9b2f --- /dev/null +++ b/Detectors/Align/include/Align/AlgTrcDbg.h @@ -0,0 +1,90 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @file AlgTrcDbg.h +/// @author ruben.shahoyan@cern.ch + +#ifndef ALGTRCDBG_H +#define ALGTRCDBG_H + +#include "Align/AlignmentTrack.h" +#include "Align/AlgPntDbg.h" +#include "ReconstructionDataFormats/GlobalTrackID.h" +#include "ReconstructionDataFormats/Track.h" + +namespace o2 +{ +namespace align +{ + +struct AlgTrcDbg : public o2::track::TrackParCov { + AlgTrcDbg(const AlignmentTrack* trc) { setTrackParam(trc); } + AlgTrcDbg() = default; + ~AlgTrcDbg() = default; + AlgTrcDbg(const AlgTrcDbg&) = default; + AlgTrcDbg& operator=(const AlgTrcDbg&) = default; + + bool setTrackParam(const AlignmentTrack* trc) + { + if (!trc) { + return false; + } + setX(trc->getX()); + setY(trc->getAlpha()); + for (int i = 0; i < 5; i++) { + setParam(trc->getParam(i), i); + } + for (int i = 0; i < 15; i++) { + setCov(trc->getCov()[i], i); + } + mPoints.clear(); + for (int i = 0; i < trc->getNPoints(); i++) { + const auto* tpoint = trc->getPoint(i); + if (tpoint->containsMeasurement()) { + auto& pnt = mPoints.emplace_back(tpoint); + pnt.mYRes = trc->getResidual(0, i); + pnt.mZRes = trc->getResidual(1, i); + } + } + setX(trc->getX()); + setY(trc->getAlpha()); + for (int i = 0; i < 5; i++) { + setParam(trc->getParam(i), i); + } + for (int i = 0; i < 15; i++) { + setCov(trc->getCov()[i], i); + } + for (int i = 0; i < trc->getNPoints(); i++) { + const auto* tpoint = trc->getPoint(i); + if (tpoint->containsMeasurement()) { + auto& pnt = mPoints.emplace_back(tpoint); + pnt.mYRes = trc->getResidual(0, i); + pnt.mZRes = trc->getResidual(1, i); + } + } + mGID.clear(); + mGIDCosmUp.clear(); + return true; + } + + auto getNPoints() const { return mPoints.size(); } + bool isCosmic() const { return mGIDCosmUp.isSourceSet(); } + + std::vector mPoints; + o2::dataformats::GlobalTrackID mGID{}; + o2::dataformats::GlobalTrackID mGIDCosmUp{}; // GID of upper leg in case of cosmic + // + ClassDefNV(AlgTrcDbg, 1); +}; + +} // namespace align +} // namespace o2 +#endif diff --git a/Detectors/Align/include/Align/AlignConfig.h b/Detectors/Align/include/Align/AlignConfig.h index 4252f9ee4364c..91b503c2c923e 100644 --- a/Detectors/Align/include/Align/AlignConfig.h +++ b/Detectors/Align/include/Align/AlignConfig.h @@ -35,6 +35,8 @@ struct AlignConfig : public o2::conf::ConfigurableParamHelper { float q2PtMin[NTrackTypes] = {0.01, 0.01}; float q2PtMax[NTrackTypes] = {10., 10.}; float tglMax[NTrackTypes] = {3., 10.}; + float defPTB0Coll = 0.6; + float defPTB0Cosm = 3.0; int minPoints[NTrackTypes] = {4, 10}; int minDetAcc[NTrackTypes] = {1, 1}; @@ -54,7 +56,7 @@ struct AlignConfig : public o2::conf::ConfigurableParamHelper { int minTOFClusters = 1; // min TOF clusters to accept track int maxTPCRowsCombined = 1; // allow combining clusters on so many rows to a single cluster int discardEdgePadrows = 3; // discard padrow if its distance to stack edge padrow < this - float discardSectorEdgeDepth = 2.; // discard clusters too close to the sector edge + float discardSectorEdgeDepth = 2.5; // discard clusters too close to the sector edge float ITSOverlapMargin = 0.15; // consider for overlaps only clusters within this marging from the chip edge (in cm) float ITSOverlapMaxChi2 = 16; // max chi2 between track and overlapping cluster int ITSOverlapEdgeRows = 1; // require clusters to not have pixels closer than this distance from the edge @@ -71,8 +73,11 @@ struct AlignConfig : public o2::conf::ConfigurableParamHelper { int minTOFClustersCosm = 0; // min TOF clusters to accept track int minTOFClustersCosmLeg = 1; // min TOF clusters per leg to accept track - int minTPCPadRow = 0; // min TPC pad-row to account - int maxTPCPadRow = 151; // max TPC pad-row to account + int minTPCPadRow = 6; // min TPC pad-row to account + int maxTPCPadRow = 146; // max TPC pad-row to account + + float cosmMaxDSnp = 0.025; // reject cosmic tracks with larger than this snp difference + float cosmMaxDTgl = 0.1; // reject cosmic tracks with larger than this tgl difference float maxDCAforVC[2] = {-1, -1}; // DCA cut in R,Z to allow track be subjected to vertex constraint float maxChi2forVC = -1; // track-vertex chi2 cut to allow the track be subjected to vertex constraint diff --git a/Detectors/Align/include/Align/AlignableSensorHMPID.h b/Detectors/Align/include/Align/AlignableSensorHMPID.h index 6064078d1b923..867b72152c73c 100644 --- a/Detectors/Align/include/Align/AlignableSensorHMPID.h +++ b/Detectors/Align/include/Align/AlignableSensorHMPID.h @@ -29,7 +29,7 @@ namespace o2 namespace align { -class AlignableSensorHMPID : public AlignableSensor +class AlignableSensorHMPID final : public AlignableSensor { public: AlignableSensorHMPID(const char* name = 0, int vid = 0, int iid = 0, int isec = 0); diff --git a/Detectors/Align/include/Align/AlignableSensorITS.h b/Detectors/Align/include/Align/AlignableSensorITS.h index de0e6d35629ec..8070869bd8c7b 100644 --- a/Detectors/Align/include/Align/AlignableSensorITS.h +++ b/Detectors/Align/include/Align/AlignableSensorITS.h @@ -29,7 +29,7 @@ namespace o2 namespace align { -class AlignableSensorITS : public AlignableSensor +class AlignableSensorITS final : public AlignableSensor { public: AlignableSensorITS() = default; diff --git a/Detectors/Align/include/Align/AlignableSensorTOF.h b/Detectors/Align/include/Align/AlignableSensorTOF.h index 745251d7dc6f2..d9e11dce98a0c 100644 --- a/Detectors/Align/include/Align/AlignableSensorTOF.h +++ b/Detectors/Align/include/Align/AlignableSensorTOF.h @@ -29,7 +29,7 @@ namespace o2 namespace align { -class AlignableSensorTOF : public AlignableSensor +class AlignableSensorTOF final : public AlignableSensor { public: AlignableSensorTOF() = default; diff --git a/Detectors/Align/include/Align/AlignableSensorTPC.h b/Detectors/Align/include/Align/AlignableSensorTPC.h index 41b48afaa38f7..838e8c8272400 100644 --- a/Detectors/Align/include/Align/AlignableSensorTPC.h +++ b/Detectors/Align/include/Align/AlignableSensorTPC.h @@ -25,7 +25,7 @@ namespace o2 namespace align { -class AlignableSensorTPC : public AlignableSensor +class AlignableSensorTPC final : public AlignableSensor { public: AlignableSensorTPC() = default; diff --git a/Detectors/Align/include/Align/AlignableSensorTRD.h b/Detectors/Align/include/Align/AlignableSensorTRD.h index 65792d597cb3a..190543bb584fd 100644 --- a/Detectors/Align/include/Align/AlignableSensorTRD.h +++ b/Detectors/Align/include/Align/AlignableSensorTRD.h @@ -26,7 +26,7 @@ namespace o2 namespace align { -class AlignableSensorTRD : public AlignableSensor +class AlignableSensorTRD final : public AlignableSensor { public: AlignableSensorTRD() = default; diff --git a/Detectors/Align/include/Align/Controller.h b/Detectors/Align/include/Align/Controller.h index 4def24472ea6d..abbb051be138a 100644 --- a/Detectors/Align/include/Align/Controller.h +++ b/Detectors/Align/include/Align/Controller.h @@ -26,6 +26,7 @@ #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Align/AlignmentTrack.h" +#include "Align/AlgTrcDbg.h" #include "ReconstructionDataFormats/PrimaryVertex.h" #include "ReconstructionDataFormats/TrackCosmics.h" #include "DataFormatsTPC/VDriftCorrFact.h" @@ -53,9 +54,8 @@ #include #include #include "Align/Mille.h" -#include "GPUO2Interface.h" -#include "GPUParam.h" -#include "DataFormatsTPC/WorkflowHelper.h" +// #include "GPUO2Interface.h" +// #include "DataFormatsTPC/WorkflowHelper.h" namespace o2 { @@ -72,6 +72,11 @@ namespace utils class TreeStreamRedirector; } +namespace gpu +{ +class GPUParam; +} + namespace align { @@ -220,6 +225,7 @@ class Controller final : public TObject void initMIlleOutput(); void initResidOutput(); bool storeProcessedTrack(o2::dataformats::GlobalTrackID tid = {}); + void extractDbgTrack(); void printStatistics() const; // void genPedeSteerFile(const Option_t* opt = "") const; @@ -302,6 +308,7 @@ class Controller final : public TObject float mMPRecOutFraction = 0.; float mControlFraction = 0.; std::unique_ptr mAlgTrack; // current alignment track + AlgTrcDbg mAlgTrackDbg; // current alignment track debug version const o2::globaltracking::RecoContainer* mRecoData = nullptr; // externally set RecoContainer const o2::trd::TrackletTransformer* mTRDTransformer = nullptr; // TRD tracket transformer bool mTRDTrigRecFilterActive = false; // select TRD triggers processed with ITS diff --git a/Detectors/Align/include/Align/ResidualsControllerFast.h b/Detectors/Align/include/Align/ResidualsControllerFast.h index 171bfb45757d2..5a2f947db9cca 100644 --- a/Detectors/Align/include/Align/ResidualsControllerFast.h +++ b/Detectors/Align/include/Align/ResidualsControllerFast.h @@ -24,7 +24,7 @@ namespace o2 namespace align { -class ResidualsControllerFast : public TObject +class ResidualsControllerFast final : public TObject { public: enum { kCosmicBit = BIT(14), diff --git a/Detectors/Align/src/AlgPntDbg.cxx b/Detectors/Align/src/AlgPntDbg.cxx new file mode 100644 index 0000000000000..b52492b3a5cc4 --- /dev/null +++ b/Detectors/Align/src/AlgPntDbg.cxx @@ -0,0 +1,22 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @file AlgPntDbg.h + +#include "Align/AlgPntDbg.h" + +namespace o2 +{ +namespace align +{ + +} // namespace align +} // namespace o2 diff --git a/Detectors/Align/src/AlgTrcDbg.cxx b/Detectors/Align/src/AlgTrcDbg.cxx new file mode 100644 index 0000000000000..157ca941449b7 --- /dev/null +++ b/Detectors/Align/src/AlgTrcDbg.cxx @@ -0,0 +1,23 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @file AlgTrcDbg.h + +#include "Align/AlgTrcDbg.h" +#include "Framework/Logger.h" + +namespace o2 +{ +namespace align +{ + +} // namespace align +} // namespace o2 diff --git a/Detectors/Align/src/AlignLinkDef.h b/Detectors/Align/src/AlignLinkDef.h index f43d6ee76fbdb..2952c46ec821d 100644 --- a/Detectors/Align/src/AlignLinkDef.h +++ b/Detectors/Align/src/AlignLinkDef.h @@ -39,6 +39,10 @@ #pragma link C++ class o2::align::GeometricalConstraint + ; #pragma link C++ class o2::align::utils; +#pragma link C++ class o2::align::AlgPntDbg + ; +#pragma link C++ class o2::align::AlgTrcDbg + ; +#pragma link C++ class std::vector < o2::align::AlgPntDbg> + ; + #pragma link C++ class o2::align::AlignConfig + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::align::AlignConfig> + ; diff --git a/Detectors/Align/src/AlignableDetectorTPC.cxx b/Detectors/Align/src/AlignableDetectorTPC.cxx index ca4cbbaaffcdd..f66d9e3f3ab95 100644 --- a/Detectors/Align/src/AlignableDetectorTPC.cxx +++ b/Detectors/Align/src/AlignableDetectorTPC.cxx @@ -24,6 +24,8 @@ #include "DataFormatsTPC/WorkflowHelper.h" #include #include +#include "GPUO2Interface.h" +#include "DataFormatsTPC/WorkflowHelper.h" #include "GPUParam.inc" namespace o2 @@ -215,6 +217,13 @@ int AlignableDetectorTPC::processPoints(GIndex gid, int npntCut, bool inv) gpu::gpustd::array p = {y, z}; gpu::gpustd::array c = {0, 0, 0}; mController->getTPCParam()->GetClusterErrors2(sector, currentRow, z, trkParam.getSnp(), trkParam.getTgl(), -1.f, 0.f, 0.f, c[0], c[2]); // TODO: Note this disables occupancy / charge components of the error estimation + mController->getTPCParam()->UpdateClusterError2ByState(clusterState, c[0], c[2]); + int nrComb = std::abs(row - currentRow) + 1; + if (nrComb > 1) { + float fact = 1. / std::sqrt(nrComb); + c[0] *= fact; + c[2] *= fact; + } if (sysE[0] > 0.f) { c[0] += sysE[0] * sysE[0]; } @@ -222,7 +231,6 @@ int AlignableDetectorTPC::processPoints(GIndex gid, int npntCut, bool inv) c[2] += sysE[1] * sysE[1]; } - mController->getTPCParam()->UpdateClusterError2ByState(clusterState, c[0], c[2]); if (!trkParam.update(p, c)) { break; } diff --git a/Detectors/Align/src/AlignableDetectorTRD.cxx b/Detectors/Align/src/AlignableDetectorTRD.cxx index 117d328e8fc0a..774d699342805 100644 --- a/Detectors/Align/src/AlignableDetectorTRD.cxx +++ b/Detectors/Align/src/AlignableDetectorTRD.cxx @@ -192,7 +192,7 @@ int AlignableDetectorTRD::processPoints(GIndex gid, int npntCut, bool inv) } int trkltId = trk.getTrackletIndex(il); const auto& trackletRaw = trackletsRaw[trkltId]; - const auto trackletCalibLoc = transformer->transformTracklet(trackletRaw, false); // calibrated tracket in local frame !!! + const auto trackletCalibLoc = transformer->transformTracklet(trackletRaw, true); // calibrated tracket in local frame !!! int trkltDet = trackletRaw.getDetector(); auto* sensor = (AlignableSensorTRD*)getSensor(trkltDet); if (sensor->isDummy()) { @@ -201,18 +201,23 @@ int AlignableDetectorTRD::processPoints(GIndex gid, int npntCut, bool inv) continue; } double locXYZ[3] = {trackletCalibLoc.getX(), trackletCalibLoc.getY(), trackletCalibLoc.getZ()}, locXYZC[3], traXYZ[3]; - + /* const auto& matAlg = sensor->getMatrixClAlg(); // local alignment matrix matAlg.LocalToMaster(locXYZ, locXYZC); // aligned point in the local frame const auto& mat = sensor->getMatrixT2L(); // RS FIXME check if correct mat.MasterToLocal(locXYZC, traXYZ); + */ + traXYZ[0] = trackletCalibLoc.getX(); + traXYZ[1] = trackletCalibLoc.getY(); + traXYZ[2] = trackletCalibLoc.getZ(); + /* // This is a hack until TRD T2L matrix problem will be solved const auto trackletCalib = recoData->getTRDCalibratedTracklets()[trkltId]; traXYZ[0] = trackletCalib.getX(); traXYZ[1] = trackletCalib.getY(); traXYZ[2] = trackletCalib.getZ(); - + */ int trkltSec = sensor->getSector(); // trkltDet / (o2::trd::constants::NLAYER * o2::trd::constants::NSTACK); float alpSens = sensor->getAlpTracking(); // o2::math_utils::sector2Angle(trkltSec); if (trkltSec != o2::math_utils::angle2Sector(trkParam.getAlpha()) || diff --git a/Detectors/Align/src/AlignmentTrack.cxx b/Detectors/Align/src/AlignmentTrack.cxx index 2987682ace4e1..554d30e246e29 100644 --- a/Detectors/Align/src/AlignmentTrack.cxx +++ b/Detectors/Align/src/AlignmentTrack.cxx @@ -787,7 +787,7 @@ void AlignmentTrack::Print(Option_t* opt) const for (int ip = 0; ip < getNPoints(); ip++) { printf("#%3d ", ip); auto* pnt = getPoint(ip); - pnt->print(0); // RS FIXME OPT + pnt->print(AlignmentPoint::kMeasurementBit); // RS FIXME OPT // if (res && pnt->containsMeasurement()) { printf(" Residuals : %+.3e %+.3e -> Pulls: %+7.2f %+7.2f\n", @@ -848,17 +848,17 @@ bool AlignmentTrack::iniFit() { // perform initial fit of the track // - trackParam_t trc(*(trackParam_t*)this); - // + const auto& algConf = AlignConfig::Instance(); if (!getFieldON()) { // for field-off data impose nominal momentum + setQ2Pt(isCosmic() ? 1. / algConf.defPTB0Cosm : 1. / algConf.defPTB0Coll); } + trackParam_t trc(*(trackParam_t*)this); mChi2 = mChi2CosmUp = mChi2CosmDn = 0; // // the points are ranged from outer to inner for collision tracks, // and from outer point of lower leg to outer point of upper leg for the cosmic track // // the fit will always start from the outgoing track in inward direction - const auto& algConf = AlignConfig::Instance(); if (!fitLeg(trc, 0, getInnerPointID(), mNeedInv[0])) { if (algConf.verbose > 2) { LOG(warn) << "Failed fitLeg 0"; @@ -922,6 +922,17 @@ bool AlignmentTrack::combineTracks(trackParam_t& trcL, const trackParam_t& trcU) return false; } // + LOGP(debug, "CosmDn: {}", trcL.asString()); + LOGP(debug, "CosmUp: {}", trcU.asString()); + float dsnp = trcL.getSnp() - trcU.getSnp(), dTgl = trcL.getTgl() - trcU.getTgl(); + if (std::abs(dsnp) > algConf.cosmMaxDSnp || std::abs(dTgl) > algConf.cosmMaxDTgl) { + if (algConf.verbose > 2) { + LOGP(error, "Rejecting track with dSnp={} dTgl={}", dsnp, dTgl); + LOGP(error, "CosmDn: {}", trcL.asString()); + LOGP(error, "CosmUp: {}", trcU.asString()); + } + return false; + } // const covMat_t& covU = trcU.getCov(); // const covMat_t& covL = trcL.getCov(); // @@ -968,7 +979,8 @@ bool AlignmentTrack::combineTracks(trackParam_t& trcL, const trackParam_t& trcU) } mChi2 += chi2; // - // printf("Combined: Chi2Tot:%.2f ChiUp:%.2f ChiDn:%.2f ChiCmb:%.2f\n",mChi2,mChi2CosmUp,mChi2CosmDn, chi2); + LOGP(debug, "CosmCB: {}", trcL.asString()); + LOGP(debug, "Combined: Chi2Tot:{} ChiUp:{} ChiDn:{} ChiCmb:{} DSnp:{} DTgl:{} Alp:{}", mChi2, mChi2CosmUp, mChi2CosmDn, chi2, dsnp, dTgl, trcL.getAlpha()); return true; } diff --git a/Detectors/Align/src/Controller.cxx b/Detectors/Align/src/Controller.cxx index ccc275b0d1057..a45314b2285c0 100644 --- a/Detectors/Align/src/Controller.cxx +++ b/Detectors/Align/src/Controller.cxx @@ -44,10 +44,13 @@ #include #include #include +#include "GPUO2Interface.h" +#include "DataFormatsTPC/WorkflowHelper.h" #include #include "CommonUtils/NameConf.h" #include "MathUtils/SymMatrixSolver.h" #include "DataFormatsParameters/GRPObject.h" +#include "GPUParam.h" #include "SimulationDataFormat/MCUtils.h" #include "Steer/MCKinematicsReader.h" @@ -329,8 +332,16 @@ void Controller::process() } continue; } - - if (mUseMC && mDebugOutputLevel) { + if (mDebugOutputLevel && mAlgTrackDbg.setTrackParam(mAlgTrack.get())) { + mAlgTrackDbg.mGID = trackIndex; + (*mDBGOut) << "algtrack" + << "runNumber=" << mTimingInfo.runNumber + << "tfID=" << mTimingInfo.tfCounter + << "orbit=" << mTimingInfo.firstTForbit + << "bz=" << PropagatorD::Instance()->getNominalBz() + << "t=" << mAlgTrackDbg << "\n"; + } + if (mUseMC && mDebugOutputLevel > 1) { auto lbl = mRecoData->getTrackMCLabel(trackIndex); if (lbl.isValid()) { std::vector pntX, pntY, pntZ, trcX, trcY, trcZ, prpX, prpY, prpZ, alpha, xsens, pntXTF, pntYTF, pntZTF, resY, resZ; @@ -421,7 +432,19 @@ void Controller::processCosmic() nTrc++; mStat.data[ProcStat::kInput][ProcStat::kCosmic]++; std::array contributorsGID[2] = {mRecoData->getSingleDetectorRefs(track.getRefBottom()), mRecoData->getSingleDetectorRefs(track.getRefTop())}; - + bool hasTRD = false, hasITS = false, hasTPC = false, hasTOF = false; + if (contributorsGID[0][GTrackID::TRD].isIndexSet() || contributorsGID[1][GTrackID::TRD].isIndexSet()) { + hasTRD = true; + } + if (contributorsGID[0][GTrackID::TOF].isIndexSet() || contributorsGID[1][GTrackID::TOF].isIndexSet()) { + hasTOF = true; + } + if (contributorsGID[0][GTrackID::TPC].isIndexSet() || contributorsGID[1][GTrackID::TPC].isIndexSet()) { + hasTPC = true; + } + if (contributorsGID[0][GTrackID::ITS].isIndexSet() || contributorsGID[1][GTrackID::ITS].isIndexSet()) { + hasITS = true; + } // check detectors contributions AlignableDetector* det = nullptr; int ndet = 0, npnt = 0; @@ -511,7 +534,7 @@ void Controller::processCosmic() if (algConf.verbose > 1) { LOGP(info, "processing cosmic track B-Leg:{} T-Leg:{}, Ndets:{}, Npoints: {}", track.getRefBottom().asString(), track.getRefTop().asString(), ndet, npnt); } - if (ndet < algConf.minDetectorsCosm || (tpcIn && ndet == 1)) { + if (ndet < algConf.minDetectorsCosm /* || (tpcIn && ndet == 1)*/) { continue; } if (npnt < algConf.minPointTotalCosm) { @@ -543,6 +566,16 @@ void Controller::processCosmic() } continue; } + if (mDebugOutputLevel && mAlgTrackDbg.setTrackParam(mAlgTrack.get())) { + mAlgTrackDbg.mGID = track.getRefBottom(); + mAlgTrackDbg.mGIDCosmUp = track.getRefTop(); + (*mDBGOut) << "algtrack" + << "runNumber=" << mTimingInfo.runNumber + << "tfID=" << mTimingInfo.tfCounter + << "orbit=" << mTimingInfo.firstTForbit + << "bz=" << PropagatorD::Instance()->getNominalBz() + << "t=" << mAlgTrackDbg << "\n"; + } storeProcessedTrack(); mStat.data[ProcStat::kAccepted][ProcStat::kCosmic]++; nTrcAcc++; diff --git a/Detectors/TRD/base/include/TRDBase/TrackletTransformer.h b/Detectors/TRD/base/include/TRDBase/TrackletTransformer.h index 2b6c793a468e3..ca9e71d392231 100644 --- a/Detectors/TRD/base/include/TRDBase/TrackletTransformer.h +++ b/Detectors/TRD/base/include/TRDBase/TrackletTransformer.h @@ -33,6 +33,7 @@ class TrackletTransformer void setCalVdriftExB(const CalVdriftExB* cal) { mCalVdriftExB = cal; }; void setApplyXOR() { mApplyXOR = true; } void setApplyShift(bool f) { mApplyShift = f; } + bool isShiftApplied() const { return mApplyShift; } float calculateZ(int padrow, const PadPlane* padPlane) const; From 78f619234b15b573a13356cc0918cd21f5b89d0e Mon Sep 17 00:00:00 2001 From: shahoian Date: Sat, 20 Apr 2024 19:31:04 +0200 Subject: [PATCH 0134/2997] Fix TRD matrices definition and pad shift accounting --- .../Align/include/Align/AlignableSensorTRD.h | 5 ++ Detectors/Align/src/AlignableDetectorTRD.cxx | 15 +--- Detectors/Align/src/AlignableSensorTRD.cxx | 68 ++++++++++++++++--- 3 files changed, 65 insertions(+), 23 deletions(-) diff --git a/Detectors/Align/include/Align/AlignableSensorTRD.h b/Detectors/Align/include/Align/AlignableSensorTRD.h index 190543bb584fd..eabc3905e9e13 100644 --- a/Detectors/Align/include/Align/AlignableSensorTRD.h +++ b/Detectors/Align/include/Align/AlignableSensorTRD.h @@ -35,7 +35,12 @@ class AlignableSensorTRD final : public AlignableSensor int getSector() const { return mSector; } void setSector(int sc) { mSector = (uint8_t)sc; } void dPosTraDParCalib(const AlignmentPoint* pnt, double* deriv, int calibID, const AlignableVolume* parent = nullptr) const final; + + void prepareMatrixL2G(bool reco = false) final; + void prepareMatrixL2GIdeal() final; void prepareMatrixT2L() final; + void prepareMatrixClAlg() final; + void prepareMatrixClAlgReco() final; protected: uint8_t mSector = 0; // sector ID diff --git a/Detectors/Align/src/AlignableDetectorTRD.cxx b/Detectors/Align/src/AlignableDetectorTRD.cxx index 774d699342805..d752553bf6ead 100644 --- a/Detectors/Align/src/AlignableDetectorTRD.cxx +++ b/Detectors/Align/src/AlignableDetectorTRD.cxx @@ -192,7 +192,7 @@ int AlignableDetectorTRD::processPoints(GIndex gid, int npntCut, bool inv) } int trkltId = trk.getTrackletIndex(il); const auto& trackletRaw = trackletsRaw[trkltId]; - const auto trackletCalibLoc = transformer->transformTracklet(trackletRaw, true); // calibrated tracket in local frame !!! + const auto trackletCalibLoc = transformer->transformTracklet(trackletRaw, false); // calibrated tracket in local frame !!! int trkltDet = trackletRaw.getDetector(); auto* sensor = (AlignableSensorTRD*)getSensor(trkltDet); if (sensor->isDummy()) { @@ -201,23 +201,10 @@ int AlignableDetectorTRD::processPoints(GIndex gid, int npntCut, bool inv) continue; } double locXYZ[3] = {trackletCalibLoc.getX(), trackletCalibLoc.getY(), trackletCalibLoc.getZ()}, locXYZC[3], traXYZ[3]; - /* const auto& matAlg = sensor->getMatrixClAlg(); // local alignment matrix matAlg.LocalToMaster(locXYZ, locXYZC); // aligned point in the local frame const auto& mat = sensor->getMatrixT2L(); // RS FIXME check if correct mat.MasterToLocal(locXYZC, traXYZ); - */ - traXYZ[0] = trackletCalibLoc.getX(); - traXYZ[1] = trackletCalibLoc.getY(); - traXYZ[2] = trackletCalibLoc.getZ(); - - /* - // This is a hack until TRD T2L matrix problem will be solved - const auto trackletCalib = recoData->getTRDCalibratedTracklets()[trkltId]; - traXYZ[0] = trackletCalib.getX(); - traXYZ[1] = trackletCalib.getY(); - traXYZ[2] = trackletCalib.getZ(); - */ int trkltSec = sensor->getSector(); // trkltDet / (o2::trd::constants::NLAYER * o2::trd::constants::NSTACK); float alpSens = sensor->getAlpTracking(); // o2::math_utils::sector2Angle(trkltSec); if (trkltSec != o2::math_utils::angle2Sector(trkParam.getAlpha()) || diff --git a/Detectors/Align/src/AlignableSensorTRD.cxx b/Detectors/Align/src/AlignableSensorTRD.cxx index 2dc7d25ca5932..aa52567a36fdf 100644 --- a/Detectors/Align/src/AlignableSensorTRD.cxx +++ b/Detectors/Align/src/AlignableSensorTRD.cxx @@ -19,6 +19,7 @@ #include "Align/utils.h" #include "Framework/Logger.h" #include "Align/AlignmentPoint.h" +#include "DetectorsBase/GeometryManager.h" namespace o2 { @@ -33,22 +34,71 @@ AlignableSensorTRD::AlignableSensorTRD(const char* name, int vid, int iid, int i // def c-tor } +//____________________________________________ +void AlignableSensorTRD::prepareMatrixClAlg() +{ + // prepare alignment matrix in the pseudo-LOCAL frame of TRD (account that the chamber has extra X,Y rotations + TGeoHMatrix ma = getMatrixL2GIdeal().Inverse(); + ma *= getMatrixL2G(); + setMatrixClAlg(ma); + // +} + +//____________________________________________ +void AlignableSensorTRD::prepareMatrixClAlgReco() +{ + // prepare alignment matrix in the pseudo-LOCAL frame of TRD (account that the chamber has extra X,Y rotations + TGeoHMatrix ma = getMatrixL2GIdeal().Inverse(); + ma *= getMatrixL2G(); + setMatrixClAlgReco(ma); + // +} + +//____________________________________________ +void AlignableSensorTRD::prepareMatrixL2GIdeal() +{ + TGeoHMatrix Rxy; + Rxy.RotateX(-90); + Rxy.RotateY(-90); + TGeoHMatrix mtmp; + if (!base::GeometryManager::getOriginalMatrix(getSymName(), mtmp)) { + LOG(fatal) << "Failed to find ideal L2G matrix for " << getSymName(); + } + mtmp *= Rxy; + setMatrixL2GIdeal(mtmp); +} + +//____________________________________________ +void AlignableSensorTRD::prepareMatrixL2G(bool reco) +{ + TGeoHMatrix Rxy; + Rxy.RotateX(-90); + Rxy.RotateY(-90); + const char* path = getSymName(); + const TGeoHMatrix* l2g = nullptr; + if (!gGeoManager->GetAlignableEntry(path) || !(l2g = base::GeometryManager::getMatrix(path))) { + LOGP(fatal, "Failed to find L2G matrix for {}alignable {} -> {}", gGeoManager->GetAlignableEntry(path) ? "" : "non-", path, (void*)l2g); + } + TGeoHMatrix mtmp = *l2g; + mtmp *= Rxy; + reco ? setMatrixL2GReco(mtmp) : setMatrixL2G(mtmp); +} + //____________________________________________ void AlignableSensorTRD::prepareMatrixT2L() { // extract from geometry T2L matrix double alp = math_utils::detail::sector2Angle(mSector); mAlp = alp; - double loc[3] = {0, 0, 0}, glo[3]; - getMatrixL2GIdeal().LocalToMaster(loc, glo); - mX = Sqrt(glo[0] * glo[0] + glo[1] * glo[1]); - TGeoHMatrix t2l; - // t2l.SetDx(mX); // to remove when T2L will be clarified - t2l.RotateZ(alp * RadToDeg()); - const TGeoHMatrix l2gi = getMatrixL2GIdeal().Inverse(); - t2l.MultiplyLeft(&l2gi); - + TGeoHMatrix Rs; + Rs.RotateZ(-alp * TMath::RadToDeg()); + TGeoHMatrix m0 = getMatrixL2GIdeal(); + m0.MultiplyLeft(Rs); + TGeoHMatrix t2l = m0.Inverse(); setMatrixT2L(t2l); + double loc[3] = {0, 0, 0}, glo[3]; + t2l.MasterToLocal(loc, glo); + mX = glo[0]; // } From d08d21a1bd2d0badc98f10863efe557fad9b4d28 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Fri, 16 Jun 2023 11:32:48 +0200 Subject: [PATCH 0135/2997] [EMCAL-916, EMCAL-537, EMCAL-550, EMCAL-911] Integrate TRU decoding into sync reco - EMCAL-916: Add decoding of TRU data (FastORs and patch index) - EMCAL-911: Add handling of TRU data in RecoContainer - Provide helper classes for TRU- and FastOR decoding including the calculation of the L0timesum - EMCAL-537: Provide data structure for patches, TRUs and Timesums - EMCAL-550: Integration into RecoWorkflow: Output channels and option to disable trigger reconstruction --- DataFormats/Detectors/EMCAL/CMakeLists.txt | 1 + .../DataFormatsEMCAL/CompressedTriggerData.h | 68 ++++ .../EMCAL/src/CompressedTriggerData.cxx | 31 ++ .../base/include/EMCALBase/TriggerMappingV2.h | 1 + Detectors/EMCAL/base/src/TriggerMappingV2.cxx | 2 +- Detectors/EMCAL/reconstruction/CMakeLists.txt | 4 + .../EMCALReconstruction/FastORTimeSeries.h | 83 +++++ .../EMCALReconstruction/RecoContainer.h | 78 +++- .../EMCALReconstruction/TRUDataHandler.h | 185 ++++++++++ .../src/EMCALReconstructionLinkDef.h | 2 + .../reconstruction/src/FastORTimeSeries.cxx | 44 +++ .../reconstruction/src/RecoContainer.cxx | 41 ++- .../reconstruction/src/TRUDataHandler.cxx | 67 ++++ .../EMCALWorkflow/RawToCellConverterSpec.h | 109 +++++- .../include/EMCALWorkflow/RecoWorkflow.h | 4 +- .../workflow/src/RawToCellConverterSpec.cxx | 337 ++++++++++++++---- Detectors/EMCAL/workflow/src/RecoWorkflow.cxx | 5 +- .../EMCAL/workflow/src/emc-reco-workflow.cxx | 4 +- 18 files changed, 978 insertions(+), 88 deletions(-) create mode 100644 DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CompressedTriggerData.h create mode 100644 DataFormats/Detectors/EMCAL/src/CompressedTriggerData.cxx create mode 100644 Detectors/EMCAL/reconstruction/include/EMCALReconstruction/FastORTimeSeries.h create mode 100644 Detectors/EMCAL/reconstruction/include/EMCALReconstruction/TRUDataHandler.h create mode 100644 Detectors/EMCAL/reconstruction/src/FastORTimeSeries.cxx create mode 100644 Detectors/EMCAL/reconstruction/src/TRUDataHandler.cxx diff --git a/DataFormats/Detectors/EMCAL/CMakeLists.txt b/DataFormats/Detectors/EMCAL/CMakeLists.txt index 80b00474465b8..9c93bae30ddf6 100644 --- a/DataFormats/Detectors/EMCAL/CMakeLists.txt +++ b/DataFormats/Detectors/EMCAL/CMakeLists.txt @@ -22,6 +22,7 @@ o2_add_library(DataFormatsEMCAL src/ErrorTypeFEE.cxx src/CellLabel.cxx src/ClusterLabel.cxx + src/CompressedTriggerData.cxx PUBLIC_LINK_LIBRARIES O2::CommonDataFormat O2::Headers O2::MathUtils diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CompressedTriggerData.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CompressedTriggerData.h new file mode 100644 index 0000000000000..5fbf2187ab5dd --- /dev/null +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CompressedTriggerData.h @@ -0,0 +1,68 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef ALICEO2_EMCAL_COMPRESSEDTRIGGERDATA_H +#define ALICEO2_EMCAL_COMPRESSEDTRIGGERDATA_H + +#include +#include + +namespace o2::emcal +{ + +/// \struct CompressedTRU +/// \brief Compressed reconstructed TRU information +/// \ingroup EMCALDataFormat +struct CompressedTRU { + uint8_t mTRUIndex; ///< TRU index + uint8_t mTriggerTime; ///< Trigger time of the TRU + bool mFired; ///< Fired status of the TRU + uint8_t mNumberOfPatches; ///< Number of patches found for the TRU +}; + +/// \struct CompressedTriggerPatch +/// \brief Compressed reconstructed L0 trigger patch information +/// \ingroup EMCALDataFormat +struct CompressedTriggerPatch { + uint8_t mTRUIndex; ///< Index of the TRU where the trigger patch has been found + uint8_t mPatchIndexInTRU; ///< Index of the trigger patch in the TRU + uint8_t mTime; ///< Reconstructed time of the trigger patch + uint16_t mADC; ///< ADC sum of the trigger patch +}; + +/// \struct CompressedL0TimeSum +/// \brief Compressed L0 timesum information +/// \ingroup EMCALDataFormat +struct CompressedL0TimeSum { + uint16_t mIndex; ///< Absolute ID of the FastOR + uint16_t mTimesum; ///< ADC value of the time-sum (4-integral) +}; + +/// \brief Output stream operator of the CompressedTRU +/// \param stream Stream to write to +/// \param tru TRU data to be streamed +/// \return Stream after writing +std::ostream& operator<<(std::ostream& stream, const CompressedTRU& tru); + +/// \brief Output stream operator of the CompressedTriggerPatch +/// \param stream Stream to write to +/// \param patch Trigger patch to be streamed +/// \return Stream after writing +std::ostream& operator<<(std::ostream& stream, const CompressedTriggerPatch& patch); + +/// \brief Output stream operator of the CompressedL0TimeSum +/// \param stream Stream to write to +/// \param timesum FastOR L0 timesum to be streamed +/// \return Stream after writing +std::ostream& operator<<(std::ostream& stream, const CompressedL0TimeSum& timesum); + +} // namespace o2::emcal + +#endif // ALICEO2_EMCAL_COMPRESSEDTRIGGERDATA_H \ No newline at end of file diff --git a/DataFormats/Detectors/EMCAL/src/CompressedTriggerData.cxx b/DataFormats/Detectors/EMCAL/src/CompressedTriggerData.cxx new file mode 100644 index 0000000000000..e60b58c958d03 --- /dev/null +++ b/DataFormats/Detectors/EMCAL/src/CompressedTriggerData.cxx @@ -0,0 +1,31 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include "DataFormatsEMCAL/CompressedTriggerData.h" + +std::ostream& o2::emcal::operator<<(std::ostream& stream, const o2::emcal::CompressedTRU& tru) +{ + stream << "TRU " << tru.mTRUIndex << ": Fired " << (tru.mFired ? "yes" : "no") << ", time " << (tru.mFired ? std::to_string(static_cast(tru.mTriggerTime)) : "Undefined") << ", number of patches " << tru.mNumberOfPatches; + return stream; +} + +std::ostream& o2::emcal::operator<<(std::ostream& stream, const o2::emcal::CompressedTriggerPatch& patch) +{ + stream << "Patch " << patch.mPatchIndexInTRU << " in TRU " << patch.mTRUIndex << ": Time " << patch.mTime << ", ADC " << patch.mADC; + return stream; +} + +std::ostream& o2::emcal::operator<<(std::ostream& stream, const o2::emcal::CompressedL0TimeSum& timesum) +{ + stream << "FastOR " << timesum.mIndex << ": " << timesum.mTimesum << " ADC counts"; + return stream; +} \ No newline at end of file diff --git a/Detectors/EMCAL/base/include/EMCALBase/TriggerMappingV2.h b/Detectors/EMCAL/base/include/EMCALBase/TriggerMappingV2.h index 3b56c1794d3e4..24d8c1686f005 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/TriggerMappingV2.h +++ b/Detectors/EMCAL/base/include/EMCALBase/TriggerMappingV2.h @@ -49,6 +49,7 @@ class TriggerMappingV2 static constexpr unsigned int FASTORSPHI = (5 * FASTORSPHISM) + (1 * FASTORSPHISM / 3) /*EMCAL*/ + (3 * FASTORSPHISM) + (1 * FASTORSPHISM / 3) /*DCAL */; ///< Number of FastOR/EMCALs in Phi static constexpr unsigned int ALLFASTORS = FASTORSETA * FASTORSPHI; ///< Number of FastOR/EMCALs + static constexpr unsigned int PATCHESINTRU = 77; //******************************************** // Index types diff --git a/Detectors/EMCAL/base/src/TriggerMappingV2.cxx b/Detectors/EMCAL/base/src/TriggerMappingV2.cxx index 5d5ee46dc6f2f..e60d7b31e5305 100644 --- a/Detectors/EMCAL/base/src/TriggerMappingV2.cxx +++ b/Detectors/EMCAL/base/src/TriggerMappingV2.cxx @@ -390,7 +390,7 @@ TriggerMappingV2::IndexTRU TriggerMappingV2::getTRUIndexFromOnlineHardareAddree( unsigned short branch = (hardwareAddress >> 11) & 0x1; // 0/1 - IndexTRU truIndex = ((ddlID << 1) | branch) - 1; // 0..2 + IndexTRU truIndex = (((ddlID % 2) << 1) | branch) - 1; // 0..2 truIndex = (supermoduleID % 2) ? 2 - truIndex : truIndex; diff --git a/Detectors/EMCAL/reconstruction/CMakeLists.txt b/Detectors/EMCAL/reconstruction/CMakeLists.txt index 952db0cf5ba01..983bef1aeba40 100644 --- a/Detectors/EMCAL/reconstruction/CMakeLists.txt +++ b/Detectors/EMCAL/reconstruction/CMakeLists.txt @@ -16,6 +16,7 @@ o2_add_library(EMCALReconstruction src/AltroDecoder.cxx src/Bunch.cxx src/Channel.cxx + src/FastORTimeSeries.cxx src/RecoParam.cxx src/RawDecodingError.cxx src/STUDecoderError.cxx @@ -32,6 +33,7 @@ o2_add_library(EMCALReconstruction src/CTFCoder.cxx src/CTFHelper.cxx src/StuDecoder.cxx + src/TRUDataHandler.cxx PUBLIC_LINK_LIBRARIES O2::Headers AliceO2::InfoLogger O2::DataFormatsEMCAL @@ -49,6 +51,7 @@ o2_target_root_dictionary( include/EMCALReconstruction/RawPayload.h include/EMCALReconstruction/Bunch.h include/EMCALReconstruction/Channel.h + include/EMCALReconstruction/FastORTimeSeries.h include/EMCALReconstruction/CaloFitResults.h include/EMCALReconstruction/CaloRawFitter.h include/EMCALReconstruction/CaloRawFitterStandard.h @@ -59,6 +62,7 @@ o2_target_root_dictionary( include/EMCALReconstruction/DigitReader.h include/EMCALReconstruction/RecoParam.h include/EMCALReconstruction/StuDecoder.h + include/EMCALReconstruction/TRUDataHandler.h ) o2_add_executable(rawreader-file diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/FastORTimeSeries.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/FastORTimeSeries.h new file mode 100644 index 0000000000000..b6dac4a3b3d0c --- /dev/null +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/FastORTimeSeries.h @@ -0,0 +1,83 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef ALICEO2_EMCAL_FASTORTIMESERIES_H +#define ALICEO2_EMCAL_FASTORTIMESERIES_H + +#include +#include +#include "Rtypes.h" + +namespace o2::emcal +{ + +/// \class FastORTimeSeries +/// \brief Container for FastOR time series +/// \author Markus Fasel , Oak Ridge National Laboratory +/// \ingroup EMCALReconstruction +/// \since April 19, 2024 +/// +/// Time series are encoded in bunches in the raw data, which are usually time-reversed. +/// The FastORTimeSeries handles the time series of all bunches in the readout window, +/// in proper future-direction time order, correcting the time-reversal from the Fake-ALTRO. +/// Consequently the ADC samples are expected in time-reversed format. The function +/// calculateL1TimeSum calculates the timesum of the timeseries as 4-integral with respect to +/// a given L0 time, which is expected at the end of the time integration range. +class FastORTimeSeries +{ + public: + /// @brief Dummy constructor + FastORTimeSeries() = default; + + /// \brief Construcor + /// \param maxsamples Maximum number of time samples + /// \param timesamples Time-reversed raw ADC samples + /// \param starttime Start time + FastORTimeSeries(int maxsamples, const gsl::span timesamples, uint8_t starttime) + { + setSize(maxsamples); + fillReversed(timesamples, starttime); + } + + /// \brief Destructor + ~FastORTimeSeries() = default; + + void setTimeSamples(const gsl::span timesamples, uint8_t starttime) { fillReversed(timesamples, starttime); } + + /// \brief Calculate L0 timesum (4-integral of the ADC series) with respect to a given L0 time + /// \param l0time L0 time (end of the time series) + /// \return Timesum of the time series + uint16_t calculateL1TimeSum(uint8_t l0time) const; + + /// \brief Access raw ADC values (in forward time order) + /// \return ADC values of the time series in forward time order + const gsl::span getADCs() const { return mTimeSamples; } + + /// \brief Clear ADC samples in the time series + void clear(); + + private: + /// \brief Set the container size for the ADC samples + /// \param maxsamples Max. amount of samples to be handled + void setSize(int maxsamples); + + /// \brief Fill the internal time samples in proper time order + /// \param timesamples Time-reversed time samples + /// \param starttime Start time + void fillReversed(const gsl::span timesamples, uint8_t starttime); + + std::vector mTimeSamples; ///< Raw ADC time samples (in forward time order) + + ClassDef(FastORTimeSeries, 1); +}; + +} // namespace o2::emcal + +#endif \ No newline at end of file diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RecoContainer.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RecoContainer.h index c1a9fc151a1d5..e02cafd1c3769 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RecoContainer.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RecoContainer.h @@ -14,8 +14,10 @@ /// \author Markus Fasel , Oak Ridge National Laboratory /// \since May 30, 2023 +#include #include #include +#include #include #include #include @@ -24,6 +26,9 @@ #include #include #include +#include +#include +#include namespace o2::emcal { @@ -53,6 +58,36 @@ struct RecCellInfo { class EventContainer { public: + /// \class TRUIndexException + /// \brief Handler for access of TRU data with invalid TRU index + /// \ingroup EMCALReconstruction + class TRUIndexException final : public std::exception + { + public: + /// \brief Constructor + /// \param index TRU index raising the exception + TRUIndexException(std::size_t index); + + /// \brief Destructor + ~TRUIndexException() noexcept final = default; + + /// \brief Get the error message of the exception + /// \return Error message + const char* what() const noexcept final { return mMessage.data(); } + + /// \brief Get the TRU index raising the exception + /// \return TRU index + std::size_t getIndex() const { return mIndex; } + + /// \brief Print error message on stream + /// \param stream Stream to print on + void printStream(std::ostream& stream) const; + + private: + std::size_t mIndex; ///< TRU index raising the exception + std::string mMessage; ///< Buffer for error message + }; + /// \brief Constructor EventContainer() = default; @@ -95,6 +130,22 @@ class EventContainer /// \return Number of LEDMONs int getNumberOfLEDMONs() const { return mLEDMons.size(); } + /// \brief Read and write access TRU data of a given TRU + /// \param truIndex Index of the TRU + /// \return TRU data handler for the TRU + /// \throw TRUIndexException in case the TRU index is invalid (>= 52) + TRUDataHandler& getTRUData(std::size_t truIndex); + + /// \brief Read-only access TRU data of a given TRU + /// \param truIndex Index of the TRU + /// \return TRU data handler for the TRU + /// \throw TRUIndexException in case the TRU index is invalid (>= 52) + const TRUDataHandler& readTRUData(std::size_t truIndex) const; + + /// \brief Access to container with FastOR time series + /// \return Container with time series + const std::unordered_map& getTimeSeriesContainer() const { return mL0FastORs; } + /// \brief Add cell information to the event container /// \param tower Tower ID /// \param energy Cell energy @@ -129,6 +180,16 @@ class EventContainer setCellCommon(tower, energy, time, celltype, true, hwaddress, ddlID, doMergeHGLG); } + /// \brief Add bunch of time series to the container + /// \param fastORAbsID Absolute ID of the FastOR + /// \param starttime Start time of the bunch + /// \param timesamples Time samples of the bunch in time-reversed format + /// + /// In case a TimeSeries is already present for the given FastOR abs. ID in the container + /// the bunch is added to this, otherwise a new TimeSeries is added with the ADCs of the + /// bunch. + void setFastOR(uint16_t fastORAbsID, uint8_t starttime, const gsl::span timesamples); + /// \brief Sort Cells / LEDMONs in container according to tower / module ID /// \param isLEDmon Switch between Cell and LEDMON void sortCells(bool isLEDmon); @@ -148,21 +209,26 @@ class EventContainer /// \return True if the energy is in the saturation region, false otherwise bool isCellSaturated(double energy) const; - o2::InteractionRecord mInteractionRecord; - uint64_t mTriggerBits = 0; ///< Trigger bits of the event - std::vector mCells; ///< Container of cells in event - std::vector mLEDMons; ///< Container of LEDMONs in event + /// \brief Initialize the TRU handlers + void initTRUs(); + + o2::InteractionRecord mInteractionRecord; ///< Interaction record of the event + uint64_t mTriggerBits = 0; ///< Trigger bits of the event + std::vector mCells; ///< Container of cells in event + std::vector mLEDMons; ///< Container of LEDMONs in event + std::array mTRUData; ///< TRU status + std::unordered_map mL0FastORs; ///< L0 FastOR time series }; /// \class RecoContainer -/// \brief Handler for cells in +/// \brief Handler for cells/LEDMONS/Trigger data in timeframes /// \ingroup EMCALReconstruction class RecoContainer { public: /// \class InteractionNotFoundException /// \brief Handling of access to trigger interaction record not present in container - class InteractionNotFoundException : public std::exception + class InteractionNotFoundException final : public std::exception { public: /// \brief Constructor diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/TRUDataHandler.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/TRUDataHandler.h new file mode 100644 index 0000000000000..419e0dc773e36 --- /dev/null +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/TRUDataHandler.h @@ -0,0 +1,185 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef ALICEO2_EMCAL_TRUDataHandler_H +#define ALICEO2_EMCAL_TRUDataHandler_H + +#include +#include +#include +#include +#include +#include + +#include "Rtypes.h" + +#include "EMCALBase/TriggerMappingV2.h" + +namespace o2::emcal +{ + +/// \class TRUDataHandler +/// \brief Helper class to handle decoded TRU data during the reconstruction +/// \author Markus Fasel , Oak Ridge National Laboratory +/// \ingroup EMCALReconstruction +/// \since April 19, 2024 +/// +/// The decoded TRU data contains the following information +/// - Index of the TRU +/// - Trigger time of the TRU +/// - Fired or not +/// - Index of fired patches with time the patch has fired +/// The information is decoded in columns 96 to 105 of the FakeALTRO data. The +/// class does not handle FastOR timesums (colums 0-96), they are handled by a +/// separate class FastORTimeSeries. +class TRUDataHandler +{ + public: + /// \class PatchIndexException + /// \brief Handler of errors related to invalid trigger patch IDs + /// \ingroup EMCALReconstruction + class PatchIndexException final : public std::exception + { + public: + /// \brief Constructor + /// \param index Patch index raising the exception + PatchIndexException(int8_t index); + + /// \brief Destructor + ~PatchIndexException() noexcept final = default; + + /// \brief Get patch index raising the exception + /// \return Patch index + int8_t getIndex() const { return mIndex; } + + /// \brief Access Error message + /// \return Error message + const char* what() const noexcept final + { + return mMessage.data(); + } + + /// \brief Print error on output stream + /// \param stream Stream to be printed to + void printStream(std::ostream& stream) const; + + private: + int8_t mIndex = -1; ///< Patch index rainsing the exception + std::string mMessage; ///< Buffer for error message + }; + + /// \brief Constructor + TRUDataHandler(); + + /// \brief Destructor + ~TRUDataHandler() = default; + + /// \brief Reset handler + void reset(); + + /// \brief Set reconstructed trigger patch + /// \param index Index of the trigger patch in the TRU + /// \param time Decoded time of the patch + /// \throw PatchIndexException in case the patch index is invalid (>= 77) + void setPatch(unsigned int index, unsigned int time) + { + checkPatchIndex(index); + mPatchTimes[index] = time; + } + + /// \brief Mark TRU as fired (containing at least one patch above threshold) + /// \param fired + void setFired(bool fired) { mL0Fired = fired; } + + /// \brief Set the L0 time of the TRU + /// \param l0time L0 time of the TRU + void setL0time(int l0time) { mL0Time = l0time; } + + /// \brief Set the index of the TRU (in global STU indexing scheme) + /// \param index Index of the TRU + void setTRUIndex(int index) { mTRUIndex = index; } + + /// \brief Check whether the TRU was fired (at least one patch above threshold) + /// \return True if the TRU was fired, false otherwise + bool isFired() const { return mL0Fired; } + + int8_t getL0time() const { return mL0Time; } + + /// \brief Check whehther the patch at the given index has fired + /// \param index Index of the patch + /// \return True if the patch has fired, false otherwise + /// \throw PatchIndexException in case the patch index is invalid (>= 77) + bool hasPatch(unsigned int index) const + { + checkPatchIndex(index); + return mPatchTimes[index] < UCHAR_MAX; + } + + /// \brief Get the trigger time of the trigger patch at a given index + /// \param index Index of the trigger patch + /// \return Reconstructed patch time (UCHAR_MAX in case the patch has not fired) + /// \throw PatchIndexException in case the patch index is invalid (>= 77) + uint8_t getPatchTime(unsigned int index) const + { + checkPatchIndex(index); + return mPatchTimes[index]; + } + + /// \brief Check whether the TRU has any patch fired + /// \return True if at least one fired patch was found, false otherwise + bool hasAnyPatch() const + { + for (int ipatch = 0; ipatch < mPatchTimes.size(); ipatch++) { + if (hasPatch(ipatch)) { + return true; + } + } + return false; + } + + /// \brief Get the index of the TRU in global (STU) index schemes + /// \return Index of the TRU + int getTRUIndex() const { return mTRUIndex; } + + /// \brief Print TRU information to an output stream + /// \param stream Stream to print on + void printStream(std::ostream& stream) const; + + private: + /// \brief Check whether the patch index is valid + /// \throw PatchIndexException in case the patch index is invalid (>= 77) + void checkPatchIndex(unsigned int index) const + { + if (index >= mPatchTimes.size()) { + throw PatchIndexException(index); + } + } + + std::array mPatchTimes; ///< Patch times: In case the patch time is smaller than UCHAR_MAX then the patch has fired + bool mL0Fired = false; ///< TRU has fired + int8_t mL0Time = -1; ///< L0 time of the TRU + int8_t mTRUIndex = -1; ///< Index of the TRU + ClassDefNV(TRUDataHandler, 1); +}; + +/// \brief Output stream operator for the TRU data handler +/// \param stream Stream to print on +/// \param data TRU data to be streamed +/// \return Stream after printing +std::ostream& operator<<(std::ostream& stream, const TRUDataHandler& data); + +/// \brief Output stream operator of the PatchIndexException +/// \param stream Stream to print on +/// \param error Error to be streamed +/// \return Stream after printing +std::ostream& operator<<(std::ostream& stream, const TRUDataHandler::PatchIndexException& error); + +} // namespace o2::emcal +#endif diff --git a/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h b/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h index 9482db17c0386..ee39958db5add 100644 --- a/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h +++ b/Detectors/EMCAL/reconstruction/src/EMCALReconstructionLinkDef.h @@ -25,6 +25,8 @@ #pragma link C++ class o2::emcal::CaloRawFitterStandard + ; #pragma link C++ class o2::emcal::CaloRawFitterGamma2 + ; #pragma link C++ class o2::emcal::StuDecoder + ; +#pragma link C++ class o2::emcal::FastORTimeSeries + ; +#pragma link C++ class o2::emcal::TRUDataHandler + ; #pragma link C++ class o2::emcal::RecoParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::emcal::RecoParam> + ; diff --git a/Detectors/EMCAL/reconstruction/src/FastORTimeSeries.cxx b/Detectors/EMCAL/reconstruction/src/FastORTimeSeries.cxx new file mode 100644 index 0000000000000..d23d982047f2b --- /dev/null +++ b/Detectors/EMCAL/reconstruction/src/FastORTimeSeries.cxx @@ -0,0 +1,44 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include +#include "EMCALReconstruction/FastORTimeSeries.h" + +using namespace o2::emcal; + +void FastORTimeSeries::fillReversed(const gsl::span samples, uint8_t starttime) +{ + + for (std::size_t isample = 0; isample < samples.size(); isample++) { + mTimeSamples[starttime - isample] = samples[isample]; + } +} + +uint16_t FastORTimeSeries::calculateL1TimeSum(uint8_t l0time) const +{ + uint16_t timesum = 0; + int firstbin = l0time - 4; // Include sample before the L0 time + for (int isample = firstbin; isample < firstbin + 4; isample++) { + timesum += mTimeSamples[isample]; + } + return timesum; +} + +void FastORTimeSeries::setSize(int maxsamples) +{ + mTimeSamples.resize(maxsamples); +} + +void FastORTimeSeries::clear() +{ + std::fill(mTimeSamples.begin(), mTimeSamples.end(), 0); +} \ No newline at end of file diff --git a/Detectors/EMCAL/reconstruction/src/RecoContainer.cxx b/Detectors/EMCAL/reconstruction/src/RecoContainer.cxx index 4ed49e5876c93..062887287f86b 100644 --- a/Detectors/EMCAL/reconstruction/src/RecoContainer.cxx +++ b/Detectors/EMCAL/reconstruction/src/RecoContainer.cxx @@ -16,7 +16,15 @@ using namespace o2::emcal; -EventContainer::EventContainer(const o2::InteractionRecord& currentIR) : mInteractionRecord(currentIR) {} +EventContainer::EventContainer(const o2::InteractionRecord& currentIR) : mInteractionRecord(currentIR) { initTRUs(); } + +void EventContainer::initTRUs() +{ + for (auto index = 0; index < mTRUData.size(); index++) { + mTRUData[index].setTRUIndex(index); + mTRUData[index].setL0time(INT8_MAX); + } +} void EventContainer::setCellCommon(int tower, double energy, double time, ChannelType_t celltype, bool isLEDmon, int hwaddress, int ddlID, bool doMergeHGLG) { @@ -83,6 +91,16 @@ void EventContainer::setCellCommon(int tower, double energy, double time, Channe } } +void EventContainer::setFastOR(uint16_t fastORAbsID, uint8_t starttime, const gsl::span timesamples) +{ + auto found = mL0FastORs.find(fastORAbsID); + if (found != mL0FastORs.end()) { + found->second.setTimeSamples(timesamples, starttime); + } else { + mL0FastORs[fastORAbsID] = FastORTimeSeries(14, timesamples, starttime); + } +} + void EventContainer::sortCells(bool isLEDmon) { auto& dataContainer = isLEDmon ? mLEDMons : mCells; @@ -94,6 +112,27 @@ bool EventContainer::isCellSaturated(double energy) const return energy / o2::emcal::constants::EMCAL_ADCENERGY > o2::emcal::constants::OVERFLOWCUT; } +TRUDataHandler& EventContainer::getTRUData(std::size_t index) +{ + if (index >= mTRUData.size()) { + throw TRUIndexException(index); + } + return mTRUData[index]; +} + +const TRUDataHandler& EventContainer::readTRUData(std::size_t index) const +{ + if (index >= mTRUData.size()) { + throw TRUIndexException(index); + } + return mTRUData[index]; +} + +EventContainer::TRUIndexException::TRUIndexException(std::size_t index) : mIndex(index), mMessage() +{ + mMessage = "Invalid TRU index " + std::to_string(index); +} + EventContainer& RecoContainer::getEventContainer(const o2::InteractionRecord& currentIR) { auto found = mEvents.find(currentIR); diff --git a/Detectors/EMCAL/reconstruction/src/TRUDataHandler.cxx b/Detectors/EMCAL/reconstruction/src/TRUDataHandler.cxx new file mode 100644 index 0000000000000..d6d9bd3535d5c --- /dev/null +++ b/Detectors/EMCAL/reconstruction/src/TRUDataHandler.cxx @@ -0,0 +1,67 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include "EMCALReconstruction/TRUDataHandler.h" + +using namespace o2::emcal; + +TRUDataHandler::TRUDataHandler() +{ + reset(); +} + +void TRUDataHandler::reset() +{ + mTRUIndex = -1; + mL0Fired = false; + mL0Time = -1; + std::fill(mPatchTimes.begin(), mPatchTimes.end(), UCHAR_MAX); +} + +void TRUDataHandler::printStream(std::ostream& stream) const +{ + std::string patchstring; + for (auto index = 0; index < mPatchTimes.size(); index++) { + if (hasPatch(index)) { + if (patchstring.length()) { + patchstring += ", "; + } + patchstring += std::to_string(index); + } + } + if (!patchstring.length()) { + patchstring = "-"; + } + stream << "TRU: " << static_cast(mTRUIndex) << ", time " << static_cast(mL0Time) << ", fired: " << (mL0Fired ? "yes" : "no") << ", patches: " << patchstring; +} + +TRUDataHandler::PatchIndexException::PatchIndexException(int8_t index) : mIndex(index), mMessage() +{ + mMessage = "Invalid patch index " + std::to_string(index); +} + +void TRUDataHandler::PatchIndexException::printStream(std::ostream& stream) const +{ + stream << what(); +} + +std::ostream& o2::emcal::operator<<(std::ostream& stream, const TRUDataHandler& data) +{ + data.printStream(stream); + return stream; +} + +std::ostream& o2::emcal::operator<<(std::ostream& stream, const TRUDataHandler::PatchIndexException& error) +{ + error.printStream(stream); + return stream; +} \ No newline at end of file diff --git a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h index a90a0f1718397..a418858c0b578 100644 --- a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h +++ b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h @@ -20,10 +20,12 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" #include "DataFormatsEMCAL/Cell.h" +#include "DataFormatsEMCAL/CompressedTriggerData.h" #include "DataFormatsEMCAL/TriggerRecord.h" #include "Headers/DataHeader.h" #include "EMCALBase/Geometry.h" #include "EMCALBase/Mapper.h" +#include "EMCALBase/TriggerMappingV2.h" #include "EMCALReconstruction/CaloRawFitter.h" #include "EMCALReconstruction/RawReaderMemory.h" #include "EMCALReconstruction/RecoContainer.h" @@ -37,6 +39,7 @@ namespace emcal { class AltroDecoderError; +class Channel; class MinorAltroDecodingError; class RawDecodingError; @@ -54,9 +57,9 @@ class RawToCellConverterSpec : public framework::Task /// \brief Constructor /// \param subspecification Output subspecification for parallel running on multiple nodes /// \param hasDecodingErrors Option to swich on/off creating raw decoding error objects for later monitoring - /// \param loadRecoParamsFromCCDB Option to load the RecoParams from the CCDB + /// \param hasTriggerReconstruction Perform trigger reconstruction and add trigger-related outputs /// \param calibhandler Calibration object handler - RawToCellConverterSpec(int subspecification, bool hasDecodingErrors, std::shared_ptr calibhandler) : framework::Task(), mSubspecification(subspecification), mCreateRawDataErrors(hasDecodingErrors), mCalibHandler(calibhandler){}; + RawToCellConverterSpec(int subspecification, bool hasDecodingErrors, bool hasTriggerReconstruction, std::shared_ptr calibhandler) : framework::Task(), mSubspecification(subspecification), mCreateRawDataErrors(hasDecodingErrors), mDoTriggerReconstruction(hasTriggerReconstruction), mCalibHandler(calibhandler){}; /// \brief Destructor ~RawToCellConverterSpec() override; @@ -88,7 +91,12 @@ class RawToCellConverterSpec : public framework::Task mMaxErrorMessages = maxMessages; } - void setNoiseThreshold(int thresold) { mNoiseThreshold = thresold; } + /// \brief Set noise threshold for gain type errors + /// \param threshold Noise threshold + void setNoiseThreshold(int threshold) { mNoiseThreshold = threshold; } + + /// \brief Get the noise threshold for gain type errors + /// \return Noise threshold int getNoiseThreshold() const { return mNoiseThreshold; } /// \brief Set ID of the subspecification @@ -170,6 +178,32 @@ class RawToCellConverterSpec : public framework::Task int mRowShifted = -1; /// << shifted row of the module (cell-case) }; + /// \struct CellTimeCorrection + /// \brief Correction for cell time + struct CellTimeCorrection { + double mTimeShift; ///< Constant time shift + int mBcMod4; ///< BC-dependent shift + + /// \brief Get the corrected cell time + /// \param rawtime Raw time from fit + /// \return Corrected time + /// + /// The time is corrected for an average shift and the BC phase + double getCorrectedTime(double rawtime) const { return rawtime - mTimeShift - 25. * mBcMod4; } + }; + + /// \struct LocalPosition + /// \brief Position in the supermodule coordinate system + struct LocalPosition { + uint16_t mSupermoduleID; ///< Supermodule ID + uint16_t mFeeID; ///< FEE ID + uint8_t mColumn; ///< Column in supermodule + uint8_t mRow; ///< Row in supermodule + }; + + using TRUContainer = std::vector; + using PatchContainer = std::vector; + /// \brief Check if the timeframe is empty /// \param ctx Processing context of timeframe /// \return True if the timeframe is empty, false otherwise @@ -193,14 +227,12 @@ class RawToCellConverterSpec : public framework::Task int bookEventCells(const gsl::span& cells, bool isLELDMON); /// \brief Send data to output channels - /// \param cells Container with output cells for timeframe - /// \param triggers Container with trigger records for timeframe - /// \param decodingErrors Container with decoding errors for timeframe + /// \param ctx target processing context /// /// Send data to all output channels for the given subspecification. The subspecification /// is determined on the fly in the run method and therefore used as parameter. Consumers /// must use wildcard subspecification via ConcreteDataTypeMatcher. - void sendData(framework::ProcessingContext& ctx, const std::vector& cells, const std::vector& triggers, const std::vector& decodingErrors) const; + void sendData(framework::ProcessingContext& ctx) const; /// \brief Get absolute Cell ID from column/row in supermodule /// \param supermoduleID Index of the supermodule @@ -217,6 +249,54 @@ class RawToCellConverterSpec : public framework::Task /// \throw ModuleIndexException in case of invalid module indices int geLEDMONAbsID(int supermoduleID, int module); + /// \brief Add FEE channel to the current evnet + /// \param currentEvent Event to add the channel to + /// \param currentchannel Current FEE channel + /// \param timeCorrector Handler for correction of the time + /// \param position Channel coordinates + /// \param chantype Channel type (High Gain, Low Gain, LEDMON) + /// + /// Performing a raw fit of the bunches in the channel to extract energy and time, and + /// adding them to the container for FEE data of the given event. + void addFEEChannelToEvent(o2::emcal::EventContainer& currentEvent, const o2::emcal::Channel& currentchannel, const CellTimeCorrection& timeCorrector, const LocalPosition& position, ChannelType_t chantype); + + /// \brief Add TRU channel to the event + /// \param currentEvent Event to add the channel to + /// \param currentchannel Current TRU channel + /// \param position Channel coordinates + /// + /// TRU channels are encoded in colums: + /// - 0-95: FastOR timeseries (time-reversed) + /// - 96-105: bitmap with fired patches and TRU header + /// The TRU index is taken from the hardware address, while the FastOR index is taken from the + /// column number. The TRU and patch times are taken from the time sample in which the corresponding + /// bit is found. + void addTRUChannelToEvent(o2::emcal::EventContainer& currentEvent, const o2::emcal::Channel& currentchannel, const LocalPosition& position); + + /// @brief Build L0 patches from FastOR time series and TRU data of the current event + /// @param currentevent Current event to process + /// @return Compressed patches + /// + /// Only reconstruct patches which were decoded as fired from the raw data. The patch energy and time + /// are calculated from the corresponding FastOR time series as the energy and time with the largest + /// patch energy extracted from all possible time integrals (see reconstructTriggerPatch) + std::tuple buildL0Patches(const EventContainer& currentevent) const; + + /// @brief Build L0 timesums with respect to a given L0 time + /// @param currentevent Current event with FastOR time series + /// @param l0time L0 time of the event + /// @return Container with time series + std::vector buildL0Timesums(const o2::emcal::EventContainer& currentevent, uint8_t l0time) const; + + /// \brief Reconstruct trigger patch energy and time from its FastOR time series + /// \param fastors FastORs contributing to the patch (only present) + /// \return Tuple with 0 - patch ADC, 1 - patch time + /// + /// For all possible combinations reconstruct the 4-time integral of the patches from + /// its contributing FastORs. The patch is reconstructed when the ADC reached its + /// maximum. The patch time is the start time of the 4-integral + std::tuple reconstructTriggerPatch(const gsl::span fastors) const; + void handleAddressError(const Mapper::AddressNotFoundException& error, int ddlID, int hwaddress); void handleAltroError(const o2::emcal::AltroDecoderError& altroerror, int ddlID); @@ -249,24 +329,33 @@ class RawToCellConverterSpec : public framework::Task bool mPrintTrailer = false; ///< Print RCU trailer bool mDisablePedestalEvaluation = false; ///< Disable pedestal evaluation independent of settings in the RCU trailer bool mCreateRawDataErrors = false; ///< Create raw data error objects for monitoring + bool mDoTriggerReconstruction = false; ///< Do trigger reconstruction std::chrono::time_point mReferenceTime; ///< Reference time for muting messages Geometry* mGeometry = nullptr; ///! mCalibHandler; ///< Handler for calibration objects std::unique_ptr mMapper = nullptr; ///! mTriggerMapping; ///! mRawFitter; ///! mOutputCells; ///< Container with output cells - std::vector mOutputTriggerRecords; ///< Container with output cells + std::vector mOutputTriggerRecords; ///< Container with output trigger records for cells std::vector mOutputDecoderErrors; ///< Container with decoder errors + std::vector mOutputTRUs; ///< Compressed output TRU information + std::vector mOutputTRUTriggerRecords; ///< Container with trigger records for TRU data + std::vector mOutputPatches; ///< Compressed trigger patch information + std::vector mOutputPatchTriggerRecords; ///< Container with trigger records for Patch data + std::vector mOutputTimesums; ///< Compressed L0 timesum information + std::vector mOutputTimesumTriggerRecords; ///< Trigger records for L0 timesum }; /// \brief Creating DataProcessorSpec for the EMCAL Cell Converter Spec /// \param askDISTSTF Include input spec FLP/DISTSUBTIMEFRAME -/// \param loadRecoParamsFromCCDB Obtain reco params from the CCDB +/// \param disableDecodingErrors Obtain reco params from the CCDB +/// \param disableTriggerReconstruction Do not run trigger reconstruction /// \param subspecification Subspecification used in the output spec /// /// Refer to RawToCellConverterSpec::run for input and output specs -framework::DataProcessorSpec getRawToCellConverterSpec(bool askDISTSTF, bool disableDecodingError, int subspecification); +framework::DataProcessorSpec getRawToCellConverterSpec(bool askDISTSTF, bool disableDecodingError, bool disableTriggerReconstruction, int subspecification); } // namespace reco_workflow diff --git a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RecoWorkflow.h b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RecoWorkflow.h index 1cc0544d3c61d..909e356297095 100644 --- a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RecoWorkflow.h +++ b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RecoWorkflow.h @@ -55,6 +55,7 @@ enum struct OutputType { Digits, ///< EMCAL digits /// \param disableRootInput Disable reading from ROOT file (raw mode) /// \param disableRootOutput Disable writing ROOT files (sync reco) /// \param disableDecodingErrors Diable streaming raw decoding errors (async reco) +/// \param disableTriggerReconstruction Disable trigger reconstrction /// \return EMCAL reconstruction workflow for the configuration provided /// \ingroup EMCALwokflow framework::WorkflowSpec getWorkflow(bool propagateMC = true, @@ -66,7 +67,8 @@ framework::WorkflowSpec getWorkflow(bool propagateMC = true, std::string const& cfgOutput = "clusters", bool disableRootInput = false, bool disableRootOutput = false, - bool disableDecodingErrors = false); + bool disableDecodingErrors = false, + bool disableTriggerReconstruction = false); } // namespace reco_workflow } // namespace emcal diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index 35fb95e010040..4e90aef881415 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -75,6 +76,10 @@ void RawToCellConverterSpec::init(framework::InitContext& ctx) LOG(error) << "Failed to initialize mapper"; } + if (!mTriggerMapping) { + mTriggerMapping = std::make_unique(mGeometry); + } + auto fitmethod = ctx.options().get("fitmethod"); if (fitmethod == "standard") { LOG(info) << "Using standard raw fitter"; @@ -131,9 +136,15 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) mOutputCells.clear(); mOutputTriggerRecords.clear(); mOutputDecoderErrors.clear(); + mOutputTRUs.clear(); + mOutputTRUTriggerRecords.clear(); + mOutputPatches.clear(); + mOutputPatchTriggerRecords.clear(); + mOutputTimesums.clear(); + mOutputTimesumTriggerRecords.clear(); if (isLostTimeframe(ctx)) { - sendData(ctx, mOutputCells, mOutputTriggerRecords, mOutputDecoderErrors); + sendData(ctx); return; } @@ -216,6 +227,7 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) if (!currentEvent.getTriggerBits()) { currentEvent.setTriggerBits(triggerbits); } + CellTimeCorrection timeCorrector{timeshift, bcmod4}; if (feeID >= 40) { continue; // skip STU ddl @@ -268,68 +280,33 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) // Loop over all the channels int nBunchesNotOK = 0; for (auto& chan : decoder.getChannels()) { - int iRow, iCol; - ChannelType_t chantype; try { - iRow = map.getRow(chan.getHardwareAddress()); - iCol = map.getColumn(chan.getHardwareAddress()); - chantype = map.getChannelType(chan.getHardwareAddress()); + auto iRow = map.getRow(chan.getHardwareAddress()); + auto iCol = map.getColumn(chan.getHardwareAddress()); + auto chantype = map.getChannelType(chan.getHardwareAddress()); + LocalPosition channelPosition{iSM, feeID, iCol, iRow}; + switch (chantype) { + case o2::emcal::ChannelType_t::HIGH_GAIN: + case o2::emcal::ChannelType_t::LOW_GAIN: + addFEEChannelToEvent(currentEvent, chan, timeCorrector, channelPosition, chantype); + break; + case o2::emcal::ChannelType_t::LEDMON: + // Drop LEDMON reconstruction in case of physics triggers + if (triggerbits & o2::trigger::Cal) { + addFEEChannelToEvent(currentEvent, chan, timeCorrector, channelPosition, chantype); + } + break; + case o2::emcal::ChannelType_t::TRU: + addTRUChannelToEvent(currentEvent, chan, channelPosition); + break; + default: + LOG(error) << "Unknown channel type for HW address " << chan.getHardwareAddress(); + break; + } } catch (Mapper::AddressNotFoundException& ex) { handleAddressError(ex, feeID, chan.getHardwareAddress()); continue; } - - if (!(chantype == o2::emcal::ChannelType_t::HIGH_GAIN || chantype == o2::emcal::ChannelType_t::LOW_GAIN || chantype == o2::emcal::ChannelType_t::LEDMON)) { - continue; - } - - // Drop LEDMON reconstruction in case of physics triggers - if (chantype == o2::emcal::ChannelType_t::LEDMON && !(triggerbits & o2::trigger::Cal)) { - continue; - } - - int CellID = -1; - bool isLowGain = false; - try { - if (chantype == o2::emcal::ChannelType_t::HIGH_GAIN || chantype == o2::emcal::ChannelType_t::LOW_GAIN) { - // high- / low-gain cell - CellID = getCellAbsID(iSM, iCol, iRow); - isLowGain = chantype == o2::emcal::ChannelType_t::LOW_GAIN; - } else { - CellID = geLEDMONAbsID(iSM, iCol); // Module index encoded in colum for LEDMONs - isLowGain = iRow == 0; // For LEDMONs gain type is encoded in the row (0 - low gain, 1 - high gain) - } - } catch (ModuleIndexException& e) { - handleGeometryError(e, iSM, CellID, chan.getHardwareAddress(), chantype); - continue; - } - - // define the conatiner for the fit results, and perform the raw fitting using the stadnard raw fitter - CaloFitResults fitResults; - try { - fitResults = mRawFitter->evaluate(chan.getBunches()); - // Prevent negative entries - we should no longer get here as the raw fit usually will end in an error state - if (fitResults.getAmp() < 0) { - fitResults.setAmp(0.); - } - if (fitResults.getTime() < 0) { - fitResults.setTime(0.); - } - // apply correction for bc mod 4 - double celltime = fitResults.getTime() - timeshift - 25 * bcmod4; - double amp = fitResults.getAmp() * o2::emcal::constants::EMCAL_ADCENERGY; - if (isLowGain) { - amp *= o2::emcal::constants::EMCAL_HGLGFACTOR; - } - if (chantype == o2::emcal::ChannelType_t::LEDMON) { - // Mark LEDMONs as HIGH_GAIN/LOW_GAIN for gain type merging - will be flagged as LEDMON later when pushing to the output container - currentEvent.setLEDMONCell(CellID, amp, celltime, isLowGain ? o2::emcal::ChannelType_t::LOW_GAIN : o2::emcal::ChannelType_t::HIGH_GAIN, chan.getHardwareAddress(), feeID, mMergeLGHG); - } else { - currentEvent.setCell(CellID, amp, celltime, chantype, chan.getHardwareAddress(), feeID, mMergeLGHG); - } - } catch (CaloRawFitter::RawFitterError_t& fiterror) { - handleFitError(fiterror, feeID, CellID, chan.getHardwareAddress()); - } } } catch (o2::emcal::MappingHandler::DDLInvalid& ddlerror) { // Unable to catch mapping @@ -400,10 +377,31 @@ void RawToCellConverterSpec::run(framework::ProcessingContext& ctx) } LOG(debug) << "Next event [Orbit " << interaction.orbit << ", BC (" << interaction.bc << "]: Accepted " << ncellsEvent << " cells and " << nLEDMONsEvent << " LEDMONS"; mOutputTriggerRecords.emplace_back(interaction, currentevent.getTriggerBits(), eventstart, ncellsEvent + nLEDMONsEvent); + + // Add trigger data + if (mDoTriggerReconstruction) { + auto [trus, patches] = buildL0Patches(currentevent); + LOG(debug) << "Found " << patches.size() << " L0 patches from " << trus.size() << " TRUs"; + auto trusstart = mOutputTRUs.size(); + std::copy(trus.begin(), trus.end(), std::back_inserter(mOutputTRUs)); + mOutputTRUTriggerRecords.emplace_back(interaction, currentevent.getTriggerBits(), trusstart, trus.size()); + auto patchesstart = mOutputPatches.size(); + std::copy(patches.begin(), patches.end(), std::back_inserter(mOutputPatches)); + mOutputPatchTriggerRecords.emplace_back(interaction, currentevent.getTriggerBits(), patchesstart, patches.size()); + // For L0 timesums use fixed time, across TRUs and triggers, determined from the patch time QC + // average found to be - will be made configurable + auto timesumsstart = mOutputTimesums.size(); + auto timesums = buildL0Timesums(currentevent, 8); + std::copy(timesums.begin(), timesums.end(), std::back_inserter(mOutputTimesums)); + mOutputTimesumTriggerRecords.emplace_back(interaction, currentevent.getTriggerBits(), timesumsstart, timesums.size()); + } } LOG(info) << "[EMCALRawToCellConverter - run] Writing " << mOutputCells.size() << " cells from " << mOutputTriggerRecords.size() << " events ..."; - sendData(ctx, mOutputCells, mOutputTriggerRecords, mOutputDecoderErrors); + if (mDoTriggerReconstruction) { + LOG(info) << "[EMCALRawToCellConverter - run] Writing " << mOutputTRUs.size() << " TRU infos and " << mOutputPatches.size() << " trigger patches and " << mOutputTimesums.size() << " timesums from " << mOutputTRUTriggerRecords.size() << " events ..."; + } + sendData(ctx); } void RawToCellConverterSpec::finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj) @@ -449,6 +447,197 @@ bool RawToCellConverterSpec::isLostTimeframe(framework::ProcessingContext& ctx) return false; } +void RawToCellConverterSpec::addFEEChannelToEvent(o2::emcal::EventContainer& currentEvent, const o2::emcal::Channel& currentchannel, const CellTimeCorrection& timeCorrector, const LocalPosition& position, ChannelType_t chantype) +{ + int CellID = -1; + bool isLowGain = false; + try { + if (chantype == o2::emcal::ChannelType_t::HIGH_GAIN || chantype == o2::emcal::ChannelType_t::LOW_GAIN) { + // high- / low-gain cell + CellID = getCellAbsID(position.mSupermoduleID, position.mColumn, position.mRow); + isLowGain = chantype == o2::emcal::ChannelType_t::LOW_GAIN; + } else { + CellID = geLEDMONAbsID(position.mSupermoduleID, position.mColumn); // Module index encoded in colum for LEDMONs + isLowGain = position.mRow == 0; // For LEDMONs gain type is encoded in the row (0 - low gain, 1 - high gain) + } + } catch (ModuleIndexException& e) { + handleGeometryError(e, position.mSupermoduleID, CellID, currentchannel.getHardwareAddress(), chantype); + return; + } + + // define the conatiner for the fit results, and perform the raw fitting using the stadnard raw fitter + CaloFitResults fitResults; + try { + fitResults = mRawFitter->evaluate(currentchannel.getBunches()); + // Prevent negative entries - we should no longer get here as the raw fit usually will end in an error state + if (fitResults.getAmp() < 0) { + fitResults.setAmp(0.); + } + if (fitResults.getTime() < 0) { + fitResults.setTime(0.); + } + // apply correction for bc mod 4 + double celltime = timeCorrector.getCorrectedTime(fitResults.getTime()); + double amp = fitResults.getAmp() * o2::emcal::constants::EMCAL_ADCENERGY; + if (isLowGain) { + amp *= o2::emcal::constants::EMCAL_HGLGFACTOR; + } + if (chantype == o2::emcal::ChannelType_t::LEDMON) { + // Mark LEDMONs as HIGH_GAIN/LOW_GAIN for gain type merging - will be flagged as LEDMON later when pushing to the output container + currentEvent.setLEDMONCell(CellID, amp, celltime, isLowGain ? o2::emcal::ChannelType_t::LOW_GAIN : o2::emcal::ChannelType_t::HIGH_GAIN, currentchannel.getHardwareAddress(), position.mFeeID, mMergeLGHG); + } else { + currentEvent.setCell(CellID, amp, celltime, chantype, currentchannel.getHardwareAddress(), position.mFeeID, mMergeLGHG); + } + } catch (CaloRawFitter::RawFitterError_t& fiterror) { + handleFitError(fiterror, position.mFeeID, CellID, currentchannel.getHardwareAddress()); + } +} + +void RawToCellConverterSpec::addTRUChannelToEvent(o2::emcal::EventContainer& currentEvent, const o2::emcal::Channel& currentchannel, const LocalPosition& position) +{ + auto tru = mTriggerMapping->getTRUIndexFromOnlineHardareAddree(currentchannel.getHardwareAddress(), position.mFeeID, position.mSupermoduleID); + if (position.mColumn >= 96 && position.mColumn <= 105) { + auto& trudata = currentEvent.getTRUData(tru); + // Trigger patch information encoded columns 95-105 + for (auto& bunch : currentchannel.getBunches()) { + LOG(debug) << "Found bunch of length " << static_cast(bunch.getBunchLength()) << " with start time " << static_cast(bunch.getStartTime()) << " (column " << static_cast(position.mColumn) << ")"; + auto l0time = bunch.getStartTime(); + int isample = 0; + for (auto& adc : bunch.getADC()) { + // patch word might be in any of the samples, need to check all of them + // in case of colum 105 the first 6 bits are the patch word, the remaining 4 bits are the header word + if (adc == 0) { + isample++; + continue; + } + if (position.mColumn == 105) { + std::bitset<6> patchBits(adc & 0x3F); + std::bitset<4> headerbits((adc >> 6) & 0xF); + for (auto localindex = 0; localindex < patchBits.size(); localindex++) { + if (patchBits.test(localindex)) { + auto globalindex = (position.mColumn - 96) * 10 + localindex; + LOG(debug) << "Found patch with index " << globalindex << " in sample " << isample; + // std::cout << "Found patch with index " << globalindex << " in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; + trudata.setPatch(globalindex, bunch.getStartTime() - isample); + } + } + if (headerbits.test(2)) { + LOG(debug) << "TRU " << tru << ": Found TRU fired (" << tru << ") in sample " << isample; + // std::cout << "TRU " << tru << ": Found TRU fired (" << tru << ") in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; + trudata.setFired(true); + trudata.setL0time(bunch.getStartTime() - isample); + } + } else { + std::bitset<10> patchBits(adc & 0x3FF); + for (auto localindex = 0; localindex < patchBits.size(); localindex++) { + if (patchBits.test(localindex)) { + auto globalindex = (position.mColumn - 96) * 10 + localindex; + LOG(debug) << "TRU " << tru << ": Found patch with index " << globalindex << " in sample " << isample; + // std::cout << "TRU " << tru << ": Found patch with index " << globalindex << " in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; + trudata.setPatch(globalindex, bunch.getStartTime() - isample); + } + } + } + isample++; + } + } + } else { + auto absFastOR = mTriggerMapping->getAbsFastORIndexFromIndexInTRU(tru, position.mColumn); + for (auto& bunch : currentchannel.getBunches()) { + // FastOR data reversed internally (positive in time direction) + // -> Start time marks the first timebin, consequently it must be also reversed. + // std::cout << "Adding non-reversed FastOR time series for FastOR " << absFastOR << " (TRU " << tru << ", index " << static_cast(position.mColumn) << ") with start time " << static_cast(bunch.getStartTime()) << " (reversed " << bunch.getStartTime() + 1 - bunch.getADC().size() << "): "; + // for (auto adc : bunch.getADC()) { + // std::cout << adc << ", "; + //} + // std::cout << std::endl; + currentEvent.setFastOR(absFastOR, bunch.getStartTime(), bunch.getADC()); + } + } +} + +std::tuple RawToCellConverterSpec::buildL0Patches(const EventContainer& currentevent) const +{ + LOG(debug) << "Reconstructing patches for Orbit " << currentevent.getInteractionRecord().orbit << ", BC " << currentevent.getInteractionRecord().bc; + TRUContainer eventTRUs; + PatchContainer eventPatches; + auto& fastOrs = currentevent.getTimeSeriesContainer(); + std::set foundFastOrs; + for (auto fastor : fastOrs) { + foundFastOrs.insert(fastor.first); + } + for (std::size_t itru = 0; itru < TriggerMappingV2::ALLTRUS; itru++) { + auto& currenttru = currentevent.readTRUData(itru); + if (!currenttru.hasAnyPatch()) { + continue; + } + auto l0time = currenttru.getL0time(); + LOG(debug) << "Found patches in TRU " << itru << ", fired: " << (currenttru.isFired() ? "yes" : "no") << ", L0 time " << static_cast(l0time); + uint8_t npatches = 0; + for (auto ipatch = 0; ipatch < o2::emcal::TriggerMappingV2::PATCHESINTRU; ipatch++) { + if (currenttru.hasPatch(ipatch)) { + auto patchtime = currenttru.getPatchTime(ipatch); + LOG(debug) << "Found patch " << ipatch << " in TRU " << itru << " with time " << static_cast(patchtime); + auto fastorStart = mTriggerMapping->getAbsFastORIndexFromIndexInTRU(itru, ipatch); + auto fastORs = mTriggerMapping->getFastORIndexFromL0Index(itru, ipatch, 4); + std::array fastors; + std::fill(fastors.begin(), fastors.end(), nullptr); + int indexFastorInTRU = 0; + for (auto fastor : fastORs) { + auto [truID, fastorTRU] = mTriggerMapping->getTRUFromAbsFastORIndex(fastor); + // std::cout << "Patch has abs FastOR " << fastor << " -> " << fastorTRU << " (in TRU)" << std::endl; + auto timeseriesFound = fastOrs.find(fastor); + if (timeseriesFound != fastOrs.end()) { + LOG(debug) << "Adding FastOR (" << indexFastorInTRU << ") with index " << fastor << " to patch"; + fastors[indexFastorInTRU] = &(timeseriesFound->second); + indexFastorInTRU++; + } + } + auto [patchADC, recpatchtime] = reconstructTriggerPatch(fastors); + // Correct for bit shift 12->10 bits due to ALTRO format + patchADC = patchADC << 2; + LOG(debug) << "Reconstructed patch at index " << ipatch << " with peak time " << static_cast(recpatchtime) << " (time sample " << static_cast(patchtime) << ") and energy " << patchADC; + eventPatches.push_back({static_cast(itru), static_cast(ipatch), patchtime, patchADC}); + } + } + eventTRUs.push_back({static_cast(itru), static_cast(l0time), currenttru.isFired(), npatches}); + } + return std::make_tuple(eventTRUs, eventPatches); +} + +std::vector RawToCellConverterSpec::buildL0Timesums(const o2::emcal::EventContainer& currentevent, uint8_t l0time) const +{ + std::vector timesums; + for (const auto& [fastorID, timeseries] : currentevent.getTimeSeriesContainer()) { + timesums.push_back({fastorID, static_cast(timeseries.calculateL1TimeSum(l0time) << 2)}); + } + return timesums; +} + +std::tuple RawToCellConverterSpec::reconstructTriggerPatch(const gsl::span fastors) const +{ + constexpr size_t INTEGRATE_SAMPLES = 4, + MAX_SAMPLES = 12; + double maxpatchenergy = 0; + uint8_t foundtime = 0; + for (size_t itime = 0; itime < MAX_SAMPLES - INTEGRATE_SAMPLES; ++itime) { + double currenttimesum = 0; + for (size_t isample = 0; isample < INTEGRATE_SAMPLES; ++isample) { + for (auto ifastor = 0; ifastor < fastors.size(); ++ifastor) { + if (fastors[ifastor]) { + currenttimesum += fastors[ifastor]->getADCs()[itime + isample]; + } + } + } + if (currenttimesum > maxpatchenergy) { + maxpatchenergy = currenttimesum; + foundtime = itime; + } + } + + return std::make_tuple(maxpatchenergy, foundtime); +} + int RawToCellConverterSpec::bookEventCells(const gsl::span& cells, bool isLELDMON) { double noiseThresholLGnoHG = RecoParam::Instance().getNoiseThresholdLGnoHG(); @@ -719,14 +908,22 @@ void RawToCellConverterSpec::handleMinorPageError(const RawReaderMemory::MinorEr } } -void RawToCellConverterSpec::sendData(framework::ProcessingContext& ctx, const std::vector& cells, const std::vector& triggers, const std::vector& decodingErrors) const +void RawToCellConverterSpec::sendData(framework::ProcessingContext& ctx) const { constexpr auto originEMC = o2::header::gDataOriginEMC; - ctx.outputs().snapshot(framework::Output{originEMC, "CELLS", mSubspecification}, cells); - ctx.outputs().snapshot(framework::Output{originEMC, "CELLSTRGR", mSubspecification}, triggers); + ctx.outputs().snapshot(framework::Output{originEMC, "CELLS", mSubspecification}, mOutputCells); + ctx.outputs().snapshot(framework::Output{originEMC, "CELLSTRGR", mSubspecification}, mOutputTriggerRecords); if (mCreateRawDataErrors) { - LOG(debug) << "Sending " << decodingErrors.size() << " decoding errors"; - ctx.outputs().snapshot(framework::Output{originEMC, "DECODERERR", mSubspecification}, decodingErrors); + LOG(debug) << "Sending " << mOutputDecoderErrors.size() << " decoding errors"; + ctx.outputs().snapshot(framework::Output{originEMC, "DECODERERR", mSubspecification}, mOutputDecoderErrors); + } + if (mDoTriggerReconstruction) { + ctx.outputs().snapshot(framework::Output{originEMC, "TRUS", mSubspecification}, mOutputTRUs); + ctx.outputs().snapshot(framework::Output{originEMC, "TRUSTRGR", mSubspecification}, mOutputTRUTriggerRecords); + ctx.outputs().snapshot(framework::Output{originEMC, "PATCHES", mSubspecification}, mOutputPatches); + ctx.outputs().snapshot(framework::Output{originEMC, "PATCHESTRGR", mSubspecification}, mOutputPatchTriggerRecords); + ctx.outputs().snapshot(framework::Output{originEMC, "FASTORS", mSubspecification}, mOutputTimesums); + ctx.outputs().snapshot(framework::Output{originEMC, "FASTORSTRGR", mSubspecification}, mOutputTimesumTriggerRecords); } } @@ -739,7 +936,7 @@ RawToCellConverterSpec::ModuleIndexException::ModuleIndexException(int moduleInd RawToCellConverterSpec::ModuleIndexException::ModuleIndexException(int moduleIndex) : mModuleType(ModuleType_t::LEDMON_MODULE), mIndex(moduleIndex) {} -o2::framework::DataProcessorSpec o2::emcal::reco_workflow::getRawToCellConverterSpec(bool askDISTSTF, bool disableDecodingErrors, int subspecification) +o2::framework::DataProcessorSpec o2::emcal::reco_workflow::getRawToCellConverterSpec(bool askDISTSTF, bool disableDecodingErrors, bool disableTriggerReconstruction, int subspecification) { constexpr auto originEMC = o2::header::gDataOriginEMC; std::vector outputs; @@ -749,6 +946,14 @@ o2::framework::DataProcessorSpec o2::emcal::reco_workflow::getRawToCellConverter if (!disableDecodingErrors) { outputs.emplace_back(originEMC, "DECODERERR", subspecification, o2::framework::Lifetime::Timeframe); } + if (!disableTriggerReconstruction) { + outputs.emplace_back(originEMC, "TRUS", subspecification, o2::framework::Lifetime::Timeframe); + outputs.emplace_back(originEMC, "TRUSTRGR", subspecification, o2::framework::Lifetime::Timeframe); + outputs.emplace_back(originEMC, "PATCHES", subspecification, o2::framework::Lifetime::Timeframe); + outputs.emplace_back(originEMC, "PATCHESTRGR", subspecification, o2::framework::Lifetime::Timeframe); + outputs.emplace_back(originEMC, "FASTORS", subspecification, o2::framework::Lifetime::Timeframe); + outputs.emplace_back(originEMC, "FASTORSTRGR", subspecification, o2::framework::Lifetime::Timeframe); + } std::vector inputs{{"stf", o2::framework::ConcreteDataTypeMatcher{originEMC, o2::header::gDataDescriptionRawData}, o2::framework::Lifetime::Timeframe}}; if (askDISTSTF) { @@ -764,7 +969,7 @@ o2::framework::DataProcessorSpec o2::emcal::reco_workflow::getRawToCellConverter "EMCALRawToCellConverterSpec", inputs, outputs, - o2::framework::adaptFromTask(subspecification, !disableDecodingErrors, calibhandler), + o2::framework::adaptFromTask(subspecification, !disableDecodingErrors, !disableTriggerReconstruction, calibhandler), o2::framework::Options{ {"fitmethod", o2::framework::VariantType::String, "gamma2", {"Fit method (standard or gamma2)"}}, {"maxmessage", o2::framework::VariantType::Int, 100, {"Max. amout of error messages to be displayed"}}, diff --git a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx index db6e95f17f643..28e0deb3ae0b3 100644 --- a/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx +++ b/Detectors/EMCAL/workflow/src/RecoWorkflow.cxx @@ -53,7 +53,8 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, std::string const& cfgOutput, bool disableRootInput, bool disableRootOutput, - bool disableDecodingErrors) + bool disableDecodingErrors, + bool disableTriggerReconstruction) { const std::unordered_map InputMap{ @@ -173,7 +174,7 @@ o2::framework::WorkflowSpec getWorkflow(bool propagateMC, specs.emplace_back(o2::emcal::reco_workflow::getCellConverterSpec(propagateMC, subspecificationIn, subspecificationOut)); } else if (inputType == InputType::Raw) { // raw data will come from upstream - specs.emplace_back(o2::emcal::reco_workflow::getRawToCellConverterSpec(askDISTSTF, disableDecodingErrors, subspecificationOut)); + specs.emplace_back(o2::emcal::reco_workflow::getRawToCellConverterSpec(askDISTSTF, disableDecodingErrors, disableTriggerReconstruction, subspecificationOut)); } } diff --git a/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx b/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx index ceb34695eb0e9..4e31a26ee4b5c 100644 --- a/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx +++ b/Detectors/EMCAL/workflow/src/emc-reco-workflow.cxx @@ -53,6 +53,7 @@ void customize(std::vector& workflowOptions) {"configKeyValues", o2::framework::VariantType::String, "", {"Semicolon separated key=value strings"}}, {"disable-mc", o2::framework::VariantType::Bool, false, {"disable sending of MC information"}}, {"disable-decoding-errors", o2::framework::VariantType::Bool, false, {"disable propagating decoding errors"}}, + {"disable-trigger-reconstruction", o2::framework::VariantType::Bool, false, {"disable reconstruction of trigger data"}}, {"ignore-dist-stf", o2::framework::VariantType::Bool, false, {"do not subscribe to FLP/DISTSUBTIMEFRAME/0 message (no lost TF recovery)"}}, {"subspecificationIn", o2::framework::VariantType::Int, 0, {"Subspecification for input in case the workflow runs in parallel on multiple nodes (i.e. different FLPs)"}}, {"subspecificationOut", o2::framework::VariantType::Int, 0, {"Subspecification for output in case the workflow runs in parallel on multiple nodes (i.e. different FLPs)"}}}; @@ -86,7 +87,8 @@ o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext co cfgc.options().get("output-type"), cfgc.options().get("disable-root-input"), cfgc.options().get("disable-root-output"), - cfgc.options().get("disable-decoding-errors")); + cfgc.options().get("disable-decoding-errors"), + cfgc.options().get("disable-trigger-reconstruction")); // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(cfgc, wf); From c95fff1b180eaf877f3a1d9de764d072e590facb Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Sun, 21 Apr 2024 13:00:45 +0200 Subject: [PATCH 0136/2997] Add track writer workflow for ITS (#13057) --- Detectors/ITSMFT/ITS/workflow/CMakeLists.txt | 6 ++++ .../include/ITSWorkflow/TrackWriterWorkflow.h | 29 +++++++++++++++ .../ITS/workflow/src/TrackWriterWorkflow.cxx | 34 ++++++++++++++++++ .../src/its-track-writer-workflow.cxx | 36 +++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackWriterWorkflow.h create mode 100644 Detectors/ITSMFT/ITS/workflow/src/TrackWriterWorkflow.cxx create mode 100644 Detectors/ITSMFT/ITS/workflow/src/its-track-writer-workflow.cxx diff --git a/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt b/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt index f221a41691f71..3609560eccf72 100644 --- a/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/workflow/CMakeLists.txt @@ -29,6 +29,7 @@ o2_add_library(ITSWorkflow src/DCSAdaposParserSpec.cxx src/DCSDataGeneratorWorkflow.cxx src/DCSGeneratorSpec.cxx + src/TrackWriterWorkflow.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::SimConfig O2::DetectorsDCS @@ -58,6 +59,11 @@ o2_add_executable(cluster-writer-workflow COMPONENT_NAME its PUBLIC_LINK_LIBRARIES O2::ITSWorkflow) +o2_add_executable(track-writer-workflow + SOURCES src/its-track-writer-workflow.cxx + COMPONENT_NAME its + PUBLIC_LINK_LIBRARIES O2::ITSWorkflow) + o2_add_executable(cluster-reader-workflow SOURCES src/its-cluster-reader-workflow.cxx COMPONENT_NAME its diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackWriterWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackWriterWorkflow.h new file mode 100644 index 0000000000000..038b3bca6bdb8 --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackWriterWorkflow.h @@ -0,0 +1,29 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_ITS_TRACK_WRITER_WORKFLOW_H +#define O2_ITS_TRACK_WRITER_WORKFLOW_H + +#include "Framework/WorkflowSpec.h" + +namespace o2 +{ +namespace its +{ + +namespace track_writer_workflow +{ +framework::WorkflowSpec getWorkflow(bool useMC); +} + +} // namespace its +} // namespace o2 +#endif \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackWriterWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterWorkflow.cxx new file mode 100644 index 0000000000000..ae2cb3648ec86 --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterWorkflow.cxx @@ -0,0 +1,34 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "ITSWorkflow/TrackWriterWorkflow.h" +#include "ITSWorkflow/TrackWriterSpec.h" + +namespace o2 +{ +namespace its +{ + +namespace track_writer_workflow +{ + +framework::WorkflowSpec getWorkflow(bool useMC) +{ + framework::WorkflowSpec specs; + + specs.emplace_back(o2::its::getTrackWriterSpec(useMC)); + + return specs; +} + +} // namespace track_writer_workflow +} // namespace its +} // namespace o2 \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-track-writer-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-track-writer-workflow.cxx new file mode 100644 index 0000000000000..d06ab366ef54c --- /dev/null +++ b/Detectors/ITSMFT/ITS/workflow/src/its-track-writer-workflow.cxx @@ -0,0 +1,36 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "ITSWorkflow/TrackWriterWorkflow.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/CompletionPolicyHelpers.h" + +using namespace o2::framework; + +void customize(std::vector& policies) +{ + // ordered policies for the writers + policies.push_back(CompletionPolicyHelpers::consumeWhenAllOrdered(".*(?:ITS|its).*[W,w]riter.*")); +} + +void customize(std::vector& workflowOptions) +{ + workflowOptions.push_back(ConfigParamSpec{"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}); +} + +#include "Framework/runDataProcessing.h" +#include "Framework/Logger.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) +{ + auto useMC = !configcontext.options().get("disable-mc"); + return std::move(o2::its::track_writer_workflow::getWorkflow(useMC)); +} From c8d7fdedba82eb43bf0d6ac6c04a2d1ade5eca46 Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 21 Apr 2024 14:04:31 +0200 Subject: [PATCH 0137/2997] Name debug stream according to the lane rules --- .../Align/Workflow/src/BarrelAlignmentSpec.cxx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx index 22e237fc4c059..78b149b5dd4e8 100644 --- a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx +++ b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx @@ -107,6 +107,7 @@ class BarrelAlignmentSpec : public Task bool mIgnoreCCDBAlignment = false; bool mCosmic = false; bool mLoadTPCCalib = false; + int mLane = 0; int mPostProcessing = 0; // special mode of extracting alignment or constraints check GTrackID::mask_t mMPsrc{}; DetID::mask_t mDetMask{}; @@ -132,12 +133,11 @@ void BarrelAlignmentSpec::init(InitContext& ic) mTimer.Reset(); o2::base::GRPGeomHelper::instance().setRequest(mGRPGeomRequest); - int dbg = ic.options().get("debug-output"), inst = ic.services().get().inputTimesliceId; - mController = std::make_unique(mDetMask, mMPsrc, mCosmic, mUseMC, inst); + int dbg = ic.options().get("debug-output"); + mLane = ic.services().get().inputTimesliceId; + mController = std::make_unique(mDetMask, mMPsrc, mCosmic, mUseMC, mLane); if (dbg) { - mDBGOut = std::make_unique(fmt::format("mpDebug_{}.root", inst).c_str(), "recreate"); mController->setDebugOutputLevel(dbg); - mController->setDebugStream(mDBGOut.get()); } mConfMacro = ic.options().get("config-macro"); @@ -213,7 +213,12 @@ void BarrelAlignmentSpec::init(InitContext& ic) void BarrelAlignmentSpec::updateTimeDependentParams(ProcessingContext& pc) { o2::base::GRPGeomHelper::instance().checkUpdates(pc); + auto tinfo = pc.services().get(); if (pc.services().get().globalRunNumberChanged) { + if (mController->getDebugOutputLevel()) { + mDBGOut = std::make_unique(fmt::format("mpDebug_{}_{:08d}_{:010d}.root", mLane, tinfo.runNumber, tinfo.tfCounter).c_str(), "recreate"); + mController->setDebugStream(mDBGOut.get()); + } if (!mIgnoreCCDBAlignment) { for (auto id = DetID::First; id <= DetID::Last; id++) { const auto* alg = o2::base::GRPGeomHelper::instance().getAlignment(id); From 6a8629caf26894234c8b660ead1eb17e60e323ba Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 19 Apr 2024 15:26:18 +0200 Subject: [PATCH 0138/2997] GPU: Add HIP per-kernel compilation mode --- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 5 +++-- .../Base/cuda/GPUReconstructionCUDA.cu | 9 +++++++-- GPU/GPUTracking/Base/hip/CMakeLists.txt | 15 ++++++++++----- .../Base/hip/per_kernel/CMakeLists.txt | 15 +++++++++++++++ GPU/GPUTracking/cmake/kernel_helpers.cmake | 2 +- 5 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 GPU/GPUTracking/Base/hip/per_kernel/CMakeLists.txt diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 395e69c43457a..7f2a4d315867c 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -48,7 +48,8 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") else() set(RTC_CUDA_ARCH "750") endif() - separate_arguments(GPU_RTC_FLAGS) + set(GPU_RTC_FLAGS_SEPARATED "${GPU_RTC_FLAGS}") + separate_arguments(GPU_RTC_FLAGS_SEPARATED) # convenience variables if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") @@ -74,7 +75,7 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") add_custom_command( OUTPUT ${GPU_RTC_BIN}.command - COMMAND echo -n "${CMAKE_CUDA_COMPILER} ${GPU_RTC_FLAGS} ${GPU_RTC_DEFINES} -fatbin" > ${GPU_RTC_BIN}.command + COMMAND echo -n "${CMAKE_CUDA_COMPILER} ${GPU_RTC_FLAGS_SEPARATED} ${GPU_RTC_DEFINES} -fatbin" > ${GPU_RTC_BIN}.command COMMAND_EXPAND_LISTS VERBATIM COMMENT "Preparing CUDA RTC command file ${GPU_RTC_BIN}.command" diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu index 250f74f803564..a51b3f9e2261f 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDA.cu @@ -26,7 +26,12 @@ #if defined(GPUCA_KERNEL_COMPILE_MODE) && GPUCA_KERNEL_COMPILE_MODE == 1 #include "utils/qGetLdBinarySymbols.h" -#define GPUCA_KRNL(x_class, ...) QGET_LD_BINARY_SYMBOLS(GPUCA_M_CAT3(cuda_kernel_module_fatbin_krnl_, GPUCA_M_KRNL_NAME(x_class), _fatbin)) +#ifndef __HIPCC__ // CUDA +#define PER_KERNEL_OBJECT_EXT _fatbin +#else // HIP +#define PER_KERNEL_OBJECT_EXT _hip_cxx_o +#endif +#define GPUCA_KRNL(x_class, ...) QGET_LD_BINARY_SYMBOLS(GPUCA_M_CAT3(cuda_kernel_module_fatbin_krnl_, GPUCA_M_KRNL_NAME(x_class), PER_KERNEL_OBJECT_EXT)) #include "GPUReconstructionKernelList.h" #undef GPUCA_KRNL #endif @@ -368,7 +373,7 @@ int GPUReconstructionCUDA::InitDevice_Runtime() else { #define GPUCA_KRNL(x_class, ...) \ mInternals->kernelModules.emplace_back(std::make_unique()); \ - GPUFailedMsg(cuModuleLoadData(mInternals->kernelModules.back().get(), GPUCA_M_CAT3(_binary_cuda_kernel_module_fatbin_krnl_, GPUCA_M_KRNL_NAME(x_class), _fatbin_start))); + GPUFailedMsg(cuModuleLoadData(mInternals->kernelModules.back().get(), GPUCA_M_CAT3(_binary_cuda_kernel_module_fatbin_krnl_, GPUCA_M_KRNL_NAME(x_class), GPUCA_M_CAT(PER_KERNEL_OBJECT_EXT, _start)))); #include "GPUReconstructionKernelList.h" #undef GPUCA_KRNL loadKernelModules(true, false); diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index 1f50cdc19d053..c4e818c31dc0c 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -80,7 +80,8 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") # build flags to use for RTC set(GPU_RTC_FLAGS "${CMAKE_HIP_FLAGS} ${CMAKE_HIP_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} -std=c++${CMAKE_HIP_STANDARD}") - separate_arguments(GPU_RTC_FLAGS) + set(GPU_RTC_FLAGS_SEPARATED "${GPU_RTC_FLAGS}") + separate_arguments(GPU_RTC_FLAGS_SEPARATED) # convenience variables if(ALIGPU_BUILD_TYPE STREQUAL "Standalone") @@ -106,7 +107,7 @@ if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") add_custom_command( OUTPUT ${GPU_RTC_BIN}.command - COMMAND echo -n "${hip_HIPCC_EXECUTABLE} ${GPU_RTC_FLAGS} ${GPU_RTC_DEFINES} --genco" > ${GPU_RTC_BIN}.command + COMMAND echo -n "${hip_HIPCC_EXECUTABLE} ${GPU_RTC_FLAGS_SEPARATED} ${GPU_RTC_DEFINES} --genco" > ${GPU_RTC_BIN}.command COMMAND_EXPAND_LISTS VERBATIM COMMENT "Preparing HIP RTC command file ${GPU_RTC_BIN}.command" @@ -206,19 +207,23 @@ if(NOT DEFINED GPUCA_HIP_COMPILE_MODE) if(ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") set(GPUCA_HIP_COMPILE_MODE "onefile") else() - set(GPUCA_HIP_COMPILE_MODE "onefile") + set(GPUCA_HIP_COMPILE_MODE "perkernel") endif() endif() if(GPUCA_HIP_COMPILE_MODE STREQUAL "onefile") target_compile_definitions(${targetName} PRIVATE GPUCA_KERNEL_COMPILE_MODE=0) elseif(GPUCA_HIP_COMPILE_MODE STREQUAL "perkernel") - add_library(GPUTrackingHIPKernels OBJECT $,REPLACE,[^A-Za-z0-9]+,_>,PREPEND,${O2_GPU_KERNEL_WRAPPER_FOLDER}/krnl_>,APPEND,.cu>, >) - set_property(TARGET GPUTrackingHIPKernels PROPERTY HIP_FATBIN_COMPILATION ON) + #add_library(GPUTrackingHIPKernels OBJECT $,REPLACE,[^A-Za-z0-9]+,_>,PREPEND,${O2_GPU_KERNEL_WRAPPER_FOLDER}/krnl_>,APPEND,.cu>, >) + #set_property(TARGET GPUTrackingHIPKernels PROPERTY HIP_FATBIN_COMPILATION ON) + add_subdirectory(per_kernel) target_compile_options(GPUTrackingHIPKernels PRIVATE $<$:-fno-gpu-rdc>) target_link_options(GPUTrackingHIPKernels PRIVATE $<$:-fno-gpu-rdc>) target_compile_definitions(${targetName} PRIVATE GPUCA_KERNEL_COMPILE_MODE=1) target_compile_definitions(GPUTrackingHIPKernels PRIVATE $) target_include_directories(GPUTrackingHIPKernels PRIVATE $) + if(NOT DEFINED GPUCA_HIP_HIPIFY_FROM_CUDA OR "${GPUCA_HIP_HIPIFY_FROM_CUDA}") + add_dependencies(GPUTrackingHIPKernels ${MODULE}_HIPIFIED) + endif() file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/hip_kernel_module_fatbin) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/GPUTrackingHIPKernelModules.o diff --git a/GPU/GPUTracking/Base/hip/per_kernel/CMakeLists.txt b/GPU/GPUTracking/Base/hip/per_kernel/CMakeLists.txt new file mode 100644 index 0000000000000..3aba296d9cc4a --- /dev/null +++ b/GPU/GPUTracking/Base/hip/per_kernel/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +add_library(GPUTrackingHIPKernels OBJECT $,REPLACE,[^A-Za-z0-9]+,_>,PREPEND,${O2_GPU_KERNEL_WRAPPER_FOLDER}/krnl_>,APPEND,.hip.cxx>, >) +set(CMAKE_CXX_COMPILER ${hip_HIPCC_EXECUTABLE}) +set(CMAKE_CXX_FLAGS "${GPU_RTC_FLAGS} --genco") +unset(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}) diff --git a/GPU/GPUTracking/cmake/kernel_helpers.cmake b/GPU/GPUTracking/cmake/kernel_helpers.cmake index 571303df4c6c2..2da1f13de517e 100644 --- a/GPU/GPUTracking/cmake/kernel_helpers.cmake +++ b/GPU/GPUTracking/cmake/kernel_helpers.cmake @@ -95,7 +95,7 @@ function(o2_gpu_add_kernel kernel_name kernel_files kernel_bounds kernel_type) endif() if(HIP_ENABLED) - set(TMP_FILENAMEA "${O2_GPU_KERNEL_WRAPPER_FOLDER}/krnl_${TMP_FILENAME}.hip") + set(TMP_FILENAMEA "${O2_GPU_KERNEL_WRAPPER_FOLDER}/krnl_${TMP_FILENAME}.hip.cxx") set(O2_GPU_KERNEL_TEMPLATE_REPLACE "${TMP_KERNEL}") configure_file(${O2_GPU_BASE_DIR}/Base/hip/GPUReconstructionHIPkernel.template.hip ${TMP_FILENAMEA}) endif() From 86578c84b965e99b3a62dc255396c129eb7f2e21 Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Sun, 21 Apr 2024 20:40:27 +0200 Subject: [PATCH 0139/2997] GPU ITS tracking: make tracking mode available in configKeyVals + fixes (#13056) * Fix usage of VertexerTraits from within the GPU reco WF * Prepare settings and cleanup interface * Temporarily re-enable the gpu-wf-spec in itsreco-wf * Extend configuration --- .../ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu | 1 - .../tracking/include/ITStracking/Configuration.h | 4 +++- .../include/ITStracking/TrackingConfigParam.h | 2 ++ .../include/ITStracking/TrackingInterface.h | 16 ++++++++++++---- .../include/ITStracking/VertexerTraits.h | 2 +- .../ITSMFT/ITS/tracking/src/Configuration.cxx | 2 ++ Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 1 + .../ITS/tracking/src/TrackingInterface.cxx | 15 +++++++-------- Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx | 4 ++-- .../workflow/include/ITSWorkflow/TrackerSpec.h | 15 +++++++-------- .../ITSMFT/ITS/workflow/src/RecoWorkflow.cxx | 3 --- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 3 ++- .../include/GPUWorkflow/GPUWorkflowSpec.h | 1 - GPU/Workflow/src/GPUWorkflowITS.cxx | 1 - GPU/Workflow/src/gpu-reco-workflow.cxx | 6 +++++- 15 files changed, 44 insertions(+), 32 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu index d8a7985b33343..9a1ed507ae5a4 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cu @@ -93,7 +93,6 @@ VertexerTraitsGPU::VertexerTraitsGPU() VertexerTraitsGPU::~VertexerTraitsGPU() { - gpu::utils::gpuFree(mDeviceIndexTableUtils); } void VertexerTraitsGPU::initialise(const TrackingParameters& trackingParams) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 2a66bbd245e87..a700dc1e806c0 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -34,7 +34,8 @@ namespace its enum class TrackingMode { Sync, Async, - Cosmics + Cosmics, + Unset, // Special value to leave a default in case we want to override via Configurable Params }; std::string asString(TrackingMode mode); @@ -146,6 +147,7 @@ struct TimeFrameGPUParameters { size_t maxVerticesCapacity = 5e4; size_t nMaxROFs = 1e3; size_t nTimeFrameChunks = 3; + size_t nROFsPerChunk = 768; // pp defaults int maxGPUMemoryGB = -1; }; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index d3a3035bd63cc..36a5fd63b12d1 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -78,6 +78,8 @@ struct TrackerParamConfig : public o2::conf::ConfigurableParamHelpergetX(), v->getY()); } mMeanVertex = v; } @@ -61,13 +62,20 @@ class ITSTrackingInterface // Custom void setTraitsFromProvider(VertexerTraits*, TrackerTraits*, TimeFrame*); + void setTrackingMode(TrackingMode mode = TrackingMode::Unset) + { + if (mode == TrackingMode::Unset) { + LOGP(fatal, "ITS Tracking mode Unset is meant to be a default. Specify the mode"); + } + mMode = mode; + } private: bool mIsMC = false; bool mRunVertexer = true; bool mCosmicsProcessing = false; int mUseTriggers = 0; - TrackingMode mMode = TrackingMode::Sync; + TrackingMode mMode = TrackingMode::Unset; bool mOverrideBeamEstimation = false; const o2::itsmft::TopologyDictionary* mDict = nullptr; std::unique_ptr mTracker = nullptr; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index 89da9a90df283..365a24cfaee62 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -85,13 +85,13 @@ class VertexerTraits TimeFrame*, std::vector*); - VertexingParameters getVertexingParameters() const { return mVrtParams; } static const std::vector> selectClusters(const int* indexTable, const std::array& selectedBinsRect, const IndexTableUtils& utils); // utils VertexingParameters& getVertexingParameters() { return mVrtParams; } + VertexingParameters getVertexingParameters() const { return mVrtParams; } void setIsGPU(const unsigned char isgpu) { mIsGPU = isgpu; }; unsigned char getIsGPU() const { return mIsGPU; }; void dumpVertexerTraits(); diff --git a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx index 3c22260901900..13cf6b472db9a 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx @@ -22,6 +22,8 @@ std::string asString(TrackingMode mode) return "async"; case TrackingMode::Cosmics: return "cosmics"; + case TrackingMode::Unset: + return "unset"; } return "unknown"; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index fc848504cf416..42df15b24f052 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -455,6 +455,7 @@ void Tracker::rectifyClusterIndices() void Tracker::getGlobalConfiguration() { auto& tc = o2::its::TrackerParamConfig::Instance(); + tc.printKeyValues(true, true); if (tc.useMatCorrTGeo) { mTraits->setCorrType(o2::base::PropagatorImpl::MatCorrType::USEMatCorrTGeo); } else if (tc.useFastMaterial) { diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index 066d400a17f19..492976d164227 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -22,6 +22,7 @@ #include "DataFormatsTRD/TriggerRecord.h" #include "CommonDataFormat/IRFrame.h" #include "DetectorsBase/GRPGeomHelper.h" +#include "ITStracking/TrackingConfigParam.h" namespace o2 { @@ -33,9 +34,11 @@ void ITSTrackingInterface::initialise() mRunVertexer = true; mCosmicsProcessing = false; std::vector trackParams; - + if (mMode == TrackingMode::Unset) { + mMode = (TrackingMode)(o2::its::TrackerParamConfig::Instance().trackingMode); + LOGP(info, "Tracking mode not set, trying to fetch it from configurable params to: {}", asString(mMode)); + } if (mMode == TrackingMode::Async) { - trackParams.resize(3); for (auto& param : trackParams) { param.ZBins = 64; @@ -49,7 +52,6 @@ void ITSTrackingInterface::initialise() trackParams[2].CellDeltaTanLambdaSigma *= 4.; trackParams[2].MinTrackLength = 4; LOG(info) << "Initializing tracker in async. phase reconstruction with " << trackParams.size() << " passes"; - } else if (mMode == TrackingMode::Sync) { trackParams.resize(1); trackParams[0].ZBins = 64; @@ -195,10 +197,7 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) } } if (processingMask[iRof] && !selROF) { // passed selection in clusters and not in vertex multiplicity - LOG(debug) << fmt::format("ROF {} rejected by the vertex multiplicity selection [{},{}]", - iRof, - multEstConf.cutMultVtxLow, - multEstConf.cutMultVtxHigh); + LOGP(info, "ROF {} rejected by the vertex multiplicity selection [{},{}]", iRof, multEstConf.cutMultVtxLow, multEstConf.cutMultVtxHigh); processingMask[iRof] = selROF; cutVertexMult++; } @@ -325,7 +324,7 @@ void ITSTrackingInterface::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) return; } if (matcher == ConcreteDataMatcher("GLO", "MEANVERTEX", 0)) { - LOGP(info, "mean vertex acquired"); + LOGP(info, "Mean vertex acquired"); setMeanVertex((const o2::dataformats::MeanVertexObject*)obj); return; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx index 05303a95a22da..acc59a66a7c2c 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx @@ -67,6 +67,7 @@ float Vertexer::clustersToVerticesHybrid(std::function logg void Vertexer::getGlobalConfiguration() { auto& vc = o2::its::VertexerParamConfig::Instance(); + vc.printKeyValues(true, true); auto& grc = o2::its::GpuRecoParamConfig::Instance(); VertexingParameters verPar; @@ -90,8 +91,7 @@ void Vertexer::getGlobalConfiguration() verPar.PhiBins = vc.PhiBins; TimeFrameGPUParameters tfGPUpar; - tfGPUpar.maxGPUMemoryGB = grc.maxGPUMemoryGB; - tfGPUpar.maxVerticesCapacity = grc.maxVerticesCapacity; + // tfGPUpar.nROFsPerChunk = grc.nROFsPerChunk; mTraits->updateVertexingParameters(verPar, tfGPUpar); } diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h index 643511cbfc164..be9965fc8be58 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h @@ -23,13 +23,11 @@ #include "ITStracking/TrackingInterface.h" -#include "GPUO2Interface.h" -#include "GPUReconstruction.h" -#include "GPUChainITS.h" -#include "CommonUtils/StringUtils.h" -#include "TStopwatch.h" +#include "GPUDataTypes.h" #include "DetectorsBase/GRPGeomHelper.h" +#include "TStopwatch.h" + namespace o2 { namespace its @@ -41,9 +39,9 @@ class TrackerDPL : public framework::Task TrackerDPL(std::shared_ptr gr, bool isMC, int trgType, - const TrackingMode& trMode, + const TrackingMode& trMode = TrackingMode::Unset, const bool overrBeamEst = false, - o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU); + gpu::GPUDataTypes::DeviceType dType = gpu::GPUDataTypes::DeviceType::CPU); ~TrackerDPL() override = default; void init(framework::InitContext& ic) final; void run(framework::ProcessingContext& pc) final; @@ -60,7 +58,8 @@ class TrackerDPL : public framework::Task TStopwatch mTimer; }; -framework::DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int useTrig, const std::string& trModeS, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType); +using o2::its::TrackingMode; +framework::DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int useTrig, const std::string& trMode, const bool overrBeamEst = false, gpu::GPUDataTypes::DeviceType dType = gpu::GPUDataTypes::DeviceType::CPU); } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx index dfa958ccd5890..dc75d90150eb8 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx @@ -31,8 +31,6 @@ namespace o2 { namespace its { -// using ITSTrackReconstruction::TrackingMode; - namespace reco_workflow { @@ -65,7 +63,6 @@ framework::WorkflowSpec getWorkflow(bool useMC, cfg.runITSTracking = true; cfg.itsTriggerType = useTrig; cfg.itsOverrBeamEst = overrideBeamPosition; - cfg.itsTrackingMode = trmode == "sync" ? (int)TrackingMode::Sync : (trmode == "async" ? (int)TrackingMode::Async : (int)TrackingMode::Cosmics); Inputs ggInputs; auto ggRequest = std::make_shared(false, true, false, true, true, diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index c26bc5171ddeb..367fa8673cc70 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -30,8 +30,9 @@ TrackerDPL::TrackerDPL(std::shared_ptr gr, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType) : mGGCCDBRequest(gr), mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)}, - mITSTrackingInterface{isMC, trgType, trMode, overrBeamEst} + mITSTrackingInterface{isMC, trgType, overrBeamEst} { + mITSTrackingInterface.setTrackingMode(trMode); } void TrackerDPL::init(InitContext& ic) diff --git a/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h b/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h index 65940b764f79c..17f88d0417979 100644 --- a/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h +++ b/GPU/Workflow/include/GPUWorkflow/GPUWorkflowSpec.h @@ -127,7 +127,6 @@ class GPURecoWorkflowSpec : public o2::framework::Task int lumiScaleType = 0; // 0=off, 1=CTP, 2=TPC scalers bool outputErrorQA = false; bool runITSTracking = false; - int itsTrackingMode = 0; // 0=sync, 1=async, 2=cosmics bool itsOverrBeamEst = false; bool tpcTriggerHandling = false; }; diff --git a/GPU/Workflow/src/GPUWorkflowITS.cxx b/GPU/Workflow/src/GPUWorkflowITS.cxx index 72f466591d231..5f6ec171d27c1 100644 --- a/GPU/Workflow/src/GPUWorkflowITS.cxx +++ b/GPU/Workflow/src/GPUWorkflowITS.cxx @@ -37,7 +37,6 @@ void GPURecoWorkflowSpec::initFunctionITS(o2::framework::InitContext& ic) o2::its::TrackerTraits* trkTraits = nullptr; mITSTrackingInterface = std::make_unique(mSpecConfig.processMC, mSpecConfig.itsTriggerType, - static_cast(mSpecConfig.itsTrackingMode), mSpecConfig.itsOverrBeamEst); mGPUReco->GetITSTraits(trkTraits, vtxTraits, mITSTimeFrame); mITSTrackingInterface->setTraitsFromProvider(vtxTraits, trkTraits, mITSTimeFrame); diff --git a/GPU/Workflow/src/gpu-reco-workflow.cxx b/GPU/Workflow/src/gpu-reco-workflow.cxx index 9e610331a3aa3..aef7694ac5de7 100644 --- a/GPU/Workflow/src/gpu-reco-workflow.cxx +++ b/GPU/Workflow/src/gpu-reco-workflow.cxx @@ -107,6 +107,7 @@ enum struct ioType { Digits, SendClustersPerSector, ITSClusters, ITSTracks, + MeanVertex, TPCTriggers }; static const std::unordered_map InputMap{ @@ -117,7 +118,9 @@ static const std::unordered_map InputMap{ {"compressed-clusters-root", ioType::CompClustROOT}, {"compressed-clusters-ctf", ioType::CompClustCTF}, {"trd-tracklets", ioType::TRDTracklets}, - {"its-clusters", ioType::ITSClusters}}; + {"its-clusters", ioType::ITSClusters}, + {"its-mean-vertex", ioType::MeanVertex}, +}; static const std::unordered_map OutputMap{ {"clusters", ioType::Clusters}, @@ -183,6 +186,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) cfg.enableDoublePipeline = cfgc.options().get("enableDoublePipeline"); cfg.tpcDeadMapSources = cfgc.options().get("tpc-deadMap-sources"); cfg.runITSTracking = isEnabled(outputTypes, ioType::ITSTracks); + cfg.itsOverrBeamEst = isEnabled(inputTypes, ioType::MeanVertex); Inputs ggInputs; auto ggRequest = std::make_shared(false, true, false, true, true, o2::base::GRPGeomRequest::Aligned, ggInputs, true); From 88838a81d230cee1f6ad1a5038e9bca515d13bff Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Mon, 22 Apr 2024 08:29:20 +0200 Subject: [PATCH 0140/2997] Allow for smooth move to the new naming of QC flags (#13053) --- DataFormats/QualityControl/CMakeLists.txt | 4 +- .../DataFormatsQualityControl/FlagType.h | 22 +++++++ .../FlagTypeFactory.h | 22 +++++++ .../QualityControlFlag.h | 22 +++++++ .../QualityControlFlagCollection.h | 22 +++++++ .../QualityControl/test/testFlagReasons.cxx | 20 +++---- .../QualityControl/test/testTimeRangeFlag.cxx | 12 ++-- .../test/testTimeRangeFlagCollection.cxx | 57 ++++++++++--------- 8 files changed, 136 insertions(+), 45 deletions(-) create mode 100644 DataFormats/QualityControl/include/DataFormatsQualityControl/FlagType.h create mode 100644 DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h create mode 100644 DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlag.h create mode 100644 DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlagCollection.h diff --git a/DataFormats/QualityControl/CMakeLists.txt b/DataFormats/QualityControl/CMakeLists.txt index 0d17d0d1d0f9e..03a3b0ed49f69 100644 --- a/DataFormats/QualityControl/CMakeLists.txt +++ b/DataFormats/QualityControl/CMakeLists.txt @@ -43,7 +43,9 @@ o2_add_library(DataFormatsQualityControl ) o2_target_root_dictionary(DataFormatsQualityControl - HEADERS include/DataFormatsQualityControl/FlagReasons.h + HEADERS include/DataFormatsQualityControl/FlagType.h + include/DataFormatsQualityControl/FlagReasons.h + include/DataFormatsQualityControl/QualityControlFlag.h include/DataFormatsQualityControl/TimeRangeFlag.h include/DataFormatsQualityControl/TimeRangeFlagCollection.h) diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagType.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagType.h new file mode 100644 index 0000000000000..c862835530de6 --- /dev/null +++ b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagType.h @@ -0,0 +1,22 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_QUALITYCONTROL_FLAGTYPE_H +#define O2_QUALITYCONTROL_FLAGTYPE_H + +#include "DataFormatsQualityControl/FlagReasons.h" + +namespace o2::quality_control +{ +using FlagType = o2::quality_control::FlagReason; +} + +#endif // O2_QUALITYCONTROL_FLAGTYPE_H diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h new file mode 100644 index 0000000000000..ea28ffbd3d944 --- /dev/null +++ b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h @@ -0,0 +1,22 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_QUALITYCONTROL_FLAGTYPEFACTORY_H +#define O2_QUALITYCONTROL_FLAGTYPEFACTORY_H + +#include "DataFormatsQualityControl/FlagReasonFactory.h" + +namespace o2::quality_control +{ +using FlagTypeFactory = o2::quality_control::FlagReasonFactory; +} + +#endif // O2_QUALITYCONTROL_FLAGTYPEFACTORY_H diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlag.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlag.h new file mode 100644 index 0000000000000..96c778220f617 --- /dev/null +++ b/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlag.h @@ -0,0 +1,22 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_QUALITYCONTROL_QCFLAG_H +#define O2_QUALITYCONTROL_QCFLAG_H + +#include "DataFormatsQualityControl/TimeRangeFlag.h" + +namespace o2::quality_control +{ +using QualityControlFlag = o2::quality_control::TimeRangeFlag; +} + +#endif // O2_QUALITYCONTROL_QCFLAG_H diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlagCollection.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlagCollection.h new file mode 100644 index 0000000000000..04cd74f09444e --- /dev/null +++ b/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlagCollection.h @@ -0,0 +1,22 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_QUALITYCONTROL_QCFLAGCOLLECTION_H +#define O2_QUALITYCONTROL_QCFLAGCOLLECTION_H + +#include "DataFormatsQualityControl/TimeRangeFlagCollection.h" + +namespace o2::quality_control +{ +using QualityControlFlagCollection = o2::quality_control::TimeRangeFlagCollection; +} + +#endif // O2_QUALITYCONTROL_QCFLAGCOLLECTION_H diff --git a/DataFormats/QualityControl/test/testFlagReasons.cxx b/DataFormats/QualityControl/test/testFlagReasons.cxx index 9e7ff15383674..ebcd409ed3d46 100644 --- a/DataFormats/QualityControl/test/testFlagReasons.cxx +++ b/DataFormats/QualityControl/test/testFlagReasons.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test quality_control FlagReasons class +#define BOOST_TEST_MODULE Test quality_control FlagTypes class #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK @@ -19,20 +19,20 @@ #include // o2 includes -#include "DataFormatsQualityControl/FlagReasons.h" -#include "DataFormatsQualityControl/FlagReasonFactory.h" +#include "DataFormatsQualityControl/FlagType.h" +#include "DataFormatsQualityControl/FlagTypeFactory.h" using namespace o2::quality_control; -BOOST_AUTO_TEST_CASE(FlagReasons) +BOOST_AUTO_TEST_CASE(FlagTypes) { - static_assert(std::is_constructible::value == false, - "FlagReason should not be constructible outside of its static methods and the factory."); + static_assert(std::is_constructible::value == false, + "FlagType should not be constructible outside of its static methods and the factory."); - FlagReason rDefault; - BOOST_CHECK_EQUAL(rDefault, FlagReasonFactory::Invalid()); + FlagType rDefault; + BOOST_CHECK_EQUAL(rDefault, FlagTypeFactory::Invalid()); - auto r1 = FlagReasonFactory::Unknown(); + auto r1 = FlagTypeFactory::Unknown(); BOOST_CHECK_EQUAL(r1.getID(), 1); BOOST_CHECK_EQUAL(r1.getName(), "Unknown"); BOOST_CHECK_EQUAL(r1.getBad(), true); @@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(FlagReasons) BOOST_CHECK(!(r1 < r2)); BOOST_CHECK(!(r1 > r2)); - auto r3 = FlagReasonFactory::LimitedAcceptance(); + auto r3 = FlagTypeFactory::LimitedAcceptance(); BOOST_CHECK(r3 > r1); BOOST_CHECK(!(r3 < r1)); } diff --git a/DataFormats/QualityControl/test/testTimeRangeFlag.cxx b/DataFormats/QualityControl/test/testTimeRangeFlag.cxx index 47eef61199103..0b912db2c1f42 100644 --- a/DataFormats/QualityControl/test/testTimeRangeFlag.cxx +++ b/DataFormats/QualityControl/test/testTimeRangeFlag.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test quality_control TimeRangeFlag class +#define BOOST_TEST_MODULE Test quality_control QualityControlFlag class #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK @@ -17,13 +17,13 @@ #include // o2 includes -#include "DataFormatsQualityControl/TimeRangeFlag.h" +#include "DataFormatsQualityControl/QualityControlFlag.h" using namespace o2::quality_control; -BOOST_AUTO_TEST_CASE(test_TimeRangeFlag) +BOOST_AUTO_TEST_CASE(test_QualityControlFlag) { - TimeRangeFlag trf1{12, 34, FlagReasonFactory::BadTracking(), "comment", "source"}; + QualityControlFlag trf1{12, 34, FlagReasonFactory::BadTracking(), "comment", "source"}; BOOST_CHECK_EQUAL(trf1.getStart(), 12); BOOST_CHECK_EQUAL(trf1.getEnd(), 34); @@ -31,9 +31,9 @@ BOOST_AUTO_TEST_CASE(test_TimeRangeFlag) BOOST_CHECK_EQUAL(trf1.getComment(), "comment"); BOOST_CHECK_EQUAL(trf1.getSource(), "source"); - BOOST_CHECK_THROW((TimeRangeFlag{12, 0, FlagReasonFactory::BadTracking()}), std::runtime_error); + BOOST_CHECK_THROW((QualityControlFlag{12, 0, FlagReasonFactory::BadTracking()}), std::runtime_error); - TimeRangeFlag trf2{10, 34, FlagReasonFactory::BadTracking(), "comment", "source"}; + QualityControlFlag trf2{10, 34, FlagReasonFactory::BadTracking(), "comment", "source"}; BOOST_CHECK(trf1 > trf2); BOOST_CHECK(!(trf1 < trf2)); diff --git a/DataFormats/QualityControl/test/testTimeRangeFlagCollection.cxx b/DataFormats/QualityControl/test/testTimeRangeFlagCollection.cxx index 9f5468ce00865..bf8ce2cab0fbd 100644 --- a/DataFormats/QualityControl/test/testTimeRangeFlagCollection.cxx +++ b/DataFormats/QualityControl/test/testTimeRangeFlagCollection.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test quality_control TimeRangeFlagCollection class +#define BOOST_TEST_MODULE Test quality_control QualityControlFlagCollection class #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK @@ -18,20 +18,21 @@ // STL #include // o2 includes -#include "DataFormatsQualityControl/TimeRangeFlagCollection.h" -#include "DataFormatsQualityControl/TimeRangeFlag.h" +#include "DataFormatsQualityControl/QualityControlFlagCollection.h" +#include "DataFormatsQualityControl/QualityControlFlag.h" +#include "DataFormatsQualityControl/FlagTypeFactory.h" using namespace o2::quality_control; -BOOST_AUTO_TEST_CASE(test_TimeRangeFlagCollection_Methods) +BOOST_AUTO_TEST_CASE(test_QualityControlFlagCollection_Methods) { - TimeRangeFlag trf1{12, 34, FlagReasonFactory::BadTracking(), "comment", "source"}; - TimeRangeFlag trf2{10, 34, FlagReasonFactory::BadTracking(), "comment", "source"}; + QualityControlFlag trf1{12, 34, FlagTypeFactory::BadTracking(), "comment", "source"}; + QualityControlFlag trf2{10, 34, FlagTypeFactory::BadTracking(), "comment", "source"}; - TimeRangeFlagCollection trfc1{"Raw data checks", "TOF", {10, 20000}, 12345, "LHC22k5", "passMC", "qc_mc"}; + QualityControlFlagCollection trfc1{"Raw data checks", "TOF", {10, 20000}, 12345, "LHC22k5", "passMC", "qc_mc"}; trfc1.insert(trf1); // by copy trfc1.insert(trf2); - trfc1.insert({50, 77, FlagReasonFactory::Invalid()}); // by move + trfc1.insert({50, 77, FlagTypeFactory::Invalid()}); // by move BOOST_CHECK_EQUAL(trfc1.size(), 3); BOOST_CHECK_EQUAL(trfc1.getName(), "Raw data checks"); BOOST_CHECK_EQUAL(trfc1.getDetector(), "TOF"); @@ -42,16 +43,16 @@ BOOST_AUTO_TEST_CASE(test_TimeRangeFlagCollection_Methods) BOOST_CHECK_EQUAL(trfc1.getPassName(), "passMC"); BOOST_CHECK_EQUAL(trfc1.getProvenance(), "qc_mc"); - TimeRangeFlagCollection trfc2{"Reco checks", "TOF"}; - trfc2.insert({50, 77, FlagReasonFactory::Invalid()}); // this is a duplicate to an entry in trfc1 - trfc2.insert({51, 77, FlagReasonFactory::Invalid()}); - trfc2.insert({1234, 3434, FlagReasonFactory::LimitedAcceptance()}); - trfc2.insert({50, 77, FlagReasonFactory::LimitedAcceptance()}); + QualityControlFlagCollection trfc2{"Reco checks", "TOF"}; + trfc2.insert({50, 77, FlagTypeFactory::Invalid()}); // this is a duplicate to an entry in trfc1 + trfc2.insert({51, 77, FlagTypeFactory::Invalid()}); + trfc2.insert({1234, 3434, FlagTypeFactory::LimitedAcceptance()}); + trfc2.insert({50, 77, FlagTypeFactory::LimitedAcceptance()}); BOOST_CHECK_EQUAL(trfc2.size(), 4); // Try merging. Duplicate entries should be left in the 'other' objects. // Notice that we merge the two partial TRFCs into the third, which covers all cases - TimeRangeFlagCollection trfc3{"ALL", "TOF"}; + QualityControlFlagCollection trfc3{"ALL", "TOF"}; trfc3.merge(trfc1); trfc3.merge(trfc2); BOOST_CHECK_EQUAL(trfc1.size(), 0); @@ -59,14 +60,14 @@ BOOST_AUTO_TEST_CASE(test_TimeRangeFlagCollection_Methods) BOOST_CHECK_EQUAL(trfc3.size(), 6); // Try const merging. It should copy the elements and keep the 'other' intact. - TimeRangeFlagCollection trfc4{"ALL", "TOF"}; + QualityControlFlagCollection trfc4{"ALL", "TOF"}; const auto& constTrfc3 = trfc3; trfc4.merge(constTrfc3); BOOST_CHECK_EQUAL(trfc3.size(), 6); BOOST_CHECK_EQUAL(trfc4.size(), 6); // Try merging different detectors - it should throw. - TimeRangeFlagCollection trfc5{"ALL", "TPC"}; + QualityControlFlagCollection trfc5{"ALL", "TPC"}; BOOST_CHECK_THROW(trfc5.merge(trfc3), std::runtime_error); BOOST_CHECK_THROW(trfc5.merge(constTrfc3), std::runtime_error); @@ -79,31 +80,31 @@ BOOST_AUTO_TEST_CASE(test_TimeRangeFlagCollection_Methods) } } -BOOST_AUTO_TEST_CASE(test_TimeRangeFlagCollection_IO) +BOOST_AUTO_TEST_CASE(test_QualityControlFlagCollection_IO) { { - TimeRangeFlagCollection trfc1{"xyz", "TST"}; + QualityControlFlagCollection trfc1{"xyz", "TST"}; std::stringstream store; trfc1.streamTo(store); - TimeRangeFlagCollection trfc2{"xyz", "TST"}; + QualityControlFlagCollection trfc2{"xyz", "TST"}; trfc2.streamFrom(store); BOOST_CHECK_EQUAL(trfc2.size(), 0); } { - TimeRangeFlagCollection trfc1{"xyz", "TST"}; - trfc1.insert({50, 77, FlagReasonFactory::Invalid(), "a comment", "a source"}); - trfc1.insert({51, 77, FlagReasonFactory::Invalid()}); - trfc1.insert({1234, 3434, FlagReasonFactory::LimitedAcceptance()}); - trfc1.insert({50, 77, FlagReasonFactory::LimitedAcceptance()}); - trfc1.insert({43434, 63421, FlagReasonFactory::NotBadFlagExample()}); + QualityControlFlagCollection trfc1{"xyz", "TST"}; + trfc1.insert({50, 77, FlagTypeFactory::Invalid(), "a comment", "a source"}); + trfc1.insert({51, 77, FlagTypeFactory::Invalid()}); + trfc1.insert({1234, 3434, FlagTypeFactory::LimitedAcceptance()}); + trfc1.insert({50, 77, FlagTypeFactory::LimitedAcceptance()}); + trfc1.insert({43434, 63421, FlagTypeFactory::NotBadFlagExample()}); std::stringstream store; trfc1.streamTo(store); - TimeRangeFlagCollection trfc2{"xyz", "TST"}; + QualityControlFlagCollection trfc2{"xyz", "TST"}; trfc2.streamFrom(store); BOOST_REQUIRE_EQUAL(trfc1.size(), trfc2.size()); @@ -115,7 +116,7 @@ BOOST_AUTO_TEST_CASE(test_TimeRangeFlagCollection_IO) std::stringstream store; store << "start,end,flag_id,invalid,header,format\n"; store << R"(123,345,11,"fdsa",1,"comment","source")"; - TimeRangeFlagCollection trfc1{"A", "TST"}; + QualityControlFlagCollection trfc1{"A", "TST"}; BOOST_CHECK_THROW(trfc1.streamFrom(store), std::runtime_error); } { @@ -128,7 +129,7 @@ BOOST_AUTO_TEST_CASE(test_TimeRangeFlagCollection_IO) store << R"(123,345,,"fdsa",1,"comment","source")" << '\n'; store << R"(123,345,11,"",1,"comment","source")" << '\n'; store << R"(123,345,11,"fdsa",,"comment","source")" << '\n'; - TimeRangeFlagCollection trfc1{"A", "TST"}; + QualityControlFlagCollection trfc1{"A", "TST"}; BOOST_CHECK_NO_THROW(trfc1.streamFrom(store)); BOOST_CHECK_EQUAL(trfc1.size(), 0); } From f5ebb6900e7cce3580ab48c751a143109dd5f0eb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:57:58 +0200 Subject: [PATCH 0141/2997] DPL: Fix memory leak in variant_helper --- Framework/Core/include/Framework/Variant.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index b8be3a780547e..54e4b54be9606 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -285,7 +285,7 @@ struct variant_helper { template struct variant_helper { - static std::string get(const S* store) { return std::string(strdup(*reinterpret_cast(store))); } + static std::string get(const S* store) { return std::string(*reinterpret_cast(store)); } static void set(S* store, std::string value) { *reinterpret_cast(store) = strdup(value.data()); } }; From 8387a8cda98d9e9177e86854e31902d784aa1311 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 21 Apr 2024 19:53:28 +0200 Subject: [PATCH 0142/2997] GPU: Fix standalone compilation without O2 headers --- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 2 +- GPU/GPUTracking/Base/hip/CMakeLists.txt | 2 +- GPU/GPUTracking/cmake/kernel_helpers.cmake | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 7f2a4d315867c..6bade1363b7ce 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -197,7 +197,7 @@ if(NOT GPUCA_CUDA_COMPILE_MODE STREQUAL "rdc") set_target_properties(${targetName} PROPERTIES LINKER_LANGUAGE CXX) endif() -if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") +if(ALIGPU_BUILD_TYPE STREQUAL "O2" OR CONFIG_O2_EXTENSIONS) add_library(GPUTrackingCUDAExternalProvider OBJECT GPUReconstructionCUDAExternalProvider.cu) add_library(O2::GPUTrackingCUDAExternalProvider ALIAS GPUTrackingCUDAExternalProvider) set_property(TARGET GPUTrackingCUDAExternalProvider PROPERTY CUDA_SEPARABLE_COMPILATION ON) diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index c4e818c31dc0c..151eb5ae3930a 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -260,7 +260,7 @@ if(NOT GPUCA_HIP_COMPILE_MODE STREQUAL "rdc") target_link_options(${targetName} PRIVATE $<$:-fno-gpu-rdc>) endif() -if(NOT ALIGPU_BUILD_TYPE STREQUAL "ALIROOT") +if(ALIGPU_BUILD_TYPE STREQUAL "O2" OR CONFIG_O2_EXTENSIONS) add_library(GPUTrackingHIPExternalProvider OBJECT ${GPUCA_HIP_SOURCE_DIR}/GPUReconstructionHIPExternalProvider.hip) add_library(O2::GPUTrackingHIPExternalProvider ALIAS GPUTrackingHIPExternalProvider) target_compile_options(GPUTrackingHIPExternalProvider PRIVATE $<$:-fgpu-rdc>) diff --git a/GPU/GPUTracking/cmake/kernel_helpers.cmake b/GPU/GPUTracking/cmake/kernel_helpers.cmake index 2da1f13de517e..30fe2850ff3eb 100644 --- a/GPU/GPUTracking/cmake/kernel_helpers.cmake +++ b/GPU/GPUTracking/cmake/kernel_helpers.cmake @@ -83,6 +83,7 @@ function(o2_gpu_add_kernel kernel_name kernel_files kernel_bounds kernel_type) endif() list(APPEND O2_GPU_KERNEL_TEMPLATE_FILES "${TMP_KERNEL_CLASS_FILE}.cxx") list(REMOVE_DUPLICATES O2_GPU_KERNEL_TEMPLATE_FILES) + list(FILTER O2_GPU_KERNEL_TEMPLATE_FILES EXCLUDE REGEX "^-$") list(TRANSFORM O2_GPU_KERNEL_TEMPLATE_FILES APPEND "\"") list(TRANSFORM O2_GPU_KERNEL_TEMPLATE_FILES PREPEND "#include \"") list(JOIN O2_GPU_KERNEL_TEMPLATE_FILES "\n" O2_GPU_KERNEL_TEMPLATE_FILES) From 8dc83c1252a649b944d001265f97998f96560b8f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 21 Apr 2024 19:53:59 +0200 Subject: [PATCH 0143/2997] GPU: Add cache folder and file lock options to RTC --- .../Base/cuda/GPUReconstructionCUDAGenRTC.cxx | 31 +++++++++++++++++-- GPU/GPUTracking/Definitions/GPUSettingsList.h | 4 +++ .../Standalone/Benchmark/standalone.cxx | 4 +-- GPU/Workflow/src/GPUWorkflowSpec.cxx | 6 ++-- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx index d8383e870f7ac..5a4ee1ea01e25 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx @@ -23,6 +23,9 @@ #ifdef GPUCA_HAVE_O2HEADERS #include "Framework/SHA1.h" #endif +#include +#include +#include using namespace GPUCA_NAMESPACE::gpu; @@ -62,11 +65,27 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) nCompile = mProcessingSettings.rtc.compilePerKernel ? kernels.size() : 1; bool cacheLoaded = false; + int fd = 0; if (mProcessingSettings.rtc.cacheOutput) { + if (mProcessingSettings.RTCcacheFolder != ".") { + std::filesystem::create_directories(mProcessingSettings.RTCcacheFolder); + } #ifndef GPUCA_HAVE_O2HEADERS throw std::runtime_error("Cannot use RTC cache without O2 headers"); #else - FILE* fp = fopen("rtc.cuda.cache", "rb"); + if (mProcessingSettings.rtc.cacheMutex) { + mode_t mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + fd = open((mProcessingSettings.RTCcacheFolder + "/cache.lock").c_str(), O_RDWR | O_CREAT | O_CLOEXEC, mask); + if (fd == -1) { + throw std::runtime_error("Error opening rtc cache mutex lock file"); + } + fchmod(fd, mask); + if (lockf(fd, F_LOCK, 0)) { + throw std::runtime_error("Error locking rtc cache mutex file"); + } + } + + FILE* fp = fopen((mProcessingSettings.RTCcacheFolder + "/rtc.cuda.cache").c_str(), "rb"); char sharead[20]; if (fp) { size_t len; @@ -100,6 +119,7 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) break; } GPUSettingsProcessingRTC cachedSettings; + static_assert(std::is_trivially_copyable_v == true, "GPUSettingsProcessingRTC must be POD"); if (fread(&cachedSettings, sizeof(cachedSettings), 1, fp) != 1) { throw std::runtime_error("Cache file corrupt"); } @@ -183,7 +203,7 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) } #ifdef GPUCA_HAVE_O2HEADERS if (mProcessingSettings.rtc.cacheOutput) { - FILE* fp = fopen("rtc.cuda.cache", "w+b"); + FILE* fp = fopen((mProcessingSettings.RTCcacheFolder + "/rtc.cuda.cache").c_str(), "w+b"); if (fp == nullptr) { throw std::runtime_error("Cannot open cache file for writing"); } @@ -218,9 +238,16 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) } } fclose(fp); + } #endif } + if (mProcessingSettings.rtc.cacheOutput && mProcessingSettings.rtc.cacheMutex) { + if (lockf(fd, F_ULOCK, 0)) { + throw std::runtime_error("Error unlocking RTC cache mutex file"); + } + close(fd); + } #endif return 0; diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 982aaaa5ed69d..3175b088d8440 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -191,6 +191,7 @@ AddSubConfig(GPUSettingsRecTRD, trd) AddHelp("help", 'h') EndConfig() +#ifndef __OPENCL__ // Settings steering the processing once the device was selected, only available on the host BeginSubConfig(GPUSettingsProcessingRTC, rtc, configStandalone.proc, "RTC", 0, "Processing settings", proc_rtc) AddOption(cacheOutput, bool, false, "", 0, "Cache RTC compilation results") @@ -198,6 +199,7 @@ AddOption(optConstexpr, bool, true, "", 0, "Replace constant variables by static AddOption(compilePerKernel, bool, true, "", 0, "Run one RTC compilation per kernel") AddOption(enable, bool, false, "", 0, "Use RTC to optimize GPU code") AddOption(runTest, int, 0, "", 0, "Do not run the actual benchmark, but just test RTC compilation (1 full test, 2 test only compilation)") +AddOption(cacheMutex, bool, true, "", 0, "Use a file lock to serialize access to the cache folder") AddHelp("help", 'h') EndConfig() @@ -276,11 +278,13 @@ AddOption(tpcSingleSector, int, -1, "", 0, "Restrict TPC processing to a single AddOption(tpcDownscaledEdx, unsigned char, 0, "", 0, "If != 0, downscale dEdx processing (if enabled) to x %") AddOption(tpcMaxAttachedClustersPerSectorRow, unsigned int, 51000, "", 0, "Maximum number of TPC attached clusters which can be decoded per SectorRow") AddOption(tpcUseOldCPUDecoding, bool, false, "", 0, "Enable old CPU-based TPC decoding") +AddOption(RTCcacheFolder, std::string, "./rtccache/", "", 0, "Folder in which the cache file is stored") AddVariable(eventDisplay, GPUCA_NAMESPACE::gpu::GPUDisplayFrontendInterface*, nullptr) AddSubConfig(GPUSettingsProcessingRTC, rtc) AddSubConfig(GPUSettingsProcessingParam, param) AddHelp("help", 'h') EndConfig() +#endif // __OPENCL__ #ifndef GPUCA_GPUCODE_DEVICE // Light settings concerning the event display (can be changed without rebuilding vertices) diff --git a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx index 4e3cff32c5bc9..92199f06a5f68 100644 --- a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx +++ b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx @@ -297,8 +297,8 @@ int SetupReconstruction() GPUSettingsGRP grp = rec->GetGRPSettings(); GPUSettingsRec recSet; GPUSettingsProcessing procSet; - memcpy((void*)&recSet, (void*)&configStandalone.rec, sizeof(GPUSettingsRec)); - memcpy((void*)&procSet, (void*)&configStandalone.proc, sizeof(GPUSettingsProcessing)); + recSet = configStandalone.rec; + procSet = configStandalone.proc; GPURecoStepConfiguration steps; if (configStandalone.eventGenerator) { diff --git a/GPU/Workflow/src/GPUWorkflowSpec.cxx b/GPU/Workflow/src/GPUWorkflowSpec.cxx index 36ce6da419d4b..af65de4ce5c48 100644 --- a/GPU/Workflow/src/GPUWorkflowSpec.cxx +++ b/GPU/Workflow/src/GPUWorkflowSpec.cxx @@ -321,11 +321,11 @@ void GPURecoWorkflowSpec::init(InitContext& ic) mode_t mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; fd = open("/tmp/o2_gpu_memlock_mutex.lock", O_RDWR | O_CREAT | O_CLOEXEC, mask); if (fd == -1) { - throw std::runtime_error("Error opening lock file"); + throw std::runtime_error("Error opening memlock mutex lock file"); } fchmod(fd, mask); if (lockf(fd, F_LOCK, 0)) { - throw std::runtime_error("Error locking file"); + throw std::runtime_error("Error locking memlock mutex file"); } } std::chrono::time_point start, end; @@ -342,7 +342,7 @@ void GPURecoWorkflowSpec::init(InitContext& ic) } if (mConfParam->mutexMemReg) { if (lockf(fd, F_ULOCK, 0)) { - throw std::runtime_error("Error unlocking file"); + throw std::runtime_error("Error unlocking memlock mutex file"); } close(fd); } From 5cb50ca9458c79cdc6fbfc7c24f14a11ce6bb846 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 22 Apr 2024 14:04:29 +0200 Subject: [PATCH 0144/2997] GPU CMake: Fix -W option must be passed only to compiler, not to device compilation --- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx | 1 - dependencies/FindO2GPU.cmake | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx index 5a4ee1ea01e25..b291bf735aee3 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx @@ -238,7 +238,6 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) } } fclose(fp); - } #endif } diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 302f5ab93209f..bd244fcaaecbe 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -111,7 +111,7 @@ if(ENABLE_CUDA) endif() endif() if(CMAKE_CUDA_COMPILER) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler \"${O2_GPU_CMAKE_CXX_FLAGS_NOSTD}\" --expt-relaxed-constexpr --extended-lambda --allow-unsupported-compiler -Xptxas -v -Wno-attributes") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler \"${O2_GPU_CMAKE_CXX_FLAGS_NOSTD}\" --expt-relaxed-constexpr --extended-lambda --allow-unsupported-compiler -Xptxas -v -Xcompiler -Wno-attributes") if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "12.3") string(APPEND CMAKE_CUDA_FLAGS " -Xcudafe --diag_suppress=20257") # TODO: Cleanup endif() From 53a14ef86448da10445cca63c9231997a354ab86 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 22 Apr 2024 14:07:54 +0200 Subject: [PATCH 0145/2997] dpl-workflow: Add option to use GPU RTC --- prodtests/full-system-test/dpl-workflow.sh | 1 + prodtests/full-system-test/start_tmux.sh | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index f67c5c01e81f1..5b5d84c413abe 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -320,6 +320,7 @@ if has_detector_calib PHS && workflow_has_parameter CALIB; then fi [[ ${O2_GPU_DOUBLE_PIPELINE:-$EPNSYNCMODE} == 1 ]] && GPU_CONFIG+=" --enableDoublePipeline" +[[ ${O2_GPU_RTC:-0} == 1 ]] && GPU_CONFIG_KEY+="GPU_proc_rtc.enable=1;GPU_proc_rtc.cacheOutput=1;GPU_proc.RTCcacheFolder=/tmp/o2_gpu_rtc_cache;" ( workflow_has_parameter AOD || [[ -z "$DISABLE_ROOT_OUTPUT" ]] || needs_root_output o2-emcal-cell-writer-workflow ) && has_detector EMC && RAW_EMC_SUBSPEC=" --subspecification 1 " has_detector_reco MID && has_detector_matching MCHMID && MFTMCHConf="FwdMatching.useMIDMatch=true;" || MFTMCHConf="FwdMatching.useMIDMatch=false;" diff --git a/prodtests/full-system-test/start_tmux.sh b/prodtests/full-system-test/start_tmux.sh index e56514196afe3..22b0ce2ddcd2a 100755 --- a/prodtests/full-system-test/start_tmux.sh +++ b/prodtests/full-system-test/start_tmux.sh @@ -97,19 +97,16 @@ fi FST_SLEEP0=0 FST_SLEEP1=0 -FST_SLEEP2=45 +FST_SLEEP2=30 if [[ -z $SHM_MANAGER_SHMID ]]; then rm -f /dev/shm/*fmq* if [[ `ls /dev/shm/*fmq* 2> /dev/null | wc -l` != "0" ]]; then echo "FMQ SHM files left which cannot be deleted, please clean up!" exit 1 fi -else - FST_SLEEP0=0 - FST_SLEEP1=0 - FST_SLEEP2=30 fi [[ ! -z $FST_TMUX_DD_WAIT ]] && FST_SLEEP2=$FST_TMUX_DD_WAIT +[[ ${O2_GPU_RTC:-0} == 1 ]] && FST_SLEEP2=60 if workflow_has_parameter CALIB_PROXIES; then CALIB_COMMAND="$GEN_TOPO_MYDIR/aggregator-workflow.sh" From e802151a3c49e22e8024b52daf09091c51d3cba6 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Mon, 22 Apr 2024 11:38:29 +0200 Subject: [PATCH 0146/2997] [EMCAL-630] Improve documentation of RawToCellConverterSpec - Document functions which were missing a documentation so far - Add class documentation --- .../EMCALWorkflow/RawToCellConverterSpec.h | 152 ++++++++++++++++-- 1 file changed, 143 insertions(+), 9 deletions(-) diff --git a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h index a418858c0b578..52797719d1fed 100644 --- a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h +++ b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h @@ -47,10 +47,72 @@ namespace reco_workflow { /// \class RawToCellConverterSpec -/// \brief Coverter task for Raw data to EMCAL cells +/// \brief Coverter task for Raw data to EMCAL cells and trigger objects /// \author Hadi Hassan , Oak Ridge National Laboratory +/// \author Markus Fasel , Oak Ridge National Laboratory +/// \ingroup EMCALworkflow /// \since December 10, 2019 +//// +/// General reconstruction task of EMCAL raw data of FEC and trigger sources, running during the synchronous +/// reconstruction. The task decodees pages from ALTRO, Fake ALTRO and STU sources, and mergees the data according +/// to events (triggers). The data is then further processed based on the origin of the data: /// +/// - in case of FEC data (cells or LEDMONS) a raw fit is performed, and data from high- and low-gain channels are +/// merged, always preferring the high-gain data if not saturated (better resolution) +/// - in case of Fake ALTRO data (TRU) the L0 timesums, trigger patches and TRU information are reconstructed. For +/// the trigger patches a small peak finder selects the time sample with the max. patch energy. For the L0 timesums +/// a fixed L0 time (8) is used for all event types +/// +/// FEC and trigger information are ordered according to events and streamed to their output buffers, where corresponding +/// trigger records mark ranges in the buffer belonging to the same trigger. Tasks subscribing to outputs from this +/// task must always subscribe to teh trigger records in addition. +/// +/// Several components of the task (raw parsing, ALTRO decoding, channel mapping and geometry, raw fit) can end in error +/// states, particularly due to unexpected data. Error handling is performed internally at different stages. Errors are +/// cathegoriezed as major or minor errors, where major errors prevent decoding the page while minor errors only lead +/// to loss of certain segments. For monitoring tasks must subscribe to EMC/DECODERERR. +/// +/// In order to guarantee data consistency a link checker compares the links contributing to data from a certain trigger +/// to the links activated in the DCS. If not all links are present the timeframe is discarded. In order to switch off +/// that feature the option --no-checkactivelinks must be activated. +/// +/// Inputs: +/// | Input spec | Optional | CCDB | Purpose | +/// |----------------------|----------|------|----------------------------------------------| +/// | EMC/RAWDATA | no | no | EMCAL raw data | +/// | FLP/DISTSUBTIMEFRAME | yes | no | Message send when no data was received in TF | +/// | EMC/RECOPARAM | no | yes | Reconstruction parameters | +/// | EMC/FEEDCS | no | yes | FEE DCS information | +/// +/// Outputs: +/// | Input spec | Subspec (default) | Optional | Purpose | +/// |----------------------|-------------------|-----------|----------------------------------------------------| +/// | EMC/CELLS | 1 | no | EMCAL cell (tower) data | +/// | EMC/CELLSTRGR | 1 | no | Trigger records related to cell data | +/// | EMC/DECODERERR | 1 | yes | Decoder errors (for QC), if enabled | +/// | EMC/TRUS | 1 | yes | TRU information, if trigger reconstruction enabled | +/// | EMC/TRUSTRGR | 1 | yes | Trigger reconrds related to TRU information | +/// | EMC/PATCHES | 1 | yes | Trigger patches, if trigger reconstruction enabled | +/// | EMC/PATCHESTRGR | 1 | yes | Trigger reconrds related to trigger patches | +/// | EMC/FASTORS | 1 | yes | L0 timesums, if trigger reconstruction enabled | +/// | EMC/FASTORSTRGR | 1 | yes | Trigger reconrds related to L0 timesums | +/// +/// Workflow options (via --EMCALRawToCellConverterSpec ...): +/// | Option | Default | Possible values | Purpose | +/// |---------------------|---------|-----------------|------------------------------------------------| +/// | fitmethod | gamma2 | gamma2,standard | Raw fit method | +/// | maxmessage | 100 | any int | Max. amount of error messages on infoLogger | +/// | printtrailer | false | set (bool) | Print RCU trailer (for debugging) | +/// | no-mergeHGLG | false | set (bool) | Do not merge HG and LG channels for same tower | +/// | no-checkactivelinks | false | set (bool) | Do not check for active links per BC | +/// | no-evalpedestal | false | set (bool) | Disable pedestal evaluation | +/// +/// Global switches of the EMCAL reco workflow related to the RawToCellConverter: +/// | Option | Default | Purpose | +/// | -------------------------------|---------|-----------------------------------------------| +/// | disable-decoding-errors | false | Disable sending decoding errors | +/// | disable-trigger-reconstruction | false | Disable trigger reconstruction | +/// | ignore-dist-stf | false | disable subscribing to FLP/DISTSUBTIMEFRAME/0 | class RawToCellConverterSpec : public framework::Task { public: @@ -297,27 +359,99 @@ class RawToCellConverterSpec : public framework::Task /// maximum. The patch time is the start time of the 4-integral std::tuple reconstructTriggerPatch(const gsl::span fastors) const; + /// \brief Handling of mapper hardware address errors + /// \param error Exception raised by the mapper + /// \param ddlID DDL ID of the segment raising the exception + /// \param hwaddress Hardware address raising the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. void handleAddressError(const Mapper::AddressNotFoundException& error, int ddlID, int hwaddress); + /// \brief Handler function for major ALTRO decoder errors + /// \param altroerror Exception raised by the ALTRO decoder + /// \param ddlID DDL ID of the segment raising the exception + /// \param hwaddress Hardware address raising the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. void handleAltroError(const o2::emcal::AltroDecoderError& altroerror, int ddlID); + /// \brief Handler function for minor ALTRO errors + /// \param altroerror Minor errors created by the ALTRO decoder + /// \param ddlID DDL ID of the segment raising the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. void handleMinorAltroError(const o2::emcal::MinorAltroDecodingError& altroerror, int ddlID); + /// \brief Handler function of mapper errors related to invalid DDL + /// \param error Exception raised by the mapper + /// \param feeID FEE ID (DDL ID) of the segment raising the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. void handleDDLError(const MappingHandler::DDLInvalid& error, int feeID); - void handleGeometryError(const ModuleIndexException& e, int supermoduleID, int cellID, int hwaddress, ChannelType_t chantype); - + /// \brief Handler function of errors related to geometry (invalid supermodule / module/ tower ...) + /// \param error Geometry exception + /// \param supermoduleID Supermodule ID of the exception + /// \param cellID Cell (Tower) ID of the exception + /// \param hwaddress Hardware address raising the exception + /// \param chantype Channel type of the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. + void handleGeometryError(const ModuleIndexException& error, int supermoduleID, int cellID, int hwaddress, ChannelType_t chantype); + + /// \brief Handler function of mapper errors related to invalid DDL + /// \param error Exception raised by the mapper + /// \param feeID FEE ID (DDL ID) of the segment raising the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. void handleFitError(const o2::emcal::CaloRawFitter::RawFitterError_t& fiterror, int ddlID, int cellID, int hwaddress); - /// \brief handler function for gain type errors + /// \brief Handler function for gain type errors /// \param errortype Gain error type - /// \param ddlID ID of the DDL - /// \param hwaddress Hardware address + /// \param ddlID DDL ID of the segment raising the exception + /// \param hwaddress Hardware address raising the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. void handleGainError(const o2::emcal::reconstructionerrors::GainError_t& errortype, int ddlID, int hwaddress); - void handlePageError(const RawDecodingError& e); - - void handleMinorPageError(const RawReaderMemory::MinorError& e); + /// \brief Handler function for raw page decoding errors (i.e. header/trailer corruptions) + /// \param error Raw page error + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. + void handlePageError(const RawDecodingError& error); + + /// \brief Handler function for minor raw page decoding errors (i.e. header/trailer corruptions) + /// \param error Raw page error + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. + void handleMinorPageError(const RawReaderMemory::MinorError& error); header::DataHeader::SubSpecificationType mSubspecification = 0; ///< Subspecification for output channels int mNoiseThreshold = 0; ///< Noise threshold in raw fit From 9e505eaeccc68415889f9baaf0adbf7d7ff8553f Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Mon, 22 Apr 2024 13:06:32 +0200 Subject: [PATCH 0147/2997] [EMCAL-911] Improve documentation of RecoContainer - Fix headers of classes (particularly ingroup) - Add class documentation --- .../EMCALReconstruction/FastORTimeSeries.h | 2 +- .../EMCALReconstruction/RecoContainer.h | 41 +++++++++++++++++-- .../EMCALReconstruction/TRUDataHandler.h | 4 +- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/FastORTimeSeries.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/FastORTimeSeries.h index b6dac4a3b3d0c..0918fced0f999 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/FastORTimeSeries.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/FastORTimeSeries.h @@ -21,7 +21,7 @@ namespace o2::emcal /// \class FastORTimeSeries /// \brief Container for FastOR time series /// \author Markus Fasel , Oak Ridge National Laboratory -/// \ingroup EMCALReconstruction +/// \ingroup EMCALreconstruction /// \since April 19, 2024 /// /// Time series are encoded in bunches in the raw data, which are usually time-reversed. diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RecoContainer.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RecoContainer.h index e02cafd1c3769..36ce04267a47f 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RecoContainer.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/RecoContainer.h @@ -54,13 +54,25 @@ struct RecCellInfo { /// \class EventContainer /// \brief Containter of cells for a given event -/// \ingroup EMCALReconstruction +/// \author Markus Fasel , Oak Ridge National Laboratory +/// \ingroup EMCALreconstruction +/// \since May 30, 2023 +/// +/// The EventContainer is part of the reco container and keeps the cell / LEDMON / TRU +/// data of a given event (trigger) defined by the BC and orbit in the raw data header. +/// In case the gain type merging is activated the event container performs on-the-fly +/// merging of high- and low-gain data for cells and LEDMONS keeping only high- or +/// low-gain and preferring the high-gain due to better resolution if not saturated. +/// +/// Error handling: +/// The EventContainer can raise a TRUIndexException in case TRU information with an +/// unexpected index (>= 52) is added / requested. class EventContainer { public: /// \class TRUIndexException /// \brief Handler for access of TRU data with invalid TRU index - /// \ingroup EMCALReconstruction + /// \ingroup EMCALreconstruction class TRUIndexException final : public std::exception { public: @@ -222,7 +234,18 @@ class EventContainer /// \class RecoContainer /// \brief Handler for cells/LEDMONS/Trigger data in timeframes -/// \ingroup EMCALReconstruction +/// \author Markus Fasel , Oak Ridge National Laboratory +/// \ingroup EMCALreconstruction +/// \since May 30, 2023 +/// +/// The RecoContainer handles the cell/LEDMON/trigger data of all events of a given +/// timeframe during the reconstruction. Event data are handled internally via the +/// EventContainer, where the RecoContainer provides access to. +/// +/// Error handling: +/// The RecoContainer can raise an InteractionNotFoundException in case read access +/// is requested for an interaction based on the o2::InteractionRecord which is not +/// for which no data was inserted into the container. class RecoContainer { public: @@ -291,7 +314,17 @@ class RecoContainer /// \class RecoContainerReader /// \brief Iterator over reco containers -/// \ingroup EMCALReconstruction +/// \author Markus Fasel , Oak Ridge National Laboratory +/// \ingroup EMCALreconstruction +/// \since May 30, 2023 +/// +/// The RecoContainerReader iterates over the events stored in the RecoContainer in +/// a time-ordered sequence. The function hasNext checks whether there are more +/// events to iterate over, while nextEvent provides access to the next event. +/// +/// Error handling: +/// The RecoContainerReader can raise an InvalidAccessException in case access is tried to +/// invalid data. class RecoContainerReader { public: diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/TRUDataHandler.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/TRUDataHandler.h index 419e0dc773e36..811faf13a05ff 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/TRUDataHandler.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/TRUDataHandler.h @@ -28,7 +28,7 @@ namespace o2::emcal /// \class TRUDataHandler /// \brief Helper class to handle decoded TRU data during the reconstruction /// \author Markus Fasel , Oak Ridge National Laboratory -/// \ingroup EMCALReconstruction +/// \ingroup EMCALreconstruction /// \since April 19, 2024 /// /// The decoded TRU data contains the following information @@ -44,7 +44,7 @@ class TRUDataHandler public: /// \class PatchIndexException /// \brief Handler of errors related to invalid trigger patch IDs - /// \ingroup EMCALReconstruction + /// \ingroup EMCALreconstruction class PatchIndexException final : public std::exception { public: From 09f01bac07b44361c98baa314259b69719d77713 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 22 Apr 2024 12:48:33 +0200 Subject: [PATCH 0148/2997] Account ITS/MFT ROF start shift in AOD ITS/MFT standalone tracks time --- .../include/AODProducerWorkflow/AODProducerWorkflowSpec.h | 2 ++ Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 13a55526afc56..49ba88c8c5858 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -301,6 +301,8 @@ class AODProducerWorkflowDPL : public Task std::vector mMCHROFs; // mapping from MCH tracks ID to corresponding ROF (for SA MCH tracks time extraction) double mITSROFrameHalfLengthNS = -1; // ITS ROF half length double mMFTROFrameHalfLengthNS = -1; // ITS ROF half length + double mITSROFBiasNS = 0; // ITS ROF start bias + double mMFTROFBiasNS = 0; // ITS ROF start bias double mNSigmaTimeTrack = -1; // number track errors sigmas (for gaussian errors only) used in track-vertex matching double mTimeMarginTrackTime = -1; // safety margin in NS used for track-vertex matching (additive to track uncertainty) double mTPCBinNS = -1; // inverse TPC time-bin in ns diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 63491ec048357..388845edc575c 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -377,7 +377,7 @@ void AODProducerWorkflowDPL::addToMFTTracksTable(mftTracksCursorType& mftTracksC int bcSlice[2] = {-1, -1}; const auto& track = data.getMFTTrack(trackID); const auto& rof = data.getMFTTracksROFRecords()[mMFTROFs[trackID.getIndex()]]; - float trackTime = rof.getBCData().differenceInBC(mStartIR) * o2::constants::lhc::LHCBunchSpacingNS + mMFTROFrameHalfLengthNS; + float trackTime = rof.getBCData().differenceInBC(mStartIR) * o2::constants::lhc::LHCBunchSpacingNS + mMFTROFrameHalfLengthNS + mMFTROFBiasNS; float trackTimeRes = mMFTROFrameHalfLengthNS; bool needBCSlice = collisionID < 0; std::uint64_t bcOfTimeRef; @@ -2422,7 +2422,7 @@ AODProducerWorkflowDPL::TrackExtraInfo AODProducerWorkflowDPL::processBarrelTrac extraInfoHolder.itsClusterSizes = itsTrack.getClusterSizes(); if (src == GIndex::ITS) { // standalone ITS track should set its time from the ROF const auto& rof = data.getITSTracksROFRecords()[mITSROFs[trackIndex.getIndex()]]; - double t = rof.getBCData().differenceInBC(mStartIR) * o2::constants::lhc::LHCBunchSpacingNS + mITSROFrameHalfLengthNS; + double t = rof.getBCData().differenceInBC(mStartIR) * o2::constants::lhc::LHCBunchSpacingNS + mITSROFrameHalfLengthNS + mITSROFBiasNS; setTrackTime(t, mITSROFrameHalfLengthNS, false); } } else if (contributorsGID[GIndex::Source::ITSAB].isIndexSet()) { // this is an ITS-TPC afterburner contributor @@ -2652,9 +2652,10 @@ void AODProducerWorkflowDPL::updateTimeDependentParams(ProcessingContext& pc) const auto& alpParamsITS = o2::itsmft::DPLAlpideParam::Instance(); mITSROFrameHalfLengthNS = 0.5 * (grpECS->isDetContinuousReadOut(o2::detectors::DetID::ITS) ? alpParamsITS.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingNS : alpParamsITS.roFrameLengthTrig); - + mITSROFBiasNS = o2::itsmft::DPLAlpideParam::Instance().roFrameBiasInBC * o2::constants::lhc::LHCBunchSpacingNS; const auto& alpParamsMFT = o2::itsmft::DPLAlpideParam::Instance(); mMFTROFrameHalfLengthNS = 0.5 * (grpECS->isDetContinuousReadOut(o2::detectors::DetID::MFT) ? alpParamsMFT.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingNS : alpParamsMFT.roFrameLengthTrig); + mMFTROFBiasNS = o2::itsmft::DPLAlpideParam::Instance().roFrameBiasInBC * o2::constants::lhc::LHCBunchSpacingNS; // RS FIXME: this is not yet fetched from the CCDB auto& elParam = o2::tpc::ParameterElectronics::Instance(); From f84b44052be72dc9c969c32e92392436782505a3 Mon Sep 17 00:00:00 2001 From: Ruben Shahoyan Date: Tue, 23 Apr 2024 10:28:12 +0200 Subject: [PATCH 0149/2997] Add mult estimators to matching debug output (#13064) --- Detectors/GlobalTracking/CMakeLists.txt | 1 + .../include/GlobalTracking/MatchTPCITS.h | 7 +++- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 42 ++++++++++++++++++- .../src/TPCITSMatchingSpec.cxx | 1 + .../Interface/GPUO2InterfaceRefit.h | 1 + 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/Detectors/GlobalTracking/CMakeLists.txt b/Detectors/GlobalTracking/CMakeLists.txt index bd5fb4f9976d1..cc62bac02a1cb 100644 --- a/Detectors/GlobalTracking/CMakeLists.txt +++ b/Detectors/GlobalTracking/CMakeLists.txt @@ -36,6 +36,7 @@ o2_add_library(GlobalTracking O2::FT0Reconstruction O2::TPCFastTransformation O2::GPUO2Interface + O2::GPUTracking O2::TPCBase O2::TPCReconstruction O2::TPCCalibration diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index a2cb21bdaf04f..f0dd8ce86a72a 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -372,6 +372,8 @@ class MatchTPCITS ///< set Bunch filling and init helpers for validation by BCs void setBunchFilling(const o2::BunchFilling& bf); + void setNHBPerTF(int n) { mNHBPerTF = n; } + ///< ITS readout mode void setITSTriggered(bool v) { mITSTriggered = v; } bool isITSTriggered() const { return mITSTriggered; } @@ -563,6 +565,9 @@ class MatchTPCITS float mBz = 0; ///< nominal Bz int mTFCount = 0; ///< internal TF counter for debugger int mNThreads = 1; ///< number of OMP threads + int mNHBPerTF = 0; + int mNTPCOccBinLength = 0; ///< TPC occ. histo bin length in TBs + float mNTPCOccBinLengthInv; o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF ///========== Parameters to be set externally, e.g. from CCDB ==================== @@ -668,7 +673,7 @@ class MatchTPCITS std::vector mTPCLblWork; ///< TPC track labels std::vector mITSLblWork; ///< ITS track labels std::vector mWinnerChi2Refit; ///< vector of refitChi2 for winners - + std::vector mTBinClOcc; ///< TPC occupancy histo: i-th entry is the integrated occupancy for ~1 orbit starting from the TB = i*mNTPCOccBinLength // ------------------------------ std::vector mTPCABSeeds; ///< pool of primary TPC seeds for AB ///< indices of selected track entries in mTPCWork (for tracks selected by AfterBurner) diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 2a6e8efd9ed03..6ea76f3b43adb 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -45,6 +45,8 @@ #include "ITStracking/IOUtils.h" #include "GPUO2Interface.h" // Needed for propper settings in GPUParam.h +#include "GPUParam.h" +#include "GPUParam.inc" #ifdef WITH_OPENMP #include #endif @@ -575,6 +577,28 @@ bool MatchTPCITS::prepareTPCData() } */ mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); + mNTPCOccBinLength = mTPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins; + mTBinClOcc.clear(); + if (mNTPCOccBinLength > 1 && mTPCRefitterOccMap.size()) { + mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength; + int nTPCBins = mNHBPerTF * o2::constants::lhc::LHCMaxBunches / 8, ninteg = 0; + int nTPCOccBins = nTPCBins * mNTPCOccBinLengthInv, sumBins = std::max(1, int(o2::constants::lhc::LHCMaxBunches / 8 * mNTPCOccBinLengthInv)); + mTBinClOcc.resize(nTPCOccBins); + float sm = 0., tb = (nTPCOccBins - 0.5) * mNTPCOccBinLength, mltPrev = 0.; + for (int i = nTPCOccBins; i--;) { + float mlt = mTPCRefitter->getParam()->GetUnscaledMult(tb); + sm += mlt; + mTBinClOcc.push_back(sm); + if (ninteg++ > mNTPCOccBinLength) { + sm -= mltPrev; + } + // LOGP(info, "BIN {} of {} -> {} with inst val {} (prev = {}) BL={} nInt={} tb={}", i, nTPCOccBins, sm, mlt, mltPrev, mNTPCOccBinLength, ninteg, tb); + mltPrev = mlt; + tb -= mNTPCOccBinLength; + } + } else { + mTBinClOcc.resize(1); + } mInteractionMUSLUT.clear(); mInteractionMUSLUT.resize(maxTime + 3 * o2::constants::lhc::LHCOrbitMUS, -1); mTimer[SWPrepTPC].Stop(); @@ -1478,6 +1502,8 @@ void MatchTPCITS::fillCalibDebug(int ifit, int iTPC, const o2::dataformats::Trac itsRefAltPID.setX(-10); } } + int tb = mTPCTracksArray[tTPC.sourceID].getTime0() * mNTPCOccBinLengthInv; + float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]); (*mDBGOut) << "refit" << "tpcOrig=" << mTPCTracksArray[tTPC.sourceID] << "itsOrig=" << mITSTracksArray[tITS.sourceID] << "itsRef=" << tITS << "tpcRef=" << tTPC << "matchRefit=" << match << "timeCorr=" << timeC << "dTimeFT0=" << minDiffFT0 << "dTimes=" << dtimes @@ -1487,6 +1513,9 @@ void MatchTPCITS::fillCalibDebug(int ifit, int iTPC, const o2::dataformats::Trac << "itsLbl=" << mITSLblWork[iITS] << "tpcLbl=" << mTPCLblWork[iTPC]; } (*mDBGOut) << "refit" + << "multTPC=" << mltTPC + << "multITSTr=" << mITSTrackROFRec[tITS.roFrame] + << "multITSCl=" << mITSClusterROFRec[tITS.roFrame] << "tf=" << mTFCount << "\n"; } #endif @@ -2803,8 +2832,14 @@ void MatchTPCITS::fillTPCITSmatchTree(int itsID, int tpcID, int rejFlag, float c (*mDBGOut) << "match" << "itsLbl=" << mITSLblWork[itsID] << "tpcLbl=" << mTPCLblWork[tpcID]; } + int tb = mTPCTracksArray[trackTPC.sourceID].getTime0() * mNTPCOccBinLengthInv; + float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]); (*mDBGOut) << "match" - << "rejFlag=" << rejFlag << "\n"; + << "rejFlag=" << rejFlag + << "multTPC=" << tb + << "multITSTr=" << mITSTrackROFRec[trackITS.roFrame] + << "multITSCl=" << mITSClusterROFRec[trackITS.roFrame] + << "\n"; mTimer[SWDBG].Stop(); } @@ -2833,7 +2868,12 @@ void MatchTPCITS::dumpWinnerMatches() (*mDBGOut) << "matchWin" << "itsLbl=" << mITSLblWork[iits] << "tpcLbl=" << mTPCLblWork[itpc]; } + int tb = mTPCTracksArray[tTPC.sourceID].getTime0() * mNTPCOccBinLengthInv; + float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]); (*mDBGOut) << "matchWin" + << "multTPC=" << mTPCRefitter->getParam()->GetUnscaledMult(mTPCTracksArray[tTPC.sourceID].getTime0()) + << "multITSTr=" << mITSTrackROFRec[tITS.roFrame] + << "multITSCl=" << mITSClusterROFRec[tITS.roFrame] << "\n"; } mTimer[SWDBG].Stop(); diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index b56c1217551ff..0dc20811087ae 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -184,6 +184,7 @@ void TPCITSMatchingDPL::updateTimeDependentParams(ProcessingContext& pc) mMatching.setITSTimeBiasInBC(alpParams.roFrameBiasInBC); mMatching.setSkipTPCOnly(mSkipTPCOnly); mMatching.setITSTriggered(!o2::base::GRPGeomHelper::instance().getGRPECS()->isDetContinuousReadOut(o2::detectors::DetID::ITS)); + mMatching.setNHBPerTF(o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF()); mMatching.setMCTruthOn(mUseMC); mMatching.setUseFT0(mUseFT0); mMatching.setVDriftCalib(mCalibMode); diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h index 5803dfbd68943..4437e51121163 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceRefit.h @@ -80,6 +80,7 @@ class GPUO2InterfaceRefit void setTrackReferenceX(float v); void setIgnoreErrorsAtTrackEnds(bool v); void updateCalib(const o2::gpu::CorrectionMapsHelper* trans, float bzNominalGPU); + auto getParam() const { return mParam.get(); } // To create shared cluster maps and occupancy maps. // param is an optional parameter to override the param object, by default a default object from --configKeyValues is used. From 17f8c92853d5a5f8b117d922235feec4e30f5088 Mon Sep 17 00:00:00 2001 From: Ole Schmidt Date: Tue, 23 Apr 2024 11:07:04 +0200 Subject: [PATCH 0150/2997] Demote exit transition timeout error to warning (#13036) * Demote exit transition timeout error to warning * Fix * Format --- Framework/Core/src/DataProcessingDevice.cxx | 2 +- Framework/Foundation/include/Framework/Signpost.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index d5a07a1ebfd52..d6b73bc7476f8 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -122,7 +122,7 @@ void on_transition_requested_expired(uv_timer_t* handle) auto* state = (DeviceState*)handle->data; state->loopReason |= DeviceState::TIMER_EXPIRED; O2_SIGNPOST_ID_FROM_POINTER(cid, device, handle); - O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "callback", "Exit transition timer expired. Exiting."); + O2_SIGNPOST_EVENT_EMIT_WARN(device, cid, "callback", "Exit transition timer expired. Exiting."); state->transitionHandling = TransitionHandlingState::Expired; } diff --git a/Framework/Foundation/include/Framework/Signpost.h b/Framework/Foundation/include/Framework/Signpost.h index 9ea8aea1192a9..fc22147415792 100644 --- a/Framework/Foundation/include/Framework/Signpost.h +++ b/Framework/Foundation/include/Framework/Signpost.h @@ -522,7 +522,7 @@ void o2_debug_log_set_stacktrace(_o2_log_t* log, int stacktrace) } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \ _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \ } \ - O2_RAW_LOG_RAW(warn, ##__VA_ARGS__); \ + O2_LOG_MACRO_RAW(warn, format, ##__VA_ARGS__); \ }) #define O2_SIGNPOST_START(log, id, name, format, ...) \ From 8a362064704d4c95553f109e97677fdc398981f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tuba=20G=C3=BCndem?= <48834043+tubagundem@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:18:21 +0200 Subject: [PATCH 0151/2997] =?UTF-8?q?TPC/simulation:=20Add=20PT=20correcti?= =?UTF-8?q?on=20to=20gas=20density=20using=20configurable=20p=E2=80=A6=20(?= =?UTF-8?q?#13048)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * TPC/simulation: Add PT correction to gas density using configurable parameters --- .../TPC/base/include/TPCBase/ParameterGas.h | 2 ++ Detectors/TPC/simulation/src/Detector.cxx | 29 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/ParameterGas.h b/Detectors/TPC/base/include/TPCBase/ParameterGas.h index 8e47391e39096..5e532a277b18e 100644 --- a/Detectors/TPC/base/include/TPCBase/ParameterGas.h +++ b/Detectors/TPC/base/include/TPCBase/ParameterGas.h @@ -39,6 +39,8 @@ struct ParameterGas : public o2::conf::ConfigurableParamHelper { float Nprim = 14.f; ///< Number of primary electrons per MIP and cm [1/cm] float ScaleFactorG4 = 0.85f; ///< Scale factor to tune WION for GEANT4 float FanoFactorG4 = 0.7f; ///< Parameter for smearing the number of ionizations (nel) using GEANT4 + float Pressure = 1013.25f; ///< Pressure [mbar] + float Temperature = 20.0f; ///< Temperature [°C] float BetheBlochParam[5] = {0.820172e-1f, 9.94795f, 8.97292e-05f, 2.05873f, 1.65272f}; ///< Parametrization of Bethe-Bloch O2ParamDef(ParameterGas, "TPCGasParam"); diff --git a/Detectors/TPC/simulation/src/Detector.cxx b/Detectors/TPC/simulation/src/Detector.cxx index 3344537dcec4f..60dcc542c70ff 100644 --- a/Detectors/TPC/simulation/src/Detector.cxx +++ b/Detectors/TPC/simulation/src/Detector.cxx @@ -315,6 +315,8 @@ void Detector::CreateMaterials() // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl //----------------------------------------------------------------- + const auto& gasParam = ParameterGas::Instance(); + Int_t iSXFLD = 2; Float_t sXMGMX = 10.0; // init the field tracking params @@ -326,6 +328,23 @@ void Detector::CreateMaterials() Float_t density; + // TODO: load pressure and temperature values from CCDB + const Double_t pressure = gasParam.Pressure; // in mbar + const Double_t temperature = gasParam.Temperature + 273.15; // in K + + // densities were taken for these values + const Double_t t1 = 293.15; // 20°C in K + const Double_t p1 = 1013.25; // 1 atm in mbars + + // sanity check - temperature between 10 and 30 deg, pressure between 800 and 1200 mbar + Double_t ptCorr = 1.; + if (TMath::Abs(temperature - 293.15) > 10. || TMath::Abs(pressure - 1000.) > 200.) { + ptCorr = 1.; + } else { + ptCorr = (pressure * t1) / (p1 * temperature); + } + LOG(info) << "Setting gas density correction to: " << ptCorr; + //***************** Gases ************************* //-------------------------------------------------------------- @@ -345,7 +364,7 @@ void Detector::CreateMaterials() density = 1.842e-3; - o2::base::Detector::Mixture(10, "CO2", amat, zmat, density, 2, wmat); + o2::base::Detector::Mixture(10, "CO2", amat, zmat, density * ptCorr, 2, wmat); // // Air // @@ -360,7 +379,7 @@ void Detector::CreateMaterials() // density = 0.001205; - o2::base::Detector::Mixture(11, "Air", amat, zmat, density, 2, wmat); + o2::base::Detector::Mixture(11, "Air", amat, zmat, density * ptCorr, 2, wmat); //---------------------------------------------------------------- // drift gases 5 mixtures, 5 materials @@ -466,9 +485,9 @@ void Detector::CreateMaterials() } // - o2::base::Detector::Mixture(12, gname1.Data(), amat1, zmat1, density, cnt, wmat1); // nonsensitive - o2::base::Detector::Mixture(13, gname2.Data(), amat1, zmat1, density, cnt, wmat1); // sensitive - o2::base::Detector::Mixture(40, gname3.Data(), amat1, zmat1, density, cnt, wmat1); // sensitive Kr + o2::base::Detector::Mixture(12, gname1.Data(), amat1, zmat1, density * ptCorr, cnt, wmat1); // nonsensitive + o2::base::Detector::Mixture(13, gname2.Data(), amat1, zmat1, density * ptCorr, cnt, wmat1); // sensitive + o2::base::Detector::Mixture(40, gname3.Data(), amat1, zmat1, density * ptCorr, cnt, wmat1); // sensitive Kr //---------------------------------------------------------------------- // solid materials From 35d6be7c5025bdcb9eefdbc81dee72bcd79af57d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 23 Apr 2024 10:43:56 +0200 Subject: [PATCH 0152/2997] CCDBApi: avoid leaking curl handle. --- CCDB/include/CCDB/CCDBDownloader.h | 4 +- CCDB/src/CCDBDownloader.cxx | 6 ++- CCDB/src/CcdbApi.cxx | 1 + CCDB/test/testCcdbApiDownloader.cxx | 74 +++++++++++------------------ 4 files changed, 38 insertions(+), 47 deletions(-) diff --git a/CCDB/include/CCDB/CCDBDownloader.h b/CCDB/include/CCDB/CCDBDownloader.h index 17b65deb06dc2..e53421dcc26fc 100644 --- a/CCDB/include/CCDB/CCDBDownloader.h +++ b/CCDB/include/CCDB/CCDBDownloader.h @@ -52,6 +52,7 @@ typedef struct DownloaderRequestData { HeaderObjectPair_t hoPair; std::map* headers; std::string userAgent; + curl_slist* optionsList; std::function localContentCallback; } DownloaderRequestData; @@ -296,6 +297,7 @@ class CCDBDownloader int hostInd; int locInd; DownloaderRequestData* requestData; + curl_slist** options; } PerformData; #endif @@ -421,6 +423,6 @@ typedef struct DataForClosingSocket { curl_socket_t socket; } DataForClosingSocket; -} // namespace o2 +} // namespace o2::ccdb #endif // O2_CCDB_CCDBDOWNLOADER_H diff --git a/CCDB/src/CCDBDownloader.cxx b/CCDB/src/CCDBDownloader.cxx index bd2bf22d0add9..8d13368688cb7 100644 --- a/CCDB/src/CCDBDownloader.cxx +++ b/CCDB/src/CCDBDownloader.cxx @@ -535,8 +535,10 @@ void CCDBDownloader::transferFinished(CURL* easy_handle, CURLcode curlCode) } } --(*performData->requestsLeft); + curl_slist_free_all(*performData->options); delete requestData; delete performData->codeDestination; + curl_easy_cleanup(easy_handle); } } break; } @@ -681,6 +683,7 @@ void CCDBDownloader::asynchSchedule(CURL* handle, size_t* requestCounter) curl_easy_getinfo(handle, CURLINFO_PRIVATE, &requestData); headerMap = &(requestData->hoPair.header); hostsPool = &(requestData->hosts); + auto* options = &(requestData->optionsList); // Prepare temporary data about transfer auto* data = new CCDBDownloader::PerformData(); // Freed in transferFinished @@ -692,6 +695,7 @@ void CCDBDownloader::asynchSchedule(CURL* handle, size_t* requestCounter) data->hostInd = 0; data->locInd = 0; data->requestData = requestData; + data->options = options; // Prepare handle and schedule download setHandleOptions(handle, data); @@ -719,4 +723,4 @@ std::string CCDBDownloader::prepareLogMessage(std::string host_url, std::string return fmt::format("CcdbDownloader finished transfer {}{}{} for {} (agent_id: {}) with http code: {}", host_url, (host_url.back() == '/') ? "" : "/", upath, (ts < 0) ? getCurrentTimestamp() : ts, userAgent, httpCode); } -} // namespace o2 +} // namespace o2::ccdb diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index 46d95bae477d4..4c4aa6ca74a80 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -1656,6 +1656,7 @@ void CcdbApi::scheduleDownload(RequestContext& requestContext, size_t* requestCo data->timestamp = requestContext.timestamp; data->localContentCallback = localContentCallback; data->userAgent = mUniqueAgentID; + data->optionsList = options_list; curl_easy_setopt(curl_handle, CURLOPT_URL, fullUrl.c_str()); initCurlOptionsForRetrieve(curl_handle, (void*)(&data->hoPair), writeCallback, false); diff --git a/CCDB/test/testCcdbApiDownloader.cxx b/CCDB/test/testCcdbApiDownloader.cxx index 68c8333f46ffa..264eff8fdb848 100644 --- a/CCDB/test/testCcdbApiDownloader.cxx +++ b/CCDB/test/testCcdbApiDownloader.cxx @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -129,7 +128,7 @@ std::vector prepareAsyncHandles(size_t num, std::vectorhoPair.object = dest; - data->hosts.push_back("http://ccdb-test.cern.ch:8080"); + data->hosts.emplace_back("http://ccdb-test.cern.ch:8080"); data->path = "Analysis/ALICE3/Centrality"; data->timestamp = 1646729604010; data->localContentCallback = nullptr; @@ -164,15 +163,20 @@ BOOST_AUTO_TEST_CASE(asynch_schedule_test) } while (transfersLeft > 0) { - downloader.runLoop(0); + downloader.runLoop(false); } for (int i = 0; i < TRANSFERS; i++) { - long httpCode; - curl_easy_getinfo(handles[i], CURLINFO_HTTP_CODE, &httpCode); - BOOST_CHECK(httpCode == 200); - BOOST_CHECK(dests[i]->size() != 0); - curl_easy_cleanup(handles[i]); + // I would claim that accessing the handles after they are complete + // is actually not supported by the current API, because it was + // previously relying on leaking the handles. Disabling the whole + // thing until we verify that's actually the case. + // + // long httpCode; + // curl_easy_getinfo(handles[i], CURLINFO_HTTP_CODE, &httpCode); + // BOOST_CHECK_EQUAL(httpCode, 200); + // BOOST_CHECK_NE(dests[i]->size(), 0); + // curl_easy_cleanup(handles[i]); delete dests[i]; } curl_global_cleanup(); @@ -191,13 +195,11 @@ BOOST_AUTO_TEST_CASE(perform_test) CURLcode curlCode = downloader.perform(handle); - BOOST_CHECK(curlCode == CURLE_OK); - std::cout << "CURL code: " << curlCode << "\n"; + BOOST_CHECK_EQUAL(curlCode, CURLE_OK); long httpCode; curl_easy_getinfo(handle, CURLINFO_HTTP_CODE, &httpCode); - BOOST_CHECK(httpCode == 200); - std::cout << "HTTP code: " << httpCode << "\n"; + BOOST_CHECK_EQUAL(httpCode, 200); curl_easy_cleanup(handle); curl_global_cleanup(); @@ -220,19 +222,13 @@ BOOST_AUTO_TEST_CASE(blocking_batch_test) auto curlCodes = downloader.batchBlockingPerform(handleVector); for (CURLcode code : curlCodes) { - BOOST_CHECK(code == CURLE_OK); - if (code != CURLE_OK) { - std::cout << "CURL Code: " << code << "\n"; - } + BOOST_CHECK_EQUAL(code, CURLE_OK); } for (CURL* handle : handleVector) { long httpCode; curl_easy_getinfo(handle, CURLINFO_HTTP_CODE, &httpCode); - BOOST_CHECK(httpCode == 200); - if (httpCode != 200) { - std::cout << "HTTP Code: " << httpCode << "\n"; - } + BOOST_CHECK_EQUAL(httpCode, 200); curl_easy_cleanup(handle); } @@ -261,19 +257,13 @@ BOOST_AUTO_TEST_CASE(test_with_break) auto curlCodes = downloader.batchBlockingPerform(handleVector); for (CURLcode code : curlCodes) { - BOOST_CHECK(code == CURLE_OK); - if (code != CURLE_OK) { - std::cout << "CURL Code: " << code << "\n"; - } + BOOST_CHECK_EQUAL(code, CURLE_OK); } for (CURL* handle : handleVector) { long httpCode; curl_easy_getinfo(handle, CURLINFO_HTTP_CODE, &httpCode); - BOOST_CHECK(httpCode == 200); - if (httpCode != 200) { - std::cout << "HTTP Code: " << httpCode << "\n"; - } + BOOST_CHECK_EQUAL(httpCode, 200); curl_easy_cleanup(handle); } @@ -292,19 +282,13 @@ BOOST_AUTO_TEST_CASE(test_with_break) auto curlCodes2 = downloader.batchBlockingPerform(handleVector2); for (CURLcode code : curlCodes2) { - BOOST_CHECK(code == CURLE_OK); - if (code != CURLE_OK) { - std::cout << "CURL Code: " << code << "\n"; - } + BOOST_CHECK_EQUAL(code, CURLE_OK); } for (CURL* handle : handleVector2) { long httpCode; curl_easy_getinfo(handle, CURLINFO_HTTP_CODE, &httpCode); - BOOST_CHECK(httpCode == 200); - if (httpCode != 200) { - std::cout << "HTTP Code: " << httpCode << "\n"; - } + BOOST_CHECK_EQUAL(httpCode, 200); curl_easy_cleanup(handle); } @@ -357,18 +341,18 @@ BOOST_AUTO_TEST_CASE(external_loop_test) CURLcode curlCode = downloader->perform(handle); - BOOST_CHECK(curlCode == CURLE_OK); + BOOST_CHECK_EQUAL(curlCode, CURLE_OK); long httpCode; curl_easy_getinfo(handle, CURLINFO_HTTP_CODE, &httpCode); - BOOST_CHECK(httpCode == 200); + BOOST_CHECK_EQUAL(httpCode, 200); curl_easy_cleanup(handle); curl_global_cleanup(); // Check if test timer and external loop are still alive - BOOST_CHECK(uv_is_active((uv_handle_t*)testTimer) != 0); - BOOST_CHECK(uv_loop_alive(uvLoop) != 0); + BOOST_CHECK_NE(uv_is_active((uv_handle_t*)testTimer), 0); + BOOST_CHECK_NE(uv_loop_alive(uvLoop), 0); // Downloader must be closed before uv_loop. // The reason for that are the uv_poll handles attached to the curl multi handle. @@ -384,11 +368,11 @@ BOOST_AUTO_TEST_CASE(external_loop_test) BOOST_AUTO_TEST_CASE(trim_host_url_test) { CCDBDownloader downloader; - BOOST_CHECK(downloader.trimHostUrl("http://localhost:8080") == "http://localhost:8080"); - BOOST_CHECK(downloader.trimHostUrl("http://localhost") == "http://localhost"); - BOOST_CHECK(downloader.trimHostUrl("http://localhost:8080/some/path") == "http://localhost:8080"); - BOOST_CHECK(downloader.trimHostUrl("http://localhost/some/path") == "http://localhost"); - BOOST_CHECK(downloader.trimHostUrl("http://localhost:8080/Task/Detector/1?HTTPOnly=true") == "http://localhost:8080"); + BOOST_CHECK_EQUAL(downloader.trimHostUrl("http://localhost:8080"), "http://localhost:8080"); + BOOST_CHECK_EQUAL(downloader.trimHostUrl("http://localhost"), "http://localhost"); + BOOST_CHECK_EQUAL(downloader.trimHostUrl("http://localhost:8080/some/path"), "http://localhost:8080"); + BOOST_CHECK_EQUAL(downloader.trimHostUrl("http://localhost/some/path"), "http://localhost"); + BOOST_CHECK_EQUAL(downloader.trimHostUrl("http://localhost:8080/Task/Detector/1?HTTPOnly=true"), "http://localhost:8080"); } } // namespace ccdb From ab8abc758c453f2a5cbf6c389b1b12a060baba7f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 23 Apr 2024 12:09:17 +0200 Subject: [PATCH 0153/2997] GPU: Do not use printf in GPU code if GPUCA_GPU_DEBUG_PRINT is not defined --- .../MathUtils/include/MathUtils/SMatrixGPU.h | 5 +++-- .../src/TrackParametrization.cxx | 19 ++++--------------- .../src/TrackParametrizationWithError.cxx | 4 ++-- .../tracking/include/ITStracking/Cluster.h | 4 ++++ 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/SMatrixGPU.h b/Common/MathUtils/include/MathUtils/SMatrixGPU.h index d0820778550dd..7175339db8592 100644 --- a/Common/MathUtils/include/MathUtils/SMatrixGPU.h +++ b/Common/MathUtils/include/MathUtils/SMatrixGPU.h @@ -32,6 +32,7 @@ #include "GPUCommonArray.h" #include "GPUCommonMath.h" #include "GPUCommonAlgorithm.h" +#include "GPUCommonLogger.h" namespace o2::math_utils { @@ -980,7 +981,7 @@ GPUdi() void Inverter::InvertBunchKaufman(MatRepSymGPU& rhs, int& if // invert D(j:j+1,j:j+1) temp2 = *mjj * *(mjj + j + 1) - *(mjj + j) * *(mjj + j); if (temp2 == 0) { - printf("SymMatrix::bunch_invert: error in pivot choice"); + LOGF(error, "SymMatrix::bunch_invert: error in pivot choice"); } temp2 = 1. / temp2; // this quotient is guaranteed to exist by the choice @@ -1070,7 +1071,7 @@ GPUdi() void Inverter::InvertBunchKaufman(MatRepSymGPU& rhs, int& if } else // 2x2 pivot, compute columns j and j-1 of the inverse { if (piv[j - 1] != 0) { - printf("error in piv %lf \n", static_cast(piv[j - 1])); + LOGF(error, "error in piv %lf \n", static_cast(piv[j - 1])); } s = 2; if (j < nrow) { diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index a30d74d940977..e1f8ee1910161 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -589,15 +589,9 @@ GPUd() void TrackParametrization::printParam() const // print parameters #ifndef GPUCA_ALIGPUCODE printf("%s\n", asString().c_str()); -#else +#elif !defined(GPUCA_GPUCODE_DEVICE) || (!defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT)) printf("X:%+.4e Alp:%+.3e Par: %+.4e %+.4e %+.4e %+.4e %+.4e |Q|:%d %s", - getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge(), -#if !defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT) - getPID().getName() -#else - "" -#endif - ); + getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge(), getPID().getName()); #endif } @@ -608,7 +602,7 @@ GPUd() void TrackParametrization::printParamHexadecimal() // print parameters #ifndef GPUCA_ALIGPUCODE printf("%s\n", asStringHexadecimal().c_str()); -#else +#elif !defined(GPUCA_GPUCODE_DEVICE) || (!defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT)) printf("X:%x Alp:%x Par: %x %x %x %x %x |Q|:%x %s", gpu::CAMath::Float2UIntReint(getX()), gpu::CAMath::Float2UIntReint(getAlpha()), @@ -618,12 +612,7 @@ GPUd() void TrackParametrization::printParamHexadecimal() gpu::CAMath::Float2UIntReint(getTgl()), gpu::CAMath::Float2UIntReint(getQ2Pt()), gpu::CAMath::Float2UIntReint(getAbsCharge()), -#if !defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT) - getPID().getName() -#else - "" -#endif - ); + getPID().getName()); #endif } diff --git a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx index b07fd8d6c3e6d..dfe4d7c31b2ab 100644 --- a/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrizationWithError.cxx @@ -1214,7 +1214,7 @@ GPUd() void TrackParametrizationWithError::print() const // print parameters #ifndef GPUCA_ALIGPUCODE printf("%s\n", asString().c_str()); -#else +#elif !defined(GPUCA_GPUCODE_DEVICE) || (!defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT)) TrackParametrization::printParam(); printf( "\nCov: [%+.3e] [%+.3e %+.3e] [%+.3e %+.3e %+.3e] [%+.3e %+.3e %+.3e %+.3e] [%+.3e %+.3e %+.3e %+.3e %+.3e]", @@ -1231,7 +1231,7 @@ GPUd() void TrackParametrizationWithError::printHexadecimal() // print parameters #ifndef GPUCA_ALIGPUCODE printf("%s\n", asStringHexadecimal().c_str()); -#else +#elif !defined(GPUCA_GPUCODE_DEVICE) || (!defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT)) TrackParametrization::printParamHexadecimal(); printf( "\nCov: [%x] [%x %x] [%x %x %x] [%x %x %x %x] [%x %x %x %x %x]", diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h index 3778f487db25d..0f136edfebfb3 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cluster.h @@ -54,7 +54,9 @@ struct Cluster final { GPUhdi() void Cluster::print() const { +#if !defined(GPUCA_GPUCODE_DEVICE) || (!defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT)) printf("Cluster: %f %f %f %f %f %d %d\n", xCoordinate, yCoordinate, zCoordinate, phi, radius, clusterId, indexTableBinIndex); +#endif } struct TrackingFrameInfo { @@ -70,10 +72,12 @@ struct TrackingFrameInfo { o2::gpu::gpustd::array covarianceTrackingFrame = {999., 999., 999.}; GPUdi() void print() const { +#if !defined(GPUCA_GPUCODE_DEVICE) || (!defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT)) printf("x: %f y: %f z: %f xTF: %f alphaTF: %f posTF: %f %f covTF: %f %f %f\n", xCoordinate, yCoordinate, zCoordinate, xTrackingFrame, alphaTrackingFrame, positionTrackingFrame[0], positionTrackingFrame[1], covarianceTrackingFrame[0], covarianceTrackingFrame[1], covarianceTrackingFrame[2]); +#endif } ClassDefNV(TrackingFrameInfo, 1); From 72a00bc7404000ab3d720c9cac43336fe6f2e73b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 24 Apr 2024 08:59:00 +0200 Subject: [PATCH 0154/2997] Bump python for Changelog creation action --- .github/workflows/reports.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index 9045b8b8c8031..b4957734347c8 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -18,10 +18,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up Python 3.7 + - name: Set up Python 3.10 uses: actions/setup-python@v1 with: - python-version: 3.7 + python-version: 3.10 - uses: actions/cache@v2 name: Configure pip caching with: From c96c7cb0e60159bd98402d9a03fd926aea2f0481 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:00:54 +0200 Subject: [PATCH 0155/2997] Update reports.yml --- .github/workflows/reports.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index b4957734347c8..5f7252dda7460 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -19,9 +19,9 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Python 3.10 - uses: actions/setup-python@v1 + uses: actions/setup-python@v5 with: - python-version: 3.10 + python-version: '3.10' - uses: actions/cache@v2 name: Configure pip caching with: From c34b2a3a61f1e1ebf39ad7c4d2c179d82e3c4ca8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:02:56 +0200 Subject: [PATCH 0156/2997] Update reports.yml --- .github/workflows/reports.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml index 5f7252dda7460..affd78216b50e 100644 --- a/.github/workflows/reports.yml +++ b/.github/workflows/reports.yml @@ -81,7 +81,7 @@ jobs: run: | set -x mkdir -p doc/data - # We create new files once per month, mostly so that + # We create new files once per month, mostly so that # we can keep the query results small. It does not # matter if we get results from different months, # as what matters is how we merge them. @@ -96,7 +96,6 @@ jobs: # being published LAST_RELEASE="${{ github.event.inputs.LAST_RELEASE_DATE }}" MERGED_AFTER=${LAST_RELEASE:-$(date -v -14d +%Y-%m-%d)} - # Here we convert all the json files to per subsystem # logs, using the MERGED_AFTER date to further filter them. # Notice we can have duplicates in each file, @@ -106,7 +105,7 @@ jobs: for f in doc/data/*_prs.json; do for x in Algorithm Analysis Common DataFormats Detectors EventVisualisation Examples Framework Generators Steer Testing Utilities; do cat $f | jq ".repository.pullRequests.edges[].node | select(.files.edges[].node.path | test(\"$x\")) | del(.files) | select(.state == \"MERGED\" and .mergedAt >= \"${MERGED_AFTER}\")" > /tmp/${x}_prs.json - if [ ! X`jq -s length /tmp/${x}_prs.json` = X0 ]; then + if [ ! X`jq -s length /tmp/${x}_prs.json` = X0 ]; then cat /tmp/${x}_prs.json | jq -r '"- [#\(.number)](https://github.com/AliceO2Group/AliceO2/pull/\(.number)) \(.mergedAt | split("T")[0]): \(.title) by [@\(.author.login)](https://github.com/\(.author.login))"' | sort -u >> /tmp/${x}_prs.md fi done From 8b9fa3d647aa85f14a34e2ac07b6cdd65293eeb5 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 24 Apr 2024 09:38:35 +0200 Subject: [PATCH 0157/2997] dpl-workflow: Use /var/tmp as cache folder for GPU RTC cache --- prodtests/full-system-test/dpl-workflow.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 5b5d84c413abe..c3554b4c6b1a6 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -320,7 +320,7 @@ if has_detector_calib PHS && workflow_has_parameter CALIB; then fi [[ ${O2_GPU_DOUBLE_PIPELINE:-$EPNSYNCMODE} == 1 ]] && GPU_CONFIG+=" --enableDoublePipeline" -[[ ${O2_GPU_RTC:-0} == 1 ]] && GPU_CONFIG_KEY+="GPU_proc_rtc.enable=1;GPU_proc_rtc.cacheOutput=1;GPU_proc.RTCcacheFolder=/tmp/o2_gpu_rtc_cache;" +[[ ${O2_GPU_RTC:-0} == 1 ]] && GPU_CONFIG_KEY+="GPU_proc_rtc.enable=1;GPU_proc_rtc.cacheOutput=1;GPU_proc.RTCcacheFolder=/var/tmp/o2_gpu_rtc_cache;" ( workflow_has_parameter AOD || [[ -z "$DISABLE_ROOT_OUTPUT" ]] || needs_root_output o2-emcal-cell-writer-workflow ) && has_detector EMC && RAW_EMC_SUBSPEC=" --subspecification 1 " has_detector_reco MID && has_detector_matching MCHMID && MFTMCHConf="FwdMatching.useMIDMatch=true;" || MFTMCHConf="FwdMatching.useMIDMatch=false;" From 2e5af850da5740f69a10921ab17495013c2536b0 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 24 Apr 2024 09:41:10 +0200 Subject: [PATCH 0158/2997] GPU: Add ignoreCacheValid debug option --- .../Base/cuda/GPUReconstructionCUDAGenRTC.cxx | 10 +++++----- GPU/GPUTracking/Definitions/GPUSettingsList.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx index b291bf735aee3..7e9dcfe0ca983 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx @@ -93,28 +93,28 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) if (fread(sharead, 1, 20, fp) != 20) { throw std::runtime_error("Cache file corrupt"); } - if (memcmp(sharead, shasource, 20)) { + if (!mProcessingSettings.rtc.ignoreCacheValid && memcmp(sharead, shasource, 20)) { GPUInfo("Cache file content outdated (source)"); break; } if (fread(sharead, 1, 20, fp) != 20) { throw std::runtime_error("Cache file corrupt"); } - if (memcmp(sharead, shaparam, 20)) { + if (!mProcessingSettings.rtc.ignoreCacheValid && memcmp(sharead, shaparam, 20)) { GPUInfo("Cache file content outdated (param)"); break; } if (fread(sharead, 1, 20, fp) != 20) { throw std::runtime_error("Cache file corrupt"); } - if (memcmp(sharead, shacmd, 20)) { + if (!mProcessingSettings.rtc.ignoreCacheValid && memcmp(sharead, shacmd, 20)) { GPUInfo("Cache file content outdated (commandline)"); break; } if (fread(sharead, 1, 20, fp) != 20) { throw std::runtime_error("Cache file corrupt"); } - if (memcmp(sharead, shakernels, 20)) { + if (!mProcessingSettings.rtc.ignoreCacheValid && memcmp(sharead, shakernels, 20)) { GPUInfo("Cache file content outdated (kernel definitions)"); break; } @@ -123,7 +123,7 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) if (fread(&cachedSettings, sizeof(cachedSettings), 1, fp) != 1) { throw std::runtime_error("Cache file corrupt"); } - if (memcmp(&cachedSettings, &mProcessingSettings.rtc, sizeof(cachedSettings))) { + if (!mProcessingSettings.rtc.ignoreCacheValid && memcmp(&cachedSettings, &mProcessingSettings.rtc, sizeof(cachedSettings))) { GPUInfo("Cache file content outdated (rtc parameters)"); break; } diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 3175b088d8440..b5d5bb5d1edc5 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -200,6 +200,7 @@ AddOption(compilePerKernel, bool, true, "", 0, "Run one RTC compilation per kern AddOption(enable, bool, false, "", 0, "Use RTC to optimize GPU code") AddOption(runTest, int, 0, "", 0, "Do not run the actual benchmark, but just test RTC compilation (1 full test, 2 test only compilation)") AddOption(cacheMutex, bool, true, "", 0, "Use a file lock to serialize access to the cache folder") +AddOption(ignoreCacheValid, bool, false, "", 0, "If set, allows to use RTC cached code files even if they are not valid for the current source code / parameters") AddHelp("help", 'h') EndConfig() From 18126db94c68b3bcb6ff3e94b884a8017bcbd92e Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 24 Apr 2024 14:03:14 +0200 Subject: [PATCH 0159/2997] GPU: Fix GPU build flags once more, HIP flags got their -O3 overridden by CXX flags O2 --- dependencies/FindO2GPU.cmake | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index bd244fcaaecbe..52d3276c2ec85 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -111,13 +111,15 @@ if(ENABLE_CUDA) endif() endif() if(CMAKE_CUDA_COMPILER) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler \"${O2_GPU_CMAKE_CXX_FLAGS_NOSTD}\" --expt-relaxed-constexpr --extended-lambda --allow-unsupported-compiler -Xptxas -v -Xcompiler -Wno-attributes") + set(CMAKE_CUDA_FLAGS "-Xcompiler \"${O2_GPU_CMAKE_CXX_FLAGS_NOSTD}\" ${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr --extended-lambda --allow-unsupported-compiler -Xptxas -v -Xcompiler -Wno-attributes") if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "12.3") string(APPEND CMAKE_CUDA_FLAGS " -Xcudafe --diag_suppress=20257") # TODO: Cleanup endif() - set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -lineinfo -Xcompiler \"${CMAKE_CXX_FLAGS_DEBUG}\" -Xptxas -O0 -Xcompiler -O0") - if(NOT CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG") - set(CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} -Xcompiler \"${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}\" -Xptxas -O4 -Xcompiler -O4") + set(CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "-Xcompiler \"${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}\" ${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}") + if(CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG") + set(CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} -lineinfo -Xptxas -O0 -Xcompiler -O0") + else() + set(CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} -Xptxas -O4 -Xcompiler -O4") endif() set(GPUCA_CUDA_NO_FAST_MATH_FLAGS "--ftz=false --prec-div=true --prec-sqrt=true --fmad false") if(DEFINED GPUCA_NO_FAST_MATH AND "${GPUCA_NO_FAST_MATH}") @@ -284,6 +286,11 @@ if(ENABLE_HIP) endif() set(CMAKE_HIP_FLAGS "${O2_GPU_CMAKE_CXX_FLAGS_NOSTD} ${CMAKE_HIP_FLAGS} ${O2_HIP_CMAKE_CXX_FLAGS}") set(CMAKE_HIP_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} ${CMAKE_HIP_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}") + if(CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG") + set(CMAKE_HIP_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "${CMAKE_HIP_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} -O0 -ggdb") + else() + set(CMAKE_HIP_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "${CMAKE_HIP_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} -O3") + endif() else() set(HIP_ENABLED OFF) endif() From eb78db97f5c326f3acff17314f792184ac4ed314 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 24 Apr 2024 14:07:21 +0200 Subject: [PATCH 0160/2997] GPU: Add RTC debug option to override the command line --- GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx index 7e9dcfe0ca983..9c2bcacc2ae43 100644 --- a/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx +++ b/GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx @@ -159,6 +159,7 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) } HighResTimer rtcTimer; rtcTimer.ResetStart(); + std::string baseCommand = getenv("O2_GPU_RTC_OVERRIDE_CMD") ? std::string(getenv("O2_GPU_RTC_OVERRIDE_CMD")) : std::string(_binary_GPUReconstructionCUDArtc_command_start, _binary_GPUReconstructionCUDArtc_command_len); #ifdef WITH_OPENMP #pragma omp parallel for schedule(dynamic, 1) #endif @@ -181,7 +182,7 @@ int GPUReconstructionCUDA::genRTC(std::string& filename, unsigned int& nCompile) throw std::runtime_error("Error writing file"); } fclose(fp); - std::string command = std::string(_binary_GPUReconstructionCUDArtc_command_start, _binary_GPUReconstructionCUDArtc_command_len); + std::string command = baseCommand; command += " -c " + filename + "_" + std::to_string(i) + mRtcSrcExtension + " -o " + filename + "_" + std::to_string(i) + mRtcBinExtension; if (mProcessingSettings.debugLevel < 0) { command += " &> /dev/null"; From c2fa55f0619870010aa07185fb27d65ca768d2aa Mon Sep 17 00:00:00 2001 From: Jan Fiete Date: Wed, 24 Apr 2024 12:06:22 +0200 Subject: [PATCH 0161/2997] Increase counter before sending metric --- run/dpl_eventgen.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run/dpl_eventgen.cxx b/run/dpl_eventgen.cxx index b1929482041b0..66dd1c8342990 100644 --- a/run/dpl_eventgen.cxx +++ b/run/dpl_eventgen.cxx @@ -101,8 +101,8 @@ struct GeneratorTask { } // report number of TFs injected for the rate limiter to work - pc.services().get().send(o2::monitoring::Metric{(uint64_t)tfCounter, "df-sent"}.addTag(o2::monitoring::tags::Key::Subsystem, o2::monitoring::tags::Value::DPL)); ++tfCounter; + pc.services().get().send(o2::monitoring::Metric{(uint64_t)tfCounter, "df-sent"}.addTag(o2::monitoring::tags::Key::Subsystem, o2::monitoring::tags::Value::DPL)); bool time_expired = false; if (ttl > 0) { timer.Stop(); From b8e9624757a86042cc170ad28e33859e5d26df2a Mon Sep 17 00:00:00 2001 From: Jan Fiete Date: Wed, 24 Apr 2024 12:07:22 +0200 Subject: [PATCH 0162/2997] Update o2sim_kine_publisher.cxx --- run/o2sim_kine_publisher.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run/o2sim_kine_publisher.cxx b/run/o2sim_kine_publisher.cxx index 83f82fd69cca3..f72dd6eebaaf0 100644 --- a/run/o2sim_kine_publisher.cxx +++ b/run/o2sim_kine_publisher.cxx @@ -49,8 +49,8 @@ struct O2simKinePublisher { ++eventCounter; } // report number of TFs injected for the rate limiter to work - pc.services().get().send(o2::monitoring::Metric{(uint64_t)tfCounter, "df-sent"}.addTag(o2::monitoring::tags::Key::Subsystem, o2::monitoring::tags::Value::DPL)); ++tfCounter; + pc.services().get().send(o2::monitoring::Metric{(uint64_t)tfCounter, "df-sent"}.addTag(o2::monitoring::tags::Key::Subsystem, o2::monitoring::tags::Value::DPL)); if (eventCounter >= nEvents) { pc.services().get().endOfStream(); pc.services().get().readyToQuit(QuitRequest::Me); From b005a9d861053f6c44769f7571d8e473c76a1650 Mon Sep 17 00:00:00 2001 From: Jan Fiete Date: Wed, 24 Apr 2024 12:07:51 +0200 Subject: [PATCH 0163/2997] Update o2sim_hepmc_publisher.cxx --- run/o2sim_hepmc_publisher.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run/o2sim_hepmc_publisher.cxx b/run/o2sim_hepmc_publisher.cxx index ec049a44439a1..bf40abacb134f 100644 --- a/run/o2sim_hepmc_publisher.cxx +++ b/run/o2sim_hepmc_publisher.cxx @@ -148,8 +148,8 @@ struct O2simHepmcPublisher { } // report number of TFs injected for the rate limiter to work - pc.services().get().send(o2::monitoring::Metric{(uint64_t)tfCounter, "df-sent"}.addTag(o2::monitoring::tags::Key::Subsystem, o2::monitoring::tags::Value::DPL)); ++tfCounter; + pc.services().get().send(o2::monitoring::Metric{(uint64_t)tfCounter, "df-sent"}.addTag(o2::monitoring::tags::Key::Subsystem, o2::monitoring::tags::Value::DPL)); if (eos || (maxEvents > 0 && eventCounter == maxEvents)) { pc.services().get().endOfStream(); pc.services().get().readyToQuit(QuitRequest::Me); From e2685358df608e5ef4b0a40d00ba081720a8d6a6 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:45:04 +0200 Subject: [PATCH 0164/2997] DPL: disable cpu_usage_fraction for proxies --- Framework/Core/src/CommonServices.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 028ed6e8e6806..ddaaa81090769 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -43,6 +43,7 @@ #include "Framework/DeviceState.h" #include "Framework/DeviceConfig.h" #include "Framework/DefaultsHelpers.h" +#include "Framework/Signpost.h" #include "TextDriverClient.h" #include "WSDriverClient.h" @@ -83,6 +84,7 @@ using Value = o2::monitoring::tags::Value; O2_DECLARE_DYNAMIC_LOG(data_processor_context); O2_DECLARE_DYNAMIC_LOG(stream_context); O2_DECLARE_DYNAMIC_LOG(async_queue); +O2_DECLARE_DYNAMIC_LOG(policies); namespace o2::framework { @@ -849,6 +851,16 @@ o2::framework::ServiceSpec CommonServices::dataProcessingStats() if (deploymentMode != DeploymentMode::OnlineDDS && deploymentMode != DeploymentMode::OnlineECS && deploymentMode != DeploymentMode::OnlineAUX && deploymentMode != DeploymentMode::FST) { arrowAndResourceLimitingMetrics = true; } + // Input proxies should not report cpu_usage_fraction, + // because of the rate limiting which biases the measurement. + auto& spec = services.get(); + bool enableCPUUsageFraction = true; + auto isProxy = [](DataProcessorLabel const& label) -> bool { return label == DataProcessorLabel{"input-proxy"}; }; + if (std::find_if(spec.labels.begin(), spec.labels.end(), isProxy) != spec.labels.end()) { + O2_SIGNPOST_ID_GENERATE(mid, policies); + O2_SIGNPOST_EVENT_EMIT(policies, mid, "metrics", "Disabling cpu_usage_fraction metric for proxy %{public}s", spec.name.c_str()); + enableCPUUsageFraction = false; + } std::vector metrics = { MetricSpec{.name = "errors", @@ -932,6 +944,7 @@ o2::framework::ServiceSpec CommonServices::dataProcessingStats() .maxRefreshLatency = onlineRefreshLatency, .sendInitialValue = true}, MetricSpec{.name = "cpu_usage_fraction", + .enabled = enableCPUUsageFraction, .metricId = (int)ProcessingStatsId::CPU_USAGE_FRACTION, .kind = Kind::Rate, .scope = Scope::Online, From c487fba13feae805b7d2a438a538a16a7e77ea9e Mon Sep 17 00:00:00 2001 From: sevdokim Date: Tue, 23 Apr 2024 12:35:08 +0200 Subject: [PATCH 0165/2997] PHS: publish pedestal vector at PHS/PedestalRun/Pedestals in the CCDB --- .../PHOS/calib/src/PHOSPedestalCalibDevice.cxx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Detectors/PHOS/calib/src/PHOSPedestalCalibDevice.cxx b/Detectors/PHOS/calib/src/PHOSPedestalCalibDevice.cxx index 42289a910debb..f65d42b735875 100644 --- a/Detectors/PHOS/calib/src/PHOSPedestalCalibDevice.cxx +++ b/Detectors/PHOS/calib/src/PHOSPedestalCalibDevice.cxx @@ -119,6 +119,7 @@ void PHOSPedestalCalibDevice::sendOutput(DataAllocator& output) header::DataHeader::SubSpecificationType subSpec{(header::DataHeader::SubSpecificationType)0}; output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBPayload, "PHOS_Pedestal", subSpec}, *image.get()); output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBWrapper, "PHOS_Pedestal", subSpec}, info); + // Now same for DCS as vector std::vector dcsPedestals(2 * (o2::phos::Mapping::NCHANNELS - 1792)); // copy HG then LG pedestals @@ -128,10 +129,18 @@ void PHOSPedestalCalibDevice::sendOutput(DataAllocator& output) for (short absId = 1793; absId <= o2::phos::Mapping::NCHANNELS; absId++) { dcsPedestals.emplace_back(mPedestals->getLGPedestal(absId)); } - auto imageDCS = o2::ccdb::CcdbApi::createObjectImage(&dcsPedestals, &info); + + auto flNameDCS = o2::ccdb::CcdbApi::generateFileName("PedestalsDCS"); + std::map mdDCS; + o2::ccdb::CcdbObjectInfo infoDCS("PHS/PedestalRun/Pedestals", "PedestalsDCS", flNameDCS, mdDCS, mRunStartTime, validityTime); + auto imageDCS = o2::ccdb::CcdbApi::createObjectImage(&dcsPedestals, &infoDCS); + // subspec 0 -> to normal CCDB + output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBPayload, "PHOS_PedestalVec", subSpec}, *imageDCS.get()); + output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBWrapper, "PHOS_PedestalVec", subSpec}, infoDCS); + // subspec 1 -> to DCS CCDB header::DataHeader::SubSpecificationType subSpec1{(header::DataHeader::SubSpecificationType)1}; - output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBPayload, "PHOS_Pedestal", subSpec1}, *imageDCS.get()); - output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBWrapper, "PHOS_Pedestal", subSpec1}, info); + output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBPayload, "PHOS_PedestalVec", subSpec1}, *imageDCS.get()); + output.snapshot(Output{o2::calibration::Utils::gDataOriginCDBWrapper, "PHOS_PedestalVec", subSpec1}, infoDCS); } // Anyway send change to QC LOG(info) << "[PHOSPedestalCalibDevice - run] Sending QC "; @@ -220,6 +229,9 @@ o2::framework::DataProcessorSpec o2::phos::getPedestalCalibSpec(bool useCCDB, bo outputs.emplace_back(o2::header::gDataOriginPHS, "CALIBDIFF", 0, o2::framework::Lifetime::Sporadic); outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCDBPayload, "PHOS_Pedestal"}, o2::framework::Lifetime::Sporadic); outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCDBWrapper, "PHOS_Pedestal"}, o2::framework::Lifetime::Sporadic); + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCDBPayload, "PHOS_PedestalVec"}, o2::framework::Lifetime::Sporadic); + outputs.emplace_back(ConcreteDataTypeMatcher{clbUtils::gDataOriginCDBWrapper, "PHOS_PedestalVec"}, o2::framework::Lifetime::Sporadic); + return o2::framework::DataProcessorSpec{"PedestalCalibSpec", inputs, outputs, From 1ca8a0ac18bd509213450d1cd5dadc1b85eb877f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Tich=C3=A1k?= <53997499+justonedev1@users.noreply.github.com> Date: Thu, 25 Apr 2024 11:01:47 +0200 Subject: [PATCH 0166/2997] DPL documentation: description how o2 terminates (#12650) --- Framework/Core/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Framework/Core/README.md b/Framework/Core/README.md index 70a35ddbaaf9d..8d3ad9db01135 100644 --- a/Framework/Core/README.md +++ b/Framework/Core/README.md @@ -277,6 +277,8 @@ however, no API is provided to explicitly send it. All the created DataChunks ar When an error happens during processing of some data, the writer of the `process` function should simply throw an exception. By default the exception is caught by the `DataProcessingDevice` and a message is printed (if `std::exeception` derived `what()` method is used, otherwise a generic message is given). Users can provide themselves an error handler by specifying via the `onError` callback specified in `DataProcessorSpec`. This will allow in the future to reinject data into the flow in case of an error. +When the exception is thrown inside processing function its message and stack trace is printed. However, the application itself is not terminated. If the error encountered is so severe that current workflow cannot continue it is advisable to call `LOG(fatal)` with proper describing message, which makes the application shutdown with non zero error code. + ### Services Services are utility classes which `DataProcessor`s can access to request out-of-bound, deployment dependent, functionalities. For example a service could be used to post metrics to the monitoring system or to get a GPU context. The former would be dependent on whether you are running on your laptop (where monitoring could simply mean print out metrics on the command line) or in a large cluster (where monitoring probably means to send metrics to an aggregator device which then pushes them to the backend. From d4776d76cb12add2be73bfef239a75788f6d132b Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 25 Apr 2024 12:58:24 +0200 Subject: [PATCH 0167/2997] fix mult. estimator for ITSMFT debug output --- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 6ea76f3b43adb..194de0cfbeaaf 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -588,7 +588,7 @@ bool MatchTPCITS::prepareTPCData() for (int i = nTPCOccBins; i--;) { float mlt = mTPCRefitter->getParam()->GetUnscaledMult(tb); sm += mlt; - mTBinClOcc.push_back(sm); + mTBinClOcc[i] = sm; if (ninteg++ > mNTPCOccBinLength) { sm -= mltPrev; } @@ -1514,8 +1514,8 @@ void MatchTPCITS::fillCalibDebug(int ifit, int iTPC, const o2::dataformats::Trac } (*mDBGOut) << "refit" << "multTPC=" << mltTPC - << "multITSTr=" << mITSTrackROFRec[tITS.roFrame] - << "multITSCl=" << mITSClusterROFRec[tITS.roFrame] + << "multITSTr=" << mITSTrackROFRec[tITS.roFrame].getNEntries() + << "multITSCl=" << mITSClusterROFRec[tITS.roFrame].getNEntries() << "tf=" << mTFCount << "\n"; } #endif @@ -2836,9 +2836,9 @@ void MatchTPCITS::fillTPCITSmatchTree(int itsID, int tpcID, int rejFlag, float c float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]); (*mDBGOut) << "match" << "rejFlag=" << rejFlag - << "multTPC=" << tb - << "multITSTr=" << mITSTrackROFRec[trackITS.roFrame] - << "multITSCl=" << mITSClusterROFRec[trackITS.roFrame] + << "multTPC=" << mltTPC + << "multITSTr=" << mITSTrackROFRec[trackITS.roFrame].getNEntries() + << "multITSCl=" << mITSClusterROFRec[trackITS.roFrame].getNEntries() << "\n"; mTimer[SWDBG].Stop(); @@ -2871,9 +2871,9 @@ void MatchTPCITS::dumpWinnerMatches() int tb = mTPCTracksArray[tTPC.sourceID].getTime0() * mNTPCOccBinLengthInv; float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]); (*mDBGOut) << "matchWin" - << "multTPC=" << mTPCRefitter->getParam()->GetUnscaledMult(mTPCTracksArray[tTPC.sourceID].getTime0()) - << "multITSTr=" << mITSTrackROFRec[tITS.roFrame] - << "multITSCl=" << mITSClusterROFRec[tITS.roFrame] + << "multTPC=" << mltTPC + << "multITSTr=" << mITSTrackROFRec[tITS.roFrame].getNEntries() + << "multITSCl=" << mITSClusterROFRec[tITS.roFrame].getNEntries() << "\n"; } mTimer[SWDBG].Stop(); From c9b95c6783ed61f4dc8cef016b9e96bf4388f573 Mon Sep 17 00:00:00 2001 From: Matthias Kleiner Date: Thu, 25 Apr 2024 10:30:34 +0200 Subject: [PATCH 0168/2997] TPC: increasing calibration length for residual gain map --- prodtests/full-system-test/aggregator-workflow.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/full-system-test/aggregator-workflow.sh b/prodtests/full-system-test/aggregator-workflow.sh index e1ca1e5477341..2812c6da76817 100755 --- a/prodtests/full-system-test/aggregator-workflow.sh +++ b/prodtests/full-system-test/aggregator-workflow.sh @@ -253,7 +253,7 @@ if [[ $AGGREGATOR_TASKS == BARREL_SPORADIC ]] || [[ $AGGREGATOR_TASKS == ALL ]]; add_W o2-tpc-calibrator-dedx "--min-entries-sector 3000 --min-entries-1d 200 --min-entries-2d 10000" fi if [[ $CALIB_TPC_RESPADGAIN == 1 ]]; then - add_W o2-tpc-calibrator-gainmap-tracks "--tf-per-slot 10000 --store-RMS-CCDB true" + add_W o2-tpc-calibrator-gainmap-tracks "--tf-per-slot 200000 --store-RMS-CCDB true" fi # TOF if [[ $CALIB_TOF_INTEGRATEDCURR == 1 ]]; then From 724584a73e4e7f669f99a02be6671800020cdb78 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 26 Apr 2024 08:55:09 +0200 Subject: [PATCH 0169/2997] DPL: force flushing of the metrics at the end of processing (#13076) --- Framework/Core/src/CommonServices.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index ddaaa81090769..7f0e710d96b2e 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -131,6 +131,7 @@ o2::framework::ServiceSpec CommonServices::monitoringSpec() } }, .exit = [](ServiceRegistryRef registry, void* service) { auto* monitoring = reinterpret_cast(service); + monitoring->flushBuffer(); delete monitoring; }, .kind = ServiceKind::Serial}; } From 717ce119f9b429948fa9ed053357200fad7aed19 Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 25 Apr 2024 15:39:54 +0200 Subject: [PATCH 0170/2997] Add calculation of mean values over all sectors --- .../DataFormatsTPC/CalibdEdxCorrection.h | 13 +++++ .../Detectors/TPC/src/CalibdEdxCorrection.cxx | 49 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxCorrection.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxCorrection.h index 4225faf8437c4..ace488b652559 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxCorrection.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxCorrection.h @@ -22,6 +22,7 @@ #ifndef GPUCA_GPUCODE_DEVICE #include #include +#include #endif // o2 includes @@ -96,6 +97,18 @@ class CalibdEdxCorrection /// \param outFileName name of the output file void dumpToTree(const char* outFileName = "calib_dedx.root") const; + /// Parameters averaged over all stacks + const std::array getMeanParams(ChargeType charge) const; + + /// Parameters averaged over all sectors for a stack type + const std::array getMeanParams(const GEMstack stack, ChargeType charge) const; + + /// Single fit parameters averaged over all sectors for a stack type + float getMeanParam(ChargeType charge, uint32_t param) const; + + /// Single fit parameters averaged over all sectors for a stack type + float getMeanParam(const GEMstack stack, ChargeType charge, uint32_t param) const; + #endif private: diff --git a/DataFormats/Detectors/TPC/src/CalibdEdxCorrection.cxx b/DataFormats/Detectors/TPC/src/CalibdEdxCorrection.cxx index b843577f1976a..28a44f15cf18c 100644 --- a/DataFormats/Detectors/TPC/src/CalibdEdxCorrection.cxx +++ b/DataFormats/Detectors/TPC/src/CalibdEdxCorrection.cxx @@ -11,6 +11,7 @@ #include "DataFormatsTPC/CalibdEdxCorrection.h" +#include #include // o2 includes @@ -86,3 +87,51 @@ void CalibdEdxCorrection::dumpToTree(const char* outFileName) const } } } + +const std::array CalibdEdxCorrection::getMeanParams(ChargeType charge) const +{ + std::array params{}; + + for (int index = 0; index < FitSize / 2; ++index) { + std::transform(params.begin(), params.end(), mParams[index + charge * FitSize / 2], params.begin(), std::plus<>()); + } + std::for_each(params.begin(), params.end(), [](auto& val) { val /= (0.5f * FitSize); }); + return params; +} + +const std::array CalibdEdxCorrection::getMeanParams(const GEMstack stack, ChargeType charge) const +{ + std::array params{}; + + for (int index = 0; index < SECTORSPERSIDE * SIDES; ++index) { + std::transform(params.begin(), params.end(), getParams(StackID{index, stack}, charge), params.begin(), std::plus<>()); + } + std::for_each(params.begin(), params.end(), [](auto& val) { val /= (SECTORSPERSIDE * SIDES); }); + return params; +} + +float CalibdEdxCorrection::getMeanParam(ChargeType charge, uint32_t param) const +{ + if (param >= ParamSize) { + return 0.f; + } + float mean{}; + for (int index = 0; index < FitSize / 2; ++index) { + mean += mParams[index + charge * FitSize / 2][param]; + } + + return mean / (0.5f * FitSize); +} + +float CalibdEdxCorrection::getMeanParam(const GEMstack stack, ChargeType charge, uint32_t param) const +{ + if (param >= ParamSize) { + return 0.f; + } + float mean{}; + for (int index = 0; index < SECTORSPERSIDE * SIDES; ++index) { + mean += getParams(StackID{index, stack}, charge)[param]; + } + + return mean / (SECTORSPERSIDE * SIDES); +} From f6e2c2a72d57e63e3b7b496c2c2efae2a50ffa0d Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 25 Apr 2024 15:41:46 +0200 Subject: [PATCH 0171/2997] Add missing forward of template parameters, cleanup --- Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h | 4 ++-- Detectors/TPC/base/include/TPCBase/FEEConfig.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h b/Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h index d0a061a9776b6..464a5eb24d4f7 100644 --- a/Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h +++ b/Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h @@ -214,7 +214,7 @@ int fillCalPad(CalDet& calPad, gsl::span data) membuf sbuf((char*)data.data(), data.size()); std::istream in(&sbuf); - return fillCalPad(calPad, in); + return fillCalPad(calPad, in); } /// create cal pad object from HW value file @@ -237,7 +237,7 @@ o2::tpc::CalDet getCalPad(const std::string_view fileName, const std::str return calPad; } - fillCalPad(calPad, infile); + fillCalPad(calPad, infile); if (outputFile.size()) { TFile f(outputFile.data(), "recreate"); diff --git a/Detectors/TPC/base/include/TPCBase/FEEConfig.h b/Detectors/TPC/base/include/TPCBase/FEEConfig.h index ef495e9f219da..2065970c42ef5 100644 --- a/Detectors/TPC/base/include/TPCBase/FEEConfig.h +++ b/Detectors/TPC/base/include/TPCBase/FEEConfig.h @@ -21,7 +21,6 @@ #include #include #include -#include #include "Rtypes.h" From f6927c9b79d5df4b1a5f9c2b8b308840fb10025e Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 25 Apr 2024 15:42:49 +0200 Subject: [PATCH 0172/2997] Add summary canvases from pad tree dump, cosmetic fixes --- Detectors/TPC/base/include/TPCBase/Painter.h | 14 ++ Detectors/TPC/base/src/Painter.cxx | 159 ++++++++++++++++++- 2 files changed, 169 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/Painter.h b/Detectors/TPC/base/include/TPCBase/Painter.h index 565c07084e054..976fe2846ce0c 100644 --- a/Detectors/TPC/base/include/TPCBase/Painter.h +++ b/Detectors/TPC/base/include/TPCBase/Painter.h @@ -184,6 +184,20 @@ struct painter { /// \return TCanvas containing CalDet content static std::vector makeSummaryCanvases(const std::string_view fileName, const std::string_view calPadNames, int nbins1D = 300, float xMin1D = 0, float xMax1D = 0, bool onlyFilled = true); + /// Create summary canvases from pad calibration tree dumped via CalibTreeDump + /// + /// 1 Canvas with 2D and 1D distributions for each side + /// 1 Canvas with 2D distributions for all ROCs + /// 1 Canvas with 1D distributions for all ROCs + /// \param tree input calibTree + /// \param draw draw string to use for the variable (1D) + /// \param cut cut string to use (default 1 = no cut) + /// \param nbins1D number of bins used for the 1D projections, if negative, exclude per ROC histograms + /// \param xMin1D minimum value for 1D distribution (xMin = 0 and xMax = 0 for auto scaling) + /// \param xMax1D maximum value for 1D distribution (xMin = 0 and xMax = 0 for auto scaling) + /// \return TCanvas containing CalDet content + static std::vector makeSummaryCanvases(TTree& tree, const std::string_view draw, std::string_view cut = "1", int nbins1D = 300, float xMin1D = 0, float xMax1D = 0); + /// draw sector boundaris, side name and sector numbers static void drawSectorsXY(Side side, int sectorLineColor = 920, int sectorTextColor = 1); diff --git a/Detectors/TPC/base/src/Painter.cxx b/Detectors/TPC/base/src/Painter.cxx index 0f7b89b71e07a..863547a666611 100644 --- a/Detectors/TPC/base/src/Painter.cxx +++ b/Detectors/TPC/base/src/Painter.cxx @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -22,6 +23,7 @@ #include "TH2.h" #include "TH3.h" #include "TH2Poly.h" +#include "TProfile2D.h" #include "TCanvas.h" #include "TLine.h" #include "TLatex.h" @@ -303,16 +305,16 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float const int bufferSize = TH1::GetDefaultBufferSize(); TH1::SetDefaultBufferSize(Sector::MAXSECTOR * mapper.getPadsInSector()); - auto hAside1D = new TH1F(fmt::format("h_Aside_1D_{}", name).data(), fmt::format("{} (A-Side)", title).data(), + auto hAside1D = new TH1F(fmt::format("h_Aside_1D_{}", name).data(), fmt::format("{0} (A-Side);{0}", title).data(), nbins1D, xMin1D, xMax1D); // TODO: modify ranges - auto hCside1D = new TH1F(fmt::format("h_Cside_1D_{}", name).data(), fmt::format("{} (C-Side)", title).data(), + auto hCside1D = new TH1F(fmt::format("h_Cside_1D_{}", name).data(), fmt::format("{0} (C-Side);{0}", title).data(), nbins1D, xMin1D, xMax1D); // TODO: modify ranges - auto hAside2D = new TH2F(fmt::format("h_Aside_2D_{}", name).data(), fmt::format("{} (A-Side);#it{{x}} (cm);#it{{y}} (cm)", title).data(), + auto hAside2D = new TH2F(fmt::format("h_Aside_2D_{}", name).data(), fmt::format("{0} (A-Side);#it{{x}} (cm);#it{{y}} (cm);{0}", title).data(), 330, -270, 270, 330, -270, 270); - auto hCside2D = new TH2F(fmt::format("h_Cside_2D_{}", name).data(), fmt::format("{} (C-Side);#it{{x}} (cm);#it{{y}} (cm)", title).data(), + auto hCside2D = new TH2F(fmt::format("h_Cside_2D_{}", name).data(), fmt::format("{0} (C-Side);#it{{x}} (cm);#it{{y}} (cm);{0}", title).data(), 330, -270, 270, 330, -270, 270); for (ROC roc; !roc.looped(); ++roc) { @@ -363,6 +365,7 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float hAside2D->SetStats(0); hAside2D->SetTitleOffset(1.05, "XY"); hAside2D->SetTitleSize(0.05, "XY"); + adjustPalette(hAside2D, 0.92); drawSectorsXY(Side::A); c->cd(2); @@ -370,6 +373,7 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float hCside2D->SetStats(0); hCside2D->SetTitleOffset(1.05, "XY"); hCside2D->SetTitleSize(0.05, "XY"); + adjustPalette(hCside2D, 0.92); drawSectorsXY(Side::C); c->cd(3); @@ -613,6 +617,153 @@ std::vector painter::makeSummaryCanvases(const CalDet& calDet, int return vecCanvases; } +std::vector o2::tpc::painter::makeSummaryCanvases(TTree& tree, const std::string_view draw, std::string_view cut, int nbins1D, float xMin1D, float xMax1D) +{ + const Mapper& mapper = Mapper::instance(); + + std::vector vecCanvases; + + // ===| name and title |====================================================== + std::string title = draw.data(); + std::string name = title; + std::replace(name.begin(), name.end(), ' ', '_'); + std::replace(name.begin(), name.end(), '/', '_'); + const std::string_view calName = name; + + // ===| Per ROC histograms |=== + if (nbins1D > 0) { + const size_t nROCs = 72; + auto cROCs1D = new TCanvas(fmt::format("c_ROCs_{}_1D", calName).data(), fmt::format("{} values for each ROC", calName).data(), 1400, 1000); + auto cROCs2D = new TCanvas(fmt::format("c_ROCs_{}_2D", calName).data(), fmt::format("{} values for each ROC", calName).data(), 1400, 1000); + + cROCs1D->DivideSquare(nROCs); + cROCs2D->DivideSquare(nROCs); + + vecCanvases.emplace_back(cROCs1D); + vecCanvases.emplace_back(cROCs2D); + + // ===| produce plots for each ROC |=== + size_t pad = 1; + for (size_t iroc = 0; iroc < nROCs; ++iroc) { + + // ===| 1D histogram |=== + auto h1D = new TH1F(fmt::format("h1_{}_{:02d}", calName, iroc).data(), fmt::format("{} distribution ROC {:02d} ({});{}", calName, iroc, getROCTitle(iroc), draw).data(), nbins1D, xMin1D, xMax1D); + tree.Draw(fmt::format("{} >> {}", draw, h1D->GetName()).data(), fmt::format("(roc == {}) && ({})", iroc, cut).data(), "goff"); + + // ===| 2D histogram |=== + const int nrows = mapper.getNumberOfPadRows(PadSubset::ROC, iroc); + const int npads = mapper.getNumberOfPadsInRow(PadSubset::ROC, iroc, nrows - 1) + 6; + + // ===| create histogram |==================================================== + + const std::string rocTitle = title + fmt::format(" ({})", getROCTitle(iroc)); + + auto h2D = new TProfile2D(fmt::format("h_{}_ROC{}", name, iroc).data(), + fmt::format("{};pad row;pad;{}", rocTitle, draw).data(), + nrows, 0., nrows, + npads, -npads / 2., npads / 2.); + tree.Draw(fmt::format("{} : cpad : row >> {}", draw, h2D->GetName()).data(), fmt::format("(roc == {}) && ({})", iroc, cut).data(), "profcolzgoff"); + + h2D->SetStats(0); + if (xMax1D > xMin1D) { + h2D->SetMinimum(xMin1D); + h2D->SetMaximum(xMax1D); + } + h2D->SetUniqueID(iroc); + + cROCs1D->cd(pad); + h1D->Draw(); + + cROCs2D->cd(pad); + h2D->Draw("colz"); + + ++pad; + + // associate histograms to canvas + h1D->SetBit(TObject::kCanDelete); + h2D->SetBit(TObject::kCanDelete); + } + } + + // ===| Side histograms |===================================================== + + // ---| define histograms |--------------------------------------------------- + // TODO: auto scaling of ranges based on mean and variance? + // for the moment use roots auto scaling + + // set buffer size such that autoscaling uses the full range. This is about 2MB per histogram! + const int bufferSize = TH1::GetDefaultBufferSize(); + TH1::SetDefaultBufferSize(Sector::MAXSECTOR * mapper.getPadsInSector()); + + auto hAside1D = new TH1F(fmt::format("h_Aside_1D_{}", name).data(), fmt::format("{0} (A-Side);{0}", title).data(), + std::abs(nbins1D), xMin1D, xMax1D); // TODO: modify ranges + + auto hCside1D = new TH1F(fmt::format("h_Cside_1D_{}", name).data(), fmt::format("{0} (C-Side);{0}", title).data(), + std::abs(nbins1D), xMin1D, xMax1D); // TODO: modify ranges + + auto hAside2D = new TProfile2D(fmt::format("h_Aside_2D_{}", name).data(), fmt::format("{} (A-Side);#it{{x}} (cm);#it{{y}} (cm);{}", title, draw).data(), + 330, -270, 270, 330, -270, 270); + + auto hCside2D = new TProfile2D(fmt::format("h_Cside_2D_{}", name).data(), fmt::format("{} (C-Side);#it{{x}} (cm);#it{{y}} (cm);{}", title, draw).data(), + 330, -270, 270, 330, -270, 270); + + tree.Draw(fmt::format("{} >> {}", draw, hAside1D->GetName()).data(), fmt::format("(A_Side) && ({})", cut).data(), "goff"); + tree.Draw(fmt::format("{} >> {}", draw, hCside1D->GetName()).data(), fmt::format("(C_Side) && ({})", cut).data(), "goff"); + tree.Draw(fmt::format("{} : gy : gx >> {}", draw, hAside2D->GetName()).data(), fmt::format("(A_Side) && ({})", cut).data(), "profcolzgoff"); + tree.Draw(fmt::format("{} : gy : gx >> {}", draw, hCside2D->GetName()).data(), fmt::format("(C_Side) && ({})", cut).data(), "profcolzgoff"); + + if (xMax1D > xMin1D) { + hAside2D->SetMinimum(xMin1D); + hAside2D->SetMaximum(xMax1D); + hCside2D->SetMinimum(xMin1D); + hCside2D->SetMaximum(xMax1D); + } + + // ===| Draw histograms |===================================================== + gStyle->SetOptStat("mr"); + auto cSides = new TCanvas(fmt::format("c_{}", name).data(), title.data(), 1000, 1000); + vecCanvases.emplace_back(cSides); + + gStyle->SetStatX(1. - gPad->GetRightMargin()); + gStyle->SetStatY(1. - gPad->GetTopMargin()); + + cSides->Clear(); + cSides->Divide(2, 2); + + cSides->cd(1); + hAside2D->Draw("colz"); + hAside2D->SetStats(0); + hAside2D->SetTitleOffset(1.05, "XY"); + hAside2D->SetTitleSize(0.05, "XY"); + adjustPalette(hAside2D, 0.92); + drawSectorsXY(Side::A); + + cSides->cd(2); + hCside2D->Draw("colz"); + hCside2D->SetStats(0); + hCside2D->SetTitleOffset(1.05, "XY"); + hCside2D->SetTitleSize(0.05, "XY"); + adjustPalette(hCside2D, 0.92); + drawSectorsXY(Side::C); + + cSides->cd(3); + hAside1D->Draw(); + + cSides->cd(4); + hCside1D->Draw(); + + // reset the buffer size + TH1::SetDefaultBufferSize(bufferSize); + + // associate histograms to canvas + hAside1D->SetBit(TObject::kCanDelete); + hCside1D->SetBit(TObject::kCanDelete); + hAside2D->SetBit(TObject::kCanDelete); + hCside2D->SetBit(TObject::kCanDelete); + + return vecCanvases; +} + //______________________________________________________________________________ std::vector painter::makeSummaryCanvases(const std::string_view fileName, const std::string_view calPadNames, int nbins1D, float xMin1D, float xMax1D, bool onlyFilled) { From fab77774bd2397422812798f33e7775ee07d26ba Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 25 Apr 2024 15:43:35 +0200 Subject: [PATCH 0173/2997] Possibility to load specific pedestal object for IDCs --- .../TPC/workflow/src/IDCToVectorSpec.cxx | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Detectors/TPC/workflow/src/IDCToVectorSpec.cxx b/Detectors/TPC/workflow/src/IDCToVectorSpec.cxx index a1b77b2774228..27dbcf5d85bbf 100644 --- a/Detectors/TPC/workflow/src/IDCToVectorSpec.cxx +++ b/Detectors/TPC/workflow/src/IDCToVectorSpec.cxx @@ -80,31 +80,38 @@ class IDCToVectorDevice : public o2::framework::Task auto pedestalFile = ic.options().get("pedestal-url"); if (pedestalFile.length()) { - if (pedestalFile.find("ccdb") != std::string::npos) { - if (pedestalFile.find("-default") != std::string::npos) { - pedestalFile = o2::base::NameConf::getCCDBServer(); + auto& cdb = o2::ccdb::BasicCCDBManager::instance(); + long timeStamp = o2::ccdb::getCurrentTimestamp(); + const auto tsPos = pedestalFile.find("@"); + std::string pedestalURL = pedestalFile.substr(0, tsPos); + if (pedestalURL.find("ccdb") != std::string::npos) { + if (pedestalURL.find("-default") != std::string::npos) { + pedestalURL = o2::base::NameConf::getCCDBServer(); } - LOGP(info, "Loading pedestals from ccdb: {}", pedestalFile); - auto& cdb = o2::ccdb::BasicCCDBManager::instance(); - cdb.setURL(pedestalFile); + LOGP(info, "Loading pedestals from ccdb: {}", pedestalURL); + cdb.setURL(pedestalURL); if (cdb.isHostReachable()) { - auto pedestalNoise = cdb.get>("TPC/Calib/PedestalNoise"); + if (tsPos != std::string::npos) { + timeStamp = std::stol(pedestalFile.substr(tsPos + 1)); + LOGP(info, "Using custom time stamp {}", timeStamp); + } + auto pedestalNoise = cdb.getForTimeStamp>("TPC/Calib/PedestalNoise", timeStamp); try { if (!pedestalNoise) { throw std::runtime_error("Couldn't retrieve PedestaNoise map"); } mPedestal = std::make_unique(pedestalNoise->at("Pedestals")); } catch (const std::exception& e) { - LOGP(fatal, "could not load pedestals from {} ({}), required for IDC processing", pedestalFile, e.what()); + LOGP(fatal, "could not load pedestals from {} ({}), required for IDC processing", pedestalURL, e.what()); } } else { - LOGP(fatal, "ccdb access to {} requested, but host is not reachable. Cannot load pedestals, required for IDC processing", pedestalFile); + LOGP(fatal, "ccdb access to {} requested, but host is not reachable. Cannot load pedestals, required for IDC processing", pedestalURL); } } else { - LOGP(info, "Loading pedestals from file: {}", pedestalFile); - auto calPads = utils::readCalPads(pedestalFile, "Pedestals"); + LOGP(info, "Loading pedestals from file: {}", pedestalURL); + auto calPads = utils::readCalPads(pedestalURL, "Pedestals"); if (calPads.size() != 1) { - LOGP(fatal, "Pedestal could not be loaded from file {}, required for IDC processing", pedestalFile); + LOGP(fatal, "Pedestal could not be loaded from file {}, required for IDC processing", pedestalURL); } else { mPedestal.reset(calPads[0]); } From 550033f752b3f91d7556032750b18ad96ffcd3f0 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Fri, 26 Apr 2024 08:37:04 +0100 Subject: [PATCH 0174/2997] ctpdev (#13080) * dev: max-input-size option for error or fatal * clang --- .../CTP/workflow/include/CTPWorkflow/RawDecoderSpec.h | 1 + Detectors/CTP/workflow/src/RawDecoderSpec.cxx | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Detectors/CTP/workflow/include/CTPWorkflow/RawDecoderSpec.h b/Detectors/CTP/workflow/include/CTPWorkflow/RawDecoderSpec.h index 239701c83fb93..607491b5cb48a 100644 --- a/Detectors/CTP/workflow/include/CTPWorkflow/RawDecoderSpec.h +++ b/Detectors/CTP/workflow/include/CTPWorkflow/RawDecoderSpec.h @@ -57,6 +57,7 @@ class RawDecoderSpec : public framework::Task bool mDoDigits = true; o2::pmr::vector mOutputDigits; int mMaxInputSize = 0; + bool mMaxInputSizeFatal = 0; // for lumi bool mDoLumi = true; // diff --git a/Detectors/CTP/workflow/src/RawDecoderSpec.cxx b/Detectors/CTP/workflow/src/RawDecoderSpec.cxx index b3c140279e8f1..df0988c871196 100644 --- a/Detectors/CTP/workflow/src/RawDecoderSpec.cxx +++ b/Detectors/CTP/workflow/src/RawDecoderSpec.cxx @@ -41,7 +41,8 @@ void RawDecoderSpec::init(framework::InitContext& ctx) mOutputLumiInfo.inp1 = inp1; mOutputLumiInfo.inp2 = inp2; mMaxInputSize = ctx.options().get("max-input-size"); - LOG(info) << "CTP reco init done. Inputs decoding here:" << decodeinps << " DoLumi:" << mDoLumi << " DoDigits:" << mDoDigits << " NTF:" << mNTFToIntegrate << " Lumi inputs:" << lumiinp1 << ":" << inp1 << " " << lumiinp2 << ":" << inp2 << " Max errors:" << maxerrors << " Max input size:" << mMaxInputSize; + mMaxInputSizeFatal = ctx.options().get("max-input-size-fatal"); + LOG(info) << "CTP reco init done. Inputs decoding here:" << decodeinps << " DoLumi:" << mDoLumi << " DoDigits:" << mDoDigits << " NTF:" << mNTFToIntegrate << " Lumi inputs:" << lumiinp1 << ":" << inp1 << " " << lumiinp2 << ":" << inp2 << " Max errors:" << maxerrors << " Max input size:" << mMaxInputSize << " MaxInputSizeFatal:" << mMaxInputSizeFatal; // mOutputLumiInfo.printInputs(); } void RawDecoderSpec::endOfStream(framework::EndOfStreamContext& ec) @@ -118,7 +119,11 @@ void RawDecoderSpec::run(framework::ProcessingContext& ctx) payloadSize += o2::framework::DataRefUtils::getPayloadSize(ref); } if (payloadSize > (size_t)mMaxInputSize) { - LOG(error) << "Input data size:" << payloadSize; + if (mMaxInputSizeFatal) { + LOG(fatal) << "Input data size:" << payloadSize; + } else { + LOG(error) << "Input data size:" << payloadSize; + } dummyOutput(); return; } @@ -203,5 +208,6 @@ o2::framework::DataProcessorSpec o2::ctp::reco_workflow::getRawDecoderSpec(bool {"lumi-inp2", o2::framework::VariantType::String, "VBA", {"The second input used for online lumi. Name in capital."}}, {"use-verbose-mode", o2::framework::VariantType::Bool, false, {"Verbose logging"}}, {"max-input-size", o2::framework::VariantType::Int, 0, {"Do not process input if bigger than max size, 0 - do not check"}}, + {"max-input-size-fatal", o2::framework::VariantType::Bool, false, {"If true issue fatal error otherwise error on;y"}}, {"ctpinputs-decoding", o2::framework::VariantType::Bool, false, {"Inputs alignment: true - raw decoder - has to be compatible with CTF decoder: allowed options: 10,01,00"}}}}; } From 1570db67be6c8940cafce0b01a7ec17cb10a47af Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Fri, 26 Apr 2024 11:07:40 +0200 Subject: [PATCH 0175/2997] [EMCAL-741] Use std::round for pedestal ADC extraction (#13078) --- .../include/EMCALCalibration/EMCALCalibExtractor.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h index 1571f29670368..035dc92ecfe09 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibExtractor.h @@ -19,6 +19,7 @@ #define EMCALCALIBEXTRACTOR_H_ #include +#include #include #include "CCDB/BasicCCDBManager.h" #include "EMCALCalib/BadChannelMap.h" @@ -465,7 +466,7 @@ class EMCALCalibExtractor if (rms > EMCALCalibParams::Instance().maxPedestalRMS) { mean = mMaxPedestalVal; } - pedestalData.addPedestalValue(iCell, mean, isLG, isLEDMON); + pedestalData.addPedestalValue(iCell, std::round(mean), isLG, isLEDMON); } } } @@ -488,7 +489,7 @@ class EMCALCalibExtractor if (!obj) continue; for (unsigned short iCell = 0; iCell < maxChannels; ++iCell) { - short mean = static_cast(obj->GetBinContent(iCell + 1)); + short mean = static_cast(std::round(obj->GetBinContent(iCell + 1))); short rms = static_cast(obj->GetBinError(iCell + 1) / obj->GetBinEntries(iCell + 1)); if (rms > EMCALCalibParams::Instance().maxPedestalRMS) { mean = mMaxPedestalVal; From 9a71e7f157272f587affb3dd3b46f41aa5256ad9 Mon Sep 17 00:00:00 2001 From: Peter Hristov Date: Fri, 26 Apr 2024 11:09:52 +0200 Subject: [PATCH 0176/2997] Additional changes for newer versions of ONNXRuntime (#13072) * Additional changes for newer versions of ONNXRuntime * Clang-format --- Detectors/TRD/pid/include/TRDPID/ML.h | 10 +++++++--- Detectors/TRD/pid/src/ML.cxx | 11 +++++++++++ dependencies/FindONNXRuntime.cmake | 3 +++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Detectors/TRD/pid/include/TRDPID/ML.h b/Detectors/TRD/pid/include/TRDPID/ML.h index c43de8921630a..210dfb56d80ff 100644 --- a/Detectors/TRD/pid/include/TRDPID/ML.h +++ b/Detectors/TRD/pid/include/TRDPID/ML.h @@ -70,10 +70,14 @@ class ML : public PIDBase [](void* param, OrtLoggingLevel severity, const char* category, const char* logid, const char* code_location, const char* message) { LOG(warn) << "Ort " << severity << ": [" << logid << "|" << category << "|" << code_location << "]: " << message << ((intptr_t)param == 3 ? " [valid]" : " [error]"); }, - (void*)3}; ///< ONNX enviroment - const OrtApi& mApi{Ort::GetApi()}; ///< ONNX api + (void*)3}; ///< ONNX enviroment + const OrtApi& mApi{Ort::GetApi()}; ///< ONNX api +#if __has_include() std::unique_ptr mSession; ///< ONNX session - Ort::SessionOptions mSessionOptions; ///< ONNX session options +#else + std::unique_ptr mSession; ///< ONNX session +#endif + Ort::SessionOptions mSessionOptions; ///< ONNX session options Ort::AllocatorWithDefaultOptions mAllocator; // Input/Output diff --git a/Detectors/TRD/pid/src/ML.cxx b/Detectors/TRD/pid/src/ML.cxx index 785f3b05cc112..bee46b27767a8 100644 --- a/Detectors/TRD/pid/src/ML.cxx +++ b/Detectors/TRD/pid/src/ML.cxx @@ -68,7 +68,11 @@ void ML::init(o2::framework::ProcessingContext& pc) LOG(info) << "Set GraphOptimizationLevel to " << mParams.graphOptimizationLevel; // create actual session +#if __has_include() mSession = std::make_unique(mEnv, reinterpret_cast(model_data.data()), model_data.size(), mSessionOptions); +#else + mSession = std::make_unique(mEnv, reinterpret_cast(model_data.data()), model_data.size(), mSessionOptions); +#endif LOG(info) << "ONNX runtime session created"; // print name/shape of inputs @@ -104,8 +108,15 @@ float ML::process(const TrackTRD& trk, const o2::globaltracking::RecoContainer& try { auto input = prepareModelInput(trk, inputTracks); // create memory mapping to vector above +#if __has_include() auto inputTensor = Ort::Experimental::Value::CreateTensor(input.data(), input.size(), {static_cast(input.size()) / mInputShapes[0][1], mInputShapes[0][1]}); +#else + Ort::MemoryInfo mem_info = + Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); + auto inputTensor = Ort::Value::CreateTensor(mem_info, input.data(), input.size(), + {static_cast(input.size()) / mInputShapes[0][1], mInputShapes[0][1]}); +#endif std::vector ortTensor; ortTensor.push_back(std::move(inputTensor)); auto outTensor = mSession->Run(mInputNames, ortTensor, mOutputNames); diff --git a/dependencies/FindONNXRuntime.cmake b/dependencies/FindONNXRuntime.cmake index 0983d44644a6c..b783c2e1c7bf3 100644 --- a/dependencies/FindONNXRuntime.cmake +++ b/dependencies/FindONNXRuntime.cmake @@ -17,4 +17,7 @@ endif() if (NOT ONNXRuntime::ONNXRuntime_FOUND) find_package(onnxruntime CONFIG) + if (onnxruntime_FOUND) + add_library(ONNXRuntime::ONNXRuntime ALIAS onnxruntime::onnxruntime) + endif() endif() From a7251617e288c03b3583f7de1c4421afcb4bd6ae Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Fri, 26 Apr 2024 12:43:57 +0200 Subject: [PATCH 0177/2997] Add CMakeLists.txt.user to .gitignore (#13083) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a489daad80115..6db76441528d9 100644 --- a/.gitignore +++ b/.gitignore @@ -63,6 +63,7 @@ compile_commands.json .vscode .ycm_extra_conf.py Session.vim +CMakeLists.txt.user # Datafiles gphysi.dat From 639b9b2cf8ff172fb7d36145f7734d87624e0399 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 26 Apr 2024 14:33:57 +0200 Subject: [PATCH 0178/2997] QC-1160 Move to the new names for QC flags (#13073) Needs new QC release. The documentation will be updated in a separate PR. --- DataFormats/QualityControl/CMakeLists.txt | 60 ++++---- .../etc/{flagReasons.csv => flagTypes.csv} | 0 .../DataFormatsQualityControl/FlagReasons.h | 73 ---------- .../DataFormatsQualityControl/FlagType.h | 50 ++++++- .../FlagTypeFactory.h | 22 --- ...easonFactory.h.in => FlagTypeFactory.h.in} | 18 +-- .../QualityControlFlag.h | 73 +++++++++- .../QualityControlFlagCollection.h | 88 +++++++++++- .../DataFormatsQualityControl/TimeRangeFlag.h | 88 ------------ .../TimeRangeFlagCollection.h | 102 ------------- .../src/DataFormatsQualityControlLinkDef.h | 6 +- .../src/{FlagReasons.cxx => FlagType.cxx} | 18 +-- ...meRangeFlag.cxx => QualityControlFlag.cxx} | 18 +-- ...n.cxx => QualityControlFlagCollection.cxx} | 68 ++++----- ...{testFlagReasons.cxx => testFlagTypes.cxx} | 48 +++---- ...ngeFlag.cxx => testQualityControlFlag.cxx} | 20 +-- .../test/testQualityControlFlagCollection.cxx | 136 ++++++++++++++++++ .../test/testTimeRangeFlagCollection.cxx | 136 ------------------ 18 files changed, 461 insertions(+), 563 deletions(-) rename DataFormats/QualityControl/etc/{flagReasons.csv => flagTypes.csv} (100%) delete mode 100644 DataFormats/QualityControl/include/DataFormatsQualityControl/FlagReasons.h delete mode 100644 DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h rename DataFormats/QualityControl/include/DataFormatsQualityControl/{FlagReasonFactory.h.in => FlagTypeFactory.h.in} (67%) delete mode 100644 DataFormats/QualityControl/include/DataFormatsQualityControl/TimeRangeFlag.h delete mode 100644 DataFormats/QualityControl/include/DataFormatsQualityControl/TimeRangeFlagCollection.h rename DataFormats/QualityControl/src/{FlagReasons.cxx => FlagType.cxx} (70%) rename DataFormats/QualityControl/src/{TimeRangeFlag.cxx => QualityControlFlag.cxx} (74%) rename DataFormats/QualityControl/src/{TimeRangeFlagCollection.cxx => QualityControlFlagCollection.cxx} (65%) rename DataFormats/QualityControl/test/{testFlagReasons.cxx => testFlagTypes.cxx} (62%) rename DataFormats/QualityControl/test/{testTimeRangeFlag.cxx => testQualityControlFlag.cxx} (58%) create mode 100644 DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx delete mode 100644 DataFormats/QualityControl/test/testTimeRangeFlagCollection.cxx diff --git a/DataFormats/QualityControl/CMakeLists.txt b/DataFormats/QualityControl/CMakeLists.txt index 03a3b0ed49f69..c0f40a88f88c1 100644 --- a/DataFormats/QualityControl/CMakeLists.txt +++ b/DataFormats/QualityControl/CMakeLists.txt @@ -10,33 +10,32 @@ # or submit itself to any jurisdiction. file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include) -### Prepare the list of methods in FlagReasonFactory -file(READ "etc/flagReasons.csv" CSV_FLAG_REASONS) +### Prepare the list of methods in FlagTypeFactory +file(READ "etc/flagTypes.csv" CSV_FLAG_TYPES) # delete the CSV file header -string(REPLACE \"id\",\"method\",\"name\",\"bad\",\"obsolete\" "" CSV_FLAG_REASONS ${CSV_FLAG_REASONS}) +string(REPLACE \"id\",\"method\",\"name\",\"bad\",\"obsolete\" "" CSV_FLAG_TYPES ${CSV_FLAG_TYPES}) # detects if there is obsolete flag '1' in the last column, adds [[deprecated]] if so and retains the rest of the string string(REGEX REPLACE \([0-9]+,\".[^\"]*.\",.[^\"]*.,[0-1]\),1 "[[deprecated]] \\1,1" - CSV_FLAG_REASONS - ${CSV_FLAG_REASONS}) + CSV_FLAG_TYPES + ${CSV_FLAG_TYPES}) # replaces the flag reason entry with a c++ method to create it string(REGEX REPLACE \([0-9]+\),\"\(.[^\"]*.\)\",\(.[^\"]*.\),\([0-1]\),[0-1] - "static FlagReason \\2\(\) { return { static_cast\(\\1\), \\3, static_cast\(\\4\) }; }" - CSV_FLAG_REASONS - ${CSV_FLAG_REASONS}) + "static FlagType \\2\(\) { return { static_cast\(\\1\), \\3, static_cast\(\\4\) }; }" + CSV_FLAG_TYPES + ${CSV_FLAG_TYPES}) # put the method lists inside the template -configure_file("include/DataFormatsQualityControl/FlagReasonFactory.h.in" - "${CMAKE_CURRENT_BINARY_DIR}/include/DataFormatsQualityControl/FlagReasonFactory.h" +configure_file("include/DataFormatsQualityControl/FlagTypeFactory.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/include/DataFormatsQualityControl/FlagTypeFactory.h" @ONLY) -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/DataFormatsQualityControl/FlagReasonFactory.h" +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/DataFormatsQualityControl/FlagTypeFactory.h" DESTINATION include/DataFormatsQualityControl) o2_add_library(DataFormatsQualityControl - SOURCES src/FlagReasons.cxx - src/TimeRangeFlag.cxx - src/TimeRangeFlagCollection.cxx - PUBLIC_LINK_LIBRARIES O2::Headers - O2::FrameworkLogger + SOURCES src/FlagType.cxx + src/QualityControlFlag.cxx + src/QualityControlFlagCollection.cxx + PUBLIC_LINK_LIBRARIES O2::FrameworkLogger O2::DetectorsCommonDataFormats PUBLIC_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}/include include @@ -44,35 +43,32 @@ o2_add_library(DataFormatsQualityControl o2_target_root_dictionary(DataFormatsQualityControl HEADERS include/DataFormatsQualityControl/FlagType.h - include/DataFormatsQualityControl/FlagReasons.h include/DataFormatsQualityControl/QualityControlFlag.h - include/DataFormatsQualityControl/TimeRangeFlag.h - include/DataFormatsQualityControl/TimeRangeFlagCollection.h) - + include/DataFormatsQualityControl/QualityControlFlagCollection.h) if(BUILD_TESTING) -o2_add_test(FlagReasons - SOURCES test/testFlagReasons.cxx +o2_add_test(FlagTypes + SOURCES test/testFlagTypes.cxx COMPONENT_NAME DataFormatsQualityControl PUBLIC_LINK_LIBRARIES O2::DataFormatsQualityControl - TARGETVARNAME flagreasons) + TARGETVARNAME flagtypes) -target_include_directories(${flagreasons} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include) +target_include_directories(${flagtypes} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include) -o2_add_test(TimeRangeFlag - SOURCES test/testTimeRangeFlag.cxx +o2_add_test(QualityControlFlag + SOURCES test/testQualityControlFlag.cxx COMPONENT_NAME DataFormatsQualityControl PUBLIC_LINK_LIBRARIES O2::DataFormatsQualityControl - TARGETVARNAME timerangeflag) + TARGETVARNAME qualitycontrolflag) -target_include_directories(${timerangeflag} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include) +target_include_directories(${qualitycontrolflag} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include) -o2_add_test(TimeRangeFlagCollection - SOURCES test/testTimeRangeFlagCollection.cxx +o2_add_test(QualityControlFlagCollection + SOURCES test/testQualityControlFlagCollection.cxx COMPONENT_NAME DataFormatsQualityControl PUBLIC_LINK_LIBRARIES O2::DataFormatsQualityControl - TARGETVARNAME timerangeflagcollection) + TARGETVARNAME qualitycontrolflagcollection) -target_include_directories(${timerangeflagcollection} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include) +target_include_directories(${qualitycontrolflagcollection} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include) endif() diff --git a/DataFormats/QualityControl/etc/flagReasons.csv b/DataFormats/QualityControl/etc/flagTypes.csv similarity index 100% rename from DataFormats/QualityControl/etc/flagReasons.csv rename to DataFormats/QualityControl/etc/flagTypes.csv diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagReasons.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagReasons.h deleted file mode 100644 index 67f5b4cc27cde..0000000000000 --- a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagReasons.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -#ifndef ALICEO2_ANALYSIS_FLAGREASONS -#define ALICEO2_ANALYSIS_FLAGREASONS - -/// \file FlagReasons.h -/// \brief classes keeping reasons for flagging time ranges -/// \author Jens Wiechula, jens.wiechula@ikf.uni-frankfurt.de -/// \author Piotr Konopka, piotr.jan.konopka@cern.ch - -// STL -#include -#include - -// ROOT includes -#include - -namespace o2 -{ -namespace quality_control -{ - -class FlagReasonFactory; -class TimeRangeFlagCollection; - -class FlagReason -{ - private: - uint16_t mId; - std::string mName; - bool mBad; // if true, data should become bad by default - - // By making the constructor private and FlagReasons available only in the FlagReasonFactory - // we forbid to declare any flags in the user code. If you need a new FlagReason, please add it FlagReasonFactory. - private: - FlagReason(uint16_t id, const char* name, bool bad) : mId(id), mName(name), mBad(bad) {} - - public: - FlagReason(); - FlagReason& operator=(const FlagReason&) = default; - FlagReason(const FlagReason&) = default; - bool operator==(const FlagReason& rhs) const; - bool operator!=(const FlagReason& rhs) const; - bool operator<(const FlagReason& rhs) const; - bool operator>(const FlagReason& rhs) const; - - uint16_t getID() const { return mId; } - const std::string& getName() const { return mName; } - bool getBad() const { return mBad; } - - friend std::ostream& operator<<(std::ostream& os, FlagReason const& me); - friend class FlagReasonFactory; - friend class TimeRangeFlagCollection; - - ClassDefNV(FlagReason, 1); -}; - -} // namespace quality_control -} // namespace o2 - -// TODO: remove once we include it in QualityControl -#include "DataFormatsQualityControl/FlagReasonFactory.h" - -#endif diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagType.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagType.h index c862835530de6..94e4a301a1784 100644 --- a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagType.h +++ b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagType.h @@ -12,11 +12,53 @@ #ifndef O2_QUALITYCONTROL_FLAGTYPE_H #define O2_QUALITYCONTROL_FLAGTYPE_H -#include "DataFormatsQualityControl/FlagReasons.h" +// STL +#include +#include -namespace o2::quality_control +// ROOT includes +#include + +namespace o2 +{ +namespace quality_control +{ + +class FlagTypeFactory; +class QualityControlFlagCollection; + +class FlagType { -using FlagType = o2::quality_control::FlagReason; -} + private: + uint16_t mId; + std::string mName; + bool mBad; // if true, data should become bad by default + + // By making the constructor private and FlagTypes available only in the FlagTypeFactory + // we forbid to declare any flags in the user code. If you need a new FlagType, please add it FlagTypeFactory. + private: + FlagType(uint16_t id, const char* name, bool bad) : mId(id), mName(name), mBad(bad) {} + + public: + FlagType(); + FlagType& operator=(const FlagType&) = default; + FlagType(const FlagType&) = default; + bool operator==(const FlagType& rhs) const; + bool operator!=(const FlagType& rhs) const; + bool operator<(const FlagType& rhs) const; + bool operator>(const FlagType& rhs) const; + + uint16_t getID() const { return mId; } + const std::string& getName() const { return mName; } + bool getBad() const { return mBad; } + + friend std::ostream& operator<<(std::ostream& os, FlagType const& me); + friend class FlagTypeFactory; + friend class QualityControlFlagCollection; + + ClassDefNV(FlagType, 1); +}; +} // namespace quality_control +} // namespace o2 #endif // O2_QUALITYCONTROL_FLAGTYPE_H diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h deleted file mode 100644 index ea28ffbd3d944..0000000000000 --- a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -#ifndef O2_QUALITYCONTROL_FLAGTYPEFACTORY_H -#define O2_QUALITYCONTROL_FLAGTYPEFACTORY_H - -#include "DataFormatsQualityControl/FlagReasonFactory.h" - -namespace o2::quality_control -{ -using FlagTypeFactory = o2::quality_control::FlagReasonFactory; -} - -#endif // O2_QUALITYCONTROL_FLAGTYPEFACTORY_H diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagReasonFactory.h.in b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h.in similarity index 67% rename from DataFormats/QualityControl/include/DataFormatsQualityControl/FlagReasonFactory.h.in rename to DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h.in index 59bd7b4c5628f..38b6c463d239f 100644 --- a/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagReasonFactory.h.in +++ b/DataFormats/QualityControl/include/DataFormatsQualityControl/FlagTypeFactory.h.in @@ -9,23 +9,23 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file FlagReasonFactory.h -/// \brief A class to create FlagReasons based on the predefined CSV list. +/// \file FlagTypeFactory.h +/// \brief A class to create FlagTypes based on the predefined CSV list. /// \author Piotr Konopka, piotr.jan.konopka@cern.ch -#ifndef O2_FLAGREASONFACTORY_H -#define O2_FLAGREASONFACTORY_H +#ifndef O2_FLAGTYPEFACTORY_H +#define O2_FLAGTYPEFACTORY_H -#include "DataFormatsQualityControl/FlagReasons.h" +#include "DataFormatsQualityControl/FlagType.h" namespace o2::quality_control { -class FlagReasonFactory { +class FlagTypeFactory { public: -FlagReasonFactory() = delete; -@CSV_FLAG_REASONS@ +FlagTypeFactory() = delete; +@CSV_FLAG_TYPES@ }; } // namespace o2::quality_control -#endif // O2_FLAGREASONFACTORY_H \ No newline at end of file +#endif // O2_FLAGTYPEFACTORY_H \ No newline at end of file diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlag.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlag.h index 96c778220f617..16123b74895ab 100644 --- a/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlag.h +++ b/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlag.h @@ -12,11 +12,76 @@ #ifndef O2_QUALITYCONTROL_QCFLAG_H #define O2_QUALITYCONTROL_QCFLAG_H -#include "DataFormatsQualityControl/TimeRangeFlag.h" +/// \file QualityControlFlag.h +/// \brief Class to define a flag type with a time range and comments +/// \author Jens Wiechula, jens.wiechula@ikf.uni-frankfurt.de +/// \author Piotr Konopka, piotr.jan.konopka@cern.ch -namespace o2::quality_control +// System includes +#include +#include + +// ROOT includes +#include + +#include + +#include "DataFormatsQualityControl/FlagType.h" +#include "DataFormatsQualityControl/FlagTypeFactory.h" + +namespace o2 { -using QualityControlFlag = o2::quality_control::TimeRangeFlag; -} +namespace quality_control +{ + +/// \class QualityControlFlag +/// A Class for associating a bit mask with a time range +class QualityControlFlag +{ + public: + using time_type = uint64_t; + using RangeInterval = o2::math_utils::detail::Bracket; + + QualityControlFlag() = default; + QualityControlFlag(QualityControlFlag const&) = default; + QualityControlFlag(time_type start, time_type end, FlagType flag, std::string comment = "", std::string source = "Unknown"); + + time_type getStart() const { return mInterval.getMin(); } + time_type getEnd() const { return mInterval.getMax(); } + RangeInterval& getInterval() { return mInterval; } + FlagType getFlag() const { return mFlag; } + const std::string& getComment() const { return mComment; } + const std::string& getSource() const { return mSource; } + + void setStart(time_type start) { mInterval.setMin(start); } + void setEnd(time_type end) { mInterval.setMax(end); } + void setInterval(RangeInterval interval) { mInterval = interval; } + void setFlag(FlagType flag) { mFlag = flag; } + void setComment(const std::string& comment) { mComment = comment; } + void setSource(const std::string& source) { mSource = source; } + + /// equal operator + bool operator==(const QualityControlFlag& rhs) const; + + /// comparison operators + bool operator<(const QualityControlFlag& rhs) const; + bool operator>(const QualityControlFlag& rhs) const; + + /// write data to ostream + void streamTo(std::ostream& output) const; + + /// overloading output stream operator + friend std::ostream& operator<<(std::ostream& output, const QualityControlFlag& data); + + private: + RangeInterval mInterval = {}; ///< time interval of the masked range + FlagType mFlag; ///< flag reason + std::string mComment = ""; ///< optional comment, which may extend the reason + std::string mSource = "Unknown"; ///< optional (but encouraged) source of the flag (e.g. Qc Check name) + + ClassDefNV(QualityControlFlag, 1); +}; +} // namespace quality_control +} // namespace o2 #endif // O2_QUALITYCONTROL_QCFLAG_H diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlagCollection.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlagCollection.h index 04cd74f09444e..120605f048cbe 100644 --- a/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlagCollection.h +++ b/DataFormats/QualityControl/include/DataFormatsQualityControl/QualityControlFlagCollection.h @@ -11,12 +11,92 @@ #ifndef O2_QUALITYCONTROL_QCFLAGCOLLECTION_H #define O2_QUALITYCONTROL_QCFLAGCOLLECTION_H +/// \file QualityControlFlagCollection.h +/// \brief classes for defining time ranges with a certain mask to be able to cut on +/// \author Jens Wiechula, jens.wiechula@ikf.uni-frankfurt.de -#include "DataFormatsQualityControl/TimeRangeFlagCollection.h" +// System includes +#include -namespace o2::quality_control +// ROOT includes +#include "Rtypes.h" + +// O2 includes +#include "MathUtils/detail/Bracket.h" +#include "DataFormatsQualityControl/QualityControlFlag.h" + +// STL +#include + +namespace o2 +{ +namespace quality_control +{ + +/// \class QualityControlFlagCollection +/// A Class for keeping several time ranges of type QualityControlFlag +class QualityControlFlagCollection { -using QualityControlFlagCollection = o2::quality_control::TimeRangeFlagCollection; -} + public: + using collection_t = std::set; + using time_type = uint64_t; + using RangeInterval = o2::math_utils::detail::Bracket; + + explicit QualityControlFlagCollection(std::string name, std::string detector = "TST", RangeInterval validityRange = {}, + int runNumber = 0, std::string periodName = "Invalid", std::string passName = "Invalid", + std::string provenance = "qc"); + + void insert(QualityControlFlag&&); + void insert(const QualityControlFlag&); + + size_t size() const; + + // moves all non-repeating QualityControlFlags from other to this + void merge(QualityControlFlagCollection& other); + // add all non-repeating QualityControlFlags from other to this. + void merge(const QualityControlFlagCollection& other); + + collection_t::const_iterator begin() const; + collection_t::const_iterator end() const; + + const std::string& getName() const; + const std::string& getDetector() const; + int getRunNumber() const; + const std::string& getPeriodName() const; + const std::string& getPassName() const; + const std::string& getProvenance() const; + + time_type getStart() const { return mValidityRange.getMin(); } + time_type getEnd() const { return mValidityRange.getMax(); } + RangeInterval& getInterval() { return mValidityRange; } + + void setStart(time_type start) { mValidityRange.setMin(start); } + void setEnd(time_type end) { mValidityRange.setMax(end); } + void setInterval(RangeInterval interval) { mValidityRange = interval; } + + /// write data to ostream + void streamTo(std::ostream& output) const; + /// Read data from instream + void streamFrom(std::istream& input); + + /// overloading output stream operator + friend std::ostream& operator<<(std::ostream& output, const QualityControlFlagCollection& data); + + private: + std::string mDetID; // three letter detector code + std::string mName; // some description of the collection, e.g. "Raw data checks", "QA Expert masks" + // with std::set we can sort the flags in time and have merge() for granted. + collection_t mQualityControlFlags; + RangeInterval mValidityRange; // we need a validity range to e.g. state that there are no TRFs for given time interval + int mRunNumber; + std::string mPeriodName; + std::string mPassName; + std::string mProvenance; + + ClassDefNV(QualityControlFlagCollection, 1); +}; + +} // namespace quality_control +} // namespace o2 #endif // O2_QUALITYCONTROL_QCFLAGCOLLECTION_H diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/TimeRangeFlag.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/TimeRangeFlag.h deleted file mode 100644 index b8e1efbce1f40..0000000000000 --- a/DataFormats/QualityControl/include/DataFormatsQualityControl/TimeRangeFlag.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -#ifndef ALICEO2_ANALYSIS_TIMERANGEFLAGS -#define ALICEO2_ANALYSIS_TIMERANGEFLAGS - -/// \file TimeRangeFlag.h -/// \brief Class to define a time range of a flag type -/// \author Jens Wiechula, jens.wiechula@ikf.uni-frankfurt.de -/// \author Piotr Konopka, piotr.jan.konopka@cern.ch - -// System includes -#include -#include - -// ROOT includes -#include - -#include - -#include "DataFormatsQualityControl/FlagReasons.h" -#include "DataFormatsQualityControl/FlagReasonFactory.h" - -namespace o2 -{ -namespace quality_control -{ - -/// \class TimeRangeFlag -/// A Class for associating a bit mask with a time range -class TimeRangeFlag -{ - public: - using time_type = uint64_t; - using flag_type = FlagReason; - using RangeInterval = o2::math_utils::detail::Bracket; - - TimeRangeFlag() = default; - TimeRangeFlag(TimeRangeFlag const&) = default; - TimeRangeFlag(time_type start, time_type end, flag_type flag, std::string comment = "", std::string source = "Unknown"); - - time_type getStart() const { return mInterval.getMin(); } - time_type getEnd() const { return mInterval.getMax(); } - RangeInterval& getInterval() { return mInterval; } - flag_type getFlag() const { return mFlag; } - const std::string& getComment() const { return mComment; } - const std::string& getSource() const { return mSource; } - - void setStart(time_type start) { mInterval.setMin(start); } - void setEnd(time_type end) { mInterval.setMax(end); } - void setInterval(RangeInterval interval) { mInterval = interval; } - void setFlag(flag_type flag) { mFlag = flag; } - void setComment(const std::string& comment) { mComment = comment; } - void setSource(const std::string& source) { mSource = source; } - - /// equal operator - bool operator==(const TimeRangeFlag& rhs) const; - - /// comparison operators - bool operator<(const TimeRangeFlag& rhs) const; - bool operator>(const TimeRangeFlag& rhs) const; - - /// write data to ostream - void streamTo(std::ostream& output) const; - - /// overloading output stream operator - friend std::ostream& operator<<(std::ostream& output, const TimeRangeFlag& data); - - private: - RangeInterval mInterval = {}; ///< time interval of the masked range - flag_type mFlag; ///< flag reason - std::string mComment = ""; ///< optional comment, which may extend the reason - std::string mSource = "Unknown"; ///< optional (but encouraged) source of the flag (e.g. Qc Check name) - - ClassDefNV(TimeRangeFlag, 1); -}; - -} // namespace quality_control -} // namespace o2 -#endif diff --git a/DataFormats/QualityControl/include/DataFormatsQualityControl/TimeRangeFlagCollection.h b/DataFormats/QualityControl/include/DataFormatsQualityControl/TimeRangeFlagCollection.h deleted file mode 100644 index 30a8230fc66e2..0000000000000 --- a/DataFormats/QualityControl/include/DataFormatsQualityControl/TimeRangeFlagCollection.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -#ifndef ALICEO2_ANALYSIS_TIMERANGEMASK -#define ALICEO2_ANALYSIS_TIMERANGEMASK - -/// \file TimeRangeFlagCollection.h -/// \brief classes for defining time ranges with a certain mask to be able to cut on -/// \author Jens Wiechula, jens.wiechula@ikf.uni-frankfurt.de - -// System includes -#include - -// ROOT includes -#include "Rtypes.h" - -// O2 includes -#include "MathUtils/detail/Bracket.h" -#include "DataFormatsQualityControl/TimeRangeFlag.h" - -// STL -#include - -namespace o2 -{ -namespace quality_control -{ - -/// \class TimeRangeFlagCollection -/// A Class for keeping several time ranges of type TimeRangeFlag -class TimeRangeFlagCollection -{ - public: - using collection_t = std::set; - using time_type = uint64_t; - using RangeInterval = o2::math_utils::detail::Bracket; - - explicit TimeRangeFlagCollection(std::string name, std::string detector = "TST", RangeInterval validityRange = {}, - int runNumber = 0, std::string periodName = "Invalid", std::string passName = "Invalid", - std::string provenance = "qc"); - - void insert(TimeRangeFlag&&); - void insert(const TimeRangeFlag&); - - size_t size() const; - - // moves all non-repeating TimeRangeFlags from other to this - void merge(TimeRangeFlagCollection& other); - // add all non-repeating TimeRangeFlags from other to this. - void merge(const TimeRangeFlagCollection& other); - - collection_t::const_iterator begin() const; - collection_t::const_iterator end() const; - - const std::string& getName() const; - const std::string& getDetector() const; - int getRunNumber() const; - const std::string& getPeriodName() const; - const std::string& getPassName() const; - const std::string& getProvenance() const; - - time_type getStart() const { return mValidityRange.getMin(); } - time_type getEnd() const { return mValidityRange.getMax(); } - RangeInterval& getInterval() { return mValidityRange; } - - void setStart(time_type start) { mValidityRange.setMin(start); } - void setEnd(time_type end) { mValidityRange.setMax(end); } - void setInterval(RangeInterval interval) { mValidityRange = interval; } - - /// write data to ostream - void streamTo(std::ostream& output) const; - /// Read data from instream - void streamFrom(std::istream& input); - - /// overloading output stream operator - friend std::ostream& operator<<(std::ostream& output, const TimeRangeFlagCollection& data); - - private: - std::string mDetID; // three letter detector code - std::string mName; // some description of the collection, e.g. "Raw data checks", "QA Expert masks" - // with std::set we can sort the flags in time and have merge() for granted. - collection_t mTimeRangeFlags; - RangeInterval mValidityRange; // we need a validity range to e.g. state that there are no TRFs for given time interval - int mRunNumber; - std::string mPeriodName; - std::string mPassName; - std::string mProvenance; - - ClassDefNV(TimeRangeFlagCollection, 1); -}; - -} // namespace quality_control -} // namespace o2 -#endif diff --git a/DataFormats/QualityControl/src/DataFormatsQualityControlLinkDef.h b/DataFormats/QualityControl/src/DataFormatsQualityControlLinkDef.h index 8d77bccef4b7c..ab10c361b29f9 100644 --- a/DataFormats/QualityControl/src/DataFormatsQualityControlLinkDef.h +++ b/DataFormats/QualityControl/src/DataFormatsQualityControlLinkDef.h @@ -15,8 +15,8 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class o2::quality_control::FlagReason + ; -#pragma link C++ class o2::quality_control::TimeRangeFlag + ; -#pragma link C++ class o2::quality_control::TimeRangeFlagCollection + ; +#pragma link C++ class o2::quality_control::FlagType + ; +#pragma link C++ class o2::quality_control::QualityControlFlag + ; +#pragma link C++ class o2::quality_control::QualityControlFlagCollection + ; #endif diff --git a/DataFormats/QualityControl/src/FlagReasons.cxx b/DataFormats/QualityControl/src/FlagType.cxx similarity index 70% rename from DataFormats/QualityControl/src/FlagReasons.cxx rename to DataFormats/QualityControl/src/FlagType.cxx index e85a0d0c7faa7..27e59911ed775 100644 --- a/DataFormats/QualityControl/src/FlagReasons.cxx +++ b/DataFormats/QualityControl/src/FlagType.cxx @@ -9,8 +9,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "DataFormatsQualityControl/FlagReasons.h" -#include "DataFormatsQualityControl/FlagReasonFactory.h" +#include "DataFormatsQualityControl/FlagType.h" +#include "DataFormatsQualityControl/FlagTypeFactory.h" #include #include @@ -18,29 +18,29 @@ namespace o2::quality_control { -FlagReason::FlagReason() +FlagType::FlagType() { - *this = FlagReasonFactory::Invalid(); + *this = FlagTypeFactory::Invalid(); } -std::ostream& operator<<(std::ostream& os, FlagReason const& my) +std::ostream& operator<<(std::ostream& os, FlagType const& my) { os << "Flag Reason: id - " << my.mId << ", name - " << my.mName << ", bad - " << (my.mBad ? "true" : "false"); return os; } -bool FlagReason::operator==(const FlagReason& rhs) const +bool FlagType::operator==(const FlagType& rhs) const { return std::tie(mId, mName, mBad) == std::tie(rhs.mId, rhs.mName, rhs.mBad); } -bool FlagReason::operator!=(const FlagReason& rhs) const +bool FlagType::operator!=(const FlagType& rhs) const { return std::tie(mId, mName, mBad) != std::tie(rhs.mId, rhs.mName, rhs.mBad); } -bool FlagReason::operator<(const FlagReason& rhs) const +bool FlagType::operator<(const FlagType& rhs) const { return std::tie(mId, mName, mBad) < std::tie(rhs.mId, rhs.mName, rhs.mBad); } -bool FlagReason::operator>(const FlagReason& rhs) const +bool FlagType::operator>(const FlagType& rhs) const { return std::tie(mId, mName, mBad) > std::tie(rhs.mId, rhs.mName, rhs.mBad); } diff --git a/DataFormats/QualityControl/src/TimeRangeFlag.cxx b/DataFormats/QualityControl/src/QualityControlFlag.cxx similarity index 74% rename from DataFormats/QualityControl/src/TimeRangeFlag.cxx rename to DataFormats/QualityControl/src/QualityControlFlag.cxx index f96d5bc9b7b72..ce749cad5315f 100644 --- a/DataFormats/QualityControl/src/TimeRangeFlag.cxx +++ b/DataFormats/QualityControl/src/QualityControlFlag.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "DataFormatsQualityControl/TimeRangeFlag.h" +#include "DataFormatsQualityControl/QualityControlFlag.h" #include #include @@ -17,20 +17,20 @@ namespace o2::quality_control { -TimeRangeFlag::TimeRangeFlag(time_type start, time_type end, flag_type flag, std::string comment, std::string source) +QualityControlFlag::QualityControlFlag(time_type start, time_type end, FlagType flag, std::string comment, std::string source) : mInterval(start, end), mFlag(flag), mComment(comment), mSource(source) { if (mInterval.isInvalid()) { - throw std::runtime_error("TimeRangeFlag start time '" + std::to_string(mInterval.getMin()) + "' is larger than end time '" + std::to_string(mInterval.getMax()) + "'"); + throw std::runtime_error("QualityControlFlag start time '" + std::to_string(mInterval.getMin()) + "' is larger than end time '" + std::to_string(mInterval.getMax()) + "'"); } } -bool TimeRangeFlag::operator==(const TimeRangeFlag& rhs) const +bool QualityControlFlag::operator==(const QualityControlFlag& rhs) const { return std::tie(mInterval, mFlag, mComment, mSource) == std::tie(rhs.mInterval, rhs.mFlag, rhs.mComment, rhs.mSource); } -bool TimeRangeFlag::operator<(const TimeRangeFlag& rhs) const +bool QualityControlFlag::operator<(const QualityControlFlag& rhs) const { // We don't use the comparison mechanism in Bracket, // because std::set which is used in TRFCollection assumes that a < b, a > b <=> a == b. @@ -38,16 +38,16 @@ bool TimeRangeFlag::operator<(const TimeRangeFlag& rhs) const return std::tie(static_cast(mInterval.getMin()), static_cast(mInterval.getMax()), mFlag, mComment, mSource) < std::tie(static_cast(rhs.mInterval.getMin()), static_cast(rhs.mInterval.getMax()), rhs.mFlag, rhs.mComment, rhs.mSource); } -bool TimeRangeFlag::operator>(const TimeRangeFlag& rhs) const +bool QualityControlFlag::operator>(const QualityControlFlag& rhs) const { // we don't use the comparison mechanism in Bracket, // because std::set which is used in TRFCollection assumes that a < b, a > b <=> a == b return std::tie(static_cast(mInterval.getMin()), static_cast(mInterval.getMax()), mFlag, mComment, mSource) > std::tie(static_cast(rhs.mInterval.getMin()), static_cast(rhs.mInterval.getMax()), rhs.mFlag, rhs.mComment, rhs.mSource); } -void TimeRangeFlag::streamTo(std::ostream& output) const +void QualityControlFlag::streamTo(std::ostream& output) const { - output << "TimeRangeFlag:\n"; + output << "QualityControlFlag:\n"; output << "- Start: " << mInterval.getMin() << "\n"; output << "- End: " << mInterval.getMax() << "\n"; output << "- " << mFlag << "\n"; @@ -55,7 +55,7 @@ void TimeRangeFlag::streamTo(std::ostream& output) const output << "- Source: " << mSource; } -std::ostream& operator<<(std::ostream& output, const TimeRangeFlag& data) +std::ostream& operator<<(std::ostream& output, const QualityControlFlag& data) { data.streamTo(output); return output; diff --git a/DataFormats/QualityControl/src/TimeRangeFlagCollection.cxx b/DataFormats/QualityControl/src/QualityControlFlagCollection.cxx similarity index 65% rename from DataFormats/QualityControl/src/TimeRangeFlagCollection.cxx rename to DataFormats/QualityControl/src/QualityControlFlagCollection.cxx index ee3adc8dc7f2f..042ef2f218d09 100644 --- a/DataFormats/QualityControl/src/TimeRangeFlagCollection.cxx +++ b/DataFormats/QualityControl/src/QualityControlFlagCollection.cxx @@ -10,8 +10,8 @@ // or submit itself to any jurisdiction. // O2 include -#include "DataFormatsQualityControl/TimeRangeFlagCollection.h" -#include "DataFormatsQualityControl/FlagReasonFactory.h" +#include "DataFormatsQualityControl/QualityControlFlagCollection.h" +#include "DataFormatsQualityControl/FlagTypeFactory.h" #include "Framework/Logger.h" #include @@ -25,56 +25,56 @@ namespace o2::quality_control constexpr const char* csvHeader = "start,end,flag_id,flag_name,flag_bad,comment,source"; constexpr size_t csvColumns = 7; -TimeRangeFlagCollection::TimeRangeFlagCollection(std::string name, std::string detector, RangeInterval validityRange, - int runNumber, std::string periodName, std::string passName, - std::string provenance) +QualityControlFlagCollection::QualityControlFlagCollection(std::string name, std::string detector, RangeInterval validityRange, + int runNumber, std::string periodName, std::string passName, + std::string provenance) : mName(std::move(name)), mDetID(std::move(detector)), mValidityRange(validityRange), mRunNumber(runNumber), mPeriodName(std::move(periodName)), mPassName(passName), mProvenance(std::move(provenance)) { } -void TimeRangeFlagCollection::insert(TimeRangeFlag&& trf) +void QualityControlFlagCollection::insert(QualityControlFlag&& trf) { - mTimeRangeFlags.insert(std::move(trf)); + mQualityControlFlags.insert(std::move(trf)); } -void TimeRangeFlagCollection::insert(const TimeRangeFlag& trf) +void QualityControlFlagCollection::insert(const QualityControlFlag& trf) { - mTimeRangeFlags.insert(trf); + mQualityControlFlags.insert(trf); } -size_t TimeRangeFlagCollection::size() const +size_t QualityControlFlagCollection::size() const { - return mTimeRangeFlags.size(); + return mQualityControlFlags.size(); } -void TimeRangeFlagCollection::merge(TimeRangeFlagCollection& other) +void QualityControlFlagCollection::merge(QualityControlFlagCollection& other) { if (mDetID != other.mDetID) { - // We assume that one TimeRangeFlagCollection should correspond to one detector at most. + // We assume that one QualityControlFlagCollection should correspond to one detector at most. // However, if this becomes annoying, we can reconsider it. throw std::runtime_error( "The detector ID of the target collection '" + mDetID + "' is different than the other '" + mDetID); } - mTimeRangeFlags.merge(other.mTimeRangeFlags); + mQualityControlFlags.merge(other.mQualityControlFlags); } -void TimeRangeFlagCollection::merge(const TimeRangeFlagCollection& other) +void QualityControlFlagCollection::merge(const QualityControlFlagCollection& other) { - TimeRangeFlagCollection otherCopy{other}; + QualityControlFlagCollection otherCopy{other}; merge(otherCopy); } -TimeRangeFlagCollection::collection_t::const_iterator TimeRangeFlagCollection::begin() const +QualityControlFlagCollection::collection_t::const_iterator QualityControlFlagCollection::begin() const { - return mTimeRangeFlags.begin(); + return mQualityControlFlags.begin(); } -TimeRangeFlagCollection::collection_t::const_iterator TimeRangeFlagCollection::end() const +QualityControlFlagCollection::collection_t::const_iterator QualityControlFlagCollection::end() const { - return mTimeRangeFlags.end(); + return mQualityControlFlags.end(); } -void TimeRangeFlagCollection::streamTo(std::ostream& output) const +void QualityControlFlagCollection::streamTo(std::ostream& output) const { auto escapeComma = [](const std::string& str) { return boost::algorithm::replace_all_copy(str, ",", "\\,"); @@ -88,7 +88,7 @@ void TimeRangeFlagCollection::streamTo(std::ostream& output) const } } -void TimeRangeFlagCollection::streamFrom(std::istream& input) +void QualityControlFlagCollection::streamFrom(std::istream& input) { std::string line; std::getline(input, line); @@ -100,9 +100,9 @@ void TimeRangeFlagCollection::streamFrom(std::istream& input) while (std::getline(input, line)) { boost::tokenizer> tok(line); - TimeRangeFlag::time_type start = 0; - TimeRangeFlag::time_type end = 0; - FlagReason flag = FlagReasonFactory::Invalid(); + QualityControlFlag::time_type start = 0; + QualityControlFlag::time_type end = 0; + FlagType flag = FlagTypeFactory::Invalid(); std::string comment; std::string source; auto it = tok.begin(); @@ -115,7 +115,7 @@ void TimeRangeFlagCollection::streamFrom(std::istream& input) LOG(error) << "Invalid line, empty start time of a flag, skipping..."; valid = false; } else { - start = static_cast(std::stoull(*it)); + start = static_cast(std::stoull(*it)); } break; } @@ -124,7 +124,7 @@ void TimeRangeFlagCollection::streamFrom(std::istream& input) LOG(error) << "Invalid line, empty end time of a flag, skipping..."; valid = false; } else { - end = static_cast(std::stoull(*it)); + end = static_cast(std::stoull(*it)); } break; } @@ -179,37 +179,37 @@ void TimeRangeFlagCollection::streamFrom(std::istream& input) } } -std::ostream& operator<<(std::ostream& output, const TimeRangeFlagCollection& data) +std::ostream& operator<<(std::ostream& output, const QualityControlFlagCollection& data) { data.streamTo(output); return output; } -const std::string& TimeRangeFlagCollection::getName() const +const std::string& QualityControlFlagCollection::getName() const { return mName; } -const std::string& TimeRangeFlagCollection::getDetector() const +const std::string& QualityControlFlagCollection::getDetector() const { return mDetID; } -int TimeRangeFlagCollection::getRunNumber() const +int QualityControlFlagCollection::getRunNumber() const { return mRunNumber; } -const std::string& TimeRangeFlagCollection::getPeriodName() const +const std::string& QualityControlFlagCollection::getPeriodName() const { return mPeriodName; } -const std::string& TimeRangeFlagCollection::getPassName() const +const std::string& QualityControlFlagCollection::getPassName() const { return mPassName; } -const std::string& TimeRangeFlagCollection::getProvenance() const +const std::string& QualityControlFlagCollection::getProvenance() const { return mProvenance; } diff --git a/DataFormats/QualityControl/test/testFlagReasons.cxx b/DataFormats/QualityControl/test/testFlagTypes.cxx similarity index 62% rename from DataFormats/QualityControl/test/testFlagReasons.cxx rename to DataFormats/QualityControl/test/testFlagTypes.cxx index ebcd409ed3d46..e1587825a323a 100644 --- a/DataFormats/QualityControl/test/testFlagReasons.cxx +++ b/DataFormats/QualityControl/test/testFlagTypes.cxx @@ -29,28 +29,28 @@ BOOST_AUTO_TEST_CASE(FlagTypes) static_assert(std::is_constructible::value == false, "FlagType should not be constructible outside of its static methods and the factory."); - FlagType rDefault; - BOOST_CHECK_EQUAL(rDefault, FlagTypeFactory::Invalid()); - - auto r1 = FlagTypeFactory::Unknown(); - BOOST_CHECK_EQUAL(r1.getID(), 1); - BOOST_CHECK_EQUAL(r1.getName(), "Unknown"); - BOOST_CHECK_EQUAL(r1.getBad(), true); - - std::cout << r1 << std::endl; - - auto r2 = r1; - BOOST_CHECK_EQUAL(r2.getID(), 1); - BOOST_CHECK_EQUAL(r1.getName(), r2.getName()); - BOOST_CHECK_EQUAL(r2.getName(), "Unknown"); - BOOST_CHECK_EQUAL(r2.getBad(), true); - - BOOST_CHECK_EQUAL(r1, r2); - BOOST_CHECK((r1 != r2) == false); - BOOST_CHECK(!(r1 < r2)); - BOOST_CHECK(!(r1 > r2)); - - auto r3 = FlagTypeFactory::LimitedAcceptance(); - BOOST_CHECK(r3 > r1); - BOOST_CHECK(!(r3 < r1)); + FlagType fDefault; + BOOST_CHECK_EQUAL(fDefault, FlagTypeFactory::Invalid()); + + auto f1 = FlagTypeFactory::Unknown(); + BOOST_CHECK_EQUAL(f1.getID(), 1); + BOOST_CHECK_EQUAL(f1.getName(), "Unknown"); + BOOST_CHECK_EQUAL(f1.getBad(), true); + + std::cout << f1 << std::endl; + + auto f2 = f1; + BOOST_CHECK_EQUAL(f2.getID(), 1); + BOOST_CHECK_EQUAL(f1.getName(), f2.getName()); + BOOST_CHECK_EQUAL(f2.getName(), "Unknown"); + BOOST_CHECK_EQUAL(f2.getBad(), true); + + BOOST_CHECK_EQUAL(f1, f2); + BOOST_CHECK((f1 != f2) == false); + BOOST_CHECK(!(f1 < f2)); + BOOST_CHECK(!(f1 > f2)); + + auto f3 = FlagTypeFactory::LimitedAcceptance(); + BOOST_CHECK(f3 > f1); + BOOST_CHECK(!(f3 < f1)); } diff --git a/DataFormats/QualityControl/test/testTimeRangeFlag.cxx b/DataFormats/QualityControl/test/testQualityControlFlag.cxx similarity index 58% rename from DataFormats/QualityControl/test/testTimeRangeFlag.cxx rename to DataFormats/QualityControl/test/testQualityControlFlag.cxx index 0b912db2c1f42..2990b3bbd355f 100644 --- a/DataFormats/QualityControl/test/testTimeRangeFlag.cxx +++ b/DataFormats/QualityControl/test/testQualityControlFlag.cxx @@ -23,18 +23,18 @@ using namespace o2::quality_control; BOOST_AUTO_TEST_CASE(test_QualityControlFlag) { - QualityControlFlag trf1{12, 34, FlagReasonFactory::BadTracking(), "comment", "source"}; + QualityControlFlag qcFlag1{12, 34, FlagTypeFactory::BadTracking(), "comment", "source"}; - BOOST_CHECK_EQUAL(trf1.getStart(), 12); - BOOST_CHECK_EQUAL(trf1.getEnd(), 34); - BOOST_CHECK_EQUAL(trf1.getFlag(), FlagReasonFactory::BadTracking()); - BOOST_CHECK_EQUAL(trf1.getComment(), "comment"); - BOOST_CHECK_EQUAL(trf1.getSource(), "source"); + BOOST_CHECK_EQUAL(qcFlag1.getStart(), 12); + BOOST_CHECK_EQUAL(qcFlag1.getEnd(), 34); + BOOST_CHECK_EQUAL(qcFlag1.getFlag(), FlagTypeFactory::BadTracking()); + BOOST_CHECK_EQUAL(qcFlag1.getComment(), "comment"); + BOOST_CHECK_EQUAL(qcFlag1.getSource(), "source"); - BOOST_CHECK_THROW((QualityControlFlag{12, 0, FlagReasonFactory::BadTracking()}), std::runtime_error); + BOOST_CHECK_THROW((QualityControlFlag{12, 0, FlagTypeFactory::BadTracking()}), std::runtime_error); - QualityControlFlag trf2{10, 34, FlagReasonFactory::BadTracking(), "comment", "source"}; + QualityControlFlag qcFlag2{10, 34, FlagTypeFactory::BadTracking(), "comment", "source"}; - BOOST_CHECK(trf1 > trf2); - BOOST_CHECK(!(trf1 < trf2)); + BOOST_CHECK(qcFlag1 > qcFlag2); + BOOST_CHECK(!(qcFlag1 < qcFlag2)); } \ No newline at end of file diff --git a/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx b/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx new file mode 100644 index 0000000000000..e069776e84907 --- /dev/null +++ b/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx @@ -0,0 +1,136 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#define BOOST_TEST_MODULE Test quality_control QualityControlFlagCollection class +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK + +// boost includes +#include +// STL +#include +// o2 includes +#include "DataFormatsQualityControl/QualityControlFlagCollection.h" +#include "DataFormatsQualityControl/QualityControlFlag.h" +#include "DataFormatsQualityControl/FlagTypeFactory.h" + +using namespace o2::quality_control; + +BOOST_AUTO_TEST_CASE(test_QualityControlFlagCollection_Methods) +{ + QualityControlFlag flag1{12, 34, FlagTypeFactory::BadTracking(), "comment", "source"}; + QualityControlFlag flag2{10, 34, FlagTypeFactory::BadTracking(), "comment", "source"}; + + QualityControlFlagCollection qcfc1{"Raw data checks", "TOF", {10, 20000}, 12345, "LHC22k5", "passMC", "qc_mc"}; + qcfc1.insert(flag1); // by copy + qcfc1.insert(flag2); + qcfc1.insert({50, 77, FlagTypeFactory::Invalid()}); // by move + BOOST_CHECK_EQUAL(qcfc1.size(), 3); + BOOST_CHECK_EQUAL(qcfc1.getName(), "Raw data checks"); + BOOST_CHECK_EQUAL(qcfc1.getDetector(), "TOF"); + BOOST_CHECK_EQUAL(qcfc1.getStart(), 10); + BOOST_CHECK_EQUAL(qcfc1.getEnd(), 20000); + BOOST_CHECK_EQUAL(qcfc1.getRunNumber(), 12345); + BOOST_CHECK_EQUAL(qcfc1.getPeriodName(), "LHC22k5"); + BOOST_CHECK_EQUAL(qcfc1.getPassName(), "passMC"); + BOOST_CHECK_EQUAL(qcfc1.getProvenance(), "qc_mc"); + + QualityControlFlagCollection qcfc2{"Reco checks", "TOF"}; + qcfc2.insert({50, 77, FlagTypeFactory::Invalid()}); // this is a duplicate to an entry in qcfc1 + qcfc2.insert({51, 77, FlagTypeFactory::Invalid()}); + qcfc2.insert({1234, 3434, FlagTypeFactory::LimitedAcceptance()}); + qcfc2.insert({50, 77, FlagTypeFactory::LimitedAcceptance()}); + BOOST_CHECK_EQUAL(qcfc2.size(), 4); + + // Try merging. Duplicate entries should be left in the 'other' objects. + // Notice that we merge the two partial TRFCs into the third, which covers all cases + QualityControlFlagCollection qcfc3{"ALL", "TOF"}; + qcfc3.merge(qcfc1); + qcfc3.merge(qcfc2); + BOOST_CHECK_EQUAL(qcfc1.size(), 0); + BOOST_CHECK_EQUAL(qcfc2.size(), 1); + BOOST_CHECK_EQUAL(qcfc3.size(), 6); + + // Try const merging. It should copy the elements and keep the 'other' intact. + QualityControlFlagCollection qcfc4{"ALL", "TOF"}; + const auto& constTrfc3 = qcfc3; + qcfc4.merge(constTrfc3); + BOOST_CHECK_EQUAL(qcfc3.size(), 6); + BOOST_CHECK_EQUAL(qcfc4.size(), 6); + + // Try merging different detectors - it should throw. + QualityControlFlagCollection qcfc5{"ALL", "TPC"}; + BOOST_CHECK_THROW(qcfc5.merge(qcfc3), std::runtime_error); + BOOST_CHECK_THROW(qcfc5.merge(constTrfc3), std::runtime_error); + + // try printing + std::cout << qcfc3 << std::endl; + + // iterating + for (const auto& flag : qcfc3) { + (void)flag; + } +} + +BOOST_AUTO_TEST_CASE(test_QualityControlFlagCollection_IO) +{ + { + QualityControlFlagCollection qcfc1{"xyz", "TST"}; + + std::stringstream store; + qcfc1.streamTo(store); + + QualityControlFlagCollection qcfc2{"xyz", "TST"}; + qcfc2.streamFrom(store); + + BOOST_CHECK_EQUAL(qcfc2.size(), 0); + } + { + QualityControlFlagCollection qcfc1{"xyz", "TST"}; + qcfc1.insert({50, 77, FlagTypeFactory::Invalid(), "a comment", "a source"}); + qcfc1.insert({51, 77, FlagTypeFactory::Invalid()}); + qcfc1.insert({1234, 3434, FlagTypeFactory::LimitedAcceptance()}); + qcfc1.insert({50, 77, FlagTypeFactory::LimitedAcceptance()}); + qcfc1.insert({43434, 63421, FlagTypeFactory::NotBadFlagExample()}); + + std::stringstream store; + qcfc1.streamTo(store); + + QualityControlFlagCollection qcfc2{"xyz", "TST"}; + qcfc2.streamFrom(store); + + BOOST_REQUIRE_EQUAL(qcfc1.size(), qcfc2.size()); + for (auto it1 = qcfc1.begin(), it2 = qcfc2.begin(); it1 != qcfc1.end() && it2 != qcfc2.end(); ++it1, ++it2) { + BOOST_CHECK_EQUAL(*it1, *it2); + } + } + { + std::stringstream store; + store << "start,end,flag_id,invalid,header,format\n"; + store << R"(123,345,11,"fdsa",1,"comment","source")"; + QualityControlFlagCollection qcfc1{"A", "TST"}; + BOOST_CHECK_THROW(qcfc1.streamFrom(store), std::runtime_error); + } + { + std::stringstream store; + store << "start,end,flag_id,flag_name,flag_bad,comment,source\n"; + store << R"(123,345,11,"fdsa",1,"comment","source","toomanycolumns")" << '\n'; + store << R"(123,345,11,"fdsa",1)" << '\n'; + store << R"(123,,11,"fdsa",1,"comment","source")" << '\n'; + store << R"(,345,11,"fdsa",1,"comment","source")" << '\n'; + store << R"(123,345,,"fdsa",1,"comment","source")" << '\n'; + store << R"(123,345,11,"",1,"comment","source")" << '\n'; + store << R"(123,345,11,"fdsa",,"comment","source")" << '\n'; + QualityControlFlagCollection qcfc1{"A", "TST"}; + BOOST_CHECK_NO_THROW(qcfc1.streamFrom(store)); + BOOST_CHECK_EQUAL(qcfc1.size(), 0); + } +} diff --git a/DataFormats/QualityControl/test/testTimeRangeFlagCollection.cxx b/DataFormats/QualityControl/test/testTimeRangeFlagCollection.cxx deleted file mode 100644 index bf8ce2cab0fbd..0000000000000 --- a/DataFormats/QualityControl/test/testTimeRangeFlagCollection.cxx +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -#define BOOST_TEST_MODULE Test quality_control QualityControlFlagCollection class -#define BOOST_TEST_MAIN -#define BOOST_TEST_DYN_LINK - -// boost includes -#include -// STL -#include -// o2 includes -#include "DataFormatsQualityControl/QualityControlFlagCollection.h" -#include "DataFormatsQualityControl/QualityControlFlag.h" -#include "DataFormatsQualityControl/FlagTypeFactory.h" - -using namespace o2::quality_control; - -BOOST_AUTO_TEST_CASE(test_QualityControlFlagCollection_Methods) -{ - QualityControlFlag trf1{12, 34, FlagTypeFactory::BadTracking(), "comment", "source"}; - QualityControlFlag trf2{10, 34, FlagTypeFactory::BadTracking(), "comment", "source"}; - - QualityControlFlagCollection trfc1{"Raw data checks", "TOF", {10, 20000}, 12345, "LHC22k5", "passMC", "qc_mc"}; - trfc1.insert(trf1); // by copy - trfc1.insert(trf2); - trfc1.insert({50, 77, FlagTypeFactory::Invalid()}); // by move - BOOST_CHECK_EQUAL(trfc1.size(), 3); - BOOST_CHECK_EQUAL(trfc1.getName(), "Raw data checks"); - BOOST_CHECK_EQUAL(trfc1.getDetector(), "TOF"); - BOOST_CHECK_EQUAL(trfc1.getStart(), 10); - BOOST_CHECK_EQUAL(trfc1.getEnd(), 20000); - BOOST_CHECK_EQUAL(trfc1.getRunNumber(), 12345); - BOOST_CHECK_EQUAL(trfc1.getPeriodName(), "LHC22k5"); - BOOST_CHECK_EQUAL(trfc1.getPassName(), "passMC"); - BOOST_CHECK_EQUAL(trfc1.getProvenance(), "qc_mc"); - - QualityControlFlagCollection trfc2{"Reco checks", "TOF"}; - trfc2.insert({50, 77, FlagTypeFactory::Invalid()}); // this is a duplicate to an entry in trfc1 - trfc2.insert({51, 77, FlagTypeFactory::Invalid()}); - trfc2.insert({1234, 3434, FlagTypeFactory::LimitedAcceptance()}); - trfc2.insert({50, 77, FlagTypeFactory::LimitedAcceptance()}); - BOOST_CHECK_EQUAL(trfc2.size(), 4); - - // Try merging. Duplicate entries should be left in the 'other' objects. - // Notice that we merge the two partial TRFCs into the third, which covers all cases - QualityControlFlagCollection trfc3{"ALL", "TOF"}; - trfc3.merge(trfc1); - trfc3.merge(trfc2); - BOOST_CHECK_EQUAL(trfc1.size(), 0); - BOOST_CHECK_EQUAL(trfc2.size(), 1); - BOOST_CHECK_EQUAL(trfc3.size(), 6); - - // Try const merging. It should copy the elements and keep the 'other' intact. - QualityControlFlagCollection trfc4{"ALL", "TOF"}; - const auto& constTrfc3 = trfc3; - trfc4.merge(constTrfc3); - BOOST_CHECK_EQUAL(trfc3.size(), 6); - BOOST_CHECK_EQUAL(trfc4.size(), 6); - - // Try merging different detectors - it should throw. - QualityControlFlagCollection trfc5{"ALL", "TPC"}; - BOOST_CHECK_THROW(trfc5.merge(trfc3), std::runtime_error); - BOOST_CHECK_THROW(trfc5.merge(constTrfc3), std::runtime_error); - - // try printing - std::cout << trfc3 << std::endl; - - // iterating - for (const auto& trf : trfc3) { - (void)trf; - } -} - -BOOST_AUTO_TEST_CASE(test_QualityControlFlagCollection_IO) -{ - { - QualityControlFlagCollection trfc1{"xyz", "TST"}; - - std::stringstream store; - trfc1.streamTo(store); - - QualityControlFlagCollection trfc2{"xyz", "TST"}; - trfc2.streamFrom(store); - - BOOST_CHECK_EQUAL(trfc2.size(), 0); - } - { - QualityControlFlagCollection trfc1{"xyz", "TST"}; - trfc1.insert({50, 77, FlagTypeFactory::Invalid(), "a comment", "a source"}); - trfc1.insert({51, 77, FlagTypeFactory::Invalid()}); - trfc1.insert({1234, 3434, FlagTypeFactory::LimitedAcceptance()}); - trfc1.insert({50, 77, FlagTypeFactory::LimitedAcceptance()}); - trfc1.insert({43434, 63421, FlagTypeFactory::NotBadFlagExample()}); - - std::stringstream store; - trfc1.streamTo(store); - - QualityControlFlagCollection trfc2{"xyz", "TST"}; - trfc2.streamFrom(store); - - BOOST_REQUIRE_EQUAL(trfc1.size(), trfc2.size()); - for (auto it1 = trfc1.begin(), it2 = trfc2.begin(); it1 != trfc1.end() && it2 != trfc2.end(); ++it1, ++it2) { - BOOST_CHECK_EQUAL(*it1, *it2); - } - } - { - std::stringstream store; - store << "start,end,flag_id,invalid,header,format\n"; - store << R"(123,345,11,"fdsa",1,"comment","source")"; - QualityControlFlagCollection trfc1{"A", "TST"}; - BOOST_CHECK_THROW(trfc1.streamFrom(store), std::runtime_error); - } - { - std::stringstream store; - store << "start,end,flag_id,flag_name,flag_bad,comment,source\n"; - store << R"(123,345,11,"fdsa",1,"comment","source","toomanycolumns")" << '\n'; - store << R"(123,345,11,"fdsa",1)" << '\n'; - store << R"(123,,11,"fdsa",1,"comment","source")" << '\n'; - store << R"(,345,11,"fdsa",1,"comment","source")" << '\n'; - store << R"(123,345,,"fdsa",1,"comment","source")" << '\n'; - store << R"(123,345,11,"",1,"comment","source")" << '\n'; - store << R"(123,345,11,"fdsa",,"comment","source")" << '\n'; - QualityControlFlagCollection trfc1{"A", "TST"}; - BOOST_CHECK_NO_THROW(trfc1.streamFrom(store)); - BOOST_CHECK_EQUAL(trfc1.size(), 0); - } -} From b2f18e7ecc4428f55fbcf35ead3738358cb8efef Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 26 Apr 2024 15:10:13 +0200 Subject: [PATCH 0179/2997] Restore discarded VDrift calib. creation time after imposing winner params on it --- Detectors/TPC/calibration/src/VDriftHelper.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/TPC/calibration/src/VDriftHelper.cxx b/Detectors/TPC/calibration/src/VDriftHelper.cxx index eb36ee4351168..fb262acc1afa1 100644 --- a/Detectors/TPC/calibration/src/VDriftHelper.cxx +++ b/Detectors/TPC/calibration/src/VDriftHelper.cxx @@ -153,6 +153,7 @@ void VDriftHelper::extractCCDBInputs(ProcessingContext& pc, bool laser, bool its mSource = mVDTPCITSTgl.creationTime < mVDLaser.creationTime ? Source::Laser : Source::ITSTPCTgl; auto loseCTime = loserVD.creationTime; loserVD = mVD; // override alternative VD to avoid normalization problems later + loserVD.creationTime = loseCTime; std::string rep = fmt::format("Prefer TPC Drift from {} with time {} to {} with time {}", SourceNames[int(mSource)], mVD.creationTime, mSource == Source::Laser ? SourceNames[int(Source::ITSTPCTgl)] : SourceNames[int(Source::Laser)], mSource == Source::Laser ? mVDTPCITSTgl.creationTime : mVDLaser.creationTime); From 34ee2e10bfd2394e7fdb85069b6c199361b41e61 Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 28 Apr 2024 01:09:30 +0200 Subject: [PATCH 0180/2997] Do not propagate to refX in TPC refitter when not not needed --- Detectors/GlobalTracking/src/MatchCosmics.cxx | 1 + Detectors/GlobalTracking/src/MatchTOF.cxx | 2 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 1 + Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx | 2 +- Detectors/TPC/workflow/src/TPCRefitter.cxx | 1 + Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx | 1 + Detectors/Vertexing/src/SVertexer.cxx | 1 + 7 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchCosmics.cxx b/Detectors/GlobalTracking/src/MatchCosmics.cxx index 3c20ecad2f36c..90964fb1c05fa 100644 --- a/Detectors/GlobalTracking/src/MatchCosmics.cxx +++ b/Detectors/GlobalTracking/src/MatchCosmics.cxx @@ -96,6 +96,7 @@ void MatchCosmics::refitWinners(const o2::globaltracking::RecoContainer& data) mTPCCorrMapsHelper, mBz, tpcClusRefs.data(), 0, tpcClusShMap.data(), tpcClusOccMap.data(), tpcClusOccMap.size(), nullptr, o2::base::Propagator::Instance()); + tpcRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500 } const auto& itsClusters = prepareITSClusters(data); diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 099eb12d1f28f..53e71083e3851 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -1805,7 +1805,7 @@ bool MatchTOF::makeConstrainedTPCTrack(int matchedID, o2::dataformats::TrackTPCT if (mTPCClusterIdxStruct) { // refit was requested float chi2 = 0; mTPCRefitter->setTrackReferenceX(o2::constants::geom::XTPCInnerRef); - if (mTPCRefitter->RefitTrackAsTrackParCov(trConstr, tpcTrOrig.getClusterRef(), timeTOFTB, &chi2, false, true) < 0) { // outward refit after resetting cov.mat. + if (mTPCRefitter->RefitTrackAsTrackParCov(trConstr, tpcTrOrig.getClusterRef(), timeTOFTB, &chi2, false, true) < 0) { // inward refit after resetting cov.mat. LOGP(debug, "Inward Refit failed {}", trConstr.asString()); return false; } diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 194de0cfbeaaf..6007a470a8d76 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -577,6 +577,7 @@ bool MatchTPCITS::prepareTPCData() } */ mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500 mNTPCOccBinLength = mTPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins; mTBinClOcc.clear(); if (mNTPCOccBinLength > 1 && mTPCRefitterOccMap.size()) { diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx index 8ab2696b7e168..0e1dc7baaa69c 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx @@ -186,7 +186,7 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) } mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); - + mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500 float vdriftTB = mTPCVDriftHelper.getVDriftObject().getVDrift() * o2::tpc::ParameterElectronics::Instance().ZbinWidth; // VDrift expressed in cm/TimeBin float tpcTBBias = mTPCVDriftHelper.getVDriftObject().getTimeOffset() / (8 * o2::constants::lhc::LHCBunchSpacingMUS); std::vector clSector, clRow; diff --git a/Detectors/TPC/workflow/src/TPCRefitter.cxx b/Detectors/TPC/workflow/src/TPCRefitter.cxx index 6a41f487f40b3..cdc4234e6a2cc 100644 --- a/Detectors/TPC/workflow/src/TPCRefitter.cxx +++ b/Detectors/TPC/workflow/src/TPCRefitter.cxx @@ -192,6 +192,7 @@ void TPCRefitterSpec::process(o2::globaltracking::RecoContainer& recoData) } mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, prop->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, prop); + mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500 float vdriftTB = mTPCVDriftHelper.getVDriftObject().getVDrift() * o2::tpc::ParameterElectronics::Instance().ZbinWidth; // VDrift expressed in cm/TimeBin float tpcTBBias = mTPCVDriftHelper.getVDriftObject().getTimeOffset() / (8 * o2::constants::lhc::LHCBunchSpacingMUS); diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index 2f365ebe4935a..bceb0f07363aa 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -276,6 +276,7 @@ void TRDGlobalTracking::run(ProcessingContext& pc) mTPCClusterIdxStruct = &inputTracks.inputsTPCclusters->clusterIndex; mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(), inputTracks.getTPCTracksClusterRefs().data(), 0, inputTracks.clusterShMapTPC.data(), inputTracks.occupancyMapTPC.data(), inputTracks.occupancyMapTPC.size(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500 auto tmpInputContainer = getRecoInputContainer(pc, &mChainTracking->mIOPtrs, &inputTracks, mUseMC); auto tmpContainer = GPUWorkflowHelper::fillIOPtr(mChainTracking->mIOPtrs, inputTracks, mUseMC, nullptr, GTrackID::getSourcesMask("TRD"), mTrkMask, GTrackID::mask_t{GTrackID::MASK_NONE}); mTrackletsRaw = inputTracks.getTRDTracklets(); diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx index 252d14c16c7a5..0516bc2bcc182 100644 --- a/Detectors/Vertexing/src/SVertexer.cxx +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -450,6 +450,7 @@ void SVertexer::buildT2V(const o2::globaltracking::RecoContainer& recoData) // a mTPCRefitterShMap = recoData.clusterShMapTPC; mTPCRefitterOccMap = mRecoCont->occupancyMapTPC; mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, o2::base::Propagator::Instance()->getNominalBz(), mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500 } std::unordered_map> tmap; From cbcb288fe5657534c326fa6d606a17bad33865b8 Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 28 Apr 2024 20:36:38 +0200 Subject: [PATCH 0181/2997] Open TreeStream file with recreate, write with kOverwrite --- Common/Utils/include/CommonUtils/TreeStreamRedirector.h | 2 +- Common/Utils/src/TreeStreamRedirector.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/Utils/include/CommonUtils/TreeStreamRedirector.h b/Common/Utils/include/CommonUtils/TreeStreamRedirector.h index 8199009df400d..80858fecea87b 100644 --- a/Common/Utils/include/CommonUtils/TreeStreamRedirector.h +++ b/Common/Utils/include/CommonUtils/TreeStreamRedirector.h @@ -41,7 +41,7 @@ namespace utils class TreeStreamRedirector { public: - TreeStreamRedirector(const char* fname = "", const char* option = "update"); + TreeStreamRedirector(const char* fname = "", const char* option = "recreate"); virtual ~TreeStreamRedirector(); void Close(); TFile* GetFile() { return mDirectory->GetFile(); } diff --git a/Common/Utils/src/TreeStreamRedirector.cxx b/Common/Utils/src/TreeStreamRedirector.cxx index 4c21fcd602543..06fb3d65678c4 100644 --- a/Common/Utils/src/TreeStreamRedirector.cxx +++ b/Common/Utils/src/TreeStreamRedirector.cxx @@ -117,7 +117,7 @@ void TreeStreamRedirector::Close() TDirectory* backup = gDirectory; mDirectory->cd(); for (auto& layout : mDataLayouts) { - layout->getTree().Write(layout->getName()); + layout->getTree().Write(layout->getName(), TObject::kOverwrite); } mDataLayouts.clear(); if (backup) { From f54e2ae98bd18de68e4b1d73a7cbf30f44b9af92 Mon Sep 17 00:00:00 2001 From: Diego Stocco Date: Mon, 29 Apr 2024 11:13:25 +0200 Subject: [PATCH 0182/2997] MID efficiency: ensure that the spanned vector exists for the full processing (#13077) --- .../MUON/Workflow/src/ChamberEfficiencySpec.cxx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Detectors/MUON/Workflow/src/ChamberEfficiencySpec.cxx b/Detectors/MUON/Workflow/src/ChamberEfficiencySpec.cxx index cee1c51e83ee4..8ca9823261f63 100644 --- a/Detectors/MUON/Workflow/src/ChamberEfficiencySpec.cxx +++ b/Detectors/MUON/Workflow/src/ChamberEfficiencySpec.cxx @@ -100,21 +100,22 @@ class EfficiencyTask auto midTracks = pc.inputs().get>("midtracks"); if (mSelectMatched) { auto matchTracks = pc.inputs().get>("matchtracks"); - std::vector selectedTracks; - selectedTracks.reserve(midTracks.size()); + mSelectedTracks.clear(); + mSelectedTracks.reserve(midTracks.size()); for (auto& matchTrack : matchTracks) { auto idx = matchTrack.getMIDRef().getIndex(); - selectedTracks.emplace_back(midTracks[idx]); + mSelectedTracks.emplace_back(midTracks[idx]); } - midTracks = gsl::span(selectedTracks); + midTracks = gsl::span(mSelectedTracks); } mEfficiency.process(midTracks); } private: - Efficiency mEfficiency{}; /// Efficiency calculator - bool mSelectMatched; /// Select matched tracks + Efficiency mEfficiency{}; /// Efficiency calculator + bool mSelectMatched; /// Select matched tracks + std::vector mSelectedTracks{}; // Vector with matched tracks }; DataProcessorSpec getChamberEfficiencySpec(bool selectMatched) From 8062b96a4692ae14415b8f448974c88acc13a93e Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 26 Apr 2024 01:34:53 +0200 Subject: [PATCH 0183/2997] Fix multiplicity accumulator for debug output --- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index 6007a470a8d76..c1b2e4b224ccb 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -585,17 +585,18 @@ bool MatchTPCITS::prepareTPCData() int nTPCBins = mNHBPerTF * o2::constants::lhc::LHCMaxBunches / 8, ninteg = 0; int nTPCOccBins = nTPCBins * mNTPCOccBinLengthInv, sumBins = std::max(1, int(o2::constants::lhc::LHCMaxBunches / 8 * mNTPCOccBinLengthInv)); mTBinClOcc.resize(nTPCOccBins); - float sm = 0., tb = (nTPCOccBins - 0.5) * mNTPCOccBinLength, mltPrev = 0.; + std::vector mltHistTB(nTPCOccBins); + float sm = 0., tb = 0.5 * mNTPCOccBinLength; + for (int i = 0; i < nTPCOccBins; i++) { + mltHistTB[i] = mTPCRefitter->getParam()->GetUnscaledMult(tb); + tb += mNTPCOccBinLength; + } for (int i = nTPCOccBins; i--;) { - float mlt = mTPCRefitter->getParam()->GetUnscaledMult(tb); - sm += mlt; - mTBinClOcc[i] = sm; - if (ninteg++ > mNTPCOccBinLength) { - sm -= mltPrev; + sm += mltHistTB[i]; + if (i + sumBins < nTPCOccBins) { + sm -= mltHistTB[i + sumBins]; } - // LOGP(info, "BIN {} of {} -> {} with inst val {} (prev = {}) BL={} nInt={} tb={}", i, nTPCOccBins, sm, mlt, mltPrev, mNTPCOccBinLength, ninteg, tb); - mltPrev = mlt; - tb -= mNTPCOccBinLength; + mTBinClOcc[i] = sm; } } else { mTBinClOcc.resize(1); From 66e37734846465be3e0db1fd8337e47e0c267e36 Mon Sep 17 00:00:00 2001 From: mwinn2 <43405856+mwinn2@users.noreply.github.com> Date: Mon, 29 Apr 2024 13:16:51 +0200 Subject: [PATCH 0184/2997] Inclination angle effects in MCH digitizer (#13038) * first prototype for inclination and impact on resolution --- .../Simulation/include/MCHSimulation/Hit.h | 10 +++- .../include/MCHSimulation/Response.h | 30 +++++++----- .../MUON/MCH/Simulation/src/DEDigitizer.cxx | 26 +++++++++- .../MUON/MCH/Simulation/src/Response.cxx | 48 ++++++++++++++++--- Detectors/MUON/MCH/Simulation/src/Stepper.cxx | 5 +- Detectors/MUON/MCH/Simulation/src/Stepper.h | 1 + .../MCH/Simulation/test/testDigitizer.cxx | 25 ++++++++-- .../src/MCHDigitizerSpec.cxx | 2 +- 8 files changed, 120 insertions(+), 27 deletions(-) diff --git a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Hit.h b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Hit.h index d216654a36add..6382b60b48e8a 100644 --- a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Hit.h +++ b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Hit.h @@ -25,19 +25,25 @@ class Hit : public ::o2::BasicXYZEHit public: Hit(int trackId = 0, short detElemId = 0, math_utils::Point3D entrancePoint = {}, const math_utils::Point3D exitPoint = {}, - float eloss = 0.0, float length = 0.0, float tof = 0.0) - : ::o2::BasicXYZEHit(entrancePoint.x(), entrancePoint.y(), entrancePoint.z(), tof, eloss, trackId, detElemId), mLength{length}, mExitPoint(exitPoint) + float eloss = 0.0, float length = 0.0, float entranceTof = 0.0, float eTot = 0.0) + : ::o2::BasicXYZEHit(entrancePoint.x(), entrancePoint.y(), entrancePoint.z(), entranceTof, eloss, trackId, detElemId), mLength{length}, mExitPoint(exitPoint), mEtot{eTot} { } math_utils::Point3D entrancePoint() const { return GetPos(); } math_utils::Point3D exitPoint() const { return mExitPoint; } + // time in s + float entranceTof() const { return GetTime(); } + // particle energy in GeV + float eTot() const { return mEtot; } + short detElemId() const { return GetDetectorID(); } private: float mLength = {}; math_utils::Point3D mExitPoint = {}; + float mEtot = {}; ClassDefNV(Hit, 1); }; diff --git a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Response.h b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Response.h index c9c46a846f2ea..09faf3af2e279 100644 --- a/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Response.h +++ b/Detectors/MUON/MCH/Simulation/include/MCHSimulation/Response.h @@ -32,11 +32,12 @@ class Response public: Response(Station station); ~Response() = default; - float getChargeSpread() const { return mChargeSpread; } float getPitch() const { return mPitch; } float getSigmaIntegration() const { return mSigmaIntegration; } bool isAboveThreshold(float charge) const { return charge > mChargeThreshold; } + bool isAngleEffect() const { return mAngleEffect; } + bool isMagnetEffect() const { return mMagnetEffect; } /** Converts energy deposition into a charge. * @@ -65,6 +66,20 @@ class Response /// compute the number of samples corresponding to the charge in ADC units uint32_t nSamples(float charge) const; + /// compute deteriation of y-resolution due to track inclination and B-field + float inclandbfield(float thetawire, float betagamma, float bx) const; + + private: + MathiesonOriginal mMathieson{}; ///< Mathieson function + float mPitch = 0.f; ///< anode-cathode pitch (cm) + float mChargeSlope = 0.f; ///< charge slope used in E to charge conversion + float mChargeSpread = 0.f; ///< width of the charge distribution (cm) + float mSigmaIntegration = 0.f; ///< number of sigmas used for charge distribution + float mChargeCorr = 0.f; ///< amplitude of charge correlation between cathodes + float mChargeThreshold = 0.f; ///< minimum fraction of charge considered + bool mAngleEffect = true; ///< switch for angle effect influencing charge deposition + bool mMagnetEffect = true; ///< switch for magnetic field influencing charge deposition + /// Ratio of particle mean eloss with respect MIP's Khalil Boudjemline, sep 2003, PhD.Thesis and Particle Data Book float eLossRatio(float logbetagamma) const; /// ToDo: check Aliroot formula vs PDG, if really log_10 and not ln or bug in Aliroot @@ -74,22 +89,11 @@ class Response /// Angle effect: Normalisation form theta=10 degres to theta between 0 and 10 (Khalil BOUDJEMLINE sep 2003 Ph.D Thesis) /// Angle with respect to the wires assuming that chambers are perpendicular to the z axis. - float angleEffectNorma(float elossratio) const; + float angleEffectNorma(float angle) const; /// Magnetic field effect: Normalisation form theta=16 degres (eq. 10 degrees B=0) to theta between -20 and 20 (Lamia Benhabib jun 2006 ) /// Angle with respect to the wires assuming that chambers are perpendicular to the z axis. float magAngleEffectNorma(float angle, float bfield) const; - - private: - MathiesonOriginal mMathieson{}; ///< Mathieson function - float mPitch = 0.f; ///< anode-cathode pitch (cm) - float mChargeSlope = 0.f; ///< charge slope used in E to charge conversion - float mChargeSpread = 0.f; ///< width of the charge distribution (cm) - float mSigmaIntegration = 0.f; ///< number of sigmas used for charge distribution - float mChargeCorr = 0.f; ///< amplitude of charge correlation between cathodes - float mChargeThreshold = 0.f; ///< minimum fraction of charge considered - bool mAngleEffect = true; ///< switch for angle effect influencing charge deposition - bool mMagnetEffect = true; ///< switch for magnetic field influencing charge deposition }; } // namespace mch } // namespace o2 diff --git a/Detectors/MUON/MCH/Simulation/src/DEDigitizer.cxx b/Detectors/MUON/MCH/Simulation/src/DEDigitizer.cxx index 7cb6814226555..5078f464aabe5 100644 --- a/Detectors/MUON/MCH/Simulation/src/DEDigitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/src/DEDigitizer.cxx @@ -17,6 +17,8 @@ #include "DetectorsRaw/HBFUtils.h" #include "MCHSimulation/DigitizerParam.h" +#include +#include "Field/MagneticField.h" /// Convert collision time to ROF time (ROF duration = 4 BC) std::pair time2ROFtime(const o2::InteractionRecord& time) @@ -25,9 +27,11 @@ std::pair time2ROFtime(const o2::InteractionReco return std::make_pair(o2::InteractionRecord(time.bc - bc, time.orbit), bc); } +//_________________________________________________________________________________________________ + namespace o2::mch { - +//_________________________________________________________________________________________________ DEDigitizer::DEDigitizer(int deId, math_utils::Transform3D transformation, std::mt19937& random) : mDeId{deId}, mResponse{deId < 300 ? Station::Type1 : Station::Type2345}, @@ -78,6 +82,26 @@ void DEDigitizer::processHit(const Hit& hit, const InteractionRecord& collisionT auto localX = mResponse.getAnod(lpos.X()); auto localY = lpos.Y(); + // calculate angle between track and wire assuming wire perpendicular to z-axis + // take global coordinates to avoid issues with rotations of detection elements + // neglect rotation of chambers w.r.t. beam + auto thetawire = atan((exitPoint.Y() - entrancePoint.Y()) / (entrancePoint.Z() - exitPoint.Z())); + + // local b-field + double b[3] = {0., 0., 0.}; + double x[3] = {entrancePoint.X(), entrancePoint.Y(), entrancePoint.Z()}; + if (TGeoGlobalMagField::Instance()->GetField()) { + TGeoGlobalMagField::Instance()->Field(x, b); + } else { + LOG(fatal) << "no b field in MCH DEDigitizer"; + } + + // calculate track betagamma + // assume beta = 1 and mass of charged muon to calculate track betagamma from particle energy + auto betagamma = hit.eTot() / 0.1056583745; + auto yAngleEffect = mResponse.inclandbfield(thetawire, betagamma, b[0]); + localY += yAngleEffect; + // borders of charge integration area auto dxy = mResponse.getSigmaIntegration() * mResponse.getChargeSpread(); auto xMin = localX - dxy; diff --git a/Detectors/MUON/MCH/Simulation/src/Response.cxx b/Detectors/MUON/MCH/Simulation/src/Response.cxx index 5c990284eee71..9cc4956772edc 100644 --- a/Detectors/MUON/MCH/Simulation/src/Response.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Response.cxx @@ -47,7 +47,6 @@ Response::Response(Station station) mChargeCorr = ResponseParam::Instance().chargeCorrelation; mChargeThreshold = ResponseParam::Instance().chargeThreshold; } - //_____________________________________________________________________ float Response::etocharge(float edepos) const { @@ -90,12 +89,49 @@ uint32_t Response::nSamples(float charge) const return std::round(std::pow(charge / signalParam[1], 1. / signalParam[2]) + signalParam[0]); } //_____________________________________________________________________ +float Response::inclandbfield(float thetawire, float betagamma, float bx) const +{ + float yAngleEffect = 0; + // auxiliary variables for b-field and inclination angle effect + float eLossParticleElossMip = 0.0; + float sigmaEffect10degrees = 0.0; + float sigmaEffectThetadegrees = 0.0; + + if (isAngleEffect()) { + if (!isMagnetEffect()) { + thetawire = abs(thetawire); + if ((betagamma > 3.2) && (thetawire * TMath::RadToDeg() <= 15.)) { + betagamma = log(betagamma); // check if ln or log10 + eLossParticleElossMip = eLossRatio(betagamma); + sigmaEffect10degrees = angleEffect10(eLossParticleElossMip); + sigmaEffectThetadegrees = sigmaEffect10degrees / angleEffectNorma(thetawire * TMath::RadToDeg()); + if (o2::mch::Station() == o2::mch::Station::Type1) { + sigmaEffectThetadegrees /= 1.09833 + 0.017 * (thetawire * TMath::RadToDeg()); + } + yAngleEffect = 0.0001 * gRandom->Gaus(0, sigmaEffectThetadegrees); // error due to the angle effect in cm + } + } else { + if ((betagamma > 3.2) && (abs(thetawire * TMath::RadToDeg()) <= 15.)) { + betagamma = log(betagamma); + eLossParticleElossMip = eLossRatio(betagamma); + sigmaEffect10degrees = angleEffect10(eLossParticleElossMip); + sigmaEffectThetadegrees = sigmaEffect10degrees / magAngleEffectNorma(thetawire * TMath::RadToDeg(), bx / 10.); // check b-field unit in aliroot and O2 + if (o2::mch::Station() == o2::mch::Station::Type1) { + sigmaEffectThetadegrees /= 1.09833 + 0.017 * (thetawire * TMath::RadToDeg()); + } + yAngleEffect = 0.0001 * gRandom->Gaus(0, sigmaEffectThetadegrees); + } + } + } + return yAngleEffect; +} +//_____________________________________________________________________ float Response::eLossRatio(float logbetagamma) const { // Ratio of particle mean eloss with respect MIP's Khalil Boudjemline, sep 2003, PhD.Thesis and Particle Data Book /// copied from aliroot AliMUONv1.cxx float eLossRatioParam[5] = {1.02138, -9.54149e-02, +7.83433e-02, -9.98208e-03, +3.83279e-04}; - return eLossRatioParam[0] + eLossRatioParam[1] * logbetagamma + eLossRatioParam[2] * std::pow(logbetagamma, 2) + eLossRatioParam[3] * std::pow(logbetagamma, 3) + eLossRatioParam[4] * std::pow(logbetagamma, 4); + return eLossRatioParam[0] + eLossRatioParam[1] * logbetagamma + eLossRatioParam[2] * logbetagamma * logbetagamma + eLossRatioParam[3] * logbetagamma * logbetagamma * logbetagamma + eLossRatioParam[4] * logbetagamma * logbetagamma * logbetagamma * logbetagamma; } //_____________________________________________________________________ float Response::angleEffect10(float elossratio) const @@ -103,16 +139,16 @@ float Response::angleEffect10(float elossratio) const /// Angle effect in tracking chambers at theta =10 degres as a function of ElossRatio (Khalil BOUDJEMLINE sep 2003 Ph.D Thesis) (in micrometers) /// copied from aliroot AliMUONv1.cxx float angleEffectParam[3] = {1.90691e+02, -6.62258e+01, 1.28247e+01}; - return angleEffectParam[0] + angleEffectParam[1] * elossratio + angleEffectParam[2] * std::pow(elossratio, 2); + return angleEffectParam[0] + angleEffectParam[1] * elossratio + angleEffectParam[2] * elossratio * elossratio; } //_____________________________________________________________________ -float Response::angleEffectNorma(float elossratio) const +float Response::angleEffectNorma(float angle) const { /// Angle effect: Normalisation form theta=10 degres to theta between 0 and 10 (Khalil BOUDJEMLINE sep 2003 Ph.D Thesis) /// Angle with respect to the wires assuming that chambers are perpendicular to the z axis. /// copied from aliroot AliMUONv1.cxx float angleEffectParam[4] = {4.148, -6.809e-01, 5.151e-02, -1.490e-03}; - return angleEffectParam[0] + angleEffectParam[1] * elossratio + angleEffectParam[2] * std::pow(elossratio, 2) + angleEffectParam[3] * std::pow(elossratio, 3); + return angleEffectParam[0] + angleEffectParam[1] * angle + angleEffectParam[2] * angle * angle + angleEffectParam[3] * angle * angle * angle; } //_____________________________________________________________________ float Response::magAngleEffectNorma(float angle, float bfield) const @@ -122,5 +158,5 @@ float Response::magAngleEffectNorma(float angle, float bfield) const /// copied from aliroot AliMUONv1.cxx float angleEffectParam[7] = {8.6995, 25.4022, 13.8822, 2.4717, 1.1551, -0.0624, 0.0012}; float aux = std::abs(angle - angleEffectParam[0] * bfield); - return 121.24 / ((angleEffectParam[1] + angleEffectParam[2] * std::abs(bfield)) + angleEffectParam[3] * aux + angleEffectParam[4] * std::pow(aux, 2) + angleEffectParam[5] * std::pow(aux, 3) + angleEffectParam[6] * std::pow(aux, 4)); + return 121.24 / ((angleEffectParam[1] + angleEffectParam[2] * std::abs(bfield)) + angleEffectParam[3] * aux + angleEffectParam[4] * aux * aux + angleEffectParam[5] * aux * aux * aux + angleEffectParam[6] * aux * aux * aux * aux); } diff --git a/Detectors/MUON/MCH/Simulation/src/Stepper.cxx b/Detectors/MUON/MCH/Simulation/src/Stepper.cxx index 744e3063aab9e..123a8eee0dba9 100644 --- a/Detectors/MUON/MCH/Simulation/src/Stepper.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Stepper.cxx @@ -59,6 +59,7 @@ void Stepper::process(const TVirtualMC& vmc) if (t.isEntering()) { float x, y, z; vmc.TrackPosition(x, y, z); + mTof = (float)vmc.TrackTime(); mEntrancePoint.SetXYZ(x, y, z); resetStep(); } @@ -68,9 +69,11 @@ void Stepper::process(const TVirtualMC& vmc) if (t.isExiting() || t.isStopped()) { float x, y, z; + float etot; vmc.TrackPosition(x, y, z); + etot = (float)vmc.Etot(); mHits->emplace_back(stack->GetCurrentTrackNumber(), detElemId, mEntrancePoint, - math_utils::Point3D{x, y, z}, mTrackEloss, mTrackLength); + math_utils::Point3D{x, y, z}, mTrackEloss, mTrackLength, mTof, etot); resetStep(); } } diff --git a/Detectors/MUON/MCH/Simulation/src/Stepper.h b/Detectors/MUON/MCH/Simulation/src/Stepper.h index 26298ca8fa4de..9bab9c87e82e5 100644 --- a/Detectors/MUON/MCH/Simulation/src/Stepper.h +++ b/Detectors/MUON/MCH/Simulation/src/Stepper.h @@ -43,6 +43,7 @@ class Stepper private: float mTrackEloss{0.0}; float mTrackLength{0.0}; + float mTof{0.0}; std::vector* mHits{nullptr}; math_utils::Point3D mEntrancePoint; }; diff --git a/Detectors/MUON/MCH/Simulation/test/testDigitizer.cxx b/Detectors/MUON/MCH/Simulation/test/testDigitizer.cxx index 2a550220bb137..d300abdf65de1 100644 --- a/Detectors/MUON/MCH/Simulation/test/testDigitizer.cxx +++ b/Detectors/MUON/MCH/Simulation/test/testDigitizer.cxx @@ -28,7 +28,9 @@ #include "MCHSimulation/Hit.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" +#include "Field/MagneticField.h" #include "TGeoManager.h" +#include "TGeoGlobalMagField.h" #include "boost/format.hpp" #include #include @@ -50,6 +52,20 @@ struct GEOMETRY { } }; +void initField(float l3Current, float dipoleCurrent) +{ + /// Create the magnetic field map if not already done + if (TGeoGlobalMagField::Instance()->GetField()) { + return; + } + + auto field = + o2::field::MagneticField::createFieldMap(l3Current, dipoleCurrent, o2::field::MagneticField::kConvLHC, false, 3500., + "A-A", "$(O2_ROOT)/share/Common/maps/mfchebKGI_sym.root"); + TGeoGlobalMagField::Instance()->SetField(field); + TGeoGlobalMagField::Instance()->Lock(); +} + namespace { short detElemId1 = 101; @@ -100,6 +116,8 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) o2::conf::ConfigurableParam::setValue("MCHDigitizer", "seed", 123); o2::mch::Digitizer digitizer(transformation); + initField(-30000.0, -6000.0); + int trackId1 = 0; int trackId2 = 1; int trackId3 = 2; @@ -108,13 +126,14 @@ BOOST_AUTO_TEST_CASE(DigitizerTest) float eloss = 1.e-6; float length = 0.f; float tof = 0.f; + float energ = 10.0; std::vector hits1(2); - hits1.at(0) = o2::mch::Hit(trackId1, detElemId1, entrancePoint1, exitPoint1, eloss, length, tof); - hits1.at(1) = o2::mch::Hit(trackId2, detElemId2, entrancePoint2, exitPoint2, eloss, length, tof); + hits1.at(0) = o2::mch::Hit(trackId1, detElemId1, entrancePoint1, exitPoint1, eloss, length, tof, energ); + hits1.at(1) = o2::mch::Hit(trackId2, detElemId2, entrancePoint2, exitPoint2, eloss, length, tof, energ); std::vector hits2(1); - hits2.at(0) = o2::mch::Hit(trackId3, detElemId3, entrancePoint3, exitPoint3, eloss, length, tof); + hits2.at(0) = o2::mch::Hit(trackId3, detElemId3, entrancePoint3, exitPoint3, eloss, length, tof, energ); digitizer.processHits(hits1, collisionTime1, 0, 0); digitizer.processHits(hits2, collisionTime2, 0, 0); diff --git a/Steer/DigitizerWorkflow/src/MCHDigitizerSpec.cxx b/Steer/DigitizerWorkflow/src/MCHDigitizerSpec.cxx index 187c24f962c1f..2cd17ba16f5d5 100644 --- a/Steer/DigitizerWorkflow/src/MCHDigitizerSpec.cxx +++ b/Steer/DigitizerWorkflow/src/MCHDigitizerSpec.cxx @@ -45,7 +45,7 @@ namespace mch class MCHDPLDigitizerTask : public o2::base::BaseDPLDigitizer { public: - MCHDPLDigitizerTask() : o2::base::BaseDPLDigitizer(o2::base::InitServices::GEOM) {} + MCHDPLDigitizerTask() : o2::base::BaseDPLDigitizer(o2::base::InitServices::FIELD | o2::base::InitServices::GEOM) {} void initDigitizerTask(framework::InitContext& ic) override { From f3f16021670042529fce8c68efde502313dc63d9 Mon Sep 17 00:00:00 2001 From: Ruben Shahoyan Date: Mon, 29 Apr 2024 18:23:06 +0200 Subject: [PATCH 0185/2997] add to debug output original TPC tracks tree (#13090) --- .../include/GlobalTracking/MatchTPCITS.h | 10 +- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 105 ++++++++++++------ 2 files changed, 78 insertions(+), 37 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h index f0dd8ce86a72a..ef45cb21adbd8 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTPCITS.h @@ -423,9 +423,10 @@ class MatchTPCITS #ifdef _ALLOW_DEBUG_TREES_ enum DebugFlagTypes : UInt_t { - MatchTreeAll = 0x1 << 1, ///< produce matching candidates tree for all candidates - MatchTreeAccOnly = 0x1 << 2, ///< fill the matching candidates tree only once the cut is passed - WinnerMatchesTree = 0x1 << 3 ///< separate debug tree for winner matches + MatchTreeAll = 0x1 << 1, ///< produce matching candidates tree for all candidates + MatchTreeAccOnly = 0x1 << 2, ///< fill the matching candidates tree only once the cut is passed + WinnerMatchesTree = 0x1 << 3, ///< separate debug tree for winner matches + TPCOrigTree = 0x1 << 4 ///< original TPC tracks with some aux info }; ///< check if partucular flags are set bool isDebugFlag(UInt_t flags) const { return mDBGFlags & flags; } @@ -450,6 +451,7 @@ class MatchTPCITS ///< fill matching debug tree void fillTPCITSmatchTree(int itsID, int tpcID, int rejFlag, float chi2 = -1., float tCorr = 0.); void dumpWinnerMatches(); + void dumpTPCOrig(bool acc, int tpcIndex); #endif private: @@ -464,7 +466,7 @@ class MatchTPCITS bool prepareFITData(); int prepareInteractionTimes(); int prepareTPCTracksAfterBurner(); - void addTPCSeed(const o2::track::TrackParCov& _tr, float t0, float terr, o2::dataformats::GlobalTrackID srcGID, int tpcID); + int addTPCSeed(const o2::track::TrackParCov& _tr, float t0, float terr, o2::dataformats::GlobalTrackID srcGID, int tpcID); int preselectChipClusters(std::vector& clVecOut, const ClusRange& clRange, const ITSChipClustersRefs& itsChipClRefs, float trackY, float trackZ, float tolerY, float tolerZ) const; diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index c1b2e4b224ccb..afb26ddcf47c9 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -402,23 +402,23 @@ int MatchTPCITS::getNMatchRecordsITS(const TrackLocITS& tTPC) const } //______________________________________________ -void MatchTPCITS::addTPCSeed(const o2::track::TrackParCov& _tr, float t0, float terr, GTrackID srcGID, int tpcID) +int MatchTPCITS::addTPCSeed(const o2::track::TrackParCov& _tr, float t0, float terr, GTrackID srcGID, int tpcID) { // account single TPC seed, can be from standalone TPC track or constrained track from match to TRD and/or TOF const float SQRT12DInv = 2. / sqrt(12.); if (_tr.getX() > o2::constants::geom::XTPCInnerRef + 0.1 || std::abs(_tr.getQ2Pt()) > mMinTPCTrackPtInv) { - return; + return -99; } const auto& tpcOrig = mTPCTracksArray[tpcID]; // discard tracks w/o certain number of total or innermost pads (last cluster is innermost one) if (tpcOrig.getNClusterReferences() < mParams->minTPCClusters) { - return; + return -89; } uint8_t clSect = 0, clRow = 0; uint32_t clIdx = 0; tpcOrig.getClusterReference(mTPCTrackClusIdx, tpcOrig.getNClusterReferences() - 1, clSect, clRow, clIdx); if (clRow > mParams->askMinTPCRow[clSect]) { - return; + return -9; } // create working copy of track param bool extConstrained = srcGID.getSource() != GTrackID::TPC; @@ -449,13 +449,14 @@ void MatchTPCITS::addTPCSeed(const o2::track::TrackParCov& _tr, float t0, float } if (!propagateToRefX(trc)) { mTPCWork.pop_back(); // discard track whose propagation to XMatchingRef failed - return; + return -1; } if (mMCTruthON) { mTPCLblWork.emplace_back(mTPCTrkLabels[tpcID]); } // cache work track index mTPCSectIndexCache[o2::math_utils::angle2Sector(trc.getAlpha())].push_back(mTPCWork.size() - 1); + return 0; } //______________________________________________ @@ -485,6 +486,32 @@ bool MatchTPCITS::prepareTPCData() mTPCSectIndexCache[sec].reserve(100 + 1.2 * ntrW / o2::constants::math::NSectors); } + mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500 + mNTPCOccBinLength = mTPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins; + mTBinClOcc.clear(); + if (mNTPCOccBinLength > 1 && mTPCRefitterOccMap.size()) { + mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength; + int nTPCBins = mNHBPerTF * o2::constants::lhc::LHCMaxBunches / 8, ninteg = 0; + int nTPCOccBins = nTPCBins * mNTPCOccBinLengthInv, sumBins = std::max(1, int(o2::constants::lhc::LHCMaxBunches / 8 * mNTPCOccBinLengthInv)); + mTBinClOcc.resize(nTPCOccBins); + std::vector mltHistTB(nTPCOccBins); + float sm = 0., tb = 0.5 * mNTPCOccBinLength; + for (int i = 0; i < nTPCOccBins; i++) { + mltHistTB[i] = mTPCRefitter->getParam()->GetUnscaledMult(tb); + tb += mNTPCOccBinLength; + } + for (int i = nTPCOccBins; i--;) { + sm += mltHistTB[i]; + if (i + sumBins < nTPCOccBins) { + sm -= mltHistTB[i + sumBins]; + } + mTBinClOcc[i] = sm; + } + } else { + mTBinClOcc.resize(1); + } + auto creator = [this](auto& trk, GTrackID gid, float time0, float terr) { if constexpr (isITSTrack()) { // do nothing, ITS tracks will be processed in a direct loop over ROFs @@ -494,20 +521,27 @@ bool MatchTPCITS::prepareTPCData() } else if (std::abs(trk.getQ2Pt()) > mMinTPCTrackPtInv) { return true; } + int resAdd = -100; + int tpcIndex = -1; if constexpr (isTPCTrack()) { // unconstrained TPC track, with t0 = TrackTPC.getTime0+0.5*(DeltaFwd-DeltaBwd) and terr = 0.5*(DeltaFwd+DeltaBwd) in TimeBins if (!this->mSkipTPCOnly && trk.getNClusters() > 0) { - this->addTPCSeed(trk, this->tpcTimeBin2MUS(time0), this->tpcTimeBin2MUS(terr), gid, gid.getIndex()); + resAdd = this->addTPCSeed(trk, this->tpcTimeBin2MUS(time0), this->tpcTimeBin2MUS(terr), gid, (tpcIndex = gid.getIndex())); } } if constexpr (isTPCTOFTrack()) { // TPC track constrained by TOF time, time and its error in \mus - this->addTPCSeed(trk, time0, terr, gid, this->mRecoCont->getTPCContributorGID(gid)); + resAdd = this->addTPCSeed(trk, time0, terr, gid, (tpcIndex = this->mRecoCont->getTPCContributorGID(gid))); } if constexpr (isTRDTrack()) { // TPC track constrained by TRD trigger time, time and its error in \mus - this->addTPCSeed(trk, time0, terr, gid, this->mRecoCont->getTPCContributorGID(gid)); + resAdd = this->addTPCSeed(trk, time0, terr, gid, (tpcIndex = this->mRecoCont->getTPCContributorGID(gid))); } +#ifdef _ALLOW_DEBUG_TREES_ + if (resAdd > -10 && mDBGOut && isDebugFlag(TPCOrigTree)) { + dumpTPCOrig(resAdd == 0, tpcIndex); + } +#endif // note: TPCTRDTPF tracks are actually TRD track with extra TOF cluster return true; }; @@ -576,31 +610,6 @@ bool MatchTPCITS::prepareTPCData() mITSROFofTPCBin[ib] = itsROF; } */ - mTPCRefitter = std::make_unique(mTPCClusterIdxStruct, mTPCCorrMapsHelper, mBz, mTPCTrackClusIdx.data(), 0, mTPCRefitterShMap.data(), mTPCRefitterOccMap.data(), mTPCRefitterOccMap.size(), nullptr, o2::base::Propagator::Instance()); - mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500 - mNTPCOccBinLength = mTPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins; - mTBinClOcc.clear(); - if (mNTPCOccBinLength > 1 && mTPCRefitterOccMap.size()) { - mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength; - int nTPCBins = mNHBPerTF * o2::constants::lhc::LHCMaxBunches / 8, ninteg = 0; - int nTPCOccBins = nTPCBins * mNTPCOccBinLengthInv, sumBins = std::max(1, int(o2::constants::lhc::LHCMaxBunches / 8 * mNTPCOccBinLengthInv)); - mTBinClOcc.resize(nTPCOccBins); - std::vector mltHistTB(nTPCOccBins); - float sm = 0., tb = 0.5 * mNTPCOccBinLength; - for (int i = 0; i < nTPCOccBins; i++) { - mltHistTB[i] = mTPCRefitter->getParam()->GetUnscaledMult(tb); - tb += mNTPCOccBinLength; - } - for (int i = nTPCOccBins; i--;) { - sm += mltHistTB[i]; - if (i + sumBins < nTPCOccBins) { - sm -= mltHistTB[i + sumBins]; - } - mTBinClOcc[i] = sm; - } - } else { - mTBinClOcc.resize(1); - } mInteractionMUSLUT.clear(); mInteractionMUSLUT.resize(maxTime + 3 * o2::constants::lhc::LHCOrbitMUS, -1); mTimer[SWPrepTPC].Stop(); @@ -2816,6 +2825,36 @@ void MatchTPCITS::setDebugFlag(UInt_t flag, bool on) } } +//_________________________________________________________ +void MatchTPCITS::dumpTPCOrig(bool acc, int tpcIndex) +{ + ///< fill debug tree for TPC original tracks (passing pT cut) + mTimer[SWDBG].Start(false); + const auto& tpcOrig = mTPCTracksArray[tpcIndex]; + uint8_t clSect = 0, clRow = 0; + uint32_t clIdx = 0; + tpcOrig.getClusterReference(mTPCTrackClusIdx, tpcOrig.getNClusterReferences() - 1, clSect, clRow, clIdx); + int tb = tpcOrig.getTime0() * mNTPCOccBinLengthInv; + float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]); + (*mDBGOut) << "tpcOrig" + << "tf=" << mTFCount + << "index=" << tpcIndex + << "acc=" << acc + << "chi2TPC=" << tpcOrig.getChi2() + << "nClus=" << tpcOrig.getNClusters() + << "time0=" << tpcOrig.getTime0() + << "trc=" << ((o2::track::TrackParCov&)tpcOrig) + << "minRow=" << clRow + << "multTPC=" << mltTPC; + if (mMCTruthON) { + (*mDBGOut) << "tpcOrig" + << "tpcLbl=" << mTPCTrkLabels[tpcIndex]; + } + (*mDBGOut) << "tpcOrig" + << "\n"; + mTimer[SWDBG].Stop(); +} + //_________________________________________________________ void MatchTPCITS::fillTPCITSmatchTree(int itsID, int tpcID, int rejFlag, float chi2, float tCorr) { From b98e26b789f6f67d7d25046cbfb00a3a10ffdf15 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 29 Apr 2024 18:24:55 +0200 Subject: [PATCH 0186/2997] Add some aux methods for interactive track drawing --- .../TrackParametrization.h | 2 ++ .../src/TrackParametrization.cxx | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index 6835ced969cad..41d3efc2cfd2d 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -216,6 +216,8 @@ class TrackParametrization GPUd() value_t getYAt(value_t xk, value_t b) const; GPUd() value_t getSnpAt(value_t xk, value_t b) const; GPUd() value_t getSnpAt(value_t alpha, value_t xk, value_t b) const; + GPUd() value_t getPhiAt(value_t xk, value_t b) const; + GPUd() value_t getPhiPosAt(value_t xk, value_t b) const; GPUd() math_utils::Point3D getXYZGloAt(value_t xk, value_t b, bool& ok) const; // parameters manipulation diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index e1f8ee1910161..ba36045f18606 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -520,6 +520,40 @@ GPUd() typename TrackParametrization::value_t TrackParametrization +GPUd() typename TrackParametrization::value_t TrackParametrization::getPhiAt(value_t xk, value_t b) const +{ + ///< this method is just an alias for obtaining phi @ X in the tree->Draw() + value_t dx = xk - getX(); + if (gpu::CAMath::Abs(dx) < constants::math::Almost0) { + return getPhi(); + } + value_t crv = (gpu::CAMath::Abs(b) < constants::math::Almost0) ? 0.f : getCurvature(b); + value_t x2r = crv * dx; + value_t snp = mP[kSnp] + x2r; + value_t phi = 999.; + if (gpu::CAMath::Abs(snp) < constants::math::Almost1) { + value_t phi = gpu::CAMath::ASin(snp) + getAlpha(); + math_utils::detail::bringTo02Pi(phi); + } + return phi; +} + +//______________________________________________________________ +template +GPUd() typename TrackParametrization::value_t TrackParametrization::getPhiPosAt(value_t xk, value_t b) const +{ + ///< this method is just an alias for obtaining phiPos @ X in the tree->Draw() + value_t phi = 999.; + auto y = getYAt(xk, b); + if (y > -9998.) { + phi = gpu::CAMath::ATan2(y, xk) + getAlpha(); + math_utils::detail::bringTo02Pi(phi); + } + return phi; +} + //______________________________________________________________ template GPUd() typename TrackParametrization::value_t TrackParametrization::getSnpAt(value_t alpha, value_t xk, value_t b) const From fc6e0844eb7f024026c8919b666cbaccd844ec32 Mon Sep 17 00:00:00 2001 From: pillot Date: Mon, 29 Apr 2024 23:30:59 +0200 Subject: [PATCH 0187/2997] add dsIndex key for muonview (#13093) --- Detectors/MUON/MCH/GlobalMapping/src/global-mapper.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/MUON/MCH/GlobalMapping/src/global-mapper.cxx b/Detectors/MUON/MCH/GlobalMapping/src/global-mapper.cxx index 285d2cb58c4e8..e981824bc3e09 100644 --- a/Detectors/MUON/MCH/GlobalMapping/src/global-mapper.cxx +++ b/Detectors/MUON/MCH/GlobalMapping/src/global-mapper.cxx @@ -122,8 +122,6 @@ void dcs2json() std::vector computeDualSampaInfos() { - uint16_t dsBin{0}; - auto elec2det = createElec2DetMapper(); auto det2elec = createDet2ElecMapper(); auto solar2FeeLink = createSolar2FeeLinkMapper(); @@ -210,6 +208,8 @@ void solar2json(bool mchview) if (mchview) { writer.Key("dsbin"); writer.Int(dsi.dsBinX); + writer.Key("dsIndex"); + writer.Int(dsi.dsBin); } else { writer.Key("binX"); writer.Int(dsi.dsBinX); From c09a35ff631124b79f966fbfb7dc2043c921bac2 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 30 Apr 2024 05:34:56 +0200 Subject: [PATCH 0188/2997] DPL: improve Signposts implementation (#13096) --- Framework/Foundation/include/Framework/Signpost.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Framework/Foundation/include/Framework/Signpost.h b/Framework/Foundation/include/Framework/Signpost.h index fc22147415792..1ddaaa6fb793f 100644 --- a/Framework/Foundation/include/Framework/Signpost.h +++ b/Framework/Foundation/include/Framework/Signpost.h @@ -26,9 +26,8 @@ struct o2_log_handle_t { // Helper function which replaces engineering types with a printf // compatible format string. -// FIXME: make this consteval when available in C++20 template -constexpr auto remove_engineering_type(char const (&src)[N]) +consteval auto remove_engineering_type(char const (&src)[N]) { std::array res = {}; // do whatever string manipulation you want in res. @@ -501,7 +500,7 @@ void o2_debug_log_set_stacktrace(_o2_log_t* log, int stacktrace) } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \ _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \ } else { \ - O2_LOG_MACRO_RAW(info, format, ##__VA_ARGS__); \ + O2_LOG_MACRO_RAW(info, remove_engineering_type(format).data(), ##__VA_ARGS__); \ } \ }) @@ -512,7 +511,7 @@ void o2_debug_log_set_stacktrace(_o2_log_t* log, int stacktrace) } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \ _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \ } \ - O2_LOG_MACRO_RAW(error, format, ##__VA_ARGS__); \ + O2_LOG_MACRO_RAW(error, remove_engineering_type(format).data(), ##__VA_ARGS__); \ }) // Similar to the above, however it will also print a normal warning message regardless of the signpost being enabled or not. @@ -522,7 +521,7 @@ void o2_debug_log_set_stacktrace(_o2_log_t* log, int stacktrace) } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \ _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \ } \ - O2_LOG_MACRO_RAW(warn, format, ##__VA_ARGS__); \ + O2_LOG_MACRO_RAW(warn, remove_engineering_type(format).data(), ##__VA_ARGS__); \ }) #define O2_SIGNPOST_START(log, id, name, format, ...) \ From 1448ff676d47e4163b5430ab62352db23d2101e3 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 30 Apr 2024 00:23:44 +0200 Subject: [PATCH 0189/2997] Optional TRD/TOF tracks request for PV used for interpolation --- .../SpacePoints/SpacePointsCalibConfParam.h | 1 + .../SpacePoints/src/TrackInterpolation.cxx | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h index 604a9e4adcde4..2465cbf512d2b 100644 --- a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h +++ b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/SpacePointsCalibConfParam.h @@ -38,6 +38,7 @@ struct SpacePointsCalibConfParam : public o2::conf::ConfigurableParamHelpergetPrimaryVertexMatchedTrackRefs(); // references from vertex to these track IDs int nv = vtxRefs.size() - 1; GTrackID::mask_t allowedSources = GTrackID::getSourcesMask("ITS-TPC,ITS-TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD-TOF"); + constexpr std::array SrcFast = {int(GTrackID::ITSTPCTRD), int(GTrackID::ITSTPCTOF), int(GTrackID::ITSTPCTRDTOF)}; for (int iv = 0; iv < nv; iv++) { LOGP(debug, "processing PV {} of {}", iv, nv); const auto& vtref = vtxRefs[iv]; auto pv = pvvec[iv]; + if (mParams->minTOFTRDPVContributors > 0) { // we want only PVs constrained by fast detectors + int nfound = 0; + bool usePV = false; + for (uint32_t is = 0; is < SrcFast.size() && !usePV; is++) { + int src = SrcFast[is], idMin = vtref.getFirstEntryOfSource(src), idMax = idMin + vtref.getEntriesOfSource(src); + for (int i = idMin; i < idMax; i++) { + if (trackIndex[i].isPVContributor() && (++nfound == mParams->minTOFTRDPVContributors)) { + usePV = true; + break; + } + } + } + if (!usePV) { + continue; + } + } + for (int is = GTrackID::NSources; is >= 0; is--) { if (!allowedSources[is]) { continue; From 7d0dc4f12a249d8f44039d6c9240797963ba2569 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Tue, 30 Apr 2024 10:10:31 +0200 Subject: [PATCH 0190/2997] QC-1163 Update QC flag type list to be in sync with BKP (#13092) One exception is NotBadFlagExample, which I will remove later, once QC can use Good. --- DataFormats/QualityControl/etc/flagTypes.csv | 28 +++++++++---------- .../QualityControl/test/testFlagTypes.cxx | 12 ++++---- .../test/testQualityControlFlagCollection.cxx | 8 +++--- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/DataFormats/QualityControl/etc/flagTypes.csv b/DataFormats/QualityControl/etc/flagTypes.csv index 23acc1b3000fa..b4504b0f8f896 100644 --- a/DataFormats/QualityControl/etc/flagTypes.csv +++ b/DataFormats/QualityControl/etc/flagTypes.csv @@ -1,15 +1,15 @@ "id","method","name","bad","obsolete" -1,"Unknown","Unknown",1,0 -2,"UnknownQuality","Unknown Quality",1,0 -3,"CertifiedByExpert","Certified by Expert",0,0 -10,"NoDetectorData","No Detector Data",1,0 -11,"LimitedAcceptance","Limited acceptance",1,0 -12,"BadPID","Bad PID",1,0 -13,"BadTracking","Bad Tracking",1,0 -14,"BadHadronPID","Bad Hadron PID",1,0 -15,"BadElectronPID","Bad Electron PID",1,0 -16,"BadEMCalorimetry","Bad EM Calorimetry",1,0 -17,"BadPhotonCalorimetry","Bad Photon Calorimetry",1,0 -65500,"ObsoleteFlagExample","Obsolete flag example",1,1 -65501,"NotBadFlagExample","Not bad flag example",0,0 -65535,"Invalid","Invalid",1,0 +1,"UnknownQuality","Unknown Quality",1,0 +3,"NoDetectorData","No Detector Data",1,0 +4,"LimitedAcceptanceMCNotReproducible","Limited Acceptance MC Not Reproducible",1,0 +5,"LimitedAcceptanceMCReproducible","Limited Acceptance MC Reproducible",1,0 +6,"BadPID","Bad PID",1,0 +7,"BadTracking","Bad Tracking",1,0 +8,"BadHadronPID","Bad Hadron PID",1,0 +9,"Good","Good",0,0 +10,"Invalid","Invalid",1,0 +11,"BadElectronPID","Bad Electron PID",1,0 +12,"BadEMCalorimetry","Bad EM Calorimetry",1,0 +13,"BadPhotonCalorimetry","Bad Photon Calorimetry",1,0 +14,"Unknown","Unknown",1,0 +65501,"NotBadFlagExample","Not bad flag example",0,0 \ No newline at end of file diff --git a/DataFormats/QualityControl/test/testFlagTypes.cxx b/DataFormats/QualityControl/test/testFlagTypes.cxx index e1587825a323a..2fe904aa1c167 100644 --- a/DataFormats/QualityControl/test/testFlagTypes.cxx +++ b/DataFormats/QualityControl/test/testFlagTypes.cxx @@ -33,14 +33,14 @@ BOOST_AUTO_TEST_CASE(FlagTypes) BOOST_CHECK_EQUAL(fDefault, FlagTypeFactory::Invalid()); auto f1 = FlagTypeFactory::Unknown(); - BOOST_CHECK_EQUAL(f1.getID(), 1); + BOOST_CHECK_EQUAL(f1.getID(), 14); BOOST_CHECK_EQUAL(f1.getName(), "Unknown"); BOOST_CHECK_EQUAL(f1.getBad(), true); - std::cout << f1 << std::endl; + BOOST_CHECK_NO_THROW(std::cout << f1 << std::endl); auto f2 = f1; - BOOST_CHECK_EQUAL(f2.getID(), 1); + BOOST_CHECK_EQUAL(f2.getID(), 14); BOOST_CHECK_EQUAL(f1.getName(), f2.getName()); BOOST_CHECK_EQUAL(f2.getName(), "Unknown"); BOOST_CHECK_EQUAL(f2.getBad(), true); @@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(FlagTypes) BOOST_CHECK(!(f1 < f2)); BOOST_CHECK(!(f1 > f2)); - auto f3 = FlagTypeFactory::LimitedAcceptance(); - BOOST_CHECK(f3 > f1); - BOOST_CHECK(!(f3 < f1)); + auto f3 = FlagTypeFactory::LimitedAcceptanceMCNotReproducible(); + BOOST_CHECK(f3 < f1); + BOOST_CHECK(!(f3 > f1)); } diff --git a/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx b/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx index e069776e84907..198ae29bc53a6 100644 --- a/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx +++ b/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx @@ -46,8 +46,8 @@ BOOST_AUTO_TEST_CASE(test_QualityControlFlagCollection_Methods) QualityControlFlagCollection qcfc2{"Reco checks", "TOF"}; qcfc2.insert({50, 77, FlagTypeFactory::Invalid()}); // this is a duplicate to an entry in qcfc1 qcfc2.insert({51, 77, FlagTypeFactory::Invalid()}); - qcfc2.insert({1234, 3434, FlagTypeFactory::LimitedAcceptance()}); - qcfc2.insert({50, 77, FlagTypeFactory::LimitedAcceptance()}); + qcfc2.insert({1234, 3434, FlagTypeFactory::LimitedAcceptanceMCNotReproducible()}); + qcfc2.insert({50, 77, FlagTypeFactory::LimitedAcceptanceMCNotReproducible()}); BOOST_CHECK_EQUAL(qcfc2.size(), 4); // Try merging. Duplicate entries should be left in the 'other' objects. @@ -97,8 +97,8 @@ BOOST_AUTO_TEST_CASE(test_QualityControlFlagCollection_IO) QualityControlFlagCollection qcfc1{"xyz", "TST"}; qcfc1.insert({50, 77, FlagTypeFactory::Invalid(), "a comment", "a source"}); qcfc1.insert({51, 77, FlagTypeFactory::Invalid()}); - qcfc1.insert({1234, 3434, FlagTypeFactory::LimitedAcceptance()}); - qcfc1.insert({50, 77, FlagTypeFactory::LimitedAcceptance()}); + qcfc1.insert({1234, 3434, FlagTypeFactory::LimitedAcceptanceMCNotReproducible()}); + qcfc1.insert({50, 77, FlagTypeFactory::LimitedAcceptanceMCNotReproducible()}); qcfc1.insert({43434, 63421, FlagTypeFactory::NotBadFlagExample()}); std::stringstream store; From bac0ea0c0c98b982ecd7ac8eab3d0148678115d0 Mon Sep 17 00:00:00 2001 From: Nicolas Strangmann <77485327+nstrangm@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:02:05 +0200 Subject: [PATCH 0191/2997] [EMCAL-604] Initialize Unit Tests for the EMCal Geometry class (#13095) - GetCellIndex as first function to be tested: - Check sm number, module number, phi and eta index for all valid cells - Check two exceptions for invalid cells - Check against on-the-fly calculation in the testGeometry.cxx file itself - Minor correction in Geometry.cxx to improve readability of the code --- Detectors/EMCAL/base/CMakeLists.txt | 7 +++ Detectors/EMCAL/base/src/Geometry.cxx | 2 +- Detectors/EMCAL/base/test/testGeometry.cxx | 66 ++++++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 Detectors/EMCAL/base/test/testGeometry.cxx diff --git a/Detectors/EMCAL/base/CMakeLists.txt b/Detectors/EMCAL/base/CMakeLists.txt index 9a852c00616e3..62a0cb6d9a25b 100644 --- a/Detectors/EMCAL/base/CMakeLists.txt +++ b/Detectors/EMCAL/base/CMakeLists.txt @@ -42,6 +42,13 @@ o2_add_test(Mapper LABELS emcal ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage) +o2_add_test(Geometry + SOURCES test/testGeometry.cxx + PUBLIC_LINK_LIBRARIES O2::EMCALBase + COMPONENT_NAME emcal + LABELS emcal + ENVIRONMENT O2_ROOT=${CMAKE_BINARY_DIR}/stage) + o2_add_test(RCUTrailer SOURCES test/testRCUTrailer.cxx PUBLIC_LINK_LIBRARIES O2::EMCALBase diff --git a/Detectors/EMCAL/base/src/Geometry.cxx b/Detectors/EMCAL/base/src/Geometry.cxx index 826b7a5d75341..5d4b793525e20 100644 --- a/Detectors/EMCAL/base/src/Geometry.cxx +++ b/Detectors/EMCAL/base/src/Geometry.cxx @@ -1026,7 +1026,7 @@ std::tuple Geometry::CalculateCellIndex(Int_t absId) const Int_t nModule = tmp / mNCellsInModule; tmp = tmp % mNCellsInModule; - Int_t nIphi = tmp / mNPHIdiv, nIeta = tmp % mNPHIdiv; + Int_t nIphi = tmp / mNPHIdiv, nIeta = tmp % mNETAdiv; return std::make_tuple(nSupMod, nModule, nIphi, nIeta); } diff --git a/Detectors/EMCAL/base/test/testGeometry.cxx b/Detectors/EMCAL/base/test/testGeometry.cxx new file mode 100644 index 0000000000000..f297410b6959f --- /dev/null +++ b/Detectors/EMCAL/base/test/testGeometry.cxx @@ -0,0 +1,66 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#define BOOST_TEST_MODULE Test EMCAL Base +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include +#include +#include "EMCALBase/Geometry.h" +#include +#include + +std::tuple GetRefCellIndex(int CellId); + +/// \macro Test implementation of the EMCAL Geometry +/// +/// Test coverage: +/// - GetCellIndex (get #sm, #mod, phi index and eta index): all cells (0-17663) +/// - Invalid CellId: exception test for cell -1 and 17664 +BOOST_AUTO_TEST_CASE(Geometry_test) +{ + auto testgeometry = o2::emcal::Geometry::GetInstanceFromRunNumber(300000); + + // Check GetCellIndex function for all valid cells by comparing to GetRefCellIndex function + for (int iCell = 0; iCell < 17664; iCell++) { + auto [smod, mod, iphi, ieta] = testgeometry->GetCellIndex(iCell); + auto [smod_ref, mod_ref, iphi_ref, ieta_ref] = GetRefCellIndex(iCell); + BOOST_CHECK_EQUAL(smod, smod_ref); + BOOST_CHECK_EQUAL(mod, mod_ref); + BOOST_CHECK_EQUAL(iphi, iphi_ref); + BOOST_CHECK_EQUAL(ieta, ieta_ref); + } // And then check the exeptions of -1 and 17664 + BOOST_CHECK_EXCEPTION(testgeometry->GetCellIndex(-1), o2::emcal::InvalidCellIDException, [](o2::emcal::InvalidCellIDException const& mCellID) { return -1; }); + BOOST_CHECK_EXCEPTION(testgeometry->GetCellIndex(17664), o2::emcal::InvalidCellIDException, [](o2::emcal::InvalidCellIDException const& mCellID) { return 17664; }); +} + +std::tuple GetRefCellIndex(int CellId) +{ + // Four cells per module: + int ieta = CellId % 2; // cells 0 and 2 (in each module) have eta index 0 + int iphi = (CellId % 4 == 2 || CellId % 4 == 3) ? 1 : 0; // cells 0 and 1 (in each module) have phi index 0 + + int smod = 0, mod = 0; // Super module number and module number + if (CellId >= 0 && CellId < 11520) { // The first 10 super modules are full modules + smod = CellId / 1152; // Their number is their cell number divided by the cells per sm (rounded down) + mod = (CellId % 1152) / 4; // And the module is the cell number within the sm (%) divided by four (four cells in one module) + } else if (CellId >= 11520 && CellId < 12288) { // First two one thirds + smod = 10 + (CellId - 11520) / 384; // +10 to account for the - 11520 + mod = ((CellId - 11520) % 384) / 4; // -11520 to subtract all cells in full super modules + } else if (CellId >= 12288 && CellId < 16896) { // Six two third modules + smod = 12 + (CellId - 12288) / 768; + mod = ((CellId - 12288) % 768) / 4; + } else if (CellId >= 16896 && CellId < 17664) { // Second two one third modules + smod = 18 + (CellId - 16896) / 384; + mod = ((CellId - 16896) % 384) / 4; + } + + return std::make_tuple(smod, mod, iphi, ieta); +} \ No newline at end of file From 70c961fc8678a0b6666b3a1a37f0bb67c3579f16 Mon Sep 17 00:00:00 2001 From: noferini <9963644+noferini@users.noreply.github.com> Date: Sun, 28 Apr 2024 17:10:13 +0200 Subject: [PATCH 0192/2997] return dca in fast propagator --- Detectors/Base/include/DetectorsBase/Propagator.h | 2 +- Detectors/Base/src/Propagator.cxx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/Propagator.h b/Detectors/Base/include/DetectorsBase/Propagator.h index 4c9424401143a..a9e2ce6e0383d 100644 --- a/Detectors/Base/include/DetectorsBase/Propagator.h +++ b/Detectors/Base/include/DetectorsBase/Propagator.h @@ -136,7 +136,7 @@ class PropagatorImpl GPUd() void setNominalBz(value_type bz) { mNominalBz = bz; } GPUd() bool hasMagFieldSet() const { return mField != nullptr; } - GPUd() void estimateLTFast(o2::track::TrackLTIntegral& lt, const o2::track::TrackParametrization& trc) const; + GPUd() value_type estimateLTFast(o2::track::TrackLTIntegral& lt, const o2::track::TrackParametrization& trc) const; GPUd() float estimateLTIncrement(const o2::track::TrackParametrization& trc, const o2::math_utils::Point3D& postStart, const o2::math_utils::Point3D& posEnd) const; #ifndef GPUCA_GPUCODE diff --git a/Detectors/Base/src/Propagator.cxx b/Detectors/Base/src/Propagator.cxx index 5e932ebe55038..0d1b53b695536 100644 --- a/Detectors/Base/src/Propagator.cxx +++ b/Detectors/Base/src/Propagator.cxx @@ -668,7 +668,7 @@ GPUd() float PropagatorImpl::estimateLTIncrement(const o2::track::Track //____________________________________________________________ template -GPUd() void PropagatorImpl::estimateLTFast(o2::track::TrackLTIntegral& lt, const o2::track::TrackParametrization& trc) const +GPUd() value_T PropagatorImpl::estimateLTFast(o2::track::TrackLTIntegral& lt, const o2::track::TrackParametrization& trc) const { value_T xdca = 0., ydca = 0., length = 0.; // , zdca = 0. // zdca might be used in future o2::math_utils::CircleXY c; @@ -715,8 +715,10 @@ GPUd() void PropagatorImpl::estimateLTFast(o2::track::TrackLTIntegral& length = straigh_line_approx(); } // since we assume the track or its parent comes from the beam-line or decay, add XY(?) distance to it - length += math_utils::detail::sqrt(xdca * xdca + ydca * ydca); + value_T dcaT = math_utils::detail::sqrt(xdca * xdca + ydca * ydca); + length += dcaT; lt.addStep(length, trc.getP2Inv()); + return dcaT; } //____________________________________________________________ From b04a3511ebd6dce76269cee886574b5c86757e04 Mon Sep 17 00:00:00 2001 From: noferini <9963644+noferini@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:40:42 +0200 Subject: [PATCH 0193/2997] fix in track length estimate for TPC only tracks --- Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h | 2 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h index 0d0e2f40f5fbb..83f4dae0c2476 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h @@ -219,7 +219,7 @@ class MatchTOF void BestMatches(std::vector& matchedTracksPairs, std::vector* matchedTracks, std::vector* matchedTracksIndex, int* matchedClustersIndex, const gsl::span& FITRecPoints, const std::vector& TOFClusWork, const std::vector* TracksWork, std::vector& CalibInfoTOF, unsigned long Timestamp, bool MCTruthON, const o2::dataformats::MCTruthContainer* TOFClusLabels, const std::vector* TracksLblWork, std::vector* OutTOFLabels, float calibMaxChi2); void BestMatchesHP(std::vector& matchedTracksPairs, std::vector* matchedTracks, std::vector* matchedTracksIndex, int* matchedClustersIndex, const gsl::span& FITRecPoints, const std::vector& TOFClusWork, std::vector& CalibInfoTOF, unsigned long Timestamp, bool MCTruthON, const o2::dataformats::MCTruthContainer* TOFClusLabels, const std::vector* TracksLblWork, std::vector* OutTOFLabels); bool propagateToRefX(o2::track::TrackParCov& trc, float xRef /*in cm*/, float stepInCm /*in cm*/, o2::track::TrackLTIntegral& intLT); - bool propagateToRefXWithoutCov(o2::track::TrackParCov& trc, float xRef /*in cm*/, float stepInCm /*in cm*/, float bz); + bool propagateToRefXWithoutCov(const o2::track::TrackParCov& trc, float xRef /*in cm*/, float stepInCm /*in cm*/, float bz); void updateTimeDependentParams(); diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 53e71083e3851..a384c489520fd 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -553,7 +553,7 @@ void MatchTOF::propagateTPCTracks(int sec) } if (trc.getX() < o2::constants::geom::XTPCOuterRef - 1.) { - if (!propagateToRefX(trc, o2::constants::geom::XTPCOuterRef, 10, intLT0) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagat> + if (!propagateToRefXWithoutCov(trc, o2::constants::geom::XTPCOuterRef, 10, mBz) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagat> mNotPropagatedToTOF[trkType::UNCONS]++; continue; } @@ -1690,7 +1690,7 @@ bool MatchTOF::propagateToRefX(o2::track::TrackParCov& trc, float xRef, float st } //______________________________________________ -bool MatchTOF::propagateToRefXWithoutCov(o2::track::TrackParCov& trc, float xRef, float stepInCm, float bzField) +bool MatchTOF::propagateToRefXWithoutCov(const o2::track::TrackParCov& trc, float xRef, float stepInCm, float bzField) { // propagate track to matching reference X without using the covariance matrix // we create the copy of the track in a TrackPar object (no cov matrix) From 72678b35d5ab3ac884230ccc513f15a6356309d1 Mon Sep 17 00:00:00 2001 From: Ivana Hrivnacova Date: Tue, 30 Apr 2024 15:21:59 +0200 Subject: [PATCH 0194/2997] Doxygen fixes (#13099) * Updated (or added) Doxygen keywords * Excluded CHANGELOG files from Doxygen documentation --- DEBUGGING.md | 4 ++ Detectors/AOD/README.md | 4 ++ Detectors/CTP/workflowScalers/README.md | 4 ++ Detectors/FIT/FT0/base/README.md | 4 ++ Detectors/FIT/FV0/base/README.md | 4 ++ Detectors/FIT/FV0/reconstruction/README.md | 4 ++ Detectors/FIT/README.md | 3 ++ Detectors/HMPID/README.md | 1 + Detectors/HMPID/calibration/README.md | 6 ++- Detectors/MUON/MCH/README.md | 40 ++++++++++--------- Detectors/MUON/MCH/Simulation/README.md | 4 ++ Detectors/MUON/MCH/Status/README.md | 4 ++ Detectors/MUON/MID/README.md | 2 + Detectors/README.md | 2 + .../TPC/calibration/SpacePoints/README.md | 4 ++ Detectors/TPC/calibration/doc/README.md | 9 +++-- Detectors/TRD/README.md | 1 + Detectors/TRD/pid/README.md | 4 ++ Detectors/TRD/reconstruction/README.md | 2 +- Detectors/Upgrades/ALICE3/README.md | 4 ++ Detectors/Upgrades/README.md | 1 + Detectors/ZDC/calib/testWorkflow/README.md | 2 +- doc/README.md | 1 + doc/doxyfile-with-graphs.in | 3 +- doc/doxyfile.in | 3 +- run/SimExamples/README.md | 5 ++- .../Selective_Transport_pi0/Readme.md | 4 ++ 27 files changed, 101 insertions(+), 28 deletions(-) diff --git a/DEBUGGING.md b/DEBUGGING.md index cda0d2a94ed81..c782b99987ef9 100644 --- a/DEBUGGING.md +++ b/DEBUGGING.md @@ -1,3 +1,7 @@ + + # How do I run in debug mode? By default, O2 builds with optimizations (`-O2`) turned on, while leaving debug symbols available. diff --git a/Detectors/AOD/README.md b/Detectors/AOD/README.md index 44104796904d2..42a9840fabc04 100644 --- a/Detectors/AOD/README.md +++ b/Detectors/AOD/README.md @@ -1,3 +1,7 @@ + + # AOD producers The code in this directory is meant to produce `AO2D.root` output diff --git a/Detectors/CTP/workflowScalers/README.md b/Detectors/CTP/workflowScalers/README.md index 4b109f779dc1d..df8df2c55cc44 100644 --- a/Detectors/CTP/workflowScalers/README.md +++ b/Detectors/CTP/workflowScalers/README.md @@ -1,3 +1,7 @@ + + How to generate c++ proto files ? On the computer where project https://gitlab.cern.ch/aliceCTP3/ctp3-ipbus/-/tree/master diff --git a/Detectors/FIT/FT0/base/README.md b/Detectors/FIT/FT0/base/README.md index 57432326eeed3..2ac1732118237 100644 --- a/Detectors/FIT/FT0/base/README.md +++ b/Detectors/FIT/FT0/base/README.md @@ -1,3 +1,7 @@ + + # FT0 Base ## Geometry diff --git a/Detectors/FIT/FV0/base/README.md b/Detectors/FIT/FV0/base/README.md index 98eb0b1988565..1fba33c47b690 100644 --- a/Detectors/FIT/FV0/base/README.md +++ b/Detectors/FIT/FV0/base/README.md @@ -1,3 +1,7 @@ + + # FV0 Base ## Geometry diff --git a/Detectors/FIT/FV0/reconstruction/README.md b/Detectors/FIT/FV0/reconstruction/README.md index f948b9cfd643e..46de9800fda92 100644 --- a/Detectors/FIT/FV0/reconstruction/README.md +++ b/Detectors/FIT/FV0/reconstruction/README.md @@ -1,3 +1,7 @@ + + # FV0 reconstruction Please note that this readme shows how the reconstruction is done _at the moment_. The current reconstruction is not necessarily done the way it _should be_. The algorithm is under review and subject to change. diff --git a/Detectors/FIT/README.md b/Detectors/FIT/README.md index b079dce2cc972..8da3f32d7f4e2 100644 --- a/Detectors/FIT/README.md +++ b/Detectors/FIT/README.md @@ -9,6 +9,9 @@ This is a top page for the FIT detector documentation. diff --git a/Detectors/HMPID/README.md b/Detectors/HMPID/README.md index 775f2ad24d77c..3a744b72812ea 100644 --- a/Detectors/HMPID/README.md +++ b/Detectors/HMPID/README.md @@ -8,4 +8,5 @@ This is a top page for the HMPID detector documentation. diff --git a/Detectors/HMPID/calibration/README.md b/Detectors/HMPID/calibration/README.md index 674ff2eca1265..a9a08309bb061 100644 --- a/Detectors/HMPID/calibration/README.md +++ b/Detectors/HMPID/calibration/README.md @@ -1,4 +1,8 @@ -#HMPID calibration + + +# HMPID calibration For a local test, use diff --git a/Detectors/MUON/MCH/README.md b/Detectors/MUON/MCH/README.md index 997ee3814d71c..af31c15a746cb 100644 --- a/Detectors/MUON/MCH/README.md +++ b/Detectors/MUON/MCH/README.md @@ -7,23 +7,25 @@ This is a top page for the MCH detector documentation. diff --git a/Detectors/MUON/MCH/Simulation/README.md b/Detectors/MUON/MCH/Simulation/README.md index 06f512d02020e..a04520141e327 100644 --- a/Detectors/MUON/MCH/Simulation/README.md +++ b/Detectors/MUON/MCH/Simulation/README.md @@ -1,3 +1,7 @@ + + # How to make a simulation including MCH ## Only MCH diff --git a/Detectors/MUON/MCH/Status/README.md b/Detectors/MUON/MCH/Status/README.md index dc2600d43c5c8..5e29dab124c87 100644 --- a/Detectors/MUON/MCH/Status/README.md +++ b/Detectors/MUON/MCH/Status/README.md @@ -1,3 +1,7 @@ + + # MCH StatusMap The status map is an object that list all pads that are not perfect, for some reason. Each such pad gets ascribed a `uint32_t` integer mask, representing the source of information that was used to decide that pad is bad. diff --git a/Detectors/MUON/MID/README.md b/Detectors/MUON/MID/README.md index a7d6e0030a7ff..d3cc0f92d5f66 100644 --- a/Detectors/MUON/MID/README.md +++ b/Detectors/MUON/MID/README.md @@ -7,7 +7,9 @@ This is a top page for the MID detector documentation. + # TPC average distortion correction The average correction for TPC space charge distortions is based on residuals of TPC clusters with respect to global ITS-TPC-TRD-TOF tracks. diff --git a/Detectors/TPC/calibration/doc/README.md b/Detectors/TPC/calibration/doc/README.md index 919ca36a75bc6..48c5f5fa66230 100644 --- a/Detectors/TPC/calibration/doc/README.md +++ b/Detectors/TPC/calibration/doc/README.md @@ -1,8 +1,11 @@ # TPC Calibration diff --git a/Detectors/TRD/README.md b/Detectors/TRD/README.md index 0c323e348e181..c7292d690003c 100644 --- a/Detectors/TRD/README.md +++ b/Detectors/TRD/README.md @@ -8,5 +8,6 @@ * \subpage refDetectorsTRDcalibration * \subpage refDetectorsTRDsimulation * \subpage refDetectorsTRDreconstruction +* \subpage refDetectorsTRDpid * \subpage refDetectorsTRDworkflow /doxy --> diff --git a/Detectors/TRD/pid/README.md b/Detectors/TRD/pid/README.md index 27101dae09eb1..0807dad4802fd 100644 --- a/Detectors/TRD/pid/README.md +++ b/Detectors/TRD/pid/README.md @@ -1,3 +1,7 @@ + + # Particle Identification with TRD ## Usage Activate PID during tracking with the '--with-pid' flag. diff --git a/Detectors/TRD/reconstruction/README.md b/Detectors/TRD/reconstruction/README.md index f4d4f2420ee5a..ba7de48cdbbd8 100644 --- a/Detectors/TRD/reconstruction/README.md +++ b/Detectors/TRD/reconstruction/README.md @@ -1,5 +1,5 @@ # TRD Reconstruction diff --git a/Detectors/Upgrades/ALICE3/README.md b/Detectors/Upgrades/ALICE3/README.md index 50789a546377f..7e1e1c03718d8 100644 --- a/Detectors/Upgrades/ALICE3/README.md +++ b/Detectors/Upgrades/ALICE3/README.md @@ -1,3 +1,7 @@ + + # ALICE 3 full simulation ## Simulation diff --git a/Detectors/Upgrades/README.md b/Detectors/Upgrades/README.md index 4b071e6a87816..febcb18e746be 100644 --- a/Detectors/Upgrades/README.md +++ b/Detectors/Upgrades/README.md @@ -17,6 +17,7 @@ ENABLE_UPGRADES=ON aliBuild build O2 --defaults o2 Currently two sections are included: # zdc calibration workflows diff --git a/doc/README.md b/doc/README.md index 68520ab356009..6ceae4b7d365e 100644 --- a/doc/README.md +++ b/doc/README.md @@ -11,6 +11,7 @@ This module contains the documentation pages. * \subpage refdocCMakeInstructions * \subpage refdocModernCMakeMigration * \subpage refdocCodeOrganization +* \subpage refdocDebugging * \subpage refdocDetectorSimulation * \subpage refdocDoxygenInstructions * \subpage refdocManPages diff --git a/doc/doxyfile-with-graphs.in b/doc/doxyfile-with-graphs.in index d60d01d5bcb59..75f18b7c54e72 100644 --- a/doc/doxyfile-with-graphs.in +++ b/doc/doxyfile-with-graphs.in @@ -83,6 +83,7 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES +SHOW_EXAMPLES = NO FILE_VERSION_FILTER = LAYOUT_FILE = CITE_BIB_FILES = @@ -109,7 +110,7 @@ EXCLUDE = .git/ \ html-docs/ \ doxygen cmake config gconfig geometry input parameters .svn vis EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = G__* ClassImp build_* +EXCLUDE_PATTERNS = G__* ClassImp build_* CHANGELOG* EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = diff --git a/doc/doxyfile.in b/doc/doxyfile.in index 08b7d37770b20..1e89f1ac1d958 100644 --- a/doc/doxyfile.in +++ b/doc/doxyfile.in @@ -83,6 +83,7 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES +SHOW_EXAMPLES = NO FILE_VERSION_FILTER = LAYOUT_FILE = CITE_BIB_FILES = @@ -109,7 +110,7 @@ EXCLUDE = .git/ \ html-docs/ \ doxygen cmake config gconfig geometry input parameters .svn vis EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = G__* ClassImp build_* +EXCLUDE_PATTERNS = G__* ClassImp build_* CHANGELOG* EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = diff --git a/run/SimExamples/README.md b/run/SimExamples/README.md index 13386d0baed97..5615848202fca 100644 --- a/run/SimExamples/README.md +++ b/run/SimExamples/README.md @@ -15,11 +15,14 @@ * \subpage refrunSimExamplesHepMC * \subpage refrunSimExamplesHepMC_STARlight * \subpage refrunSimExamplesJet_Embedding_Pythia8 -* \subpage refrunSimExamplesStepMonitoringSimple1 +* \subpage refrunSimExamplesMcTracksToAOD +* \subpage refrunSimExamplesMcTracksToAOD +* \subpage refrunSimExamplesPythia * \subpage refrunSimExamplesForceDecay_Lambda_Neutron_Dalitz * \subpage refrunSimExamplesJustPrimaryKinematics * \subpage refrunSimExamplesSelective_Transport * \subpage refrunSimExamplesSelective_Transport_pi0 +* \subpage refrunSimExamplesStepMonitoringSimple1 * \subpage refrunSimExamplesCustom_EventInfo * \subpage refrunSimExamplesMCTrackToDPL * \subpage refrunSimExamplesTParticle diff --git a/run/SimExamples/Selective_Transport_pi0/Readme.md b/run/SimExamples/Selective_Transport_pi0/Readme.md index 56df617faafd9..77dc700ed455e 100644 --- a/run/SimExamples/Selective_Transport_pi0/Readme.md +++ b/run/SimExamples/Selective_Transport_pi0/Readme.md @@ -1,3 +1,7 @@ + + This is a simulation example showing how to run simulation and selectively transport particles through the detector geometry according to configurable settings and how to use the external event trigger mechanism on generators. From 49824b63cd7fa54bc92ef80d92e1eda8f7aa433b Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 30 Apr 2024 19:12:54 +0200 Subject: [PATCH 0195/2997] V0: Fix wrong V0 Photon TPConly cut Reported by @shahor02. --- Detectors/Vertexing/src/SVertexer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx index 0516bc2bcc182..e09135e69c516 100644 --- a/Detectors/Vertexing/src/SVertexer.cxx +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -1328,7 +1328,7 @@ bool SVertexer::processTPCTrack(const o2::tpc::TrackTPC& trTPC, GIndex gid, int // require minimum of tpc clusters bool dCls = trTPC.getNClusters() < mSVParams->mTPCTrackMinNClusters; // check track z cuts - bool dDPV = std::abs(trLoc.getX() * trLoc.getTgl() - trLoc.getZ() - vtx.getZ()) > mSVParams->mTPCTrack2Beam; + bool dDPV = std::abs(trLoc.getX() * trLoc.getTgl() - trLoc.getZ() + vtx.getZ()) > mSVParams->mTPCTrack2Beam; // check track transveres cuts float sna{0}, csa{0}; o2::math_utils::CircleXYf_t trkCircle; From fc2b9e459d745c45bd3387691849e49b486f26bf Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 30 Apr 2024 23:43:09 +0200 Subject: [PATCH 0196/2997] Optionally skip PV validation by interacting BC --- .../src/PrimaryVertexingSpec.cxx | 9 ++-- .../include/DetectorsVertexing/PVertexer.h | 16 ++++-- .../DetectorsVertexing/PVertexerParams.h | 2 + Detectors/Vertexing/src/PVertexer.cxx | 49 ++++++++++++------- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx index 23c1010c994ce..6b83f787be17d 100644 --- a/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx @@ -161,11 +161,12 @@ void PrimaryVertexingSpec::run(ProcessingContext& pc) } mTimer.Stop(); - LOGP(info, "Found {} PVs, Time CPU/Real:{:.3f}/{:.3f} (DBScan: {:.4f}, Finder:{:.4f}, MADSel:{:.4f}, Rej.Debris:{:.4f}, Reattach:{:.4f}) | {} trials for {} TZ-clusters, max.trials: {}, Slowest TZ-cluster: {} ms of mult {}", + LOGP(info, "Found {} PVs, Time CPU/Real:{:.3f}/{:.3f} (DBScan: {:.4f}, Finder:{:.4f}, MADSel:{:.4f}, Rej.Debris:{:.4f}, Reattach:{:.4f}) | {} trials for {} TZ-clusters, max.trials: {}, Slowest TZ-cluster: {} ms of mult {} | NInitial:{}, Rejections: NoFilledBC:{}, NoIntCand:{}, Debris:{}, Quality:{}, ITSOnly:{}", vertices.size(), mTimer.CpuTime() - timeCPU0, mTimer.RealTime() - timeReal0, - mVertexer.getTimeDBScan().CpuTime(), mVertexer.getTimeVertexing().CpuTime(), mVertexer.getTimeMADSel().CpuTime(), mVertexer.getTimeDebris().CpuTime(), mVertexer.getTimeReAttach().CpuTime(), - mVertexer.getTotTrials(), mVertexer.getNTZClusters(), mVertexer.getMaxTrialsPerCluster(), - mVertexer.getLongestClusterTimeMS(), mVertexer.getLongestClusterMult()); + mVertexer.getTimeDBScan().CpuTime(), mVertexer.getTimeVertexing().CpuTime(), mVertexer.getTimeMADSel().CpuTime(), mVertexer.getTimeDebris().CpuTime(), + mVertexer.getTimeReAttach().CpuTime(), mVertexer.getTotTrials(), mVertexer.getNTZClusters(), mVertexer.getMaxTrialsPerCluster(), + mVertexer.getLongestClusterTimeMS(), mVertexer.getLongestClusterMult(), mVertexer.getNIniFound(), + mVertexer.getNKilledBCValid(), mVertexer.getNKilledIntCand(), mVertexer.getNKilledDebris(), mVertexer.getNKilledQuality(), mVertexer.getNKilledITSOnly()); } void PrimaryVertexingSpec::endOfStream(EndOfStreamContext& ec) diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h index e15dafbe108f8..9967cbfcd5642 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h @@ -119,6 +119,12 @@ class PVertexer auto getMaxTrialsPerCluster() const { return mMaxTrialPerCluster; } auto getLongestClusterMult() const { return mLongestClusterMult; } auto getLongestClusterTimeMS() const { return mLongestClusterTimeMS; } + auto getNKilledBCValid() const { return mNKilledBCValid; } + auto getNKilledIntCand() const { return mNKilledIntCand; } + auto getNKilledDebris() const { return mNKilledDebris; } + auto getNKilledQuality() const { return mNKilledQuality; } + auto getNKilledITSOnly() const { return mNKilledITSOnly; } + auto getNIniFound() const { return mNIniFound; } TStopwatch& getTimeDBScan() { return mTimeDBScan; } TStopwatch& getTimeVertexing() { return mTimeVertexing; } @@ -184,9 +190,7 @@ class PVertexer float mDBScanDeltaT = 0.; ///< deltaT cut for DBScan check float mDBSMaxZ2InvCorePoint = 0; ///< inverse of max sigZ^2 of the track which can be core point in the DBScan bool mValidateWithIR = false; ///< require vertex validation with InteractionCandidates (if available) - - o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF - + o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF // structure for the vertex refit o2d::VertexBase mVtxRefitOrig{}; ///< original vertex whose tracks are refitted std::vector mRefitTrackIDs{}; ///< dummy IDs for refitted tracks @@ -201,6 +205,12 @@ class PVertexer static constexpr float kHugeF = 1.e12; ///< very large float static constexpr float kAlmost0F = 1e-12; ///< tiny float static constexpr double kAlmost0D = 1e-16; ///< tiny double + int mNIniFound = 0; + int mNKilledBCValid = 0; + int mNKilledIntCand = 0; + int mNKilledDebris = 0; + int mNKilledQuality = 0; + int mNKilledITSOnly = 0; size_t mNTZClustersIni = 0; size_t mTotTrials = 0; size_t mMaxTrialPerCluster = 0; diff --git a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h index cc372b4f6c301..f7beb009a766d 100644 --- a/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h +++ b/Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h @@ -102,6 +102,8 @@ struct PVertexerParams : public o2::conf::ConfigurableParamHelper gids, const gsl: mMaxTrialPerCluster = 0; mLongestClusterTimeMS = 0; mLongestClusterMult = 0; + mNIniFound = 0; + mNKilledBCValid = 0; + mNKilledIntCand = 0; + mNKilledDebris = 0; + mNKilledQuality = 0; + mNKilledITSOnly = 0; mPoolDumpProduced = false; std::vector verticesLoc; @@ -82,6 +88,7 @@ int PVertexer::runVertexing(const gsl::span gids, const gsl: createMCLabels(lblTracks, trackIDs, v2tRefsLoc, lblVtxLoc); } #endif + mNIniFound = verticesLoc.size(); if (mValidateWithIR && mPVParams->minNContributorsForIRcutIni >= 0) { applInteractionValidation(verticesLoc, vtTimeSortID, intCand, mPVParams->minNContributorsForIRcutIni); @@ -126,6 +133,7 @@ int PVertexer::runVertexing(const gsl::span gids, const gsl: auto& vtx = verticesLoc[i]; if (!setCompatibleIR(vtx)) { i = -1; + mNKilledBCValid++; } } // do we need to validate by Int. records ? @@ -576,6 +584,7 @@ void PVertexer::applyMADSelection(std::vector& vertices, std::vector mPVParams->maxTMAD || tmad < mPVParams->minTMAD) { timeSort[ivt] = -1; // disable vertex + mNKilledQuality++; LOGP(debug, "Killing vertex {} with TMAD {}, {} of {} killed", iv, tmad, ++nkill, nv); continue; } @@ -590,6 +599,7 @@ void PVertexer::applyMADSelection(std::vector& vertices, std::vector mPVParams->maxZMAD || zmad < mPVParams->minZMAD) { timeSort[ivt] = -1; // disable vertex + mNKilledQuality++; LOGP(debug, "Killing vertex {} with ZMAD {}, {} of {} killed", iv, zmad, ++nkill, nv); continue; } @@ -621,6 +631,7 @@ void PVertexer::applITSOnlyFractionCut(std::vector& vertices, std::vect float frac = nITS / float(trefs.getEntries()); if (frac > mPVParams->maxITSOnlyFraction || frac < mPVParams->minITSOnlyFraction) { timeSort[ivt] = -1; // disable vertex + mNKilledITSOnly++; } } } @@ -669,6 +680,7 @@ void PVertexer::applInteractionValidation(std::vector& vertices, std::v } } else if (pv.getNContributors() >= minContrib) { timeSort[ivt] = -1; // discard + mNKilledIntCand++; } } } @@ -724,6 +736,7 @@ void PVertexer::reduceDebris(std::vector& vertices, std::vector& t } if (rej) { timeSort[j] = -1; + mNKilledDebris++; vtJ.setNContributors(0); } return false; @@ -964,7 +977,7 @@ void PVertexer::setBunchFilling(const o2::BunchFilling& bf) bool PVertexer::setCompatibleIR(PVertex& vtx) { // assign compatible IRs accounting for the bunch filling scheme - if (mClosestBunchAbove[0] < 0) { // empty or no BF was provided + if (mClosestBunchAbove[0] < 0 && mPVParams->doBCValidation) { // empty or no BF was provided return false; } const auto& vtxT = vtx.getTimeStamp(); @@ -979,22 +992,24 @@ bool PVertexer::setCompatibleIR(PVertex& vtx) } irMax += o2::InteractionRecord(1.e3 * (t + rangeT)); // RS TODO: make sure that irMax does not exceed TF edge irMax++; // to account for rounding - // restrict using bunch filling - int bc = mClosestBunchAbove[irMin.bc]; - LOG(debug) << "irMin.bc = " << irMin.bc << " bcAbove = " << bc; - if (bc < irMin.bc) { - irMin.orbit++; - } - irMin.bc = bc; - bc = mClosestBunchBelow[irMax.bc]; - LOG(debug) << "irMax.bc = " << irMax.bc << " bcBelow = " << bc; - if (bc > irMax.bc) { - if (irMax.orbit == 0) { - return false; - } - irMax.orbit--; - } - irMax.bc = bc; + if (mPVParams->doBCValidation) { + // restrict using bunch filling + int bc = mClosestBunchAbove[irMin.bc]; + LOG(debug) << "irMin.bc = " << irMin.bc << " bcAbove = " << bc; + if (bc < irMin.bc) { + irMin.orbit++; + } + irMin.bc = bc; + bc = mClosestBunchBelow[irMax.bc]; + LOG(debug) << "irMax.bc = " << irMax.bc << " bcBelow = " << bc; + if (bc > irMax.bc) { + if (irMax.orbit == 0) { + return false; + } + irMax.orbit--; + } + irMax.bc = bc; + } vtx.setIRMin(irMin); vtx.setIRMax(irMax); if (irMin > irMax) { From 67e9df494a525c9265306b732c9fade84f40a951 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 1 May 2024 18:32:04 +0200 Subject: [PATCH 0197/2997] Fix: copy original v0 if refit is not required --- Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx index 9ea30577dc579..c1fa8b51b9d57 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx @@ -157,6 +157,9 @@ o2::dataformats::V0Ext SVStudySpec::processV0(int iv, o2::globaltracking::RecoCo invalidate(); return v0ext; } + if (!mRefit) { + v0ext.v0 = v0sel; + } v0ext.v0ID = v0id; for (int ip = 0; ip < 2; ip++) { auto& prInfo = v0ext.prInfo[ip]; From 7f0abfba4ebaaa4e1474f4748e9ea9d8cfa9a359 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 2 May 2024 13:01:52 +0200 Subject: [PATCH 0198/2997] DPL: improve instrumentation for the preProcessingCallbacks (#13104) --- Framework/Core/src/DataProcessingDevice.cxx | 1 + Framework/Core/src/StreamContext.cxx | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index d6b73bc7476f8..bb3858a9d3ed2 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -2321,6 +2321,7 @@ bool DataProcessingDevice::tryDispatchComputation(ServiceRegistryRef ref, std::v *context.registry}; ProcessingContext processContext{record, ref, ref.get()}; { + O2_SIGNPOST_EVENT_EMIT(device, aid, "device", "Invoking preProcessingCallbacks"); // Notice this should be thread safe and reentrant // as it is called from many threads. streamContext.preProcessingCallbacks(processContext); diff --git a/Framework/Core/src/StreamContext.cxx b/Framework/Core/src/StreamContext.cxx index 2ce0c1c427cbd..0712025849447 100644 --- a/Framework/Core/src/StreamContext.cxx +++ b/Framework/Core/src/StreamContext.cxx @@ -31,12 +31,17 @@ void StreamContext::preStartStreamCallbacks(ServiceRegistryRef ref) /// Invoke callbacks to be executed before every process method invokation void StreamContext::preProcessingCallbacks(ProcessingContext& pcx) { + O2_SIGNPOST_ID_FROM_POINTER(dpid, stream_context, &pcx); + O2_SIGNPOST_START(stream_context, dpid, "callbacks", "Starting StreamContext preProcessingCallbacks"); for (auto& handle : preProcessingHandles) { - LOG(debug) << "Invoking preProcessingCallbacks for" << handle.service; + O2_SIGNPOST_ID_FROM_POINTER(cid, stream_context, handle.service); + O2_SIGNPOST_START(stream_context, cid, "callbacks", "Starting StreamContext::preProcessingCallbacks for service %{public}s", handle.spec.name.c_str()); assert(handle.service); assert(handle.callback); handle.callback(pcx, handle.service); + O2_SIGNPOST_END(stream_context, cid, "callbacks", "Ending StreamContext::preProcessingCallbacks for service %{public}s", handle.spec.name.c_str()); } + O2_SIGNPOST_END(stream_context, dpid, "callbacks", "Ending StreamContext preProcessingCallbacks"); } /// Invoke callbacks to be executed after every process method invokation From 01cb9e93d90f51e2b9b1cace4d6ce2ada479eab9 Mon Sep 17 00:00:00 2001 From: Nicolo Valle Date: Tue, 30 Apr 2024 00:24:48 +0200 Subject: [PATCH 0199/2997] [WIP] ITS Fix for online dead map builder --- .../ITSMFTReconstruction/RUDecodeData.h | 40 ++++++++++--------- .../reconstruction/src/RawPixelDecoder.cxx | 2 + 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h index 0f2725821b1f8..c15a8bc82d117 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h @@ -34,23 +34,23 @@ struct RUDecodeData { static constexpr int MaxChipsPerRU = 196; // max number of chips the RU can readout static constexpr int MaxLinksPerRU = 3; // max number of GBT links per RU - std::array cableData{}; // cable data in compressed ALPIDE format - std::vector chipsData{}; // fully decoded data in 1st nChipsFired chips - std::vector seenChipIDs{}; // IDs of all chips seen during ROF decoding, including empty ones - std::array links{}; // link entry RSTODO: consider removing this and using pointer - std::array cableHWID{}; // HW ID of cable whose data is in the corresponding slot of cableData - std::array cableLinkID{}; // ID of the GBT link transmitting this cable data - std::array cableLinkPtr{}; // Ptr of the GBT link transmitting this cable data - std::unordered_map linkHBFToDump{}; // FEEID<<32+hbfEntry to dump in case of error - int ruSWID = -1; // SW (stave) ID - int nChipsFired = 0; // number of chips with data or with errors - int lastChipChecked = 0; // last chips checked among nChipsFired - int nNonEmptyLinks = 0; // number of non-empty links for current ROF - int nLinks = 0; // number of links seen for this TF - int nLinksDone = 0; // number of links finished for this TF - int verbosity = 0; // verbosity level, for -1,0 print only summary data, for 1: print once every error - bool ROFRampUpStage = false; // flag that the data come from the ROF rate ramp-up stage - GBTCalibData calibData{}; // calibration info from GBT calibration word + std::array cableData{}; // cable data in compressed ALPIDE format + std::vector chipsData{}; // fully decoded data in 1st nChipsFired chips + std::vector seenChipIDs{}; // IDs of all chips seen during ROF decoding, including empty ones + std::array links{}; // link entry RSTODO: consider removing this and using pointer + std::array cableHWID{}; // HW ID of cable whose data is in the corresponding slot of cableData + std::array cableLinkID{}; // ID of the GBT link transmitting this cable data + std::array cableLinkPtr{}; // Ptr of the GBT link transmitting this cable data + std::unordered_map linkHBFToDump{}; // FEEID<<32+hbfEntry to dump in case of error + int ruSWID = -1; // SW (stave) ID + int nChipsFired = 0; // number of chips with data or with errors + int lastChipChecked = 0; // last chips checked among nChipsFired + int nNonEmptyLinks = 0; // number of non-empty links for current ROF + int nLinks = 0; // number of links seen for this TF + int nLinksDone = 0; // number of links finished for this TF + int verbosity = 0; // verbosity level, for -1,0 print only summary data, for 1: print once every error + bool ROFRampUpStage = false; // flag that the data come from the ROF rate ramp-up stage + GBTCalibData calibData{}; // calibration info from GBT calibration word std::unordered_map> chipErrorsTF{}; // vector of chip decoding errors seen in the given TF const RUInfo* ruInfo = nullptr; @@ -59,6 +59,10 @@ struct RUDecodeData { memset(&links[0], -1, MaxLinksPerRU * sizeof(int)); } void clear(); + void clearSeenChipIDs() + { + seenChipIDs.clear(); + } void setROFInfo(ChipPixelData* chipData, const GBTLink* lnk); template int decodeROF(const Mapping& mp, const o2::InteractionRecord ir); @@ -90,7 +94,7 @@ int RUDecodeData::decodeROF(const Mapping& mp, const o2::InteractionRecord ir) } auto cabHW = cableHWID[icab]; auto chIdGetter = [this, &mp, cabHW](int cid) { - //return mp.getGlobalChipID(cid, cabHW, *this->ruInfo); + // return mp.getGlobalChipID(cid, cabHW, *this->ruInfo); auto chip = mp.getGlobalChipID(cid, cabHW, *this->ruInfo); return chip; }; diff --git a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx index b0db826fd30b1..9cd5d8e0054bd 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/RawPixelDecoder.cxx @@ -111,6 +111,8 @@ int RawPixelDecoder::decodeNextTrigger() ru.ROFRampUpStage = mROFRampUpStage; mNPixelsFiredROF += ru.decodeROF(mMAP, mInteractionRecord); mNChipsFiredROF += ru.nChipsFired; + } else { + ru.clearSeenChipIDs(); } } From ca74488bf526ade0ea457d92e17cf69c66a23f47 Mon Sep 17 00:00:00 2001 From: Nicolo Valle Date: Tue, 30 Apr 2024 13:35:27 +0200 Subject: [PATCH 0200/2997] Increasing default value of TF sampling --- .../ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h | 2 +- .../workflow/include/ITSMFTWorkflow/DeadMapBuilderSpec.h | 2 +- Detectors/ITSMFT/common/workflow/src/DeadMapBuilderSpec.cxx | 4 ++-- prodtests/full-system-test/dpl-workflow.sh | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h index 6afcb258e76b6..a0b214f705d7c 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h @@ -132,7 +132,7 @@ class TimeDeadMap LOG(warning) << "Requested orbit " << orbit << "from an empty time-dependent map. Doing nothing"; return (long)orbit; } - auto closest = mEvolvingDeadMap.lower_bound(orbit); + auto closest = mEvolvingDeadMap.upper_bound(orbit); if (closest != mEvolvingDeadMap.begin()) { --closest; mmap = closest->second; diff --git a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DeadMapBuilderSpec.h b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DeadMapBuilderSpec.h index 99dca8475f2a6..14f4575ee972c 100644 --- a/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DeadMapBuilderSpec.h +++ b/Detectors/ITSMFT/common/workflow/include/ITSMFTWorkflow/DeadMapBuilderSpec.h @@ -107,7 +107,7 @@ class ITSMFTDeadMapBuilder : public Task std::string mDataSource = "chipsstatus"; - int mTFSampling = 1000; + int mTFSampling = 350; std::string mSamplingMode = "first-orbit-run"; // Use this default to ensure process of first TF. At the moment, use any other option to sample on absolute orbit value. o2::itsmft::TimeDeadMap mMapObject; diff --git a/Detectors/ITSMFT/common/workflow/src/DeadMapBuilderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/DeadMapBuilderSpec.cxx index 362787500a617..8bb86a547fb25 100644 --- a/Detectors/ITSMFT/common/workflow/src/DeadMapBuilderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/DeadMapBuilderSpec.cxx @@ -284,7 +284,7 @@ void ITSMFTDeadMapBuilder::PrepareOutputCcdb(EndOfStreamContext* ec, std::string else if (!ccdburl.empty()) { // send from this workflow - LOG(important) << mSelfName << "sending object " << ccdburl << "/browse/" << info.getPath() << "/" << info.getFileName() + LOG(important) << mSelfName << " sending object " << ccdburl << "/browse/" << info.getPath() << "/" << info.getFileName() << " of size " << image->size() << " bytes, valid for " << info.getStartValidityTimestamp() << " : " << info.getEndValidityTimestamp(); @@ -378,7 +378,7 @@ DataProcessorSpec getITSMFTDeadMapBuilderSpec(std::string datasource, bool doMFT inputs, outputs, AlgorithmSpec{adaptFromTask(datasource, doMFT)}, - Options{{"tf-sampling", VariantType::Int, 1000, {"Process every Nth TF. Selection according to first TF orbit."}}, + Options{{"tf-sampling", VariantType::Int, 350, {"Process every Nth TF. Selection according to first TF orbit."}}, {"sampling-mode", VariantType::String, "first-orbit-run", {"Use absolute orbit value or offset from first processed orbit."}}, {"tf-length", VariantType::Int, 32, {"Orbits per TF."}}, {"skip-static-map", VariantType::Bool, false, {"Do not fill static part of the map."}}, diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index c3554b4c6b1a6..a5d0b290e11a5 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -633,8 +633,8 @@ workflow_has_parameter AOD && [[ ! -z "$AOD_SOURCES" ]] && add_W o2-aod-producer # extra workflows in case we want to extra ITS/MFT info for dead channel maps to then go to CCDB for MC : ${ALIEN_JDL_PROCESSITSDEADMAP:=} : ${ALIEN_JDL_PROCESSMFTDEADMAP:=} -[[ $ALIEN_JDL_PROCESSITSDEADMAP == 1 ]] && has_detector ITS && add_W o2-itsmft-deadmap-builder-workflow " --local-output --output-dir . --source clusters --tf-sampling 1000" -[[ $ALIEN_JDL_PROCESSMFTDEADMAP == 1 ]] && has_detector MFT && add_W o2-itsmft-deadmap-builder-workflow " --runmft --local-output --output-dir . --source clusters --tf-sampling 1000" +[[ $ALIEN_JDL_PROCESSITSDEADMAP == 1 ]] && has_detector ITS && add_W o2-itsmft-deadmap-builder-workflow " --local-output --output-dir . --source clusters --tf-sampling 350" +[[ $ALIEN_JDL_PROCESSMFTDEADMAP == 1 ]] && has_detector MFT && add_W o2-itsmft-deadmap-builder-workflow " --runmft --local-output --output-dir . --source clusters --tf-sampling 350" # --------------------------------------------------------------------------------------------------------------------- From c28cbd15b6e3d1f8f14a0277110641bd4bfbb580 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 2 May 2024 20:19:18 +0200 Subject: [PATCH 0201/2997] DPL: add test to verify crashing workflows (#13102) --- Framework/Core/CMakeLists.txt | 6 ++ Framework/Core/test/test_AllCrashTypes.sh | 23 +++++ Framework/Core/test/test_CrashingWorkflow.cxx | 88 +++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100755 Framework/Core/test/test_AllCrashTypes.sh create mode 100644 Framework/Core/test/test_CrashingWorkflow.cxx diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index d153fe9b4184e..fabb62eb6530d 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -281,6 +281,11 @@ o2_add_test(O2DatabasePDG NAME test_Framework_test_O2DatabasePDG LABELS framework PUBLIC_LINK_LIBRARIES O2::Framework O2::FrameworkPhysicsSupport) +o2_add_executable(crashing-workflow + SOURCES test/test_CrashingWorkflow.cxx + COMPONENT_NAME Framework + PUBLIC_LINK_LIBRARIES O2::Framework) + # All the tests which require ROOT to work add_executable(o2-test-framework-root test/test_Root2ArrowTable.cxx @@ -290,6 +295,7 @@ target_link_libraries(o2-test-framework-root PRIVATE O2::Catch2) target_link_libraries(o2-test-framework-root PRIVATE ROOT::ROOTDataFrame) set_property(TARGET o2-test-framework-root PROPERTY RUNTIME_OUTPUT_DIRECTORY ${outdir}) add_test(NAME framework:root COMMAND o2-test-framework-root --skip-benchmarks) +add_test(NAME framework:crash COMMAND sh -e -c "PATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}:$PATH ${CMAKE_CURRENT_LIST_DIR}/test/test_AllCrashTypes.sh") o2_add_test(InfoLogger NAME test_Framework_test_InfoLogger SOURCES test/test_InfoLogger.cxx diff --git a/Framework/Core/test/test_AllCrashTypes.sh b/Framework/Core/test/test_AllCrashTypes.sh new file mode 100755 index 0000000000000..52c8e62ee8469 --- /dev/null +++ b/Framework/Core/test/test_AllCrashTypes.sh @@ -0,0 +1,23 @@ +#!/bin/sh -e +echo $PATH +printf "ok\nTesting runtime-init..." +o2-framework-crashing-workflow --crash-type=runtime-init --completion-policy=quit -b --run | grep -q "Exception caught: This is a std::runtime_error" || { printf "runtime error not found" ; exit 1; } +printf "ok\nTesting framework-init..." +o2-framework-crashing-workflow --crash-type=framework-init --completion-policy=quit -b --run | grep -q "Exception caught: This is a o2::framework::runtime_error" || { printf "framework error not found" ; exit 1; } +printf "ok\nTesting framework-run..." +o2-framework-crashing-workflow --crash-type=framework-run --completion-policy=quit -b --run | grep -q "Unhandled o2::framework::runtime_error reached the top of main of o2-framework-crashing-workflow, device shutting down. Reason: This is a o2::framework::runtime_error" || { printf "framework error not found" ; exit 1; } +printf "ok\nTesting runtime-run..." +o2-framework-crashing-workflow --crash-type=runtime-run --completion-policy=quit --run | grep -q "Unhandled o2::framework::runtime_error reached the top of main of o2-framework-crashing-workflow, device shutting down. Reason: This is a std::runtime_error" || { echo "runtime error not found" ; exit 1; } +printf "ok\n" + +export O2_NO_CATCHALL_EXCEPTIONS=1 +echo O2_NO_CATCHALL_EXCEPTIONS enabled +printf "ok\nTesting runtime-init..." +o2-framework-crashing-workflow --crash-type=runtime-init --completion-policy=quit -b --run | grep -v -q "Exception caught: This is a std::runtime_error" || { printf "runtime error not found" ; exit 1; } +printf "ok\nTesting framework-init..." +o2-framework-crashing-workflow --crash-type=framework-init --completion-policy=quit -b --run | grep -v -q "Exception caught: This is a o2::framework::runtime_error" || { printf "framework error not found" ; exit 1; } +printf "ok\nTesting framework-run..." +o2-framework-crashing-workflow --crash-type=framework-run --completion-policy=quit -b --run | grep -v -q "Unhandled o2::framework::runtime_error reached the top of main of o2-framework-crashing-workflow, device shutting down. Reason: This is a o2::framework::runtime_error" || { printf "framework error not found" ; exit 1; } +printf "ok\nTesting runtime-run..." +o2-framework-crashing-workflow --crash-type=runtime-run --completion-policy=quit --run | grep -v -q "Unhandled o2::framework::runtime_error reached the top of main of o2-framework-crashing-workflow, device shutting down. Reason: This is a std::runtime_error" || { echo "runtime error not found" ; exit 1; } +printf "ok" diff --git a/Framework/Core/test/test_CrashingWorkflow.cxx b/Framework/Core/test/test_CrashingWorkflow.cxx new file mode 100644 index 0000000000000..396b48a85c166 --- /dev/null +++ b/Framework/Core/test/test_CrashingWorkflow.cxx @@ -0,0 +1,88 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#include "Framework/ConfigParamSpec.h" +#include "Framework/AlgorithmSpec.h" +#include "Framework/Configurable.h" +#include "Framework/Logger.h" +#include "Framework/CallbackService.h" +#include "Framework/Signpost.h" + +O2_DECLARE_DYNAMIC_LOG(crash_test); + +using namespace o2::framework; + +struct WorkflowOptions { + Configurable crashType{"crash-type", "fatal-init", {"how should this crash? (fatal-init, fatal-run, runtime-init, runtime-fail, abort-init, abort-run)"}}; +}; + +#include "Framework/runDataProcessing.h" + +AlgorithmSpec simpleCrashingSource(std::string const& what) +{ + return AlgorithmSpec{adaptStateful([what](InitContext& ctx) { + O2_SIGNPOST_ID_FROM_POINTER(ii, crash_test, &ctx); + O2_SIGNPOST_START(crash_test, ii, "Init", "Starting Init"); + O2_SIGNPOST_EVENT_EMIT(crash_test, ii, "Init", "%{public}s selected", what.c_str()); + + if (what == "fatal-init") { + LOG(fatal) << "This should have a fatal"; + } else if (what == "runtime-init") { + throw std::runtime_error("This is a std::runtime_error"); + } else if (what == "abort-init") { + abort(); + } else if (what == "framework-init") { + throw o2::framework::runtime_error("This is a o2::framework::runtime_error"); + } else if (what == "framework-prerun") { + ctx.services().get().set([](ServiceRegistryRef, int) { + throw o2::framework::runtime_error("This is o2::framework::runtime_error in PreProcessing"); + }); + } else if (what == "runtime-prerun") { + ctx.services().get().set([](ServiceRegistryRef, int) { + throw std::runtime_error("This is std::runtime_error in PreProcessing"); + }); + } + O2_SIGNPOST_END(crash_test, ii, "Init", "Init Done"); + return adaptStateless([what](ProcessingContext& pCtx) { + O2_SIGNPOST_ID_FROM_POINTER(ri, crash_test, &pCtx); + O2_SIGNPOST_START(crash_test, ri, "Run", "Starting Run"); + O2_SIGNPOST_EVENT_EMIT(crash_test, ri, "Run", "%{public}s selected", what.c_str()); + if (what == "fatal-run") { + LOG(fatal) << "This should have a fatal"; + } else if (what == "runtime-run") { + throw std::runtime_error("This is a std::runtime_error"); + } else if (what == "abort-run") { + abort(); + } else if (what == "framework-run") { + throw o2::framework::runtime_error("This is a o2::framework::runtime_error"); + } + O2_SIGNPOST_EVENT_EMIT_ERROR(crash_test, ri, "Run", "Unknown option for crash-type: %{public}s.", what.c_str()); + O2_SIGNPOST_END(crash_test, ri, "Init", "Run Done"); + exit(1); + }); + })}; +} + +// This is how you can define your processing in a declarative way +WorkflowSpec defineDataProcessing(ConfigContext const& config) +{ + auto crashType = config.options().get("crash-type"); + DataProcessorSpec a{ + .name = "deliberately-crashing", + .outputs = {OutputSpec{{"a1"}, "TST", "A1"}}, + .algorithm = AlgorithmSpec{simpleCrashingSource(crashType)}}; + DataProcessorSpec b{ + .name = "B", + .inputs = {InputSpec{"x", "TST", "A1", Lifetime::Timeframe}}, + .algorithm = AlgorithmSpec{adaptStateless([](ProcessingContext&) {})}}; + + return workflow::concat(WorkflowSpec{a, b}); +} + From 6e3d0300c50259c63d8382792ec960ded7a15c32 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 2 May 2024 16:38:33 +0200 Subject: [PATCH 0202/2997] GPU: Fix compile-warnings in GPU per-kernel compilation with clang --- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index a5e7710739304..5473814610be0 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -57,11 +57,11 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace o2::tpc; -static constexpr float kDeg2Rad = M_PI / 180.f; -static constexpr float kSectAngle = 2 * M_PI / 18.f; - GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger* GPUrestrict() merger, int iTrk, GPUTPCGMMergedTrackHit* GPUrestrict() clusters, GPUTPCGMMergedTrackHitXYZ* GPUrestrict() clustersXYZ, int& GPUrestrict() N, int& GPUrestrict() NTolerated, float& GPUrestrict() Alpha, int attempt, float maxSinPhi, gputpcgmmergertypes::GPUTPCOuterParam* GPUrestrict() outerParam) { + static constexpr float kDeg2Rad = M_PI / 180.f; + CADEBUG(static constexpr float kSectAngle = 2 * M_PI / 18.f); + const GPUParam& GPUrestrict() param = merger->Param(); GPUdEdx dEdx; @@ -425,6 +425,9 @@ GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger* GPUrestrict() merger, int iT GPUdni() void GPUTPCGMTrackParam::MoveToReference(GPUTPCGMPropagator& prop, const GPUParam& param, float& Alpha) { + static constexpr float kDeg2Rad = M_PI / 180.f; + static constexpr float kSectAngle = 2 * M_PI / 18.f; + if (param.rec.tpc.trackReferenceX <= 500) { GPUTPCGMTrackParam save = *this; float saveAlpha = Alpha; @@ -635,6 +638,7 @@ GPUd() float GPUTPCGMTrackParam::AttachClusters(const GPUTPCGMMerger* GPUrestric GPUd() bool GPUTPCGMTrackParam::AttachClustersPropagate(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int lastRow, int toRow, int iTrack, bool goodLeg, GPUTPCGMPropagator& GPUrestrict() prop, bool inFlyDirection, float maxSinPhi, bool dodEdx) { + static constexpr float kSectAngle = 2 * M_PI / 18.f; if (Merger->Param().rec.tpc.disableRefitAttachment & 2) { return dodEdx; } @@ -735,6 +739,7 @@ GPUdii() void GPUTPCGMTrackParam::RefitLoop(const GPUTPCGMMerger* GPUrestrict() template GPUdic(0, 1) int GPUTPCGMTrackParam::FollowCircle(const GPUTPCGMMerger* GPUrestrict() Merger, GPUTPCGMPropagator& GPUrestrict() prop, int slice, int iRow, int iTrack, float toAlpha, float toX, float toY, int toSlice, int toRow, bool inFlyDirection, bool phase2) { + static constexpr float kSectAngle = 2 * M_PI / 18.f; if (Merger->Param().rec.tpc.disableRefitAttachment & 4) { return 1; } @@ -838,6 +843,8 @@ GPUdic(0, 1) int GPUTPCGMTrackParam::FollowCircle(const GPUTPCGMMerger* GPUrestr template GPUdni() void GPUTPCGMTrackParam::AttachClustersMirror(const GPUTPCGMMerger* GPUrestrict() Merger, int slice, int iRow, int iTrack, float toY, GPUTPCGMPropagator& GPUrestrict() prop, bool phase2) { + static constexpr float kSectAngle = 2 * M_PI / 18.f; + if (Merger->Param().rec.tpc.disableRefitAttachment & 8) { return; } From 7a9c10412554c64f505afde74e3f4f43dfca5a54 Mon Sep 17 00:00:00 2001 From: Casper van Veen <96796377+Cas1997@users.noreply.github.com> Date: Fri, 3 May 2024 10:15:08 +0200 Subject: [PATCH 0203/2997] ALICE3: Beam pipe update and TRK & FT3 modifications that follow from it (#13106) * Beam pipe update --- .../include/FT3Simulation/Detector.h | 1 + .../ALICE3/FT3/simulation/src/Detector.cxx | 74 ++++++++++++++++++- .../include/Alice3DetectorsPassive/Pipe.h | 6 +- .../Upgrades/ALICE3/Passive/src/Pipe.cxx | 42 +++++------ .../include/TRKSimulation/Detector.h | 1 + .../ALICE3/TRK/simulation/src/Detector.cxx | 30 +++++++- .../ALICE3/TRK/simulation/src/TRKServices.cxx | 2 +- macro/build_geometry.C | 2 +- 8 files changed, 128 insertions(+), 30 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/Detector.h b/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/Detector.h index ec735a66f4390..a88ea5a351ad2 100644 --- a/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/Detector.h @@ -115,6 +115,7 @@ class Detector : public o2::base::DetImpl void buildFT3V1(); void buildFT3V3b(); void buildFT3Scoping(); + void buildFT3NewVacuumVessel(); void buildFT3FromFile(std::string); GeometryTGeo* mGeometryTGeo; //! access to geometry details diff --git a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx index 625f2b28182c5..296bec8aa8922 100644 --- a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx @@ -277,6 +277,78 @@ void Detector::buildFT3V3b() } } +void Detector::buildFT3NewVacuumVessel() +{ + // Build the FT3 detector according to changes proposed during + // https://indico.cern.ch/event/1407704/ + // to adhere to the changes that were presented at the ALICE 3 Upgrade days in March 2024 + // Inner radius at C-side to 7 cm + // Inner radius at A-side stays at 5 cm + + LOG(info) << "Building FT3 Detector: After Upgrade Days March 2024 version"; + + mNumberOfLayers = 12; + float sensorThickness = 30.e-4; + float layersx2X0 = 1.e-2; + std::vector> layersConfigCSide{ + {26., .5, 2.5, 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0} + {30., .5, 2.5, 0.1f * layersx2X0}, + {34., .5, 2.5, 0.1f * layersx2X0}, + {77., 7.0, 35., layersx2X0}, + {100., 7.0, 35., layersx2X0}, + {122., 7.0, 35., layersx2X0}, + {150., 7.0, 68.f, layersx2X0}, + {180., 7.0, 68.f, layersx2X0}, + {220., 7.0, 68.f, layersx2X0}, + {260., 7.0, 68.f, layersx2X0}, + {300., 7.0, 68.f, layersx2X0}, + {350., 7.0, 68.f, layersx2X0}}; + + std::vector> layersConfigASide{ + {26., .5, 2.5, 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0} + {30., .5, 2.5, 0.1f * layersx2X0}, + {34., .5, 2.5, 0.1f * layersx2X0}, + {77., 5.0, 35., layersx2X0}, + {100., 5.0, 35., layersx2X0}, + {122., 5.0, 35., layersx2X0}, + {150., 5.0, 68.f, layersx2X0}, + {180., 5.0, 68.f, layersx2X0}, + {220., 5.0, 68.f, layersx2X0}, + {260., 5.0, 68.f, layersx2X0}, + {300., 5.0, 68.f, layersx2X0}, + {350., 5.0, 68.f, layersx2X0}}; + + mLayerName.resize(2); + mLayerName[0].resize(mNumberOfLayers); + mLayerName[1].resize(mNumberOfLayers); + mLayerID.clear(); + mLayers.resize(2); + + for (auto direction : {0, 1}) { + for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) { + std::string directionName = std::to_string(direction); + std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber); + mLayerName[direction][layerNumber] = layerName; + float z, rIn, rOut, x0; + if (direction == 0) { // C-Side + z = layersConfigCSide[layerNumber][0]; + rIn = layersConfigCSide[layerNumber][1]; + rOut = layersConfigCSide[layerNumber][2]; + x0 = layersConfigCSide[layerNumber][3]; + } else if (direction == 1) { // A-Side + z = layersConfigASide[layerNumber][0]; + rIn = layersConfigASide[layerNumber][1]; + rOut = layersConfigASide[layerNumber][2]; + x0 = layersConfigASide[layerNumber][3]; + } + + LOG(info) << "Adding Layer " << layerName << " at z = " << z; + // Add layers + auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0); + } + } +} + //_________________________________________________________________________________________________ void Detector::buildFT3Scoping() { @@ -342,7 +414,7 @@ Detector::Detector(bool active) } else { switch (ft3BaseParam.geoModel) { case Default: - buildFT3Scoping(); // FT3Scoping + buildFT3NewVacuumVessel(); // FT3 after Upgrade days March 2024 break; case Telescope: buildBasicFT3(ft3BaseParam); // BasicFT3 = Parametrized telescopic detector (equidistant layers) diff --git a/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Pipe.h b/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Pipe.h index 47b803c1bcbd1..1d9858e2dfec3 100644 --- a/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Pipe.h +++ b/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/Pipe.h @@ -33,7 +33,7 @@ class Alice3Pipe : public Alice3PassiveBase const float a3ipLength = 0.f, const float vacuumVesselRIn = 0.f, const float vacuumVesselThickness = 0.f, - const float vacuumVesselLength = 0.f); + const float vacuumVesselASideLength = 0.f); void ConstructGeometry() override; @@ -48,7 +48,7 @@ class Alice3Pipe : public Alice3PassiveBase float getVacuumVesselRIn() const { return mVacuumVesselRIn; } float getVacuumVesselRMax() const { return mVacuumVesselRIn + mVacuumVesselThick; } float getVacuumVesselWidth() const { return mVacuumVesselThick; } - float getVacuumVesselLength() const { return mVacuumVesselLength; } + float getVacuumVesselLength() const { return mVacuumVesselASideLength; } bool IsTRKActivated() const { return mIsTRKActivated; } bool IsFT3Activated() const { return mIsFT3Activated; } @@ -64,7 +64,7 @@ class Alice3Pipe : public Alice3PassiveBase float mVacuumVesselRIn = 0.; // inner diameter of the vacuum vessel float mVacuumVesselThick = 0.; // outer beam pipe section thickness - float mVacuumVesselLength = 0.; // half length of the outer beampipe around the IP + float mVacuumVesselASideLength = 0.; // Length of the A Side of the vacuum vessel around the IP bool mIsTRKActivated = true; // If TRK is not active don't create TRK layers allocations in the vacuum volume bool mIsFT3Activated = true; diff --git a/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx b/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx index f7f4c1844f7df..57f30241bd4ff 100644 --- a/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx +++ b/Detectors/Upgrades/ALICE3/Passive/src/Pipe.cxx @@ -38,7 +38,7 @@ Alice3Pipe::Alice3Pipe(const char* name, float a3ipLength, float vacuumVesselRIn, float vacuumVesselThickness, - float vacuumVesselLength) + float vacuumVesselASideLength) : Alice3PassiveBase{name, title}, mIsTRKActivated{isTRKActivated}, mIsFT3Activated{isFT3Activated}, @@ -47,7 +47,7 @@ Alice3Pipe::Alice3Pipe(const char* name, mA3IPLength{a3ipLength}, mVacuumVesselRIn{vacuumVesselRIn}, mVacuumVesselThick{vacuumVesselThickness}, - mVacuumVesselLength{vacuumVesselLength} + mVacuumVesselASideLength{vacuumVesselASideLength} { } @@ -95,19 +95,24 @@ void Alice3Pipe::ConstructGeometry() } // We split the naming of the parts if the beam pipe for ALICE 3 into parts - // - pipe - // - vacuum vessel (which hosts the primary vacuum) + // - pipe A Side + // - vacuum vessel (which hosts the primary vacuum and covers all C Side as well) // - iris vacuum vessel (which hosts the secondary vacuum) // A3IP update // Vacuum + Double_t pipeASideLength = mA3IPLength / 2. - mVacuumVesselThick - mVacuumVesselASideLength; + Double_t pipeCSideLength = mA3IPLength / 2. + mVacuumVesselASideLength; TGeoTube* vacuumBasePipe = new TGeoTube("PIPEVACUUM_BASEsh", 0., mPipeRIn, mA3IPLength / 2.); - TGeoTube* vacuumBaseVacuumVessel = new TGeoTube("VACUUM_VESSELVACUUM_BASEsh", mPipeRIn, mVacuumVesselRIn, mVacuumVesselLength / 2.); + TGeoTube* vacuumBaseVacuumVessel = new TGeoTube("VACUUM_VESSELVACUUM_BASEsh", mPipeRIn, mVacuumVesselRIn, pipeCSideLength / 2.); + + TGeoTranslation* posPipeCSide = new TGeoTranslation("PIPE_CSIDE_POSITION", 0, 0, mVacuumVesselASideLength - pipeCSideLength / 2.); + posPipeCSide->RegisterYourself(); // Excavate volumes from the vacuum such that there is place for the TRK barrel layers and FT3 disc layers of the IRIS tracker // And the other passive shapes: coldplate, iris tracker vacuum vessel TGeoCompositeShape* vacuumComposite; TGeoVolume* vacuumVolume; - TString compositeFormula{"PIPEVACUUM_BASEsh+VACUUM_VESSELVACUUM_BASEsh"}; + TString compositeFormula{"PIPEVACUUM_BASEsh+VACUUM_VESSELVACUUM_BASEsh:PIPE_CSIDE_POSITION"}; TString subtractorsFormula; if (!mIsTRKActivated) { @@ -183,28 +188,21 @@ void Alice3Pipe::ConstructGeometry() } // Pipe tubes - Double_t pipeLengthHalf = mA3IPLength / 2. - mVacuumVesselThick - mVacuumVesselLength / 2.; - TGeoTube* pipe = new TGeoTube("PIPEsh", mPipeRIn, mPipeRIn + mPipeThick, pipeLengthHalf / 2.); - TGeoTube* vacuumVesselTube = new TGeoTube("VACUUM_VESSEL_TUBEsh", mVacuumVesselRIn, mVacuumVesselRIn + mVacuumVesselThick, mVacuumVesselLength / 2.); + TGeoTube* pipeASide = new TGeoTube("PIPE_Ash", mPipeRIn, mPipeRIn + mPipeThick, pipeASideLength / 2.); + TGeoTube* pipeCSide = new TGeoTube("PIPE_Csh", mVacuumVesselRIn, mVacuumVesselRIn + mVacuumVesselThick, pipeCSideLength / 2.); TGeoTube* vacuumVesselWall = new TGeoTube("VACUUM_VESSEL_WALLsh", mPipeRIn, mVacuumVesselRIn + mVacuumVesselThick, mVacuumVesselThick / 2.); // Pipe and vacuum vessel positions - TGeoTranslation* posVacuumVesselWallNegZSide = new TGeoTranslation("WALLNEGZ", 0, 0, -mVacuumVesselLength / 2. - mVacuumVesselThick / 2.); - posVacuumVesselWallNegZSide->RegisterYourself(); - TGeoTranslation* posVacuumVesselWallPosZSide = new TGeoTranslation("WALLPOSZ", 0, 0, mVacuumVesselLength / 2. + mVacuumVesselThick / 2.); - posVacuumVesselWallPosZSide->RegisterYourself(); - TGeoTranslation* posPipeNegZSide = new TGeoTranslation("PIPENEGZ", 0, 0, -mVacuumVesselLength / 2. - mVacuumVesselThick - pipeLengthHalf / 2.); - posPipeNegZSide->RegisterYourself(); - TGeoTranslation* posPipePosZSide = new TGeoTranslation("PIPEPOSZ", 0, 0, mVacuumVesselLength / 2. + mVacuumVesselThick + pipeLengthHalf / 2.); - posPipePosZSide->RegisterYourself(); + TGeoTranslation* posVacuumVesselWall = new TGeoTranslation("WALL_POSITION", 0, 0, mVacuumVesselASideLength + mVacuumVesselThick / 2.); + posVacuumVesselWall->RegisterYourself(); + TGeoTranslation* posPipeASide = new TGeoTranslation("PIPE_ASIDE_POSITION", 0, 0, mVacuumVesselASideLength + mVacuumVesselThick + pipeASideLength / 2.); + posPipeASide->RegisterYourself(); // Pipe composite shape and volume TString pipeCompositeFormula = - "VACUUM_VESSEL_WALLsh:WALLNEGZ" - "+VACUUM_VESSEL_WALLsh:WALLPOSZ" - "+VACUUM_VESSEL_TUBEsh" - "+PIPEsh:PIPEPOSZ" - "+PIPEsh:PIPENEGZ"; + "VACUUM_VESSEL_WALLsh:WALL_POSITION" + "+PIPE_Ash:PIPE_ASIDE_POSITION" + "+PIPE_Csh:PIPE_CSIDE_POSITION"; if (subtractorsFormula.Length()) { LOG(info) << "Subtractors formula before : " << subtractorsFormula; diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h index ec516ecc8aa2a..47a48167e0562 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h @@ -61,6 +61,7 @@ class Detector : public o2::base::DetImpl } void configDefault(); + void buildTRKNewVacuumVessel(); void configFromFile(std::string fileName = "alice3_TRK_layout.txt"); void configToFile(std::string fileName = "alice3_TRK_layout.txt"); diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index db326eba84091..d6c4613b6b589 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -48,7 +48,7 @@ Detector::Detector(bool active) if (trkPars.configFile != "") { configFromFile(trkPars.configFile); } else { - configDefault(); + buildTRKNewVacuumVessel(); configToFile(); configServices(); } @@ -74,9 +74,12 @@ void Detector::ConstructGeometry() void Detector::configDefault() { + + // Build TRK detector according to the scoping document + mLayers.clear(); - LOGP(warning, "Loading default configuration for ALICE3 TRK"); + LOGP(warning, "Loading Scoping Document configuration for ALICE3 TRK"); mLayers.emplace_back(0, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(0)}, 0.5f, 50.f, 100.e-4); mLayers.emplace_back(1, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(1)}, 1.2f, 50.f, 100.e-4); mLayers.emplace_back(2, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(2)}, 2.5f, 50.f, 100.e-4); @@ -90,6 +93,29 @@ void Detector::configDefault() mLayers.emplace_back(10, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(10)}, 80.f, 258.f, 100.e-3); } +void Detector::buildTRKNewVacuumVessel() +{ + // Build the TRK detector according to changes proposed during + // https://indico.cern.ch/event/1407704/ + // to adhere to the changes that were presented at the ALICE 3 Upgrade days in March 2024 + // L3 -> 7 cm, L4 -> 9 cm + + mLayers.clear(); + + LOGP(warning, "Loading \"After Upgrade Days March 2024\" configuration for ALICE3 TRK"); + mLayers.emplace_back(0, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(0)}, 0.5f, 50.f, 100.e-4); + mLayers.emplace_back(1, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(1)}, 1.2f, 50.f, 100.e-4); + mLayers.emplace_back(2, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(2)}, 2.5f, 50.f, 100.e-4); + mLayers.emplace_back(3, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(3)}, 7.f, 124.f, 100.e-3); + mLayers.emplace_back(4, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(4)}, 9.f, 124.f, 100.e-3); + mLayers.emplace_back(5, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(5)}, 12.f, 124.f, 100.e-3); + mLayers.emplace_back(6, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(6)}, 20.f, 124.f, 100.e-3); + mLayers.emplace_back(7, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(7)}, 30.f, 124.f, 100.e-3); + mLayers.emplace_back(8, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(8)}, 45.f, 258.f, 100.e-3); + mLayers.emplace_back(9, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(9)}, 60.f, 258.f, 100.e-3); + mLayers.emplace_back(10, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(10)}, 80.f, 258.f, 100.e-3); +} + void Detector::configFromFile(std::string fileName) { // Override the default geometry if config file provided diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx index a9ea634777037..7937e3b4de09a 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKServices.cxx @@ -316,7 +316,7 @@ void TRKServices::createMiddleServices(TGeoVolume* motherVolume) motherVolume->AddNode(middleBarrelCoolingH2OVolume, 1, combiTrans); } // Middle barrel connection disks - const float rMinMiddleBarrelDisk = 3.78f; + const float rMinMiddleBarrelDisk = 5.68f; const float rMaxMiddleBarrelDisk = 35.f; const float zLengthMiddleBarrel = 62.f; for (auto& orientation : {Orientation::kASide, Orientation::kCSide}) { diff --git a/macro/build_geometry.C b/macro/build_geometry.C index 3b33f3c3ddfee..3712f6bf85a93 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -165,7 +165,7 @@ void build_geometry(FairRunSim* run = nullptr) #ifdef ENABLE_UPGRADES // upgraded beampipe at the interaction point (IP) if (isActivated("A3IP")) { - run->AddModule(new o2::passive::Alice3Pipe("A3IP", "Alice 3 beam pipe", !isActivated("TRK"), !isActivated("FT3"), 1.8f, 0.08f, 1000.f, 3.7f, 0.08f, 76.f)); + run->AddModule(new o2::passive::Alice3Pipe("A3IP", "Alice 3 beam pipe", !isActivated("TRK"), !isActivated("FT3"), 1.8f, 0.08f, 1000.f, 5.6f, 0.08f, 76.f)); } // the absorber From afa2f1047b06a8f5bffe453b7cfaac914efa0078 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 2 May 2024 18:31:07 +0200 Subject: [PATCH 0204/2997] TrackIndices are simple counters, not GlobalTrackID --- .../SpacePoints/include/SpacePoints/TrackInterpolation.h | 2 +- .../TPC/calibration/SpacePoints/src/TrackInterpolation.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h index c9b37263389bd..4b74eaadf5d92 100644 --- a/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h +++ b/Detectors/TPC/calibration/SpacePoints/include/SpacePoints/TrackInterpolation.h @@ -303,7 +303,7 @@ class TrackInterpolation std::vector mTrackTimes{}; ///< time estimates for all input tracks in micro seconds std::vector mSeeds{}; ///< seeding track parameters (ITS tracks) std::map mTrackTypes; ///< mapping of track source to array index in mTrackIndices - std::array, 4> mTrackIndices; ///< keep GIDs of input tracks separately for each track type + std::array, 4> mTrackIndices; ///< keep GIDs of input tracks separately for each track type gsl::span mTPCTracksClusIdx; ///< input TPC cluster indices from span const ClusterNativeAccess* mTPCClusterIdxStruct = nullptr; ///< struct holding the TPC cluster indices // ITS specific input only needed for debugging diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index c87dc905aa110..a32bf17fcd1c5 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -262,7 +262,7 @@ void TrackInterpolation::process() // in blocks. std::random_device rd; std::mt19937 g(rd()); - std::vector trackIndices; // here we keep the GIDs for all track types in a single vector to use in loop + std::vector trackIndices; // here we keep the GIDs for all track types in a single vector to use in loop std::shuffle(mTrackIndices[mTrackTypes[GTrackID::ITSTPCTRDTOF]].begin(), mTrackIndices[mTrackTypes[GTrackID::ITSTPCTRDTOF]].end(), g); std::shuffle(mTrackIndices[mTrackTypes[GTrackID::ITSTPCTRD]].begin(), mTrackIndices[mTrackTypes[GTrackID::ITSTPCTRD]].end(), g); std::shuffle(mTrackIndices[mTrackTypes[GTrackID::ITSTPCTOF]].begin(), mTrackIndices[mTrackTypes[GTrackID::ITSTPCTOF]].end(), g); From 6122bfe6d1dad392f3386af178d115cf03b692e6 Mon Sep 17 00:00:00 2001 From: Matthias Kleiner <48915672+matthias-kleiner@users.noreply.github.com> Date: Fri, 3 May 2024 22:47:21 +0200 Subject: [PATCH 0205/2997] TPC Timeseries: Adding cov and delta track params at vertex (#12928) * TPC Timeseries: Adding cov and delta track params at vertex * Fix bug when not using sampling * Fixing delta track parameters * Copy TrackParCov only --- .../TPC/workflow/src/TPCTimeSeriesSpec.cxx | 69 +++++++++++++++++-- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx index 00204afa1ea2e..4ab34762fd645 100644 --- a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx +++ b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx @@ -99,7 +99,7 @@ class TPCTimeSeries : public Task mXOuterMatching = ic.options().get("refX-for-outer-ITS"); mUseMinBiasTrigger = !ic.options().get("disable-min-bias-trigger"); - if (mSampleTsallis) { + if (mUnbinnedWriter) { for (int iThread = 0; iThread < mNThreads; ++iThread) { mGenerator.emplace_back(std::mt19937(std::random_device{}())); } @@ -1215,11 +1215,11 @@ class TPCTimeSeries : public Task o2::track::TrackPar trackITS(tracksITS[idxITSTrack]); const bool propITSOk = propagator->propagateTo(trackITS, trackITSTPCTmp.getX(), false, mMaxSnp, mFineStep, mMatType); if (propITSOk) { - deltaP0 = track.getParam(0) - trackITSTPCTmp.getParam(0); - deltaP1 = track.getParam(1) - trackITSTPCTmp.getParam(1); - deltaP2 = track.getParam(2) - trackITSTPCTmp.getParam(2); - deltaP3 = track.getParam(3) - trackITSTPCTmp.getParam(3); - deltaP4 = track.getParam(4) - trackITSTPCTmp.getParam(4); + deltaP0 = track.getParam(0) - trackITS.getParam(0); + deltaP1 = track.getParam(1) - trackITS.getParam(1); + deltaP2 = track.getParam(2) - trackITS.getParam(2); + deltaP3 = track.getParam(3) - trackITS.getParam(3); + deltaP4 = track.getParam(4) - trackITS.getParam(4); mBufferVals[iThread].front().setDeltaParam(deltaP2, deltaP3, deltaP4); } } @@ -1304,6 +1304,48 @@ class TPCTimeSeries : public Task } const int triggerMask = 0x1 * minBiasOk + 0x2 * writeData; + float deltaP2ConstrVtx = -999; + float deltaP3ConstrVtx = -999; + float deltaP4ConstrVtx = -999; + + // cov of TPC track constrained at vertex + float covTPCConstrVtxP2 = -999; + float covTPCConstrVtxP3 = -999; + float covTPCConstrVtxP4 = -999; + + // cov of ITS-TPC track at vertex + float covITSTPCConstrVtxP2 = -999; + float covITSTPCConstrVtxP3 = -999; + float covITSTPCConstrVtxP4 = -999; + + float covTPCAtVertex0 = -999; + float covTPCAtVertex1 = -999; + + const bool contributeToVertex = (idxITSTPC.back() != -1); + if (hasITSTPC && contributeToVertex) { + o2::track::TrackParCov trackITSTPCTmp = tracksITSTPC[idxITSTPC.front()]; + o2::gpu::gpustd::array dcaITSTPCTmp{-1, -1}; + if (propagator->propagateToDCA(vertex.getXYZ(), trackITSTPCTmp, propagator->getNominalBz(), mFineStep, mMatType, &dcaITSTPCTmp)) { + o2::track::TrackParCov trackTPC = tracksTPC[iTrk]; + if (trackTPC.rotate(trackITSTPCTmp.getAlpha()) && propagator->propagateTo(trackTPC, trackITSTPCTmp.getX(), false, mMaxSnp, mFineStep, mMatType)) { + // store covariance of TPC track at vertex + covTPCAtVertex0 = trackTPC.getCovarElem(0, 0); + covTPCAtVertex1 = trackTPC.getCovarElem(1, 1); + + trackTPC.update(vertex); + deltaP2ConstrVtx = trackTPC.getParam(2) - trackITSTPCTmp.getParam(2); + deltaP3ConstrVtx = trackTPC.getParam(3) - trackITSTPCTmp.getParam(3); + deltaP4ConstrVtx = trackTPC.getParam(4) - trackITSTPCTmp.getParam(4); + covTPCConstrVtxP2 = trackTPC.getCovarElem(2, 2); + covTPCConstrVtxP3 = trackTPC.getCovarElem(3, 3); + covTPCConstrVtxP4 = trackTPC.getCovarElem(4, 4); + covITSTPCConstrVtxP2 = trackITSTPCTmp.getCovarElem(2, 2); + covITSTPCConstrVtxP3 = trackITSTPCTmp.getCovarElem(3, 3); + covITSTPCConstrVtxP4 = trackITSTPCTmp.getCovarElem(4, 4); + } + } + } + *mStreamer[iThread] << "treeTimeSeries" // DCAs << "triggerMask=" << triggerMask @@ -1343,6 +1385,21 @@ class TPCTimeSeries : public Task << "chi2ITS=" << chi2ITS << "chi2match_ITSTPC=" << chi2match_ITSTPC << "PID=" << trkOrig.getPID().getID() + // TPC cov at vertex (without vertex constrained) + << "covTPCAtVertex0=" << covTPCAtVertex0 + << "covTPCAtVertex1=" << covTPCAtVertex1 + // TPC cov at vertex (with vertex constrained) + << "covTPCConstrVtxP2=" << covTPCConstrVtxP2 + << "covTPCConstrVtxP3=" << covTPCConstrVtxP3 + << "covTPCConstrVtxP4=" << covTPCConstrVtxP4 + // ITS-TPC cov at vertex (with vertex constrained) + << "covITSTPCConstrVtxP2=" << covITSTPCConstrVtxP2 + << "covITSTPCConstrVtxP3=" << covITSTPCConstrVtxP3 + << "covITSTPCConstrVtxP4=" << covITSTPCConstrVtxP4 + // delta Parameter at vertex with TPC track constrained at vertex + << "deltaP2ConstrVtx=" << deltaP2ConstrVtx + << "deltaP3ConstrVtx=" << deltaP3ConstrVtx + << "deltaP4ConstrVtx=" << deltaP4ConstrVtx // << "deltaPar0=" << deltaP0 << "deltaPar1=" << deltaP1 From d0f3f04cfb36053971caedc5634db7e921f50241 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 4 May 2024 08:56:30 +0200 Subject: [PATCH 0206/2997] DPL: refactor plugin manager (#13113) - Move PluginManager to a separate header so that we do not include the code to load plugin in the plugin declarations. - Make the PluginManager code generic to use it for the upcoming metadata discovery. --- Framework/Core/CMakeLists.txt | 2 +- .../Core/include/Framework/AnalysisManagers.h | 6 +- .../Core/include/Framework/PluginManager.h | 137 ++++++++++++++++++ Framework/Core/include/Framework/Plugins.h | 41 ------ .../Core/include/Framework/ServiceSpec.h | 5 - Framework/Core/src/CommonDataProcessors.cxx | 2 +- Framework/Core/src/CommonDriverServices.cxx | 7 +- Framework/Core/src/CommonServices.cxx | 8 +- .../src/{Plugins.cxx => PluginManager.cxx} | 51 ++++++- Framework/Core/src/ServiceSpec.cxx | 120 --------------- Framework/Core/src/WorkflowHelpers.cxx | 2 +- Framework/Core/src/runDataProcessing.cxx | 2 +- Framework/Core/test/test_AlgorithmWrapper.cxx | 2 +- 13 files changed, 203 insertions(+), 182 deletions(-) create mode 100644 Framework/Core/include/Framework/PluginManager.h rename Framework/Core/src/{Plugins.cxx => PluginManager.cxx} (72%) diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index fabb62eb6530d..d392ba42fe8ac 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -109,7 +109,7 @@ o2_add_library(Framework src/OptionsHelpers.cxx src/PropertyTreeHelpers.cxx src/ProcessingContext.cxx - src/Plugins.cxx + src/PluginManager.cxx src/RateLimiter.cxx src/ResourcesMonitoringHelper.cxx src/ResourcePolicy.cxx diff --git a/Framework/Core/include/Framework/AnalysisManagers.h b/Framework/Core/include/Framework/AnalysisManagers.h index c8daac1c5edb5..f341f60392e9f 100644 --- a/Framework/Core/include/Framework/AnalysisManagers.h +++ b/Framework/Core/include/Framework/AnalysisManagers.h @@ -28,7 +28,7 @@ #include "Framework/RootConfigParamHelpers.h" #include "Framework/ExpressionHelpers.h" #include "Framework/CommonServices.h" -#include "Framework/Plugins.h" +#include "Framework/PluginManager.h" #include "Framework/RootMessageContext.h" #include "Framework/DeviceSpec.h" @@ -465,8 +465,8 @@ struct ServiceManager> { { if constexpr (o2::framework::is_base_of_template_v) { T p = T{}; - auto loadableServices = ServiceHelpers::parseServiceSpecString(p.loadSpec.c_str()); - ServiceHelpers::loadFromPlugin(loadableServices, specs); + auto loadableServices = PluginManager::parsePluginSpecString(p.loadSpec.c_str()); + PluginManager::loadFromPlugin(loadableServices, specs); } return true; } diff --git a/Framework/Core/include/Framework/PluginManager.h b/Framework/Core/include/Framework/PluginManager.h new file mode 100644 index 0000000000000..38966c5a969a9 --- /dev/null +++ b/Framework/Core/include/Framework/PluginManager.h @@ -0,0 +1,137 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef O2_FRAMEWORK_PLUGIN_MANAGER_H_ +#define O2_FRAMEWORK_PLUGIN_MANAGER_H_ + +#include "Framework/Plugins.h" +#include +#include +#include + +// Struct to hold live plugin information which the plugin itself cannot +// know and that is owned by the framework. +struct PluginInfo { + uv_lib_t* dso = nullptr; + std::string name; + DPLPluginHandle* instance = nullptr; +}; + +// Struct to hold information about the location of a plugin +struct LoadablePlugin { + std::string name; + std::string library; +}; + +namespace o2::framework +{ +struct PluginManager { + using WrapperProcessCallback = std::function; + + template + static T* getByName(DPLPluginHandle* handle, char const* name) + { + while (handle != nullptr) { + if (strncmp(handle->name, name, strlen(name)) == 0) { + return reinterpret_cast(handle->instance); + } + handle = handle->previous; + } + return nullptr; + } + /// Load a DSO called @a dso and insert its handle in @a infos + /// On successfull completion @a onSuccess is called passing + /// the DPLPluginHandle provided by the library. + static void load(std::vector& infos, const char* dso, std::function& onSuccess); + /// Load an called @plugin from a library called @a library and + /// return the associtated AlgorithmSpec. + static auto loadAlgorithmFromPlugin(std::string library, std::string plugin) -> AlgorithmSpec; + /// Wrap an algorithm with some lambda @wrapper which will be called + /// with the original callback and the ProcessingContext. + static auto wrapAlgorithm(AlgorithmSpec const& spec, WrapperProcessCallback&& wrapper) -> AlgorithmSpec; + + /// Parse a comma separated list of : plugin declarations. + static std::vector parsePluginSpecString(char const* str); + + template + static void loadFromPlugin(std::vector const& loadablePlugins, std::vector& specs) + { + struct LoadedDSO { + std::string library; + uv_lib_t handle; + }; + + struct LoadedPlugin { + std::string name; + ServicePlugin* factory; + }; + std::vector loadedDSOs; + std::vector loadedPlugins; + for (auto& loadablePlugin : loadablePlugins) { + auto loadedDSO = std::find_if(loadedDSOs.begin(), loadedDSOs.end(), [&loadablePlugin](auto& dso) { + return dso.library == loadablePlugin.library; + }); + + if (loadedDSO == loadedDSOs.end()) { + uv_lib_t handle; +#ifdef __APPLE__ + auto libraryName = fmt::format("lib{}.dylib", loadablePlugin.library); +#else + auto libraryName = fmt::format("lib{}.so", loadablePlugin.library); +#endif + auto ret = uv_dlopen(libraryName.c_str(), &handle); + if (ret != 0) { + LOGP(error, "Could not load library {}", loadablePlugin.library); + LOG(error) << uv_dlerror(&handle); + continue; + } + loadedDSOs.push_back({loadablePlugin.library, handle}); + loadedDSO = loadedDSOs.end() - 1; + } + int result = 0; + + auto loadedPlugin = std::find_if(loadedPlugins.begin(), loadedPlugins.end(), [&loadablePlugin](auto& plugin) { + return plugin.name == loadablePlugin.name; + }); + + if (loadedPlugin == loadedPlugins.end()) { + DPLPluginHandle* (*dpl_plugin_callback)(DPLPluginHandle*); + result = uv_dlsym(&loadedDSO->handle, "dpl_plugin_callback", (void**)&dpl_plugin_callback); + if (result == -1) { + LOG(error) << uv_dlerror(&loadedDSO->handle); + continue; + } + + DPLPluginHandle* pluginInstance = dpl_plugin_callback(nullptr); + PLUGIN* factory = PluginManager::getByName(pluginInstance, loadablePlugin.name.c_str()); + if (factory == nullptr) { + LOGP(error, "Could not find service {} in library {}", loadablePlugin.name, loadablePlugin.library); + continue; + } + + loadedPlugins.push_back({loadablePlugin.name, factory}); + loadedPlugin = loadedPlugins.begin() + loadedPlugins.size() - 1; + } + assert(loadedPlugin != loadedPlugins.end()); + assert(loadedPlugin->factory != nullptr); + + CONCRETE* spec = loadedPlugin->factory->create(); + if (!spec) { + LOG(error) << "Plugin " << loadablePlugin.name << " could not be created"; + continue; + } + LOGP(debug, "Loading service {} from {}", loadablePlugin.name, loadablePlugin.library); + specs.push_back(*spec); + } + } +}; + +} // namespace o2::framework +#endif // O2_FRAMEWORK_PLUGIN_MANAGER_H_ diff --git a/Framework/Core/include/Framework/Plugins.h b/Framework/Core/include/Framework/Plugins.h index 788470b472f2a..c29d96f7e0781 100644 --- a/Framework/Core/include/Framework/Plugins.h +++ b/Framework/Core/include/Framework/Plugins.h @@ -12,10 +12,7 @@ #define O2_FRAMEWORK_PLUGINS_H_ #include "Framework/AlgorithmSpec.h" -#include #include -#include -#include namespace o2::framework { @@ -82,14 +79,6 @@ struct DPLPluginHandle { DPLPluginHandle* previous = nullptr; }; -// Struct to hold live plugin information which the plugin itself cannot -// know and that is owned by the framework. -struct PluginInfo { - uv_lib_t* dso = nullptr; - std::string name; - DPLPluginHandle* instance = nullptr; -}; - #define DEFINE_DPL_PLUGIN(NAME, KIND) \ extern "C" { \ DPLPluginHandle* dpl_plugin_callback(DPLPluginHandle* previous) \ @@ -111,34 +100,4 @@ struct PluginInfo { } \ } -namespace o2::framework -{ -struct PluginManager { - using WrapperProcessCallback = std::function; - - template - static T* getByName(DPLPluginHandle* handle, char const* name) - { - while (handle != nullptr) { - if (strncmp(handle->name, name, strlen(name)) == 0) { - return reinterpret_cast(handle->instance); - } - handle = handle->previous; - } - return nullptr; - } - /// Load a DSO called @a dso and insert its handle in @a infos - /// On successfull completion @a onSuccess is called passing - /// the DPLPluginHandle provided by the library. - static void load(std::vector& infos, const char* dso, std::function& onSuccess); - /// Load an called @plugin from a library called @a library and - /// return the associtated AlgorithmSpec. - static auto loadAlgorithmFromPlugin(std::string library, std::string plugin) -> AlgorithmSpec; - /// Wrap an algorithm with some lambda @wrapper which will be called - /// with the original callback and the ProcessingContext. - static auto wrapAlgorithm(AlgorithmSpec const& spec, WrapperProcessCallback&& wrapper) -> AlgorithmSpec; -}; - -} // namespace o2::framework - #endif // O2_FRAMEWORK_PLUGINS_H_ diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index 910620fcd0655..abac3ad05914c 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -327,11 +327,6 @@ struct LoadableService { std::string library; }; -struct ServiceHelpers { - static std::vector parseServiceSpecString(char const* str); - static void loadFromPlugin(std::vector const& loadableServices, std::vector& specs); -}; - } // namespace o2::framework #endif // O2_FRAMEWORK_SERVICESPEC_H_ diff --git a/Framework/Core/src/CommonDataProcessors.cxx b/Framework/Core/src/CommonDataProcessors.cxx index 593cb8d1ac1f8..9817a57734c1d 100644 --- a/Framework/Core/src/CommonDataProcessors.cxx +++ b/Framework/Core/src/CommonDataProcessors.cxx @@ -39,7 +39,7 @@ #include "Framework/ExternalFairMQDeviceProxy.h" #include "Framework/RuntimeError.h" #include "Framework/RateLimiter.h" -#include "Framework/Plugins.h" +#include "Framework/PluginManager.h" #include "Framework/DeviceSpec.h" #include "WorkflowHelpers.h" #include diff --git a/Framework/Core/src/CommonDriverServices.cxx b/Framework/Core/src/CommonDriverServices.cxx index 893087d555210..6fd27b700e047 100644 --- a/Framework/Core/src/CommonDriverServices.cxx +++ b/Framework/Core/src/CommonDriverServices.cxx @@ -11,6 +11,7 @@ #include "CommonDriverServices.h" #include "Framework/CommonServices.h" +#include "Framework/PluginManager.h" // Make sure we can use aggregated initialisers. #pragma GCC diagnostic push @@ -24,14 +25,14 @@ std::vector o2::framework::CommonDriverServices::defaultServices() std::vector specs{ CommonServices::configurationSpec()}; // Load plugins depending on the environment - std::vector loadableServices = {}; + std::vector loadableServices = {}; char* loadableServicesEnv = getenv("DPL_LOAD_DRIVER_SERVICES"); // String to define the services to load is: // // library1:name1,library2:name2,... if (loadableServicesEnv) { - loadableServices = ServiceHelpers::parseServiceSpecString(loadableServicesEnv); - ServiceHelpers::loadFromPlugin(loadableServices, specs); + loadableServices = PluginManager::parsePluginSpecString(loadableServicesEnv); + PluginManager::loadFromPlugin(loadableServices, specs); } return specs; } diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 7f0e710d96b2e..7f145fe4318ff 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -36,7 +36,7 @@ #include "Framework/Tracing.h" #include "Framework/Monitoring.h" #include "Framework/AsyncQueue.h" -#include "Framework/Plugins.h" +#include "Framework/PluginManager.h" #include "Framework/DeviceContext.h" #include "Framework/DataProcessingContext.h" #include "Framework/StreamContext.h" @@ -1260,7 +1260,7 @@ std::vector CommonServices::defaultServices(std::string extraPlugin loadableServicesStr += "O2FrameworkDataTakingSupport:InfoLoggerContext,O2FrameworkDataTakingSupport:InfoLogger"; } // Load plugins depending on the environment - std::vector loadableServices = {}; + std::vector loadablePlugins = {}; char* loadableServicesEnv = getenv("DPL_LOAD_SERVICES"); // String to define the services to load is: // @@ -1271,8 +1271,8 @@ std::vector CommonServices::defaultServices(std::string extraPlugin } loadableServicesStr += loadableServicesEnv; } - loadableServices = ServiceHelpers::parseServiceSpecString(loadableServicesStr.c_str()); - ServiceHelpers::loadFromPlugin(loadableServices, specs); + loadablePlugins = PluginManager::parsePluginSpecString(loadableServicesStr.c_str()); + PluginManager::loadFromPlugin(loadablePlugins, specs); // I should make it optional depending wether the GUI is there or not... specs.push_back(CommonServices::guiMetricsSpec()); if (numThreads) { diff --git a/Framework/Core/src/Plugins.cxx b/Framework/Core/src/PluginManager.cxx similarity index 72% rename from Framework/Core/src/Plugins.cxx rename to Framework/Core/src/PluginManager.cxx index c4a0ee7fd6dc5..96666722fc169 100644 --- a/Framework/Core/src/Plugins.cxx +++ b/Framework/Core/src/PluginManager.cxx @@ -8,7 +8,7 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/Plugins.h" +#include "Framework/PluginManager.h" #include "Framework/Logger.h" #include #include @@ -16,6 +16,55 @@ namespace o2::framework { +std::vector PluginManager::parsePluginSpecString(char const* str) +{ + std::vector loadablePlugins; + enum struct ParserState : int { + IN_LIBRARY, + IN_NAME, + IN_END, + IN_ERROR, + }; + const char* cur = str; + const char* next = cur; + ParserState state = ParserState::IN_LIBRARY; + std::string_view library; + std::string_view name; + while (cur && *cur != '\0') { + ParserState previousState = state; + state = ParserState::IN_ERROR; + switch (previousState) { + case ParserState::IN_LIBRARY: + next = strchr(cur, ':'); + if (next != nullptr) { + state = ParserState::IN_NAME; + library = std::string_view(cur, next - cur); + } + break; + case ParserState::IN_NAME: + next = strchr(cur, ','); + if (next == nullptr) { + state = ParserState::IN_END; + name = std::string_view(cur, strlen(cur)); + } else { + name = std::string_view(cur, next - cur); + state = ParserState::IN_LIBRARY; + } + loadablePlugins.push_back({std::string(name), std::string(library)}); + break; + case ParserState::IN_END: + break; + case ParserState::IN_ERROR: + LOG(error) << "Error while parsing DPL_LOAD_SERVICES"; + break; + } + if (!next) { + break; + } + cur = next + 1; + }; + return loadablePlugins; +} void PluginManager::load(std::vector& libs, const char* dso, std::function& onSuccess) { diff --git a/Framework/Core/src/ServiceSpec.cxx b/Framework/Core/src/ServiceSpec.cxx index fdbe0c0c4dd4b..4f38651b68924 100644 --- a/Framework/Core/src/ServiceSpec.cxx +++ b/Framework/Core/src/ServiceSpec.cxx @@ -104,124 +104,4 @@ ServiceSpecs ServiceSpecHelpers::filterDisabled(ServiceSpecs originals, Override return result; } -std::vector ServiceHelpers::parseServiceSpecString(char const* str) -{ - std::vector loadableServices; - enum struct ParserState : int { - IN_LIBRARY, - IN_NAME, - IN_END, - IN_ERROR, - }; - const char* cur = str; - const char* next = cur; - ParserState state = ParserState::IN_LIBRARY; - std::string_view library; - std::string_view name; - while (cur && *cur != '\0') { - ParserState previousState = state; - state = ParserState::IN_ERROR; - switch (previousState) { - case ParserState::IN_LIBRARY: - next = strchr(cur, ':'); - if (next != nullptr) { - state = ParserState::IN_NAME; - library = std::string_view(cur, next - cur); - } - break; - case ParserState::IN_NAME: - next = strchr(cur, ','); - if (next == nullptr) { - state = ParserState::IN_END; - name = std::string_view(cur, strlen(cur)); - } else { - name = std::string_view(cur, next - cur); - state = ParserState::IN_LIBRARY; - } - loadableServices.push_back({std::string(name), std::string(library)}); - break; - case ParserState::IN_END: - break; - case ParserState::IN_ERROR: - LOG(error) << "Error while parsing DPL_LOAD_SERVICES"; - break; - } - if (!next) { - break; - } - cur = next + 1; - }; - return loadableServices; -} - -void ServiceHelpers::loadFromPlugin(std::vector const& loadableServices, std::vector& specs) -{ - struct LoadedDSO { - std::string library; - uv_lib_t handle; - }; - - struct LoadedPlugin { - std::string name; - ServicePlugin* factory; - }; - std::vector loadedDSOs; - std::vector loadedPlugins; - for (auto& loadableService : loadableServices) { - auto loadedDSO = std::find_if(loadedDSOs.begin(), loadedDSOs.end(), [&loadableService](auto& dso) { - return dso.library == loadableService.library; - }); - - if (loadedDSO == loadedDSOs.end()) { - uv_lib_t handle; -#ifdef __APPLE__ - auto libraryName = fmt::format("lib{}.dylib", loadableService.library); -#else - auto libraryName = fmt::format("lib{}.so", loadableService.library); -#endif - auto ret = uv_dlopen(libraryName.c_str(), &handle); - if (ret != 0) { - LOGP(error, "Could not load library {}", loadableService.library); - LOG(error) << uv_dlerror(&handle); - continue; - } - loadedDSOs.push_back({loadableService.library, handle}); - loadedDSO = loadedDSOs.end() - 1; - } - int result = 0; - - auto loadedPlugin = std::find_if(loadedPlugins.begin(), loadedPlugins.end(), [&loadableService](auto& plugin) { - return plugin.name == loadableService.name; - }); - - if (loadedPlugin == loadedPlugins.end()) { - DPLPluginHandle* (*dpl_plugin_callback)(DPLPluginHandle*); - result = uv_dlsym(&loadedDSO->handle, "dpl_plugin_callback", (void**)&dpl_plugin_callback); - if (result == -1) { - LOG(error) << uv_dlerror(&loadedDSO->handle); - continue; - } - - DPLPluginHandle* pluginInstance = dpl_plugin_callback(nullptr); - ServicePlugin* factory = PluginManager::getByName(pluginInstance, loadableService.name.c_str()); - if (factory == nullptr) { - LOGP(error, "Could not find service {} in library {}", loadableService.name, loadableService.library); - continue; - } - - loadedPlugins.push_back({loadableService.name, factory}); - loadedPlugin = loadedPlugins.begin() + loadedPlugins.size() - 1; - } - assert(loadedPlugin != loadedPlugins.end()); - assert(loadedPlugin->factory != nullptr); - - ServiceSpec* spec = loadedPlugin->factory->create(); - if (!spec) { - LOG(error) << "Plugin " << loadableService.name << " could not be created"; - continue; - } - LOGP(debug, "Loading service {} from {}", loadableService.name, loadableService.library); - specs.push_back(*spec); - } -} } // namespace o2::framework diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index f5a66722aa713..bd875ad421f6e 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -21,7 +21,7 @@ #include "Framework/RawDeviceService.h" #include "Framework/StringHelpers.h" #include "Framework/ChannelSpecHelpers.h" -#include "Framework/Plugins.h" +#include "Framework/PluginManager.h" #include "Framework/DataTakingContext.h" #include "Framework/DefaultsHelpers.h" diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index c72b4da73a45a..f91716d28cfd7 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -22,7 +22,7 @@ #include "Framework/DataProcessingDevice.h" #include "Framework/DataProcessingContext.h" #include "Framework/DataProcessorSpec.h" -#include "Framework/Plugins.h" +#include "Framework/PluginManager.h" #include "Framework/DeviceControl.h" #include "Framework/DeviceExecution.h" #include "Framework/DeviceInfo.h" diff --git a/Framework/Core/test/test_AlgorithmWrapper.cxx b/Framework/Core/test/test_AlgorithmWrapper.cxx index 7671b6afa194b..6a02aea62c528 100644 --- a/Framework/Core/test/test_AlgorithmWrapper.cxx +++ b/Framework/Core/test/test_AlgorithmWrapper.cxx @@ -14,7 +14,7 @@ #include "Framework/ServiceRegistry.h" #include "Framework/RawDeviceService.h" #include "Framework/runDataProcessing.h" -#include "Framework/Plugins.h" +#include "Framework/PluginManager.h" #include using namespace o2::framework; From 0c56a09aa772a5352d459e08eb328590497b6663 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 4 May 2024 09:33:41 +0200 Subject: [PATCH 0207/2997] DPL: improve messages on caught exceptions - Provide a bit of context in the printout - Use signposts --- Framework/Core/src/DataProcessingDevice.cxx | 32 +++++++++++++++++---- Framework/Core/test/test_AllCrashTypes.sh | 4 +-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index bb3858a9d3ed2..602fe7cc29548 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -372,6 +372,9 @@ void DataProcessingDevice::Init() auto ref = ServiceRegistryRef{mServiceRegistry}; auto& context = ref.get(); auto& spec = getRunningDevice(mRunningDevice, ref); + + O2_SIGNPOST_ID_FROM_POINTER(cid, device, &context); + O2_SIGNPOST_START(device, cid, "Init", "Entering Init callback."); context.statelessProcess = spec.algorithm.onProcess; context.statefulProcess = nullptr; context.error = spec.algorithm.onError; @@ -412,8 +415,10 @@ void DataProcessingDevice::Init() /// FIXME: we should pass the salt in, so that the message /// can access information which were stored in the stream. ServiceRegistryRef ref{serviceRegistry, ServiceRegistry::globalDeviceSalt()}; + auto& context = ref.get(); auto& err = error_from_ref(e); - LOGP(error, "Exception caught: {} ", err.what); + O2_SIGNPOST_ID_FROM_POINTER(cid, device, &context); + O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "Init", "Exception caught while in Init: %{public}s. Invoking errorCallback.", err.what); demangled_backtrace_symbols(err.backtrace, err.maxBacktrace, STDERR_FILENO); auto& stats = ref.get(); stats.updateStats({(int)ProcessingStatsId::EXCEPTION_COUNT, DataProcessingStats::Op::Add, 1}); @@ -425,8 +430,10 @@ void DataProcessingDevice::Init() auto& err = error_from_ref(e); /// FIXME: we should pass the salt in, so that the message /// can access information which were stored in the stream. - LOGP(error, "Exception caught: {} ", err.what); ServiceRegistryRef ref{serviceRegistry, ServiceRegistry::globalDeviceSalt()}; + auto& context = ref.get(); + O2_SIGNPOST_ID_FROM_POINTER(cid, device, &context); + O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "Init", "Exception caught while in Init: %{public}s. Exiting with 1.", err.what); demangled_backtrace_symbols(err.backtrace, err.maxBacktrace, STDERR_FILENO); auto& stats = ref.get(); stats.updateStats({(int)ProcessingStatsId::EXCEPTION_COUNT, DataProcessingStats::Op::Add, 1}); @@ -491,6 +498,7 @@ void DataProcessingDevice::Init() ServiceRegistry::Salt streamSalt = ServiceRegistry::streamSalt(si + 1, ServiceRegistry::globalDeviceSalt().dataProcessorId); mServiceRegistry.lateBindStreamServices(state, *options, streamSalt); } + O2_SIGNPOST_END(device, cid, "Init", "Exiting Init callback."); } void on_signal_callback(uv_signal_t* handle, int signum) @@ -1079,7 +1087,9 @@ void DataProcessingDevice::fillContext(DataProcessorContext& context, DeviceCont /// can access information which were stored in the stream. ServiceRegistryRef ref{serviceRegistry, ServiceRegistry::globalDeviceSalt()}; auto& err = error_from_ref(e); - LOGP(error, "Exception caught: {} ", err.what); + auto& context = ref.get(); + O2_SIGNPOST_ID_FROM_POINTER(cid, device, &context); + O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "Run", "Exception while running: %{public}s. Invoking callback.", err.what); demangled_backtrace_symbols(err.backtrace, err.maxBacktrace, STDERR_FILENO); auto& stats = ref.get(); stats.updateStats({(int)ProcessingStatsId::EXCEPTION_COUNT, DataProcessingStats::Op::Add, 1}); @@ -1092,15 +1102,18 @@ void DataProcessingDevice::fillContext(DataProcessorContext& context, DeviceCont auto& err = error_from_ref(e); /// FIXME: we should pass the salt in, so that the message /// can access information which were stored in the stream. - LOGP(error, "Exception caught: {} ", err.what); ServiceRegistryRef ref{serviceRegistry, ServiceRegistry::globalDeviceSalt()}; + auto& context = ref.get(); + O2_SIGNPOST_ID_FROM_POINTER(cid, device, &context); demangled_backtrace_symbols(err.backtrace, err.maxBacktrace, STDERR_FILENO); auto& stats = ref.get(); stats.updateStats({(int)ProcessingStatsId::EXCEPTION_COUNT, DataProcessingStats::Op::Add, 1}); switch (errorPolicy) { case TerminationPolicy::QUIT: + O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "Run", "Exception while running: %{public}s. Rethrowing.", err.what); throw e; default: + O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "Run", "Exception while running: %{public}s. Skipping to next timeframe.", err.what); break; } }; @@ -1148,6 +1161,9 @@ void DataProcessingDevice::PreRun() { auto ref = ServiceRegistryRef{mServiceRegistry}; auto& state = ref.get(); + + O2_SIGNPOST_ID_FROM_POINTER(cid, device, state.loop); + O2_SIGNPOST_START(device, cid, "PreRun", "Entering PreRun callback."); state.quitRequested = false; state.streaming = StreamingState::Streaming; for (auto& info : state.inputChannelInfos) { @@ -1168,13 +1184,16 @@ void DataProcessingDevice::PreRun() context.preStartStreamCallbacks(streamRef); } } catch (std::exception& e) { - LOGP(error, "Exception caught: {} ", e.what()); + O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "PreRun", "Exception of type std::exception caught in PreRun: %{public}s. Rethrowing.", e.what()); + O2_SIGNPOST_END(device, cid, "PreRun", "Exiting PreRun due to exception thrown."); throw; } catch (o2::framework::RuntimeErrorRef& e) { auto& err = error_from_ref(e); - LOGP(error, "Exception caught: {} ", err.what); + O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "PreRun", "Exception of type o2::framework::RuntimeErrorRef caught in PreRun: %{public}s. Rethrowing.", err.what); + O2_SIGNPOST_END(device, cid, "PreRun", "Exiting PreRun due to exception thrown."); throw; } catch (...) { + O2_SIGNPOST_END(device, cid, "PreRun", "Unknown exception being thrown. Rethrowing."); throw; } @@ -1189,6 +1208,7 @@ void DataProcessingDevice::PreRun() auto& monitoring = ref.get(); monitoring.send(Metric{(uint64_t)1, "device_state"}.addTag(Key::Subsystem, Value::DPL)); + O2_SIGNPOST_END(device, cid, "PreRun", "Exiting PreRun callback."); } void DataProcessingDevice::PostRun() diff --git a/Framework/Core/test/test_AllCrashTypes.sh b/Framework/Core/test/test_AllCrashTypes.sh index 52c8e62ee8469..54898fd9c4c5d 100755 --- a/Framework/Core/test/test_AllCrashTypes.sh +++ b/Framework/Core/test/test_AllCrashTypes.sh @@ -1,9 +1,9 @@ #!/bin/sh -e echo $PATH printf "ok\nTesting runtime-init..." -o2-framework-crashing-workflow --crash-type=runtime-init --completion-policy=quit -b --run | grep -q "Exception caught: This is a std::runtime_error" || { printf "runtime error not found" ; exit 1; } +o2-framework-crashing-workflow --crash-type=runtime-init --completion-policy=quit -b --run | grep -q "Exception caught while in Init: This is a std::runtime_error. Exiting with 1." || { printf "runtime error not found" ; exit 1; } printf "ok\nTesting framework-init..." -o2-framework-crashing-workflow --crash-type=framework-init --completion-policy=quit -b --run | grep -q "Exception caught: This is a o2::framework::runtime_error" || { printf "framework error not found" ; exit 1; } +o2-framework-crashing-workflow --crash-type=framework-init --completion-policy=quit -b --run | grep -q "Exception caught while in Init: This is a o2::framework::runtime_error. Exiting with 1." || { printf "framework error not found" ; exit 1; } printf "ok\nTesting framework-run..." o2-framework-crashing-workflow --crash-type=framework-run --completion-policy=quit -b --run | grep -q "Unhandled o2::framework::runtime_error reached the top of main of o2-framework-crashing-workflow, device shutting down. Reason: This is a o2::framework::runtime_error" || { printf "framework error not found" ; exit 1; } printf "ok\nTesting runtime-run..." From 0f401e808d2c24d85a0b3151d539099061a38b1d Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Mon, 6 May 2024 08:39:04 +0200 Subject: [PATCH 0208/2997] QC-1163 Rework and update the documentation for QC flags (#13091) * QC-1163 Rework and update the documentation for QC flags * formatting happy make * gRPC upload to RCT not done yet --- DataFormats/QualityControl/README.md | 133 ++++++++++++++++----------- 1 file changed, 81 insertions(+), 52 deletions(-) diff --git a/DataFormats/QualityControl/README.md b/DataFormats/QualityControl/README.md index ededa028c7b93..486856c983306 100644 --- a/DataFormats/QualityControl/README.md +++ b/DataFormats/QualityControl/README.md @@ -1,63 +1,99 @@ \page refDataFormatsQualityControl Data Formats Quality Control -Data formats for tagging good quality data for analysis. +## Tagging Good Quality Data for Processing and Analysis -# Flagging time ranges -## General idea -* Each detector has its own CCDB (QCDB) entry - TimeRangeFlagCollection -* The CCDB Entry validity will be run or fill, depending on the final data taking granularity -* Each entry can define sub ranges (TimeRangeFlags) of certain data characteristics (FlagReasons) inside the CCDB Entry validity -* Flags are defined in a CSV master file, they are used to derive the Data Tags - the final filters for good quality data during analysis. -* Data Tag are stored as CCDB entries. They might require different detectors and may suppress different flags dependent on the analysis type. - -## Implementation - -[Flag Reason](include/DataFormatsQualityControl/FlagReasons.h) is defined with an identifier number, a name and a 'bad quality' determinant. -The latter decides if such a flag should mark the data quality as bad by default. -FlagReasons can be created only with FlagReasonFactory, so that the list of available reasons is common and centralised. -For example: -``` -id: 10 -name: Limited Acceptance -bad: true -``` -The list of available FlagReasons is defined in [etc/flagReasons.csv](etc/flagReasons.csv), which is used to generate the corresponding list of methods in FlagReasonFactory. -The existing flags should never be modified, except for marking them as obsolete. -New flags may be added via pull requests if there is no flag which conveys a similar meaning. +This document outlines the data formats used for tagging good quality data for further processing and analysis. +They allow us to describe problems affecting the data in concrete time intervals. +Using this information, data can be filtered out according to criteria specific to a given analysis type. + +### Data Quality Control workflow + +Data quality is determined through two methods: + +1. **Automated Checks:** The Quality Control framework runs Checks which may return quality Flags. +2. **Manual Review:** Detector experts review data using the Run Condition Table (RCT) and can modify or add Flags. + +Both methods utilize the same data format for Flags. +During processing (both synchronous and asynchronous), Checks produce Qualities and associate them with Flags. +The Quality Control framework then transmits these Flags to the RCT through a gRPC interface (**not ready yet**, to be done in the scope of QC-978). +Detector experts can then review the automatically generated Flags and make any necessary modifications or additions directly in the RCT. + +### Quality Control Flag Structure + +A [Quality Control Flag](include/DataFormatsQualityControl/QualityControlFlag.h) consists of the following elements: + +* **Flag Type:** This identifies the specific issue the flag represents. (More details below) +* **Time Range:** This defines the time period affected by the flag. +* **Comment (Optional):** This allows human-readable explanations for assigning the flag. +* **Source String:** This identifies the entity (person or software module) that created the flag. + +**Example:** -With [TimeRangeFlags](include/DataFormatsQualityControl/TimeRangeFlag.h) we can define the time range of a chosen FlagReason, add an additional comment and specify the source of this flag. -For example: ``` -start: 1612707603626 +flag: Limited Acceptance MC Reproducible +start: 1612707603626 end: 1613999652000 -flag: Limited Acceptance comment: Sector B in TPC inactive -source: o2::quality_control_modules::tpc::ClustersCheck +source: TPC/Clusters Check ``` -[TimeRangeFlagCollection](include/DataFormatsQualityControl/TimeRangeFlagCollection.h) contains all TimeRangeFlags for the validity range (run or fill). -TimeRangeFlags may overlap, e.g. if they use different FlagReasons and they are sorted by their start time. -If certain period does not include any TimeRangeFlags with *bad* FlagReasons, then the data quality can be considered as good. -The [TimeRangeFlagCollection test](test/testTimeRangeFlagCollection.cxx) shows the usage example. +### Flag Types + +[Flag Types](include/DataFormatsQualityControl/FlagType.h) define the specific categories of issues represented by flags. +Each Flag Type has the following attributes: + +* **Identifier Number:** A unique numerical ID for the Flag Type. +* **Name:** A human-readable name describing the issue. +* **"Bad Quality" Determinant:** This boolean constant indicates whether the type inherently signifies bad data quality. + +#### Creating and Managing Flag Types + +* **FlagTypeFactory** ensures a centralized and consistent list of available Flag Types. + New types can only be created through this factory. +* **[flagTypes.csv](etc/flagTypes.csv)** defines the existing Flag Types, including their ID, name, and "bad quality" determinant, factory method name and a switch to deprecate a flag. + The table serves as the source to automatically generate the corresponding methods in FlagTypeFactory. +* **Adding new Flag Types:** If a new issue requires a flag not currently defined, propose the addition by contacting the async QC coordinators. + They have the authority to add new Flag Types to the RCT. + These changes will then be reflected in the [flagTypes.csv](etc/flagTypes.csv) file through a pull request. +* **Modification of existing Flag Types:** Existing Flag Types should not be modified in terms of their definition. + Instead, one may create a new Flag Type and mark the existing one as obsolete in the CSV table. + This will add the `[[ deprecated ]]` attribute to the corresponding method. -TimeRangeFlagCollections are supposed to be created automatically with QC Post-processing Tasks based on Quality Objects created by QC Checks. -However, they might be created manually by QA experts as well. -The procedure to do that has to be defined. +#### Currently available Flag Types -## TODO -* Define the complete list of available Flag Reasons -* implement CCDB storage and access - - define CCDB storage place e.g. - * `/QC/QualityFlags` - * `Analysis/QualityFlags/` -* Data Tags Definitions and Data Tags +This section details the currently available Flag Types and provides a brief explanation of their intended use cases. -### Notes on plans for Data Tags +* **Good:** a Check or an expert sees nothing wrong with given time interval, but would like to add a comment. + Note that the absence of any flag for a run implies good data quality. + Thus, there is no need to mark it explicitly as such by using this flag type. +* **No Detector Data:** a complete and unexpected absence of data for a specific detector. +* **Limited Acceptance MC Not Reproducible:** a part of a detector did not acquire good data and this condition cannot be reproduced in Monte Carlo. + If an automated Check cannot determine MC reproducibility, it should default to "Not Reproducible" for later expert review. +* **Limited Acceptance MC Reproducible:** a part of a detector did not acquire good data, but this condition can be reproduced in Monte Carlo. +* **Bad Tracking:** analyses relying on accurate track reconstruction should not use this data. +* **Bad PID:** analyses relying on correct identification of all kinds of tracked particles should not use this data. +* **Bad Hadron PID:** analyses relying on correct hadron identification should not use this data. +* **Bad Electron PID:** analyses relying on correct electron identification should not use this data. +* **Bad Photon Calorimetry:** analyses relying on correct photon calorimetry should not use this data. +* **Bad EMCalorimetry:** analyses relying on correct electromagnetic calorimetry should not use this data. +* **Unknown:** the exact impact of an issue on the data is unclear, but it's likely bad. + Treat data with this flag with caution until further investigation. +* **Unknown Quality:** the quality of data could not be determined definitively. +* **Invalid:** there was an issue with processing the flags. + +## Usage in Analysis framework (plans, wishlist) + +## General idea +* RCT exports a read-only copy of the flags for each detector, run and pass combination in the CCDB. +* The Analysis framework uses the flags and user selection criteria to provide their Analysis Task with data matching these criteria. + **Data Tags** are the structures defining the good time intervals for the provided criteria. + +## Notes on plans for Data Tags Data Tag definition has: * name -* global suppression list for bad flag reasons (applies to all detectors) -* global requirement list for not bad flag reasons +* global suppression list for bad flag types (applies to all detectors) +* global requirement list for not bad flag types * list of needed detectors, * list of suppression list and requirement list specific to detectors @@ -94,10 +130,3 @@ Example configurations } ] ``` - -## Wishlist / Ideas -* executable to add flags to the flag store -* executable to extrags the flag store -* summary of all masks for one TimeRangeFlagCollection -* functionality to extract flags for a specific detector (from CCDB) -* cut class to specify detectors and flags which to exclude \ No newline at end of file From dfc1d73ec0ef309bdead06bc1de878bbf52f47e1 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Mon, 6 May 2024 08:40:34 +0200 Subject: [PATCH 0209/2997] [EMCAL-1134, EMCAL-1135] Handle TRU decoding errors (#13112) - EMCAL-1135: Define TRU error codes in ErrorTypeFEE - EMCAL-1134: Catch Mapping/Patch errors and forward to ErrorTypeFee --- .../include/DataFormatsEMCAL/ErrorTypeFEE.h | 13 +- .../Detectors/EMCAL/src/ErrorTypeFEE.cxx | 9 +- .../ReconstructionErrors.h | 126 +++++++++++-- .../src/ReconstructionErrors.cxx | 71 ++++++++ .../EMCALWorkflow/RawToCellConverterSpec.h | 35 ++++ .../workflow/src/RawToCellConverterSpec.cxx | 165 ++++++++++++------ 6 files changed, 349 insertions(+), 70 deletions(-) diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h index fb7538bee9694..cc3540cd388d3 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h @@ -58,6 +58,7 @@ class ErrorTypeFEE GEOMETRY_ERROR, ///< Decoded position outside EMCAL GAIN_ERROR, ///< Error due to gain type LINK_ERROR, ///< Error due to missing DDL links + TRU_ERROR, ///< Errors from TRU data STU_ERROR, ///< Error from STU data UNDEFINED ///< Error source undefined }; @@ -105,7 +106,11 @@ class ErrorTypeFEE /// \brief Set the error as STU decoder error and store the error code /// \param gainError Error code of the STU decoder error - void setSTUDecoderErrorType(int gainError) { setError(ErrorSource_t::STU_ERROR, gainError); } + void setSTUDecoderErrorType(int stuerror) { setError(ErrorSource_t::STU_ERROR, stuerror); } + + /// \brief Set the error as TRU decoder error and store the error code + /// \param gainError Error code of the TRU decoder error + void setTRUDecoderErrorType(int truerror) { setError(ErrorSource_t::TRU_ERROR, truerror); } /// \brief Set the error type of the object /// \param errorsource Error type of the object @@ -175,6 +180,10 @@ class ErrorTypeFEE /// \return Error code (-1 in case the object is not a STU decoder error) int getSTUDecoderErrorType() const { return getRawErrorForType(ErrorSource_t::STU_ERROR); } + /// \brief Get the error code of the obect in case the object is a TRU decoder error + /// \return Error code (-1 in case the object is not a STU decoder error) + int getTRUDecoderErrorType() const { return getRawErrorForType(ErrorSource_t::TRU_ERROR); } + /// \brief Get subspecification of the error /// \return Subspecification of the error int getSubspecification() const { return mSubspecification; } @@ -191,7 +200,7 @@ class ErrorTypeFEE /// \brief Get the number of error types /// \return Number of error types (including undefined) - static constexpr int getNumberOfErrorTypes() { return 9; } + static constexpr int getNumberOfErrorTypes() { return 10; } /// \brief Get the name of the error type /// \param errorTypeID ID of the error type diff --git a/DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx b/DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx index 25d1addf4b41b..21d985b2a832a 100644 --- a/DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx +++ b/DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx @@ -37,6 +37,9 @@ void ErrorTypeFEE::PrintStream(std::ostream& stream) const case ErrorSource_t::GAIN_ERROR: typestring = "gain type error"; break; + case ErrorSource_t::TRU_ERROR: + typestring = "STU decoder error"; + break; case ErrorSource_t::STU_ERROR: typestring = "STU decoder error"; break; @@ -74,6 +77,8 @@ const char* ErrorTypeFEE::getErrorTypeName(unsigned int errorTypeID) return "Geometry"; case ErrorSource_t::GAIN_ERROR: return "GainType"; + case ErrorSource_t::TRU_ERROR: + return "TRUDecoding"; case ErrorSource_t::STU_ERROR: return "STUDecoding"; case ErrorSource_t::LINK_ERROR: @@ -100,8 +105,10 @@ const char* ErrorTypeFEE::getErrorTypeTitle(unsigned int errorTypeID) return "Geometry"; case ErrorSource_t::GAIN_ERROR: return "Gain"; + case ErrorSource_t::TRU_ERROR: + return "TRU Decoding"; case ErrorSource_t::STU_ERROR: - return "STUDecoding"; + return "STU Decoding"; case ErrorSource_t::LINK_ERROR: return "Link missing"; case ErrorSource_t::UNDEFINED: diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/ReconstructionErrors.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/ReconstructionErrors.h index 49dd4d34b6937..ceab0333b15b7 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/ReconstructionErrors.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/ReconstructionErrors.h @@ -163,18 +163,18 @@ GainError_t getGainErrorFromErrorCode(unsigned int errorcode); /// Name is a short single word descriptor used i.e. in /// object names. /// -/// \param errortype Error type of the gain error -/// \return Name connected to gain error type +/// \param errortype Error type of the gain type error +/// \return Name connected to gain type error const char* getGainErrorName(GainError_t errortype); /// \brief Get name of a given gain error code /// /// Name is a short single word descriptor used i.e. in /// object names. Attention: Error code must be a valid -/// geomentry error code. +/// gain type error code. /// -/// \param errorcode Error code of the gain error -/// \return Name connected to gain error type +/// \param errorcode Error code of the gain type error +/// \return Name connected to gain type error const char* getGainErrorName(unsigned int errorcode); /// \brief Get title of a given gain error type @@ -182,37 +182,133 @@ const char* getGainErrorName(unsigned int errorcode); /// Title is a short descriptor used i.e. in /// histogram titles. /// -/// \param errortype Error type of the gain error -/// \return Title connected to gain error type +/// \param errortype Error type of the gain type error +/// \return Title connected to gain type error const char* getGainErrorTitle(GainError_t errortype); /// \brief Get title of a given gain error type /// /// Title is a short descriptor used i.e. in /// histogram titles. Attention: Error code must -/// be a valid geomentry error code. +/// be a valid gain type error code. /// -/// \param errorcode Error code of the gain error -/// \return Title connected to gain error type +/// \param errorcode Error code of the gain type error +/// \return Title connected to gain type error const char* getGainErrorTitle(unsigned int errorcode); /// \brief Get detailed description of a given gain error type /// /// Provides a long description to be used i.e. in error messages. /// -/// \param errortype Error type of the gain error -/// \return Detaied description connected to gain error type +/// \param errortype Error type of the gain type error +/// \return Detaied description connected to gain type error const char* getGainErrorDescription(GainError_t errortype); /// \brief Get detailed description of a given gain error type /// /// Provides a long description to be used i.e. in error messages. -/// Attention: Error code must be a valid gain error code. +/// Attention: Error code must be a valid gain type error code. /// -/// \param errortype Error type of the geometry error -/// \return Detaied description connected to gain error type +/// \param errortype Error type of the gain type error +/// \return Detaied description connected to gain type error const char* getGainErrorDescription(unsigned int errorcode); +/// \enum TRUDecodingError_t +/// \brief Errors related to TRU data decoding +/// \ingroup EMCALReconstruction +/// +/// TRU decoding errors appear during the decoding of the TRU data. +/// They can be raised by the trigger mapping, in case an invalid +/// FastOR index or TRU index is called, or by the TRU data handler if +/// the patch index is outside range. +enum class TRUDecodingError_t { + TRU_INDEX_INVALID, ///< TRU index invalid + PATCH_INDEX_INVALID, ///< Patch index outside range + FASTOR_INDEX_INVALID, ///< FastOR index unknown + UNKNOWN_ERROR ///< Unknown error type +}; + +/// \brief Convert error code to TRU decoding error type +/// +/// Attention: Error code must be a valid error code, handled +/// internally via assert. +/// +/// \param errorcode Error code to be converted +/// \return Error type connected to error code +TRUDecodingError_t getTRUDecodingErrorFromErrorCode(unsigned int errorcode); + +/// \brief Convert TRU decoding error type into numberic representation +/// \param errortype TRU decoding error type +/// \return Error code connected to error type +constexpr int getErrorCodeFromTRUDecodingError(TRUDecodingError_t error) +{ + switch (error) { + case TRUDecodingError_t::TRU_INDEX_INVALID: + return 0; + case TRUDecodingError_t::PATCH_INDEX_INVALID: + return 1; + case TRUDecodingError_t::FASTOR_INDEX_INVALID: + return 2; + case TRUDecodingError_t::UNKNOWN_ERROR: + return -1; + } +} + +/// \brief Get name of a given TRU decoding error type +/// +/// Name is a short single word descriptor used i.e. in +/// object names. +/// +/// \param errortype Error type of the TRU decoding error +/// \return Name connected to TRU decoding error type +const char* getTRUDecodingErrorName(TRUDecodingError_t errortype); + +/// \brief Get name of a given TRU decoding error code +/// +/// Name is a short single word descriptor used i.e. in +/// object names. Attention: Error code must be a valid +/// TRU decoding error code. +/// +/// \param errorcode Error code of the TRU decoding error +/// \return Name connected to TRU decoding error type +const char* getTRUDecodingErrorName(unsigned int errorcode); + +/// \brief Get title of a given TRU decoding error type +/// +/// Title is a short descriptor used i.e. in +/// histogram titles. +/// +/// \param errortype Error type of the TRU decoding error +/// \return Title connected to TRU decoding error +const char* getTRUDecodingErrorTitle(TRUDecodingError_t errortype); + +/// \brief Get title of a given TRU decoding error type +/// +/// Title is a short descriptor used i.e. in +/// histogram titles. Attention: Error code must +/// be a valid TRU decoding error code. +/// +/// \param errorcode Error code of the TRU decoding error +/// \return Title connected to TRU decoding error +const char* getTRUDecodingErrorTitle(unsigned int errorcode); + +/// \brief Get detailed description of a given TRU decoding error type +/// +/// Provides a long description to be used i.e. in error messages. +/// +/// \param errortype Error type of the TRU decoding error +/// \return Detaied description connected to TRU decoding error +const char* getTRUDecodingErrorErrorDescription(TRUDecodingError_t errortype); + +/// \brief Get detailed description of a given TRU decoding error type +/// +/// Provides a long description to be used i.e. in error messages. +/// Attention: Error code must be a valid TRU decoding error code. +/// +/// \param errortype Error type of the TRU decoding error +/// \return Detaied description connected to TRU decoding error +const char* getTRUDecodingErrorErrorDescription(unsigned int errorcode); + } // namespace reconstructionerrors } // namespace emcal diff --git a/Detectors/EMCAL/reconstruction/src/ReconstructionErrors.cxx b/Detectors/EMCAL/reconstruction/src/ReconstructionErrors.cxx index 30f2a403daac0..d2e5ea6d92a6f 100644 --- a/Detectors/EMCAL/reconstruction/src/ReconstructionErrors.cxx +++ b/Detectors/EMCAL/reconstruction/src/ReconstructionErrors.cxx @@ -147,6 +147,77 @@ const char* getGainErrorDescription(unsigned int errorcode) return getGainErrorDescription(getGainErrorFromErrorCode(errorcode)); } +TRUDecodingError_t getTRUDecodingErrorFromErrorCode(unsigned int errorcode) +{ + switch (errorcode) { + case 0: + return TRUDecodingError_t::TRU_INDEX_INVALID; + case 1: + return TRUDecodingError_t::PATCH_INDEX_INVALID; + case 2: + return TRUDecodingError_t::FASTOR_INDEX_INVALID; + default: + return TRUDecodingError_t::UNKNOWN_ERROR; + } +} + +const char* getTRUDecodingErrorName(TRUDecodingError_t errortype) +{ + switch (errortype) { + case TRUDecodingError_t::TRU_INDEX_INVALID: + return "TRUIndexInvalid"; + case TRUDecodingError_t::PATCH_INDEX_INVALID: + return "PatchIndexInvalid"; + case TRUDecodingError_t::FASTOR_INDEX_INVALID: + return "FastORIndexInvalid"; + default: + return "UnknownError"; + } +} + +const char* getTRUDecodingErrorName(unsigned int errorcode) +{ + return getTRUDecodingErrorName(getTRUDecodingErrorFromErrorCode(errorcode)); +} + +const char* getTRUDecodingErrorTitle(TRUDecodingError_t errortype) +{ + switch (errortype) { + case TRUDecodingError_t::TRU_INDEX_INVALID: + return "TRU index invalid"; + case TRUDecodingError_t::PATCH_INDEX_INVALID: + return "Patch index invalid"; + case TRUDecodingError_t::FASTOR_INDEX_INVALID: + return "FastOR index invalid"; + default: + return "Unknown error"; + } +} + +const char* getTRUDecodingErrorTitle(unsigned int errortype) +{ + return getTRUDecodingErrorTitle(getTRUDecodingErrorFromErrorCode(errortype)); +} + +const char* getTRUDecodingErrorErrorDescription(TRUDecodingError_t errortype) +{ + switch (errortype) { + case TRUDecodingError_t::TRU_INDEX_INVALID: + return "TRU index is invalid"; + case TRUDecodingError_t::PATCH_INDEX_INVALID: + return "Patch index is invalid"; + case TRUDecodingError_t::FASTOR_INDEX_INVALID: + return "FastOR index is invalid"; + default: + return "Unknown error"; + } +} + +const char* getTRUDecodingErrorErrorDescription(unsigned int errorcode) +{ + return getTRUDecodingErrorErrorDescription(getTRUDecodingErrorFromErrorCode(errorcode)); +} + } // namespace reconstructionerrors } // namespace emcal diff --git a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h index 52797719d1fed..78436eedfd522 100644 --- a/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h +++ b/Detectors/EMCAL/workflow/include/EMCALWorkflow/RawToCellConverterSpec.h @@ -42,6 +42,8 @@ class AltroDecoderError; class Channel; class MinorAltroDecodingError; class RawDecodingError; +class FastORIndexException; +class TRUIndexException; namespace reco_workflow { @@ -453,6 +455,39 @@ class RawToCellConverterSpec : public framework::Task /// produced. void handleMinorPageError(const RawReaderMemory::MinorError& error); + /// \brief Handler function for FastOR indexing errors + /// \param error FastOR index error + /// \param linkID DDL raising the exception + /// \param indexTRU TRU raising the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. + void handleFastORErrors(const FastORIndexException& error, unsigned int linkID, unsigned int indexTRU); + + /// \brief Handler function patch index exception + /// \param error Patch index error + /// \param linkID DDL raising the exception + /// \param indexTRU TRU raising the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. + void handlePatchError(const TRUDataHandler::PatchIndexException& error, unsigned int linkID, unsigned int indexTRU); + + /// \brief Handler function for TRU index exception + /// \param error TRU index error + /// \param linkID DDL raising the exception + /// \param hwaddress Hardware address of the channel raising the exception + /// + /// Errors are printed to the infoLogger until a user-defiened + /// threshold is reached. In case the export of decoder errors + /// is activated an error object with additional information is + /// produced. + void handleTRUIndexError(const TRUIndexException& error, unsigned int linkID, unsigned int hwaddress); + header::DataHeader::SubSpecificationType mSubspecification = 0; ///< Subspecification for output channels int mNoiseThreshold = 0; ///< Noise threshold in raw fit int mNumErrorMessages = 0; ///< Current number of error messages diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index 4e90aef881415..26167cf2c3d27 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx @@ -32,6 +32,7 @@ #include "DetectorsRaw/RDHUtils.h" #include "EMCALBase/Geometry.h" #include "EMCALBase/Mapper.h" +#include "EMCALBase/TriggerMappingErrors.h" #include "EMCALCalib/FeeDCS.h" #include "EMCALReconstruction/CaloFitResults.h" #include "EMCALReconstruction/Bunch.h" @@ -495,64 +496,76 @@ void RawToCellConverterSpec::addFEEChannelToEvent(o2::emcal::EventContainer& cur void RawToCellConverterSpec::addTRUChannelToEvent(o2::emcal::EventContainer& currentEvent, const o2::emcal::Channel& currentchannel, const LocalPosition& position) { - auto tru = mTriggerMapping->getTRUIndexFromOnlineHardareAddree(currentchannel.getHardwareAddress(), position.mFeeID, position.mSupermoduleID); - if (position.mColumn >= 96 && position.mColumn <= 105) { - auto& trudata = currentEvent.getTRUData(tru); - // Trigger patch information encoded columns 95-105 - for (auto& bunch : currentchannel.getBunches()) { - LOG(debug) << "Found bunch of length " << static_cast(bunch.getBunchLength()) << " with start time " << static_cast(bunch.getStartTime()) << " (column " << static_cast(position.mColumn) << ")"; - auto l0time = bunch.getStartTime(); - int isample = 0; - for (auto& adc : bunch.getADC()) { - // patch word might be in any of the samples, need to check all of them - // in case of colum 105 the first 6 bits are the patch word, the remaining 4 bits are the header word - if (adc == 0) { - isample++; - continue; - } - if (position.mColumn == 105) { - std::bitset<6> patchBits(adc & 0x3F); - std::bitset<4> headerbits((adc >> 6) & 0xF); - for (auto localindex = 0; localindex < patchBits.size(); localindex++) { - if (patchBits.test(localindex)) { - auto globalindex = (position.mColumn - 96) * 10 + localindex; - LOG(debug) << "Found patch with index " << globalindex << " in sample " << isample; - // std::cout << "Found patch with index " << globalindex << " in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; - trudata.setPatch(globalindex, bunch.getStartTime() - isample); - } - } - if (headerbits.test(2)) { - LOG(debug) << "TRU " << tru << ": Found TRU fired (" << tru << ") in sample " << isample; - // std::cout << "TRU " << tru << ": Found TRU fired (" << tru << ") in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; - trudata.setFired(true); - trudata.setL0time(bunch.getStartTime() - isample); + try { + auto tru = mTriggerMapping->getTRUIndexFromOnlineHardareAddree(currentchannel.getHardwareAddress(), position.mFeeID, position.mSupermoduleID); + if (position.mColumn >= 96 && position.mColumn <= 105) { + auto& trudata = currentEvent.getTRUData(tru); + // Trigger patch information encoded columns 95-105 + for (auto& bunch : currentchannel.getBunches()) { + LOG(debug) << "Found bunch of length " << static_cast(bunch.getBunchLength()) << " with start time " << static_cast(bunch.getStartTime()) << " (column " << static_cast(position.mColumn) << ")"; + auto l0time = bunch.getStartTime(); + int isample = 0; + for (auto& adc : bunch.getADC()) { + // patch word might be in any of the samples, need to check all of them + // in case of colum 105 the first 6 bits are the patch word, the remaining 4 bits are the header word + if (adc == 0) { + isample++; + continue; } - } else { - std::bitset<10> patchBits(adc & 0x3FF); - for (auto localindex = 0; localindex < patchBits.size(); localindex++) { - if (patchBits.test(localindex)) { - auto globalindex = (position.mColumn - 96) * 10 + localindex; - LOG(debug) << "TRU " << tru << ": Found patch with index " << globalindex << " in sample " << isample; - // std::cout << "TRU " << tru << ": Found patch with index " << globalindex << " in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; - trudata.setPatch(globalindex, bunch.getStartTime() - isample); + if (position.mColumn == 105) { + std::bitset<6> patchBits(adc & 0x3F); + std::bitset<4> headerbits((adc >> 6) & 0xF); + for (auto localindex = 0; localindex < patchBits.size(); localindex++) { + if (patchBits.test(localindex)) { + auto globalindex = (position.mColumn - 96) * 10 + localindex; + LOG(debug) << "Found patch with index " << globalindex << " in sample " << isample; + // std::cout << "Found patch with index " << globalindex << " in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; + trudata.setPatch(globalindex, bunch.getStartTime() - isample); + } + } + if (headerbits.test(2)) { + LOG(debug) << "TRU " << tru << ": Found TRU fired (" << tru << ") in sample " << isample; + // std::cout << "TRU " << tru << ": Found TRU fired (" << tru << ") in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; + trudata.setFired(true); + trudata.setL0time(bunch.getStartTime() - isample); + } + } else { + std::bitset<10> patchBits(adc & 0x3FF); + for (auto localindex = 0; localindex < patchBits.size(); localindex++) { + if (patchBits.test(localindex)) { + auto globalindex = (position.mColumn - 96) * 10 + localindex; + LOG(debug) << "TRU " << tru << ": Found patch with index " << globalindex << " in sample " << isample; + // std::cout << "TRU " << tru << ": Found patch with index " << globalindex << " in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; + try { + trudata.setPatch(globalindex, bunch.getStartTime() - isample); + } catch (TRUDataHandler::PatchIndexException& e) { + handlePatchError(e, position.mFeeID, tru); + } + } } } + isample++; } - isample++; + } + } else { + try { + auto absFastOR = mTriggerMapping->getAbsFastORIndexFromIndexInTRU(tru, position.mColumn); + for (auto& bunch : currentchannel.getBunches()) { + // FastOR data reversed internally (positive in time direction) + // -> Start time marks the first timebin, consequently it must be also reversed. + // std::cout << "Adding non-reversed FastOR time series for FastOR " << absFastOR << " (TRU " << tru << ", index " << static_cast(position.mColumn) << ") with start time " << static_cast(bunch.getStartTime()) << " (reversed " << bunch.getStartTime() + 1 - bunch.getADC().size() << "): "; + // for (auto adc : bunch.getADC()) { + // std::cout << adc << ", "; + //} + // std::cout << std::endl; + currentEvent.setFastOR(absFastOR, bunch.getStartTime(), bunch.getADC()); + } + } catch (FastORIndexException& e) { + handleFastORErrors(e, position.mFeeID, tru); } } - } else { - auto absFastOR = mTriggerMapping->getAbsFastORIndexFromIndexInTRU(tru, position.mColumn); - for (auto& bunch : currentchannel.getBunches()) { - // FastOR data reversed internally (positive in time direction) - // -> Start time marks the first timebin, consequently it must be also reversed. - // std::cout << "Adding non-reversed FastOR time series for FastOR " << absFastOR << " (TRU " << tru << ", index " << static_cast(position.mColumn) << ") with start time " << static_cast(bunch.getStartTime()) << " (reversed " << bunch.getStartTime() + 1 - bunch.getADC().size() << "): "; - // for (auto adc : bunch.getADC()) { - // std::cout << adc << ", "; - //} - // std::cout << std::endl; - currentEvent.setFastOR(absFastOR, bunch.getStartTime(), bunch.getADC()); - } + } catch (TRUIndexException& e) { + handleTRUIndexError(e, position.mFeeID, currentchannel.getHardwareAddress()); } } @@ -908,6 +921,54 @@ void RawToCellConverterSpec::handleMinorPageError(const RawReaderMemory::MinorEr } } +void RawToCellConverterSpec::handleFastORErrors(const FastORIndexException& e, unsigned int linkID, unsigned int indexTRU) +{ + if (mCreateRawDataErrors) { + mOutputDecoderErrors.emplace_back(linkID, ErrorTypeFEE::ErrorSource_t::TRU_ERROR, reconstructionerrors::getErrorCodeFromTRUDecodingError(reconstructionerrors::TRUDecodingError_t::TRU_INDEX_INVALID), indexTRU, -1); + } + if (mNumErrorMessages < mMaxErrorMessages) { + LOG(warning) << " TRU decoding: " << e.what() << " in FEE ID " << linkID << ", TRU " << indexTRU; + mNumErrorMessages++; + if (mNumErrorMessages == mMaxErrorMessages) { + LOG(warning) << "Max. amount of error messages (" << mMaxErrorMessages << " reached, further messages will be suppressed"; + } + } else { + mErrorMessagesSuppressed++; + } +} + +void RawToCellConverterSpec::handlePatchError(const TRUDataHandler::PatchIndexException& e, unsigned int linkID, unsigned int indexTRU) +{ + if (mCreateRawDataErrors) { + mOutputDecoderErrors.emplace_back(linkID, ErrorTypeFEE::ErrorSource_t::TRU_ERROR, reconstructionerrors::getErrorCodeFromTRUDecodingError(reconstructionerrors::TRUDecodingError_t::PATCH_INDEX_INVALID), indexTRU, -1); + } + if (mNumErrorMessages < mMaxErrorMessages) { + LOG(warning) << " TRU decoding: " << e.what() << " in FEE ID " << linkID << ", TRU " << indexTRU; + mNumErrorMessages++; + if (mNumErrorMessages == mMaxErrorMessages) { + LOG(warning) << "Max. amount of error messages (" << mMaxErrorMessages << " reached, further messages will be suppressed"; + } + } else { + mErrorMessagesSuppressed++; + } +} + +void RawToCellConverterSpec::handleTRUIndexError(const TRUIndexException& e, unsigned int linkID, unsigned int hwaddress) +{ + if (mCreateRawDataErrors) { + mOutputDecoderErrors.emplace_back(linkID, ErrorTypeFEE::ErrorSource_t::TRU_ERROR, reconstructionerrors::getErrorCodeFromTRUDecodingError(reconstructionerrors::TRUDecodingError_t::PATCH_INDEX_INVALID), e.getTRUIndex(), hwaddress); + } + if (mNumErrorMessages < mMaxErrorMessages) { + LOG(warning) << " TRU decoding: " << e.what() << " in FEE ID " << linkID << ", TRU " << e.getTRUIndex() << "(hardware address: " << hwaddress << ")"; + mNumErrorMessages++; + if (mNumErrorMessages == mMaxErrorMessages) { + LOG(warning) << "Max. amount of error messages (" << mMaxErrorMessages << " reached, further messages will be suppressed"; + } + } else { + mErrorMessagesSuppressed++; + } +} + void RawToCellConverterSpec::sendData(framework::ProcessingContext& ctx) const { constexpr auto originEMC = o2::header::gDataOriginEMC; From 589c192aa2832d7c0dadcc6b983d51fff9d68e9e Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Mon, 6 May 2024 17:25:36 +0200 Subject: [PATCH 0210/2997] [EMCAL-1134] Handle leftover case (#13115) --- .../include/EMCALReconstruction/ReconstructionErrors.h | 4 ++++ Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/ReconstructionErrors.h b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/ReconstructionErrors.h index ceab0333b15b7..2f09c83140ec0 100644 --- a/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/ReconstructionErrors.h +++ b/Detectors/EMCAL/reconstruction/include/EMCALReconstruction/ReconstructionErrors.h @@ -228,6 +228,10 @@ enum class TRUDecodingError_t { UNKNOWN_ERROR ///< Unknown error type }; +/// \brief Get the number of TRU error codes +/// \return Number of TRU error codes +constexpr int getNumberOfTRUErrorCodes() { return 3; } + /// \brief Convert error code to TRU decoding error type /// /// Attention: Error code must be a valid error code, handled diff --git a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx index 26167cf2c3d27..55f464644ab73 100644 --- a/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx +++ b/Detectors/EMCAL/workflow/src/RawToCellConverterSpec.cxx @@ -520,7 +520,11 @@ void RawToCellConverterSpec::addTRUChannelToEvent(o2::emcal::EventContainer& cur auto globalindex = (position.mColumn - 96) * 10 + localindex; LOG(debug) << "Found patch with index " << globalindex << " in sample " << isample; // std::cout << "Found patch with index " << globalindex << " in sample " << isample << " (" << (bunch.getStartTime() - isample) << ")" << std::endl; - trudata.setPatch(globalindex, bunch.getStartTime() - isample); + try { + trudata.setPatch(globalindex, bunch.getStartTime() - isample); + } catch (TRUDataHandler::PatchIndexException& e) { + handlePatchError(e, position.mFeeID, tru); + } } } if (headerbits.test(2)) { From 4e7202236435d771ca884a70110eeef41c03ec58 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 3 May 2024 11:52:38 +0200 Subject: [PATCH 0211/2997] GPU CMake: There are no special HIP No Fast Math flags, use $GPUCA_CXX_NO_FAST_MATH_FLAGS --- GPU/GPUTracking/Base/hip/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/hip/CMakeLists.txt b/GPU/GPUTracking/Base/hip/CMakeLists.txt index 151eb5ae3930a..cadbe788e46a7 100644 --- a/GPU/GPUTracking/Base/hip/CMakeLists.txt +++ b/GPU/GPUTracking/Base/hip/CMakeLists.txt @@ -244,7 +244,7 @@ elseif(GPUCA_HIP_COMPILE_MODE STREQUAL "perkernel") ${O2_GPU_KERNEL_WRAPPER_FOLDER}/krnl_GPUTPCDecompressionKernels_step1unattached.hip TARGET_DIRECTORY ${targetName} PROPERTIES - COMPILE_FLAGS "${GPUCA_HIP_NO_FAST_MATH_FLAGS}" + COMPILE_FLAGS "${GPUCA_CXX_NO_FAST_MATH_FLAGS}" COMPILE_DEFINITIONS "GPUCA_NO_FAST_MATH") elseif(GPUCA_HIP_COMPILE_MODE STREQUAL "rdc") message(FATAL_ERROR "HIP RDC compilation of GPUReconstruction ios not yet working!") From 65e2bd713f524c7b6e1b95310905f0edf140ce1b Mon Sep 17 00:00:00 2001 From: iravasen Date: Tue, 7 May 2024 08:44:53 +0200 Subject: [PATCH 0212/2997] s curve points for threshold scans in the root trees (#13114) --- .../ITSWorkflow/ThresholdCalibratorSpec.h | 7 +- .../workflow/src/ThresholdCalibratorSpec.cxx | 93 +++++++++++++------ 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h index 07761f20fd872..18fd2bda0c4df 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h @@ -161,6 +161,7 @@ class ITSThresholdCalibrator : public Task // Tree to save threshold info in full threshold scan case TFile* mRootOutfile = nullptr; TTree* mThresholdTree = nullptr; + TTree* mScTree = nullptr; TTree* mSlopeTree = nullptr; short int vChipid[N_COL]; short int vRow[N_COL]; @@ -169,9 +170,11 @@ class ITSThresholdCalibrator : public Task float vNoise[N_COL]; unsigned char vPoints[N_COL]; short int vMixData[N_COL]; - unsigned char vCharge[N_COL]; float vSlope[N_COL]; float vIntercept[N_COL]; + unsigned char vCharge[N_COL]; + unsigned char vHits[N_COL]; + short int mColStep = 8; // save s-curves to tree every mColStep pixels on 1 row // Initialize pointers for doing error function fits TH1F* mFitHist = nullptr; @@ -231,7 +234,7 @@ class ITSThresholdCalibrator : public Task short int mRunTypeUp = -1; short int mRunTypeRU[N_RU] = {0}; short int mRunTypeChip[24120] = {0}; - short int mChipLastRow[24120] = {-1}; + short int mChipLastRow[24120] = {0}; bool mActiveLinks[N_RU][3] = {{false}}; std::set mRuSet; short int mRu = 0; diff --git a/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx index 391ef5c38677c..895e70866e5ba 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx @@ -67,6 +67,15 @@ void ITSThresholdCalibrator::init(InitContext& ic) { LOGF(info, "ITSThresholdCalibrator init...", mSelfName); + for (int i = 0; i < 24120; i++) { + mChipLastRow[i] = -1; + } + + mColStep = ic.options().get("s-curve-col-step"); + if (mColStep >= N_COL) { + LOG(warning) << "mColStep = " << mColStep << ": saving s-curves of only 1 pixel (pix 0) per row"; + } + std::string fittype = ic.options().get("fittype"); if (fittype == "derivative") { this->mFitType = DERIVATIVE; @@ -359,41 +368,49 @@ void ITSThresholdCalibrator::initThresholdTree(bool recreate /*=true*/) // Initialize ROOT output file // to prevent premature external usage, use temporary name const char* option = recreate ? "RECREATE" : "UPDATE"; - this->mRootOutfile = new TFile(filename.c_str(), option); + mRootOutfile = new TFile(filename.c_str(), option); + + // Tree containing the s-curves points + mScTree = new TTree("s-curve-points", "s-curve-points"); + mScTree->Branch("chipid", &vChipid, "vChipID[1024]/S"); + mScTree->Branch("row", &vRow, "vRow[1024]/S"); // Initialize output TTree branches - this->mThresholdTree = new TTree("ITS_calib_tree", "ITS_calib_tree"); - this->mThresholdTree->Branch("chipid", &vChipid, "vChipID[1024]/S"); - this->mThresholdTree->Branch("row", &vRow, "vRow[1024]/S"); - if (this->mScanType == 'T') { - this->mThresholdTree->Branch("thr", &vThreshold, "vThreshold[1024]/S"); - this->mThresholdTree->Branch("noise", &vNoise, "vNoise[1024]/F"); - this->mThresholdTree->Branch("spoints", &vPoints, "vPoints[1024]/b"); - this->mThresholdTree->Branch("success", &vSuccess, "vSuccess[1024]/O"); + mThresholdTree = new TTree("ITS_calib_tree", "ITS_calib_tree"); + mThresholdTree->Branch("chipid", &vChipid, "vChipID[1024]/S"); + mThresholdTree->Branch("row", &vRow, "vRow[1024]/S"); + if (mScanType == 'T') { + mThresholdTree->Branch("thr", &vThreshold, "vThreshold[1024]/S"); + mThresholdTree->Branch("noise", &vNoise, "vNoise[1024]/F"); + mThresholdTree->Branch("spoints", &vPoints, "vPoints[1024]/b"); + mThresholdTree->Branch("success", &vSuccess, "vSuccess[1024]/O"); + + mScTree->Branch("chg", &vCharge, "vCharge[1024]/b"); + mScTree->Branch("hits", &vHits, "vHits[1024]/b"); } else if (mScanType == 'D' || mScanType == 'A') { // this->mScanType == 'D' and this->mScanType == 'A' - this->mThresholdTree->Branch("n_hits", &vThreshold, "vThreshold[1024]/S"); + mThresholdTree->Branch("n_hits", &vThreshold, "vThreshold[1024]/S"); } else if (mScanType == 'P') { - this->mThresholdTree->Branch("n_hits", &vThreshold, "vThreshold[1024]/S"); - this->mThresholdTree->Branch("strobedel", &vMixData, "vMixData[1024]/S"); + mThresholdTree->Branch("n_hits", &vThreshold, "vThreshold[1024]/S"); + mThresholdTree->Branch("strobedel", &vMixData, "vMixData[1024]/S"); } else if (mScanType == 'p') { - this->mThresholdTree->Branch("n_hits", &vThreshold, "vThreshold[1024]/S"); - this->mThresholdTree->Branch("strobedel", &vMixData, "vMixData[1024]/S"); - this->mThresholdTree->Branch("charge", &vCharge, "vCharge[1024]/b"); + mThresholdTree->Branch("n_hits", &vThreshold, "vThreshold[1024]/S"); + mThresholdTree->Branch("strobedel", &vMixData, "vMixData[1024]/S"); + mThresholdTree->Branch("charge", &vCharge, "vCharge[1024]/b"); if (doSlopeCalculation) { - this->mSlopeTree = new TTree("line_tree", "line_tree"); - this->mSlopeTree->Branch("chipid", &vChipid, "vChipID[1024]/S"); - this->mSlopeTree->Branch("row", &vRow, "vRow[1024]/S"); - this->mSlopeTree->Branch("slope", &vSlope, "vSlope[1024]/F"); - this->mSlopeTree->Branch("intercept", &vIntercept, "vIntercept[1024]/F"); + mSlopeTree = new TTree("line_tree", "line_tree"); + mSlopeTree->Branch("chipid", &vChipid, "vChipID[1024]/S"); + mSlopeTree->Branch("row", &vRow, "vRow[1024]/S"); + mSlopeTree->Branch("slope", &vSlope, "vSlope[1024]/F"); + mSlopeTree->Branch("intercept", &vIntercept, "vIntercept[1024]/F"); } } else if (mScanType == 'R') { - this->mThresholdTree->Branch("n_hits", &vThreshold, "vThreshold[1024]/S"); - this->mThresholdTree->Branch("vresetd", &vMixData, "vMixData[1024]/S"); + mThresholdTree->Branch("n_hits", &vThreshold, "vThreshold[1024]/S"); + mThresholdTree->Branch("vresetd", &vMixData, "vMixData[1024]/S"); } else if (mScanType == 'r') { - this->mThresholdTree->Branch("thr", &vThreshold, "vThreshold[1024]/S"); - this->mThresholdTree->Branch("noise", &vNoise, "vNoise[1024]/F"); - this->mThresholdTree->Branch("success", &vSuccess, "vSuccess[1024]/O"); - this->mThresholdTree->Branch("vresetd", &vMixData, "vMixData[1024]/S"); + mThresholdTree->Branch("thr", &vThreshold, "vThreshold[1024]/S"); + mThresholdTree->Branch("noise", &vNoise, "vNoise[1024]/F"); + mThresholdTree->Branch("success", &vSuccess, "vSuccess[1024]/O"); + mThresholdTree->Branch("vresetd", &vMixData, "vMixData[1024]/S"); } return; @@ -770,7 +787,18 @@ void ITSThresholdCalibrator::extractThresholdRow(const short int& chipID, const this->saveThreshold(); // save before moving to the next vresetd } } - } + + // Fill the ScTree tree + if (mScanType == 'T' || mScanType == 'I' || mScanType == 'V') { // TODO: store also for other scans? + for (int ichg = mMin; ichg <= mMax; ichg++) { + for (short int col_i = 0; col_i < this->N_COL; col_i += mColStep) { + vCharge[col_i] = ichg; + vHits[col_i] = mPixelHits[chipID][row][col_i][0][ichg - mMin]; + } + mScTree->Fill(); + } + } + } // end of the else // Saves threshold information to internal memory if (mScanType != 'P' && mScanType != 'p' && mScanType != 'R' && mScanType != 'r') { @@ -823,20 +851,24 @@ void ITSThresholdCalibrator::saveThreshold() void ITSThresholdCalibrator::finalizeOutput() { // Check that objects actually exist in memory - if (!(this->mRootOutfile) || !(this->mThresholdTree) || (doSlopeCalculation && !(this->mSlopeTree))) { + if (!(mScTree) || !(this->mRootOutfile) || !(this->mThresholdTree) || (doSlopeCalculation && !(this->mSlopeTree))) { return; } // Ensure that everything has been written to the ROOT file this->mRootOutfile->cd(); this->mThresholdTree->Write(nullptr, TObject::kOverwrite); + this->mScTree->Write(nullptr, TObject::kOverwrite); + if (doSlopeCalculation) { this->mSlopeTree->Write(nullptr, TObject::kOverwrite); } - // Clean up the mThresholdTree and ROOT output file + // Clean up the mThresholdTree, mScTree and ROOT output file delete this->mThresholdTree; this->mThresholdTree = nullptr; + delete mScTree; + mScTree = nullptr; if (doSlopeCalculation) { delete this->mSlopeTree; this->mSlopeTree = nullptr; @@ -2015,7 +2047,8 @@ DataProcessorSpec getITSThresholdCalibratorSpec(const ITSCalibInpConf& inpConf) {"finalize-at-eos", VariantType::Bool, false, {"Call the finalize() method at the end of stream: to be used in case end-of-run flags are not available so to force calculations at end of run"}}, {"charge-a", VariantType::Int, 0, {"To use with --calculate-slope, it defines the charge (in DAC) for the 1st point used for the slope calculation"}}, {"charge-b", VariantType::Int, 0, {"To use with --calculate-slope, it defines the charge (in DAC) for the 2nd point used for the slope calculation"}}, - {"meb-select", VariantType::Int, -1, {"Select from which multi-event buffer consider the hits: 0,1 or 2"}}}}; + {"meb-select", VariantType::Int, -1, {"Select from which multi-event buffer consider the hits: 0,1 or 2"}}, + {"s-curve-col-step", VariantType::Int, 8, {"save s-curves points to tree every s-curve-col-step pixels on 1 row"}}}}; } } // namespace its } // namespace o2 From 96518eded242e1a3136b6dc0da23c2471f647de9 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 7 May 2024 12:07:56 +0200 Subject: [PATCH 0213/2997] FST: Digitization must use '--early-forward-policy always' , otherwise DPL serializes it --- prodtests/full_system_test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index dd2d71f76c6c0..e429ee7ad078b 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -140,8 +140,8 @@ taskwrapper sim.log o2-sim ${FST_BFIELD+--field=}${FST_BFIELD} --seed $O2SIMSEED if [[ $DO_EMBEDDING == 1 ]]; then taskwrapper embed.log o2-sim ${FST_BFIELD+--field=}${FST_BFIELD} -j $NJOBS --run ${RUNNUMBER} -n $NEvents -g pythia8pp -e ${FST_MC_ENGINE} -o sig --configKeyValues ${FST_EMBEDDING_CONFIG} --embedIntoFile o2sim_Kine.root fi -taskwrapper digi.log o2-sim-digitizer-workflow -n $NEvents ${DIGIQED} ${NOMCLABELS} --sims ${SIM_SOURCES} --tpc-lanes $((NJOBS < 36 ? NJOBS : 36)) --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} ${DIGITOPT} --configKeyValues "\"${DIGITOPTKEY}\"" --interactionRate $FST_COLRATE -[[ $SPLITTRDDIGI == "1" ]] && taskwrapper digiTRD.log o2-sim-digitizer-workflow -n $NEvents ${NOMCLABELS} --onlyDet TRD --trd-digit-downscaling ${DIGITDOWNSCALINGTRD} --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} --incontext collisioncontext.root --configKeyValues "\"${DIGITOPTKEYTRD}\"" +taskwrapper digi.log o2-sim-digitizer-workflow -n $NEvents ${DIGIQED} ${NOMCLABELS} --sims ${SIM_SOURCES} --tpc-lanes $((NJOBS < 36 ? NJOBS : 36)) --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} ${DIGITOPT} --configKeyValues "\"${DIGITOPTKEY}\"" --interactionRate $FST_COLRATE --early-forward-policy always +[[ $SPLITTRDDIGI == "1" ]] && taskwrapper digiTRD.log o2-sim-digitizer-workflow -n $NEvents ${NOMCLABELS} --onlyDet TRD --trd-digit-downscaling ${DIGITDOWNSCALINGTRD} --shm-segment-size $SHMSIZE ${GLOBALDPLOPT} --incontext collisioncontext.root --configKeyValues "\"${DIGITOPTKEYTRD}\"" --early-forward-policy always touch digiTRD.log_done if [[ "0$GENERATE_ITSMFT_DICTIONARIES" == "01" ]]; then From 827664515366c9ae0aa880348f71ea3da3fb20c6 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 7 May 2024 15:32:17 +0200 Subject: [PATCH 0214/2997] Do not const_cast/modify sh.mem. objetcs from upstream procsesses --- .../include/SimulationDataFormat/MCCompLabel.h | 2 +- .../include/GlobalTracking/TrackCuts.h | 11 +++++------ .../postprocessing/studies/src/ImpactParameter.cxx | 9 +++++---- .../ITS/postprocessing/studies/src/TrackCheck.cxx | 8 ++++---- .../ITS/tracking/include/ITStracking/ROframe.h | 12 ++++++------ 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/MCCompLabel.h b/DataFormats/simulation/include/SimulationDataFormat/MCCompLabel.h index ed0d5300afc35..74c47c87f22d5 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/MCCompLabel.h +++ b/DataFormats/simulation/include/SimulationDataFormat/MCCompLabel.h @@ -129,7 +129,7 @@ class MCCompLabel int getEventID() const { return (mLabel >> nbitsTrackID) & maskEvID; } int getSourceID() const { return (mLabel >> (nbitsTrackID + nbitsEvID)) & maskSrcID; } uint64_t getTrackEventSourceID() const { return static_cast(mLabel & maskFull); } - void get(int& trackID, int& evID, int& srcID, bool& fake) + void get(int& trackID, int& evID, int& srcID, bool& fake) const { /// parse label trackID = getTrackID(); diff --git a/Detectors/GlobalTracking/include/GlobalTracking/TrackCuts.h b/Detectors/GlobalTracking/include/GlobalTracking/TrackCuts.h index 3c08b769fb07d..215e5e8a72f63 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/TrackCuts.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/TrackCuts.h @@ -104,12 +104,11 @@ class TrackCuts const auto& tpcTrk = data.getTPCTrack(contributorsGID[GID::TPC]); math_utils::Point3D v{}; // vertex not defined?! std::array dca; - if (tpcTrk.getPt() < mPtTPCCut || - std::abs(tpcTrk.getEta()) > mEtaTPCCut || // TODO: define 2 different values for min and max (***) - tpcTrk.getNClusters() < mNTPCClustersCut || - (!(const_cast(tpcTrk).propagateParamToDCA(v, mBz, &dca, mDCATPCCut)) || - std::abs(dca[0]) > mDCATPCCutY) || - std::hypot(dca[0], dca[1]) > mDCATPCCut) { + if (tpcTrk.getPt() < mPtTPCCut || std::abs(tpcTrk.getEta()) > mEtaTPCCut || tpcTrk.getNClusters() < mNTPCClustersCut) { // TODO: define 2 different values for min and max (***) + return false; + } + o2::track::TrackPar trTmp(tpcTrk); + if (!trTmp.propagateParamToDCA(v, mBz, &dca, mDCATPCCut) || std::abs(dca[0]) > mDCATPCCutY || std::hypot(dca[0], dca[1]) > mDCATPCCut) { return false; } } diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx index 885ae108754ef..16c38edeb0250 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx @@ -360,12 +360,13 @@ void ImpactParameterStudy::process(o2::globaltracking::RecoContainer& recoData) auto pt = trc.getPt(); o2::gpu::gpustd::array dcaInfo{-999., -999.}; // LOGP(info, " ---> Bz={}", o2::base::Propagator::Instance()->getNominalBz()); - if (o2::base::Propagator::Instance()->propagateToDCABxByBz({Pvtx_refitted.getX(), Pvtx_refitted.getY(), Pvtx_refitted.getZ()}, const_cast(trc), 2.f, matCorr, &dcaInfo)) { + o2::track::TrackPar trcTmp{trc}; + if (o2::base::Propagator::Instance()->propagateToDCABxByBz({Pvtx_refitted.getX(), Pvtx_refitted.getY(), Pvtx_refitted.getZ()}, trcTmp, 2.f, matCorr, &dcaInfo)) { impParRPhi = dcaInfo[0] * toMicrometers; impParZ = dcaInfo[1] * toMicrometers; mHistoImpParXy->Fill(pt, impParRPhi); mHistoImpParZ->Fill(pt, impParZ); - double phi = trc.getPhi(); + double phi = trcTmp.getPhi(); mHistoImpParXyPhi->Fill(phi, impParRPhi); mHistoImpParZPhi->Fill(phi, impParZ); if (phi < TMath::Pi()) { @@ -376,7 +377,7 @@ void ImpactParameterStudy::process(o2::globaltracking::RecoContainer& recoData) mHistoImpParXyBottom->Fill(pt, impParRPhi); mHistoImpParZBottom->Fill(pt, impParZ); } - double sign = trc.getSign(); + double sign = trcTmp.getSign(); if (sign < 0) { mHistoImpParXyNegativeCharge->Fill(pt, impParRPhi); mHistoImpParZNegativeCharge->Fill(pt, impParZ); @@ -557,4 +558,4 @@ DataProcessorSpec getImpactParameterStudy(mask_t srcTracksMask, mask_t srcCluste } // namespace study } // namespace its -} // namespace o2 \ No newline at end of file +} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/src/TrackCheck.cxx b/Detectors/ITSMFT/ITS/postprocessing/studies/src/TrackCheck.cxx index 87c76e492e0fa..bbe7a6ec5e9bb 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/studies/src/TrackCheck.cxx +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/src/TrackCheck.cxx @@ -477,7 +477,7 @@ void TrackCheckStudy::process() } int trackID, evID, srcID; bool fake; - const_cast(lab).get(trackID, evID, srcID, fake); + lab.get(trackID, evID, srcID, fake); auto& cluster = mClusters[iCluster]; auto layer = mGeometry->getLayer(cluster.getSensorID()); mParticleInfo[srcID][evID][trackID].clusters |= (1 << layer); @@ -510,7 +510,7 @@ void TrackCheckStudy::process() } int trackID, evID, srcID; bool fake; - const_cast(lab).get(trackID, evID, srcID, fake); + lab.get(trackID, evID, srcID, fake); if (srcID == 99) { // skip QED unaccounted++; @@ -723,7 +723,7 @@ void TrackCheckStudy::process() } bool fakec; - const_cast(lab).get(TrackID, EvID, SrcID, fakec); + lab.get(TrackID, EvID, SrcID, fakec); double intHisto = 0; for (int hg = 0; hg < 7; hg++) { if (mParticleInfo[SrcID][EvID][TrackID].pdg == PdgcodeClusterFake[hg] || mParticleInfo[SrcID][EvID][TrackID].pdg == -1 * (PdgcodeClusterFake[hg])) { @@ -819,7 +819,7 @@ void TrackCheckStudy::process() } int trackID, evID, srcID; bool fake; - const_cast(lab).get(trackID, evID, srcID, fake); + lab.get(trackID, evID, srcID, fake); if (srcID == 99) { continue; // skip QED } diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h index a39ee1b96c72a..d35e5bc545904 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h @@ -58,8 +58,8 @@ class ROframe final const TrackingFrameInfo& getClusterTrackingFrameInfo(int layerId, const Cluster& cl) const; const MCCompLabel& getClusterFirstLabel(int layerId, const Cluster& cl) const; const MCCompLabel& getClusterFirstLabel(int layerId, const int clId) const; - gsl::span getClusterLabels(int layerId, const int clId) const; - gsl::span getClusterLabels(int layerId, const Cluster& cl) const; + const gsl::span getClusterLabels(int layerId, const int clId) const; + const gsl::span getClusterLabels(int layerId, const Cluster& cl) const; int getClusterExternalIndex(int layerId, const int clId) const; std::vector getTracksId(const int layerId, const std::vector& cl); @@ -75,7 +75,7 @@ class ROframe final private: const int mROframeId; - o2::dataformats::MCTruthContainer* mMClabels = nullptr; + const o2::dataformats::MCTruthContainer* mMClabels = nullptr; std::vector mPrimaryVertices; std::vector> mClusters; std::vector> mTrackingFrameInfo; @@ -115,12 +115,12 @@ inline const MCCompLabel& ROframe::getClusterFirstLabel(int layerId, const int c return *(mMClabels->getLabels(getClusterExternalIndex(layerId, clId)).begin()); } -inline gsl::span ROframe::getClusterLabels(int layerId, const int clId) const +inline const gsl::span ROframe::getClusterLabels(int layerId, const int clId) const { return mMClabels->getLabels(getClusterExternalIndex(layerId, clId)); } -inline gsl::span ROframe::getClusterLabels(int layerId, const Cluster& cl) const +inline const gsl::span ROframe::getClusterLabels(int layerId, const Cluster& cl) const { return getClusterLabels(layerId, cl.clusterId); } @@ -153,7 +153,7 @@ void ROframe::addTrackingFrameInfoToLayer(int layer, T&&... values) inline void ROframe::setMClabelsContainer(const dataformats::MCTruthContainer* ptr) { - mMClabels = const_cast*>(ptr); + mMClabels = ptr; } inline void ROframe::addClusterExternalIndexToLayer(int layer, const int idx) From 3783e5079d7a3acb93b26f654a557cc685f1786b Mon Sep 17 00:00:00 2001 From: Ole Schmidt Date: Wed, 8 May 2024 09:32:48 +0200 Subject: [PATCH 0215/2997] TRD gain calibration don't create TCanvas (#13086) --- .../include/DetectorsCalibration/TimeSlotCalibration.h | 2 +- Detectors/TRD/calibration/src/CalibratorGain.cxx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h b/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h index f0d11fca9384b..36e9e209af878 100644 --- a/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h +++ b/Detectors/Calibration/include/DetectorsCalibration/TimeSlotCalibration.h @@ -454,7 +454,7 @@ template void TimeSlotCalibration::print() const { for (int i = 0; i < getNSlots(); i++) { - LOG(info) << "Slot #" << i << " of " << getNSlots(); + LOG(info) << "Slot #" << i + 1 << " of " << getNSlots(); getSlot(i).print(); } } diff --git a/Detectors/TRD/calibration/src/CalibratorGain.cxx b/Detectors/TRD/calibration/src/CalibratorGain.cxx index 6b5ff2bdc7674..77efeaeb36f1e 100644 --- a/Detectors/TRD/calibration/src/CalibratorGain.cxx +++ b/Detectors/TRD/calibration/src/CalibratorGain.cxx @@ -52,6 +52,7 @@ void CalibratorGain::initProcessing() if (mInitDone) { return; } + LOG(info) << "Initializing the processing"; for (int iDet = 0; iDet < MAXCHAMBER; ++iDet) { mdEdxhists[iDet] = std::make_unique(Form("hdEdx%d", iDet), "dEdx", NBINSGAINCALIB, 0., NBINSGAINCALIB); } @@ -129,7 +130,7 @@ void CalibratorGain::finalizeSlot(Slot& slot) // Fitting histogram mFitFunction->SetParameter(0, mdEdxhists[iDet]->GetMean() / 1.25); - int fitStatus = mdEdxhists[iDet]->Fit("fitConvLandau", "LQB", "", 1, NBINSGAINCALIB - 4); + int fitStatus = mdEdxhists[iDet]->Fit("fitConvLandau", "LQB0", "", 1, NBINSGAINCALIB - 4); if (fitStatus != 0) { LOGF(warn, "Fit for chamber %i failed, nEntries: %d", iDet, nEntries); From 33e256c3ddeb2e22f053d26b3a4db6e5fb218715 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 8 May 2024 17:50:53 +0200 Subject: [PATCH 0216/2997] more informative report from sv-reader --- .../readers/src/SecondaryVertexReaderSpec.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/GlobalTrackingWorkflow/readers/src/SecondaryVertexReaderSpec.cxx b/Detectors/GlobalTrackingWorkflow/readers/src/SecondaryVertexReaderSpec.cxx index 4dd6324c83675..9f252616c9d55 100644 --- a/Detectors/GlobalTrackingWorkflow/readers/src/SecondaryVertexReaderSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/readers/src/SecondaryVertexReaderSpec.cxx @@ -91,7 +91,8 @@ void SecondaryVertexReader::run(ProcessingContext& pc) auto ent = mTree->GetReadEntry() + 1; assert(ent < mTree->GetEntries()); // this should not happen mTree->GetEntry(ent); - LOG(info) << "Pushing " << mV0s.size() << " V0s and " << mCascs.size() << " cascades at entry " << ent; + LOGP(info, "Pushing {} V0s ({} indices), {} cascades ({} indices) and {} 3-body ({} indices ) at entry {}", + mV0s.size(), mV0sIdx.size(), mCascs.size(), mCascsIdx.size(), m3Bodys.size(), m3BodysIdx.size(), ent); pc.outputs().snapshot(Output{"GLO", "V0S_IDX", 0}, mV0sIdx); pc.outputs().snapshot(Output{"GLO", "V0S", 0}, mV0s); From 175d771842aec4c5581effeede990bb486511d21 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 9 May 2024 16:05:52 +0200 Subject: [PATCH 0217/2997] Data: Change default compression mode to recommended settings (#13120) * Data: Change default compression mode to recommended settings As described [here](https://root.cern/doc/master/structROOT_1_1RCompressionSetting.html) for ZSTD recommended is 505 not 501. After measuring it, throughput/compression/peak memory usage stay stay almost unchanged but measured aod size reduces by 5%. Signed-off-by: Felix Schlepper * AOD: Merger, Thinner use recommended compression settings This propagates the changes from the AO2D producer also to the merger and thinner. Signed-off-by: Felix Schlepper * DPL: Set file compression to global settings Signed-off-by: Felix Schlepper --------- Signed-off-by: Felix Schlepper --- Framework/AODMerger/src/aodMerger.cxx | 2 +- Framework/AODMerger/src/aodThinner.cxx | 2 +- Framework/Core/src/DataOutputDirector.cxx | 2 +- Framework/Utils/include/DPLUtils/RootTreeWriter.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Framework/AODMerger/src/aodMerger.cxx b/Framework/AODMerger/src/aodMerger.cxx index 0b98d6f740c15..feb945e7176f3 100644 --- a/Framework/AODMerger/src/aodMerger.cxx +++ b/Framework/AODMerger/src/aodMerger.cxx @@ -95,7 +95,7 @@ int main(int argc, char* argv[]) std::map offsets; std::map unassignedIndexOffset; - auto outputFile = TFile::Open(outputFileName.c_str(), "RECREATE", "", 501); + auto outputFile = TFile::Open(outputFileName.c_str(), "RECREATE", "", 505); TDirectory* outputDir = nullptr; long currentDirSize = 0; diff --git a/Framework/AODMerger/src/aodThinner.cxx b/Framework/AODMerger/src/aodThinner.cxx index 811e907aa79ab..6d474aae511c6 100644 --- a/Framework/AODMerger/src/aodThinner.cxx +++ b/Framework/AODMerger/src/aodThinner.cxx @@ -89,7 +89,7 @@ int main(int argc, char* argv[]) TStopwatch clock; clock.Start(kTRUE); - auto outputFile = TFile::Open(outputFileName.c_str(), (bOverwrite) ? "RECREATE" : "CREATE", "", 501); + auto outputFile = TFile::Open(outputFileName.c_str(), (bOverwrite) ? "RECREATE" : "CREATE", "", 505); if (outputFile == nullptr) { printf("Error: File %s exists or cannot be created!\n", outputFileName.c_str()); return 1; diff --git a/Framework/Core/src/DataOutputDirector.cxx b/Framework/Core/src/DataOutputDirector.cxx index e6a6b89c33f61..80a31586ef7c1 100644 --- a/Framework/Core/src/DataOutputDirector.cxx +++ b/Framework/Core/src/DataOutputDirector.cxx @@ -501,7 +501,7 @@ FileAndFolder DataOutputDirector::getFileFolder(DataOutputDescriptor* dodesc, ui auto fn = resdirname + "/" + mfilenameBases[ind] + ".root"; delete mfilePtrs[ind]; mParentMaps[ind]->Clear(); - mfilePtrs[ind] = TFile::Open(fn.c_str(), mfileMode.c_str(), "", 501); + mfilePtrs[ind] = TFile::Open(fn.c_str(), mfileMode.c_str(), "", 505); } fileAndFolder.file = mfilePtrs[ind]; diff --git a/Framework/Utils/include/DPLUtils/RootTreeWriter.h b/Framework/Utils/include/DPLUtils/RootTreeWriter.h index 8047249bc4506..0161c67396543 100644 --- a/Framework/Utils/include/DPLUtils/RootTreeWriter.h +++ b/Framework/Utils/include/DPLUtils/RootTreeWriter.h @@ -309,7 +309,7 @@ class RootTreeWriter /// branch definition provided to the constructor. void init(const char* filename, const char* treename, const char* treetitle = nullptr) { - mFile = std::make_unique(filename, "RECREATE"); + mFile = std::make_unique(filename, "RECREATE", "", 505); mTree = std::make_unique(treename, treetitle != nullptr ? treetitle : treename); mTree->SetDirectory(mFile.get()); mTreeStructure->setup(mBranchSpecs, mTree.get()); From 42d6d45b525e3865cd5e7b6e3a807d5c18809f1a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 7 May 2024 08:50:21 +0200 Subject: [PATCH 0218/2997] DPL: mark o2-dpl-input-proxy as a proxy --- Framework/Utils/src/raw-proxy.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Utils/src/raw-proxy.cxx b/Framework/Utils/src/raw-proxy.cxx index e04e9879e1e0c..fe33b4b4c8ab8 100644 --- a/Framework/Utils/src/raw-proxy.cxx +++ b/Framework/Utils/src/raw-proxy.cxx @@ -77,6 +77,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) std::move(readoutProxyOutput), "type=pair,method=connect,address=ipc:///tmp/readout-pipe-0,rateLogging=1,transport=shmem", dplModelAdaptor(filterSpecs, throwOnUnmatched), minSHM, false, injectMissingData, printSizes); + readoutProxy.labels.emplace_back(DataProcessorLabel{"input-proxy"}); WorkflowSpec workflow; workflow.emplace_back(readoutProxy); From 221c1f0fabeb7d92d3c894d00791e5b174f5c07d Mon Sep 17 00:00:00 2001 From: noferini <9963644+noferini@users.noreply.github.com> Date: Fri, 10 May 2024 09:45:07 +0200 Subject: [PATCH 0219/2997] reducing log severity for TOF compressor --- Detectors/TOF/compression/src/Compressor.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Detectors/TOF/compression/src/Compressor.cxx b/Detectors/TOF/compression/src/Compressor.cxx index ef76e386733ee..6d08a056852ac 100644 --- a/Detectors/TOF/compression/src/Compressor.cxx +++ b/Detectors/TOF/compression/src/Compressor.cxx @@ -119,7 +119,7 @@ bool Compressor::processHBF() auto rdh = mDecoderRDH; if (!o2::raw::RDHUtils::checkRDH(rdh, false)) { - LOG(error) << "Bad RDH found in TOF compressor -> skip it"; + LOG(warning) << "Bad RDH found in TOF compressor -> skip it"; o2::raw::RDHUtils::checkRDH(rdh, true); return true; } @@ -164,13 +164,13 @@ bool Compressor::processHBF() auto drmPayload = memorySize - headerSize; if (drmPayload < 0) { - LOG(error) << "link = " << rdh->feeId << ": memorySize < headerSize (" << memorySize << " < " << headerSize << ")"; + LOG(warning) << "link = " << rdh->feeId << ": memorySize < headerSize (" << memorySize << " < " << headerSize << ")"; return true; } if (mDecoderSaveBufferDataSize + drmPayload >= mDecoderSaveBufferSize) { // avoid to allocate memory out of the buffer - LOG(error) << "link = " << rdh->feeId << ": beyond the buffer size " << mDecoderSaveBufferSize; + LOG(warning) << "link = " << rdh->feeId << ": beyond the buffer size " << mDecoderSaveBufferSize; return true; } @@ -211,8 +211,8 @@ bool Compressor::processHBF() /** copy RDH open to encoder buffer **/ if (mEncoderPointer + mDecoderRDH->headerSize >= mEncoderPointerMax) { - LOG(error) << "link = " << rdh->feeId << ": beyond the buffer size mEncoderPointer+mDecoderRDH->headerSize = " << mEncoderPointer + mDecoderRDH->headerSize << " >= " - << "mEncoderPointerMax = " << mEncoderPointerMax; + LOG(warning) << "link = " << rdh->feeId << ": beyond the buffer size mEncoderPointer+mDecoderRDH->headerSize = " << mEncoderPointer + mDecoderRDH->headerSize << " >= " + << "mEncoderPointerMax = " << mEncoderPointerMax; encoderRewind(); return true; } @@ -254,8 +254,8 @@ bool Compressor::processHBF() /** copy RDH close to encoder buffer **/ /** CAREFUL WITH THE PAGE COUNTER **/ if (mEncoderPointer + rdh->headerSize >= mEncoderPointerMax) { - LOG(error) << "link = " << rdh->feeId << ": beyond the buffer size mEncoderPointer+rdh->headerSize = " << mEncoderPointer + rdh->headerSize << " >= " - << "mEncoderPointerMax = " << mEncoderPointerMax; + LOG(warning) << "link = " << rdh->feeId << ": beyond the buffer size mEncoderPointer+rdh->headerSize = " << mEncoderPointer + rdh->headerSize << " >= " + << "mEncoderPointerMax = " << mEncoderPointerMax; return true; } mEncoderRDH = reinterpret_cast(mEncoderPointer); From f939934e730cfbc44339f5f1cc0148e7a63c4a14 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 10 May 2024 11:47:53 +0200 Subject: [PATCH 0220/2997] DPL: mark input proxies with the correct label --- Detectors/CTP/workflowScalers/src/ctp-proxy.cxx | 1 + Detectors/CTP/workflowScalers/src/ctp-qc-proxy.cxx | 3 ++- Detectors/DCS/testWorkflow/src/dcs-proxy.cxx | 1 + Framework/Core/test/test_ExternalFairMQDeviceProxy.cxx | 1 + Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx | 1 + Utilities/Mergers/test/multinodeBenchmarkMergers.cxx | 1 + 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Detectors/CTP/workflowScalers/src/ctp-proxy.cxx b/Detectors/CTP/workflowScalers/src/ctp-proxy.cxx index 3634df6d30bda..1b90eb8c23d9d 100644 --- a/Detectors/CTP/workflowScalers/src/ctp-proxy.cxx +++ b/Detectors/CTP/workflowScalers/src/ctp-proxy.cxx @@ -110,6 +110,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) // this is just default, can be overriden by --ctp-config-proxy '--channel-config..' chan.c_str(), dcs2dpl(ccdbhost)); + ctpProxy.labels.emplace_back(DataProcessorLabel{"input-proxy"}); LOG(info) << "===> Proxy done"; WorkflowSpec workflow; workflow.emplace_back(ctpProxy); diff --git a/Detectors/CTP/workflowScalers/src/ctp-qc-proxy.cxx b/Detectors/CTP/workflowScalers/src/ctp-qc-proxy.cxx index 2372ba07a28f7..0a4eeb64cf3af 100644 --- a/Detectors/CTP/workflowScalers/src/ctp-qc-proxy.cxx +++ b/Detectors/CTP/workflowScalers/src/ctp-qc-proxy.cxx @@ -47,7 +47,7 @@ InjectorFunction dcs2dpl() // InjectorFunction dcs2dpl() { return [](TimingInfo&, ServiceRegistryRef const& services, fair::mq::Parts& parts, ChannelRetriever channelRetriever, size_t newTimesliceId, bool&) -> bool { - auto *device = services.get().device(); + auto* device = services.get().device(); std::string messageHeader{static_cast(parts.At(0)->GetData()), parts.At(0)->GetSize()}; size_t dataSize = parts.At(1)->GetSize(); std::string messageData{static_cast(parts.At(1)->GetData()), parts.At(1)->GetSize()}; @@ -135,6 +135,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) // this is just default, can be overriden by --ctp-config-proxy '--channel-config..' chan.c_str(), dcs2dpl()); + ctpProxy.labels.emplace_back(DataProcessorLabel{"input-proxy"}); LOG(info) << "===> Proxy done"; WorkflowSpec workflow; workflow.emplace_back(ctpProxy); diff --git a/Detectors/DCS/testWorkflow/src/dcs-proxy.cxx b/Detectors/DCS/testWorkflow/src/dcs-proxy.cxx index f8f0dba8fd8f6..bfe91a946d13b 100644 --- a/Detectors/DCS/testWorkflow/src/dcs-proxy.cxx +++ b/Detectors/DCS/testWorkflow/src/dcs-proxy.cxx @@ -122,6 +122,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) std::move(dcsOutputs), "type=pull,method=connect,address=tcp://aldcsadaposactor:60000,rateLogging=1,transport=zeromq", dcs2dpl(dpid2DataDesc, fbiFirst, verbose, repRate)); + dcsProxy.labels.emplace_back(DataProcessorLabel{"input-proxy"}); WorkflowSpec workflow; workflow.emplace_back(dcsProxy); diff --git a/Framework/Core/test/test_ExternalFairMQDeviceProxy.cxx b/Framework/Core/test/test_ExternalFairMQDeviceProxy.cxx index cf33da8cd6dd6..4ca725c1551e5 100644 --- a/Framework/Core/test/test_ExternalFairMQDeviceProxy.cxx +++ b/Framework/Core/test/test_ExternalFairMQDeviceProxy.cxx @@ -20,6 +20,7 @@ TEST_CASE("ExternalFairMQDeviceProxy") InjectorFunction f; DataProcessorSpec spec = specifyExternalFairMQDeviceProxy("testSource", {}, "type=sub,method=connect,address=tcp://localhost:10000,rateLogging=1", f); + spec.labels.emplace_back(DataProcessorLabel{"input-proxy"}); REQUIRE(spec.name == "testSource"); REQUIRE(spec.inputs.size() == 0); REQUIRE(spec.options.size() == 2); diff --git a/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx b/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx index d4d204f206e0a..6c991aba7fff5 100644 --- a/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx +++ b/Framework/Core/test/test_ExternalFairMQDeviceWorkflow.cxx @@ -441,6 +441,7 @@ std::vector defineDataProcessing(ConfigContext const& config) channelConfig.c_str(), o2::framework::dplModelAdaptor(filterSpecs, true))); } + workflow.back().labels.emplace_back(DataProcessorLabel{"input-proxy"}); return workflow; } diff --git a/Utilities/Mergers/test/multinodeBenchmarkMergers.cxx b/Utilities/Mergers/test/multinodeBenchmarkMergers.cxx index bc8c5162a6100..319bfacea8aa0 100644 --- a/Utilities/Mergers/test/multinodeBenchmarkMergers.cxx +++ b/Utilities/Mergers/test/multinodeBenchmarkMergers.cxx @@ -67,6 +67,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) {{{"histo"}, {"TST", "HISTO"}}}, inputChannelConfig.c_str(), dplModelAdaptor()))); + specs.back().labels.emplace_back(DataProcessorLabel{"input-proxy"}); MergerInfrastructureBuilder mergersBuilder; mergersBuilder.setInfrastructureName("histos"); From a0c7d5a0ec82d2175201cabece3e0490c26c2e3a Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 10 May 2024 17:02:30 +0200 Subject: [PATCH 0221/2997] Fix typo: requestPrimaryVertertices -> requestPrimaryVertices --- .../include/DataFormatsGlobalTracking/RecoContainer.h | 4 ++-- DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx | 4 ++-- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 2 +- Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx | 2 +- Detectors/FIT/FT0/calibration/src/RecoCalibInfoWorkflow.cxx | 2 +- Detectors/FIT/FT0/workflow/src/RecoQCworkflow.cxx | 2 +- Detectors/Filtering/src/FilteringSpec.cxx | 2 +- .../GlobalTrackingWorkflow/src/SecondaryVertexingSpec.cxx | 2 +- .../GlobalTrackingWorkflow/src/StrangenessTrackingSpec.cxx | 2 +- .../GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx | 2 +- Detectors/GlobalTrackingWorkflow/study/src/DumpTracks.cxx | 2 +- Detectors/GlobalTrackingWorkflow/study/src/ITSOffsStudy.cxx | 2 +- Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx | 2 +- Detectors/GlobalTrackingWorkflow/study/src/TPCDataFilter.cxx | 2 +- Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx | 2 +- Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx | 2 +- .../tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx | 2 +- .../ITSMFT/ITS/postprocessing/studies/src/AvgClusSize.cxx | 4 ++-- .../ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx | 2 +- Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx | 2 +- EventVisualisation/Workflow/src/O2DPLDisplay.cxx | 2 +- 21 files changed, 24 insertions(+), 24 deletions(-) diff --git a/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h b/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h index 3f063c8b8509d..bb2ef3066f6e4 100644 --- a/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h +++ b/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainer.h @@ -241,8 +241,8 @@ struct DataRequest { void requestCoscmicTracks(bool mc); - void requestPrimaryVertertices(bool mc); - void requestPrimaryVerterticesTMP(bool mc); + void requestPrimaryVertices(bool mc); + void requestPrimaryVerticesTMP(bool mc); void requestSecondaryVertices(bool mc); void requestStrangeTracks(bool mc); diff --git a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx index a79e2736dde60..4e6991125c5e8 100644 --- a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx +++ b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx @@ -380,7 +380,7 @@ void DataRequest::requestCoscmicTracks(bool mc) requestMap["Cosmics"] = mc; } -void DataRequest::requestPrimaryVertertices(bool mc) +void DataRequest::requestPrimaryVertices(bool mc) { addInput({"pvtx", "GLO", "PVTX", 0, Lifetime::Timeframe}); addInput({"pvtx_trmtc", "GLO", "PVTX_TRMTC", 0, Lifetime::Timeframe}); // global ids of associated tracks @@ -391,7 +391,7 @@ void DataRequest::requestPrimaryVertertices(bool mc) requestMap["PVertex"] = mc; } -void DataRequest::requestPrimaryVerterticesTMP(bool mc) // primary vertices before global vertex-track matching +void DataRequest::requestPrimaryVerticesTMP(bool mc) // primary vertices before global vertex-track matching { addInput({"pvtx", "GLO", "PVTX", 0, Lifetime::Timeframe}); addInput({"pvtx_cont", "GLO", "PVTX_CONTID", 0, Lifetime::Timeframe}); // global ids of contributors diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 388845edc575c..4270257751578 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -2852,7 +2852,7 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo dataRequest->inputs.emplace_back("ctpconfig", "CTP", "CTPCONFIG", 0, Lifetime::Condition, ccdbParamSpec("CTP/Config/Config", CTPConfigPerRun)); dataRequest->requestTracks(src, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); if (src[GID::CTP]) { dataRequest->requestCTPDigits(useMC); } diff --git a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx index 78b149b5dd4e8..72e78bfd4b40c 100644 --- a/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx +++ b/Detectors/Align/Workflow/src/BarrelAlignmentSpec.cxx @@ -390,7 +390,7 @@ DataProcessorSpec getBarrelAlignmentSpec(GTrackID::mask_t srcMP, GTrackID::mask_ if (!postprocess) { dataRequest->requestTracks(src, useMC); dataRequest->requestClusters(src, false, skipDetClusters); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); if (GTrackID::includesDet(DetID::TRD, srcMP)) { dataRequest->inputs.emplace_back("calvdexb", "TRD", "CALVDRIFTEXB", 0, Lifetime::Condition, ccdbParamSpec("TRD/Calib/CalVdriftExB")); } diff --git a/Detectors/FIT/FT0/calibration/src/RecoCalibInfoWorkflow.cxx b/Detectors/FIT/FT0/calibration/src/RecoCalibInfoWorkflow.cxx index 9de69b8748e60..f3ea99442efbf 100644 --- a/Detectors/FIT/FT0/calibration/src/RecoCalibInfoWorkflow.cxx +++ b/Detectors/FIT/FT0/calibration/src/RecoCalibInfoWorkflow.cxx @@ -95,7 +95,7 @@ void RecoCalibInfoWorkflow::endOfStream(EndOfStreamContext& ec) DataProcessorSpec getRecoCalibInfoWorkflow(GID::mask_t src, bool useMC) { auto dataRequest = std::make_shared(); - dataRequest->requestPrimaryVertertices(false); + dataRequest->requestPrimaryVertices(false); dataRequest->requestFT0RecPoints(false); return DataProcessorSpec{ diff --git a/Detectors/FIT/FT0/workflow/src/RecoQCworkflow.cxx b/Detectors/FIT/FT0/workflow/src/RecoQCworkflow.cxx index d5cb7cdf980e9..6993c46197dac 100644 --- a/Detectors/FIT/FT0/workflow/src/RecoQCworkflow.cxx +++ b/Detectors/FIT/FT0/workflow/src/RecoQCworkflow.cxx @@ -132,7 +132,7 @@ DataProcessorSpec getRecoQCworkflow(GID::mask_t src) { auto dataRequest = std::make_shared(); LOG(info) << "@@ request primary vertex"; - dataRequest->requestPrimaryVertertices(false); + dataRequest->requestPrimaryVertices(false); dataRequest->requestFT0RecPoints(false); LOG(info) << "@@@ requested T0"; std::vector outputs; // empty diff --git a/Detectors/Filtering/src/FilteringSpec.cxx b/Detectors/Filtering/src/FilteringSpec.cxx index ee09bb9420ab9..847fa2cf7e1e5 100644 --- a/Detectors/Filtering/src/FilteringSpec.cxx +++ b/Detectors/Filtering/src/FilteringSpec.cxx @@ -327,7 +327,7 @@ DataProcessorSpec getDataFilteringSpec(GID::mask_t src, bool enableSV, bool useM auto dataRequest = std::make_shared(); dataRequest->requestTracks(src, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); if (src[GID::CTP]) { LOGF(info, "Requesting CTP digits"); dataRequest->requestCTPDigits(useMC); diff --git a/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexingSpec.cxx index 28ef8016565bc..f7fa925ef040c 100644 --- a/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/SecondaryVertexingSpec.cxx @@ -249,7 +249,7 @@ DataProcessorSpec getSecondaryVertexingSpec(GTrackID::mask_t src, bool enableCas dataRequest->requestClusters(srcClus, useMC); } dataRequest->requestTracks(src, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); dataRequest->inputs.emplace_back("meanvtx", "GLO", "MEANVERTEX", 0, Lifetime::Condition, ccdbParamSpec("GLO/Calib/MeanVertex", {}, 1)); auto ggRequest = std::make_shared(false, // orbitResetTime true, // GRPECS=true diff --git a/Detectors/GlobalTrackingWorkflow/src/StrangenessTrackingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/StrangenessTrackingSpec.cxx index 7f0d0e5ed2d03..699772bcdda74 100644 --- a/Detectors/GlobalTrackingWorkflow/src/StrangenessTrackingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/StrangenessTrackingSpec.cxx @@ -136,7 +136,7 @@ DataProcessorSpec getStrangenessTrackerSpec(o2::dataformats::GlobalTrackID::mask auto dataRequest = std::make_shared(); dataRequest->requestITSClusters(useMC); dataRequest->requestTracks(src, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); dataRequest->requestSecondaryVertices(useMC); auto ggRequest = std::make_shared(false, // orbitResetTime diff --git a/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx index e5d2afb1ee700..f24e7c13e336f 100644 --- a/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/VertexTrackMatcherSpec.cxx @@ -150,7 +150,7 @@ DataProcessorSpec getVertexTrackMatcherSpec(GTrackID::mask_t src) dataRequest->requestTracks(src, false); dataRequest->requestClusters(src & GTrackID::getSourcesMask("EMC,PHS,CPV"), false); - dataRequest->requestPrimaryVerterticesTMP(false); + dataRequest->requestPrimaryVerticesTMP(false); auto ggRequest = std::make_shared(false, // orbitResetTime true, // GRPECS=true diff --git a/Detectors/GlobalTrackingWorkflow/study/src/DumpTracks.cxx b/Detectors/GlobalTrackingWorkflow/study/src/DumpTracks.cxx index 6fe851f8a53d9..dbf34b8eb14ad 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/DumpTracks.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/DumpTracks.cxx @@ -297,7 +297,7 @@ DataProcessorSpec getDumpTracksSpec(GTrackID::mask_t srcTracks, GTrackID::mask_t dataRequest->requestTracks(srcTracks, useMC); dataRequest->requestClusters(srcClusters, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); auto ggRequest = std::make_shared(false, // orbitResetTime true, // GRPECS=true false, // GRPLHCIF diff --git a/Detectors/GlobalTrackingWorkflow/study/src/ITSOffsStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/ITSOffsStudy.cxx index 03bb8cc945147..9456c7740c977 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/ITSOffsStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/ITSOffsStudy.cxx @@ -162,7 +162,7 @@ DataProcessorSpec getITSOffsStudy(GTrackID::mask_t srcTracks, GTrackID::mask_t s bool useMC = false; dataRequest->requestTracks(srcTracks, useMC); dataRequest->requestClusters(srcClusters, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); return DataProcessorSpec{ "its-offset-study", diff --git a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx index c1fa8b51b9d57..e61f6067912c5 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx @@ -303,7 +303,7 @@ DataProcessorSpec getSVStudySpec(GTrackID::mask_t srcTracks, bool useMC) auto dataRequest = std::make_shared(); dataRequest->requestTracks(srcTracks, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); dataRequest->requestSecondaryVertices(useMC); dataRequest->inputs.emplace_back("meanvtx", "GLO", "MEANVERTEX", 0, Lifetime::Condition, ccdbParamSpec("GLO/Calib/MeanVertex", {}, 1)); auto ggRequest = std::make_shared(false, // orbitResetTime diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TPCDataFilter.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TPCDataFilter.cxx index 8a962686d743e..7a7f9056b89af 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TPCDataFilter.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TPCDataFilter.cxx @@ -297,7 +297,7 @@ DataProcessorSpec getTPCDataFilter(GTrackID::mask_t srcTracks, GTrackID::mask_t dataRequest->requestTracks(srcTracks, useMC); dataRequest->requestClusters(srcClusters, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); return DataProcessorSpec{ "tpc-data-filter", diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx index 810a8a0d5de9e..b4ad366c291cb 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx @@ -478,7 +478,7 @@ DataProcessorSpec getTrackMCStudySpec(GTrackID::mask_t srcTracks, GTrackID::mask bool useMC = true; dataRequest->requestTracks(srcTracks, useMC); dataRequest->requestClusters(srcClusters, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); o2::tpc::VDriftHelper::requestCCDBInputs(dataRequest->inputs); auto ggRequest = std::make_shared(false, // orbitResetTime diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx index 9a0957c1038d2..2d60e6870067d 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx @@ -402,7 +402,7 @@ DataProcessorSpec getTrackingStudySpec(GTrackID::mask_t srcTracks, GTrackID::mas dataRequest->requestTracks(srcTracks, useMC); dataRequest->requestClusters(srcClusters, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); dataRequest->inputs.emplace_back("meanvtx", "GLO", "MEANVERTEX", 0, Lifetime::Condition, ccdbParamSpec("GLO/Calib/MeanVertex", {}, 1)); auto ggRequest = std::make_shared(false, // orbitResetTime true, // GRPECS=true diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx index ac1ad304caba4..521a02cabcbee 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/TPCInterpolationSpec.cxx @@ -169,7 +169,7 @@ DataProcessorSpec getTPCInterpolationSpec(GTrackID::mask_t srcCls, GTrackID::mas dataRequest->requestTracks(srcVtx, useMC); dataRequest->requestClusters(srcCls, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); auto ggRequest = std::make_shared(false, // orbitResetTime true, // GRPECS=true diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/src/AvgClusSize.cxx b/Detectors/ITSMFT/ITS/postprocessing/studies/src/AvgClusSize.cxx index 6d74c48d0f358..727d564958935 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/studies/src/AvgClusSize.cxx +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/src/AvgClusSize.cxx @@ -653,8 +653,8 @@ DataProcessorSpec getAvgClusSizeStudy(mask_t srcTracksMask, mask_t srcClustersMa dataRequest->requestTracks(srcTracksMask, useMC); dataRequest->requestClusters(srcClustersMask, useMC); dataRequest->requestSecondaryVertices(useMC); - dataRequest->requestPrimaryVertertices(useMC); // NOTE: may be necessary to use requestPrimaryVerterticesTMP()... - // dataRequest->requestPrimaryVerterticesTMP(useMC); + dataRequest->requestPrimaryVertices(useMC); // NOTE: may be necessary to use requestPrimaryVerticesTMP()... + // dataRequest->requestPrimaryVerticesTMP(useMC); auto ggRequest = std::make_shared(false, // orbitResetTime true, // GRPECS=true diff --git a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx index 16c38edeb0250..5ca1bf2bd5c8f 100644 --- a/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx +++ b/Detectors/ITSMFT/ITS/postprocessing/studies/src/ImpactParameter.cxx @@ -537,7 +537,7 @@ DataProcessorSpec getImpactParameterStudy(mask_t srcTracksMask, mask_t srcCluste std::vector outputs; auto dataRequest = std::make_shared(); dataRequest->requestTracks(srcTracksMask, useMC); - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); auto ggRequest = std::make_shared(false, // orbitResetTime true, // GRPECS=true diff --git a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx index 4ab34762fd645..f508140581138 100644 --- a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx +++ b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx @@ -1737,7 +1737,7 @@ o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, GID::mask_t srcTracks = tpcOnly ? GID::getSourcesMask("TPC") : GID::getSourcesMask("TPC,ITS,ITS-TPC,ITS-TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD-TOF"); dataRequest->requestTracks(srcTracks, useMC); if (!tpcOnly) { - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); } const bool enableAskMatLUT = matType == o2::base::Propagator::MatCorrType::USEMatCorrLUT; diff --git a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx index 068390f0e22ea..083cdc65bb714 100644 --- a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx +++ b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx @@ -387,7 +387,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) InputHelper::addInputSpecs(cfgc, specs, srcCl, srcTrk, srcTrk, useMC); if (primaryVertexMode) { - dataRequest->requestPrimaryVertertices(useMC); + dataRequest->requestPrimaryVertices(useMC); InputHelper::addInputSpecsPVertex(cfgc, specs, useMC); } From 09e38b60205acb7720aeb1e0f13a591fed79e3d4 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 10 May 2024 18:33:30 +0200 Subject: [PATCH 0222/2997] ignore empty lines in the FileFetcher input list --- Common/Utils/src/FileFetcher.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Common/Utils/src/FileFetcher.cxx b/Common/Utils/src/FileFetcher.cxx index fd7d9d2be3c32..41265764246da 100644 --- a/Common/Utils/src/FileFetcher.cxx +++ b/Common/Utils/src/FileFetcher.cxx @@ -84,14 +84,12 @@ void FileFetcher::processInput(const std::vector& input) { for (auto inp : input) { o2::utils::Str::trim(inp); - if (fs::is_directory(inp)) { processDirectory(inp); } else if (mSelRegex && !std::regex_match(inp, *mSelRegex.get())) { // provided selector does not match, treat as a txt file with list // Avoid reading a multigiB data file as a list of inputs // bringing down the system. std::filesystem::path p(inp); - if (std::filesystem::file_size(p) > 10000000) { LOGP(error, "file list {} larger than 10MB. Is this a data file?", inp); continue; @@ -106,7 +104,7 @@ void FileFetcher::processInput(const std::vector& input) std::vector newInput; while (getline(listFile, line)) { o2::utils::Str::trim(line); - if (line[0] == '#') { // ignore commented file + if (line[0] == '#' || line.empty()) { // ignore commented file or empty line continue; } newInput.push_back(line); From a79d1214c11b33aa8e91127f7e135b5c994330d5 Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 12 May 2024 01:33:32 +0200 Subject: [PATCH 0223/2997] Add to TrackingStudy output tracks w/o ITS and occ. estimator --- .../GlobalTrackingStudy/TrackingStudy.h | 3 +- .../study/src/TrackingStudy.cxx | 212 ++++++++++++++---- .../study/src/tracking-study-workflow.cxx | 17 +- 3 files changed, 184 insertions(+), 48 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackingStudy.h b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackingStudy.h index b3a55416f4818..7a15c191cbeed 100644 --- a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackingStudy.h +++ b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackingStudy.h @@ -18,11 +18,12 @@ #include "ReconstructionDataFormats/Track.h" #include "MathUtils/detail/Bracket.h" #include "DataFormatsTPC/ClusterNative.h" +#include "TPCCalibration/CorrectionMapsLoader.h" namespace o2::trackstudy { /// create a processor spec -o2::framework::DataProcessorSpec getTrackingStudySpec(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClus, bool useMC); +o2::framework::DataProcessorSpec getTrackingStudySpec(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClus, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts); } // namespace o2::trackstudy diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx index 2d60e6870067d..a5b6d48810e4e 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx @@ -39,6 +39,12 @@ #include "CommonUtils/TreeStreamRedirector.h" #include "ReconstructionDataFormats/VtxTrackRef.h" #include "ReconstructionDataFormats/DCA.h" +#include "TPCCalibration/VDriftHelper.h" +#include "TPCCalibration/CorrectionMapsLoader.h" +#include "GPUO2InterfaceRefit.h" +#include "GPUO2Interface.h" // Needed for propper settings in GPUParam.h +#include "GPUParam.h" +#include "GPUParam.inc" #include "Steer/MCKinematicsReader.h" #include "MathUtils/fit.h" @@ -60,8 +66,12 @@ using timeEst = o2::dataformats::TimeStampWithError; class TrackingStudySpec : public Task { public: - TrackingStudySpec(std::shared_ptr dr, std::shared_ptr gr, GTrackID::mask_t src, bool useMC) - : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(src), mUseMC(useMC) {} + TrackingStudySpec(std::shared_ptr dr, std::shared_ptr gr, GTrackID::mask_t src, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts) + : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(src), mUseMC(useMC) + { + mTPCCorrMapsLoader.setLumiScaleType(sclOpts.lumiType); + mTPCCorrMapsLoader.setLumiScaleMode(sclOpts.lumiMode); + } ~TrackingStudySpec() final = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -72,12 +82,19 @@ class TrackingStudySpec : public Task private: void updateTimeDependentParams(ProcessingContext& pc); float getDCAYCut(float pt) const; + float getDCAZCut(float pt) const; std::shared_ptr mDataRequest; std::shared_ptr mGGCCDBRequest; + o2::tpc::VDriftHelper mTPCVDriftHelper{}; + o2::tpc::CorrectionMapsLoader mTPCCorrMapsLoader{}; bool mUseMC{false}; ///< MC flag std::unique_ptr mDBGOut; std::unique_ptr mDBGOutVtx; - float mITSROFrameLengthMUS = 0.; + std::unique_ptr mTPCRefitter; ///< TPC refitter used for TPC tracks refit during the reconstruction + std::vector mTBinClOccAft, mTBinClOccBef; ///< TPC occupancy histo: i-th entry is the integrated occupancy for ~1 orbit starting/preceding from the TB = i*mNTPCOccBinLength + float mITSROFrameLengthMUS = 0.f; + float mTPCTBinMUS = 0.f; // TPC bin in microseconds + float mTPCTBinMUSInv = 0.f; int mMaxNeighbours = 3; float mMaxVTTimeDiff = 80.; // \mus float mTPCDCAYCut = 2.; @@ -86,8 +103,12 @@ class TrackingStudySpec : public Task float mMaxEta = 0.8; float mMinPt = 0.1; int mMinTPCClusters = 60; + int mNTPCOccBinLength = 0; ///< TPC occ. histo bin length in TBs + int mNHBPerTF = 0; + float mNTPCOccBinLengthInv; + bool mStoreWithITSOnly = false; std::string mDCAYFormula = "0.0105 + 0.0350 / pow(x, 1.1)"; - + std::string mDCAZFormula = "0.0105 + 0.0350 / pow(x, 1.1)"; GTrackID::mask_t mTracksSrc{}; o2::dataformats::MeanVertexObject mMeanVtx{}; o2::steer::MCKinematicsReader mcReader; // reader of MC information @@ -96,9 +117,10 @@ class TrackingStudySpec : public Task void TrackingStudySpec::init(InitContext& ic) { o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); + mTPCCorrMapsLoader.init(ic); mDBGOut = std::make_unique("trackStudy.root", "recreate"); mDBGOutVtx = std::make_unique("trackStudyVtx.root", "recreate"); - + mStoreWithITSOnly = ic.options().get("with-its-only"); mMaxVTTimeDiff = ic.options().get("max-vtx-timediff"); mMaxNeighbours = ic.options().get("max-vtx-neighbours"); mTPCDCAYCut = ic.options().get("max-tpc-dcay"); @@ -108,6 +130,7 @@ void TrackingStudySpec::init(InitContext& ic) mMinPt = ic.options().get("min-pt"); mMinTPCClusters = ic.options().get("min-tpc-clusters"); mDCAYFormula = ic.options().get("dcay-vs-pt"); + mDCAZFormula = ic.options().get("dcaz-vs-pt"); } void TrackingStudySpec::run(ProcessingContext& pc) @@ -115,12 +138,56 @@ void TrackingStudySpec::run(ProcessingContext& pc) o2::globaltracking::RecoContainer recoData; recoData.collectData(pc, *mDataRequest.get()); // select tracks of needed type, with minimal cuts, the real selected will be done in the vertexer updateTimeDependentParams(pc); // Make sure this is called after recoData.collectData, which may load some conditions + + mTPCRefitter = std::make_unique(&recoData.inputsTPCclusters->clusterIndex, &mTPCCorrMapsLoader, o2::base::Propagator::Instance()->getNominalBz(), + recoData.getTPCTracksClusterRefs().data(), 0, recoData.clusterShMapTPC.data(), recoData.occupancyMapTPC.data(), + recoData.occupancyMapTPC.size(), nullptr, o2::base::Propagator::Instance()); + mTPCRefitter->setTrackReferenceX(900); // disable propagation after refit by setting reference to value > 500 + mNTPCOccBinLength = mTPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins; + mTBinClOccBef.clear(); + mTBinClOccAft.clear(); + + // prepare TPC occupancy data + if (mNTPCOccBinLength > 1 && recoData.occupancyMapTPC.size()) { + mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength; + int nTPCBins = mNHBPerTF * o2::constants::lhc::LHCMaxBunches / 8, ninteg = 0; + int nTPCOccBins = nTPCBins * mNTPCOccBinLengthInv, sumBins = std::max(1, int(o2::constants::lhc::LHCMaxBunches / 8 * mNTPCOccBinLengthInv)); + mTBinClOccAft.resize(nTPCOccBins); + mTBinClOccBef.resize(nTPCOccBins); + std::vector mltHistTB(nTPCOccBins); + float sm = 0., tb = 0.5 * mNTPCOccBinLength; + for (int i = 0; i < nTPCOccBins; i++) { + mltHistTB[i] = mTPCRefitter->getParam()->GetUnscaledMult(tb); + tb += mNTPCOccBinLength; + } + for (int i = nTPCOccBins; i--;) { + sm += mltHistTB[i]; + if (i + sumBins < nTPCOccBins) { + sm -= mltHistTB[i + sumBins]; + } + mTBinClOccAft[i] = sm; + } + sm = 0; + for (int i = 0; i < nTPCOccBins; i++) { + sm += mltHistTB[i]; + if (i - sumBins > 0) { + sm -= mltHistTB[i - sumBins]; + } + mTBinClOccBef[i] = sm; + } + } else { + mTBinClOccBef.resize(1); + mTBinClOccAft.resize(1); + } + process(recoData); } void TrackingStudySpec::updateTimeDependentParams(ProcessingContext& pc) { o2::base::GRPGeomHelper::instance().checkUpdates(pc); + mTPCVDriftHelper.extractCCDBInputs(pc); + mTPCCorrMapsLoader.extractCCDBInputs(pc); static bool initOnceDone = false; if (!initOnceDone) { // this params need to be queried only once initOnceDone = true; @@ -133,6 +200,26 @@ void TrackingStudySpec::updateTimeDependentParams(ProcessingContext& pc) mITSROFrameLengthMUS = alpParams.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingNS * 1e-3; // ITS ROFrame duration in \mus } pc.inputs().get("meanvtx"); + mNHBPerTF = o2::base::GRPGeomHelper::instance().getGRPECS()->getNHBFPerTF(); + auto& elParam = o2::tpc::ParameterElectronics::Instance(); + mTPCTBinMUS = elParam.ZbinWidth; // TPC bin in microseconds + mTPCTBinMUSInv = 1. / mTPCTBinMUS; + } + bool updateMaps = false; + if (mTPCCorrMapsLoader.isUpdated()) { + mTPCCorrMapsLoader.acknowledgeUpdate(); + updateMaps = true; + } + if (mTPCVDriftHelper.isUpdated()) { + LOGP(info, "Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}", + mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift, + mTPCVDriftHelper.getVDriftObject().timeOffsetCorr, mTPCVDriftHelper.getVDriftObject().refTimeOffset, + mTPCVDriftHelper.getSourceName()); + mTPCVDriftHelper.acknowledgeUpdate(); + updateMaps = true; + } + if (updateMaps) { + mTPCCorrMapsLoader.updateVDrift(mTPCVDriftHelper.getVDriftObject().corrFact, mTPCVDriftHelper.getVDriftObject().refVDrift, mTPCVDriftHelper.getVDriftObject().getTimeOffset()); } } @@ -153,12 +240,17 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) float tBiasITS = alpParams.roFrameBiasInBC * o2::constants::lhc::LHCBunchSpacingMUS; const o2::ft0::InteractionTag& ft0Params = o2::ft0::InteractionTag::Instance(); std::vector trcExtVec; + auto vdrit = mTPCVDriftHelper.getVDriftObject().getVDrift(); + bool tpcTrackOK = recoData.isTrackSourceLoaded(GTrackID::TPC); + for (int iv = 0; iv < nv; iv++) { LOGP(debug, "processing PV {} of {}", iv, nv); const auto& vtref = vtxRefs[iv]; if (iv != nv - 1) { auto& pve = pveVec[iv]; static_cast(pve) = pvvec[iv]; + + // find best matching FT0 signal float bestTimeDiff = 1000, bestTime = -999; int bestFTID = -1; if (mTracksSrc[GTrackID::FT0]) { @@ -197,43 +289,52 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) if (skipTracks) { continue; } + GTrackID tpcTrID; + const o2::tpc::TrackTPC* tpcTr = nullptr; + int nclTPC = 0; + if (dm[DetID::TPC] && tpcTrackOK) { + tpcTrID = recoData.getTPCContributorGID(vid); + tpcTr = &recoData.getTPCTrack(tpcTrID); + nclTPC = tpcTr->getNClusters(); + if (nclTPC < mMinTPCClusters) { + continue; + } + } bool ambig = vid.isAmbiguous(); auto trc = recoData.getTrackParam(vid); + if (abs(trc.getEta()) > mMaxEta) { + continue; + } + if (iv < nv - 1 && is == GTrackID::TPC && tpcTr && !tpcTr->hasBothSidesClusters()) { // for unconstrained TPC tracks correct track Z + float corz = vdrit * (tpcTr->getTime0() * mTPCTBinMUS - pvvec[iv].getTimeStamp().getTimeStamp()); + if (tpcTr->hasASideClustersOnly()) { + corz = -corz; // A-side + } + trc.setZ(trc.getZ() + corz); + } float xmin = trc.getX(); o2::dataformats::DCA dca; if (!prop->propagateToDCA(iv == nv - 1 ? vtxDummy : pvvec[iv], trc, prop->getNominalBz(), 2., o2::base::PropagatorF::MatCorrType::USEMatCorrLUT, &dca)) { continue; } bool hasITS = GTrackID::getSourceDetectorsMask(is)[GTrackID::ITS]; - bool acceptGlo = true; - int nclTPC = 0, nclITS = 0, pattITS = 0; - while (1) { - // do we cound this track for global multiplicity? - if (!(acceptGlo = abs(trc.getEta()) < mMaxEta && trc.getPt() > mMinPt)) { - break; - } - if (!(acceptGlo = std::abs(dca.getY()) < (hasITS ? getDCAYCut(trc.getPt()) : mTPCDCAYCut) && std::abs(dca.getZ()) < mTPCDCAYCut && xmin < mMinX)) { - break; - } - GTrackID tpcTrID; - if (GTrackID::getSourceDetectorsMask(is)[GTrackID::TPC] && recoData.isTrackSourceLoaded(GTrackID::TPC) && (tpcTrID = recoData.getTPCContributorGID(vid))) { - auto& tpcTr = recoData.getTPCTrack(tpcTrID); - if (!(acceptGlo = (nclTPC = tpcTr.getNClusters()) >= mMinTPCClusters)) { - break; - } - } - if (iv != nv - 1) { - pveVec[iv].nSrcA[is]++; - if (ambig) { - pveVec[iv].nSrcAU[is]++; - } + if (std::abs(dca.getY()) > (hasITS ? getDCAYCut(trc.getPt()) : mTPCDCAYCut) || + std::abs(dca.getZ()) > (hasITS ? getDCAZCut(trc.getPt()) : mTPCDCAZCut)) { + continue; + } + if (trc.getPt() < mMinPt) { + continue; + } + if (iv != nv - 1) { + pveVec[iv].nSrcA[is]++; + if (ambig) { + pveVec[iv].nSrcAU[is]++; } - break; } - if (!hasITS) { + if (!hasITS && mStoreWithITSOnly) { continue; } - if (acceptGlo) { + { auto& trcExt = trcExtVec.emplace_back(); recoData.getTrackTime(vid, trcExt.ttime, trcExt.ttimeE); trcExt.track = trc; @@ -277,8 +378,15 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) } } } + float tpcOccBef = 0., tpcOccAft = 0.; + if (iv != nv - 1) { + int tb = pveVec[iv].getTimeStamp().getTimeStamp() * mTPCTBinMUSInv * mNTPCOccBinLengthInv; + tpcOccBef = tb < 0 ? mTBinClOccBef[0] : (tb >= mTBinClOccBef.size() ? mTBinClOccBef.back() : mTBinClOccBef[tb]); + tpcOccAft = tb < 0 ? mTBinClOccAft[0] : (tb >= mTBinClOccAft.size() ? mTBinClOccAft.back() : mTBinClOccAft[tb]); + } (*mDBGOut) << "trpv" << "orbit=" << recoData.startIR.orbit << "tfID=" << TFCount + << "tpcOccBef=" << tpcOccBef << "tpcOccAft=" << tpcOccAft << "pve=" << pveVec[iv] << "trc=" << trcExtVec << "\n"; } @@ -382,6 +490,12 @@ void TrackingStudySpec::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) if (o2::base::GRPGeomHelper::instance().finaliseCCDB(matcher, obj)) { return; } + if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) { + return; + } + if (mTPCCorrMapsLoader.accountCCDBInputs(matcher, obj)) { + return; + } if (matcher == ConcreteDataMatcher("GLO", "MEANVERTEX", 0)) { LOG(info) << "Imposing new MeanVertex: " << ((const o2::dataformats::MeanVertexObject*)obj)->asString(); mMeanVtx = *(const o2::dataformats::MeanVertexObject*)obj; @@ -395,7 +509,13 @@ float TrackingStudySpec::getDCAYCut(float pt) const return fun.Eval(pt); } -DataProcessorSpec getTrackingStudySpec(GTrackID::mask_t srcTracks, GTrackID::mask_t srcClusters, bool useMC) +float TrackingStudySpec::getDCAZCut(float pt) const +{ + static TF1 fun("dcazvspt", mDCAZFormula.c_str(), 0, 20); + return fun.Eval(pt); +} + +DataProcessorSpec getTrackingStudySpec(GTrackID::mask_t srcTracks, GTrackID::mask_t srcClusters, bool useMC, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts) { std::vector outputs; auto dataRequest = std::make_shared(); @@ -413,22 +533,28 @@ DataProcessorSpec getTrackingStudySpec(GTrackID::mask_t srcTracks, GTrackID::mas dataRequest->inputs, true); + Options opts{ + {"max-vtx-neighbours", VariantType::Int, 3, {"Max PV neighbours fill, no PV study if < 0"}}, + {"max-vtx-timediff", VariantType::Float, 90.f, {"Max PV time difference to consider"}}, + {"dcay-vs-pt", VariantType::String, "0.0105 + 0.0350 / pow(x, 1.1)", {"Formula for global tracks DCAy vs pT cut"}}, + {"dcaz-vs-pt", VariantType::String, "0.0105 + 0.0350 / pow(x, 1.1)", {"Formula for global tracks DCAy vs pT cut"}}, + {"min-tpc-clusters", VariantType::Int, 60, {"Cut on TPC clusters"}}, + {"max-tpc-dcay", VariantType::Float, 5.f, {"Cut on TPC dcaY"}}, + {"max-tpc-dcaz", VariantType::Float, 5.f, {"Cut on TPC dcaZ"}}, + {"max-eta", VariantType::Float, 1.0f, {"Cut on track eta"}}, + {"min-pt", VariantType::Float, 0.1f, {"Cut on track pT"}}, + {"with-its-only", VariantType::Bool, false, {"Store tracks with ITS only"}}, + {"min-x-prop", VariantType::Float, 100.f, {"track should be propagated to this X at least"}}, + }; + o2::tpc::VDriftHelper::requestCCDBInputs(dataRequest->inputs); + o2::tpc::CorrectionMapsLoader::requestCCDBInputs(dataRequest->inputs, opts, sclOpts); + return DataProcessorSpec{ "track-study", dataRequest->inputs, outputs, - AlgorithmSpec{adaptFromTask(dataRequest, ggRequest, srcTracks, useMC)}, - Options{ - {"max-vtx-neighbours", VariantType::Int, 3, {"Max PV neighbours fill, no PV study if < 0"}}, - {"max-vtx-timediff", VariantType::Float, 90.f, {"Max PV time difference to consider"}}, - {"dcay-vs-pt", VariantType::String, "0.0105 + 0.0350 / pow(x, 1.1)", {"Formula for global tracks DCAy vs pT cut"}}, - {"min-tpc-clusters", VariantType::Int, 60, {"Cut on TPC clusters"}}, - {"max-tpc-dcay", VariantType::Float, 2.f, {"Cut on TPC dcaY"}}, - {"max-tpc-dcaz", VariantType::Float, 2.f, {"Cut on TPC dcaZ"}}, - {"max-eta", VariantType::Float, 0.8f, {"Cut on track eta"}}, - {"min-pt", VariantType::Float, 0.1f, {"Cut on track pT"}}, - {"min-x-prop", VariantType::Float, 46.f, {"track should be propagated to this X at least"}}, - }}; + AlgorithmSpec{adaptFromTask(dataRequest, ggRequest, srcTracks, useMC, sclOpts)}, + opts}; } } // namespace o2::trackstudy diff --git a/Detectors/GlobalTrackingWorkflow/study/src/tracking-study-workflow.cxx b/Detectors/GlobalTrackingWorkflow/study/src/tracking-study-workflow.cxx index 2e9e67ea7251b..413d2e63653fc 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/tracking-study-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/tracking-study-workflow.cxx @@ -20,6 +20,8 @@ #include "DetectorsBase/DPLWorkflowUtils.h" #include "GlobalTrackingWorkflowHelpers/InputHelper.h" #include "DetectorsRaw/HBFUtilsInitializer.h" +#include "TPCCalibration/CorrectionMapsLoader.h" +#include "TPCWorkflow/TPCScalerSpec.h" using namespace o2::framework; using GID = o2::dataformats::GlobalTrackID; @@ -38,9 +40,10 @@ void customize(std::vector& workflowOptions) std::vector options{ {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation"}}, {"track-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of track sources to use"}}, - {"cluster-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of cluster sources to use"}}, + {"cluster-sources", VariantType::String, "TPC,TOF", {"comma-separated list of cluster sources to use"}}, {"disable-root-input", VariantType::Bool, false, {"disable root-files input reader"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; + o2::tpc::CorrectionMapsLoader::addGlobalOptions(options); o2::raw::HBFUtilsInitializer::addConfigOption(options); std::swap(workflowOptions, options); } @@ -58,15 +61,21 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) // Update the (declared) parameters if changed from the command line o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); - + auto sclOpt = o2::tpc::CorrectionMapsLoader::parseGlobalOptions(configcontext.options()); auto useMC = !configcontext.options().get("disable-mc"); GID::mask_t srcTrc = allowedSourcesTrc & GID::getSourcesMask(configcontext.options().get("track-sources")); GID::mask_t srcCls = allowedSourcesClus & GID::getSourcesMask(configcontext.options().get("cluster-sources")); - + if (sclOpt.requestCTPLumi) { + srcCls = srcCls | GID::getSourcesMask("CTP"); + } + if (sclOpt.needTPCScalersWorkflow() && !configcontext.options().get("disable-root-input")) { + specs.emplace_back(o2::tpc::getTPCScalerSpec(sclOpt.lumiType == 2, sclOpt.enableMShapeCorrection)); + } o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, srcCls, srcTrc, srcTrc, useMC); o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC); // P-vertex is always needed - specs.emplace_back(o2::trackstudy::getTrackingStudySpec(srcTrc, srcCls, useMC)); + + specs.emplace_back(o2::trackstudy::getTrackingStudySpec(srcTrc, srcCls, useMC, sclOpt)); // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(configcontext, specs); From 08fd30a92d4623abebfd536ccb0a074c1fc35f02 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Fri, 26 Apr 2024 14:40:27 +0200 Subject: [PATCH 0224/2997] [EMCAL-1136] Unit tests for trigger reconstruction - Unit test for TRUDataHandler - Unit test for FastORTimeSeries - Move unit tests for EMCALReconstruction in correct group --- Detectors/EMCAL/reconstruction/CMakeLists.txt | 12 ++ .../test/testAltroDecoderError.cxx | 2 +- .../test/testCaloRawFitterError.cxx | 2 +- .../test/testFastORTimeSeries.cxx | 168 ++++++++++++++++++ .../test/testMinorAltroDecodingError.cxx | 2 +- .../test/testRawDecodingError.cxx | 2 +- .../reconstruction/test/testRecoContainer.cxx | 2 +- .../test/testTRUDataHandler.cxx | 92 ++++++++++ 8 files changed, 277 insertions(+), 5 deletions(-) create mode 100644 Detectors/EMCAL/reconstruction/test/testFastORTimeSeries.cxx create mode 100644 Detectors/EMCAL/reconstruction/test/testTRUDataHandler.cxx diff --git a/Detectors/EMCAL/reconstruction/CMakeLists.txt b/Detectors/EMCAL/reconstruction/CMakeLists.txt index 983bef1aeba40..62f66b7b613fe 100644 --- a/Detectors/EMCAL/reconstruction/CMakeLists.txt +++ b/Detectors/EMCAL/reconstruction/CMakeLists.txt @@ -100,6 +100,18 @@ o2_add_test(RecoContainer COMPONENT_NAME emcal LABELS emcal) +o2_add_test(TRUDataHandler + SOURCES test/testTRUDataHandler.cxx + PUBLIC_LINK_LIBRARIES O2::EMCALReconstruction + COMPONENT_NAME emcal + LABELS emcal) + +o2_add_test(FastORTimeSeries + SOURCES test/testFastORTimeSeries.cxx + PUBLIC_LINK_LIBRARIES O2::EMCALReconstruction + COMPONENT_NAME emcal + LABELS emcal) + o2_add_test_root_macro(macros/RawFitterTESTs.C PUBLIC_LINK_LIBRARIES O2::EMCALReconstruction O2::Headers LABELS emcal COMPILE_ONLY) diff --git a/Detectors/EMCAL/reconstruction/test/testAltroDecoderError.cxx b/Detectors/EMCAL/reconstruction/test/testAltroDecoderError.cxx index 811685f821009..ad68cf171e6f8 100644 --- a/Detectors/EMCAL/reconstruction/test/testAltroDecoderError.cxx +++ b/Detectors/EMCAL/reconstruction/test/testAltroDecoderError.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test EMCAL Calib +#define BOOST_TEST_MODULETest EMCAL Reconstruction #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK #include diff --git a/Detectors/EMCAL/reconstruction/test/testCaloRawFitterError.cxx b/Detectors/EMCAL/reconstruction/test/testCaloRawFitterError.cxx index 33fe6862a84e8..1094f419e92ff 100644 --- a/Detectors/EMCAL/reconstruction/test/testCaloRawFitterError.cxx +++ b/Detectors/EMCAL/reconstruction/test/testCaloRawFitterError.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test EMCAL Calib +#define BOOST_TEST_MODULE Test EMCAL Reconstruction #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK #include diff --git a/Detectors/EMCAL/reconstruction/test/testFastORTimeSeries.cxx b/Detectors/EMCAL/reconstruction/test/testFastORTimeSeries.cxx new file mode 100644 index 0000000000000..3b1dfcb4c240e --- /dev/null +++ b/Detectors/EMCAL/reconstruction/test/testFastORTimeSeries.cxx @@ -0,0 +1,168 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#define BOOST_TEST_MODULE Test EMCAL Reconstruction +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include +#include +#include +#include +#include + +namespace o2 +{ + +namespace emcal +{ + +void printBunch(const gsl::span adcs) +{ + bool first = true; + for (auto& adc : adcs) { + if (!first) { + std::cout << ", "; + } else { + first = false; + } + std::cout << adc; + } + std::cout << " (size " << adcs.size() << ")" << std::endl; +} + +std::vector getReversed(const std::vector& original) +{ + std::vector reversed(13); + for (std::size_t sample = 0; sample < 13; sample++) { + reversed[12 - sample] = original[sample]; + } + return reversed; +} + +std::tuple, std::vector> generatePulseTimeReversed() +{ + std::vector pulse(13); + std::fill(pulse.begin(), pulse.end(), 0); + // calculate forward pulse + auto peak_signal = static_cast(gRandom->Uniform(0, 1024)); + pulse[4] = peak_signal; + auto last = peak_signal; + for (std::size_t sample = 5; sample < 13; sample++) { + if (last == 0) { + break; + } + auto current = static_cast(gRandom->Uniform(0, last)); + pulse[sample] = current; + last = current; + } + last = peak_signal; + for (std::size_t sample = 3; sample > 0; sample--) { + if (last == 0) { + break; + } + auto current = static_cast(gRandom->Uniform(0, last)); + pulse[sample] = current; + last = current; + } + // find start time + uint8_t starttime = 12; + for (std::size_t currenttime = 12; currenttime > 0; currenttime--) { + starttime = currenttime; + if (pulse[currenttime]) { + break; + } + } + // time-reverse pulse + auto reversed = getReversed(pulse); + // zero-suppress time series + std::vector zerosuppressed; + bool bunchstart = false; + for (std::size_t sample = 0; sample < 13; sample++) { + if (reversed[sample] == 0) { + if (!bunchstart) { + continue; + } + break; + } + bunchstart = true; + zerosuppressed.push_back(reversed[sample]); + } + return std::make_tuple(starttime, zerosuppressed, pulse); +} + +uint16_t calculateTimesum(const std::vector samplesOrdered, uint8_t l0time) +{ + uint16_t timesum = 0; + uint8_t starttime = l0time - 4; + for (uint8_t sample = starttime; sample < starttime + 4; sample++) { + timesum += samplesOrdered[sample]; + } + return timesum; +} + +std::vector generateSmallBunch(uint8_t bunchlength) +{ + std::vector bunch(bunchlength); + auto peak_signal = static_cast(gRandom->Uniform(0, 1024)); + bunch[bunchlength - 2] = peak_signal; + bunch[bunchlength - 1] = static_cast(gRandom->Uniform(0, peak_signal)); + auto last = peak_signal; + for (int sample = bunchlength - 3; sample >= 0; sample--) { + auto current = static_cast(gRandom->Uniform(0, last)); + bunch[sample] = current; + last = current; + } + return bunch; +} + +void add_bunch_to_buffer(std::vector& buffer, const std::vector& bunch, uint8_t starttime) +{ + for (int sample = 0; sample < bunch.size(); sample++) { + buffer[starttime - sample] = bunch[bunch.size() - 1 - sample]; + } +} + +BOOST_AUTO_TEST_CASE(FastORTimeSeries_test) +{ + // test fill and integral + for (int itest = 0; itest < 500; itest++) { + auto [starttime, zerosuppressed, reference] = generatePulseTimeReversed(); + FastORTimeSeries testcase(13, zerosuppressed, starttime); + auto adcs = testcase.getADCs(); + BOOST_CHECK_EQUAL_COLLECTIONS(adcs.begin(), adcs.end(), reference.begin(), reference.end()); + BOOST_CHECK_EQUAL(testcase.calculateL1TimeSum(8), calculateTimesum(reference, 8)); + } + return; + + // test adding 2 bunches + for (int itest = 0; itest < 500; itest++) { + auto length_bunch1 = static_cast(gRandom->Uniform(3, 5)), + length_bunch2 = static_cast(gRandom->Uniform(3, 5)); + auto sumbunchlength = length_bunch1 + length_bunch2; + auto offset_bunch1 = static_cast(gRandom->Uniform(0, 13 - sumbunchlength)), + offset_bunch2 = static_cast(gRandom->Uniform(0, 13 - sumbunchlength - offset_bunch1)); + auto bunch1 = generateSmallBunch(length_bunch1), + bunch2 = generateSmallBunch(length_bunch2); + auto starttime_bunch1 = offset_bunch1 + length_bunch1, + starttime_bunch2 = starttime_bunch1 + offset_bunch2 + length_bunch2; + std::vector buffer_reversed{13}; + add_bunch_to_buffer(buffer_reversed, bunch2, starttime_bunch2); + add_bunch_to_buffer(buffer_reversed, bunch1, starttime_bunch1); + FastORTimeSeries testcase(13, bunch2, starttime_bunch2); + testcase.setTimeSamples(bunch1, starttime_bunch1); + auto adcs_timeordered = getReversed(buffer_reversed); + auto adcs_timeseries_reversed = testcase.getADCs(); + BOOST_CHECK_EQUAL_COLLECTIONS(adcs_timeseries_reversed.begin(), adcs_timeseries_reversed.end(), adcs_timeordered.begin(), adcs_timeordered.end()); + } +} + +} // namespace emcal + +} // namespace o2 diff --git a/Detectors/EMCAL/reconstruction/test/testMinorAltroDecodingError.cxx b/Detectors/EMCAL/reconstruction/test/testMinorAltroDecodingError.cxx index c14ab175f7bdf..9fc088ebc6a3e 100644 --- a/Detectors/EMCAL/reconstruction/test/testMinorAltroDecodingError.cxx +++ b/Detectors/EMCAL/reconstruction/test/testMinorAltroDecodingError.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test EMCAL Calib +#define BOOST_TEST_MODULE Test EMCAL Reconstruction #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK #include diff --git a/Detectors/EMCAL/reconstruction/test/testRawDecodingError.cxx b/Detectors/EMCAL/reconstruction/test/testRawDecodingError.cxx index 02b0d8addb031..f701531dc9545 100644 --- a/Detectors/EMCAL/reconstruction/test/testRawDecodingError.cxx +++ b/Detectors/EMCAL/reconstruction/test/testRawDecodingError.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test EMCAL Calib +#define BOOST_TEST_MODULE Test EMCAL Reconstruction #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK #include diff --git a/Detectors/EMCAL/reconstruction/test/testRecoContainer.cxx b/Detectors/EMCAL/reconstruction/test/testRecoContainer.cxx index f440d05920053..182c7ceacb654 100644 --- a/Detectors/EMCAL/reconstruction/test/testRecoContainer.cxx +++ b/Detectors/EMCAL/reconstruction/test/testRecoContainer.cxx @@ -8,7 +8,7 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test EMCAL Calib +#define BOOST_TEST_MODULE Test EMCAL Reconstruction #define BOOST_TEST_MAIN #define BOOST_TEST_DYN_LINK #include diff --git a/Detectors/EMCAL/reconstruction/test/testTRUDataHandler.cxx b/Detectors/EMCAL/reconstruction/test/testTRUDataHandler.cxx new file mode 100644 index 0000000000000..69d6cc1d53c59 --- /dev/null +++ b/Detectors/EMCAL/reconstruction/test/testTRUDataHandler.cxx @@ -0,0 +1,92 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#define BOOST_TEST_MODULE Test EMCAL Reconstruction +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK +#include +#include +#include +#include +#include + +namespace o2 +{ +namespace emcal +{ + +BOOST_AUTO_TEST_CASE(TRUDataHandler_test) +{ + o2::emcal::TRUDataHandler testhandler; + + // no patch set + BOOST_CHECK_EQUAL(testhandler.hasAnyPatch(), false); + for (int ipatch = 0; ipatch < o2::emcal::TriggerMappingV2::PATCHESINTRU; ipatch++) { + BOOST_CHECK_EQUAL(testhandler.hasPatch(ipatch), false); + } + + // set all patches with L0 time 8 + for (int ipatch = 0; ipatch < o2::emcal::TriggerMappingV2::PATCHESINTRU; ipatch++) { + testhandler.setPatch(ipatch, 8); + } + BOOST_CHECK_EQUAL(testhandler.hasAnyPatch(), true); + for (int ipatch = 0; ipatch < o2::emcal::TriggerMappingV2::PATCHESINTRU; ipatch++) { + BOOST_CHECK_EQUAL(testhandler.hasPatch(ipatch), true); + BOOST_CHECK_EQUAL(testhandler.getPatchTime(ipatch), 8); + } + + // test reset + testhandler.reset(); + BOOST_CHECK_EQUAL(testhandler.hasAnyPatch(), false); + for (int ipatch = 0; ipatch < o2::emcal::TriggerMappingV2::PATCHESINTRU; ipatch++) { + BOOST_CHECK_EQUAL(testhandler.hasPatch(ipatch), false); + } + + // test error handling + for (int8_t index = o2::emcal::TriggerMappingV2::PATCHESINTRU; index < CHAR_MAX; index++) { + BOOST_CHECK_EXCEPTION(testhandler.hasPatch(index), o2::emcal::TRUDataHandler::PatchIndexException, [index](const o2::emcal::TRUDataHandler::PatchIndexException& e) { return e.getIndex() == index; }); + BOOST_CHECK_EXCEPTION(testhandler.setPatch(index, 8), o2::emcal::TRUDataHandler::PatchIndexException, [index](const o2::emcal::TRUDataHandler::PatchIndexException& e) { return e.getIndex() == index; }); + } + + for (int iiter = 0; iiter < 100; iiter++) { + // For 100 iterations simulate patch index and time + std::map patchtimes; + int npatches_expect = static_cast(gRandom->Uniform(0, o2::emcal::TriggerMappingV2::PATCHESINTRU)); + while (patchtimes.size() < npatches_expect) { + auto patchindex = static_cast(gRandom->Uniform(0, o2::emcal::TriggerMappingV2::PATCHESINTRU)); + if (patchtimes.find(patchindex) == patchtimes.end()) { + auto patchtime = static_cast(gRandom->Gaus(8, 1)); + if (patchtime >= 12) { + patchtime = 11; + } + patchtimes[patchindex] = patchtime; + } + } + o2::emcal::TRUDataHandler iterhandler; + iterhandler.setFired(npatches_expect > 0); + for (auto [patchindex, patchtime] : patchtimes) { + iterhandler.setPatch(patchindex, patchtime); + } + + BOOST_CHECK_EQUAL(iterhandler.isFired(), npatches_expect > 0); + BOOST_CHECK_EQUAL(iterhandler.hasAnyPatch(), npatches_expect > 0); + for (auto ipatch = 0; ipatch < o2::emcal::TriggerMappingV2::PATCHESINTRU; ipatch++) { + auto hasPatch = patchtimes.find(ipatch) != patchtimes.end(); + BOOST_CHECK_EQUAL(iterhandler.hasPatch(ipatch), hasPatch); + if (hasPatch) { + BOOST_CHECK_EQUAL(iterhandler.getPatchTime(ipatch), patchtimes[ipatch]); + } + } + } +} + +} // namespace emcal + +} // namespace o2 \ No newline at end of file From 2f440e53a5c41f6c748427a54cab18774f688573 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 13 May 2024 16:54:37 +0200 Subject: [PATCH 0225/2997] DPL: use idiomatic C++ to get rid of whitespaces --- .../include/Framework/DataOutputDirector.h | 2 -- Framework/Core/src/DataOutputDirector.cxx | 24 ++++--------------- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/Framework/Core/include/Framework/DataOutputDirector.h b/Framework/Core/include/Framework/DataOutputDirector.h index 8661dc3eb87e5..bdcb8faf976c0 100644 --- a/Framework/Core/include/Framework/DataOutputDirector.h +++ b/Framework/Core/include/Framework/DataOutputDirector.h @@ -51,8 +51,6 @@ struct DataOutputDescriptor { private: std::string mfilenameBase; std::string* mfilenameBasePtr = nullptr; - - std::string remove_ws(const std::string& s); }; struct DataOutputDirector { diff --git a/Framework/Core/src/DataOutputDirector.cxx b/Framework/Core/src/DataOutputDirector.cxx index 80a31586ef7c1..4b803e1050817 100644 --- a/Framework/Core/src/DataOutputDirector.cxx +++ b/Framework/Core/src/DataOutputDirector.cxx @@ -26,9 +26,7 @@ namespace fs = std::filesystem; -namespace o2 -{ -namespace framework +namespace o2::framework { using namespace rapidjson; @@ -39,7 +37,7 @@ DataOutputDescriptor::DataOutputDescriptor(std::string inString) // the 1st part is used to create a DataDescriptorMatcher // the other parts are used to fill treename, colnames, and filename // remove all spaces - auto cleanString = remove_ws(inString); + inString.erase(std::remove_if(inString.begin(), inString.end(), isspace), inString.end()); // reset treename = ""; @@ -49,8 +47,8 @@ DataOutputDescriptor::DataOutputDescriptor(std::string inString) // analyze the parts of the input string static const std::regex delim1(":"); std::sregex_token_iterator end; - std::sregex_token_iterator iter1(cleanString.begin(), - cleanString.end(), + std::sregex_token_iterator iter1(inString.begin(), + inString.end(), delim1, -1); @@ -134,17 +132,6 @@ void DataOutputDescriptor::printOut() } } -std::string DataOutputDescriptor::remove_ws(const std::string& s) -{ - std::string s_wns; - for (auto c : s) { - if (!std::isspace(c)) { - s_wns += c; - } - } - return s_wns; -} - DataOutputDirector::DataOutputDirector() { mfilenameBase = std::string(""); @@ -637,5 +624,4 @@ void DataOutputDirector::setMaximumFileSize(float maxfs) { mmaxfilesize = maxfs; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework From 41d0f712ea168d56c96552dc2873d37264a6fd00 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Wed, 15 May 2024 15:08:10 +0200 Subject: [PATCH 0226/2997] QC-1172 Do not use sampling policies which are turned off (#13134) * QC-1172 Do not use sampling policies which are turned off In the early O2 days, the disabled policies were still the Dispatcher to allow for enabling them during a run by reconfiguring the Dispatcher without modifying the topology. Knowing that this feature will not come before Run 4 on the ECS and ODC side, we can change change this behaviour, as it is seen as a bug. In particular, it does not allow to programmatically enable/disable sampling policies depending on the availability of data in async reco. * missing continue --- .../include/DataSampling/DataSamplingPolicy.h | 2 ++ Utilities/DataSampling/src/DataSampling.cxx | 4 +++ .../DataSampling/src/DataSamplingPolicy.cxx | 7 ++++ .../DataSampling/test/test_DataSampling.cxx | 7 ++++ .../DataSampling/test/test_DataSampling.json | 32 +++++++++++-------- 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h b/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h index 3638e198efc3d..40a9680502b18 100644 --- a/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h +++ b/Utilities/DataSampling/include/DataSampling/DataSamplingPolicy.h @@ -86,11 +86,13 @@ class DataSamplingPolicy std::string getFairMQOutputChannelName() const; uint32_t getTotalAcceptedMessages() const; uint32_t getTotalEvaluatedMessages() const; + bool isActive() const; static header::DataOrigin createPolicyDataOrigin(); static header::DataDescription createPolicyDataDescription(std::string policyName, size_t id); private: + bool mActive = true; std::string mName; PathMap mPaths; std::vector> mConditions; diff --git a/Utilities/DataSampling/src/DataSampling.cxx b/Utilities/DataSampling/src/DataSampling.cxx index cd30759629c9d..71bab97997b3c 100644 --- a/Utilities/DataSampling/src/DataSampling.cxx +++ b/Utilities/DataSampling/src/DataSampling.cxx @@ -65,6 +65,10 @@ void DataSampling::DoGenerateInfrastructure(Dispatcher& dispatcher, WorkflowSpec // We don't want the Dispatcher to exit due to one faulty Policy try { auto policy = DataSamplingPolicy::fromConfiguration(policyConfig.second); + if (!policy.isActive()) { + LOG(debug) << "The data sampling policy '" << policy.getName() << "' is inactive, skipping..."; + continue; + } if (ids.count(policy.getName()) == 1) { LOG(error) << "A policy with the same id has already been encountered (" + policy.getName() + ")"; } diff --git a/Utilities/DataSampling/src/DataSamplingPolicy.cxx b/Utilities/DataSampling/src/DataSamplingPolicy.cxx index 44a7a63efcf51..2c63ba7993f98 100644 --- a/Utilities/DataSampling/src/DataSamplingPolicy.cxx +++ b/Utilities/DataSampling/src/DataSamplingPolicy.cxx @@ -52,7 +52,9 @@ void DataSamplingPolicy::setFairMQOutputChannel(std::string channel) DataSamplingPolicy DataSamplingPolicy::fromConfiguration(const ptree& config) { auto name = config.get("id"); + DataSamplingPolicy policy(name); + policy.mActive = config.get("active", "true"); size_t outputId = 0; std::vector inputSpecs = DataDescriptorQueryBuilder::parse(config.get("query").c_str()); @@ -166,6 +168,11 @@ uint32_t DataSamplingPolicy::getTotalEvaluatedMessages() const return mTotalEvaluatedMessages; } +bool DataSamplingPolicy::isActive() const +{ + return mActive; +} + header::DataOrigin DataSamplingPolicy::createPolicyDataOrigin() { return header::DataOrigin("DS"); diff --git a/Utilities/DataSampling/test/test_DataSampling.cxx b/Utilities/DataSampling/test/test_DataSampling.cxx index 0e0620ddc2c1c..08553e4ed2afe 100644 --- a/Utilities/DataSampling/test/test_DataSampling.cxx +++ b/Utilities/DataSampling/test/test_DataSampling.cxx @@ -64,6 +64,13 @@ BOOST_AUTO_TEST_CASE(DataSamplingSimpleFlow) }); BOOST_CHECK(input != disp->inputs.end()); + // a policy which is switched off + input = std::find_if(disp->inputs.begin(), disp->inputs.end(), + [](const InputSpec& in) { + return DataSpecUtils::match(in, DataOrigin("Y"), DataDescription("Z"), 0) && in.lifetime == Lifetime::Timeframe; + }); + BOOST_CHECK(input == disp->inputs.end()); + auto output = std::find_if(disp->outputs.begin(), disp->outputs.end(), [](const OutputSpec& out) { return DataSpecUtils::match(out, ConcreteDataMatcher{"DS", "tpcclusters0", 0}) && out.lifetime == Lifetime::QA; diff --git a/Utilities/DataSampling/test/test_DataSampling.json b/Utilities/DataSampling/test/test_DataSampling.json index 90087fbd41a2f..f9792f4ea2097 100644 --- a/Utilities/DataSampling/test/test_DataSampling.json +++ b/Utilities/DataSampling/test/test_DataSampling.json @@ -1,23 +1,29 @@ { - "dataSamplingPolicies" : [ + "dataSamplingPolicies": [ { - "id" : "tpcclusters", - "active" : "true", - "query" : "clusters:TPC/CLUSTERS;clusters_p:TPC/CLUSTERS_P", - "samplingConditions" : [], - "bindLocation" : "local" + "id": "tpcclusters", + "active": "true", + "query": "clusters:TPC/CLUSTERS;clusters_p:TPC/CLUSTERS_P", + "samplingConditions": [], + "bindLocation": "local" }, { - "id" : "tpcraw", - "active" : "true", - "machines" : [ + "id": "tpcraw", + "active": "true", + "machines": [ "machineA", "machineB" ], - "port" : "1234", - "query" : "clusters:TPC/RAWDATA", - "outputs" : "clusters:TPC/SMP_RAWDATA", - "samplingConditions" : [] + "port": "1234", + "query": "clusters:TPC/RAWDATA", + "outputs": "clusters:TPC/SMP_RAWDATA", + "samplingConditions": [] + }, + { + "id": "switched-off", + "active": "false", + "query": "x:Y/Z", + "samplingConditions": [] } ] } From 92ee48d6a675dd80d932beafdb489f76d5eb813d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20von=20Haller?= Date: Thu, 16 May 2024 08:46:48 +0200 Subject: [PATCH 0227/2997] [QC-1171] CCDB api should timeout (#13129) --- CCDB/include/CCDB/CcdbApi.h | 1 + CCDB/src/CcdbApi.cxx | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index 2b49fac188b6c..3c1cfe71a5035 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -629,6 +629,7 @@ class CcdbApi //: public DatabaseInterface static std::unique_ptr mJAlienCredentials; // access JAliEn credentials int mCurlRetries = 3; int mCurlDelayRetries = 100000; // in microseconds + size_t mCurlTimeout = 15; // in seconds, can be configured via ALICEO2_CCDB_CURL_TIMEOUT, updated according to the deployment mode ClassDefNV(CcdbApi, 1); }; diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index 4c4aa6ca74a80..bd34b50dcd648 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -216,6 +216,27 @@ void CcdbApi::init(std::string const& host) mNeedAlienToken = (host.find("https://") != std::string::npos) || (host.find("alice-ccdb.cern.ch") != std::string::npos); + // Set the curl timeout. It can be forced with an env var or it has different defaults based on the deployment mode. + if (getenv("ALICEO2_CCDB_CURL_TIMEOUT")) { + auto timeout = atoi(getenv("ALICEO2_CCDB_CURL_TIMEOUT")); + if (timeout >= 0) { // if valid int + mCurlTimeout = timeout; + } + } else { // set a default depending on the deployment mode + o2::framework::DeploymentMode deploymentMode = o2::framework::DefaultsHelpers::deploymentMode(); + if (deploymentMode == o2::framework::DeploymentMode::OnlineDDS || + deploymentMode == o2::framework::DeploymentMode::OnlineAUX || + deploymentMode == o2::framework::DeploymentMode::OnlineECS) { + mCurlTimeout = 5; + } else if (deploymentMode == o2::framework::DeploymentMode::Grid || + deploymentMode == o2::framework::DeploymentMode::FST) { + mCurlTimeout = 15; + } else if (deploymentMode == o2::framework::DeploymentMode::Local) { + mCurlTimeout = 1; + } + } + LOG(debug) << "Curl timeout set to " << mCurlTimeout << " seconds"; + LOGP(info, "Init CcdApi with UserAgentID: {}, Host: {}{}", mUniqueAgentID, host, mInSnapshotMode ? "(snapshot readonly mode)" : snapshotReport.c_str()); } @@ -382,6 +403,7 @@ int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::strin curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_USERAGENT, mUniqueAgentID.c_str()); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, mCurlTimeout); CURLcode res = CURL_LAST; @@ -395,7 +417,11 @@ int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::strin res = CURL_perform(curl); /* Check for errors */ if (res != CURLE_OK) { - LOGP(alarm, "curl_easy_perform() failed: {}", curl_easy_strerror(res)); + if (res == CURLE_OPERATION_TIMEDOUT) { + LOGP(alarm, "curl_easy_perform() timed out. Consider increasing the timeout using the env var `ALICEO2_CCDB_CURL_TIMEOUT` (seconds)"); + } else { // generic message + LOGP(alarm, "curl_easy_perform() failed: {}", curl_easy_strerror(res)); + } returnValue = res; } } From 08d9479cb3a7e75c10789da8b01430bf6fcfce53 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 16 May 2024 14:08:55 +0200 Subject: [PATCH 0228/2997] AOD: Add TPC time0 option B (#13131) * AOD: Add TPC time0 option B Signed-off-by: Felix Schlepper * AOD: skip call to truncateFloat if tpc-only track Signed-off-by: Felix Schlepper * AOD: store t0 wrt to BC of assoc. collision Signed-off-by: Felix Schlepper * AOD: Also store used bcOfTimeRef Signed-off-by: Felix Schlepper --------- Signed-off-by: Felix Schlepper --- .../AODProducerWorkflowSpec.h | 1 + Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 31 ++++++++--- .../include/Framework/AnalysisDataModel.h | 27 +++++++++- Framework/Core/include/Framework/DataTypes.h | 52 ++++++++++++++++++- 4 files changed, 101 insertions(+), 10 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 49ba88c8c5858..8d1cb65524003 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -389,6 +389,7 @@ class AODProducerWorkflowDPL : public Task float trackTimeRes = -999.f; int diffBCRef = 0; // offset of time reference BC from the start of the orbit int bcSlice[2] = {-1, -1}; + bool isTPConly = false; // not to be written out }; struct TrackQA { diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 4270257751578..3f5acad91fcbf 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -321,6 +321,13 @@ void AODProducerWorkflowDPL::addToTracksTable(TracksCursorType& tracksCursor, Tr template void AODProducerWorkflowDPL::addToTracksExtraTable(TracksExtraCursorType& tracksExtraCursor, TrackExtraInfo& extraInfoHolder) { + // In case of TPC-only tracks, do not truncate the time error since we encapsulate there a special encoding of + // the deltaFwd/Bwd times + auto trackTimeRes = extraInfoHolder.trackTimeRes; + if (!extraInfoHolder.isTPConly) { + trackTimeRes = truncateFloatFraction(trackTimeRes, mTrackTimeError); + } + // extra tracksExtraCursor(truncateFloatFraction(extraInfoHolder.tpcInnerParam, mTrack1Pt), extraInfoHolder.flags, @@ -341,7 +348,7 @@ void AODProducerWorkflowDPL::addToTracksExtraTable(TracksExtraCursorType& tracks truncateFloatFraction(extraInfoHolder.trackEtaEMCAL, mTrackPosEMCAL), truncateFloatFraction(extraInfoHolder.trackPhiEMCAL, mTrackPosEMCAL), truncateFloatFraction(extraInfoHolder.trackTime, mTrackTime), - truncateFloatFraction(extraInfoHolder.trackTimeRes, mTrackTimeError)); + trackTimeRes); } template @@ -486,7 +493,7 @@ void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID, } } - if (extraInfoHolder.trackTimeRes < 0.f) { // failed or rejected? + if (!extraInfoHolder.isTPConly && extraInfoHolder.trackTimeRes < 0.f) { // failed or rejected? LOG(warning) << "Barrel track " << trackIndex << " has no time set, rejection is not expected : time=" << extraInfoHolder.trackTime << " timeErr=" << extraInfoHolder.trackTimeRes << " BCSlice: " << extraInfoHolder.bcSlice[0] << ":" << extraInfoHolder.bcSlice[1]; continue; @@ -2438,11 +2445,21 @@ AODProducerWorkflowDPL::TrackExtraInfo AODProducerWorkflowDPL::processBarrelTrac extraInfoHolder.tpcNClsFindableMinusFound = tpcOrig.getNClusters() - tpcClData.found; extraInfoHolder.tpcNClsFindableMinusCrossedRows = tpcOrig.getNClusters() - tpcClData.crossed; extraInfoHolder.tpcNClsShared = tpcClData.shared; - if (src == GIndex::TPC) { // standalone TPC track should set its time from their timebins range - double terr = 0.5 * (tpcOrig.getDeltaTFwd() + tpcOrig.getDeltaTBwd()) * mTPCBinNS; // half-span of the interval - double t = (tpcOrig.getTime0() + 0.5 * (tpcOrig.getDeltaTFwd() - tpcOrig.getDeltaTBwd())) * mTPCBinNS; // central value - LOG(debug) << "TPC tracks t0:" << tpcOrig.getTime0() << " tbwd: " << tpcOrig.getDeltaTBwd() << " tfwd: " << tpcOrig.getDeltaTFwd() << " t: " << t << " te: " << terr; - setTrackTime(t, terr, false); + if (src == GIndex::TPC) { // standalone TPC track should set its time from their timebins range + if (needBCSlice) { + double t = (tpcOrig.getTime0() + 0.5 * (tpcOrig.getDeltaTFwd() - tpcOrig.getDeltaTBwd())) * mTPCBinNS; // central value + double terr = 0.5 * (tpcOrig.getDeltaTFwd() + tpcOrig.getDeltaTBwd()) * mTPCBinNS; + double err = mTimeMarginTrackTime + terr; + bcOfTimeRef = fillBCSlice(extraInfoHolder.bcSlice, t - err, t + err, bcsMap); + } + aod::track::extensions::TPCTimeErrEncoding p; + p.setDeltaTFwd(tpcOrig.getDeltaTFwd()); + p.setDeltaTBwd(tpcOrig.getDeltaTBwd()); + extraInfoHolder.trackTimeRes = p.getTimeErr(); + extraInfoHolder.trackTime = float(tpcOrig.getTime0() * mTPCBinNS - bcOfTimeRef * o2::constants::lhc::LHCBunchSpacingNS); + extraInfoHolder.diffBCRef = int(bcOfTimeRef); + extraInfoHolder.isTPConly = true; // no truncation + extraInfoHolder.flags |= o2::aod::track::TrackTimeAsym; } else if (src == GIndex::ITSTPC) { // its-tpc matched tracks have gaussian time error and the time was not set above const auto& trITSTPC = data.getTPCITSTrack(trackIndex); auto ts = trITSTPC.getTimeMUS(); diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index 0df1186f4d04e..6cd2a12d7632f 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -306,6 +306,29 @@ DECLARE_SOA_DYNAMIC_COLUMN(ITSClsSizeInLayer, itsClsSizeInLayer, //! Size of the return (itsClusterSizes >> (layer * 4)) & 0xf; }); +namespace extensions +{ +using TPCTimeErrEncoding = o2::aod::track::extensions::TPCTimeErrEncoding; +DECLARE_SOA_DYNAMIC_COLUMN(TPCDeltaTFwd, tpcDeltaTFwd, //! Delta Forward of track time in TPC time bis + [](float timeErr, uint32_t trackType) -> float { + if (!(trackType & TrackFlags::TrackTimeAsym)) { + return TPCTimeErrEncoding::invalidValue; + } + TPCTimeErrEncoding enc; + enc.encoding.timeErr = timeErr; + return enc.getDeltaTFwd(); + }); + +DECLARE_SOA_DYNAMIC_COLUMN(TPCDeltaTBwd, tpcDeltaTBwd, //! Delta Backward of track time in TPC time bis + [](float timeErr, uint32_t trackType) -> float { + if (!(trackType & TrackFlags::TrackTimeAsym)) { + return TPCTimeErrEncoding::invalidValue; + } + TPCTimeErrEncoding p; + p.encoding.timeErr = timeErr; + return p.getDeltaTBwd(); + }); +} // namespace extensions } // namespace v001 DECLARE_SOA_DYNAMIC_COLUMN(HasITS, hasITS, //! Flag to check if track has a ITS match @@ -477,8 +500,8 @@ DECLARE_SOA_TABLE_FULL(StoredTracksExtra_000, "TracksExtra", "AOD", "TRACKEXTRA" DECLARE_SOA_TABLE_FULL_VERSIONED(StoredTracksExtra_001, "TracksExtra", "AOD", "TRACKEXTRA", 1, // On disk version of TracksExtra, version 1 track::TPCInnerParam, track::Flags, track::ITSClusterSizes, track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, - track::TPCNClsShared, track::TRDPattern, track::ITSChi2NCl, - track::TPCChi2NCl, track::TRDChi2, track::TOFChi2, + track::TPCNClsShared, track::v001::extensions::TPCDeltaTFwd, track::v001::extensions::TPCDeltaTBwd, + track::TRDPattern, track::ITSChi2NCl, track::TPCChi2NCl, track::TRDChi2, track::TOFChi2, track::TPCSignal, track::TRDSignal, track::Length, track::TOFExpMom, track::PIDForTracking, track::IsPVContributor, diff --git a/Framework/Core/include/Framework/DataTypes.h b/Framework/Core/include/Framework/DataTypes.h index 011c71fa27b38..67dca478eb7c1 100644 --- a/Framework/Core/include/Framework/DataTypes.h +++ b/Framework/Core/include/Framework/DataTypes.h @@ -11,7 +11,10 @@ #ifndef O2_FRAMEWORK_DATATYPES_H_ #define O2_FRAMEWORK_DATATYPES_H_ +#include "CommonConstants/LHCConstants.h" + #include +#include namespace o2::aod::collision { @@ -34,10 +37,11 @@ enum TrackTypeEnum : uint8_t { Run2Track = 254, Run2Tracklet = 255 }; -enum TrackFlags { +enum TrackFlags : uint32_t { TrackTimeResIsRange = 0x1, // Gaussian or range PVContributor = 0x2, // This track has contributed to the collision vertex fit OrphanTrack = 0x4, // Track has no association with any collision vertex + TrackTimeAsym = 0x8, // track with an asymmetric time range // NOTE Highest 4 (29..32) bits reserved for PID hypothesis }; enum TrackFlagsRun2Enum { @@ -62,6 +66,52 @@ enum TRDTrackPattern : uint8_t { HasNeighbor = 0x40, HasCrossing = 0x80, }; +namespace extensions +{ +struct TPCTimeErrEncoding { + // TPC delta forward & backward packing + union TPCDeltaTime { + struct { + uint16_t timeForward; + uint16_t timeBackward; + } __attribute__((packed)) deltas; + float timeErr; + } encoding; + static_assert(sizeof(float) == 2 * sizeof(uint16_t)); + + float getTimeErr() const + { + return encoding.timeErr; + } + + // Use all 16 bits of uint16_t to encode delta scale with max precision + // e.g., TPCTrack::mDeltaFwd * timeScaler + // max range for the time deltas is 0 - <512 (1<<9) TPC time bins + static constexpr float timeScaler{(1 << 16) / (1 << 9)}; + // bogus value to max incorrect usae immedately obvious + static constexpr float invalidValue{std::numeric_limits::min()}; + // convert TPC time bins to ns + static constexpr float TPCBinNS = 8 * o2::constants::lhc::LHCBunchSpacingNS; + + void setDeltaTFwd(float fwd) + { + encoding.deltas.timeForward = static_cast(fwd * timeScaler); + } + void setDeltaTBwd(float bwd) + { + encoding.deltas.timeBackward = static_cast(bwd * timeScaler); + } + + float getDeltaTFwd() const + { + return static_cast(encoding.deltas.timeForward) / timeScaler * TPCBinNS; + } + float getDeltaTBwd() const + { + return static_cast(encoding.deltas.timeBackward) / timeScaler * TPCBinNS; + } +}; +} // namespace extensions } // namespace o2::aod::track namespace o2::aod::fwdtrack From b4acd68ca4c83790e5462f52d7f15784bfb930a7 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 16 May 2024 12:19:30 +0200 Subject: [PATCH 0229/2997] DPL: allow short formatting for data header --- .../include/Headers/DataHeaderHelpers.h | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/DataFormats/Headers/include/Headers/DataHeaderHelpers.h b/DataFormats/Headers/include/Headers/DataHeaderHelpers.h index 0fa179c6e83aa..f264460890494 100644 --- a/DataFormats/Headers/include/Headers/DataHeaderHelpers.h +++ b/DataFormats/Headers/include/Headers/DataHeaderHelpers.h @@ -46,15 +46,15 @@ struct fmt::formatter::value, c template <> struct fmt::formatter { - // Presentation format: 'f' - fixed, 'e' - exponential. char presentation = 's'; - // Parses format specifications of the form ['f' | 'e']. constexpr auto parse(format_parse_context& ctx) { auto it = ctx.begin(), end = ctx.end(); if (it != end && (*it == 's')) { presentation = *it++; + } else if (it != end && (*it == 'x')) { + presentation = *it++; } // Check if reached the end of the range: @@ -69,17 +69,25 @@ struct fmt::formatter { template auto format(const o2::header::DataHeader& h, FormatContext& ctx) { - auto res = fmt::format("Data header version {}, flags: {}\n", h.headerVersion, h.flags) + - fmt::format(" origin : {}\n", h.dataOrigin.str) + - fmt::format(" serialization: {}\n", h.payloadSerializationMethod.str) + - fmt::format(" description : {}\n", h.dataDescription.str) + - fmt::format(" sub spec. : {}\n", (long long unsigned int)h.subSpecification) + - fmt::format(" header size : {}\n", h.headerSize) + - fmt::format(" payloadSize : {}\n", (long long unsigned int)h.payloadSize) + - fmt::format(" firstTForbit : {}\n", h.firstTForbit) + - fmt::format(" tfCounter : {}\n", h.tfCounter) + - fmt::format(" runNumber : {}\n", h.runNumber); - return fmt::format_to(ctx.out(), "{}", res); + if (presentation == 's') { + auto res = fmt::format("Data header version {}, flags: {}\n", h.headerVersion, h.flags) + + fmt::format(" origin : {}\n", h.dataOrigin.str) + + fmt::format(" serialization: {}\n", h.payloadSerializationMethod.str) + + fmt::format(" description : {}\n", h.dataDescription.str) + + fmt::format(" sub spec. : {}\n", (long long unsigned int)h.subSpecification) + + fmt::format(" header size : {}\n", h.headerSize) + + fmt::format(" payloadSize : {}\n", (long long unsigned int)h.payloadSize) + + fmt::format(" firstTForbit : {}\n", h.firstTForbit) + + fmt::format(" tfCounter : {}\n", h.tfCounter) + + fmt::format(" runNumber : {}\n", h.runNumber); + return fmt::format_to(ctx.out(), "{}", res); + } else { + auto res = fmt::format("{}/{}/{}", + h.dataOrigin.str, + h.dataDescription.str, + (long long unsigned int)h.subSpecification); + return fmt::format_to(ctx.out(), "{}", res); + } } }; From 95e5b9a7f24d8b04bed681f9edbcc4298955b0bb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 16 May 2024 12:19:30 +0200 Subject: [PATCH 0230/2997] DPL: improve save in slot message --- Framework/Core/src/DataRelayer.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index bcb5f2a0d9d74..943cd0404f0b3 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -445,7 +445,9 @@ DataRelayer::RelayChoice &cache = mCache, numInputTypes = mDistinctRoutesIndex.size()](TimesliceId timeslice, int input, TimesliceSlot slot) { O2_SIGNPOST_ID_GENERATE(aid, data_relayer); - O2_SIGNPOST_EVENT_EMIT(data_relayer, aid, "saveInSlot", "saving %zu in slot %zu", timeslice.value, slot.index); + O2_SIGNPOST_EVENT_EMIT(data_relayer, aid, "saveInSlot", "saving %{public}s@%zu in slot %zu", + fmt::format("{:x}", *o2::header::get(messages[0]->GetData())).c_str(), + timeslice.value, slot.index); auto cacheIdx = numInputTypes * slot.index + input; MessageSet& target = cache[cacheIdx]; cachedStateMetrics[cacheIdx] = CacheEntryStatus::PENDING; From 52d98c8e08c50ea87d4091a202fb456519c8815f Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 16 May 2024 16:53:22 +0200 Subject: [PATCH 0231/2997] DPL Analysis: provide metadata to workflow construction --- .../src/AODJAlienReaderHelpers.cxx | 6 +- Framework/AnalysisSupport/src/Plugin.cxx | 67 ++++++++++++ Framework/Core/CMakeLists.txt | 2 + Framework/Core/include/Framework/Capability.h | 44 ++++++++ .../include/Framework/ConfigParamDiscovery.h | 37 +++++++ .../include/Framework/ConfigParamRegistry.h | 6 ++ .../Core/include/Framework/ConfigParamStore.h | 4 +- .../Core/include/Framework/PluginManager.h | 2 +- Framework/Core/include/Framework/Plugins.h | 9 ++ .../Core/include/Framework/ServiceSpec.h | 5 - .../include/Framework/runDataProcessing.h | 11 +- Framework/Core/src/ConfigParamDiscovery.cxx | 81 ++++++++++++++ Framework/Core/src/ConfigParamStore.cxx | 11 ++ Framework/Core/src/DeviceSpecHelpers.cxx | 35 ++++-- Framework/Core/src/DeviceSpecHelpers.h | 1 + Framework/Core/src/Plugin.cxx | 100 ++++++++++++++++++ .../Core/src/WorkflowCustomizationHelpers.cxx | 4 + Framework/Core/src/WorkflowHelpers.cxx | 2 +- Framework/Core/src/runDataProcessing.cxx | 7 ++ .../Core/test/test_DeviceSpecHelpers.cxx | 2 +- .../Core/test/test_FrameworkDataFlowToDDS.cxx | 4 +- .../test_FrameworkDataFlowToO2Control.cxx | 2 +- Framework/TestWorkflows/CMakeLists.txt | 4 + .../TestWorkflows/src/o2AnalysisWorkflow.cxx | 13 ++- .../TestWorkflows/src/o2TestHistograms.cxx | 68 ++++++++++++ 25 files changed, 500 insertions(+), 27 deletions(-) create mode 100644 Framework/Core/include/Framework/Capability.h create mode 100644 Framework/Core/include/Framework/ConfigParamDiscovery.h create mode 100644 Framework/Core/src/ConfigParamDiscovery.cxx create mode 100644 Framework/Core/src/Plugin.cxx create mode 100644 Framework/TestWorkflows/src/o2TestHistograms.cxx diff --git a/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx index 092857d585a02..5ce2eca49c07b 100644 --- a/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx +++ b/Framework/AnalysisSupport/src/AODJAlienReaderHelpers.cxx @@ -133,12 +133,12 @@ AlgorithmSpec AODJAlienReaderHelpers::rootFileReaderCallback() stats.updateStats({static_cast(ProcessingStatsId::ARROW_MESSAGES_DESTROYED), DataProcessingStats::Op::Set, 0}); stats.updateStats({static_cast(ProcessingStatsId::ARROW_BYTES_EXPIRED), DataProcessingStats::Op::Set, 0}); - if (!options.isSet("aod-file")) { + if (!options.isSet("aod-file-private")) { LOGP(fatal, "No input file defined!"); throw std::runtime_error("Processing is stopped!"); } - auto filename = options.get("aod-file"); + auto filename = options.get("aod-file-private"); std::string parentFileReplacement; if (options.isSet("aod-parent-base-path-replacement")) { @@ -306,7 +306,7 @@ AlgorithmSpec AODJAlienReaderHelpers::rootFileReaderCallback() control.readyToQuit(QuitRequest::Me); return; } - } + } }); })}; diff --git a/Framework/AnalysisSupport/src/Plugin.cxx b/Framework/AnalysisSupport/src/Plugin.cxx index 8f2e489086afb..2ee8d316f3675 100644 --- a/Framework/AnalysisSupport/src/Plugin.cxx +++ b/Framework/AnalysisSupport/src/Plugin.cxx @@ -12,7 +12,17 @@ #include "Framework/AlgorithmSpec.h" #include "Framework/ServiceSpec.h" #include "Framework/ServiceMetricsInfo.h" +#include "Framework/ConfigParamDiscovery.h" +#include "Framework/Capability.h" +#include "Framework/Signpost.h" #include "AODJAlienReaderHelpers.h" +#include +#include +#include +#include +#include + +O2_DECLARE_DYNAMIC_LOG(analysis_support); struct ROOTFileReader : o2::framework::AlgorithmPlugin { o2::framework::AlgorithmSpec create() override @@ -54,7 +64,64 @@ struct RunSummary : o2::framework::ServicePlugin { } }; +struct DiscoverMetadataInAOD : o2::framework::ConfigDiscoveryPlugin { + ConfigDiscovery* create() override + { + return new ConfigDiscovery{ + .init = []() {}, + .discover = [](ConfigParamRegistry& registry, int argc, char** argv) -> std::vector { + auto filename = registry.get("aod-file"); + if (filename.empty()) { + return {}; + } + LOGP(info, "Loading metadata from file {} in PID {}", filename, getpid()); + std::vector results; + TFile* currentFile = nullptr; + if (filename.at(0) == '@') { + filename.erase(0, 1); + // read the text file and set filename to the contents of the first line + std::ifstream file(filename); + if (!file.is_open()) { + LOGP(fatal, "Couldn't open file \"{}\"!", filename); + } + std::getline(file, filename); + file.close(); + currentFile = TFile::Open(filename.c_str()); + } else { + currentFile = TFile::Open(filename.c_str()); + } + if (!currentFile) { + LOGP(fatal, "Couldn't open file \"{}\"!", filename); + } + + // Get the metadata, if any + auto m = (TMap*)currentFile->Get("metaData"); + if (!m) { + LOGP(warning, "No metadata found in file \"{}\"", filename); + return results; + } + auto it = m->MakeIterator(); + + // Serialise metadata into a ; separated string with : separating key and value + bool first = true; + while (auto obj = it->Next()) { + if (first) { + LOGP(info, "Metadata for file \"{}\":", filename); + first = false; + } + auto objString = (TObjString*)m->GetValue(obj); + LOGP(info, "- {}: {}", obj->GetName(), objString->String().Data()); + std::string key = "aod-metadata-" + std::string(obj->GetName()); + char const* value = strdup(objString->String()); + results.push_back(ConfigParamSpec{key, VariantType::String, value, {"Metadata in AOD"}}); + } + return results; + }}; + } +}; + DEFINE_DPL_PLUGINS_BEGIN DEFINE_DPL_PLUGIN_INSTANCE(ROOTFileReader, CustomAlgorithm); DEFINE_DPL_PLUGIN_INSTANCE(RunSummary, CustomService); +DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInAOD, ConfigDiscovery); DEFINE_DPL_PLUGINS_END diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index d392ba42fe8ac..4381b6c4fa29d 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -47,6 +47,7 @@ o2_add_library(Framework src/DefaultsHelpers.cxx src/DomainInfoHeader.cxx src/ProcessingPoliciesHelpers.cxx + src/ConfigParamDiscovery.cxx src/ConfigParamStore.cxx src/ConfigParamsHelper.cxx src/ChannelParamSpec.cxx @@ -109,6 +110,7 @@ o2_add_library(Framework src/OptionsHelpers.cxx src/PropertyTreeHelpers.cxx src/ProcessingContext.cxx + src/Plugin.cxx src/PluginManager.cxx src/RateLimiter.cxx src/ResourcesMonitoringHelper.cxx diff --git a/Framework/Core/include/Framework/Capability.h b/Framework/Core/include/Framework/Capability.h new file mode 100644 index 0000000000000..23ef7b7d9bf17 --- /dev/null +++ b/Framework/Core/include/Framework/Capability.h @@ -0,0 +1,44 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_FRAMEWORK_CAPABILITY_H_ +#define O2_FRAMEWORK_CAPABILITY_H_ + +#include +#include + +namespace o2::framework +{ + +struct ConfigParamRegistry; + +/// A plugin which is able to discover more option then the ones +/// provided on the command line. The actual loading is in two parts, +/// the first one decides if the options are enough to actually perform +/// the discovery, the second part will do the discovery itself. +/// +/// Its a good idea to have the Loader part in a standalone library to +/// minimize dependency on unneed thir party code, e.g. ROOT. +struct Capability { + // Wether or not this capability is required. + // FIXME: for now let's pass the arguments to get the metadata to work + std::string name; + std::function checkIfNeeded; + char const* requiredPlugin; +}; + +struct CapabilityPlugin { + virtual Capability* create() = 0; +}; + +} // namespace o2::framework + +#endif // O2_FRAMEWORK_CAPABILITY_H_ diff --git a/Framework/Core/include/Framework/ConfigParamDiscovery.h b/Framework/Core/include/Framework/ConfigParamDiscovery.h new file mode 100644 index 0000000000000..3d13d3662ceb1 --- /dev/null +++ b/Framework/Core/include/Framework/ConfigParamDiscovery.h @@ -0,0 +1,37 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_FRAMEWORK_CONFIGPARAMDISCOVERY_H_ +#define O2_FRAMEWORK_CONFIGPARAMDISCOVERY_H_ + +#include "Framework/ConfigParamRegistry.h" + +namespace o2::framework +{ +// A plugin which can be used to inject extra configuration +// options. +struct ConfigParamDiscovery { + static std::vector discover(ConfigParamRegistry&, int, char**); +}; + +struct ConfigDiscovery { + std::function init; + /// A function which uses the arguments available so far to discover more + /// @return the extra ConfigParamSpecs it derives. + std::function(ConfigParamRegistry&, int, char**)> discover; +}; + +struct ConfigDiscoveryPlugin { + virtual ConfigDiscovery* create() = 0; +}; + +} // namespace o2::framework +#endif // O2_FRAMEWORK_CONFIGPARAMDISCOVERY_H_ diff --git a/Framework/Core/include/Framework/ConfigParamRegistry.h b/Framework/Core/include/Framework/ConfigParamRegistry.h index 8f2d80cea0948..397a491be9f9c 100644 --- a/Framework/Core/include/Framework/ConfigParamRegistry.h +++ b/Framework/Core/include/Framework/ConfigParamRegistry.h @@ -125,6 +125,12 @@ class ConfigParamRegistry } } + // Load extra parameters discovered while we process data + void loadExtra(std::vector& extras) + { + mStore->load(extras); + } + private: std::unique_ptr mStore; }; diff --git a/Framework/Core/include/Framework/ConfigParamStore.h b/Framework/Core/include/Framework/ConfigParamStore.h index 37442a6cf7f41..b3ae76aa47ad1 100644 --- a/Framework/Core/include/Framework/ConfigParamStore.h +++ b/Framework/Core/include/Framework/ConfigParamStore.h @@ -34,12 +34,14 @@ class ConfigParamStore /// the configuration. void preload(); + void load(std::vector& specs); + /// Get the store boost::property_tree::ptree& store() { return *mStore; }; boost::property_tree::ptree& provenanceTree() { return *mProvenance; }; /// Get the specs - std::vector const& specs() const + [[nodiscard]] std::vector const& specs() const { return mSpecs; } diff --git a/Framework/Core/include/Framework/PluginManager.h b/Framework/Core/include/Framework/PluginManager.h index 38966c5a969a9..4c6e965502500 100644 --- a/Framework/Core/include/Framework/PluginManager.h +++ b/Framework/Core/include/Framework/PluginManager.h @@ -70,7 +70,7 @@ struct PluginManager { struct LoadedPlugin { std::string name; - ServicePlugin* factory; + PLUGIN* factory; }; std::vector loadedDSOs; std::vector loadedPlugins; diff --git a/Framework/Core/include/Framework/Plugins.h b/Framework/Core/include/Framework/Plugins.h index c29d96f7e0781..23d55a512e1fa 100644 --- a/Framework/Core/include/Framework/Plugins.h +++ b/Framework/Core/include/Framework/Plugins.h @@ -27,6 +27,15 @@ enum struct DplPluginKind : int { // A plugin which implements a custom Services. Needs to return // an object of the kind o2::framework::ServiceSpec CustomService, + // A plugin which implements a new way to discover extra configuration. + // parameters. E.g. it can be used to read metadata from a file or a service + // if a certain parameter is available. + ConfigDiscovery, + // A capability plugin is a plugin used to discover other viable plugins. + // For example, if you find out that you have the --aod-file option + // set, you might want to load metadata from it and attach it to the + // configuration. + Capability, // A plugin which was not initialised properly. Unknown }; diff --git a/Framework/Core/include/Framework/ServiceSpec.h b/Framework/Core/include/Framework/ServiceSpec.h index abac3ad05914c..5684889e85376 100644 --- a/Framework/Core/include/Framework/ServiceSpec.h +++ b/Framework/Core/include/Framework/ServiceSpec.h @@ -322,11 +322,6 @@ struct ServicePlugin { virtual ServiceSpec* create() = 0; }; -struct LoadableService { - std::string name; - std::string library; -}; - } // namespace o2::framework #endif // O2_FRAMEWORK_SERVICESPEC_H_ diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 77a4c9f5ba8d6..fbf2843d4db01 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -29,7 +29,7 @@ #include "Framework/Logger.h" #include "Framework/CheckTypes.h" #include "Framework/StructToTuple.h" - +#include "Framework/ConfigParamDiscovery.h" #include namespace o2::framework @@ -137,6 +137,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& specs, std::vector const& callbacksPolicies, std::vector const& sendingPolicies, std::vector const& workflowOptions, + std::vector const& detectedOptions, o2::framework::ConfigContext& configContext); void doDefaultWorkflowTerminationHook(); @@ -192,6 +193,12 @@ int mainNoCatch(int argc, char** argv) workflowOptionsStore->preload(); workflowOptionsStore->activate(); ConfigParamRegistry workflowOptionsRegistry(std::move(workflowOptionsStore)); + auto extraOptions = o2::framework::ConfigParamDiscovery::discover(workflowOptionsRegistry, argc, argv); + for (auto& extra : extraOptions) { + workflowOptions.push_back(extra); + } + workflowOptionsRegistry.loadExtra(extraOptions); + ConfigContext configContext(workflowOptionsRegistry, argc, argv); o2::framework::WorkflowSpec specs = defineDataProcessing(configContext); overrideCloning(configContext, specs); @@ -206,7 +213,7 @@ int mainNoCatch(int argc, char** argv) channelPolicies.insert(std::end(channelPolicies), std::begin(defaultChannelPolicies), std::end(defaultChannelPolicies)); return doMain(argc, argv, specs, channelPolicies, completionPolicies, dispatchPolicies, - resourcePolicies, callbacksPolicies, sendingPolicies, workflowOptions, configContext); + resourcePolicies, callbacksPolicies, sendingPolicies, workflowOptions, extraOptions, configContext); } int callMain(int argc, char** argv, int (*)(int, char**)); diff --git a/Framework/Core/src/ConfigParamDiscovery.cxx b/Framework/Core/src/ConfigParamDiscovery.cxx new file mode 100644 index 0000000000000..6c24a44bac566 --- /dev/null +++ b/Framework/Core/src/ConfigParamDiscovery.cxx @@ -0,0 +1,81 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/ConfigParamDiscovery.h" +#include "Framework/PluginManager.h" +#include "Framework/Signpost.h" +#include "Framework/Capability.h" +#include +#include +#include + +O2_DECLARE_DYNAMIC_LOG(config_parameter_discovery); + +namespace o2::framework +{ + +std::vector ConfigParamDiscovery::discover(ConfigParamRegistry& registry, int argc, char** argv) +{ + std::vector capabilitiesSpecs = { + "O2Framework:DiscoverMetadataInAODCapability", + "O2Framework:DiscoverMetadataInCommandLineCapability", + }; + + // Load all the requested plugins and discover what we can do. + O2_SIGNPOST_ID_GENERATE(sid, config_parameter_discovery); + std::vector plugins; + for (auto spec : capabilitiesSpecs) { + O2_SIGNPOST_EVENT_EMIT(config_parameter_discovery, sid, "capability", "Parsing Capability plugin: %{public}s", spec); + auto morePlugins = PluginManager::parsePluginSpecString(spec); + for (auto& extra : morePlugins) { + plugins.push_back(extra); + } + } + + std::vector availableCapabilities; + std::vector configDiscoverySpec = {}; + PluginManager::loadFromPlugin(plugins, availableCapabilities); + for (auto& capability : availableCapabilities) { + O2_SIGNPOST_EVENT_EMIT(config_parameter_discovery, sid, "capability", "- Using Capability of : %{public}s", + capability.name.c_str()); + + if (capability.checkIfNeeded(registry, argc, argv)) { + O2_SIGNPOST_EVENT_EMIT(config_parameter_discovery, sid, "capability", "- Required: %{}s", + capability.requiredPlugin); + configDiscoverySpec.push_back(capability.requiredPlugin); + } else { + O2_SIGNPOST_EVENT_EMIT(config_parameter_discovery, sid, "capability", "- No requirements added"); + } + } + + std::vector configDiscoveryPlugins; + for (auto spec : configDiscoverySpec) { + O2_SIGNPOST_EVENT_EMIT(config_parameter_discovery, sid, "discovery", "Parsing ConfigDiscovery plugin: %{public}s", spec); + auto morePlugins = PluginManager::parsePluginSpecString(spec); + for (auto& extra : morePlugins) { + configDiscoveryPlugins.push_back(extra); + } + } + + std::vector availableConfigDiscovery; + PluginManager::loadFromPlugin(configDiscoveryPlugins, availableConfigDiscovery); + std::vector result; + for (auto& configDiscovery : availableConfigDiscovery) { + O2_SIGNPOST_EVENT_EMIT(config_parameter_discovery, sid, "discovery", "Parsing extra configuration as needed"); + auto extras = configDiscovery.discover(registry, argc, argv); + for (auto& extra : extras) { + result.push_back(extra); + } + } + return result; +} + +} // namespace o2::framework diff --git a/Framework/Core/src/ConfigParamStore.cxx b/Framework/Core/src/ConfigParamStore.cxx index 249a8b0052a67..19e123a23e5d0 100644 --- a/Framework/Core/src/ConfigParamStore.cxx +++ b/Framework/Core/src/ConfigParamStore.cxx @@ -41,6 +41,17 @@ void ConfigParamStore::preload() } } +void ConfigParamStore::load(std::vector& specs) +{ + mNextStore->clear(); + mNextProvenance->clear(); + // By default we populate with code. + PropertyTreeHelpers::populateDefaults(specs, *mNextStore, *mNextProvenance); + for (auto& retriever : mRetrievers) { + retriever->update(specs, *mStore, *mProvenance); + } +} + /// Activate the next store void ConfigParamStore::activate() { diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index 30197538f2dda..b9552dc093115 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -32,7 +32,7 @@ #include "Framework/OutputRoute.h" #include "Framework/WorkflowSpec.h" #include "Framework/ComputingResource.h" -#include "Framework/Logger.h" +#include "Framework/Signpost.h" #include "Framework/RuntimeError.h" #include "Framework/RawDeviceService.h" #include "ProcessingPoliciesHelpers.h" @@ -50,8 +50,7 @@ #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" +O2_DECLARE_DYNAMIC_LOG(device_spec_helpers); namespace bpo = boost::program_options; @@ -125,7 +124,9 @@ struct ExpirationHandlerHelpers { if (periods.empty()) { std::string defaultRateName = std::string{"period-"} + matcher.binding; auto defaultRate = std::chrono::milliseconds(options.get(defaultRateName.c_str())); - LOGP(detail, "Using default rate of {} ms as specified by option period-{}", defaultRate.count(), matcher.binding); + O2_SIGNPOST_ID_GENERATE(tid, device_spec_helpers); + O2_SIGNPOST_EVENT_EMIT(device_spec_helpers, tid, "timeDrivenCreation", "Using default rate of %" PRIi64 " ms as specified by option period-%{public}s", defaultRate.count(), + matcher.binding.c_str()); periods.emplace_back(defaultRate.count()); durations.emplace_back(std::chrono::seconds((std::size_t)-1)); } else { @@ -1359,12 +1360,15 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, std::vector const& deviceSpecs, std::vector& deviceExecutions, std::vector& deviceControls, + std::vector const& detectedOptions, std::string const& uniqueWorkflowId) { assert(deviceSpecs.size() == deviceExecutions.size()); assert(deviceControls.size() == deviceExecutions.size()); for (size_t si = 0; si < deviceSpecs.size(); ++si) { auto& spec = deviceSpecs[si]; + O2_SIGNPOST_ID_GENERATE(poid, device_spec_helpers); + O2_SIGNPOST_START(device_spec_helpers, poid, "prepareArguments", "Preparing options for %{public}s", spec.id.c_str()); auto& control = deviceControls[si]; auto& execution = deviceExecutions[si]; @@ -1373,7 +1377,14 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, int argc; char** argv; - std::vector workflowOptions; + // We need to start with the detected options, so that they are not lost. + // Notice how detected options can be detected at any moment in the chain, + // so it's important that if you rely on them, they get passed on + // always. + std::vector workflowOptions = detectedOptions; + for (auto& opt : detectedOptions) { + O2_SIGNPOST_EVENT_EMIT(device_spec_helpers, poid, "prepareArguments", "Processor option %{public}s passed as previously detected", opt.name.c_str()); + } /// Lookup the executable name in the metadata associated with the workflow. /// If we find it, we rewrite the command line arguments to be processed /// so that they look like the ones passed to the merged workflow. @@ -1386,8 +1397,17 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, argv[ai + 1] = strdup(arg.data()); } argv[argc] = nullptr; - workflowOptions = pi->workflowOptions; + for (auto& opt : pi->workflowOptions) { + O2_SIGNPOST_EVENT_EMIT(device_spec_helpers, poid, "prepareArguments", "Processor option %{public}s found in process description", opt.name.c_str()); + workflowOptions.push_back(opt); + } + std::sort(workflowOptions.begin(), workflowOptions.end(), [](ConfigParamSpec const& a, ConfigParamSpec const& b) { return a.name < b.name; }); + auto last = std::unique(workflowOptions.begin(), workflowOptions.end()); + workflowOptions.erase(last, workflowOptions.end()); + for (auto& opt : workflowOptions) { + O2_SIGNPOST_EVENT_EMIT(device_spec_helpers, poid, "prepareArguments", "Final unique option %{public}s added to list of workflowOptions", opt.name.c_str()); + } // We duplicate the list of options, filtering only those // which are actually relevant for the given device. The additional // four are to add @@ -1662,7 +1682,8 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped, assert(execution.args[ai]); str << " " << execution.args[ai]; } - LOG(debug) << "The following options are being forwarded to " << spec.id << ":" << str.str(); + O2_SIGNPOST_END(device_spec_helpers, poid, "prepareArguments", "The following options are being forwarded to %{public}s: %{public}s", + spec.id.c_str(), str.str().c_str()); } } diff --git a/Framework/Core/src/DeviceSpecHelpers.h b/Framework/Core/src/DeviceSpecHelpers.h index 17601c81342c1..5b54bc84cf6c8 100644 --- a/Framework/Core/src/DeviceSpecHelpers.h +++ b/Framework/Core/src/DeviceSpecHelpers.h @@ -129,6 +129,7 @@ struct DeviceSpecHelpers { std::vector const& deviceSpecs, std::vector& deviceExecutions, std::vector& deviceControls, + std::vector const& detectedOptions, std::string const& uniqueWorkflowId); /// Rework the environment string diff --git a/Framework/Core/src/Plugin.cxx b/Framework/Core/src/Plugin.cxx new file mode 100644 index 0000000000000..2298896821dab --- /dev/null +++ b/Framework/Core/src/Plugin.cxx @@ -0,0 +1,100 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#include "Framework/Plugins.h" +#include "Framework/ConfigParamDiscovery.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/Logger.h" +#include "Framework/Capability.h" +#include "Framework/Signpost.h" +#include + +O2_DECLARE_DYNAMIC_LOG(capabilities); +namespace o2::framework +{ +auto lookForAodFile = [](ConfigParamRegistry& registry, int argc, char** argv) -> bool { + O2_SIGNPOST_ID_GENERATE(sid, capabilities); + if (registry.hasOption("aod-file") && registry.isSet("aod-file")) { + for (size_t i = 0; i < argc; i++) { + std::string_view arg = argv[i]; + if (arg.starts_with("--aod-metadata-")) { + return false; + } + } + O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInAODCapability", "Metadata not found in arguments. Checking in AOD file."); + return true; + } + return false; +}; + +auto lookForCommandLineOptions = [](ConfigParamRegistry& registry, int argc, char** argv) -> bool { + O2_SIGNPOST_ID_GENERATE(sid, capabilities); + for (size_t i = 0; i < argc; i++) { + std::string_view arg = argv[i]; + if (arg.starts_with("--aod-metadata-")) { + O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInCommandLineCapability", "Metadata found in arguments. Populating from them."); + return true; + } + } + return false; +}; + +struct DiscoverMetadataInAODCapability : o2::framework::CapabilityPlugin { + Capability* create() override + { + return new Capability{ + .name = "DiscoverMetadataInAODCapability", + .checkIfNeeded = lookForAodFile, + .requiredPlugin = "O2FrameworkAnalysisSupport:DiscoverMetadataInAOD"}; + } +}; + +// Trigger discovery of metadata from command line, if needed. +struct DiscoverMetadataInCommandLineCapability : o2::framework::CapabilityPlugin { + Capability* create() override + { + return new Capability{ + .name = "DiscoverMetadataInCommandLineCapability", + .checkIfNeeded = lookForCommandLineOptions, + .requiredPlugin = "O2Framework:DiscoverMetadataInCommandLine"}; + } +}; + +struct DiscoverMetadataInCommandLine : o2::framework::ConfigDiscoveryPlugin { + ConfigDiscovery* create() override + { + return new ConfigDiscovery{ + .init = []() {}, + .discover = [](ConfigParamRegistry& registry, int argc, char** argv) -> std::vector { + O2_SIGNPOST_ID_GENERATE(sid, capabilities); + O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInCommandLine", + "Discovering metadata for analysis from well known environment variables."); + std::vector results; + for (size_t i = 0; i < argc; i++) { + std::string_view arg = argv[i]; + if (!arg.starts_with("--aod-metadata")) { + continue; + } + std::string key = arg.data() + 2; + std::string value = argv[i + 1]; + O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInCommandLine", + "Found %{public}s with value %{public}s.", key.c_str(), value.c_str()); + results.push_back(ConfigParamSpec{key, VariantType::String, value, {"Metadata in command line"}}); + } + return results; + }}; + } +}; +DEFINE_DPL_PLUGINS_BEGIN +DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInAODCapability, Capability); +DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInCommandLineCapability, Capability); +DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInCommandLine, ConfigDiscovery); +DEFINE_DPL_PLUGINS_END +} // namespace o2::framework diff --git a/Framework/Core/src/WorkflowCustomizationHelpers.cxx b/Framework/Core/src/WorkflowCustomizationHelpers.cxx index ffad8a8720019..05abb5dab98cd 100644 --- a/Framework/Core/src/WorkflowCustomizationHelpers.cxx +++ b/Framework/Core/src/WorkflowCustomizationHelpers.cxx @@ -54,6 +54,10 @@ std::vector WorkflowCustomizationHelpers::requiredWorkflowOptio // options for AOD rate limiting {"aod-memory-rate-limit", VariantType::Int64, 0LL, {"Rate limit AOD processing based on memory"}}, + // options for the AOD reader + // aod-file needs to be available as workflow option, because we + // can configure the workflow based on the contents of the first file. + {"aod-file", VariantType::String, "", {"Input AOD file"}}, // options for AOD writer {"aod-writer-json", VariantType::String, "", {"Name of the json configuration file"}}, {"aod-writer-resdir", VariantType::String, "", {"Name of the output directory"}}, diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index bd875ad421f6e..da60bdbc6961e 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -292,7 +292,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext static_cast(compile_time_hash("internal-dpl-aod-reader")), aodLifetime}}, .algorithm = AlgorithmSpec::dummyAlgorithm(), - .options = {ConfigParamSpec{"aod-file", VariantType::String, {"Input AOD file"}}, + .options = {ConfigParamSpec{"aod-file-private", VariantType::String, ctx.options().get("aod-file"), {"AOD file"}}, ConfigParamSpec{"aod-reader-json", VariantType::String, {"json configuration file"}}, ConfigParamSpec{"aod-parent-access-level", VariantType::String, {"Allow parent file access up to specified level. Default: no (0)"}}, ConfigParamSpec{"aod-parent-base-path-replacement", VariantType::String, {R"(Replace base path of parent files. Syntax: FROM;TO. E.g. "alien:///path/in/alien;/local/path". Enclose in "" on the command line.)"}}, diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index f91716d28cfd7..930132e972881 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -748,6 +748,9 @@ void spawnDevice(uv_loop_t* loop, putenv(strdup(DeviceSpecHelpers::reworkTimeslicePlaceholder(env, spec).data())); } execvp(execution.args[0], execution.args.data()); + } else { + O2_SIGNPOST_ID_GENERATE(sid, driver); + O2_SIGNPOST_EVENT_EMIT(driver, sid, "spawnDevice", "New child at %{pid}d", id); } close(childFds[ref.index].childstdin[0]); close(childFds[ref.index].childstdout[1]); @@ -1359,6 +1362,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, DriverInfo& driverInfo, DriverConfig& driverConfig, std::vector& metricsInfos, + std::vector const& detectedParams, boost::program_options::variables_map& varmap, std::vector& driverServices, std::string frameworkId) @@ -2048,6 +2052,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, runningWorkflow.devices, deviceExecutions, controls, + detectedParams, driverInfo.uniqueWorkflowId); } catch (o2::framework::RuntimeErrorRef& ref) { auto& err = o2::framework::error_from_ref(ref); @@ -2742,6 +2747,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, std::vector const& callbacksPolicies, std::vector const& sendingPolicies, std::vector const& currentWorkflowOptions, + std::vector const& detectedParams, o2::framework::ConfigContext& configContext) { std::vector currentArgs; @@ -3173,6 +3179,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, driverInfo, driverConfig, gDeviceMetricsInfos, + detectedParams, varmap, driverServices, frameworkId); diff --git a/Framework/Core/test/test_DeviceSpecHelpers.cxx b/Framework/Core/test/test_DeviceSpecHelpers.cxx index 762c2df6f82aa..6240e784d09d3 100644 --- a/Framework/Core/test/test_DeviceSpecHelpers.cxx +++ b/Framework/Core/test/test_DeviceSpecHelpers.cxx @@ -79,7 +79,7 @@ void check(const std::vector& arguments, dataProcessorInfos, deviceSpecs, deviceExecutions, - deviceControls, + deviceControls, {}, "workflow-id"); for (size_t index = 0; index < deviceSpecs.size(); index++) { diff --git a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx index 3c08bbae74475..593728696e77a 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToDDS.cxx @@ -153,7 +153,7 @@ TEST_CASE("TestDDS") DeviceSpecHelpers::prepareArguments(false, false, false, 8080, driverConfig, dataProcessorInfos, - devices, executions, controls, + devices, executions, controls, {}, "workflow-id"); CommandInfo command{"foo"}; DDSConfigHelpers::dumpDeviceSpec2DDS(ss, DriverMode::STANDALONE, "", workflow, dataProcessorInfos, devices, executions, command); @@ -417,7 +417,7 @@ TEST_CASE("TestDDSExpendable") DeviceSpecHelpers::prepareArguments(false, false, false, 8080, driverConfig, dataProcessorInfos, - devices, executions, controls, + devices, executions, controls, {}, "workflow-id"); CommandInfo command{"foo"}; DDSConfigHelpers::dumpDeviceSpec2DDS(ss, DriverMode::STANDALONE, "", workflow, dataProcessorInfos, devices, executions, command); diff --git a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx index bbd5b78fbbb68..4aca1bd9680a1 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx @@ -560,7 +560,7 @@ TEST_CASE("TestO2ControlDump") DeviceSpecHelpers::prepareArguments(false, false, false, 8080, driverConfig, dataProcessorInfos, - devices, executions, controls, + devices, executions, controls, {}, "workflow-id"); dumpWorkflow(ss, devices, executions, commandInfo, "testwf", ""); diff --git a/Framework/TestWorkflows/CMakeLists.txt b/Framework/TestWorkflows/CMakeLists.txt index bfbdcfc6f169b..21af45422e0b1 100644 --- a/Framework/TestWorkflows/CMakeLists.txt +++ b/Framework/TestWorkflows/CMakeLists.txt @@ -33,6 +33,10 @@ o2_add_dpl_workflow(diamond-workflow SOURCES src/o2DiamondWorkflow.cxx COMPONENT_NAME TestWorkflows) +o2_add_dpl_workflow(analysis-histograms + SOURCES src/o2TestHistograms.cxx + COMPONENT_NAME TestWorkflows) + o2_add_dpl_workflow(two-timers SOURCES src/o2TwoTimers.cxx COMPONENT_NAME TestWorkflows) diff --git a/Framework/TestWorkflows/src/o2AnalysisWorkflow.cxx b/Framework/TestWorkflows/src/o2AnalysisWorkflow.cxx index 05bf3aabaceab..43d71a9b40528 100644 --- a/Framework/TestWorkflows/src/o2AnalysisWorkflow.cxx +++ b/Framework/TestWorkflows/src/o2AnalysisWorkflow.cxx @@ -49,7 +49,14 @@ struct EtaAndClsHistograms { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - }; + // For the sake of running without an option, we do not throw an exception + // in case the option is not present. + if (cfgc.options().hasOption("aod-metadata-Run") == false || + cfgc.options().get("aod-metadata-Run") == "2") { + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; + } else { + throw std::runtime_error("Unsupported run type"); + } } diff --git a/Framework/TestWorkflows/src/o2TestHistograms.cxx b/Framework/TestWorkflows/src/o2TestHistograms.cxx new file mode 100644 index 0000000000000..4dbea06d03679 --- /dev/null +++ b/Framework/TestWorkflows/src/o2TestHistograms.cxx @@ -0,0 +1,68 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief FullTracks is a join of Tracks, TracksCov, and TracksExtra. +/// \author +/// \since + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct EtaAndClsHistogramsSimple { + OutputObj etaClsH{TH2F("eta_vs_pt", "#eta vs pT", 102, -2.01, 2.01, 100, 0, 10)}; + + void process(aod::Tracks const& tracks) + { + LOGP(info, "Invoking the simple one"); + for (auto& track : tracks) { + etaClsH->Fill(track.eta(), track.pt(), 0); + } + } +}; + +struct EtaAndClsHistogramsFull { + OutputObj etaClsH{TH3F("eta_vs_cls_vs_sigmapT", "#eta vs N_{cls} vs sigma_{1/pT}", 102, -2.01, 2.01, 160, -0.5, 159.5, 100, 0, 10)}; + + void process(soa::Join const& tracks) + { + LOGP(info, "Invoking the run 3 one"); + for (auto& track : tracks) { + etaClsH->Fill(track.eta(), track.tpcNClsFindable(), track.sigma1Pt()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::string runType = "3"; + if (cfgc.options().hasOption("aod-metadata-Run")) { + runType = cfgc.options().get("aod-metadata-Run"); + } + LOGP(info, "Runtype is {}", runType); + // Notice it's important for the tasks to use the same name, otherwise topology generation will be confused. + if (runType == "2") { + LOGP(info, "Using only tracks {}", runType); + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"simple-histos"}), + }; + } else { + LOGP(info, "Using tracks extra {}", runType); + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"simple-histos"}), + }; + } +} From c145207f88bf784924aa911b9f7bc28e0cebd61b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 17 May 2024 08:44:03 +0200 Subject: [PATCH 0232/2997] DPL: allow reading metadata from alien files --- Framework/AnalysisSupport/src/Plugin.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Framework/AnalysisSupport/src/Plugin.cxx b/Framework/AnalysisSupport/src/Plugin.cxx index 2ee8d316f3675..2ec12a92857cf 100644 --- a/Framework/AnalysisSupport/src/Plugin.cxx +++ b/Framework/AnalysisSupport/src/Plugin.cxx @@ -18,6 +18,7 @@ #include "AODJAlienReaderHelpers.h" #include #include +#include #include #include #include @@ -74,6 +75,10 @@ struct DiscoverMetadataInAOD : o2::framework::ConfigDiscoveryPlugin { if (filename.empty()) { return {}; } + if (filename.rfind("alien://", 0) == 0) { + LOGP(debug, "AliEn file requested. Enabling support."); + TGrid::Connect("alien://"); + } LOGP(info, "Loading metadata from file {} in PID {}", filename, getpid()); std::vector results; TFile* currentFile = nullptr; From b40e0dd45df130835aead146df432be8b8301ae4 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 15 May 2024 18:23:06 +0200 Subject: [PATCH 0233/2997] MeanVertex calibrator sends CSV MeanVertex object to DCS CCDB --- .../Calibration/src/MeanVertexCalibrator.cxx | 2 +- .../MeanVertexCalibratorSpec.h | 8 ++-- .../workflow/src/MeanVertexCalibratorSpec.cxx | 37 ++++++++++++++++--- .../src/mean-vertex-calibration-workflow.cxx | 3 +- .../full-system-test/aggregator-workflow.sh | 36 ++++++++++++++++-- 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/Detectors/Calibration/src/MeanVertexCalibrator.cxx b/Detectors/Calibration/src/MeanVertexCalibrator.cxx index 63ed7830fff31..1f6eaf759304d 100644 --- a/Detectors/Calibration/src/MeanVertexCalibrator.cxx +++ b/Detectors/Calibration/src/MeanVertexCalibrator.cxx @@ -370,7 +370,7 @@ void MeanVertexCalibrator::finalizeSlot(Slot& slot) std::map md; auto clName = o2::utils::MemFileHelper::getClassName(mSMAMVobj); auto flName = o2::ccdb::CcdbApi::generateFileName(clName); - mInfoVector.emplace_back("GLO/Calib/MeanVertex", clName, flName, md, startValidity - 10 * o2::ccdb::CcdbObjectInfo::SECOND, startValidity + o2::ccdb::CcdbObjectInfo::MONTH); + mInfoVector.emplace_back("GLO/Calib/MeanVertex", clName, flName, md, startValidity - 10 * o2::ccdb::CcdbObjectInfo::SECOND, startValidity + offset + 10 * o2::ccdb::CcdbObjectInfo::SECOND); mMeanVertexVector.emplace_back(mSMAMVobj); if (mVerbose) { LOG(info) << "Printing MeanVertex Object:"; diff --git a/Detectors/Calibration/workflow/include/DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h b/Detectors/Calibration/workflow/include/DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h index 3ee4c02bab3f2..9cfbe79484837 100644 --- a/Detectors/Calibration/workflow/include/DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h +++ b/Detectors/Calibration/workflow/include/DetectorsCalibrationWorkflow/MeanVertexCalibratorSpec.h @@ -29,7 +29,7 @@ namespace calibration class MeanVertexCalibDevice : public Task { public: - MeanVertexCalibDevice(std::shared_ptr req) : mCCDBRequest(req) {} + MeanVertexCalibDevice(std::shared_ptr req, uint32_t dcsMVsubspec) : mCCDBRequest(req), mDCSSubSpec(dcsMVsubspec) {} void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; @@ -37,7 +37,9 @@ class MeanVertexCalibDevice : public Task private: void sendOutput(DataAllocator& output); - + int mFillNumber = 0; + int mRunNumber = 0; + uint32_t mDCSSubSpec = 0; std::unique_ptr mCalibrator; std::shared_ptr mCCDBRequest; }; @@ -46,7 +48,7 @@ class MeanVertexCalibDevice : public Task namespace framework { -DataProcessorSpec getMeanVertexCalibDeviceSpec(); +DataProcessorSpec getMeanVertexCalibDeviceSpec(uint32_t dcsMVsubspec); } // namespace framework } // namespace o2 diff --git a/Detectors/Calibration/workflow/src/MeanVertexCalibratorSpec.cxx b/Detectors/Calibration/workflow/src/MeanVertexCalibratorSpec.cxx index 16f406cda2398..1a64adcd9bf3c 100644 --- a/Detectors/Calibration/workflow/src/MeanVertexCalibratorSpec.cxx +++ b/Detectors/Calibration/workflow/src/MeanVertexCalibratorSpec.cxx @@ -45,6 +45,12 @@ void MeanVertexCalibDevice::init(InitContext& ic) void MeanVertexCalibDevice::run(o2::framework::ProcessingContext& pc) { o2::base::GRPGeomHelper::instance().checkUpdates(pc); + const auto& tinfo = pc.services().get(); + if (tinfo.globalRunNumberChanged) { // new run is starting + mRunNumber = (tinfo.runNumber != -1 && tinfo.runNumber > 0) ? tinfo.runNumber : o2::base::GRPGeomHelper::instance().getGRPECS()->getRun(); + mFillNumber = o2::base::GRPGeomHelper::instance().getGRPLHCIF()->getFillNumber(); + } + auto data = pc.inputs().get>("input"); o2::base::TFIDInfoHelper::fillTFIDInfo(pc, mCalibrator->getCurrentTFInfo()); LOG(debug) << "Processing TF " << mCalibrator->getCurrentTFInfo().tfCounter << " with " << data.size() << " vertices"; @@ -82,13 +88,30 @@ void MeanVertexCalibDevice::sendOutput(DataAllocator& output) auto& infoVec = mCalibrator->getMeanVertexObjectInfoVector(); // use non-const version as we update it assert(payloadVec.size() == infoVec.size()); + if (mDCSSubSpec && mDCSSubSpec < payloadVec.size()) { + LOGP(alarm, "Minimum subspec {} of messages for DCS CCDB is below the maximum subspec {} for production CCDB, increase the former", mDCSSubSpec, payloadVec.size()); + } + static std::vector dcsMVObj; for (uint32_t i = 0; i < payloadVec.size(); i++) { - auto& w = infoVec[i]; - auto image = o2::ccdb::CcdbApi::createObjectImage(&payloadVec[i], &w); + auto w = infoVec[i]; + auto& mv = payloadVec[i]; + auto image = o2::ccdb::CcdbApi::createObjectImage(&mv, &w); LOG(info) << (MeanVertexParams::Instance().skipObjectSending ? "Skip " : "") << "sending object " << w.getPath() << "/" << w.getFileName() << " of size " << image->size() << " bytes, valid for " << w.getStartValidityTimestamp() << " : " << w.getEndValidityTimestamp(); if (!MeanVertexParams::Instance().skipObjectSending) { + if (mDCSSubSpec) { // create message for DCS CCDB + auto ts = (w.getStartValidityTimestamp() + w.getEndValidityTimestamp()) / 2; + o2::ccdb::CcdbObjectInfo dcsw("GLO/Calib/MeanVertexCSV", "csv", fmt::format("meanvertex_{}.csv", ts), {}, w.getStartValidityTimestamp(), w.getEndValidityTimestamp()); + + std::string csvMeanVertex = fmt::format("timestamp={},fillNumber={},runNumber={},x={:+.4e},y={:+.4e},z={:+.4e},sigmax={:+.4e},sigmay={:+.4e},sigmaz={:+.4e}", + ts, mFillNumber, mRunNumber, mv.getX(), mv.getY(), mv.getZ(), mv.getSigmaX(), mv.getSigmaY(), mv.getSigmaZ()); + dcsMVObj.clear(); + std::copy(csvMeanVertex.begin(), csvMeanVertex.end(), std::back_inserter(dcsMVObj)); + output.snapshot(Output{clbUtils::gDataOriginCDBPayload, "MEANVERTEX_DCS", mDCSSubSpec + i}, dcsMVObj); + output.snapshot(Output{clbUtils::gDataOriginCDBWrapper, "MEANVERTEX_DCS", mDCSSubSpec + i}, dcsw); + } + w.setEndValidityTimestamp(w.getEndValidityTimestamp() + o2::ccdb::CcdbObjectInfo::MONTH); output.snapshot(Output{clbUtils::gDataOriginCDBPayload, "MEANVERTEX", i}, *image.get()); // vector output.snapshot(Output{clbUtils::gDataOriginCDBWrapper, "MEANVERTEX", i}, w); // root-serialized } @@ -102,7 +125,7 @@ void MeanVertexCalibDevice::sendOutput(DataAllocator& output) namespace framework { -DataProcessorSpec getMeanVertexCalibDeviceSpec() +DataProcessorSpec getMeanVertexCalibDeviceSpec(uint32_t dcsMVsubspec) { using device = o2::calibration::MeanVertexCalibDevice; @@ -111,7 +134,7 @@ DataProcessorSpec getMeanVertexCalibDeviceSpec() inputs.emplace_back("input", "GLO", "PVTX"); auto ccdbRequest = std::make_shared(true, // orbitResetTime true, // GRPECS=true - false, // GRPLHCIF + true, // GRPLHCIF false, // GRPMagField false, // askMatLUT o2::base::GRPGeomRequest::None, // geometry @@ -120,12 +143,16 @@ DataProcessorSpec getMeanVertexCalibDeviceSpec() std::vector outputs; outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBPayload, "MEANVERTEX"}, Lifetime::Sporadic); outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBWrapper, "MEANVERTEX"}, Lifetime::Sporadic); + if (dcsMVsubspec) { + outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBPayload, "MEANVERTEX_DCS"}, Lifetime::Sporadic); + outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBWrapper, "MEANVERTEX_DCS"}, Lifetime::Sporadic); + } return DataProcessorSpec{ "mean-vertex-calibration", inputs, outputs, - AlgorithmSpec{adaptFromTask(ccdbRequest)}, + AlgorithmSpec{adaptFromTask(ccdbRequest, dcsMVsubspec)}, Options{{"use-verbose-mode", VariantType::Bool, false, {"Use verbose mode"}}}}; } diff --git a/Detectors/Calibration/workflow/src/mean-vertex-calibration-workflow.cxx b/Detectors/Calibration/workflow/src/mean-vertex-calibration-workflow.cxx index 337690ec5104d..a893f99a60552 100644 --- a/Detectors/Calibration/workflow/src/mean-vertex-calibration-workflow.cxx +++ b/Detectors/Calibration/workflow/src/mean-vertex-calibration-workflow.cxx @@ -20,6 +20,7 @@ void customize(std::vector& workflowOptions) { // option allowing to set parameters std::vector options{ + {"meanvertex-dcs-subspec", VariantType::Int, 0x7fff, {"If >0, send text version of MeanVertex to this subspec"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}}; std::swap(workflowOptions, options); } @@ -32,6 +33,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { WorkflowSpec specs; o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); - specs.emplace_back(getMeanVertexCalibDeviceSpec()); + specs.emplace_back(getMeanVertexCalibDeviceSpec(configcontext.options().get("meanvertex-dcs-subspec"))); return specs; } diff --git a/prodtests/full-system-test/aggregator-workflow.sh b/prodtests/full-system-test/aggregator-workflow.sh index 2812c6da76817..2c0a4de6dcf70 100755 --- a/prodtests/full-system-test/aggregator-workflow.sh +++ b/prodtests/full-system-test/aggregator-workflow.sh @@ -14,10 +14,21 @@ source $O2DPG_ROOT/DATA/common/setenv.sh || { echo "setenv.sh failed" 1>&2 && ex source $O2DPG_ROOT/DATA/common/getCommonArgs.sh || { echo "getCommonArgs.sh failed" 1>&2 && exit 1; } source $O2DPG_ROOT/DATA/common/setenv_calib.sh || { echo "setenv_calib.sh failed" 1>&2 && exit 1; } +# if the populator for DCS CCDB is needed, set it to non-0 +: ${NEED_DCS_CCDB_POPULATOR:=0} + +# the production CCDB populator will accept subspecs in this range +: ${CCDBPRO_SUBSPEC_MIN:=0} +: ${CCDBPRO_SUBSPEC_MAX:=32767} + +# the DCS CCDB populator will accept subspecs in this range +: ${CCDBDCS_SUBSPEC_MIN:=32768} +: ${CCDBDCS_SUBSPEC_MAX:=65535} + # check that WORKFLOW_DETECTORS is needed, otherwise the wrong calib wf will be built if [[ -z ${WORKFLOW_DETECTORS:-} ]]; then echo "WORKFLOW_DETECTORS must be defined" 1>&2; exit 1; fi -# CCDB destination for uploads +# CCDB destination for uploads to the standard ccdb if [[ -z ${CCDB_POPULATOR_UPLOAD_PATH+x} ]]; then if [[ $RUNTYPE == "SYNTHETIC" || "${GEN_TOPO_DEPLOYMENT_TYPE:-}" == "ALICE_STAGING" ]]; then CCDB_POPULATOR_UPLOAD_PATH="http://ccdb-test.cern.ch:8080" @@ -31,8 +42,23 @@ if [[ -z ${CCDB_POPULATOR_UPLOAD_PATH+x} ]]; then CCDB_POPULATOR_UPLOAD_PATH="none" fi fi +# CCDB destination for uploads to the DCS exchange ccdb +if [[ -z ${CCDB_DCS_POPULATOR_UPLOAD_PATH+x} ]]; then + if [[ $RUNTYPE == "SYNTHETIC" || "${GEN_TOPO_DEPLOYMENT_TYPE:-}" == "ALICE_STAGING" ]]; then + CCDB_DCS_POPULATOR_UPLOAD_PATH="http://ccdb-test.cern.ch:8080" + elif [[ $RUNTYPE == "PHYSICS" ]]; then + if [[ $EPNSYNCMODE == 1 ]]; then + CCDB_DCS_POPULATOR_UPLOAD_PATH="$DCSCCDBSERVER_PERS" + else + CCDB_DCS_POPULATOR_UPLOAD_PATH="http://ccdb-test.cern.ch:8080" + fi + else + CCDB_DCS_POPULATOR_UPLOAD_PATH="none" + fi +fi if [[ "${GEN_TOPO_VERBOSE:-}" == "1" ]]; then echo "CCDB_POPULATOR_UPLOAD_PATH = $CCDB_POPULATOR_UPLOAD_PATH" 1>&2 + echo "CCDB_DCS_POPULATOR_UPLOAD_PATH = $CCDB_DCS_POPULATOR_UPLOAD_PATH" 1>&2 fi # Avoid writing calibration data for run types different than physics @@ -200,7 +226,9 @@ if [[ $AGGREGATOR_TASKS == BARREL_TF ]] || [[ $AGGREGATOR_TASKS == ALL ]]; then if [[ $CALIB_PRIMVTX_MEANVTX == 1 ]]; then : ${TFPERSLOTS_MEANVTX:=55000} : ${DELAYINTFS_MEANVTX:=10} - add_W o2-calibration-mean-vertex-calibration-workflow "" "MeanVertexCalib.tfPerSlot=$TFPERSLOTS_MEANVTX;MeanVertexCalib.maxTFdelay=$DELAYINTFS_MEANVTX" + : ${DCSSUBSPEC_MEANVTX:=$CCDBDCS_SUBSPEC_MIN} # set 0 to deactivate sending CSV meanvertex version, use value >= $CCDBDCS_SUBSPEC_MIN to send it to DCS CCDB server instead of production one + [[ $DCSSUBSPEC_MEANVTX -ge $CCDBDCS_SUBSPEC_MIN ]] && NEED_DCS_CCDB_POPULATOR=1 + add_W o2-calibration-mean-vertex-calibration-workflow "--meanvertex-dcs-subspec $DCSSUBSPEC_MEANVTX" "MeanVertexCalib.tfPerSlot=$TFPERSLOTS_MEANVTX;MeanVertexCalib.maxTFdelay=$DELAYINTFS_MEANVTX" fi # ITS if [[ $CALIB_ITS_DEADMAP_TIME == 1 ]]; then @@ -371,7 +399,9 @@ if [[ "${GEN_TOPO_VERBOSE:-}" == "1" ]]; then fi fi -if [[ $CCDB_POPULATOR_UPLOAD_PATH != "none" ]] && [[ ! -z $WORKFLOW ]]; then add_W o2-calibration-ccdb-populator-workflow "--ccdb-path $CCDB_POPULATOR_UPLOAD_PATH --environment \"DPL_DONT_DROP_OLD_TIMESLICE=1\""; fi +if [[ $CCDB_POPULATOR_UPLOAD_PATH != "none" ]] && [[ ! -z $WORKFLOW ]]; then add_W o2-calibration-ccdb-populator-workflow "--ccdb-path $CCDB_POPULATOR_UPLOAD_PATH --environment \"DPL_DONT_DROP_OLD_TIMESLICE=1\" --sspec-min $CCDBPRO_SUBSPEC_MIN --sspec-max $CCDBPRO_SUBSPEC_MAX"; fi + +if [[ $CCDB_DCS_POPULATOR_UPLOAD_PATH != "none" ]] && [[ ! -z $WORKFLOW ]] && [[ $NEED_DCS_CCDB_POPULATOR != 0 ]]; then add_W o2-calibration-ccdb-populator-workflow "--ccdb-path $CCDB_DCS_POPULATOR_UPLOAD_PATH --environment \"DPL_DONT_DROP_OLD_TIMESLICE=1\" --sspec-min $CCDBDCS_SUBSPEC_MIN --sspec-max $CCDBDCS_SUBSPEC_MAX --name-extention dcs"; fi if ! workflow_has_parameter CALIB_LOCAL_INTEGRATED_AGGREGATOR; then WORKFLOW+="o2-dpl-run $ARGS_ALL $GLOBALDPLOPT" From 2ce233c4eabdb4d930a8f000099e09b3f0d1c257 Mon Sep 17 00:00:00 2001 From: wiechula <11199190+wiechula@users.noreply.github.com> Date: Fri, 17 May 2024 13:01:36 +0200 Subject: [PATCH 0234/2997] TPC: update default cluster errors seeding --- GPU/GPUTracking/Definitions/GPUSettingsList.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index b5d5bb5d1edc5..777ea1e70b0d8 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -44,8 +44,8 @@ AddOptionRTC(clusterError2CorrectionY, float, 1.f, "", 0, "correction (multiplic AddOptionRTC(clusterError2CorrectionZ, float, 1.f, "", 0, "correction (multiplicative) for the squared cluster error during tracking") AddOptionRTC(clusterError2AdditionalY, float, 0.f, "", 0, "correction (additive) for the squared cluster error during track fitting") AddOptionRTC(clusterError2AdditionalZ, float, 0.f, "", 0, "correction (additive) for the squared cluster error during track fitting") -AddOptionRTC(clusterError2AdditionalYSeeding, float, 0.f, "", 0, "correction (additive) for the squared cluster error during track seeding") -AddOptionRTC(clusterError2AdditionalZSeeding, float, 0.f, "", 0, "correction (additive) for the squared cluster error during track seeding") +AddOptionRTC(clusterError2AdditionalYSeeding, float, 0.1f, "", 0, "correction (additive) for the squared cluster error during track seeding") +AddOptionRTC(clusterError2AdditionalZSeeding, float, 0.15f, "", 0, "correction (additive) for the squared cluster error during track seeding") AddOptionRTC(clusterRejectChi2TolleranceY, float, 1.f, "", 0, "Multiplicative factor multiplied onto chi2 in Y direction for cluster rejection check during track fit") AddOptionRTC(clusterRejectChi2TolleranceZ, float, 1.f, "", 0, "Multiplicative factor multiplied onto chi2 in Z direction for cluster rejection check during track fit") AddOptionRTC(clusterErrorOccupancyScaler, float, 9.95e-04f, "", 0, "Scaling factor applied to occupancy histogram bin in cluster error estimation") From b518797699ab5f113be52093a5a5209358a43ff3 Mon Sep 17 00:00:00 2001 From: shahoian Date: Sat, 18 May 2024 15:37:53 +0200 Subject: [PATCH 0235/2997] mch-digit-reader uses --mch-digit-infile and not --infile --- prodtests/full-system-test/dpl-workflow.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index a5d0b290e11a5..6ae605e86cd58 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -382,8 +382,8 @@ if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ ! -z ${WORKFL add_W o2-global-track-cluster-reader "--cluster-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS --track-types $WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS $GLOBAL_READER_OPTIONS $DISABLE_MC $HBFINI_OPTIONS" has_detector FV0 && has_detector_from_global_reader FV0 && add_W o2-fv0-digit-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --fv0-digit-infile o2_fv0digits.root" has_detector MID && has_detector_from_global_reader MID && add_W o2-mid-digits-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --mid-digit-infile mid-digits-decoded.root" - has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-digits-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --infile mchdigits.root" - has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-digits-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --infile mchfdigits.root --mch-output-digits-data-description F-DIGITS --mch-output-digitrofs-data-description TC-F-DIGITROFS" + has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-digits-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --mch-digit-infile mchdigits.root" + has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-digits-reader-workflow "$DISABLE_MC $HBFINI_OPTIONS --mch-digit-infile mchfdigits.root --mch-output-digits-data-description F-DIGITS --mch-output-digitrofs-data-description TC-F-DIGITROFS" has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-errors-reader-workflow "$HBFINI_OPTIONS" "" 0 has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-clusters-reader-workflow "$HBFINI_OPTIONS" "" 0 has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-preclusters-reader-workflow "$HBFINI_OPTIONS" "" 0 From fa02b6687f316bdd6159cee299cf657efb1b2628 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 17 May 2024 14:27:42 +0200 Subject: [PATCH 0236/2997] DPL: print channel name when tracing messages --- .../Core/include/Framework/DataRelayer.h | 19 ++++++++ Framework/Core/src/DataProcessingDevice.cxx | 43 +++++++------------ Framework/Core/src/DataRelayer.cxx | 13 +++--- Framework/Core/test/benchmark_DataRelayer.cxx | 18 +++++--- Framework/Core/test/test_DataRelayer.cxx | 42 ++++++++++++------ 5 files changed, 82 insertions(+), 53 deletions(-) diff --git a/Framework/Core/include/Framework/DataRelayer.h b/Framework/Core/include/Framework/DataRelayer.h index 1ebcf549d6a29..012b909096317 100644 --- a/Framework/Core/include/Framework/DataRelayer.h +++ b/Framework/Core/include/Framework/DataRelayer.h @@ -81,6 +81,24 @@ class DataRelayer CompletionPolicy::CompletionOp op; }; + enum struct InputType : int { + Invalid = 0, + Data = 1, + SourceInfo = 2, + DomainInfo = 3 + }; + + struct InputInfo { + InputInfo(size_t p, size_t s, InputType t, ChannelIndex i) + : position(p), size(s), type(t), index(i) + { + } + size_t position; + size_t size; + InputType type; + ChannelIndex index; + }; + DataRelayer(CompletionPolicy const&, std::vector const& routes, TimesliceIndex&, @@ -114,6 +132,7 @@ class DataRelayer /// Notice that we expect that the header is an O2 Header Stack RelayChoice relay(void const* rawHeader, std::unique_ptr* messages, + InputInfo const& info, size_t nMessages, size_t nPayloads = 1, OnDropCallback onDrop = nullptr); diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 602fe7cc29548..6b926d92353be 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -1765,29 +1765,15 @@ struct WaitBackpressurePolicy { /// boilerplate which the user does not need to care about at top level. void DataProcessingDevice::handleData(ServiceRegistryRef ref, InputChannelInfo& info) { + using InputInfo = DataRelayer::InputInfo; + using InputType = DataRelayer::InputType; + auto& context = ref.get(); // This is the same id as the upper level function, so we get the events // associated with the same interval. We will simply use "handle_data" as // the category. O2_SIGNPOST_ID_FROM_POINTER(cid, device, &info); - enum struct InputType : int { - Invalid = 0, - Data = 1, - SourceInfo = 2, - DomainInfo = 3 - }; - - struct InputInfo { - InputInfo(size_t p, size_t s, InputType t) - : position(p), size(s), type(t) - { - } - size_t position; - size_t size; - InputType type; - }; - // This is how we validate inputs. I.e. we try to enforce the O2 Data model // and we do a few stats. We bind parts as a lambda captured variable, rather // than an input, because we do not want the outer loop actually be exposed @@ -1804,8 +1790,8 @@ void DataProcessingDevice::handleData(ServiceRegistryRef ref, InputChannelInfo& results.reserve(parts.Size() / 2); size_t nTotalPayloads = 0; - auto insertInputInfo = [&results, &nTotalPayloads](size_t position, size_t length, InputType type) { - results.emplace_back(position, length, type); + auto insertInputInfo = [&results, &nTotalPayloads](size_t position, size_t length, InputType type, ChannelIndex index) { + results.emplace_back(position, length, type, index); if (type != InputType::Invalid && length > 1) { nTotalPayloads += length - 1; } @@ -1817,24 +1803,24 @@ void DataProcessingDevice::handleData(ServiceRegistryRef ref, InputChannelInfo& if (sih) { O2_SIGNPOST_EVENT_EMIT(device, cid, "handle_data", "Got SourceInfoHeader with state %d", (int)sih->state); info.state = sih->state; - insertInputInfo(pi, 2, InputType::SourceInfo); + insertInputInfo(pi, 2, InputType::SourceInfo, info.id); *context.wasActive = true; continue; } auto dih = o2::header::get(headerData); if (dih) { - insertInputInfo(pi, 2, InputType::DomainInfo); + insertInputInfo(pi, 2, InputType::DomainInfo, info.id); *context.wasActive = true; continue; } auto dh = o2::header::get(headerData); if (!dh) { - insertInputInfo(pi, 0, InputType::Invalid); + insertInputInfo(pi, 0, InputType::Invalid, info.id); O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "handle_data", "Header is not a DataHeader?"); continue; } if (dh->payloadSize > parts.At(pi + 1)->GetSize()) { - insertInputInfo(pi, 0, InputType::Invalid); + insertInputInfo(pi, 0, InputType::Invalid, info.id); O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "handle_data", "DataHeader payloadSize mismatch"); continue; } @@ -1847,14 +1833,14 @@ void DataProcessingDevice::handleData(ServiceRegistryRef ref, InputChannelInfo& O2_SIGNPOST_START(parts, pid, "parts", "Processing DataHeader with splitPayloadParts %d and splitPayloadIndex %d", dh->splitPayloadParts, dh->splitPayloadIndex); } if (!dph) { - insertInputInfo(pi, 2, InputType::Invalid); + insertInputInfo(pi, 2, InputType::Invalid, info.id); O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "handle_data", "Header stack does not contain DataProcessingHeader"); continue; } if (dh->splitPayloadParts > 0 && dh->splitPayloadParts == dh->splitPayloadIndex) { // this is indicating a sequence of payloads following the header // FIXME: we will probably also set the DataHeader version - insertInputInfo(pi, dh->splitPayloadParts + 1, InputType::Data); + insertInputInfo(pi, dh->splitPayloadParts + 1, InputType::Data, info.id); pi += dh->splitPayloadParts - 1; } else { // We can set the type for the next splitPayloadParts @@ -1864,12 +1850,12 @@ void DataProcessingDevice::handleData(ServiceRegistryRef ref, InputChannelInfo& size_t finalSplitPayloadIndex = pi + (dh->splitPayloadParts > 0 ? dh->splitPayloadParts : 1) * 2; if (finalSplitPayloadIndex > parts.Size()) { O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "handle_data", "DataHeader::splitPayloadParts invalid"); - insertInputInfo(pi, 0, InputType::Invalid); + insertInputInfo(pi, 0, InputType::Invalid, info.id); continue; } - insertInputInfo(pi, 2, InputType::Data); + insertInputInfo(pi, 2, InputType::Data, info.id); for (; pi + 2 < finalSplitPayloadIndex; pi += 2) { - insertInputInfo(pi + 2, 2, InputType::Data); + insertInputInfo(pi + 2, 2, InputType::Data, info.id); } } } @@ -1941,6 +1927,7 @@ void DataProcessingDevice::handleData(ServiceRegistryRef ref, InputChannelInfo& }; auto relayed = relayer.relay(parts.At(headerIndex)->GetData(), &parts.At(headerIndex), + input, nMessages, nPayloadsPerHeader, onDrop); diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index 943cd0404f0b3..bd0fba7b35e3e 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -394,6 +394,7 @@ void DataRelayer::pruneCache(TimesliceSlot slot, OnDropCallback onDrop) DataRelayer::RelayChoice DataRelayer::relay(void const* rawHeader, std::unique_ptr* messages, + InputInfo const& info, size_t nMessages, size_t nPayloads, std::function&, TimesliceIndex::OldestOutputInfo)> onDrop) @@ -443,11 +444,13 @@ DataRelayer::RelayChoice &nMessages, &nPayloads, &cache = mCache, - numInputTypes = mDistinctRoutesIndex.size()](TimesliceId timeslice, int input, TimesliceSlot slot) { + &services = mContext, + numInputTypes = mDistinctRoutesIndex.size()](TimesliceId timeslice, int input, TimesliceSlot slot, InputInfo const& info) { O2_SIGNPOST_ID_GENERATE(aid, data_relayer); - O2_SIGNPOST_EVENT_EMIT(data_relayer, aid, "saveInSlot", "saving %{public}s@%zu in slot %zu", + O2_SIGNPOST_EVENT_EMIT(data_relayer, aid, "saveInSlot", "saving %{public}s@%zu in slot %zu from %{public}s", fmt::format("{:x}", *o2::header::get(messages[0]->GetData())).c_str(), - timeslice.value, slot.index); + timeslice.value, slot.index, + info.index.value == ChannelIndex::INVALID ? "invalid" : services.get().getInputChannel(info.index)->GetName().c_str()); auto cacheIdx = numInputTypes * slot.index + input; MessageSet& target = cache[cacheIdx]; cachedStateMetrics[cacheIdx] = CacheEntryStatus::PENDING; @@ -537,7 +540,7 @@ DataRelayer::RelayChoice this->pruneCache(slot, onDrop); mPruneOps.erase(std::remove_if(mPruneOps.begin(), mPruneOps.end(), [slot](const auto& x) { return x.slot == slot; }), mPruneOps.end()); } - saveInSlot(timeslice, input, slot); + saveInSlot(timeslice, input, slot, info); index.publishSlot(slot); index.markAsDirty(slot, true); stats.updateStats({static_cast(ProcessingStatsId::RELAYED_MESSAGES), DataProcessingStats::Op::Add, (int)1}); @@ -619,7 +622,7 @@ DataRelayer::RelayChoice // cache still holds the old data, so we prune it. this->pruneCache(slot, onDrop); mPruneOps.erase(std::remove_if(mPruneOps.begin(), mPruneOps.end(), [slot](const auto& x) { return x.slot == slot; }), mPruneOps.end()); - saveInSlot(timeslice, input, slot); + saveInSlot(timeslice, input, slot, info); index.publishSlot(slot); index.markAsDirty(slot, true); return RelayChoice{.type = RelayChoice::Type::WillRelay}; diff --git a/Framework/Core/test/benchmark_DataRelayer.cxx b/Framework/Core/test/benchmark_DataRelayer.cxx index 3e8302e97b0a7..dcff3930dbaad 100644 --- a/Framework/Core/test/benchmark_DataRelayer.cxx +++ b/Framework/Core/test/benchmark_DataRelayer.cxx @@ -86,8 +86,9 @@ static void BM_RelaySingleSlot(benchmark::State& state) inflightMessages.emplace_back(transport->CreateMessage(1000)); memcpy(inflightMessages[0]->GetData(), stack.data(), stack.size()); + DataRelayer::InputInfo fakeInfo{0, inflightMessages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; for (auto _ : state) { - relayer.relay(inflightMessages[0]->GetData(), inflightMessages.data(), inflightMessages.size()); + relayer.relay(inflightMessages[0]->GetData(), inflightMessages.data(), fakeInfo, inflightMessages.size()); std::vector ready; relayer.getReadyToProcess(ready); assert(ready.size() == 1); @@ -144,7 +145,8 @@ static void BM_RelayMultipleSlots(benchmark::State& state) Stack stack{dh, DataProcessingHeader{timeslice++, 1}}; memcpy(inflightMessages[0]->GetData(), stack.data(), stack.size()); - relayer.relay(inflightMessages[0]->GetData(), inflightMessages.data(), inflightMessages.size()); + DataRelayer::InputInfo fakeInfo{0, inflightMessages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(inflightMessages[0]->GetData(), inflightMessages.data(), fakeInfo, inflightMessages.size()); std::vector ready; relayer.getReadyToProcess(ready); assert(ready.size() == 1); @@ -211,13 +213,15 @@ static void BM_RelayMultipleRoutes(benchmark::State& state) memcpy(inflightMessages[2]->GetData(), stack2.data(), stack2.size()); for (auto _ : state) { - relayer.relay(inflightMessages[0]->GetData(), &inflightMessages[0], 2); + DataRelayer::InputInfo fakeInfo{0, inflightMessages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(inflightMessages[0]->GetData(), &inflightMessages[0], fakeInfo, 2); std::vector ready; relayer.getReadyToProcess(ready); assert(ready.size() == 1); assert(ready[0].op == CompletionPolicy::CompletionOp::Consume); - relayer.relay(inflightMessages[2]->GetData(), &inflightMessages[2], 2); + DataRelayer::InputInfo fakeInfo2{0, inflightMessages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(inflightMessages[2]->GetData(), &inflightMessages[2], fakeInfo2, 2); ready.clear(); relayer.getReadyToProcess(ready); assert(ready.size() == 1); @@ -282,8 +286,9 @@ static void BM_RelaySplitParts(benchmark::State& state) inflightMessages.emplace_back(std::move(payload)); } + DataRelayer::InputInfo fakeInfo{0, inflightMessages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; for (auto _ : state) { - relayer.relay(inflightMessages[0]->GetData(), inflightMessages.data(), inflightMessages.size()); + relayer.relay(inflightMessages[0]->GetData(), inflightMessages.data(), fakeInfo, inflightMessages.size()); std::vector ready; relayer.getReadyToProcess(ready); assert(ready.size() == 1); @@ -336,8 +341,9 @@ static void BM_RelayMultiplePayloads(benchmark::State& state) inflightMessages.emplace_back(transport->CreateMessage(dh.payloadSize)); } + DataRelayer::InputInfo fakeInfo{0, inflightMessages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; for (auto _ : state) { - relayer.relay(inflightMessages[0]->GetData(), inflightMessages.data(), inflightMessages.size(), nPayloads); + relayer.relay(inflightMessages[0]->GetData(), inflightMessages.data(), fakeInfo, inflightMessages.size(), nPayloads); std::vector ready; relayer.getReadyToProcess(ready); assert(ready.size() == 1); diff --git a/Framework/Core/test/test_DataRelayer.cxx b/Framework/Core/test/test_DataRelayer.cxx index bd1ead40c9773..d112e8736399a 100644 --- a/Framework/Core/test/test_DataRelayer.cxx +++ b/Framework/Core/test/test_DataRelayer.cxx @@ -99,7 +99,8 @@ TEST_CASE("DataRelayer") messages[1] = transport->CreateMessage(1000); fair::mq::MessagePtr& header = messages[0]; fair::mq::MessagePtr& payload = messages[1]; - relayer.relay(header->GetData(), messages.data(), messages.size()); + DataRelayer::InputInfo fakeInfo{0, messages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(header->GetData(), messages.data(), fakeInfo, messages.size()); std::vector ready; relayer.getReadyToProcess(ready); REQUIRE(ready.size() == 1); @@ -148,7 +149,8 @@ TEST_CASE("DataRelayer") messages[1] = transport->CreateMessage(1000); fair::mq::MessagePtr& header = messages[0]; fair::mq::MessagePtr& payload = messages[1]; - relayer.relay(header->GetData(), messages.data(), messages.size()); + DataRelayer::InputInfo fakeInfo{0, messages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(header->GetData(), messages.data(), fakeInfo, messages.size()); std::vector ready; relayer.getReadyToProcess(ready); REQUIRE(ready.size() == 1); @@ -201,7 +203,8 @@ TEST_CASE("DataRelayer") messages[1] = transport->CreateMessage(1000); fair::mq::MessagePtr& header = messages[0]; fair::mq::MessagePtr& payload = messages[1]; - relayer.relay(header->GetData(), messages.data(), messages.size()); + DataRelayer::InputInfo fakeInfo{0, messages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(header->GetData(), messages.data(), fakeInfo, messages.size()); REQUIRE(header.get() == nullptr); REQUIRE(payload.get() == nullptr); }; @@ -281,7 +284,8 @@ TEST_CASE("DataRelayer") messages[1] = transport->CreateMessage(1000); fair::mq::MessagePtr& header = messages[0]; fair::mq::MessagePtr& payload = messages[1]; - relayer.relay(header->GetData(), messages.data(), messages.size()); + DataRelayer::InputInfo fakeInfo{0, messages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(header->GetData(), messages.data(), fakeInfo, messages.size()); REQUIRE(header.get() == nullptr); REQUIRE(payload.get() == nullptr); }; @@ -373,7 +377,8 @@ TEST_CASE("DataRelayer") messages[1] = transport->CreateMessage(1000); fair::mq::MessagePtr& header = messages[0]; fair::mq::MessagePtr& payload = messages[1]; - auto res = relayer.relay(header->GetData(), messages.data(), messages.size()); + DataRelayer::InputInfo fakeInfo{0, messages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + auto res = relayer.relay(header->GetData(), messages.data(), fakeInfo, messages.size()); REQUIRE((res.type != DataRelayer::RelayChoice::Type::WillRelay || header.get() == nullptr)); REQUIRE((res.type != DataRelayer::RelayChoice::Type::WillRelay || payload.get() == nullptr)); REQUIRE((res.type != DataRelayer::RelayChoice::Type::Backpressured || header.get() != nullptr)); @@ -455,7 +460,8 @@ TEST_CASE("DataRelayer") messages[0] = o2::pmr::getMessage(Stack{channelAlloc, dh, h}); messages[1] = transport->CreateMessage(1000); fair::mq::MessagePtr& header = messages[0]; - return relayer.relay(header->GetData(), messages.data(), messages.size()); + DataRelayer::InputInfo fakeInfo{0, messages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + return relayer.relay(header->GetData(), messages.data(), fakeInfo, messages.size()); }; // This fills the cache, and then empties it. @@ -526,7 +532,8 @@ TEST_CASE("DataRelayer") messages[0] = o2::pmr::getMessage(Stack{channelAlloc, dh, h}); messages[1] = transport->CreateMessage(1000); fair::mq::MessagePtr& header = messages[0]; - return relayer.relay(header->GetData(), messages.data(), messages.size()); + DataRelayer::InputInfo fakeInfo{0, messages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + return relayer.relay(header->GetData(), messages.data(), fakeInfo, messages.size()); }; // This fills the cache, and then empties it. @@ -585,7 +592,8 @@ TEST_CASE("DataRelayer") messages[1] = transport->CreateMessage(1000); fair::mq::MessagePtr& header = messages[0]; fair::mq::MessagePtr& payload = messages[1]; - relayer.relay(header->GetData(), &messages[0], 2); + DataRelayer::InputInfo fakeInfo{0, messages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(header->GetData(), &messages[0], fakeInfo, 2); REQUIRE(header.get() == nullptr); REQUIRE(payload.get() == nullptr); // This fills the cache, and then waits. @@ -593,7 +601,8 @@ TEST_CASE("DataRelayer") messages[3] = transport->CreateMessage(1000); fair::mq::MessagePtr& header2 = messages[2]; fair::mq::MessagePtr& payload2 = messages[3]; - auto action = relayer.relay(header2->GetData(), &messages[2], 2); + DataRelayer::InputInfo fakeInfo2{2, 2, DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + auto action = relayer.relay(header2->GetData(), &messages[2], fakeInfo2, 2); REQUIRE(action.type == DataRelayer::RelayChoice::Type::Backpressured); REQUIRE(header2.get() != nullptr); REQUIRE(payload2.get() != nullptr); @@ -644,7 +653,8 @@ TEST_CASE("DataRelayer") messages[1] = transport->CreateMessage(1000); fair::mq::MessagePtr& header = messages[0]; fair::mq::MessagePtr& payload = messages[1]; - relayer.relay(header->GetData(), &messages[0], 2); + DataRelayer::InputInfo fakeInfo{0, 2, DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(header->GetData(), &messages[0], fakeInfo, 2); REQUIRE(header.get() == nullptr); REQUIRE(payload.get() == nullptr); // This fills the cache, and then waits. @@ -652,7 +662,8 @@ TEST_CASE("DataRelayer") messages[3] = transport->CreateMessage(1000); fair::mq::MessagePtr& header2 = messages[2]; fair::mq::MessagePtr& payload2 = messages[3]; - auto action = relayer.relay(header2->GetData(), &messages[2], 2); + DataRelayer::InputInfo fakeInfo2{2, 2, DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + auto action = relayer.relay(header2->GetData(), &messages[2], fakeInfo, 2); REQUIRE(action.type == DataRelayer::RelayChoice::Type::Backpressured); CHECK(action.timeslice.value == 1); REQUIRE(header2.get() != nullptr); @@ -660,7 +671,8 @@ TEST_CASE("DataRelayer") // This fills the cache, and then waits. messages[4] = o2::pmr::getMessage(Stack{channelAlloc, dh1, DataProcessingHeader{1, 1}}); messages[5] = transport->CreateMessage(1000); - relayer.relay(header2->GetData(), &messages[4], 2); + DataRelayer::InputInfo fakeInfo3{4, 2, DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(header2->GetData(), &messages[4], fakeInfo3, 2); REQUIRE(action.type == DataRelayer::RelayChoice::Type::Backpressured); CHECK(action.timeslice.value == 1); REQUIRE(header2.get() != nullptr); @@ -707,7 +719,8 @@ TEST_CASE("DataRelayer") } REQUIRE(splitParts.size() == 2 * nSplitParts); - relayer.relay(splitParts[0]->GetData(), splitParts.data(), splitParts.size()); + DataRelayer::InputInfo fakeInfo{0, splitParts.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(splitParts[0]->GetData(), splitParts.data(), fakeInfo, splitParts.size()); std::vector ready; relayer.getReadyToProcess(ready); REQUIRE(ready.size() == 1); @@ -763,7 +776,8 @@ TEST_CASE("DataRelayer") ++nTotalPayloads; } REQUIRE(messages.size() == nPayloads + 1); - relayer.relay(messages[0]->GetData(), messages.data(), messages.size(), nPayloads); + DataRelayer::InputInfo fakeInfo{0, messages.size(), DataRelayer::InputType::Data, {ChannelIndex::INVALID}}; + relayer.relay(messages[0]->GetData(), messages.data(), fakeInfo, messages.size(), nPayloads); sequenceSize.emplace_back(nPayloads); }; createSequence(100); From 39e24c8000e2d6f87172dc6945a20c1dfc69c17b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 18 May 2024 14:46:14 +0200 Subject: [PATCH 0237/2997] DPL: fix reading of metadata Previously, reading metadata from alien:// did not work when using an @input_list.txt file containting the filename, rather than specifying alien directly on the command line. --- Framework/AnalysisSupport/src/Plugin.cxx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Framework/AnalysisSupport/src/Plugin.cxx b/Framework/AnalysisSupport/src/Plugin.cxx index 2ec12a92857cf..c69e5c8c56bdd 100644 --- a/Framework/AnalysisSupport/src/Plugin.cxx +++ b/Framework/AnalysisSupport/src/Plugin.cxx @@ -75,11 +75,6 @@ struct DiscoverMetadataInAOD : o2::framework::ConfigDiscoveryPlugin { if (filename.empty()) { return {}; } - if (filename.rfind("alien://", 0) == 0) { - LOGP(debug, "AliEn file requested. Enabling support."); - TGrid::Connect("alien://"); - } - LOGP(info, "Loading metadata from file {} in PID {}", filename, getpid()); std::vector results; TFile* currentFile = nullptr; if (filename.at(0) == '@') { @@ -91,10 +86,12 @@ struct DiscoverMetadataInAOD : o2::framework::ConfigDiscoveryPlugin { } std::getline(file, filename); file.close(); - currentFile = TFile::Open(filename.c_str()); - } else { - currentFile = TFile::Open(filename.c_str()); } + if (filename.rfind("alien://", 0) == 0) { + TGrid::Connect("alien://"); + } + LOGP(info, "Loading metadata from file {} in PID {}", filename, getpid()); + currentFile = TFile::Open(filename.c_str()); if (!currentFile) { LOGP(fatal, "Couldn't open file \"{}\"!", filename); } From bb45d28dac77e8ab17fbf4b07e22fae70aab76ab Mon Sep 17 00:00:00 2001 From: noferini <9963644+noferini@users.noreply.github.com> Date: Sun, 21 Apr 2024 11:23:18 +0200 Subject: [PATCH 0238/2997] add trk res in TOF match chi2 --- .../ReconstructionDataFormats/MatchInfoTOF.h | 9 +- .../MatchInfoTOFReco.h | 12 +- .../include/GlobalTracking/MatchTOF.h | 3 +- .../include/GlobalTracking/MatchTOFParams.h | 8 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 174 ++++++++++++++++-- 5 files changed, 187 insertions(+), 19 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h index 29442325e2f66..c3cdae54823e6 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOF.h @@ -58,6 +58,11 @@ class MatchInfoTOF int getIdLocal() const { return mIdLocal; } + float getVz() const { return mVz; } + void setVz(float val) { mVz = val; } + int getChannel() const { return mChannel; } + void setChannel(int val) { mChannel = val; } + private: int mIdLocal; // track id in sector of the pair track-TOFcluster float mChi2; // chi2 of the pair track-TOFcluster @@ -69,8 +74,10 @@ class MatchInfoTOF float mDZatTOF = 0.0; ///< DZ position at TOF float mDeltaT = 0.0; ///< tTOF - TPC (microsec) double mSignal = 0.0; ///< TOF time in ps + float mVz = 0.0; ///< Vz from TOF match + int mChannel = -1; ///< channel - ClassDefNV(MatchInfoTOF, 5); + ClassDefNV(MatchInfoTOF, 6); }; } // namespace dataformats } // namespace o2 diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h index aa955ca81c1c6..188b7b3ab121a 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/MatchInfoTOFReco.h @@ -45,6 +45,13 @@ class MatchInfoTOFReco : public MatchInfoTOF float pt() const { return mPt; } void setPt(float pt) { mPt = pt; } + void setResX(float val) { mResX = val; } + void setResZ(float val) { mResZ = val; } + void setResT(float val) { mResT = val; } + float getResX() const { return mResX; } + float getResZ() const { return mResZ; } + float getResT() const { return mResT; } + void setTrackType(TrackType value) { mTrackType = value; } TrackType getTrackType() const { return mTrackType; } @@ -52,7 +59,10 @@ class MatchInfoTOFReco : public MatchInfoTOF TrackType mTrackType; ///< track type (TPC, ITSTPC, TPCTRD, ITSTPCTRD) bool mFakeMC = false; float mPt = 0; - ClassDefNV(MatchInfoTOFReco, 4); + float mResX = 1; + float mResZ = 1; + float mResT = 1; + ClassDefNV(MatchInfoTOFReco, 5); }; } // namespace dataformats } // namespace o2 diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h index 83f4dae0c2476..957ae07544cf4 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h @@ -309,6 +309,7 @@ class MatchTOF ///< per sector indices of track entry in mTracksWork std::array, o2::constants::math::NSectors> mTracksSectIndexCache[trkType::SIZE]; std::array, o2::constants::math::NSectors> mTracksSeed[trkType::SIZE]; + std::vector mVZtpcOnly[o2::constants::math::NSectors]; std::vector mExtraTPCFwdTime[o2::constants::math::NSectors]; ///< track extra params for TPC tracks: Fws Max time std::vector mTOFClusWork; ///< track params prepared for matching @@ -347,7 +348,7 @@ class MatchTOF TStopwatch mTimerMatchITSTPC; TStopwatch mTimerMatchTPC; TStopwatch mTimerDBG; - ClassDefNV(MatchTOF, 5); + ClassDefNV(MatchTOF, 6); }; } // namespace globaltracking } // namespace o2 diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOFParams.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOFParams.h index 503f96ec36f19..6ed36a6e18450 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOFParams.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOFParams.h @@ -23,8 +23,12 @@ namespace globaltracking { struct MatchTOFParams : public o2::conf::ConfigurableParamHelper { - float calibMaxChi2 = 3.0; - float nsigmaTimeCut = 4.; // number of sigmas for non-TPC track time resolution to consider + float calibMaxChi2 = 3.0; // max value of Chi2 allowed for using matched tracks in calibration + float nsigmaTimeCut = 4.; // number of sigmas for non-TPC track time resolution to consider + float maxResX = 1.; // max value of track resolution (X dir) used in TOF matching (truncation to that in case it is larger) + float maxResZ = 1.; // max value of track resolution (Z dir) used in TOF matching (truncation to that in case it is larger) + float maxChi2 = 10.; // max value of Chi2 accepted for matching to TOF + bool applyPIDcutTPConly = true; // apply PID cut on TPC only tracks O2ParamDef(MatchTOFParams, "MatchTOF"); }; diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index a384c489520fd..8e66905a91b93 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -187,7 +187,10 @@ void MatchTOF::run(const o2::globaltracking::RecoContainer& inp, unsigned long f } } else { for (auto& matchingPair : mMatchedTracksPairsSec[sec]) { - int bct0 = int((matchingPair.getSignal() - 10000) * Geo::BC_TIME_INPS_INV); + int bct0 = int((matchingPair.getSignal() - matchingPair.getLTIntegralOut().getTOF(0) + 5000) * Geo::BC_TIME_INPS_INV); // bc taken assuming speed of light (el) and 5 ns of margin + if (bct0 < 0) { // if negative time (it can happen at the beginng of the TF int was truncated per excess... adjusting) + bct0--; + } float tof = matchingPair.getSignal() - bct0 * Geo::BC_TIME_INPS; if (abs(tof - matchingPair.getLTIntegralOut().getTOF(2)) < 600) { } else if (abs(tof - matchingPair.getLTIntegralOut().getTOF(3)) < 600) { @@ -701,6 +704,11 @@ void MatchTOF::addTPCSeed(const o2::tpc::TrackTPC& _tr, o2::dataformats::GlobalT o2::track::TrackLTIntegral intLT0; // mTPCTracksWork.back().getLTIntegralOut(); // we get the integrated length from TPC-ITC outward propagation // compute track length up to now mLTinfos[sector][trkType::UNCONS].emplace_back(intLT0); + float vz0 = _tr.getZAt(0, mBz); + if (abs(vz0) > 9000) { + vz0 = _tr.getZ() - _tr.getX() * _tr.getTgl(); + } + mVZtpcOnly[sector].push_back(vz0); /* const auto& trackTune = TrackTuneParams::Instance(); @@ -841,6 +849,8 @@ void MatchTOF::doMatching(int sec) // Printf("intLT (before doing anything): length = %f, time (Pion) = %f", intLT.getL(), intLT.getTOF(o2::track::PID::Pion)); float minTrkTime = (trackWork.second.getTimeStamp() - mSigmaTimeCut * trackWork.second.getTimeStampError()) * 1.E6 + timeShift; // minimum time in ps float maxTrkTime = (trackWork.second.getTimeStamp() + mSigmaTimeCut * trackWork.second.getTimeStampError()) * 1.E6 + timeShift + 100E3; // maximum time in ps + 100 ns for slow tracks (beta->0.2) + const float sqrt12inv = 1. / sqrt(12.); + float resT = (trackWork.second.getTimeStampError() + 100E-3) * sqrt12inv; int istep = 1; // number of steps float step = 1.0; // step size in cm @@ -1012,12 +1022,49 @@ void MatchTOF::doMatching(int sec) int eventIdTOF; int sourceIdTOF; for (auto iPropagation = 0; iPropagation < nStripsCrossedInPropagation; iPropagation++) { + int bct0 = int((mTOFClusWork[cacheTOF[itof]].getTime() - trkLTInt[iPropagation].getTOF(0) + 5000) * Geo::BC_TIME_INPS_INV); // bc taken assuming speed of light (el) and 5 ns of margin + if (bct0 < 0) { // if negative time (it can happen at the beginng of the TF int was truncated per excess... adjusting) + bct0--; + } + float tof = mTOFClusWork[cacheTOF[itof]].getTime() - bct0 * Geo::BC_TIME_INPS; + if (tof - trkLTInt[iPropagation].getTOF(6) > 2000) { // reject tracks slower than triton + continue; + } + float cosangle = TMath::Cos(Geo::getAngles(indices[1], indices[2]) * TMath::DegToRad()); + const float errXinvMin = 1. / (mMatchParams->maxResX * mMatchParams->maxResX); + const float errZinvMin = 1. / (mMatchParams->maxResZ * mMatchParams->maxResZ); + float errXinv2 = 1. / (trefTrk.getSigmaY2()); + float errZinv2 = 1. / (trefTrk.getSigmaZ2() * cosangle); // should be valid only at eta=0 + + if (errXinv2 < errXinvMin) { + errXinv2 = errXinvMin; + } + if (errZinv2 < errZinvMin) { + errZinv2 = errZinvMin; + } + LOG(debug) << "TOF Cluster [" << itof << ", " << cacheTOF[itof] << "]: indices = " << indices[0] << ", " << indices[1] << ", " << indices[2] << ", " << indices[3] << ", " << indices[4]; LOG(debug) << "Propagated Track [" << itrk << "]: detId[" << iPropagation << "] = " << detId[iPropagation][0] << ", " << detId[iPropagation][1] << ", " << detId[iPropagation][2] << ", " << detId[iPropagation][3] << ", " << detId[iPropagation][4]; float resX = deltaPos[iPropagation][0] - (indices[4] - detId[iPropagation][4]) * Geo::XPAD + posCorr[0]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster float resZ = deltaPos[iPropagation][2] - (indices[3] - detId[iPropagation][3]) * Geo::ZPAD + posCorr[2]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster float res = TMath::Sqrt(resX * resX + resZ * resZ); + if (resX < -1.25) { // distance from closest border + resX += 1.25; + } else if (resX > 1.25) { + resX -= 1.25; + } else { + resX = 1E-3 / (pt + 1E-3); // high-pt should be favoured + } + + if (resZ < -1.75) { // distance from closest border + resZ += 1.75; + } else if (resZ > 1.75) { + resZ -= 1.75; + } else { + resZ = 1E-3 / (pt + 1E-3); // high-pt should be favoured + } + LOG(debug) << "resX = " << resX << ", resZ = " << resZ << ", res = " << res; if (indices[0] != detId[iPropagation][0]) { continue; @@ -1028,15 +1075,20 @@ void MatchTOF::doMatching(int sec) if (indices[2] != detId[iPropagation][2]) { continue; } - float chi2 = res; // TODO: take into account also the time! + float chi2 = 0.5 * (resX * resX * errXinv2 + resZ * resZ * errZinv2); // TODO: take into account also the time! - if (res < mSpaceTolerance) { // matching ok! + if (res < mSpaceTolerance && chi2 < mMatchParams->maxChi2) { // matching ok! LOG(debug) << "MATCHING FOUND: We have a match! between track " << mTracksSectIndexCache[type][sec][itrk] << " and TOF cluster " << mTOFClusSectIndexCache[indices[0]][itof]; foundCluster = true; // set event indexes (to be checked) int eventIndexTOFCluster = mTOFClusSectIndexCache[indices[0]][itof]; mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[iPropagation], mTrackGid[sec][type][cacheTrk[itrk]], type, (trefTOF.getTime() - (minTrkTime + maxTrkTime - 100E3) * 0.5) * 1E-6, trefTOF.getZ(), resX, resZ); // subracting 100 ns to max track which was artificially added mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setPt(pt); + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResX(sqrt(1. / errXinv2)); + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResZ(sqrt(1. / errZinv2)); + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResT(resT); + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setVz(0.0); // not needed for constrained tracks + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setChannel(mainChannel); } } } @@ -1076,6 +1128,7 @@ void MatchTOF::doMatchingForTPC(int sec) std::vector> trkLTInt; std::vector, 2>> deltaPos; std::vector> nStepsInsideSameStrip; + std::vector> Zshift; LOG(debug) << "Trying to match %d tracks" << cacheTrk.size(); @@ -1097,6 +1150,8 @@ void MatchTOF::doMatchingForTPC(int sec) double minTrkTime = (tpctime - trackWork.second.getTimeStampError()) * 1.E6 + timeShift; // minimum time in ps minTrkTime = int(minTrkTime / BCgranularity) * BCgranularity; // align min to a BC double maxTrkTime = (tpctime + mExtraTPCFwdTime[sec][cacheTrk[itrk]]) * 1.E6 + timeShift; // maximum time in ps + const float sqrt12inv = 1. / sqrt(12.); + float resT = (maxTrkTime - minTrkTime) * sqrt12inv; if (mIsCosmics) { for (double tBC = minTrkTime; tBC < maxTrkTime; tBC += BCgranularity) { @@ -1147,6 +1202,8 @@ void MatchTOF::doMatchingForTPC(int sec) detId.reserve(BCcand.size()); trkLTInt.clear(); trkLTInt.reserve(BCcand.size()); + Zshift.clear(); + Zshift.reserve(BCcand.size()); deltaPos.clear(); deltaPos.reserve(BCcand.size()); nStepsInsideSameStrip.clear(); @@ -1209,6 +1266,8 @@ void MatchTOF::doMatchingForTPC(int sec) posFloat[2] = pos[2]; } + float ZshiftCurrent = posFloat[2] - pos[2]; + Geo::getPadDxDyDz(posFloat, detIdTemp, deltaPosTemp, sec); if (detIdTemp[2] == -1) { @@ -1238,6 +1297,7 @@ void MatchTOF::doMatchingForTPC(int sec) deltaPos[ibc][nStripsCrossedInPropagation[ibc] - 1][2] = deltaPosTemp[2]; trkLTInt[ibc][nStripsCrossedInPropagation[ibc] - 1] = intLT; + Zshift[ibc][nStripsCrossedInPropagation[ibc] - 1] = ZshiftCurrent; // Printf("intLT (after matching to strip %d): length = %f, time (Pion) = %f", nStripsCrossedInPropagation - 1, trkLTInt[nStripsCrossedInPropagation - 1].getL(), trkLTInt[nStripsCrossedInPropagation - 1].getTOF(o2::track::PID::Pion)); nStepsInsideSameStrip[ibc][nStripsCrossedInPropagation[ibc] - 1]++; } else { // a further propagation step in the same strip -> update info (we sum up on all matching with strip - we will divide for the number of steps a bit below) @@ -1338,6 +1398,37 @@ void MatchTOF::doMatchingForTPC(int sec) continue; } + int bct0 = int((mTOFClusWork[cacheTOF[itof]].getTime() - trkLTInt[ibc][iPropagation].getTOF(0) + 5000) * Geo::BC_TIME_INPS_INV); // bc taken assuming speed of light (el) and 5 ns of margin + if (bct0 < 0) { // if negative time (it can happen at the beginng of the TF int was truncated per excess... adjusting) + bct0--; + } + float tof = mTOFClusWork[cacheTOF[itof]].getTime() - bct0 * Geo::BC_TIME_INPS; + if (tof - trkLTInt[ibc][iPropagation].getTOF(6) > 2000) { // reject tracks slower than triton + continue; + } + + if (mMatchParams->applyPIDcutTPConly) { // for TPC only tracks allowing possibility to apply a PID cut + if (abs(tof - trkLTInt[ibc][iPropagation].getTOF(2)) < 2000) { // pion hypotesis + } else if (abs(tof - trkLTInt[ibc][iPropagation].getTOF(3)) < 2000) { // kaon hypoteis + } else if (abs(tof - trkLTInt[ibc][iPropagation].getTOF(4)) < 2000) { // proton hypotesis + } else { // reject matching + continue; + } + } + + float cosangle = TMath::Cos(Geo::getAngles(indices[1], indices[2]) * TMath::DegToRad()); + const float errXinvMin = 1. / (mMatchParams->maxResX * mMatchParams->maxResX); + const float errZinvMin = 1. / (mMatchParams->maxResZ * mMatchParams->maxResZ); + float errXinv2 = 1. / (trefTrk.getSigmaY2()); + float errZinv2 = 1. / (trefTrk.getSigmaZ2() * cosangle); // should be valid only at eta=0 + + if (errXinv2 < errXinvMin) { + errXinv2 = errXinvMin; + } + if (errZinv2 < errZinvMin) { + errZinv2 = errZinvMin; + } + LOG(debug) << "TOF Cluster [" << itof << ", " << cacheTOF[itof] << "]: indices = " << indices[0] << ", " << indices[1] << ", " << indices[2] << ", " << indices[3] << ", " << indices[4]; LOG(debug) << "Propagated Track [" << itrk << "]: detId[" << iPropagation << "] = " << detId[ibc][iPropagation][0] << ", " << detId[ibc][iPropagation][1] << ", " << detId[ibc][iPropagation][2] << ", " << detId[ibc][iPropagation][3] << ", " << detId[ibc][iPropagation][4]; float resX = deltaPos[ibc][iPropagation][0] - (indices[4] - detId[ibc][iPropagation][4]) * Geo::XPAD + posCorr[0]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster @@ -1349,6 +1440,22 @@ void MatchTOF::doMatchingForTPC(int sec) } float res = TMath::Sqrt(resX * resX + resZ * resZ); + if (resX < -1.25) { // distance from closest border + resX += 1.25; + } else if (resX > 1.25) { + resX -= 1.25; + } else { + resX = 1E-3 / (pt + 1E-3); // high-pt should be favoured + } + + if (resZ < -1.75) { // distance from closest border + resZ += 1.75; + } else if (resZ > 1.75) { + resZ -= 1.75; + } else { + resZ = 1E-3 / (pt + 1E-3); // high-pt should be favoured + } + if (indices[0] != detId[ibc][iPropagation][0]) { continue; } @@ -1360,15 +1467,21 @@ void MatchTOF::doMatchingForTPC(int sec) } LOG(debug) << "resX = " << resX << ", resZ = " << resZ << ", res = " << res; - float chi2 = mIsCosmics ? resX : res; // TODO: take into account also the time! + float chi2 = mIsCosmics ? resX : 0.5 * (resX * resX * errXinv2 + resZ * resZ * errZinv2); // TODO: take into account also the time! - if (res < mSpaceTolerance) { // matching ok! + if (res < mSpaceTolerance && chi2 < mMatchParams->maxChi2) { // matching ok! LOG(debug) << "MATCHING FOUND: We have a match! between track " << mTracksSectIndexCache[trkType::UNCONS][sec][itrk] << " and TOF cluster " << mTOFClusSectIndexCache[indices[0]][itof]; foundCluster = true; // set event indexes (to be checked) + int eventIndexTOFCluster = mTOFClusSectIndexCache[indices[0]][itof]; mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[ibc][iPropagation], mTrackGid[sec][trkType::UNCONS][cacheTrk[itrk]], trkType::UNCONS, trefTOF.getTime() * 1E-6 - tpctime, trefTOF.getZ(), resX, resZ); // TODO: check if this is correct! mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setPt(pt); + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResX(sqrt(1. / errXinv2)); + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResZ(sqrt(1. / errZinv2)); + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResT(resT); + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setVz(mVZtpcOnly[sec][itrk] + Zshift[ibc][iPropagation]); + mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setChannel(mainChannel); } } } @@ -1443,15 +1556,6 @@ void MatchTOF::BestMatches(std::vector& match int itrk = matchingPair.getIdLocal(); - if (matchedTracksIndex[trkType][itrk] != -1) { // the track was already filled - continue; - } - if (matchedClustersIndex[matchingPair.getTOFClIndex()] != -1) { // the cluster was already filled - continue; - } - matchedTracksIndex[trkType][itrk] = matchedTracks[trkType].size(); // index of the MatchInfoTOF correspoding to this track - matchedClustersIndex[matchingPair.getTOFClIndex()] = matchedTracksIndex[trkType][itrk]; // index of the track that was matched to this cluster - int trkTypeSplitted = trkType; auto sourceID = matchingPair.getTrackRef().getSource(); if (sourceID == o2::dataformats::GlobalTrackID::TPCTRD) { @@ -1459,6 +1563,48 @@ void MatchTOF::BestMatches(std::vector& match } else if (sourceID == o2::dataformats::GlobalTrackID::ITSTPCTRD) { trkTypeSplitted = (int)trkType::ITSTPCTRD; } + + if (matchedClustersIndex[matchingPair.getTOFClIndex()] != -1) { // the cluster was already filled + continue; + } + if (matchedTracksIndex[trkType][itrk] != -1) { // the track was already filled + if (trkType) { // not applied for unconstrained tracks (trkType == 0) + // let's check if we can use both matching to improve TOF time + int pairInd = matchedTracksIndex[trkType][itrk]; + auto& prevMatching = matchedTracks[trkTypeSplitted][pairInd]; + + if (pairInd >= matchedTracks[trkTypeSplitted].size()) { + LOG(error) << "Pair index out of range when trying to update TOF time. This should not happen"; + continue; + } + + int istripOld = TOFClusWork[prevMatching.getTOFClIndex()].getMainContributingChannel() / o2::tof::Geo::NPADS; + int istripNew = TOFClusWork[matchingPair.getTOFClIndex()].getMainContributingChannel() / o2::tof::Geo::NPADS; + + if (istripOld != istripNew) { // we accept it only if in a different strip + const o2::track::TrackLTIntegral& intLTnew = matchingPair.getLTIntegralOut(); + const o2::track::TrackLTIntegral& intLTold = prevMatching.getLTIntegralOut(); + + const float cinv = 1.E+10 / TMath::C(); // cm/ps + float deltaT = (intLTnew.getL() - intLTold.getL()) * cinv; + + float timeNew = TOFClusWork[matchingPair.getTOFClIndex()].getTime() - deltaT; + float timeOld = TOFClusWork[prevMatching.getTOFClIndex()].getTime(); + + if (fabs(timeNew - timeOld) < 200) { + // update time information averaging the two (the second one corrected for the difference in the track length) + prevMatching.setSignal((timeNew + timeOld) * 0.5); + prevMatching.setChi2(0); // flag such cases with chi2 equal to zero + matchedClustersIndex[matchingPair.getTOFClIndex()] = matchedTracksIndex[trkType][itrk]; // flag also the second cluster as already used + } + } + } + + continue; + } + matchedTracksIndex[trkType][itrk] = matchedTracks[trkTypeSplitted].size(); // index of the MatchInfoTOF correspoding to this track + matchedClustersIndex[matchingPair.getTOFClIndex()] = matchedTracksIndex[trkType][itrk]; // index of the track that was matched to this cluster + matchedTracks[trkTypeSplitted].push_back(matchingPair); // array of MatchInfoTOF // get fit info From e95263359963f96ce97c35f0e9fbc6c8276983a4 Mon Sep 17 00:00:00 2001 From: noferini <9963644+noferini@users.noreply.github.com> Date: Tue, 14 May 2024 14:11:59 +0200 Subject: [PATCH 0239/2997] reading TOF time from matchInfo instead of clusters --- .../RecoContainerCreateTracksVariadic.h | 14 +++++++------- .../Detectors/GlobalTracking/src/RecoContainer.cxx | 12 ++++++------ Detectors/GlobalTracking/src/MatchTOF.cxx | 8 ++++++-- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h b/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h index 4cec730c620a5..ecce5a4d58b2f 100644 --- a/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h +++ b/DataFormats/Detectors/GlobalTracking/include/DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h @@ -150,8 +150,8 @@ void o2::globaltracking::RecoContainer::createTracksVariadic(T creator, GTrackID const auto& match = matchesITSTPCTRDTOF[i]; auto gidx = match.getTrackRef(); // this should be corresponding ITS-TPC-TRD track // no need to check isUsed: by construction this ITS-TPC-TRD was not used elsewhere - const auto& tofCl = tofClusters[match.getTOFClIndex()]; - float timeTOFMUS = (tofCl.getTime() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF + // const auto& tofCl = tofClusters[match.getTOFClIndex()]; + float timeTOFMUS = (match.getSignal() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF const float timeErr = 0.010f; // assume 10 ns error FIXME if (creator(tracksITSTPCTRD[gidx.getIndex()], {i, currentSource}, timeTOFMUS, timeErr)) { flagUsed(gidx); // flag used ITS-TPC-TRD tracks @@ -170,9 +170,9 @@ void o2::globaltracking::RecoContainer::createTracksVariadic(T creator, GTrackID } for (unsigned i = 0; i < matchesTPCTRDTOF.size(); i++) { const auto& match = matchesTPCTRDTOF[i]; - auto gidx = match.getTrackRef(); // this should be corresponding TPC-TRD track - const auto& tofCl = tofClusters[match.getTOFClIndex()]; - float timeTOFMUS = (tofCl.getTime() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF + auto gidx = match.getTrackRef(); // this should be corresponding TPC-TRD track + // const auto& tofCl = tofClusters[match.getTOFClIndex()]; + float timeTOFMUS = (match.getSignal() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF const float timeErr = 0.010f; // assume 10 ns error FIXME if (creator(tracksTPCTRD[gidx.getIndex()], {i, currentSource}, timeTOFMUS, timeErr)) { flagUsed(gidx); // flag used TPC-TRD tracks @@ -223,8 +223,8 @@ void o2::globaltracking::RecoContainer::createTracksVariadic(T creator, GTrackID continue; } // no need to check isUsed: by construction this ITS-TPC was not used elsewhere - const auto& tofCl = tofClusters[match.getTOFClIndex()]; - float timeTOFMUS = (tofCl.getTime() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF + // const auto& tofCl = tofClusters[match.getTOFClIndex()]; + float timeTOFMUS = (match.getSignal() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF const float timeErr = 0.010f; // assume 10 ns error FIXME if (creator(tracksTPCITS[gidx.getIndex()], {i, currentSource}, timeTOFMUS, timeErr)) { flagUsed(gidx); // flag used ITS-TPC tracks diff --git a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx index 4e6991125c5e8..0a24277921ce6 100644 --- a/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx +++ b/DataFormats/Detectors/GlobalTracking/src/RecoContainer.cxx @@ -1491,8 +1491,8 @@ void RecoContainer::getTrackTimeITSTPCTRDTOF(GTrackID gid, float& t, float& tErr { const auto& match = getITSTPCTRDTOFMatches()[gid]; auto gidx = match.getTrackRef(); // this should be corresponding ITS-TPC-TRD track - const auto& tofCl = getTOFClusters()[match.getTOFClIndex()]; - t = (tofCl.getTime() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF + // const auto& tofCl = getTOFClusters()[match.getTOFClIndex()]; + t = (match.getSignal() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF tErr = 0.010f; } @@ -1501,8 +1501,8 @@ void RecoContainer::getTrackTimeTPCTRDTOF(GTrackID gid, float& t, float& tErr) c { const auto& match = getTPCTRDTOFMatches()[gid]; auto gidx = match.getTrackRef(); // this should be corresponding ITS-TPC-TRD track - const auto& tofCl = getTOFClusters()[match.getTOFClIndex()]; - t = (tofCl.getTime() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF + // const auto& tofCl = getTOFClusters()[match.getTOFClIndex()]; + t = (match.getSignal() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF tErr = 0.010f; } @@ -1511,8 +1511,8 @@ void RecoContainer::getTrackTimeITSTPCTOF(GTrackID gid, float& t, float& tErr) c { const auto& match = getITSTPCTOFMatches()[gid]; auto gidx = match.getTrackRef(); // this should be corresponding ITS-TPC track - const auto& tofCl = getTOFClusters()[match.getTOFClIndex()]; - t = (tofCl.getTime() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF + // const auto& tofCl = getTOFClusters()[match.getTOFClIndex()]; + t = (match.getSignal() - match.getLTIntegralOut().getTOF(o2::track::PID::Pion)) * PS2MUS; // tof time in \mus, FIXME: account for time of flight to R TOF tErr = 0.010f; } diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 8e66905a91b93..d67708608df55 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -1047,6 +1047,8 @@ void MatchTOF::doMatching(int sec) LOG(debug) << "Propagated Track [" << itrk << "]: detId[" << iPropagation << "] = " << detId[iPropagation][0] << ", " << detId[iPropagation][1] << ", " << detId[iPropagation][2] << ", " << detId[iPropagation][3] << ", " << detId[iPropagation][4]; float resX = deltaPos[iPropagation][0] - (indices[4] - detId[iPropagation][4]) * Geo::XPAD + posCorr[0]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster float resZ = deltaPos[iPropagation][2] - (indices[3] - detId[iPropagation][3]) * Geo::ZPAD + posCorr[2]; // readjusting the residuals due to the fact that the propagation fell in a pad that was not exactly the one of the cluster + float resXor = resX; + float resZor = resZ; float res = TMath::Sqrt(resX * resX + resZ * resZ); if (resX < -1.25) { // distance from closest border @@ -1082,7 +1084,7 @@ void MatchTOF::doMatching(int sec) foundCluster = true; // set event indexes (to be checked) int eventIndexTOFCluster = mTOFClusSectIndexCache[indices[0]][itof]; - mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[iPropagation], mTrackGid[sec][type][cacheTrk[itrk]], type, (trefTOF.getTime() - (minTrkTime + maxTrkTime - 100E3) * 0.5) * 1E-6, trefTOF.getZ(), resX, resZ); // subracting 100 ns to max track which was artificially added + mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[iPropagation], mTrackGid[sec][type][cacheTrk[itrk]], type, (trefTOF.getTime() - (minTrkTime + maxTrkTime - 100E3) * 0.5) * 1E-6, trefTOF.getZ(), resXor, resZor); // subracting 100 ns to max track which was artificially added mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setPt(pt); mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResX(sqrt(1. / errXinv2)); mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResZ(sqrt(1. / errZinv2)); @@ -1438,6 +1440,8 @@ void MatchTOF::doMatchingForTPC(int sec) } else { resZ -= (bcClus - BCcand[ibc]) * vdriftInBC * side; } + float resXor = resX; + float resZor = resZ; float res = TMath::Sqrt(resX * resX + resZ * resZ); if (resX < -1.25) { // distance from closest border @@ -1475,7 +1479,7 @@ void MatchTOF::doMatchingForTPC(int sec) // set event indexes (to be checked) int eventIndexTOFCluster = mTOFClusSectIndexCache[indices[0]][itof]; - mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[ibc][iPropagation], mTrackGid[sec][trkType::UNCONS][cacheTrk[itrk]], trkType::UNCONS, trefTOF.getTime() * 1E-6 - tpctime, trefTOF.getZ(), resX, resZ); // TODO: check if this is correct! + mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[ibc][iPropagation], mTrackGid[sec][trkType::UNCONS][cacheTrk[itrk]], trkType::UNCONS, trefTOF.getTime() * 1E-6 - tpctime, trefTOF.getZ(), resXor, resZor); // TODO: check if this is correct! mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setPt(pt); mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResX(sqrt(1. / errXinv2)); mMatchedTracksPairsSec[sec][mMatchedTracksPairsSec[sec].size() - 1].setResZ(sqrt(1. / errZinv2)); From a264cccd9f64fc8cc3819e1fc09a025d5a310410 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 20 May 2024 17:26:18 +0200 Subject: [PATCH 0240/2997] add lane ID to debug file name if more than 1 lanes --- .../GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx | 4 ++++ .../GlobalTrackingWorkflow/study/src/TrackingStudy.cxx | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx index 0dc20811087ae..228ec4ae052c4 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TPCITSMatchingSpec.cxx @@ -21,6 +21,7 @@ #include "Framework/Task.h" #include "Framework/DataRefUtils.h" #include "Framework/CCDBParamSpec.h" +#include "Framework/DeviceSpec.h" #include #include "TStopwatch.h" #include "Framework/ConfigParamRegistry.h" @@ -94,6 +95,9 @@ void TPCITSMatchingDPL::init(InitContext& ic) { mTimer.Stop(); mTimer.Reset(); + int lane = ic.services().get().inputTimesliceId; + int maxLanes = ic.services().get().maxInputTimeslices; + mMatching.setDebugTreeFileName(maxLanes == 1 ? "dbg_TPCITSmatch.root" : fmt::format("dbg_TPCITSmatch_{}.root", lane)); o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); mMatching.setNThreads(std::max(1, ic.options().get("nthreads"))); mMatching.setUseBCFilling(!ic.options().get("ignore-bc-check")); diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx index a5b6d48810e4e..fd90475a4c670 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx @@ -26,6 +26,7 @@ #include "DataFormatsFT0/RecPoints.h" #include "Framework/ConfigParamRegistry.h" #include "Framework/CCDBParamSpec.h" +#include "Framework/DeviceSpec.h" #include "FT0Reconstruction/InteractionTag.h" #include "ITSMFTBase/DPLAlpideParam.h" #include "DetectorsCommonDataFormats/DetID.h" @@ -118,8 +119,12 @@ void TrackingStudySpec::init(InitContext& ic) { o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); mTPCCorrMapsLoader.init(ic); - mDBGOut = std::make_unique("trackStudy.root", "recreate"); - mDBGOutVtx = std::make_unique("trackStudyVtx.root", "recreate"); + int lane = ic.services().get().inputTimesliceId; + int maxLanes = ic.services().get().maxInputTimeslices; + std::string dbgnm = maxLanes == 1 ? "trackStudy.root" : fmt::format("trackStudy_{}.root", lane); + mDBGOut = std::make_unique(dbgnm.c_str(), "recreate"); + dbgnm = maxLanes == 1 ? "trackStudyVtx.root" : fmt::format("trackStudyVtx_{}.root", lane); + mDBGOutVtx = std::make_unique(dbgnm.c_str(), "recreate"); mStoreWithITSOnly = ic.options().get("with-its-only"); mMaxVTTimeDiff = ic.options().get("max-vtx-timediff"); mMaxNeighbours = ic.options().get("max-vtx-neighbours"); From c0c56f721ce85d7f680b4f126ae025ee342549e4 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 21 May 2024 00:20:59 +0200 Subject: [PATCH 0241/2997] extend alignment dump with more points on the sensor --- Detectors/Align/macro/algDump.C | 2 +- Detectors/Align/src/AlignLinkDef.h | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Detectors/Align/macro/algDump.C b/Detectors/Align/macro/algDump.C index 865f8a0bbf6a0..2d1dfcbaaa0de 100644 --- a/Detectors/Align/macro/algDump.C +++ b/Detectors/Align/macro/algDump.C @@ -40,7 +40,7 @@ void algDump(const std::string& geom = "", const std::string& outname = "algdump auto store = [&outstream, &det, &pos, &pos0](int lr, int sid, int sidLr) { outstream << "gm" << "det=" << det.getID() << "lr=" << lr << "sid=" << sid << "sidlr=" << sidLr << "pos0=" << pos0 << "pos=" << pos << "\n"; - // printf("xx %d %d %d %f %f %f\n", det.getID(), lr, sid, pos0[0], pos0[1], pos0[1]); + printf("xx %d %d %d %f %f %f\n", det.getID(), lr, sid, pos0[0], pos0[1], pos0[1]); }; det = DetID("ITS"); diff --git a/Detectors/Align/src/AlignLinkDef.h b/Detectors/Align/src/AlignLinkDef.h index 2952c46ec821d..66f3220d720ca 100644 --- a/Detectors/Align/src/AlignLinkDef.h +++ b/Detectors/Align/src/AlignLinkDef.h @@ -8,7 +8,6 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. - #ifdef __CLING__ #pragma link off all globals; @@ -21,7 +20,7 @@ #pragma link C++ class o2::align::AlignableDetectorTOF + ; #pragma link C++ class o2::align::AlignableDetectorTPC + ; #pragma link C++ class o2::align::AlignableDetectorTRD + ; -//#pragma link C++ class o2::align::AlignableDetectorHMPID + ; +// #pragma link C++ class o2::align::AlignableDetectorHMPID + ; #pragma link C++ class o2::align::Millepede2Record + ; #pragma link C++ class o2::align::AlignmentPoint + ; #pragma link C++ class o2::align::AlignableSensor + ; @@ -29,7 +28,7 @@ #pragma link C++ class o2::align::AlignableSensorTOF + ; #pragma link C++ class o2::align::AlignableSensorTPC + ; #pragma link C++ class o2::align::AlignableSensorTRD + ; -//#pragma link C++ class o2::align::AlignableSensorHMPID + ; +// #pragma link C++ class o2::align::AlignableSensorHMPID + ; #pragma link C++ class o2::align::Controller + ; #pragma link C++ class o2::align::AlignmentTrack + ; #pragma link C++ class o2::align::AlignableVolume + ; @@ -48,4 +47,7 @@ #pragma link C++ class std::vector < o2::track::TrackParametrization < double>> + ; +#include "TVector3.h" +#pragma link C++ class std::vector < TVector3> + ; + #endif From 189812f4170aabc2e7f779f3a1a42e57c5dad03a Mon Sep 17 00:00:00 2001 From: sevdokim Date: Mon, 13 May 2024 18:49:21 +0200 Subject: [PATCH 0242/2997] PHS: fix segfault when reading TRU flags in AltroDecoder.cxx --- Detectors/PHOS/reconstruction/src/AltroDecoder.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx index 7202b27325c0e..6471a824d344e 100644 --- a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx +++ b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx @@ -312,6 +312,11 @@ void AltroDecoder::readTRUFlags(short hwAddress, int payloadSize) return; } int timeBin = mBunchwords[currentsample + 1] + 1; // +1 for further convenience + if (timeBin > 128) { // corrupted sample: add error and ignore the reast of bunchwords + // 1: wrong TRU header + mOutputHWErrors.emplace_back(mddl, kGeneralTRUErr, static_cast(2)); // PAYLOAD_DECODING + return; + } int istart = currentsample + 2; int iend = istart + std::min(bunchlength, static_cast(mBunchwords.size()) - currentsample - 2); currentsample += bunchlength + 2; From fba58dba589e57e8255a00c36f854143d07fa59d Mon Sep 17 00:00:00 2001 From: pillot Date: Thu, 2 May 2024 17:04:10 +0200 Subject: [PATCH 0243/2997] add StatusMap IO and a converter to RejectList --- Detectors/MUON/MCH/IO/CMakeLists.txt | 16 ++ Detectors/MUON/MCH/IO/README.md | 20 ++ .../MUON/MCH/IO/src/StatusMapReaderSpec.cxx | 70 ++++++ .../MUON/MCH/IO/src/StatusMapReaderSpec.h | 22 ++ .../MUON/MCH/IO/src/StatusMapWriterSpec.cxx | 33 +++ .../MUON/MCH/IO/src/StatusMapWriterSpec.h | 22 ++ .../MCH/IO/src/statusmaps-reader-workflow.cxx | 38 +++ .../MCH/IO/src/statusmaps-writer-workflow.cxx | 29 +++ Detectors/MUON/MCH/Status/CMakeLists.txt | 13 + .../Status/src/statusmap-to-rejectlist.cxx | 225 ++++++++++++++++++ 10 files changed, 488 insertions(+) create mode 100644 Detectors/MUON/MCH/IO/src/StatusMapReaderSpec.cxx create mode 100644 Detectors/MUON/MCH/IO/src/StatusMapReaderSpec.h create mode 100644 Detectors/MUON/MCH/IO/src/StatusMapWriterSpec.cxx create mode 100644 Detectors/MUON/MCH/IO/src/StatusMapWriterSpec.h create mode 100644 Detectors/MUON/MCH/IO/src/statusmaps-reader-workflow.cxx create mode 100644 Detectors/MUON/MCH/IO/src/statusmaps-writer-workflow.cxx create mode 100644 Detectors/MUON/MCH/Status/src/statusmap-to-rejectlist.cxx diff --git a/Detectors/MUON/MCH/IO/CMakeLists.txt b/Detectors/MUON/MCH/IO/CMakeLists.txt index e609e6edbb002..18a8630a7fed0 100644 --- a/Detectors/MUON/MCH/IO/CMakeLists.txt +++ b/Detectors/MUON/MCH/IO/CMakeLists.txt @@ -97,3 +97,19 @@ o2_add_executable(tracks-writer-workflow COMPONENT_NAME mch PUBLIC_LINK_LIBRARIES O2::MCHIO) +o2_add_executable(statusmaps-reader-workflow + SOURCES src/StatusMapReaderSpec.cxx src/statusmaps-reader-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES + O2::DPLUtils + O2::DetectorsRaw + O2::MCHStatus + ) + +o2_add_executable(statusmaps-writer-workflow + SOURCES src/StatusMapWriterSpec.cxx src/statusmaps-writer-workflow.cxx + COMPONENT_NAME mch + PUBLIC_LINK_LIBRARIES + O2::DPLUtils + O2::MCHStatus + ) diff --git a/Detectors/MUON/MCH/IO/README.md b/Detectors/MUON/MCH/IO/README.md index 94409b658bf11..4924840ac1d2c 100644 --- a/Detectors/MUON/MCH/IO/README.md +++ b/Detectors/MUON/MCH/IO/README.md @@ -14,6 +14,8 @@ * [Cluster writer](#cluster-writer) * [Track reader](#track-reader) * [Track writer](#track-writer) +* [StatusMap reader](#statusmap-reader) +* [StatusMap writer](#statusmap-writer) @@ -126,3 +128,21 @@ Option `--digits` allows to also write the associated digits ([Digit](/DataForma Option `--enable-mc` allows to also write the track MC labels from the input message with the data description "TRACKLABELS". +## StatusMap reader + +```shell +o2-mch-statusmaps-reader-workflow --infile mchstatusmaps.root +``` + +Send the status map ([StatusMap](../Status/include/MCHStatus/StatusMap.h)) of the current time frame, with the data description "STATUSMAP". + +Option `--input-dir` allows to set the name of the directory containing the input file (default = current directory). + +## StatusMap writer + +```shell +o2-mch-statusmaps-writer-workflow +``` + +Take as input the status map ([StatusMap](../Status/include/MCHStatus/StatusMap.h)) of the current time frame, with the data description "STATUSMAP", and write it in the root file "mchstatusmaps.root". + diff --git a/Detectors/MUON/MCH/IO/src/StatusMapReaderSpec.cxx b/Detectors/MUON/MCH/IO/src/StatusMapReaderSpec.cxx new file mode 100644 index 0000000000000..351a5a3c36511 --- /dev/null +++ b/Detectors/MUON/MCH/IO/src/StatusMapReaderSpec.cxx @@ -0,0 +1,70 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "StatusMapReaderSpec.h" + +#include +#include + +#include "Framework/ConfigParamRegistry.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/ControlService.h" +#include "Framework/InitContext.h" +#include "Framework/Lifetime.h" +#include "Framework/OutputSpec.h" +#include "Framework/ProcessingContext.h" +#include "Framework/Task.h" + +#include "DPLUtils/RootTreeReader.h" +#include "CommonUtils/StringUtils.h" +#include "MCHStatus/StatusMap.h" + +using namespace o2::framework; + +namespace o2::mch +{ + +struct StatusMapReader { + std::unique_ptr mTreeReader; + + void init(InitContext& ic) + { + auto fileName = o2::utils::Str::concat_string(o2::utils::Str::rectifyDirectory(ic.options().get("input-dir")), ic.options().get("infile")); + mTreeReader = std::make_unique( + "o2sim", + fileName.c_str(), + -1, + RootTreeReader::PublishingMode::Single, + RootTreeReader::BranchDefinition{Output{"MCH", "STATUSMAP", 0}, "statusmaps"}); + } + + void run(ProcessingContext& pc) + { + if (mTreeReader->next()) { + (*mTreeReader)(pc); + } else { + pc.services().get().endOfStream(); + } + } +}; + +DataProcessorSpec getStatusMapReaderSpec(const char* specName) +{ + return DataProcessorSpec{ + specName, + Inputs{}, + Outputs{OutputSpec{{"statusmaps"}, "MCH", "STATUSMAP", 0, Lifetime::Timeframe}}, + adaptFromTask(), + Options{{"infile", VariantType::String, "mchstatusmaps.root", {"name of the input status map file"}}, + {"input-dir", VariantType::String, "none", {"Input directory"}}}}; +} + +} // namespace o2::mch diff --git a/Detectors/MUON/MCH/IO/src/StatusMapReaderSpec.h b/Detectors/MUON/MCH/IO/src/StatusMapReaderSpec.h new file mode 100644 index 0000000000000..1742d0a84be68 --- /dev/null +++ b/Detectors/MUON/MCH/IO/src/StatusMapReaderSpec.h @@ -0,0 +1,22 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_MCH_WORKFLOW_STATUSMAP_READER_SPEC_H +#define O2_MCH_WORKFLOW_STATUSMAP_READER_SPEC_H + +#include "Framework/DataProcessorSpec.h" + +namespace o2::mch +{ +framework::DataProcessorSpec getStatusMapReaderSpec(const char* specName = "mch-statusmap-reader"); +} + +#endif diff --git a/Detectors/MUON/MCH/IO/src/StatusMapWriterSpec.cxx b/Detectors/MUON/MCH/IO/src/StatusMapWriterSpec.cxx new file mode 100644 index 0000000000000..04e2bd973c9fa --- /dev/null +++ b/Detectors/MUON/MCH/IO/src/StatusMapWriterSpec.cxx @@ -0,0 +1,33 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "StatusMapWriterSpec.h" + +#include "DPLUtils/MakeRootTreeWriterSpec.h" +#include "MCHStatus/StatusMap.h" + +using namespace o2::framework; + +namespace o2::mch +{ + +template +using BranchDefinition = MakeRootTreeWriterSpec::BranchDefinition; + +DataProcessorSpec getStatusMapWriterSpec(const char* specName) +{ + return MakeRootTreeWriterSpec(specName, + "mchstatusmaps.root", + MakeRootTreeWriterSpec::TreeAttributes{"o2sim", "Tree MCH StatusMaps"}, + BranchDefinition{InputSpec{"statusmaps", "MCH", "STATUSMAP"}, "statusmaps"})(); +} + +} // namespace o2::mch diff --git a/Detectors/MUON/MCH/IO/src/StatusMapWriterSpec.h b/Detectors/MUON/MCH/IO/src/StatusMapWriterSpec.h new file mode 100644 index 0000000000000..6386d8b5c8817 --- /dev/null +++ b/Detectors/MUON/MCH/IO/src/StatusMapWriterSpec.h @@ -0,0 +1,22 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_MCH_WORKFLOW_STATUSMAP_WRITER_SPEC_H +#define O2_MCH_WORKFLOW_STATUSMAP_WRITER_SPEC_H + +#include "Framework/DataProcessorSpec.h" + +namespace o2::mch +{ +framework::DataProcessorSpec getStatusMapWriterSpec(const char* specName = "mch-statusmap-writer"); +} + +#endif diff --git a/Detectors/MUON/MCH/IO/src/statusmaps-reader-workflow.cxx b/Detectors/MUON/MCH/IO/src/statusmaps-reader-workflow.cxx new file mode 100644 index 0000000000000..2edaf3534463e --- /dev/null +++ b/Detectors/MUON/MCH/IO/src/statusmaps-reader-workflow.cxx @@ -0,0 +1,38 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include "DetectorsRaw/HBFUtilsInitializer.h" +#include "Framework/CallbacksPolicy.h" +#include "Framework/ConfigParamSpec.h" +#include "StatusMapReaderSpec.h" + +using namespace o2::framework; + +void customize(std::vector& policies) +{ + o2::raw::HBFUtilsInitializer::addNewTimeSliceCallback(policies); +} + +// we need to add workflow options before including Framework/runDataProcessing +void customize(std::vector& workflowOptions) +{ + o2::raw::HBFUtilsInitializer::addConfigOption(workflowOptions); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(const ConfigContext& config) +{ + WorkflowSpec wf{o2::mch::getStatusMapReaderSpec("mch-statusmap-reader")}; + o2::raw::HBFUtilsInitializer hbfIni(config, wf); + return wf; +} diff --git a/Detectors/MUON/MCH/IO/src/statusmaps-writer-workflow.cxx b/Detectors/MUON/MCH/IO/src/statusmaps-writer-workflow.cxx new file mode 100644 index 0000000000000..f07a8b14ee3d2 --- /dev/null +++ b/Detectors/MUON/MCH/IO/src/statusmaps-writer-workflow.cxx @@ -0,0 +1,29 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include "Framework/CompletionPolicyHelpers.h" +#include "StatusMapWriterSpec.h" + +using namespace o2::framework; + +void customize(std::vector& policies) +{ + // ordered policies for the writers + policies.push_back(CompletionPolicyHelpers::consumeWhenAllOrdered(".*(?:MCH|mch).*[W,w]riter.*")); +} + +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(const ConfigContext&) +{ + return WorkflowSpec{o2::mch::getStatusMapWriterSpec("mch-statusmap-writer")}; +} diff --git a/Detectors/MUON/MCH/Status/CMakeLists.txt b/Detectors/MUON/MCH/Status/CMakeLists.txt index b8d54049470c8..949c64f487c39 100644 --- a/Detectors/MUON/MCH/Status/CMakeLists.txt +++ b/Detectors/MUON/MCH/Status/CMakeLists.txt @@ -35,6 +35,19 @@ o2_add_executable( O2::MCHStatus ) +o2_add_executable( + statusmap-to-rejectlist + COMPONENT_NAME mch + SOURCES src/statusmap-to-rejectlist.cxx + PUBLIC_LINK_LIBRARIES + ROOT::TreePlayer + O2::CCDB + O2::DataFormatsMCH + O2::Framework + O2::MCHGlobalMapping + O2::MCHStatus + ) + if(BUILD_TESTING) o2_add_test( diff --git a/Detectors/MUON/MCH/Status/src/statusmap-to-rejectlist.cxx b/Detectors/MUON/MCH/Status/src/statusmap-to-rejectlist.cxx new file mode 100644 index 0000000000000..c50d7022ad1b6 --- /dev/null +++ b/Detectors/MUON/MCH/Status/src/statusmap-to-rejectlist.cxx @@ -0,0 +1,225 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// @author Philippe Pillot + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "CCDB/CcdbApi.h" +#include "DataFormatsMCH/DsChannelId.h" +#include "Framework/Logger.h" +#include "MCHGlobalMapping/ChannelCode.h" +#include "MCHStatus/StatusMap.h" + +namespace po = boost::program_options; + +using BadChannelsVector = std::vector; + +//____________________________________________________________________________________ +std::tuple loadData(const std::string inFile) +{ + /// open the input file and get the intput tree + + TFile* f = TFile::Open(inFile.c_str(), "READ"); + if (!f || f->IsZombie()) { + LOG(error) << "opening file " << inFile << " failed"; + exit(2); + } + + TTreeReader* r = new TTreeReader("o2sim", f); + if (r->IsZombie()) { + LOG(error) << "tree o2sim not found"; + exit(2); + } + + return std::make_tuple(f, r); +} + +//____________________________________________________________________________________ +int size(const std::map>& badChannels) +{ + /// return the total number of bad channels + + int n = 0; + + for (const auto& channels : badChannels) { + n += channels.second.size(); + } + + return n; +}; + +//____________________________________________________________________________________ +void printContent(const std::string inFile, const uint32_t mask) +{ + /// print the content of the status maps with the given mask + + auto [dataFile, dataReader] = loadData(inFile); + TTreeReaderValue statusMap(*dataReader, "statusmaps"); + + int iTF(-1); + int firstTF(-1); + int lastTF(-1); + std::map> currentBadChannels{}; + + while (dataReader->Next()) { + ++iTF; + + // record the first status map + if (firstTF < 0) { + firstTF = iTF; + lastTF = iTF; + currentBadChannels = o2::mch::applyMask(*statusMap, mask); + continue; + } + + auto badChannels = o2::mch::applyMask(*statusMap, mask); + + // extend the TF range of the current status map if it did not change + if (badChannels == currentBadChannels) { + lastTF = iTF; + continue; + } + + // print the current status map + LOGP(info, "TF [{}, {}]: the status map contains {} bad channels in {} detection element{} (using statusMask=0x{:x})", + firstTF, lastTF, size(currentBadChannels), currentBadChannels.size(), currentBadChannels.size() > 1 ? "s" : "", mask); + + // update the current status map + firstTF = iTF; + lastTF = iTF; + currentBadChannels = badChannels; + } + + // print the last status map + LOGP(info, "TF [{}, {}]: the status map contains {} bad channels in {} detection element{} (using statusMask=0x{:x})", + firstTF, lastTF, size(currentBadChannels), currentBadChannels.size(), currentBadChannels.size() > 1 ? "s" : "", mask); + + dataFile->Close(); +} + +//____________________________________________________________________________________ +BadChannelsVector statusMap2RejectList(const std::string inFile, const size_t iTF, const uint32_t mask) +{ + /// convert the status map of the given TF into a reject list with the given mask + + auto [dataFile, dataReader] = loadData(inFile); + TTreeReaderValue statusMap(*dataReader, "statusmaps"); + + if (dataReader->SetEntry(iTF) != TTreeReader::kEntryValid) { + LOGP(error, "invalid TF index {} (number of TFs = {})", iTF, dataReader->GetEntries()); + exit(3); + } + + BadChannelsVector bv; + + for (const auto& status : *statusMap) { + auto channel = status.first; + if (!channel.isValid()) { + LOG(error) << "invalid channel"; + } + if ((mask & status.second) != 0) { + const auto c = o2::mch::DsChannelId(channel.getSolarId(), channel.getElinkId(), channel.getChannel()); + bv.emplace_back(c); + } + } + + dataFile->Close(); + + LOGP(info, "the reject list contains {} bad channels (using statusMask=0x{:x})", bv.size(), mask); + + return bv; +} + +//____________________________________________________________________________________ +void uploadRejectList(const std::string ccdbUrl, uint64_t startTS, uint64_t endTS, const BadChannelsVector& bv) +{ + o2::ccdb::CcdbApi api; + api.init(ccdbUrl); + std::map md; + + LOGP(info, "storing MCH RejectList (valid from {} to {}) to MCH/Calib/RejectList", + startTS, endTS); + + api.storeAsTFileAny(&bv, "MCH/Calib/RejectList", md, startTS, endTS); +} + +//____________________________________________________________________________________ +int main(int argc, char** argv) +{ + po::variables_map vm; + po::options_description usage("Usage"); + + std::string ccdbUrl; + uint64_t startTS; + uint64_t endTS; + std::string inFile; + size_t iTF; + uint32_t mask; + bool print; + + auto tnow = std::chrono::system_clock::now().time_since_epoch(); + using namespace std::chrono_literals; + auto tend = tnow + 24h; + uint64_t now = std::chrono::duration_cast(tnow).count(); + uint64_t end = std::chrono::duration_cast(tend).count(); + + uint32_t defaultMask = o2::mch::StatusMap::kBadPedestal | o2::mch::StatusMap::kRejectList | o2::mch::StatusMap::kBadHV; + + // clang-format off + usage.add_options() + ("help,h", "produce help message") + ("ccdb,c",po::value(&ccdbUrl)->default_value("http://localhost:6464"),"ccdb url") + ("starttimestamp,st",po::value(&startTS)->default_value(now),"timestamp for query or put - (default=now)") + ("endtimestamp,et", po::value(&endTS)->default_value(end), "end of validity (for put) - default=1 day from now") + ("infile,f",po::value(&inFile)->default_value("mchstatusmaps.root"),"input file of StatusMap objects") + ("tf,i", po::value(&iTF)->default_value(0), "index of the TF to process") + ("mask,m", po::value(&mask)->default_value(defaultMask), "mask to apply to the statusMap to produce the RejectList") + ("print,p",po::bool_switch(&print),"print the content of the input file without processing it") + ; + // clang-format on + + po::options_description cmdline; + cmdline.add(usage); + + po::store(po::command_line_parser(argc, argv).options(cmdline).run(), vm); + + if (vm.count("help")) { + LOG(info) << "This program converts a StatusMap to a RejectList CCDB object"; + LOG(info) << usage; + return 2; + } + + try { + po::notify(vm); + } catch (boost::program_options::error& e) { + LOG(error) << e.what(); + exit(1); + } + + if (print) { + printContent(inFile, mask); + } else { + auto bv = statusMap2RejectList(inFile, iTF, mask); + uploadRejectList(ccdbUrl, startTS, endTS, bv); + } + + return 0; +} From 529d890e816de22dd0aa63c37c2562c367d6d80c Mon Sep 17 00:00:00 2001 From: iravasen Date: Tue, 21 May 2024 17:42:30 +0200 Subject: [PATCH 0244/2997] new default ranges for vcasn scan + fix of trivial bug with scurves tree --- .../workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h | 2 +- Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h index 18fd2bda0c4df..d40c8a2cafce6 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h @@ -283,7 +283,7 @@ class ITSThresholdCalibrator : public Task // To set min and max ITHR and VCASN in the tuning scans short int inMinVcasn = 30; - short int inMaxVcasn = 80; + short int inMaxVcasn = 100; short int inMinIthr = 30; short int inMaxIthr = 100; diff --git a/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx index 895e70866e5ba..890a6633732ab 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx @@ -789,7 +789,7 @@ void ITSThresholdCalibrator::extractThresholdRow(const short int& chipID, const } // Fill the ScTree tree - if (mScanType == 'T' || mScanType == 'I' || mScanType == 'V') { // TODO: store also for other scans? + if (mScanType == 'T') { // TODO: store also for other scans? for (int ichg = mMin; ichg <= mMax; ichg++) { for (short int col_i = 0; col_i < this->N_COL; col_i += mColStep) { vCharge[col_i] = ichg; @@ -2023,7 +2023,7 @@ DataProcessorSpec getITSThresholdCalibratorSpec(const ITSCalibInpConf& inpConf) {"enable-single-pix-tag", VariantType::Bool, false, {"Use to enable tagging of single noisy pix in digital and analogue scan"}}, {"ccdb-mgr-url", VariantType::String, "", {"CCDB url to download confDBmap"}}, {"min-vcasn", VariantType::Int, 30, {"Min value of VCASN in vcasn scan, default is 30"}}, - {"max-vcasn", VariantType::Int, 80, {"Max value of VCASN in vcasn scan, default is 80"}}, + {"max-vcasn", VariantType::Int, 100, {"Max value of VCASN in vcasn scan, default is 80"}}, {"min-ithr", VariantType::Int, 30, {"Min value of ITHR in ithr scan, default is 30"}}, {"max-ithr", VariantType::Int, 100, {"Max value of ITHR in ithr scan, default is 100"}}, {"manual-mode", VariantType::Bool, false, {"Flag to activate the manual mode in case run type is not recognized"}}, From e5cca646eb075e401812fbffd7bc719d46054fca Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 21 May 2024 15:15:35 +0200 Subject: [PATCH 0245/2997] FT0: Delete unused variables - fixes a floating point exception in FT0 geometry construction - these variables/assignments were anyway never used later so simply deleting them solves the issue https://its.cern.ch/jira/browse/O2-4426 --- Detectors/FIT/FT0/simulation/src/Detector.cxx | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/Detectors/FIT/FT0/simulation/src/Detector.cxx b/Detectors/FIT/FT0/simulation/src/Detector.cxx index 015b709355f98..ea856eb204802 100644 --- a/Detectors/FIT/FT0/simulation/src/Detector.cxx +++ b/Detectors/FIT/FT0/simulation/src/Detector.cxx @@ -882,18 +882,10 @@ TGeoVolume* Detector::constructFrameCGeometry() Double_t yPMT[NCellsC]; Double_t zPMT[NCellsC]; - Double_t aPMT[NCellsC]; - Double_t bPMT[NCellsC]; - Double_t gPMT[NCellsC]; - Double_t xQrad[NCellsC]; Double_t yQrad[NCellsC]; Double_t zQrad[NCellsC]; - Double_t aQrad[NCellsC]; - Double_t bQrad[NCellsC]; - Double_t gQrad[NCellsC]; - Double_t rotC[NCellsC]; Double_t comC[NCellsC]; @@ -903,31 +895,10 @@ TGeoVolume* Detector::constructFrameCGeometry() yPMT[i] = scalePMT * yc2[i]; zPMT[i] = scalePMT * zc2[i]; - aPMT[i] = TMath::ATan(yPMT[i] / xPMT[i]) - TMath::Pi() / 2 + 2 * TMath::Pi(); - if (xPMT[i] < 0) { - bPMT[i] = TMath::ACos(zPMT[i] / crad); - } else { - bPMT[i] = -1 * TMath::ACos(zPMT[i] / crad); - } - - aPMT[i] *= 180 / TMath::Pi(); - bPMT[i] *= 180 / TMath::Pi(); - gPMT[i] = -1 * aPMT[i]; - // Quartz radiator transformations xQrad[i] = scaleQrad * xc2[i]; yQrad[i] = scaleQrad * yc2[i]; zQrad[i] = scaleQrad * zc2[i]; - - aQrad[i] = TMath::ATan(yQrad[i] / xQrad[i]) - TMath::Pi() / 2 + 2 * TMath::Pi(); - if (xQrad[i] < 0) { - bQrad[i] = TMath::ACos(zQrad[i] / crad); - } else { - bQrad[i] = -1 * TMath::ACos(zQrad[i] / crad); - } - aQrad[i] *= 180 / TMath::Pi(); - bQrad[i] *= 180 / TMath::Pi(); - gQrad[i] = -1 * aQrad[i]; } TString nameRot; From 0635b951e90f4e381da3b121be4d4b461395b367 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Wed, 22 May 2024 17:13:33 +0200 Subject: [PATCH 0246/2997] Update FOCAL CODEOWNERS --- CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 144380ff96161..91af5306f247a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -30,7 +30,7 @@ /DataFormats/Detectors/CTP @lietava /DataFormats/Detectors/EMCAL @mfasDa @jokonig /DataFormats/Detectors/FIT @jotwinow @afurs @andreasmolander @arvindkhuntia @mslupeck -/DataFormats/Detectors/FOCAL @maxrauch @mfasDa +/DataFormats/Detectors/FOCAL @maxrauch @mfasDa @iarsene @matthiasrichter /DataFormats/Detectors/GlobalTracking @shahor02 /DataFormats/Detectors/GlobalTrackingWorkflow @shahor02 /DataFormats/Detectors/HMPID @gvolpe79 @@ -60,7 +60,7 @@ /Detectors/CPV @peressounko @kharlov /Detectors/EMCAL @mfasDa @jokonig /Detectors/FIT @jotwinow @afurs @andreasmolander @arvindkhuntia @mslupeck -/Detectors/FOCAL @maxrauch @mfasDa +/Detectors/FOCAL @maxrauch @mfasDa @iarsene @matthiasrichter /Detectors/Geometry @sawenzel @shahor02 @benedikt-voelkel /Detectors/GlobalTracking @shahor02 /Detectors/GlobalTrackingWorkflow @shahor02 From ca156d966e90195af3fd5a94c88e811b12a4c9ca Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 23 May 2024 10:08:46 +0200 Subject: [PATCH 0247/2997] DPL: avoid memory churn when pushing variable state --- Framework/Core/src/DataRelayer.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index bd0fba7b35e3e..703043477639e 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -260,7 +260,8 @@ void sendVariableContextMetrics(VariableContext& context, TimesliceSlot slot, Da context.publish([](VariableContext const& variables, TimesliceSlot slot, void* context) { auto& states = *static_cast(context); - std::string state = ""; + static std::string state = ""; + state.clear(); for (size_t i = 0; i < MAX_MATCHING_VARIABLE; ++i) { auto var = variables.get(i); if (auto pval = std::get_if(&var)) { From 107fc784663d891c7503e216e4ba33e335b06fb6 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene Date: Fri, 24 May 2024 10:56:37 +0200 Subject: [PATCH 0248/2997] [FOCAL-78, FOCAL-84] First commit for the geometry helper class for the FOCAL detector (#13153) * Porting of the geometry helper for FOCAL-E and FOCAL-H * clang fixes * Implementing comments and CI fixes * clang fixes * some more clang and whitespace fixes * more whitespaces * fix fullCI comments --------- Co-authored-by: Ionut-Cristian Arsene --- Detectors/FOCAL/base/CMakeLists.txt | 8 +- .../base/include/FOCALBase/Composition.h | 77 + .../FOCAL/base/include/FOCALBase/Geometry.h | 237 +++ Detectors/FOCAL/base/src/Composition.cxx | 43 + Detectors/FOCAL/base/src/FOCALBaseLinkDef.h | 2 + Detectors/FOCAL/base/src/Geometry.cxx | 1383 +++++++++++++++++ 6 files changed, 1748 insertions(+), 2 deletions(-) create mode 100644 Detectors/FOCAL/base/include/FOCALBase/Composition.h create mode 100644 Detectors/FOCAL/base/include/FOCALBase/Geometry.h create mode 100644 Detectors/FOCAL/base/src/Composition.cxx create mode 100644 Detectors/FOCAL/base/src/Geometry.cxx diff --git a/Detectors/FOCAL/base/CMakeLists.txt b/Detectors/FOCAL/base/CMakeLists.txt index 6b8bf8e418bd2..3154e7cc2b773 100644 --- a/Detectors/FOCAL/base/CMakeLists.txt +++ b/Detectors/FOCAL/base/CMakeLists.txt @@ -10,13 +10,17 @@ # or submit itself to any jurisdiction. o2_add_library(FOCALBase - SOURCES src/EventReader.cxx + SOURCES src/Composition.cxx + src/EventReader.cxx + src/Geometry.cxx src/TestbeamAnalysis.cxx PUBLIC_LINK_LIBRARIES O2::DataFormatsFOCAL ROOT::RIO ROOT::Tree ROOT::TreePlayer Microsoft.GSL::GSL) o2_target_root_dictionary( FOCALBase - HEADERS include/FOCALBase/EventReader.h + HEADERS include/FOCALBase/Composition.h + include/FOCALBase/EventReader.h + include/FOCALBase/Geometry.h include/FOCALBase/TestbeamAnalysis.h ) \ No newline at end of file diff --git a/Detectors/FOCAL/base/include/FOCALBase/Composition.h b/Detectors/FOCAL/base/include/FOCALBase/Composition.h new file mode 100644 index 0000000000000..7f8b14386a2b4 --- /dev/null +++ b/Detectors/FOCAL/base/include/FOCALBase/Composition.h @@ -0,0 +1,77 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef ALICEO2_FOCAL_COMPOSITION_H_ +#define ALICEO2_FOCAL_COMPOSITION_H_ + +#include + +namespace o2 +{ + +namespace focal +{ + +class Composition +{ + public: + Composition() = default; + Composition(std::string material, int layer, int stack, int id, + float cx, float cy, float cz, float dx, float dy, float dz); + Composition(Composition* comp); + Composition(const Composition& comp) = default; + ~Composition() = default; + + void setCompositionParameters(std::string material, int layer, int stack, int id, + float cx, float cy, float cz, float dx, float dy, float dz) + { + mMaterial = material; + mLayer = layer; + mStack = stack; + mId = id; + mCenterX = cx; + mCenterY = cy; + mCenterZ = cz; + mSizeX = dx; + mSizeY = dy; + mSizeZ = dz; + }; + void setLayerNumber(int layer) { mLayer = layer; } + void setId(int id) { mId = id; } + void setCenterZ(float val) { mCenterZ = val; } + + std::string material() const { return mMaterial; } + int layer() const { return mLayer; } + int stack() const { return mStack; } + int id() const { return mId; } + float centerX() const { return mCenterX; } + float centerY() const { return mCenterY; } + float centerZ() const { return mCenterZ; } + float sizeX() const { return mSizeX; } + float sizeY() const { return mSizeY; } + float sizeZ() const { return mSizeZ; } + float getThickness(void) const { return mSizeZ; } + + private: + std::string mMaterial; + int mLayer = 0; + int mStack = 0; + int mId = 0; + float mCenterX = 0.0; + float mCenterY = 0.0; + float mCenterZ = 0.0; + float mSizeX = 0.0; + float mSizeY = 0.0; + float mSizeZ = 0.0; +}; +} // end namespace focal +} // end namespace o2 +#endif \ No newline at end of file diff --git a/Detectors/FOCAL/base/include/FOCALBase/Geometry.h b/Detectors/FOCAL/base/include/FOCALBase/Geometry.h new file mode 100644 index 0000000000000..be1eb5132f977 --- /dev/null +++ b/Detectors/FOCAL/base/include/FOCALBase/Geometry.h @@ -0,0 +1,237 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef ALICEO2_FOCAL_GEOMETRY_H_ +#define ALICEO2_FOCAL_GEOMETRY_H_ + +#include +#include +#include +#include +#include + +#include "FOCALBase/Composition.h" + +namespace o2 +{ +namespace focal +{ + +class VirtualSegment +{ + + public: + VirtualSegment() + { + } + + VirtualSegment& operator=(const VirtualSegment& segment) + { + if (this != &segment) { + mMinLayer = segment.mMinLayer; + mMaxLayer = segment.mMaxLayer; + mPadSize = segment.mPadSize; + mRelativeSensitiveThickness = segment.mRelativeSensitiveThickness; + mIsPixel = segment.mIsPixel; + mPixelTreshold = segment.mPixelTreshold; + } + return *this; + } + + ~VirtualSegment() {} + + int mMinLayer = -1; + int mMaxLayer = -1; + float mPadSize = -1.0; + float mRelativeSensitiveThickness = -1.0; + int mIsPixel = 0; // 0: pad or strip; 1: pixel; 2: HCAL + float mPixelTreshold = -1.0; +}; // class VirtualSegment + +class Geometry +{ + public: + Geometry() = default; + Geometry(Geometry* geo); + Geometry(const Geometry& geo) = default; + Geometry& operator=(const Geometry& geo) = default; + ~Geometry() = default; + + static Geometry* getInstance(); + static Geometry* getInstance(const std::string name); + + void init(const std::string geoFile); + void init(); + void buildComposition(); + void setParameters(const std::string geoFile); + void setParameters(); + + // geometry helper functions + // TODO: return tuples instead of using references + std::tuple getGeoPadCenter(int tower, int layer, int stack, int row, int col) const; + std::tuple getGeoPadCenterLocal(int towerX, int towerY, int row, int col) const; + std::tuple getGeoPixCenterLocal(int row, int col) const; + std::tuple getGeoPixelCenter(int pixel_id, int tower, int layer, int stack, int row, int col) const; + std::tuple getGeoCompositionCenter(int tower, int layer, int stack) const; + std::tuple getPadPositionId2RowColStackLayer(int id) const; + int getPixelNumber(int vol0, int vol1, int vol2, double x, double y) const; + std::tuple getGeoTowerCenter(int tower, int segment = -1) const; + bool disabledTower(int tower); + std::tuple getVirtualInfo(double x, double y, double z) const; + std::tuple getXYZFromColRowSeg(int col, int row, int segment) const; + std::tuple getVirtualNColRow(int segment) const; + std::tuple getVirtualLayerSegment(float z) const; + std::tuple getVirtualSegmentFromLayer(int layer) const; + int getVirtualSegment(float z) const; + + // getters + int getNumberOfPads() const { return mGlobal_PAD_NX * mGlobal_PAD_NY; } + int getNumberOfPADsInX() const { return mGlobal_PAD_NX_Tower; } + int getNumberOfPADsInY() const { return mGlobal_PAD_NY_Tower; } + int getNumberOfPIXsInX() const { return mGlobal_PIX_NX_Tower; } + int getNumberOfPIXsInY() const { return mGlobal_PIX_NY_Tower; } + float getHCALTowerSize() const { return mGlobal_HCAL_Tower_Size; } + int getHCALTowersInX() const { return mGlobal_HCAL_Tower_NX; } + int getHCALTowersInY() const { return mGlobal_HCAL_Tower_NY; } + int getNumberOfSegments() const { return mNumberOfSegments; } // NOTE: These are not the virtual segments, but just total number of layers as read from the geometry file. Need to disambiguate + int getNumberOfPadLayers() const { return mNPadLayers; } + int getNumberOfPixelLayers() const { return mNPixelLayers; } + int getNumberOfHCalLayers() const { return mNHCalLayers; } + int getNumberOfLayers() const { return mNPadLayers + mNPixelLayers + mNHCalLayers; } + int getNumberOfLayerSeg() const { return mLayerSeg; } + + double getFOCALSizeX() const; + double getFOCALSizeY() const; + double getTowerSize() const { return mTowerSizeX; } + double getTowerSizeX() const; + double getTowerSizeY() const; + double getFOCALSizeZ() const; + double getECALSizeZ() const; + double getECALCenterZ() const; + double getHCALSizeZ() const; + double getHCALCenterZ() const; + double getFOCALSegmentZ(int seg) const; + double getFOCALZ0() const { return mGlobal_FOCAL_Z0; } + int getNumberOfTowersInX() const { return mGlobal_Tower_NX; } + int getNumberOfTowersInY() const { return mGlobal_Tower_NY; } + double getTowerGapSize() const { return mGlobal_TOWER_TOLX; } + double getTowerGapSizeX() const { return mGlobal_TOWER_TOLX; } + double getTowerGapSizeY() const { return mGlobal_TOWER_TOLY; } + double getGlobalPixelSize() const { return mGlobal_Pixel_Size; } + double getGlobalPixelWaferSizeX() const { return mGlobal_PIX_SizeX; } + double getGlobalPixelWaferSizeY() const { return mGlobal_PIX_SizeY; } + double getGlobalPixelSkin() const { return mGlobal_PIX_SKIN; } + double getGlobalPixelOffsetX() const { return mGlobal_PIX_OffsetX; } + double getGlobalPadSize() const { return mGlobal_Pad_Size; } + float getMiddleTowerOffset() const { return mGlobal_Middle_Tower_Offset; } + bool getInsertFrontPadLayers() const { return mInsertFrontPadLayers; } + bool getInsertHCalReadoutMaterial() const { return mInsertFrontHCalReadoutMaterial; } + + // TObjArray* getFOCALMicroModule(int layer) const; // NOTE: Check if needed, otherwise remove + const Composition* getComposition(int layer, int stack) const; + std::string_view getTowerGapMaterial() const { return mGlobal_Gap_Material; } + + int getVirtualNSegments() const; + + float getVirtualPadSize(int segment) const; + float getVirtualRelativeSensitiveThickness(int segment) const; + float getVirtualPixelTreshold(int segment) const; + float getVirtualSegmentSizeZ(int segment) const; + float getVirtualSegmentZ(int segment) const; + bool getVirtualIsPixel(int segment) const; + bool getVirtualIsHCal(int segment) const; + int getVirtualNLayersInSegment(int segment) const; + int getVirtualMinLayerInSegment(int segment) const; + int getVirtualMaxLayerInSegment(int segment) const; + + void setUpLayerSegmentMap(); + void setUpTowerWaferSize(); + + bool getUseHCALSandwich() { return mUseSandwichHCAL; } + + protected: + std::vector mGeometryComposition; + std::vector mFrontMatterCompositionBase; + std::vector mPadCompositionBase; + std::vector mPixelCompositionBase; + std::vector mHCalCompositionBase; + + // PAD setup + float mGlobal_Pad_Size = 0.0; // pad size + int mGlobal_PAD_NX = 0; // number of X pads in wafer + int mGlobal_PAD_NY = 0; // number of Y pads in wafer + int mGlobal_PAD_NX_Tower = 0; // number of X wafers in tower + int mGlobal_PAD_NY_Tower = 0; // number of Y wafers in tower + float mGlobal_PPTOL = 0.0; // tolerance between the wafers + float mGlobal_PAD_SKIN = 0.0; // dead area (guard ring) on the wafer + float mWaferSizeX = 0.0; // Wafer X size + float mWaferSizeY = 0.0; // Wafer Y size + + // PIX setup + float mGlobal_Pixel_Size = 0.0; // pixel size + float mGlobal_PIX_SizeX = 0.0; // sensor size X + float mGlobal_PIX_SizeY = 0.0; // sensor size Y + float mGlobal_PIX_OffsetX = 0.0; // offset for pixel layers in X + float mGlobal_PIX_OffsetY = 0.0; // offset for pixel layers in Y + float mGlobal_PIX_SKIN = 0.0; + int mGlobal_PIX_NX_Tower = 0; // number of sensors in X + int mGlobal_PIX_NY_Tower = 0; // number of sensors in Y + bool mGlobal_Pixel_Readout = false; // readout on + + // Tower setup + int mNPadLayers = 0; // total number of pad layers + int mNPixelLayers = 0; // number of pixel layers + std::array mPixelLayerLocations; // location of the pixel layers + int mGlobal_Tower_NX = 0; // How many towers in X + int mGlobal_Tower_NY = 0; // How many towers in Y + float mTowerSizeX = 0.0; // X size of tower + float mTowerSizeY = 0.0; // Y size of tower + float mGlobal_TOWER_TOLX = 0.0; // X - tolarance around tower + float mGlobal_TOWER_TOLY = 0.0; // Y - tolarance around tower + float mGlobal_Middle_Tower_Offset = 0.0; // if odd layers, the middle tower is offset due to the beampipe + std::string mGlobal_Gap_Material; // gap filling material NOTE: currently not used + + float mGlobal_HCAL_Tower_Size = 0.0; + int mGlobal_HCAL_Tower_NX = 0; // Number of HCAL towers on X + int mGlobal_HCAL_Tower_NY = 0; // Number of HCAL towers on Y + bool mUseSandwichHCAL = false; + + float mGlobal_FOCAL_Z0 = 0.0; + + bool mInsertFrontPadLayers = false; // Have 2 pad layers in front of ECAL for charged particle veto + bool mInsertFrontHCalReadoutMaterial = false; // if true, insert an 1cm thick aluminium layer at 2cm behind HCal to simulate the material introduced by the readout + + int mLayerSeg = 0; + int mNHCalLayers = 0; // number of HCalLayers + std::array mSegments; // which layer belongs to which segment + std::array mNumberOfLayersInSegments; // nymber of layers in each segment + int mNumberOfSegments = 0; // number of long. segements + int mNFrontMatterCompositionBase = 0; + std::array mLocalLayerZ; //// layer location in z + std::array mLocalSegmentsZ; /// segment location in z + float mFrontMatterLayerThickness = 0.0; + float mPadLayerThickness = 0.0; + float mPixelLayerThickness = 0.0; + float mHCalLayerThickness = 0.0; + std::array mLayerThickness; // thickenss of the layers + std::list mDisableTowers; + + int mVirtualNSegments = 0; + std::vector mVirtualSegmentComposition; + + private: + static Geometry* sGeom; + static bool sInit; +}; // Geometry + +} // namespace focal +} // namespace o2 +#endif \ No newline at end of file diff --git a/Detectors/FOCAL/base/src/Composition.cxx b/Detectors/FOCAL/base/src/Composition.cxx new file mode 100644 index 0000000000000..aefbbee3cd6ca --- /dev/null +++ b/Detectors/FOCAL/base/src/Composition.cxx @@ -0,0 +1,43 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "FOCALBase/Geometry.h" + +using namespace o2::focal; + +Composition::Composition(std::string material, int layer, int stack, int id, + float cx, float cy, float cz, float dx, float dy, float dz) : mMaterial(material), + mLayer(layer), + mStack(stack), + mId(id), + mCenterX(cx), + mCenterY(cy), + mCenterZ(cz), + mSizeX(dx), + mSizeY(dy), + mSizeZ(dz) +{ + // Default constructor +} + +Composition::Composition(Composition* comp) : mMaterial(nullptr), + mLayer(0), + mStack(0), + mId(0), + mCenterX(0), + mCenterY(0), + mCenterZ(0), + mSizeX(0), + mSizeY(0), + mSizeZ(0) +{ + *this = comp; +} \ No newline at end of file diff --git a/Detectors/FOCAL/base/src/FOCALBaseLinkDef.h b/Detectors/FOCAL/base/src/FOCALBaseLinkDef.h index cbb99ddb51abb..d37fad38a9364 100644 --- a/Detectors/FOCAL/base/src/FOCALBaseLinkDef.h +++ b/Detectors/FOCAL/base/src/FOCALBaseLinkDef.h @@ -17,4 +17,6 @@ #pragma link C++ class o2::focal::EventReader + ; #pragma link C++ class o2::focal::TestbeamAnalysis + ; +#pragma link C++ class o2::focal::Geometry + ; +#pragma link C++ class o2::focal::Composition + ; #endif diff --git a/Detectors/FOCAL/base/src/Geometry.cxx b/Detectors/FOCAL/base/src/Geometry.cxx new file mode 100644 index 0000000000000..714d51ab5efdd --- /dev/null +++ b/Detectors/FOCAL/base/src/Geometry.cxx @@ -0,0 +1,1383 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// --- Standard library --- +#include +#include + +// --- ROOT system --- + +#include + +#include "FOCALBase/Geometry.h" + +using namespace o2::focal; + +bool Geometry::sInit = false; +Geometry* Geometry::sGeom = nullptr; + +//_________________________________________________________________________ +Geometry::Geometry(Geometry* geo) +{ + std::fill_n(mPixelLayerLocations.begin(), 20, -1); + std::fill_n(mSegments.begin(), 100, -100); + std::fill_n(mNumberOfLayersInSegments.begin(), 100, -1); + std::fill_n(mLocalLayerZ.begin(), 100, 0.0); + std::fill_n(mLocalSegmentsZ.begin(), 100, 0.0); + std::fill_n(mLayerThickness.begin(), 100, 0.0); + + *this = geo; +} + +//_________________________________________________________________________ +Geometry* Geometry::getInstance() +{ + + if (sGeom == nullptr) { + sGeom = new Geometry(); + sGeom->init(); + } else { + if (sInit == false) { + sGeom = new Geometry(); + sGeom->init(); + } + } + + return sGeom; +} + +//_________________________________________________________________________ +Geometry* Geometry::getInstance(std::string filename) +{ + + if (sGeom == nullptr) { + sGeom = new Geometry(); + sGeom->init(filename); + } else { + if (sInit == false) { + sGeom = new Geometry(); + sGeom->init(filename); + } + } + return sGeom; +} + +//_________________________________________________________________________ +void Geometry::init(std::string filename) +{ + if (filename != "default") { + setParameters(filename); + } else { + setParameters(); + } + + buildComposition(); + sInit = true; +} + +//_________________________________________________________________________ +void Geometry::init() +{ + setParameters(); + buildComposition(); + sInit = true; +} + +//_________________________________________________________________________ +void Geometry::buildComposition() +{ + mGeometryComposition.reserve(1000); + + int nlayers = mNPadLayers + mNPixelLayers + mNHCalLayers; + + ////// Si pad micro module for the first Pad layer + for (int i = 0; i < nlayers; i++) { + if (i < mNPadLayers + mNPixelLayers) { + // Check whether it is a pixel layer + int isPixel = 0; + for (int iPix = 0; iPix < mNPixelLayers && !isPixel; iPix++) { + LOG(debug) << "Check pixel layer idx " << iPix << " loc " << mPixelLayerLocations[iPix] << " i= " << i; + if (i == mPixelLayerLocations[iPix]) { + isPixel = 1; + } + } + + if (isPixel) { + // create pixel compositions + LOG(debug) << "Adding pixel layer at layer " << i; + for (auto& icomp : mPixelCompositionBase) { + icomp.setLayerNumber(i); + mGeometryComposition.push_back(icomp); + } + mLayerThickness[i] = mPixelLayerThickness; + } else { + // create pad compositions + for (auto& icomp : mPadCompositionBase) { + icomp.setLayerNumber(i); + mGeometryComposition.push_back(icomp); + } + mLayerThickness[i] = mPadLayerThickness; + } + } else { + // create hcal compositions + for (auto& icomp : mHCalCompositionBase) { + icomp.setLayerNumber(i); + mGeometryComposition.push_back(icomp); + } + mLayerThickness[i] = mHCalLayerThickness; + } + } // end loop over nlayers + + for (int i = 0; i < nlayers; i++) { + mLocalLayerZ[i] = 0; + for (int j = 0; j < i; j++) { + mLocalLayerZ[i] += mLayerThickness[j]; + } + } + for (int i = 0; i < nlayers; i++) { + mLocalSegmentsZ[mSegments[i]] += mLayerThickness[i]; + } + + mLocalLayerZ[nlayers] = -1; + + ////// add the front matter to the tower + for (auto& icomp : mFrontMatterCompositionBase) { + icomp.setLayerNumber(-1); + mGeometryComposition.push_back(icomp); + } + + //// re-iterate to set the longitudinal positions + for (auto& icomp : mGeometryComposition) { + if (icomp.layer() >= 0) { + icomp.setCenterZ(mFrontMatterLayerThickness + mLocalLayerZ[icomp.layer()] + icomp.centerZ() + icomp.sizeZ() / 2); /// this is pad/strip layer + } else { + icomp.setCenterZ(icomp.centerZ() + icomp.sizeZ() / 2); /// this is frontmatter + } + } +} + +//_________________________________________________________________________ +void Geometry::setParameters() +{ + + LOG(warning) << " Default parameters are not used "; + /////// this is default setting for the global parameters + mGlobal_FOCAL_Z0 = 500; +} + +//_________________________________________________________________________ +void Geometry::setParameters(std::string geometryfile) +{ + /////// this is default setting for the global parameters + mGlobal_FOCAL_Z0 = 700.0; + mInsertFrontPadLayers = false; + // PAD setup + mGlobal_Pad_Size = 1.0; // pad size + mGlobal_PAD_NX = 9; // number of X pads in wafer + mGlobal_PAD_NY = 8; // number of Y pads in wafer + mGlobal_PAD_NX_Tower = 5; // number of X wafers in tower + mGlobal_PAD_NY_Tower = 1; // number of Y wafers in tower + mGlobal_PPTOL = 0.0; // tolerance between the wafers + mGlobal_PAD_SKIN = 0.2; // dead area (guard ring) on the wafer + mGlobal_PIX_SKIN = 0.004; + // PIX setup + mGlobal_Pixel_Readout = false; + mGlobal_Pixel_Size = 0.005; // pixel size + mGlobal_PIX_SizeX = 3.0; // sensor size X + mGlobal_PIX_SizeY = 2.74; // sensor size Y + mGlobal_PIX_OffsetX = 1.0; + mGlobal_PIX_OffsetY = 0.09; + mGlobal_PIX_NX_Tower = 15; // number of sensors in X + mGlobal_PIX_NY_Tower = 3; // number of sensors in Y + + mGlobal_Tower_NX = 2; + mGlobal_Tower_NY = 11; + + mNPixelLayers = 4; + mPixelLayerLocations[0] = 2; + mPixelLayerLocations[1] = 4; + mPixelLayerLocations[2] = 6; + mPixelLayerLocations[3] = 8; + + mTowerSizeX = 0; + mTowerSizeY = 0; + mWaferSizeX = 0; + mWaferSizeY = 0; + + std::ifstream fin(geometryfile); + if (fin.fail()) { + LOG(error) << "No geometry file for FoCAL. Use default ones"; + setParameters(); + return; + } else { + LOG(info) << "Using geometry file " << geometryfile; + } + + std::vector padCompDummy(10); + std::vector hCalCompDummy(10); + std::vector pixelCompDummy(10); + std::vector frontMatterCompDummy(10); + int nPad = 0; + int hHCal = 0; + int nPixel = 0; + int nFrontMatter = 0; + + int npadlayers = 0; + int npixlayers = 0; + int pixl[10]; + + std::string input; + + LOG(info) << "Loading FOCAL geometry file "; + while (getline(fin, input)) { + LOG(debug) << "Read string :: " << input.c_str(); + const char* p = std::strpbrk("#", input.c_str()); + if (p != nullptr) { + LOG(debug) << "Skipping comment"; + continue; + } + + std::vector tokens; + std::stringstream str(input); + std::string tmpStr; + while (getline(str, tmpStr, ' ')) { + if (tmpStr.empty()) { + continue; + } + tokens.push_back(tmpStr); + } + + std::string command = tokens[0]; + LOG(debug) << "command: " << command; + + if (command.find("COMPOSITION") != std::string::npos) /// definition of the composition + { + std::string material = tokens[1]; + float cx = std::stof(tokens[2]); + float cy = std::stof(tokens[3]); + float dx = std::stof(tokens[4]); + float dy = std::stof(tokens[5]); + float dz = std::stof(tokens[6]); + float cz = 0; + + LOG(debug) << "Material :: " << material; + LOG(debug) << "cx/cy/dx/dy/dz :: " << cx << " / " << cy << " / " << dx << " / " << dy << " / " << dz; + + int stack; + if (command.find("PAD") != std::string::npos) { + sscanf(command.c_str(), "COMPOSITION_PAD_S%d", &stack); + padCompDummy.emplace_back(material, stack, stack, 0, cx, cy, cz, dx, dy, dz); + nPad++; + } + + if (command.find("HCAL") != std::string::npos) { + sscanf(command.c_str(), "COMPOSITION_HCAL_S%d", &stack); + hCalCompDummy.emplace_back(material, stack, stack, 0, cx, cy, cz, dx, dy, dz); + hHCal++; + } + + if (command.find("PIX") != std::string::npos) { + sscanf(command.c_str(), "COMPOSITION_PIX_S%d", &stack); + pixelCompDummy.emplace_back(material, stack, stack, 0, cx, cy, cz, dx, dy, dz); + mGlobal_PIX_SizeX = dx; + mGlobal_PIX_SizeY = dy; + nPixel++; + } + + if (command.find("FM") != std::string::npos) { + sscanf(command.c_str(), "COMPOSITION_FM_S%d", &stack); + frontMatterCompDummy.emplace_back(material, stack, stack, 0, cx, cy, cz, dx, dy, dz); + nFrontMatter++; + } + } // end if COMPOSITION + + if (command.find("GLOBAL") != std::string::npos) { + + if (command.find("PAD_SIZE") != std::string::npos) { + mGlobal_Pad_Size = std::stof(tokens[1]); + LOG(debug) << "Pad sensor size is set to : " << mGlobal_Pad_Size; + } + + if (command.find("PAD_NX") != std::string::npos) { + mGlobal_PAD_NX = std::stoi(tokens[1]); + LOG(debug) << "No. sensors per pad wafer in X direction : " << mGlobal_PAD_NX; + } + + if (command.find("PAD_NY") != std::string::npos) { + mGlobal_PAD_NY = std::stoi(tokens[1]); + LOG(debug) << "No. sensors per pad wafer in Y direction : " << mGlobal_PAD_NY; + } + + if (command.find("PAD_SUPERMODULE_X") != std::string::npos) { + mGlobal_PAD_NX_Tower = std::stoi(tokens[1]); + LOG(debug) << "Number of pad wafers per module in X direction : " << mGlobal_PAD_NX_Tower; + } + + if (command.find("PAD_SUPERMODULE_Y") != std::string::npos) { + mGlobal_PAD_NY_Tower = std::stoi(tokens[1]); + LOG(debug) << "Number of pad wafers per module in Y direction : " << mGlobal_PAD_NY_Tower; + } + + if (command.find("PIX_NX") != std::string::npos) { + mGlobal_PIX_NX_Tower = std::stoi(tokens[1]); + LOG(debug) << "Number of pixels sensors per module in X direction : " << mGlobal_PIX_NX_Tower; + } + + if (command.find("PIX_NY") != std::string::npos) { + mGlobal_PIX_NY_Tower = std::stoi(tokens[1]); + LOG(debug) << "Number of pixels sensors per module in Y direction : " << mGlobal_PIX_NY_Tower; + } + + if (command.find("PAD_PPTOL") != std::string::npos) { + mGlobal_PPTOL = std::stof(tokens[1]); + LOG(debug) << "Distance between pad sensors : " << mGlobal_PPTOL; + } + + if (command.find("PAD_SKIN") != std::string::npos) { + mGlobal_PAD_SKIN = std::stof(tokens[1]); + LOG(debug) << "Pad wafer skin : " << mGlobal_PAD_SKIN; + } + + if (command.find("FOCAL_Z") != std::string::npos) { + mGlobal_FOCAL_Z0 = std::stof(tokens[1]); + LOG(debug) << "Z-Location of the FoCAL is set to : " << mGlobal_FOCAL_Z0; + } + + if (command.find("HCAL_TOWER_SIZE") != std::string::npos) { + mGlobal_HCAL_Tower_Size = std::stof(tokens[1]); + LOG(debug) << "The size of the HCAL readout tower will be : " << mGlobal_HCAL_Tower_Size; + } + + if (command.find("HCAL_TOWER_NX") != std::string::npos) { + mGlobal_HCAL_Tower_NX = std::stoi(tokens[1]); + LOG(debug) << "The number of the HCAL readout towers in X will be : " << mGlobal_HCAL_Tower_NX; + } + + if (command.find("HCAL_TOWER_NY") != std::string::npos) { + mGlobal_HCAL_Tower_NY = std::stoi(tokens[1]); + LOG(debug) << "The number of the HCAL readout towers in Y will be : " << mGlobal_HCAL_Tower_NY; + } + + if (command.find("PIX_OffsetX") != std::string::npos) { + mGlobal_PIX_OffsetX = std::stof(tokens[1]); + LOG(debug) << "Pixel offset from the beam pipe will be: " << mGlobal_PIX_OffsetX; + } + + if (command.find("PIX_OffsetY") != std::string::npos) { + mGlobal_PIX_OffsetY = std::stof(tokens[1]); + LOG(debug) << "Pixel offset from the top of module will be: " << mGlobal_PIX_OffsetY; + } + + if (command.find("PIX_SKIN") != std::string::npos) { + mGlobal_PIX_SKIN = std::stof(tokens[1]); + LOG(debug) << "Pixel sensor skin : " << mGlobal_PIX_SKIN; + } + + if (command.find("TOWER_TOLX") != std::string::npos) { + mGlobal_TOWER_TOLX = std::stof(tokens[1]); + mGlobal_Gap_Material = tokens[2]; + LOG(debug) << "Distance between modules in X direction : " << mGlobal_TOWER_TOLX << ", Material : " << mGlobal_Gap_Material; + } + + if (command.find("TOWER_TOLY") != std::string::npos) { + mGlobal_TOWER_TOLY = std::stof(tokens[1]); + mGlobal_Gap_Material = tokens[2]; + LOG(debug) << "Distance between modules in Y direction : " << mGlobal_TOWER_TOLY << " Material : " << mGlobal_Gap_Material; + } + + if (command.find("MIDDLE_TOWER_OFFSET") != std::string::npos) { + mGlobal_Middle_Tower_Offset = std::stof(tokens[1]); + LOG(debug) << "Middle tower offset will be: " << mGlobal_Middle_Tower_Offset; + } + + if (command.find("Tower_NX") != std::string::npos) { + mGlobal_Tower_NX = std::stof(tokens[1]); + LOG(debug) << "Number of FOCAL modules in x direction is set to : " << mGlobal_Tower_NX; + } + + if (command.find("Tower_NY") != std::string::npos) { + mGlobal_Tower_NY = std::stof(tokens[1]); + LOG(debug) << "Number of FOCAL modules in y direction is set to : " << mGlobal_Tower_NY; + } + } // end if GLOBAL + + if (command.find("COMMAND") != std::string::npos) { + + if (command.find("NUMBER_OF_PAD_LAYERS") != std::string::npos) { + npadlayers = std::stoi(tokens[1]); + LOG(debug) << "Number of pad layers " << npadlayers; + } + + if (command.find("NUMBER_OF_HCAL_LAYERS") != std::string::npos) { + mNHCalLayers = std::stoi(tokens[1]); + LOG(debug) << "Number of HCAL layers " << mNHCalLayers; + if (mNHCalLayers == 1) { + mUseSandwichHCAL = false; + } else { + mUseSandwichHCAL = true; + } + } + + if (command.find("NUMBER_OF_SEGMENTS") != std::string::npos) { + mNumberOfSegments = std::stoi(tokens[1]); + LOG(debug) << "Number of Segments " << mNumberOfSegments; + } + + if (command.find("INSERT_PIX") != std::string::npos) { + sscanf(command.c_str(), "COMMAND_INSERT_PIX_AT_L%d", &pixl[npixlayers]); + LOG(debug) << "Number of pixel layer " << npixlayers << " : location " << pixl[npixlayers]; + npixlayers++; + } + + if (command.find("COMMAND_PIXEL_READOUT_ON") != std::string::npos) { + mGlobal_Pixel_Readout = true; + mGlobal_Pixel_Size = std::stof(tokens[1]); + LOG(debug) << "Pixel readout on (for MASPS): pixel size is set to : " << mGlobal_Pixel_Size; + } + + if (command.find("COMMAND_INSERT_FRONT_PAD_LAYERS") != std::string::npos) { + mInsertFrontPadLayers = true; + LOG(debug) << "Insert two pad layers in front of ECAL for charged particle veto!"; + } + + if (command.find("COMMAND_INSERT_HCAL_READOUT") != std::string::npos) { + mInsertFrontHCalReadoutMaterial = true; + LOG(debug) << "Insert Aluminium 1cm thick layer behind HCAL to simulate readout SiPM material !"; + } + } // end if COMMAND + + if (command.find("VIRTUAL") != std::string::npos) { + + int segment, minlayer, maxLayer, isPixel; + float padSize, sensitiveThickness, pixelTreshold; + + if (command.find("N_SEGMENTS") != std::string::npos) { + mVirtualNSegments = std::stoi(tokens[1]); + LOG(debug) << "Number of Virtual Segments is set to : " << mVirtualNSegments; + } + + if (command.find("SEGMENT_LAYOUT") != std::string::npos) { + minlayer = std::stoi(tokens[1]); + maxLayer = std::stoi(tokens[2]); + padSize = std::stof(tokens[3]); + sensitiveThickness = std::stof(tokens[4]); + isPixel = std::stoi(tokens[5]); + pixelTreshold = std::stof(tokens[6]); + + if (mVirtualSegmentComposition.size() == 0) { + if (mVirtualNSegments <= 0) { + LOG(debug) << "Making 20 segments"; + for (int seg = 0; seg < 20; seg++) { + mVirtualSegmentComposition.emplace_back(); + } + mVirtualNSegments = 20; + } else { + LOG(debug) << "Making " << mVirtualNSegments << " segments"; + for (int seg = 0; seg < mVirtualNSegments; seg++) { + mVirtualSegmentComposition.emplace_back(); + } + } + } + + sscanf(command.c_str(), "VIRTUAL_SEGMENT_LAYOUT_N%d", &segment); + if (segment > mVirtualNSegments) { + continue; + } + mVirtualSegmentComposition[segment].mMinLayer = minlayer; + mVirtualSegmentComposition[segment].mMaxLayer = maxLayer; + mVirtualSegmentComposition[segment].mPadSize = padSize; + mVirtualSegmentComposition[segment].mRelativeSensitiveThickness = sensitiveThickness; + mVirtualSegmentComposition[segment].mPixelTreshold = pixelTreshold; + mVirtualSegmentComposition[segment].mIsPixel = isPixel; + + LOG(debug) << "Segment number " << segment << " defined with (minLayer, maxLayer, padSize, isPixel): (" + << minlayer << ", " << maxLayer << ", " << padSize << ", " << isPixel << ")"; + } // end if SEGMENT_LAYOUT + + } // end if VIRTUAL + + } // end while + + setUpTowerWaferSize(); + /////// re-arrange the longitudinal components + mNPixelLayers = npixlayers; + for (int i = 0; i < npixlayers; i++) { + mPixelLayerLocations[i] = pixl[i]; + } + + mNPadLayers = npadlayers; + LOG(debug) << "mNPadLayers, mNPixelLayers, mNHCalLayers, mNumberOfSegments :: " << mNPadLayers << " / " << mNPixelLayers << " / " << mNHCalLayers << " / " << mNumberOfSegments; + + mLayerSeg = (mNPadLayers + mNPixelLayers + mNHCalLayers) / mNumberOfSegments; + + if (mNumberOfSegments >= 100) { + LOG(warning) << "You reached the segments limits! Setting Number of segments to: 100"; + mNumberOfSegments = 99; + LOG(warning) << "New number of segments: " << mNumberOfSegments; + mLayerSeg = (mNPadLayers + mNPixelLayers + mNHCalLayers) / mNumberOfSegments; + } + if ((mNPadLayers + mNPixelLayers + mNHCalLayers) % mNumberOfSegments) { + mNumberOfSegments++; + for (int i = 0; i < mNumberOfSegments; i++) { + mNumberOfLayersInSegments[i] = mLayerSeg; + } + LOG(debug) << "Number of segments: " << mNumberOfSegments; + } else { + for (int i = 0; i < mNumberOfSegments; i++) { + mNumberOfLayersInSegments[i] = mLayerSeg; + } + } + + setUpLayerSegmentMap(); + + float center_z = 0; + + mPadCompositionBase.reserve(200); + mHCalCompositionBase.reserve(200); + mPixelCompositionBase.reserve(200); + mFrontMatterCompositionBase.reserve(200); + + for (auto& tmpComp : padCompDummy) { + LOG(debug) << "Material(pad layer) " << tmpComp.material(); + LOG(debug) << "layer / stack / id :: " << tmpComp.layer() << " / " << tmpComp.stack() << " / " << tmpComp.id(); + LOG(debug) << "center x,y,dz :: " << tmpComp.sizeX() << " / " << tmpComp.sizeY() << " / " << tmpComp.sizeZ(); + if (tmpComp.material().compare("SiPad")) { // materials other than SiPad + mPadCompositionBase.emplace_back(tmpComp.material(), tmpComp.layer(), tmpComp.stack(), tmpComp.id(), + tmpComp.centerX(), tmpComp.centerY(), center_z, + mTowerSizeX, mTowerSizeY, tmpComp.sizeZ()); + if (mTowerSizeX < tmpComp.sizeX()) { + mTowerSizeX = tmpComp.sizeX(); + } + if (mTowerSizeY < tmpComp.sizeY()) { + mTowerSizeY = tmpComp.sizeY(); + } + } else { + for (int itowerX = 0; itowerX < mGlobal_PAD_NX_Tower; itowerX++) { + for (int itowerY = 0; itowerY < mGlobal_PAD_NY_Tower; itowerY++) { + for (int ix = 0; ix < mGlobal_PAD_NX; ix++) { + for (int iy = 0; iy < mGlobal_PAD_NY; iy++) { + auto [x, y] = getGeoPadCenterLocal(itowerX, itowerY, iy, ix); + mPadCompositionBase.emplace_back("SiPad", tmpComp.layer(), tmpComp.stack(), + ix + iy * mGlobal_PAD_NX + itowerX * mGlobal_PAD_NX * mGlobal_PAD_NY + itowerY * mGlobal_PAD_NX_Tower * mGlobal_PAD_NX * mGlobal_PAD_NY, + x, y, center_z, + mGlobal_Pad_Size, mGlobal_Pad_Size, tmpComp.sizeZ()); + if (mTowerSizeX < mGlobal_Pad_Size) { + mTowerSizeX = mGlobal_Pad_Size; + } + if (mTowerSizeY < mGlobal_Pad_Size) { + mTowerSizeY = mGlobal_Pad_Size; + } + } + } + } // end for itowerY + } // end for itowerX + } // end else + center_z += tmpComp.getThickness(); + } // end loop over pad layer compositions + LOG(debug) << "============ Created all pad layer compositions (" << mPadCompositionBase.size() << " volumes)"; + + mPadLayerThickness = center_z; + + mGlobal_PIX_OffsetY = (getTowerSizeY() - mGlobal_PIX_NY_Tower * mGlobal_PIX_SizeY) / 2 - 2.0 * mGlobal_PIX_SKIN; + + center_z = 0; + for (auto& tmpComp : pixelCompDummy) { + LOG(debug) << "Material (pixel layer) " << tmpComp.material(); + LOG(debug) << "layer / stack / id :: " << tmpComp.layer() << " / " << tmpComp.stack() << " / " << tmpComp.id(); + LOG(debug) << "center x,y,dz :: " << tmpComp.sizeX() << " / " << tmpComp.sizeY() << " / " << tmpComp.sizeZ(); + if (tmpComp.material().compare("SiPix")) { + mPixelCompositionBase.emplace_back(tmpComp.material(), mPixelLayerLocations[0], tmpComp.stack(), tmpComp.id(), + tmpComp.centerX(), tmpComp.centerY(), center_z, mTowerSizeX, mTowerSizeY, tmpComp.sizeZ()); + } else { + for (int ix = 0; ix < mGlobal_PIX_NX_Tower; ix++) { + for (int iy = 0; iy < mGlobal_PIX_NY_Tower; iy++) { + auto [pixX, pixY] = getGeoPixCenterLocal(iy, ix); + mPixelCompositionBase.emplace_back("SiPix", tmpComp.layer(), tmpComp.stack(), ix + iy * mGlobal_PIX_NX_Tower, + pixX, pixY, center_z, + mGlobal_PIX_SizeX, mGlobal_PIX_SizeY, tmpComp.sizeZ()); + } + } + } + center_z += tmpComp.getThickness(); + } + LOG(debug) << "============ Created all pixel layer compositions (" << mPixelCompositionBase.size() << " volumes)"; + mPixelLayerThickness = center_z; + + // Add HCal Layers + center_z = 0; + for (auto& tmpComp : hCalCompDummy) { + LOG(debug) << "Material (hcal) " << tmpComp.material(); + LOG(debug) << "layer / stack / id :: " << tmpComp.layer() << " / " << tmpComp.stack() << " / " << tmpComp.id(); + LOG(debug) << "center x,y,dz :: " << tmpComp.sizeX() << " / " << tmpComp.sizeY() << " / " << tmpComp.sizeZ(); + mHCalCompositionBase.emplace_back(tmpComp.material(), tmpComp.layer(), tmpComp.stack(), tmpComp.id(), + tmpComp.centerX(), tmpComp.centerY(), mNHCalLayers == 1 ? 0. : center_z, // if we decided to use the spagetti HCAL it will be only one layer with two compositions + tmpComp.sizeX(), tmpComp.sizeY(), tmpComp.sizeZ()); + if (mNHCalLayers == 1) { + center_z = tmpComp.getThickness(); + } else { + center_z += tmpComp.getThickness(); + } + } + LOG(debug) << "============ Created all hcal compositions (" << mHCalCompositionBase.size() << " volumes)"; + mHCalLayerThickness = center_z; + center_z = 0; + + mFrontMatterLayerThickness = center_z; + LOG(debug) << " end of SetParameters "; +} + +//_________________________________________________________________________ +const Composition* Geometry::getComposition(int layer, int stack) const +{ + + for (auto& icomp : mGeometryComposition) { + if (icomp.layer() == layer && icomp.stack() == stack) { + return &icomp; + } + } + return nullptr; +} + +//_________________________________________________________________________ +/// this gives global position of the center of tower +std::tuple Geometry::getGeoTowerCenter(int tower, int segment) const +{ + int id = tower; + int itowerx = id % getNumberOfTowersInX(); + int itowery = id / getNumberOfTowersInX(); + + float dwx = getTowerSizeX() + getTowerGapSizeX(); + float dwy = getTowerSizeY() + getTowerGapSizeY(); + + double x = itowerx * dwx + 0.5 * dwx - 0.5 * getFOCALSizeX(); + double y = itowery * dwy + 0.5 * dwy - 0.5 * getFOCALSizeY(); + if (itowerx == 0 && itowery == 5) { + x -= mGlobal_Middle_Tower_Offset; + } + if (itowerx == 1 && itowery == 5) { + x += mGlobal_Middle_Tower_Offset; + } + + // From here is HCal stuff + if (getVirtualIsHCal(segment)) { + auto [status, nCols, nRows] = getVirtualNColRow(segment); + int ix = id % nCols; + int iy = id / nRows; + + if (mUseSandwichHCAL) { + float padSize = mVirtualSegmentComposition[segment].mPadSize; + double hCALsizeX = nCols * padSize; + double hCALsizeY = nRows * padSize; + x = ix * padSize + 0.5 * padSize - 0.5 * hCALsizeX; + y = iy * padSize + 0.5 * padSize - 0.5 * hCALsizeY; + } else { + nCols = std::floor(getFOCALSizeX() / getHCALTowerSize() + 0.001) + 1; + nRows = std::floor(getFOCALSizeY() / getHCALTowerSize() + 0.001); + ix = id % nCols; + iy = id / nRows; + double beamPipeRadius = 3.6; // in cm TODO: check if this is OK + double towerHalfDiag = std::sqrt(2) * 0.5 * getTowerSizeX(); // tower half diagonal + double minRadius = beamPipeRadius + towerHalfDiag; + + float towerSize = getHCALTowerSize() / 7; // To be set from outside (number of channels on x & y) + y = iy * towerSize + 0.5 * towerSize - 0.5 * towerSize * nRows; + x = ix * towerSize + 0.5 * towerSize - 0.5 * towerSize * nCols; + if (y < minRadius && y > -minRadius) { + x = int(x) <= 0 ? x - (minRadius - towerSize) : x + (minRadius - towerSize); + } + } + } + + /* + //// remove beam pipe area + // define beam pipe radius, calculate half of the tower diagonal in XY + // and remove every tower which center is closer than the sum of the two... + double beamPipeRadius = 3.6; // in cm TODO: check if this is OK + double towerHalfDiag = std::sqrt(2)*0.5*getTowerSizeX(); // tower half diagonal + double minRadius = beamPipeRadius+towerHalfDiag; + // + if((x*x+y*y) < (minRadius*minRadius)){ // comparing the tower center position with the minimum distance in second powers. + //mDisableTowers.push_back(Tower+1); + //return false; + } + */ + + return {x, y, getFOCALZ0()}; +} + +//_________________________________________________________________________ +std::tuple Geometry::getGeoCompositionCenter(int tower, int layer, int stack) const +{ + auto [status, segment] = getVirtualSegmentFromLayer(layer); + auto [towX, towY, towZ] = getGeoTowerCenter(tower, segment); + double z = towZ; + + Composition* comp1 = (Composition*)getComposition(layer, stack); + if (comp1 == nullptr) { + z = z + mLocalLayerZ[layer] - getFOCALSizeZ() / 2; + } else { + z = comp1->centerZ() - getFOCALSizeZ() / 2 + getFOCALZ0(); + } + return {towX, towY, z}; +} + +//_________________________________________________________________________ +/// this gives global position of the pad +std::tuple Geometry::getGeoPadCenter(int tower, int layer, int stack, int row, int col) const +{ + auto [x, y, z] = getGeoCompositionCenter(tower, layer, stack); + int itowerx = tower % mGlobal_PAD_NX_Tower; + int itowery = tower / mGlobal_PAD_NX_Tower; + auto [padX, padY] = getGeoPadCenterLocal(itowerx, itowery, row, col); + + return {x + padX, y + padY, z}; +} + +//_________________________________________________________________________ +/// this gives local position of the pad with respect to the wafer +std::tuple Geometry::getGeoPadCenterLocal(int towerX, int towerY, int row, int col) const +{ + /// startting to count from upper-left + /* + (0,0) + ___________________ + | __ __ + | |__| |__| + | __ __ + | |__| |__| + | __ __ + | |__| |__| + | + */ + double x = +towerX * mWaferSizeX + mGlobal_PAD_SKIN + col * (mGlobal_Pad_Size + mGlobal_PPTOL) + 0.5 * mGlobal_Pad_Size; + double y = -towerY * mWaferSizeY - mGlobal_PAD_SKIN - row * (mGlobal_Pad_Size + mGlobal_PPTOL) - 0.5 * mGlobal_Pad_Size; + x = x - 0.5 * getTowerSizeX(); + y = y + 0.5 * mTowerSizeY; + return {x, y}; +} + +/// this gives local position of the pad with respect to the wafer +std::tuple Geometry::getGeoPixCenterLocal(int row, int col) const +{ + /// startting to count from upper-left + /* + (0,0) + ___________________ + | __ __ + | |__| |__| + | __ __ + | |__| |__| + | __ __ + | |__| |__| + | + */ + double x = +col * (mGlobal_PIX_SizeX + 2.0 * mGlobal_PIX_SKIN) + 0.5 * mGlobal_PIX_SizeX; + double y = -row * (mGlobal_PIX_SizeY + 2.0 * mGlobal_PIX_SKIN) - 0.5 * mGlobal_PIX_SizeY; + x = x - 0.5 * mTowerSizeX; + y = y + 0.5 * mTowerSizeY - mGlobal_PIX_OffsetY; + return {x, y}; +} + +//_________________________________________________________________________ +double Geometry::getTowerSizeX() const +{ + return mTowerSizeX; + // return mGlobal_NX_NY_Pads*(mGlobal_Pad_Size+mGlobal_PPTOL)-mGlobal_PPTOL+2*mGlobal_PAD_SKIN; +} + +//_________________________________________________________________________ +double Geometry::getTowerSizeY() const +{ + return mTowerSizeY; + // return mGlobal_NX_NY_Pads*(mGlobal_Pad_Size+mGlobal_PPTOL)-mGlobal_PPTOL+2*mGlobal_PAD_SKIN; +} + +//_________________________________________________________________________ +double Geometry::getFOCALSizeX() const +{ + return mGlobal_Tower_NX * (getTowerSizeX() + mGlobal_TOWER_TOLX); +} + +//_________________________________________________________________________ +double Geometry::getFOCALSizeY() const +{ + return mGlobal_Tower_NY * (getTowerSizeY() + mGlobal_TOWER_TOLY); +} + +//_________________________________________________________________________ +double Geometry::getFOCALSizeZ() const +{ + + double ret = 0; + for (int i = 0; i < mNPadLayers + mNPixelLayers + mNHCalLayers; i++) { + ret += mLayerThickness[i]; + } + ret = ret + mFrontMatterLayerThickness; + return ret; +} + +//_________________________________________________________________________ +double Geometry::getECALSizeZ() const +{ + + double ret = 0; + for (int i = 0; i < mNPadLayers + mNPixelLayers; i++) { + ret += mLayerThickness[i]; + } + ret = ret + mFrontMatterLayerThickness; + return ret; +} + +//_________________________________________________________________________ +double Geometry::getECALCenterZ() const +{ + + // Determines the ECAL z center of mass with respect to the FOCAL + double centerZ = mFrontMatterLayerThickness + mLocalLayerZ[0] + getECALSizeZ() / 2; + return centerZ; +} + +//_________________________________________________________________________ +double Geometry::getHCALSizeZ() const +{ + + double ret = 0; + for (int i = mNPadLayers + mNPixelLayers; i < mNPadLayers + mNPixelLayers + mNHCalLayers; i++) { + ret += mLayerThickness[i]; + } + return ret; +} + +//_________________________________________________________________________ +double Geometry::getHCALCenterZ() const +{ + + double centerZ = mFrontMatterLayerThickness + mLocalLayerZ[mNPadLayers + mNPixelLayers] + getHCALSizeZ() / 2; + return centerZ; +} + +//_________________________________________________________________________ +// this returns the following quantities for the pad position location +// layer depth +// pad row and col in the wafer +// wafer id in the brick, where the pad belongs to +std::tuple Geometry::getPadPositionId2RowColStackLayer(int id) const +{ + + //// id contains loction of pads in the tower, pad stack, pad layer + ///// (fComp->id()) + (fComp->stack() << 12) + (fComp->layer() << 16) +1 ; + ///// + int number = id - 1; + int padid = (number & 0xfff); + int stack = (number >> 12) & 0x000f; + // lay = (number >> 16) & 0x00ff; + int lay = (number >> 16) & 0x000f; + + // seg = fSegments[lay]; + auto [status, seg] = getVirtualSegmentFromLayer(lay); // NOTE: to be checked since this overrides the initialization above + /*col = padid%mGlobal_PAD_NX; + row = padid/mGlobal_PAD_NX;*/ + int waferx = 0; + int wafery = 0; + int col = 0; + int row = 0; + + // This gives the (col,row) of the pixel sensor + if (getVirtualIsPixel(seg)) { + col = padid % mGlobal_PIX_NX_Tower; + row = padid / mGlobal_PIX_NX_Tower; + } else { + col = padid % mGlobal_PAD_NX; + int remainder = (padid - col) / mGlobal_PAD_NX; + row = remainder % mGlobal_PAD_NY; + remainder = (remainder - row) / mGlobal_PAD_NY; + waferx = remainder % mGlobal_PAD_NX_Tower; + wafery = remainder / mGlobal_PAD_NX_Tower; + } + /*cout << "FROM GEOMETRY stack/lay/seg/waferx/wafery/col/row :: " << stack << " / " << lay << " / " << seg << " / " + << waferx << " / " << wafery << " / " << col << " / " << row << endl;*/ + if (getVirtualIsHCal(seg)) { + auto [status, nCols, nRows] = getVirtualNColRow(seg); + col = id % nCols; + row = id / nRows; + } + + return {row, col, stack, lay, seg, waferx, wafery}; +} + +//_________________________________________________________________________ +//// this gives longitudinal position of the segment +double Geometry::getFOCALSegmentZ(int seg) const +{ + + double ret = 0; + if (seg < 0 || seg > mNumberOfSegments) { + ret = getFOCALZ0(); + } else { + for (int i = 0; i < seg; i++) { + ret += mLocalSegmentsZ[i]; + } + } + ret = ret + mLocalSegmentsZ[seg] / 2 + getFOCALZ0() - getFOCALSizeZ() / 2; + return ret; +} + +//_________________________________________________________________________ +/// this function defines: +/// layer is pixel or pad +/// which segment this layer belongs to? +void Geometry::setUpLayerSegmentMap() +{ + ///// define the longitudinal elements + //// mSegments = -1 -> strip layer + //// mSegments = 0 --> pad 0th segement + //// mSegments = 1 --> pad 1th segement + //// mSegments = 2 --> pad 2th segement + + std::vector layerType; + for (int j = 0; j < mNPixelLayers + mNPadLayers + mNHCalLayers; j++) { + layerType.push_back(0); + } + for (int i = 0; i < mNPixelLayers; i++) { + layerType[mPixelLayerLocations[i]] = -1; + } + + int low = 0; + int start = 0; + int high = 0; + for (int i = 0; i < mNumberOfSegments; i++) { + high += mNumberOfLayersInSegments[i]; + for (int j = start; j < mNPixelLayers + mNPadLayers + mNHCalLayers; j++) { + if (layerType[j] == -1) { + mSegments[j] = i; + start++; + } else { + mSegments[j] = i; + low++; + start++; + } + if (low >= high) { + break; + } + } + } +} + +//_________________________________________________________________________ +/// this is the pixel number to be stored in the Hits.root file +/// this is used for the study with fine pixel readout +/// the pad is divided into the pixels with the size of mGlobal_ Pixel_Size +int Geometry::getPixelNumber(int vol0, int vol1, int /*vol2*/, double x, double y) const +{ + int ret = 0; + if (mGlobal_Pixel_Readout == false) { + ret = -1; + return ret; + } + int id = vol0; + // int tower = vol1; + // int brick = vol2; /// meaning 0 in the current design + + auto [row, col, stack, layer, segment, waferX, waferY] = getPadPositionId2RowColStackLayer(id); + auto [pixX, pixY] = getGeoPixCenterLocal(row, col); + + double x_loc = x - pixX; + double y_loc = y - pixY; + double pixel_nbr_x = ((x_loc + 0.5 * getGlobalPixelWaferSizeX()) / (mGlobal_Pixel_Size)); + double pixel_nbr_y = ((y_loc + 0.5 * getGlobalPixelWaferSizeY()) / (mGlobal_Pixel_Size)); + + int pixel_number_x; + pixel_number_x = static_cast(pixel_nbr_x); + // if(pixel_number_x-pixel_nbr_x>0.5){ + // pixel_number_x = pixel_number_x+1; + // } + + int pixel_number_y; + pixel_number_y = static_cast(pixel_nbr_y); + // if(pixel_number_y-pixel_nbr_y>0.5){ + // pixel_number_y = pixel_number_y+1; + // } + ret = (pixel_number_x << 16) | pixel_number_y; + // cout< Geometry::getGeoPixelCenter(int pixel, int tower, int layer, int stack, int row, int col) const +{ + auto [x0, y0, z0] = getGeoPadCenter(tower, layer, stack, row, col); + + int pixel_y = pixel & 0xff; + int pixel_x = (pixel >> 8) & 0xff; + + double x1, y1; + x1 = pixel_x * mGlobal_Pixel_Size + 0.5 * mGlobal_Pixel_Size - 0.5 * mGlobal_Pad_Size; + y1 = pixel_y * mGlobal_Pixel_Size + 0.5 * mGlobal_Pixel_Size - 0.5 * mGlobal_Pad_Size; + + return {x1 + x0, y1 + y0, z0}; +} + +std::tuple Geometry::getVirtualInfo(double x, double y, double z) const +{ + // + // Calculate col, row, layer, (virtual) segment from x,y,z + // returns false if outside volume + // + int col = -1, row = -1; + auto [status, layer, segment] = getVirtualLayerSegment(z); + + if (!status) { + return {false, col, row, layer, segment}; + } + if (segment == -1) { + return {false, col, row, layer, segment}; + } + if (std::abs(x) > (getFOCALSizeX() + 2 * getMiddleTowerOffset()) / 2) { + return {false, col, row, layer, segment}; + } + if (std::abs(y) > getFOCALSizeY() / 2) { + return {false, col, row, layer, segment}; + } + + if (getVirtualIsHCal(segment)) { + float towerSize = getHCALTowerSize(); + double beamPipeRadius = 3.0; // in cm TODO check the number is OK (different hardcoded values are used elsewhere) + double minRadius = beamPipeRadius + towerSize / 2.; + + double hCALsizeX = getHCALTowersInX() * towerSize; + double hCALsizeY = getHCALTowersInY() * towerSize; + + if (x < minRadius && x > -minRadius && y < minRadius && y > -minRadius) { + x = x < 0 ? x - 0.001 : x + 0.001; + y = y < 0 ? y - 0.001 : y + 0.001; + } + if (!mUseSandwichHCAL) { + row = (int)((y + hCALsizeY / 2) / (towerSize / 7)); + col = (int)((x + hCALsizeX / 2) / (towerSize / 7)); + } else { + row = (int)((y + hCALsizeY / 2) / (towerSize)); + col = (int)((x + hCALsizeX / 2) / (towerSize)); + } + } else { + row = (int)((y + getFOCALSizeY() / 2) / mVirtualSegmentComposition[segment].mPadSize); + // if it is the towers right and left of the beam pipe, adjust x so the offset is removed + // if(y < 4.2 && y > - 4.2) { // TO BE set from outside or somewhere else -4,4 is the y position of the middle towers + // x = x < 0 ? x + GetMiddleTowerOffset() : x - GetMiddleTowerOffset(); + // } + col = (int)((x + getFOCALSizeX() / 2) / mVirtualSegmentComposition[segment].mPadSize); + } + return {true, col, row, layer, segment}; +} + +//_______________________________________________________________________ +std::tuple Geometry::getXYZFromColRowSeg(int col, int row, int segment) const +{ + + double x = 0.0, y = 0.0, z = 0.0; + if (segment > mVirtualNSegments) { + return {false, x, y, z}; + } + + if (getVirtualIsHCal(segment)) { + float towerSize = getHCALTowerSize(); + double hCALsizeX = getHCALTowersInX() * towerSize; + double hCALsizeY = getHCALTowersInY() * towerSize; + + if (!mUseSandwichHCAL) { + y = -1 * hCALsizeY / 2 + ((float)row + 0.5) * (towerSize / 7); + x = -1 * hCALsizeX / 2 + ((float)col + 0.5) * (towerSize / 7); + } else { + y = -1 * hCALsizeY / 2 + ((float)row + 0.5) * (towerSize); + x = -1 * hCALsizeX / 2 + ((float)col + 0.5) * (towerSize); + } + } else { + y = -1 * getFOCALSizeY() / 2 + ((float)row + 0.5) * mVirtualSegmentComposition[segment].mPadSize; + x = -1 * getFOCALSizeX() / 2 + ((float)col + 0.5) * mVirtualSegmentComposition[segment].mPadSize; + // Middle towers offset + // if(y < 4.2 && y > - 4.2) { // TO BE set from outside or somewhere else -4,4 is the y position of the middle towers + // x = x < 0 ? x - GetMiddleTowerOffset() : x + GetMiddleTowerOffset(); + // } + } + + if (std::abs(x) > (getFOCALSizeX() + 2 * getMiddleTowerOffset()) / 2) { + return {false, x, y, z}; + } + if (std::abs(y) > getFOCALSizeY() / 2) { + return {false, x, y, z}; + } + z = getVirtualSegmentZ(segment); + return {true, x, y, z}; +} + +//_______________________________________________________________________ +std::tuple Geometry::getVirtualNColRow(int segment) const +{ + + // ix + iy*mGlobal_PAD_NX + itowerX*mGlobal_PAD_NX*mGlobal_PAD_NY + itowerY*mGlobal_PAD_NX_Tower*mGlobal_PAD_NX*mGlobal_PAD_NY + int nCol = -1, nRow = -1; + if (mVirtualSegmentComposition.size() == 0) { + return {false, nCol, nRow}; + } + if ((segment < 0) || (segment >= mVirtualNSegments)) { + return {false, nCol, nRow}; + } + nCol = (int)(getFOCALSizeX() / mVirtualSegmentComposition[segment].mPadSize + 0.001); + nRow = (int)(getFOCALSizeY() / mVirtualSegmentComposition[segment].mPadSize + 0.001); + if (getVirtualIsHCal(segment)) { + if (!mUseSandwichHCAL) { + nCol = getHCALTowersInX() * 7; // To be set from outside (number of channels in each tower on x) + nRow = getHCALTowersInY() * 7; // To be set from outside (number of channels in each tower on y) + } else { + nCol = getHCALTowersInX(); + nRow = getHCALTowersInY(); + } + } + return {true, nCol, nRow}; +} + +//_______________________________________________________________________ +int Geometry::getVirtualNSegments() const +{ + + return mVirtualNSegments; +} + +//_______________________________________________________________________ +std::tuple Geometry::getVirtualLayerSegment(float z) const +{ + + int layer = -1; + int segment = -1; + + z = z - getFOCALZ0() + getFOCALSizeZ() / 2; // z from front face (excluding fron matter) + float emLayersZ = mNPadLayers * mPadLayerThickness + mNPixelLayers * mPixelLayerThickness; // Pixel layers replace pad layers + if (z < emLayersZ) { + layer = mNPadLayers + mNPixelLayers - 1; + while (layer >= 0 && z < mLocalLayerZ[layer]) { + layer--; + } + } else { + z = z - emLayersZ; + layer = int(z / mHCalLayerThickness) + mNPadLayers + mNPixelLayers; + } + + if ((layer < 0) || (layer >= (mNPadLayers + mNPixelLayers + mNHCalLayers))) { + return {false, layer, segment}; + } + + segment = -1; + for (int nSeg = 0; nSeg < mVirtualNSegments; nSeg++) { + if ((layer >= mVirtualSegmentComposition[nSeg].mMinLayer) && (layer <= mVirtualSegmentComposition[nSeg].mMaxLayer)) { + segment = nSeg; + break; + } + } + + if (segment == mVirtualNSegments) { + return {false, layer, segment}; + } + return {true, layer, segment}; +} + +//_______________________________________________________________________ +std::tuple Geometry::getVirtualSegmentFromLayer(int layer) const +{ + + int segment = -1; + for (int nSeg = 0; nSeg < mVirtualNSegments; nSeg++) { + // cout << "Segment boundaries " << nSeg << " : " << mVirtualSegmentComposition[nSeg].fMinLayer << " " << mVirtualSegmentComposition[nSeg].fMaxLayer << endl; + if ((layer >= mVirtualSegmentComposition[nSeg].mMinLayer) && (layer <= mVirtualSegmentComposition[nSeg].mMaxLayer)) { + segment = nSeg; + break; + } + } + if (segment == mVirtualNSegments) { + return {false, segment}; + } + return {true, segment}; +} + +//_______________________________________________________________________ +int Geometry::getVirtualSegment(float z) const +{ + auto [status, layer, segment] = getVirtualLayerSegment(z); + return segment; +} + +//_______________________________________________________________________ +float Geometry::getVirtualPadSize(int segment) const +{ + if (mVirtualSegmentComposition.size() == 0) { + return -1; + } + return mVirtualSegmentComposition[segment].mPadSize; +} + +//_______________________________________________________________________ +float Geometry::getVirtualRelativeSensitiveThickness(int segment) const +{ + + if (mVirtualSegmentComposition.size() == 0) { + return -1; + } + return mVirtualSegmentComposition[segment].mRelativeSensitiveThickness; +} + +//_______________________________________________________________________ +float Geometry::getVirtualPixelTreshold(int segment) const +{ + + if (mVirtualSegmentComposition.size() == 0) { + return -1; + } + return mVirtualSegmentComposition[segment].mPixelTreshold; +} + +//________________________________________________________________________ +float Geometry::getVirtualSegmentSizeZ(int segment) const +{ + + if (mVirtualSegmentComposition.size() == 0) { + return -1; + } + + float size = 0; + for (int nLay = mVirtualSegmentComposition[segment].mMinLayer; nLay <= mVirtualSegmentComposition[segment].mMaxLayer; nLay++) { + size += mLayerThickness[nLay]; + } + return size; +} + +//________________________________________________________________________ +float Geometry::getVirtualSegmentZ(int segment) const +{ + + if (mVirtualSegmentComposition.size() == 0) { + return -1; + } + + float before = 0; + float thickness = 0; + + for (int nLay = 0; nLay < mVirtualSegmentComposition[segment].mMinLayer; nLay++) { + before += mLayerThickness[nLay]; + } + for (int nLay = mVirtualSegmentComposition[segment].mMinLayer; nLay <= mVirtualSegmentComposition[segment].mMaxLayer; nLay++) { + thickness += mLayerThickness[nLay]; + } + return getFOCALZ0() - getFOCALSizeZ() / 2 + before + thickness / 2; +} + +//________________________________________________________________________ +bool Geometry::getVirtualIsPixel(int segment) const +{ + + if (mVirtualSegmentComposition.size() == 0) { + return false; + } + + if ((segment < 0) || (segment >= mVirtualNSegments)) { + return false; + } + + return (mVirtualSegmentComposition[segment].mIsPixel == 1); +} + +//________________________________________________________________________ +bool Geometry::getVirtualIsHCal(int segment) const +{ + + if (mVirtualSegmentComposition.size() == 0) { + return false; + } + + if ((segment < 0) || (segment >= mVirtualNSegments)) { + return false; + } + return (mVirtualSegmentComposition[segment].mIsPixel == 2); +} + +//________________________________________________________________________ +int Geometry::getVirtualNLayersInSegment(int segment) const +{ + // + // Get the number of layers in a given segment + // + if (mVirtualSegmentComposition.size() == 0) { + return -1; + } + + if ((segment < 0) || (segment >= mVirtualNSegments)) { + return -1; + } + return (mVirtualSegmentComposition[segment].mMaxLayer - mVirtualSegmentComposition[segment].mMinLayer + 1); +} + +//_______________________________________________________________________ +int Geometry::getVirtualMinLayerInSegment(int segment) const +{ + // + // Get the number of first layer in a given segment + // + if (mVirtualSegmentComposition.size() == 0) { + return -1; + } + + if ((segment < 0) || (segment >= mVirtualNSegments)) { + return -1; + } + return mVirtualSegmentComposition[segment].mMinLayer; +} + +//_______________________________________________________________________ +int Geometry::getVirtualMaxLayerInSegment(int segment) const +{ + // + // Get the number of first layer in a given segment + // + if (mVirtualSegmentComposition.size() == 0) { + return -1; + } + + if ((segment < 0) || (segment >= mVirtualNSegments)) { + return -1; + } + return mVirtualSegmentComposition[segment].mMaxLayer; +} From 641cf737cf6bc9ef0ea0b4a82160f4b7c385a388 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 24 May 2024 10:51:23 +0200 Subject: [PATCH 0249/2997] Reduce minimum distance to IFC to apply masking error from 2cm to 1.5 cm --- GPU/GPUTracking/Definitions/GPUSettingsList.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 777ea1e70b0d8..cf91f7ce45f88 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -56,7 +56,7 @@ AddOptionRTC(sysClusErrorIFCCEZRegion, float, -5.f, "", 0, "Systematic cluster e AddOptionRTC(sysClusErrorslopeIFCCEZ, float, 1.f / 2.0f, "", 0, "Systematic cluster error parameterization IFCCE z Region Sigma Inverse") AddOptionRTC(sysClusErrorNormIFC, float, 0.5f, "", 0, "Systematic cluster error parameterization IFC normalization") AddOptionRTC(sysClusErrorSlopeIFC, float, 0.2f, "", 0, "Systematic cluster error parameterization IFC slope") -AddOptionRTC(sysClusErrorMinDist, float, 2.f, "", 0, "Systematic cluster error parameterization IFC Minimum Distance") +AddOptionRTC(sysClusErrorMinDist, float, 1.5f, "", 0, "Systematic cluster error parameterization IFC Minimum Distance") AddOptionRTC(sysClusErrorMaskError, float, 5.f, "", 0, "Systematic cluster error parameterization IFC Large Error for masking") AddOptionRTC(sysClusErrorC12Norm, float, 5.3333333e-06f, "", 0, "Systematic cluster for Sector C1/2 normalization") AddOptionRTC(sysClusErrorC12Box, float, 1.1e-05f, "", 0, "Systematic cluster for Sector C1/2 box size") From a8ae2132a9b711968d480f620b59e90e170ef931 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 24 May 2024 14:27:24 +0200 Subject: [PATCH 0250/2997] track getDCAY/Z (slow) method for interactive tree drawing --- .../TrackParametrization.h | 2 ++ .../src/TrackParametrization.cxx | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index 41d3efc2cfd2d..2ef5577ec6bf2 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -218,6 +218,8 @@ class TrackParametrization GPUd() value_t getSnpAt(value_t alpha, value_t xk, value_t b) const; GPUd() value_t getPhiAt(value_t xk, value_t b) const; GPUd() value_t getPhiPosAt(value_t xk, value_t b) const; + GPUd() value_t getDCAYtoMV(value_t b, value_t xmv = 0.f, value_t ymv = 0.f, value_t zmv = 0.f) const; + GPUd() value_t getDCAZtoMV(value_t b, value_t xmv = 0.f, value_t ymv = 0.f, value_t zmv = 0.f) const; GPUd() math_utils::Point3D getXYZGloAt(value_t xk, value_t b, bool& ok) const; // parameters manipulation diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index ba36045f18606..fe6c8f7d89cbb 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -936,6 +936,24 @@ GPUd() typename o2::track::TrackParametrization::yzerr_t TrackParametri {v.getSigmaX2() * sn2 + dsxysncs + v.getSigmaY2() * cs2, (sn + cs) * v.getSigmaYZ(), v.getSigmaZ2()}}; } +//______________________________________________ +template +GPUd() typename TrackParametrization::value_t TrackParametrization::getDCAYtoMV(value_t b, value_t xmv, value_t ymv, value_t zmv) const +{ + auto ttmp = *this; + dim2_t dca; + return ttmp.propagateParamToDCA({xmv, ymv, zmv}, b, &dca) ? dca[0] : -9999.; +} + +//______________________________________________ +template +GPUd() typename TrackParametrization::value_t TrackParametrization::getDCAZtoMV(value_t b, value_t xmv, value_t ymv, value_t zmv) const +{ + auto ttmp = *this; + dim2_t dca; + return ttmp.propagateParamToDCA({xmv, ymv, zmv}, b, &dca) ? dca[1] : -9999.; +} + namespace o2::track { template class TrackParametrization; From bf62a5437f75fbb125136ced8a42f7d686a92bcb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 24 May 2024 11:34:43 +0200 Subject: [PATCH 0251/2997] DPL: adapt to support new FairLogger --- Framework/DataTakingSupport/src/Plugin.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/DataTakingSupport/src/Plugin.cxx b/Framework/DataTakingSupport/src/Plugin.cxx index e414b1e49b57f..f719fd5ef7d1f 100644 --- a/Framework/DataTakingSupport/src/Plugin.cxx +++ b/Framework/DataTakingSupport/src/Plugin.cxx @@ -117,8 +117,8 @@ auto createInfoLoggerSinkHelper(InfoLogger* logger, InfoLoggerContext* ctx) severity, level, InfoLogger::undefinedMessageOption.errorCode, - metadata.file.c_str(), - atoi(metadata.line.c_str())}; + metadata.file.data(), + atoi(metadata.line.data())}; if (logger) { logger->log(opt, *ctx, "%s", content.c_str()); From 5b42afc2eee9d1ca732e1a3bf3af015b58a78104 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 24 May 2024 21:55:35 +0200 Subject: [PATCH 0252/2997] DPL: improve signposts for adding parts --- Framework/Core/src/DataAllocator.cxx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index fe38283d5e2de..0bf0f86f812ec 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -21,6 +21,8 @@ #include "Framework/DeviceSpec.h" #include "Framework/StreamContext.h" #include "Framework/Signpost.h" +#include "Headers/DataHeader.h" +#include "Headers/DataHeaderHelpers.h" #include "Headers/Stack.h" #include @@ -131,13 +133,13 @@ void DataAllocator::addPartToContext(RouteIndex routeIndex, fair::mq::MessagePtr { auto headerMessage = headerMessageFromOutput(spec, routeIndex, serializationMethod, 0); O2_SIGNPOST_ID_FROM_POINTER(pid, parts, headerMessage->GetData()); - O2_SIGNPOST_START(parts, pid, "parts", "addPartToContext %p", headerMessage->GetData()); - // FIXME: this is kind of ugly, we know that we can change the content of the // header message because we have just created it, but the API declares it const const DataHeader* cdh = o2::header::get(headerMessage->GetData()); auto* dh = const_cast(cdh); dh->payloadSize = payloadMessage->GetSize(); + O2_SIGNPOST_START(parts, pid, "parts", "addPartToContext %{public}s@%p %" PRIu64, + cdh ? fmt::format("{}/{}/{}", cdh->dataOrigin, cdh->dataDescription, cdh->subSpecification).c_str() : "unknown", headerMessage->GetData(), dh->payloadSize); auto& context = mRegistry.get(); // make_scoped creates the context object inside of a scope handler, since it goes out of // scope immediately, the created object is scheduled and can be directly sent if the context @@ -153,8 +155,10 @@ void DataAllocator::adopt(const Output& spec, std::string* ptr) // the correct payload size is set later when sending the // StringContext, see DataProcessor::doSend auto header = headerMessageFromOutput(spec, routeIndex, o2::header::gSerializationMethodNone, 0); + const DataHeader* cdh = o2::header::get(header->GetData()); O2_SIGNPOST_ID_FROM_POINTER(pid, parts, header->GetData()); - O2_SIGNPOST_START(parts, pid, "parts", "addPartToContext %p", header->GetData()); + O2_SIGNPOST_START(parts, pid, "parts", "addPartToContext %{public}s@%p %" PRIu64, + cdh ? fmt::format("{}/{}/{}", cdh->dataOrigin, cdh->dataDescription, cdh->subSpecification).c_str() : "unknown", header->GetData(), cdh->payloadSize); mRegistry.get().addString(std::move(header), std::move(payload), routeIndex); assert(payload.get() == nullptr); } @@ -211,8 +215,10 @@ void DataAllocator::adopt(const Output& spec, LifetimeHolder& tb) auto& timingInfo = mRegistry.get(); RouteIndex routeIndex = matchDataHeader(spec, timingInfo.timeslice); auto header = headerMessageFromOutput(spec, routeIndex, o2::header::gSerializationMethodArrow, 0); + const DataHeader* cdh = o2::header::get(header->GetData()); O2_SIGNPOST_ID_FROM_POINTER(pid, parts, header->GetData()); - O2_SIGNPOST_START(parts, pid, "parts", "adopt %p", header->GetData()); + O2_SIGNPOST_START(parts, pid, "parts", "adopt %{public}s@%p %" PRIu64, + cdh ? fmt::format("{}/{}/{}", cdh->dataOrigin, cdh->dataDescription, cdh->subSpecification).c_str() : "unknown", header->GetData(), cdh->payloadSize); auto& context = mRegistry.get(); auto creator = [transport = context.proxy().getOutputTransport(routeIndex)](size_t s) -> std::unique_ptr { From b9f0dfc83878d02f054bed3f132ca74e6ccf312b Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 26 May 2024 22:42:32 +0200 Subject: [PATCH 0253/2997] Check for ITS cableID mapper out of bound access --- .../include/ITSMFTReconstruction/ChipMappingITS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h index b8add5f8106c2..9ba894208d45d 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/ChipMappingITS.h @@ -199,7 +199,7 @@ class ChipMappingITS uint8_t cableHW2Pos(uint8_t ruType, uint8_t hwid) const { return mCableHW2Pos[ruType][hwid]; } ///< convert HW cable ID to SW ID for given RU type (see ChipOnRUInfo.cableSW explanation) - uint8_t cableHW2SW(uint8_t ruType, uint8_t hwid) const { return mCableHW2SW[ruType][hwid]; } + uint8_t cableHW2SW(uint8_t ruType, uint8_t hwid) const { return hwid < mCableHW2SW[ruType].size() ? mCableHW2SW[ruType][hwid] : 0xff; } ///< convert cable iterator ID to the position on the ActiveLanes word in the GBT.header for given RU type; MFT lanes position compatible uint8_t cablePos(uint8_t ruType, uint8_t id) const { return mCablePos[ruType][id]; } From 8c7538f2166965488c69445af4c9ade003b35756 Mon Sep 17 00:00:00 2001 From: cima22 Date: Wed, 13 Mar 2024 16:29:12 +0100 Subject: [PATCH 0254/2997] GPU TPC: Decompression: attached clusters decoding run in multiple streams, unattached clusters input transfer in separate stream --- .../DataCompression/GPUTPCDecompression.cxx | 1 + .../DataCompression/GPUTPCDecompression.h | 1 + .../GPUTPCDecompressionKernels.cxx | 33 +++++-- .../GPUTPCDecompressionKernels.h | 9 +- .../Definitions/GPUDefGPUParameters.h | 7 ++ .../Global/GPUChainTrackingCompression.cxx | 90 ++++++++++++------- GPU/GPUTracking/kernels.cmake | 3 +- 7 files changed, 96 insertions(+), 48 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCDecompression.cxx b/GPU/GPUTracking/DataCompression/GPUTPCDecompression.cxx index a204d20463b18..1d71594523b35 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCDecompression.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCDecompression.cxx @@ -80,6 +80,7 @@ void* GPUTPCDecompression::SetPointersTmpNativeBuffersOutput(void* mem) void* GPUTPCDecompression::SetPointersTmpNativeBuffersInput(void* mem) { computePointerWithAlignment(mem, mUnattachedClustersOffsets, NSLICES * GPUCA_ROW_COUNT); + computePointerWithAlignment(mem, mAttachedClustersOffsets, mInputGPU.nTracks); return mem; } diff --git a/GPU/GPUTracking/DataCompression/GPUTPCDecompression.h b/GPU/GPUTracking/DataCompression/GPUTPCDecompression.h index 269f0d7b373f4..a8f058c62891e 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCDecompression.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCDecompression.h @@ -64,6 +64,7 @@ class GPUTPCDecompression : public GPUProcessor unsigned int mMaxNativeClustersPerBuffer; unsigned int* mNativeClustersIndex; unsigned int* mUnattachedClustersOffsets; + unsigned int* mAttachedClustersOffsets; o2::tpc::ClusterNative* mTmpNativeClusters; o2::tpc::ClusterNative* mNativeClustersBuffer; diff --git a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx index 63627d3dce476..0536f3384d2f3 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx @@ -22,25 +22,20 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace o2::tpc; template <> -GPUdii() void GPUTPCDecompressionKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) +GPUdii() void GPUTPCDecompressionKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors, int trackStart, int trackEnd) { GPUTPCDecompression& GPUrestrict() decompressor = processors.tpcDecompressor; CompressedClusters& GPUrestrict() cmprClusters = decompressor.mInputGPU; const GPUParam& GPUrestrict() param = processors.param; - unsigned int offset = 0, lasti = 0; const unsigned int maxTime = (param.par.continuousMaxTimeBin + 1) * ClusterNative::scaleTimePacked - 1; - for (unsigned int i = get_global_id(0); i < cmprClusters.nTracks; i += get_global_size(0)) { - while (lasti < i) { - offset += cmprClusters.nTrackClusters[lasti++]; - } - lasti++; - decompressTrack(cmprClusters, param, maxTime, i, offset, decompressor); + for (unsigned int i = trackStart + get_global_id(0); i < trackEnd; i += get_global_size(0)) { + decompressTrack(cmprClusters, param, maxTime, i, decompressor.mAttachedClustersOffsets[i], decompressor); } } -GPUdii() void GPUTPCDecompressionKernels::decompressTrack(CompressedClusters& cmprClusters, const GPUParam& param, const unsigned int maxTime, const unsigned int trackIndex, unsigned int& clusterOffset, GPUTPCDecompression& decompressor) +GPUdii() void GPUTPCDecompressionKernels::decompressTrack(CompressedClusters& cmprClusters, const GPUParam& param, const unsigned int maxTime, const unsigned int trackIndex, unsigned int clusterOffset, GPUTPCDecompression& decompressor) { float zOffset = 0; unsigned int slice = cmprClusters.sliceA[trackIndex]; @@ -194,6 +189,26 @@ GPUdi() void GPUTPCDecompressionKernels::decompressorMemcpyBasic(T* GPUrestrict( } } +template <> +GPUdii() void GPUTPCDecompressionUtilKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) +{ + GPUTPCDecompression& GPUrestrict() decompressor = processors.tpcDecompressor; + CompressedClusters& GPUrestrict() cmprClusters = decompressor.mInputGPU; + ClusterNative* GPUrestrict() clusterBuffer = decompressor.mNativeClustersBuffer; + const ClusterNativeAccess* outputAccess = processors.ioPtrs.clustersNative; + + unsigned int* offsets = decompressor.mUnattachedClustersOffsets; + for (unsigned int i = get_global_id(0); i < GPUCA_NSLICES * GPUCA_ROW_COUNT; i += get_global_size(0)) { + unsigned int slice = i / GPUCA_ROW_COUNT; + unsigned int row = i % GPUCA_ROW_COUNT; + unsigned int tmpBufferIndex = computeLinearTmpBufferIndex(slice, row, decompressor.mMaxNativeClustersPerBuffer); + ClusterNative* buffer = clusterBuffer + outputAccess->clusterOffset[slice][row]; + if (decompressor.mNativeClustersIndex[i] != 0) { + decompressorMemcpyBasic(buffer, decompressor.mTmpNativeClusters + tmpBufferIndex, decompressor.mNativeClustersIndex[i]); + } + } +} + template <> GPUdii() void GPUTPCDecompressionUtilKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) { diff --git a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.h b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.h index 39f9e4e0b4412..4d21bcaef1ab8 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.h @@ -43,9 +43,9 @@ class GPUTPCDecompressionKernels : public GPUKernelTemplate step1unattached = 1, }; - template - GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() processors); - GPUd() static void decompressTrack(o2::tpc::CompressedClusters& cmprClusters, const GPUParam& param, const unsigned int maxTime, const unsigned int trackIndex, unsigned int& clusterOffset, GPUTPCDecompression& decompressor); + template + GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() processors, Args... args); + GPUd() static void decompressTrack(o2::tpc::CompressedClusters& cmprClusters, const GPUParam& param, const unsigned int maxTime, const unsigned int trackIndex, unsigned int clusterOffset, GPUTPCDecompression& decompressor); GPUdi() static o2::tpc::ClusterNative decompressTrackStore(const o2::tpc::CompressedClusters& cmprClusters, const unsigned int clusterOffset, unsigned int slice, unsigned int row, unsigned int pad, unsigned int time, GPUTPCDecompression& decompressor); GPUdi() static void decompressHits(const o2::tpc::CompressedClusters& cmprClusters, const unsigned int start, const unsigned int end, o2::tpc::ClusterNative* clusterNativeBuffer); @@ -62,7 +62,8 @@ class GPUTPCDecompressionUtilKernels : public GPUKernelTemplate { public: enum K : int { - sortPerSectorRow = 0 + gatherAttachedClusters = 0, + sortPerSectorRow = 1, }; template diff --git a/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h b/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h index 4bb8303ee9a96..9bc51f8a325ee 100644 --- a/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h +++ b/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h @@ -199,6 +199,8 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 64, 2 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 3 + #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 128, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 288, 2 #define GPUCA_LB_GPUTPCCFCheckPadBaseline 64,8 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillIndexMap 448 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillFromDigits 448 @@ -263,6 +265,8 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 128 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 128, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 288, 2 #define GPUCA_LB_COMPRESSION_GATHER 1024 #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 4 #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 20 @@ -337,6 +341,9 @@ #ifndef GPUCA_LB_GPUTPCDecompressionUtilKernels_sortPerSectorRow #define GPUCA_LB_GPUTPCDecompressionUtilKernels_sortPerSectorRow 256 #endif +#ifndef GPUCA_LB_GPUTPCDecompressionUtilKernels_computeAttachedOffsets + #define GPUCA_LB_GPUTPCDecompressionUtilKernels_computeAttachedOffsets 256 +#endif #ifndef GPUCA_LB_GPUTPCCFDecodeZS #define GPUCA_LB_GPUTPCCFDecodeZS 128, 4 #endif diff --git a/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx b/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx index 4c99523da8f1d..a02be0461f416 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx @@ -16,6 +16,8 @@ #include "GPULogging.h" #include "GPUO2DataTypes.h" #include "GPUTrackingInputProvider.h" +#include +#include #ifdef GPUCA_HAVE_O2HEADERS #include "GPUTPCCFChainContext.h" @@ -205,7 +207,8 @@ int GPUChainTracking::RunTPCCompression() int GPUChainTracking::RunTPCDecompression() { -#ifdef GPUCA_HAVE_O2HEADERS + auto start = std::chrono::high_resolution_clock::now(); +//#ifdef GPUCA_HAVE_O2HEADERS if (GetProcessingSettings().tpcUseOldCPUDecoding) { const auto& threadContext = GetThreadContext(); TPCClusterDecompressor decomp; @@ -244,6 +247,8 @@ int GPUChainTracking::RunTPCDecompression() CompressedClusters& inputGPU = Decompressor.mInputGPU; CompressedClusters& inputGPUShadow = DecompressorShadow.mInputGPU; + int inputStream = 0; + int unattachedStream = 4; inputGPU.nAttachedClusters = cmprClsHost.nAttachedClusters; inputGPU.nUnattachedClusters = cmprClsHost.nUnattachedClusters; inputGPU.nTracks = cmprClsHost.nTracks; @@ -252,33 +257,10 @@ int GPUChainTracking::RunTPCDecompression() inputGPU.nComppressionModes = param().rec.tpc.compressionTypeMask; inputGPU.solenoidBz = param().bzkG; inputGPU.maxTimeBin = param().par.continuousMaxTimeBin; + SetupGPUProcessor(&Decompressor, true); - WriteToConstantMemory(myStep, (char*)&processors()->tpcDecompressor - (char*)processors(), &DecompressorShadow, sizeof(DecompressorShadow), 0); - int inputStream = 0; - bool toGPU = true; - GPUMemCpy(myStep, inputGPUShadow.nTrackClusters, cmprClsHost.nTrackClusters, cmprClsHost.nTracks * sizeof(cmprClsHost.nTrackClusters[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.qTotU, cmprClsHost.qTotU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.qTotU[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.qMaxU, cmprClsHost.qMaxU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.qMaxU[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.flagsU, cmprClsHost.flagsU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.flagsU[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.padDiffU, cmprClsHost.padDiffU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.padDiffU[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.timeDiffU, cmprClsHost.timeDiffU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.timeDiffU[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.sigmaPadU, cmprClsHost.sigmaPadU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.sigmaPadU[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.sigmaTimeU, cmprClsHost.sigmaTimeU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.sigmaTimeU[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.nSliceRowClusters, cmprClsHost.nSliceRowClusters, NSLICES * GPUCA_ROW_COUNT * sizeof(cmprClsHost.nSliceRowClusters[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.qTotA, cmprClsHost.qTotA, cmprClsHost.nAttachedClusters * sizeof(cmprClsHost.qTotA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.qMaxA, cmprClsHost.qMaxA, cmprClsHost.nAttachedClusters * sizeof(cmprClsHost.qMaxA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.flagsA, cmprClsHost.flagsA, cmprClsHost.nAttachedClusters * sizeof(cmprClsHost.flagsA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.rowDiffA, cmprClsHost.rowDiffA, (cmprClsHost.nAttachedClusters - cmprClsHost.nTracks) * sizeof(cmprClsHost.rowDiffA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.sliceLegDiffA, cmprClsHost.sliceLegDiffA, (cmprClsHost.nAttachedClusters - cmprClsHost.nTracks) * sizeof(cmprClsHost.sliceLegDiffA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.padResA, cmprClsHost.padResA, (cmprClsHost.nAttachedClusters - cmprClsHost.nTracks) * sizeof(cmprClsHost.padResA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.timeResA, cmprClsHost.timeResA, (cmprClsHost.nAttachedClusters - cmprClsHost.nTracks) * sizeof(cmprClsHost.timeResA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.sigmaPadA, cmprClsHost.sigmaPadA, cmprClsHost.nAttachedClusters * sizeof(cmprClsHost.sigmaPadA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.sigmaTimeA, cmprClsHost.sigmaTimeA, cmprClsHost.nAttachedClusters * sizeof(cmprClsHost.sigmaTimeA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.qPtA, cmprClsHost.qPtA, cmprClsHost.nTracks * sizeof(cmprClsHost.qPtA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.rowA, cmprClsHost.rowA, cmprClsHost.nTracks * sizeof(cmprClsHost.rowA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.sliceA, cmprClsHost.sliceA, cmprClsHost.nTracks * sizeof(cmprClsHost.sliceA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.timeA, cmprClsHost.timeA, cmprClsHost.nTracks * sizeof(cmprClsHost.timeA[0]), inputStream, toGPU); - GPUMemCpy(myStep, inputGPUShadow.padA, cmprClsHost.padA, cmprClsHost.nTracks * sizeof(cmprClsHost.padA[0]), inputStream, toGPU); + WriteToConstantMemory(myStep, (char*)&processors()->tpcDecompressor - (char*)processors(), &DecompressorShadow, sizeof(DecompressorShadow), inputStream); + inputGPU.nTrackClusters = cmprClsHost.nTrackClusters; inputGPU.qTotU = cmprClsHost.qTotU; inputGPU.qMaxU = cmprClsHost.qMaxU; @@ -303,8 +285,45 @@ int GPUChainTracking::RunTPCDecompression() inputGPU.timeA = cmprClsHost.timeA; inputGPU.padA = cmprClsHost.padA; - runKernel(GetGridAutoStep(inputStream, RecoStep::TPCDecompression), DecompressorShadow.mNativeClustersIndex, NSLICES * GPUCA_ROW_COUNT * sizeof(DecompressorShadow.mNativeClustersIndex[0])); - runKernel(GetGridAuto(inputStream)); + bool toGPU = true; + runKernel(GetGridAutoStep(inputStream, RecoStep::TPCDecompression), krnlRunRangeNone, &mEvents->init, DecompressorShadow.mNativeClustersIndex, NSLICES * GPUCA_ROW_COUNT * sizeof(DecompressorShadow.mNativeClustersIndex[0])); + std::exclusive_scan(cmprClsHost.nTrackClusters, cmprClsHost.nTrackClusters + cmprClsHost.nTracks, Decompressor.mAttachedClustersOffsets,0u); + int nStreams = 4; + for (unsigned int iStream = 0; iStream < nStreams; ++iStream) { + unsigned int startTrack = cmprClsHost.nTracks / nStreams * iStream; + unsigned int endTrack = cmprClsHost.nTracks / nStreams * (iStream + 1) + (iStream < nStreams - 1 ? 0 : cmprClsHost.nTracks % nStreams); + unsigned int numTracks = endTrack - startTrack; + unsigned int* offsets = Decompressor.mAttachedClustersOffsets; + unsigned int numClusters = (endTrack == cmprClsHost.nTracks ? offsets[endTrack - 1] + cmprClsHost.nTrackClusters[endTrack - 1] : offsets[endTrack]) - offsets[startTrack]; + unsigned int numClustersRed = numClusters - numTracks; + GPUMemCpy(myStep, DecompressorShadow.mAttachedClustersOffsets + startTrack, Decompressor.mAttachedClustersOffsets + startTrack, numTracks * sizeof(Decompressor.mAttachedClustersOffsets[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.nTrackClusters + startTrack, cmprClsHost.nTrackClusters + startTrack, numTracks * sizeof(cmprClsHost.nTrackClusters[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.qTotA + offsets[startTrack], cmprClsHost.qTotA + offsets[startTrack], numClusters * sizeof(cmprClsHost.qTotA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.qMaxA + offsets[startTrack], cmprClsHost.qMaxA + offsets[startTrack], numClusters * sizeof(cmprClsHost.qMaxA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.flagsA + offsets[startTrack], cmprClsHost.flagsA + offsets[startTrack], numClusters * sizeof(cmprClsHost.flagsA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.rowDiffA + offsets[startTrack] - startTrack, cmprClsHost.rowDiffA + offsets[startTrack] - startTrack, numClustersRed * sizeof(cmprClsHost.rowDiffA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.sliceLegDiffA + offsets[startTrack] - startTrack, cmprClsHost.sliceLegDiffA + offsets[startTrack] - startTrack, numClustersRed * sizeof(cmprClsHost.sliceLegDiffA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.padResA + offsets[startTrack] - startTrack, cmprClsHost.padResA + offsets[startTrack] - startTrack, numClustersRed * sizeof(cmprClsHost.padResA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.timeResA + offsets[startTrack] - startTrack, cmprClsHost.timeResA + offsets[startTrack] - startTrack, numClustersRed * sizeof(cmprClsHost.timeResA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.sigmaPadA + offsets[startTrack], cmprClsHost.sigmaPadA + offsets[startTrack], numClusters * sizeof(cmprClsHost.sigmaPadA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.sigmaTimeA + offsets[startTrack], cmprClsHost.sigmaTimeA + offsets[startTrack], numClusters * sizeof(cmprClsHost.sigmaTimeA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.qPtA + startTrack, cmprClsHost.qPtA + startTrack, numTracks * sizeof(cmprClsHost.qPtA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.rowA + startTrack, cmprClsHost.rowA + startTrack, numTracks * sizeof(cmprClsHost.rowA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.sliceA + startTrack, cmprClsHost.sliceA + startTrack, numTracks * sizeof(cmprClsHost.sliceA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.timeA + startTrack, cmprClsHost.timeA + startTrack, numTracks * sizeof(cmprClsHost.timeA[0]), iStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.padA + startTrack, cmprClsHost.padA + startTrack, numTracks * sizeof(cmprClsHost.padA[0]), iStream, toGPU); + + runKernel({46,64,iStream}, krnlRunRangeNone, {&mEvents->stream[iStream], &mEvents->init}, startTrack, endTrack); + } + + GPUMemCpy(myStep, inputGPUShadow.nSliceRowClusters, cmprClsHost.nSliceRowClusters, NSLICES * GPUCA_ROW_COUNT * sizeof(cmprClsHost.nSliceRowClusters[0]), unattachedStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.qTotU, cmprClsHost.qTotU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.qTotU[0]), unattachedStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.qMaxU, cmprClsHost.qMaxU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.qMaxU[0]), unattachedStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.flagsU, cmprClsHost.flagsU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.flagsU[0]), unattachedStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.padDiffU, cmprClsHost.padDiffU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.padDiffU[0]), unattachedStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.timeDiffU, cmprClsHost.timeDiffU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.timeDiffU[0]), unattachedStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.sigmaPadU, cmprClsHost.sigmaPadU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.sigmaPadU[0]), unattachedStream, toGPU); + GPUMemCpy(myStep, inputGPUShadow.sigmaTimeU, cmprClsHost.sigmaTimeU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.sigmaTimeU[0]), unattachedStream, toGPU); mInputsHost->mNClusterNative = mInputsShadow->mNClusterNative = cmprClsHost.nAttachedClusters + cmprClsHost.nUnattachedClusters; AllocateRegisteredMemory(mInputsHost->mResourceClusterNativeOutput, mSubOutputControls[GPUTrackingOutputs::getIndex(&GPUTrackingOutputs::clustersNative)]); @@ -312,7 +331,7 @@ int GPUChainTracking::RunTPCDecompression() DecompressorShadow.mNativeClustersBuffer = mInputsShadow->mPclusterNativeBuffer; Decompressor.mNativeClustersBuffer = mInputsHost->mPclusterNativeOutput; WriteToConstantMemory(myStep, (char*)&processors()->tpcDecompressor - (char*)processors(), &DecompressorShadow, sizeof(DecompressorShadow), inputStream); - TransferMemoryResourceLinkToHost(RecoStep::TPCDecompression, Decompressor.mResourceTmpIndexes, inputStream); + TransferMemoryResourceLinkToHost(RecoStep::TPCDecompression, Decompressor.mResourceTmpIndexes, inputStream,nullptr,mEvents->stream,nStreams); SynchronizeStream(inputStream); unsigned int offset = 0; @@ -338,7 +357,7 @@ int GPUChainTracking::RunTPCDecompression() *mInputsHost->mPclusterNativeAccess = *mClusterNativeAccess; processorsShadow()->ioPtrs.clustersNative = mInputsShadow->mPclusterNativeAccess; WriteToConstantMemory(RecoStep::TPCDecompression, (char*)&processors()->ioPtrs - (char*)processors(), &processorsShadow()->ioPtrs, sizeof(processorsShadow()->ioPtrs), inputStream); - TransferMemoryResourceLinkToGPU(RecoStep::TPCDecompression, mInputsHost->mResourceClusterNativeAccess, inputStream); + TransferMemoryResourceLinkToGPU(RecoStep::TPCDecompression, mInputsHost->mResourceClusterNativeAccess, inputStream, &mEvents->init); } mIOPtrs.clustersNative = mClusterNativeAccess.get(); mClusterNativeAccess->clustersLinear = mInputsHost->mPclusterNativeOutput; @@ -348,10 +367,13 @@ int GPUChainTracking::RunTPCDecompression() if (GetProcessingSettings().deterministicGPUReconstruction || GetProcessingSettings().debugLevel >= 4) { runKernel(GetGridAutoStep(inputStream, RecoStep::TPCDecompression)); } - SynchronizeStream(inputStream); - GPUMemCpy(RecoStep::TPCDecompression, (void*)mInputsHost->mPclusterNativeOutput, (void*)mInputsShadow->mPclusterNativeBuffer, sizeof(mInputsShadow->mPclusterNativeBuffer[0]) * mIOPtrs.clustersNative->nClustersTotal, inputStream, false); + GPUMemCpy(RecoStep::TPCDecompression, (void*)mInputsHost->mPclusterNativeOutput, (void*)mInputsShadow->mPclusterNativeBuffer, sizeof(mInputsShadow->mPclusterNativeBuffer[0]) * mIOPtrs.clustersNative->nClustersTotal, unattachedStream, false); + SynchronizeStream(unattachedStream); mRec->PopNonPersistentMemory(RecoStep::TPCDecompression, qStr2Tag("TPCDCMPR")); } -#endif +//#endif + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + LOGP(info,"Exec time: {} ms", duration.count() * 1e3); return 0; } diff --git a/GPU/GPUTracking/kernels.cmake b/GPU/GPUTracking/kernels.cmake index d4f5ca93e9def..c4347d48cd498 100644 --- a/GPU/GPUTracking/kernels.cmake +++ b/GPU/GPUTracking/kernels.cmake @@ -105,9 +105,10 @@ o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, buffered32" "GPUTPCCom o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, buffered64" "GPUTPCCompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, buffered128" "GPUTPCCompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, multiBlock" "GPUTPCCompressionKernels" LB simple) -o2_gpu_add_kernel("GPUTPCDecompressionKernels, step0attached" "= TPCDECOMPRESSION" LB simple) +o2_gpu_add_kernel("GPUTPCDecompressionKernels, step0attached" "= TPCDECOMPRESSION" LB simple int trackStart int trackEnd) o2_gpu_add_kernel("GPUTPCDecompressionKernels, step1unattached" "= TPCDECOMPRESSION" LB simple) o2_gpu_add_kernel("GPUTPCDecompressionUtilKernels, sortPerSectorRow" "GPUTPCDecompressionKernels" LB simple) +o2_gpu_add_kernel("GPUTPCDecompressionUtilKernels, computeAttachedOffsets" "GPUTPCDecompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCCFCheckPadBaseline" "= TPCCLUSTERFINDER" LB single) o2_gpu_add_kernel("GPUTPCCFChargeMapFiller, fillIndexMap" "= TPCCLUSTERFINDER" LB single) o2_gpu_add_kernel("GPUTPCCFChargeMapFiller, fillFromDigits" "= TPCCLUSTERFINDER" LB single) From 22be8c67d787bde6926c9b0771bd6eb2a865e255 Mon Sep 17 00:00:00 2001 From: cima22 Date: Wed, 27 Mar 2024 11:38:06 +0100 Subject: [PATCH 0255/2997] GPU TPC: Decompression: scattered DMA transfer to host tunings --- .../GPUTPCDecompressionKernels.cxx | 20 ----------- .../TPCClusterDecompressor.cxx | 2 +- .../Definitions/GPUDefGPUParameters.h | 7 ++-- .../Global/GPUChainTrackingCompression.cxx | 34 +++++++++++++++---- GPU/GPUTracking/kernels.cmake | 1 - 5 files changed, 31 insertions(+), 33 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx index 0536f3384d2f3..cd93e1a412cd0 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx @@ -189,26 +189,6 @@ GPUdi() void GPUTPCDecompressionKernels::decompressorMemcpyBasic(T* GPUrestrict( } } -template <> -GPUdii() void GPUTPCDecompressionUtilKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) -{ - GPUTPCDecompression& GPUrestrict() decompressor = processors.tpcDecompressor; - CompressedClusters& GPUrestrict() cmprClusters = decompressor.mInputGPU; - ClusterNative* GPUrestrict() clusterBuffer = decompressor.mNativeClustersBuffer; - const ClusterNativeAccess* outputAccess = processors.ioPtrs.clustersNative; - - unsigned int* offsets = decompressor.mUnattachedClustersOffsets; - for (unsigned int i = get_global_id(0); i < GPUCA_NSLICES * GPUCA_ROW_COUNT; i += get_global_size(0)) { - unsigned int slice = i / GPUCA_ROW_COUNT; - unsigned int row = i % GPUCA_ROW_COUNT; - unsigned int tmpBufferIndex = computeLinearTmpBufferIndex(slice, row, decompressor.mMaxNativeClustersPerBuffer); - ClusterNative* buffer = clusterBuffer + outputAccess->clusterOffset[slice][row]; - if (decompressor.mNativeClustersIndex[i] != 0) { - decompressorMemcpyBasic(buffer, decompressor.mTmpNativeClusters + tmpBufferIndex, decompressor.mNativeClustersIndex[i]); - } - } -} - template <> GPUdii() void GPUTPCDecompressionUtilKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) { diff --git a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx index a5b84369a46e2..08d1c8bac6762 100644 --- a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx +++ b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx @@ -105,7 +105,7 @@ int TPCClusterDecompressor::decompress(const CompressedClusters* clustersCompres cl.setTime(t); } } - std::sort(buffer, buffer + clustersNative.nClusters[i][j]); +// std::sort(buffer, buffer + clustersNative.nClusters[i][j]); } } diff --git a/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h b/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h index 9bc51f8a325ee..ab66e6a1f8e9b 100644 --- a/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h +++ b/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h @@ -199,7 +199,7 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 64, 2 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 3 - #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 128, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 64, 1 #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 288, 2 #define GPUCA_LB_GPUTPCCFCheckPadBaseline 64,8 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillIndexMap 448 @@ -265,7 +265,7 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 128 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 2 - #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 128, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 64, 1 #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 288, 2 #define GPUCA_LB_COMPRESSION_GATHER 1024 #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 4 @@ -341,9 +341,6 @@ #ifndef GPUCA_LB_GPUTPCDecompressionUtilKernels_sortPerSectorRow #define GPUCA_LB_GPUTPCDecompressionUtilKernels_sortPerSectorRow 256 #endif -#ifndef GPUCA_LB_GPUTPCDecompressionUtilKernels_computeAttachedOffsets - #define GPUCA_LB_GPUTPCDecompressionUtilKernels_computeAttachedOffsets 256 -#endif #ifndef GPUCA_LB_GPUTPCCFDecodeZS #define GPUCA_LB_GPUTPCCFDecodeZS 128, 4 #endif diff --git a/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx b/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx index a02be0461f416..7780b7debd893 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx @@ -288,7 +288,7 @@ int GPUChainTracking::RunTPCDecompression() bool toGPU = true; runKernel(GetGridAutoStep(inputStream, RecoStep::TPCDecompression), krnlRunRangeNone, &mEvents->init, DecompressorShadow.mNativeClustersIndex, NSLICES * GPUCA_ROW_COUNT * sizeof(DecompressorShadow.mNativeClustersIndex[0])); std::exclusive_scan(cmprClsHost.nTrackClusters, cmprClsHost.nTrackClusters + cmprClsHost.nTracks, Decompressor.mAttachedClustersOffsets,0u); - int nStreams = 4; + int nStreams = 5; for (unsigned int iStream = 0; iStream < nStreams; ++iStream) { unsigned int startTrack = cmprClsHost.nTracks / nStreams * iStream; unsigned int endTrack = cmprClsHost.nTracks / nStreams * (iStream + 1) + (iStream < nStreams - 1 ? 0 : cmprClsHost.nTracks % nStreams); @@ -313,7 +313,7 @@ int GPUChainTracking::RunTPCDecompression() GPUMemCpy(myStep, inputGPUShadow.timeA + startTrack, cmprClsHost.timeA + startTrack, numTracks * sizeof(cmprClsHost.timeA[0]), iStream, toGPU); GPUMemCpy(myStep, inputGPUShadow.padA + startTrack, cmprClsHost.padA + startTrack, numTracks * sizeof(cmprClsHost.padA[0]), iStream, toGPU); - runKernel({46,64,iStream}, krnlRunRangeNone, {&mEvents->stream[iStream], &mEvents->init}, startTrack, endTrack); + runKernel({60,128,iStream}, krnlRunRangeNone, {&mEvents->stream[iStream], &mEvents->init}, startTrack, endTrack); } GPUMemCpy(myStep, inputGPUShadow.nSliceRowClusters, cmprClsHost.nSliceRowClusters, NSLICES * GPUCA_ROW_COUNT * sizeof(cmprClsHost.nSliceRowClusters[0]), unattachedStream, toGPU); @@ -363,12 +363,34 @@ int GPUChainTracking::RunTPCDecompression() mClusterNativeAccess->clustersLinear = mInputsHost->mPclusterNativeOutput; mClusterNativeAccess->setOffsetPtrs(); - runKernel(GetGridAuto(inputStream)); - if (GetProcessingSettings().deterministicGPUReconstruction || GetProcessingSettings().debugLevel >= 4) { - runKernel(GetGridAutoStep(inputStream, RecoStep::TPCDecompression)); + runKernel(GetGridAuto(unattachedStream), krnlRunRangeNone, {nullptr, &mEvents->init}); + + for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { + for (unsigned int iRow = 0; iRow < GPUCA_ROW_COUNT; iRow++) { + int linearIndex = iSlice * GPUCA_ROW_COUNT + iRow; + GPUMemCpy(RecoStep::TPCDecompression, mInputsHost->mPclusterNativeOutput + mClusterNativeAccess->clusterOffset[iSlice][iRow], DecompressorShadow.mTmpNativeClusters + GPUTPCDecompressionKernels::computeLinearTmpBufferIndex(iSlice, iRow, Decompressor.mMaxNativeClustersPerBuffer), sizeof(DecompressorShadow.mTmpNativeClusters[0]) * Decompressor.mNativeClustersIndex[linearIndex], inputStream, false, nullptr,mEvents->stream,nStreams); + } } - GPUMemCpy(RecoStep::TPCDecompression, (void*)mInputsHost->mPclusterNativeOutput, (void*)mInputsShadow->mPclusterNativeBuffer, sizeof(mInputsShadow->mPclusterNativeBuffer[0]) * mIOPtrs.clustersNative->nClustersTotal, unattachedStream, false); + for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { + for (unsigned int iRow = 0; iRow < GPUCA_ROW_COUNT; iRow++) { + int linearIndex = iSlice * GPUCA_ROW_COUNT + iRow; + GPUMemCpy(RecoStep::TPCDecompression, mInputsHost->mPclusterNativeOutput + mClusterNativeAccess->clusterOffset[iSlice][iRow] + Decompressor.mNativeClustersIndex[linearIndex], DecompressorShadow.mNativeClustersBuffer + mClusterNativeAccess->clusterOffset[iSlice][iRow] + Decompressor.mNativeClustersIndex[linearIndex], sizeof(DecompressorShadow.mNativeClustersBuffer[0]) * ((linearIndex >= cmprClsHost.nSliceRows) ? 0 : cmprClsHost.nSliceRowClusters[linearIndex]), unattachedStream, false); + } + } + SynchronizeStream(inputStream); SynchronizeStream(unattachedStream); + + if (GetProcessingSettings().deterministicGPUReconstruction || GetProcessingSettings().debugLevel >= 4) { + runKernel(GetGridAutoStep(unattachedStream, RecoStep::TPCDecompression), krnlRunRangeNone, krnlEventNone); + const ClusterNativeAccess* decoded = mIOPtrs.clustersNative; + for (unsigned int i = 0; i < NSLICES; i++) { + for (unsigned int j = 0; j < GPUCA_ROW_COUNT; j++) { + ClusterNative* begin = mInputsHost->mPclusterNativeOutput + decoded->clusterOffset[i][j]; + ClusterNative* end = begin + decoded->nClusters[i][j]; + std::sort(begin, end); + } + } + } mRec->PopNonPersistentMemory(RecoStep::TPCDecompression, qStr2Tag("TPCDCMPR")); } //#endif diff --git a/GPU/GPUTracking/kernels.cmake b/GPU/GPUTracking/kernels.cmake index c4347d48cd498..5f97b2474388a 100644 --- a/GPU/GPUTracking/kernels.cmake +++ b/GPU/GPUTracking/kernels.cmake @@ -108,7 +108,6 @@ o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, multiBlock" "GPUTPCCom o2_gpu_add_kernel("GPUTPCDecompressionKernels, step0attached" "= TPCDECOMPRESSION" LB simple int trackStart int trackEnd) o2_gpu_add_kernel("GPUTPCDecompressionKernels, step1unattached" "= TPCDECOMPRESSION" LB simple) o2_gpu_add_kernel("GPUTPCDecompressionUtilKernels, sortPerSectorRow" "GPUTPCDecompressionKernels" LB simple) -o2_gpu_add_kernel("GPUTPCDecompressionUtilKernels, computeAttachedOffsets" "GPUTPCDecompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCCFCheckPadBaseline" "= TPCCLUSTERFINDER" LB single) o2_gpu_add_kernel("GPUTPCCFChargeMapFiller, fillIndexMap" "= TPCCLUSTERFINDER" LB single) o2_gpu_add_kernel("GPUTPCCFChargeMapFiller, fillFromDigits" "= TPCCLUSTERFINDER" LB single) From f8f5f43e22d82414d0dd9459c22b2c3043a90ca6 Mon Sep 17 00:00:00 2001 From: cima22 Date: Tue, 2 Apr 2024 15:11:47 +0200 Subject: [PATCH 0256/2997] GPU TPC: Decompression: unattached clusters kernels on multiple streams --- .../GPUTPCDecompressionKernels.cxx | 23 +++++++------ .../Definitions/GPUDefGPUParameters.h | 4 +-- .../Global/GPUChainTrackingCompression.cxx | 33 ++++++++----------- GPU/GPUTracking/kernels.cmake | 2 +- 4 files changed, 27 insertions(+), 35 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx index cd93e1a412cd0..bbe9c338acc79 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx @@ -126,7 +126,7 @@ GPUdii() ClusterNative GPUTPCDecompressionKernels::decompressTrackStore(const o2 } template <> -GPUdii() void GPUTPCDecompressionKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors) +GPUdii() void GPUTPCDecompressionKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors, int iSlice) { GPUTPCDecompression& GPUrestrict() decompressor = processors.tpcDecompressor; CompressedClusters& GPUrestrict() cmprClusters = decompressor.mInputGPU; @@ -134,19 +134,18 @@ GPUdii() void GPUTPCDecompressionKernels::ThreadclusterOffset[slice][row]; - if (decompressor.mNativeClustersIndex[i] != 0) { - decompressorMemcpyBasic(buffer, decompressor.mTmpNativeClusters + tmpBufferIndex, decompressor.mNativeClustersIndex[i]); + for (unsigned int iRow = get_global_id(0); iRow < GPUCA_ROW_COUNT; iRow += get_global_size(0)) { + const int linearIndex = iSlice * GPUCA_ROW_COUNT + iRow; + unsigned int tmpBufferIndex = computeLinearTmpBufferIndex(iSlice, iRow, decompressor.mMaxNativeClustersPerBuffer); + ClusterNative* buffer = clusterBuffer + outputAccess->clusterOffset[iSlice][iRow]; + if (decompressor.mNativeClustersIndex[linearIndex] != 0) { + decompressorMemcpyBasic(buffer, decompressor.mTmpNativeClusters + tmpBufferIndex, decompressor.mNativeClustersIndex[linearIndex]); } - ClusterNative* clout = buffer + decompressor.mNativeClustersIndex[i]; - unsigned int end = offsets[i] + ((i >= decompressor.mInputGPU.nSliceRows) ? 0 : decompressor.mInputGPU.nSliceRowClusters[i]); - decompressHits(cmprClusters, offsets[i], end, clout); + ClusterNative* clout = buffer + decompressor.mNativeClustersIndex[linearIndex]; + unsigned int end = offsets[linearIndex] + ((linearIndex >= decompressor.mInputGPU.nSliceRows) ? 0 : decompressor.mInputGPU.nSliceRowClusters[linearIndex]); + decompressHits(cmprClusters, offsets[linearIndex], end, clout); if (processors.param.rec.tpc.clustersShiftTimebins != 0.f) { - for (unsigned int k = 0; k < outputAccess->nClusters[slice][row]; k++) { + for (unsigned int k = 0; k < outputAccess->nClusters[iSlice][iRow]; k++) { auto& cl = buffer[k]; float t = cl.getTime() + processors.param.rec.tpc.clustersShiftTimebins; if (t < 0) { diff --git a/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h b/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h index ab66e6a1f8e9b..db1a0c5863c57 100644 --- a/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h +++ b/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h @@ -200,7 +200,7 @@ #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 64, 2 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 3 #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 64, 1 - #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 288, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 64, 1 #define GPUCA_LB_GPUTPCCFCheckPadBaseline 64,8 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillIndexMap 448 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillFromDigits 448 @@ -266,7 +266,7 @@ #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 128 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 2 #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 64, 1 - #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 288, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 64, 1 #define GPUCA_LB_COMPRESSION_GATHER 1024 #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 4 #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 20 diff --git a/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx b/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx index 7780b7debd893..8a9d98d16bf55 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx @@ -208,7 +208,7 @@ int GPUChainTracking::RunTPCCompression() int GPUChainTracking::RunTPCDecompression() { auto start = std::chrono::high_resolution_clock::now(); -//#ifdef GPUCA_HAVE_O2HEADERS + //#ifdef GPUCA_HAVE_O2HEADERS if (GetProcessingSettings().tpcUseOldCPUDecoding) { const auto& threadContext = GetThreadContext(); TPCClusterDecompressor decomp; @@ -248,7 +248,7 @@ int GPUChainTracking::RunTPCDecompression() CompressedClusters& inputGPUShadow = DecompressorShadow.mInputGPU; int inputStream = 0; - int unattachedStream = 4; + int unattachedStream = mRec->NStreams() - 1; inputGPU.nAttachedClusters = cmprClsHost.nAttachedClusters; inputGPU.nUnattachedClusters = cmprClsHost.nUnattachedClusters; inputGPU.nTracks = cmprClsHost.nTracks; @@ -288,7 +288,7 @@ int GPUChainTracking::RunTPCDecompression() bool toGPU = true; runKernel(GetGridAutoStep(inputStream, RecoStep::TPCDecompression), krnlRunRangeNone, &mEvents->init, DecompressorShadow.mNativeClustersIndex, NSLICES * GPUCA_ROW_COUNT * sizeof(DecompressorShadow.mNativeClustersIndex[0])); std::exclusive_scan(cmprClsHost.nTrackClusters, cmprClsHost.nTrackClusters + cmprClsHost.nTracks, Decompressor.mAttachedClustersOffsets,0u); - int nStreams = 5; + int nStreams = mRec->NStreams() - 1; for (unsigned int iStream = 0; iStream < nStreams; ++iStream) { unsigned int startTrack = cmprClsHost.nTracks / nStreams * iStream; unsigned int endTrack = cmprClsHost.nTracks / nStreams * (iStream + 1) + (iStream < nStreams - 1 ? 0 : cmprClsHost.nTracks % nStreams); @@ -313,7 +313,7 @@ int GPUChainTracking::RunTPCDecompression() GPUMemCpy(myStep, inputGPUShadow.timeA + startTrack, cmprClsHost.timeA + startTrack, numTracks * sizeof(cmprClsHost.timeA[0]), iStream, toGPU); GPUMemCpy(myStep, inputGPUShadow.padA + startTrack, cmprClsHost.padA + startTrack, numTracks * sizeof(cmprClsHost.padA[0]), iStream, toGPU); - runKernel({60,128,iStream}, krnlRunRangeNone, {&mEvents->stream[iStream], &mEvents->init}, startTrack, endTrack); + runKernel({60,96,iStream}, krnlRunRangeNone, {&mEvents->stream[iStream], &mEvents->init}, startTrack, endTrack); } GPUMemCpy(myStep, inputGPUShadow.nSliceRowClusters, cmprClsHost.nSliceRowClusters, NSLICES * GPUCA_ROW_COUNT * sizeof(cmprClsHost.nSliceRowClusters[0]), unattachedStream, toGPU); @@ -362,23 +362,16 @@ int GPUChainTracking::RunTPCDecompression() mIOPtrs.clustersNative = mClusterNativeAccess.get(); mClusterNativeAccess->clustersLinear = mInputsHost->mPclusterNativeOutput; mClusterNativeAccess->setOffsetPtrs(); - - runKernel(GetGridAuto(unattachedStream), krnlRunRangeNone, {nullptr, &mEvents->init}); - - for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { - for (unsigned int iRow = 0; iRow < GPUCA_ROW_COUNT; iRow++) { - int linearIndex = iSlice * GPUCA_ROW_COUNT + iRow; - GPUMemCpy(RecoStep::TPCDecompression, mInputsHost->mPclusterNativeOutput + mClusterNativeAccess->clusterOffset[iSlice][iRow], DecompressorShadow.mTmpNativeClusters + GPUTPCDecompressionKernels::computeLinearTmpBufferIndex(iSlice, iRow, Decompressor.mMaxNativeClustersPerBuffer), sizeof(DecompressorShadow.mTmpNativeClusters[0]) * Decompressor.mNativeClustersIndex[linearIndex], inputStream, false, nullptr,mEvents->stream,nStreams); - } + auto startU = std::chrono::high_resolution_clock::now(); + for (unsigned int iSlice = 0; iSlice < NSLICES; ++iSlice) { + int iStream = iSlice % mRec->NStreams(); + runKernel({120,32,iStream}, krnlRunRangeNone, {nullptr, &mEvents->init}, iSlice); + GPUMemCpy(RecoStep::TPCDecompression, mInputsHost->mPclusterNativeOutput + mClusterNativeAccess->clusterOffset[iSlice][0], DecompressorShadow.mNativeClustersBuffer + mClusterNativeAccess->clusterOffset[iSlice][0], sizeof(Decompressor.mNativeClustersBuffer[0]) * mClusterNativeAccess->nClustersSector[iSlice], iStream, false); } - for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice++) { - for (unsigned int iRow = 0; iRow < GPUCA_ROW_COUNT; iRow++) { - int linearIndex = iSlice * GPUCA_ROW_COUNT + iRow; - GPUMemCpy(RecoStep::TPCDecompression, mInputsHost->mPclusterNativeOutput + mClusterNativeAccess->clusterOffset[iSlice][iRow] + Decompressor.mNativeClustersIndex[linearIndex], DecompressorShadow.mNativeClustersBuffer + mClusterNativeAccess->clusterOffset[iSlice][iRow] + Decompressor.mNativeClustersIndex[linearIndex], sizeof(DecompressorShadow.mNativeClustersBuffer[0]) * ((linearIndex >= cmprClsHost.nSliceRows) ? 0 : cmprClsHost.nSliceRowClusters[linearIndex]), unattachedStream, false); - } - } - SynchronizeStream(inputStream); - SynchronizeStream(unattachedStream); + SynchronizeGPU(); + auto endU = std::chrono::high_resolution_clock::now(); + std::chrono::duration durationU = endU - startU; + LOGP(info,"Unatt time: {} ms", durationU.count() * 1e3); if (GetProcessingSettings().deterministicGPUReconstruction || GetProcessingSettings().debugLevel >= 4) { runKernel(GetGridAutoStep(unattachedStream, RecoStep::TPCDecompression), krnlRunRangeNone, krnlEventNone); diff --git a/GPU/GPUTracking/kernels.cmake b/GPU/GPUTracking/kernels.cmake index 5f97b2474388a..51668dfff42a5 100644 --- a/GPU/GPUTracking/kernels.cmake +++ b/GPU/GPUTracking/kernels.cmake @@ -106,7 +106,7 @@ o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, buffered64" "GPUTPCCom o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, buffered128" "GPUTPCCompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, multiBlock" "GPUTPCCompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCDecompressionKernels, step0attached" "= TPCDECOMPRESSION" LB simple int trackStart int trackEnd) -o2_gpu_add_kernel("GPUTPCDecompressionKernels, step1unattached" "= TPCDECOMPRESSION" LB simple) +o2_gpu_add_kernel("GPUTPCDecompressionKernels, step1unattached" "= TPCDECOMPRESSION" LB simple int iSlice) o2_gpu_add_kernel("GPUTPCDecompressionUtilKernels, sortPerSectorRow" "GPUTPCDecompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCCFCheckPadBaseline" "= TPCCLUSTERFINDER" LB single) o2_gpu_add_kernel("GPUTPCCFChargeMapFiller, fillIndexMap" "= TPCCLUSTERFINDER" LB single) From 6572437ede601a79279eb88355ebada582a559a4 Mon Sep 17 00:00:00 2001 From: cima22 Date: Wed, 3 Apr 2024 17:00:59 +0200 Subject: [PATCH 0257/2997] GPU TPC: Decompression: unattached clusters kernels handle more sectors per kernel call --- .../GPUTPCClusterStatistics.cxx | 2 +- .../GPUTPCDecompressionKernels.cxx | 7 ++- .../GPUTPCDecompressionKernels.h | 3 +- .../TPCClusterDecompressor.cxx | 11 ++-- .../DataCompression/TPCClusterDecompressor.h | 4 +- .../Definitions/GPUDefGPUParameters.h | 12 ++-- .../Global/GPUChainTrackingCompression.cxx | 59 ++++++++----------- GPU/GPUTracking/kernels.cmake | 2 +- 8 files changed, 48 insertions(+), 52 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx index 04e57426c1927..f050563645faf 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx @@ -110,7 +110,7 @@ void GPUTPCClusterStatistics::RunStatistics(const o2::tpc::ClusterNativeAccess* std::vector clusterBuffer; GPUInfo("Compression statistics, decoding: %d attached (%d tracks), %d unattached", clustersCompressed->nAttachedClusters, clustersCompressed->nTracks, clustersCompressed->nUnattachedClusters); auto allocator = [&clusterBuffer](size_t size) {clusterBuffer.resize(size); return clusterBuffer.data(); }; - mDecoder.decompress(clustersCompressed, clustersNativeDecoded, allocator, param); + mDecoder.decompress(clustersCompressed, clustersNativeDecoded, allocator, param, true); std::vector tmpClusters; if (param.rec.tpc.rejectionStrategy == GPUSettings::RejectionNone) { // verification does not make sense if we reject clusters during compression for (unsigned int i = 0; i < NSLICES; i++) { diff --git a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx index bbe9c338acc79..7cad6b4377f92 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.cxx @@ -126,15 +126,16 @@ GPUdii() ClusterNative GPUTPCDecompressionKernels::decompressTrackStore(const o2 } template <> -GPUdii() void GPUTPCDecompressionKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors, int iSlice) +GPUdii() void GPUTPCDecompressionKernels::Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors, int sliceStart, int nSlices) { GPUTPCDecompression& GPUrestrict() decompressor = processors.tpcDecompressor; CompressedClusters& GPUrestrict() cmprClusters = decompressor.mInputGPU; ClusterNative* GPUrestrict() clusterBuffer = decompressor.mNativeClustersBuffer; const ClusterNativeAccess* outputAccess = processors.ioPtrs.clustersNative; - unsigned int* offsets = decompressor.mUnattachedClustersOffsets; - for (unsigned int iRow = get_global_id(0); iRow < GPUCA_ROW_COUNT; iRow += get_global_size(0)) { + for (unsigned int i = get_global_id(0); i < GPUCA_ROW_COUNT * nSlices; i += get_global_size(0)) { + unsigned int iRow = i % GPUCA_ROW_COUNT; + unsigned int iSlice = sliceStart + (i / GPUCA_ROW_COUNT); const int linearIndex = iSlice * GPUCA_ROW_COUNT + iRow; unsigned int tmpBufferIndex = computeLinearTmpBufferIndex(iSlice, iRow, decompressor.mMaxNativeClustersPerBuffer); ClusterNative* buffer = clusterBuffer + outputAccess->clusterOffset[iSlice][iRow]; diff --git a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.h b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.h index 4d21bcaef1ab8..904dc5aabd2c4 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCDecompressionKernels.h @@ -62,8 +62,7 @@ class GPUTPCDecompressionUtilKernels : public GPUKernelTemplate { public: enum K : int { - gatherAttachedClusters = 0, - sortPerSectorRow = 1, + sortPerSectorRow = 0, }; template diff --git a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx index 08d1c8bac6762..61e3392af0f03 100644 --- a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx +++ b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.cxx @@ -25,7 +25,7 @@ using namespace GPUCA_NAMESPACE::gpu; using namespace o2::tpc; -int TPCClusterDecompressor::decompress(const CompressedClustersFlat* clustersCompressed, o2::tpc::ClusterNativeAccess& clustersNative, std::function allocator, const GPUParam& param) +int TPCClusterDecompressor::decompress(const CompressedClustersFlat* clustersCompressed, o2::tpc::ClusterNativeAccess& clustersNative, std::function allocator, const GPUParam& param, bool deterministicRec) { CompressedClusters c; const CompressedClusters* p; @@ -35,10 +35,10 @@ int TPCClusterDecompressor::decompress(const CompressedClustersFlat* clustersCom c = *clustersCompressed; p = &c; } - return decompress(p, clustersNative, allocator, param); + return decompress(p, clustersNative, allocator, param, deterministicRec); } -int TPCClusterDecompressor::decompress(const CompressedClusters* clustersCompressed, o2::tpc::ClusterNativeAccess& clustersNative, std::function allocator, const GPUParam& param) +int TPCClusterDecompressor::decompress(const CompressedClusters* clustersCompressed, o2::tpc::ClusterNativeAccess& clustersNative, std::function allocator, const GPUParam& param, bool deterministicRec) { if (clustersCompressed->nTracks && clustersCompressed->solenoidBz != -1e6f && clustersCompressed->solenoidBz != param.bzkG) { throw std::runtime_error("Configured solenoid Bz does not match value used for track model encoding"); @@ -105,9 +105,10 @@ int TPCClusterDecompressor::decompress(const CompressedClusters* clustersCompres cl.setTime(t); } } -// std::sort(buffer, buffer + clustersNative.nClusters[i][j]); + if (deterministicRec) { + std::sort(buffer, buffer + clustersNative.nClusters[i][j]); + } } } - return 0; } diff --git a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.h b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.h index 03c40e9b54923..79f14fe71e093 100644 --- a/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.h +++ b/GPU/GPUTracking/DataCompression/TPCClusterDecompressor.h @@ -33,8 +33,8 @@ class TPCClusterDecompressor { public: static constexpr unsigned int NSLICES = GPUCA_NSLICES; - static int decompress(const o2::tpc::CompressedClustersFlat* clustersCompressed, o2::tpc::ClusterNativeAccess& clustersNative, std::function allocator, const GPUParam& param); - static int decompress(const o2::tpc::CompressedClusters* clustersCompressed, o2::tpc::ClusterNativeAccess& clustersNative, std::function allocator, const GPUParam& param); + static int decompress(const o2::tpc::CompressedClustersFlat* clustersCompressed, o2::tpc::ClusterNativeAccess& clustersNative, std::function allocator, const GPUParam& param, bool deterministicRec); + static int decompress(const o2::tpc::CompressedClusters* clustersCompressed, o2::tpc::ClusterNativeAccess& clustersNative, std::function allocator, const GPUParam& param, bool deterministicRec); template static void decompressTrack(const o2::tpc::CompressedClusters* clustersCompressed, const GPUParam& param, const unsigned int maxTime, const unsigned int i, unsigned int& offset, Args&... args); diff --git a/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h b/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h index db1a0c5863c57..9ab78d034d8bf 100644 --- a/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h +++ b/GPU/GPUTracking/Definitions/GPUDefGPUParameters.h @@ -71,6 +71,8 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 64, 2 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 128, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 64, 2 #define GPUCA_LB_GPUTPCCFCheckPadBaseline 64 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillIndexMap 512 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillFromDigits 512 @@ -135,6 +137,8 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 192, 2 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 128, 2 + #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 64, 2 #define GPUCA_LB_GPUTPCCFCheckPadBaseline 64 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillIndexMap 512 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillFromDigits 512 @@ -199,8 +203,8 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 64, 2 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 3 - #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 64, 1 - #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 64, 1 + #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 32, 1 + #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 32, 1 #define GPUCA_LB_GPUTPCCFCheckPadBaseline 64,8 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillIndexMap 448 #define GPUCA_LB_GPUTPCCFChargeMapFiller_fillFromDigits 448 @@ -265,8 +269,8 @@ #define GPUCA_LB_GPUTPCGMMergerFinalize_2 256 #define GPUCA_LB_GPUTPCCompressionKernels_step0attached 128 #define GPUCA_LB_GPUTPCCompressionKernels_step1unattached 512, 2 - #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 64, 1 - #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 64, 1 + #define GPUCA_LB_GPUTPCDecompressionKernels_step0attached 32, 1 + #define GPUCA_LB_GPUTPCDecompressionKernels_step1unattached 32, 1 #define GPUCA_LB_COMPRESSION_GATHER 1024 #define GPUCA_NEIGHBOURS_FINDER_MAX_NNEIGHUP 4 #define GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE 20 diff --git a/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx b/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx index 8a9d98d16bf55..955b54645f6ad 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingCompression.cxx @@ -17,7 +17,6 @@ #include "GPUO2DataTypes.h" #include "GPUTrackingInputProvider.h" #include -#include #ifdef GPUCA_HAVE_O2HEADERS #include "GPUTPCCFChainContext.h" @@ -207,8 +206,7 @@ int GPUChainTracking::RunTPCCompression() int GPUChainTracking::RunTPCDecompression() { - auto start = std::chrono::high_resolution_clock::now(); - //#ifdef GPUCA_HAVE_O2HEADERS +#ifdef GPUCA_HAVE_O2HEADERS if (GetProcessingSettings().tpcUseOldCPUDecoding) { const auto& threadContext = GetThreadContext(); TPCClusterDecompressor decomp; @@ -219,7 +217,7 @@ int GPUChainTracking::RunTPCDecompression() }; auto& gatherTimer = getTimer("TPCDecompression", 0); gatherTimer.Start(); - if (decomp.decompress(mIOPtrs.tpcCompressedClusters, *mClusterNativeAccess, allocator, param())) { + if (decomp.decompress(mIOPtrs.tpcCompressedClusters, *mClusterNativeAccess, allocator, param(), GetProcessingSettings().deterministicGPUReconstruction)) { GPUError("Error decompressing clusters"); return 1; } @@ -257,7 +255,6 @@ int GPUChainTracking::RunTPCDecompression() inputGPU.nComppressionModes = param().rec.tpc.compressionTypeMask; inputGPU.solenoidBz = param().bzkG; inputGPU.maxTimeBin = param().par.continuousMaxTimeBin; - SetupGPUProcessor(&Decompressor, true); WriteToConstantMemory(myStep, (char*)&processors()->tpcDecompressor - (char*)processors(), &DecompressorShadow, sizeof(DecompressorShadow), inputStream); @@ -286,12 +283,12 @@ int GPUChainTracking::RunTPCDecompression() inputGPU.padA = cmprClsHost.padA; bool toGPU = true; - runKernel(GetGridAutoStep(inputStream, RecoStep::TPCDecompression), krnlRunRangeNone, &mEvents->init, DecompressorShadow.mNativeClustersIndex, NSLICES * GPUCA_ROW_COUNT * sizeof(DecompressorShadow.mNativeClustersIndex[0])); - std::exclusive_scan(cmprClsHost.nTrackClusters, cmprClsHost.nTrackClusters + cmprClsHost.nTracks, Decompressor.mAttachedClustersOffsets,0u); - int nStreams = mRec->NStreams() - 1; + runKernel({GetGridAutoStep(inputStream, RecoStep::TPCDecompression), krnlRunRangeNone, &mEvents->init}, DecompressorShadow.mNativeClustersIndex, NSLICES * GPUCA_ROW_COUNT * sizeof(DecompressorShadow.mNativeClustersIndex[0])); + std::exclusive_scan(cmprClsHost.nTrackClusters, cmprClsHost.nTrackClusters + cmprClsHost.nTracks, Decompressor.mAttachedClustersOffsets, 0u); // computing clusters offsets for first kernel + int nStreams = doGPU ? mRec->NStreams() - 1 : 1; for (unsigned int iStream = 0; iStream < nStreams; ++iStream) { unsigned int startTrack = cmprClsHost.nTracks / nStreams * iStream; - unsigned int endTrack = cmprClsHost.nTracks / nStreams * (iStream + 1) + (iStream < nStreams - 1 ? 0 : cmprClsHost.nTracks % nStreams); + unsigned int endTrack = cmprClsHost.nTracks / nStreams * (iStream + 1) + (iStream < nStreams - 1 ? 0 : cmprClsHost.nTracks % nStreams); // index of last track (excluded from computation) unsigned int numTracks = endTrack - startTrack; unsigned int* offsets = Decompressor.mAttachedClustersOffsets; unsigned int numClusters = (endTrack == cmprClsHost.nTracks ? offsets[endTrack - 1] + cmprClsHost.nTrackClusters[endTrack - 1] : offsets[endTrack]) - offsets[startTrack]; @@ -312,10 +309,8 @@ int GPUChainTracking::RunTPCDecompression() GPUMemCpy(myStep, inputGPUShadow.sliceA + startTrack, cmprClsHost.sliceA + startTrack, numTracks * sizeof(cmprClsHost.sliceA[0]), iStream, toGPU); GPUMemCpy(myStep, inputGPUShadow.timeA + startTrack, cmprClsHost.timeA + startTrack, numTracks * sizeof(cmprClsHost.timeA[0]), iStream, toGPU); GPUMemCpy(myStep, inputGPUShadow.padA + startTrack, cmprClsHost.padA + startTrack, numTracks * sizeof(cmprClsHost.padA[0]), iStream, toGPU); - - runKernel({60,96,iStream}, krnlRunRangeNone, {&mEvents->stream[iStream], &mEvents->init}, startTrack, endTrack); + runKernel({GetGridAuto(iStream), krnlRunRangeNone, {&mEvents->stream[iStream], &mEvents->init}}, startTrack, endTrack); } - GPUMemCpy(myStep, inputGPUShadow.nSliceRowClusters, cmprClsHost.nSliceRowClusters, NSLICES * GPUCA_ROW_COUNT * sizeof(cmprClsHost.nSliceRowClusters[0]), unattachedStream, toGPU); GPUMemCpy(myStep, inputGPUShadow.qTotU, cmprClsHost.qTotU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.qTotU[0]), unattachedStream, toGPU); GPUMemCpy(myStep, inputGPUShadow.qMaxU, cmprClsHost.qMaxU, cmprClsHost.nUnattachedClusters * sizeof(cmprClsHost.qMaxU[0]), unattachedStream, toGPU); @@ -331,9 +326,8 @@ int GPUChainTracking::RunTPCDecompression() DecompressorShadow.mNativeClustersBuffer = mInputsShadow->mPclusterNativeBuffer; Decompressor.mNativeClustersBuffer = mInputsHost->mPclusterNativeOutput; WriteToConstantMemory(myStep, (char*)&processors()->tpcDecompressor - (char*)processors(), &DecompressorShadow, sizeof(DecompressorShadow), inputStream); - TransferMemoryResourceLinkToHost(RecoStep::TPCDecompression, Decompressor.mResourceTmpIndexes, inputStream,nullptr,mEvents->stream,nStreams); + TransferMemoryResourceLinkToHost(RecoStep::TPCDecompression, Decompressor.mResourceTmpIndexes, inputStream, nullptr, mEvents->stream, nStreams); SynchronizeStream(inputStream); - unsigned int offset = 0; unsigned int decodedAttachedClusters = 0; for (unsigned int i = 0; i < NSLICES; i++) { @@ -350,45 +344,42 @@ int GPUChainTracking::RunTPCDecompression() if (decodedAttachedClusters != cmprClsHost.nAttachedClusters) { GPUWarning("%u / %u clusters failed track model decoding (%f %%)", cmprClsHost.nAttachedClusters - decodedAttachedClusters, cmprClsHost.nAttachedClusters, 100.f * (float)(cmprClsHost.nAttachedClusters - decodedAttachedClusters) / (float)cmprClsHost.nAttachedClusters); } - if (doGPU) { mClusterNativeAccess->clustersLinear = mInputsShadow->mPclusterNativeBuffer; mClusterNativeAccess->setOffsetPtrs(); *mInputsHost->mPclusterNativeAccess = *mClusterNativeAccess; processorsShadow()->ioPtrs.clustersNative = mInputsShadow->mPclusterNativeAccess; WriteToConstantMemory(RecoStep::TPCDecompression, (char*)&processors()->ioPtrs - (char*)processors(), &processorsShadow()->ioPtrs, sizeof(processorsShadow()->ioPtrs), inputStream); - TransferMemoryResourceLinkToGPU(RecoStep::TPCDecompression, mInputsHost->mResourceClusterNativeAccess, inputStream, &mEvents->init); + TransferMemoryResourceLinkToGPU(RecoStep::TPCDecompression, mInputsHost->mResourceClusterNativeAccess, inputStream, &mEvents->single); } mIOPtrs.clustersNative = mClusterNativeAccess.get(); mClusterNativeAccess->clustersLinear = mInputsHost->mPclusterNativeOutput; mClusterNativeAccess->setOffsetPtrs(); - auto startU = std::chrono::high_resolution_clock::now(); - for (unsigned int iSlice = 0; iSlice < NSLICES; ++iSlice) { - int iStream = iSlice % mRec->NStreams(); - runKernel({120,32,iStream}, krnlRunRangeNone, {nullptr, &mEvents->init}, iSlice); - GPUMemCpy(RecoStep::TPCDecompression, mInputsHost->mPclusterNativeOutput + mClusterNativeAccess->clusterOffset[iSlice][0], DecompressorShadow.mNativeClustersBuffer + mClusterNativeAccess->clusterOffset[iSlice][0], sizeof(Decompressor.mNativeClustersBuffer[0]) * mClusterNativeAccess->nClustersSector[iSlice], iStream, false); + + unsigned int batchSize = doGPU ? 6 : NSLICES; + for (unsigned int iSlice = 0; iSlice < NSLICES; iSlice = iSlice + batchSize) { + int iStream = (iSlice / batchSize) % mRec->NStreams(); + runKernel({GetGridAuto(iStream), krnlRunRangeNone, {nullptr, &mEvents->single}}, iSlice, batchSize); + unsigned int copySize = std::accumulate(mClusterNativeAccess->nClustersSector + iSlice, mClusterNativeAccess->nClustersSector + iSlice + batchSize, 0u); + GPUMemCpy(RecoStep::TPCDecompression, mInputsHost->mPclusterNativeOutput + mClusterNativeAccess->clusterOffset[iSlice][0], DecompressorShadow.mNativeClustersBuffer + mClusterNativeAccess->clusterOffset[iSlice][0], sizeof(Decompressor.mNativeClustersBuffer[0]) * copySize, iStream, false); } SynchronizeGPU(); - auto endU = std::chrono::high_resolution_clock::now(); - std::chrono::duration durationU = endU - startU; - LOGP(info,"Unatt time: {} ms", durationU.count() * 1e3); if (GetProcessingSettings().deterministicGPUReconstruction || GetProcessingSettings().debugLevel >= 4) { - runKernel(GetGridAutoStep(unattachedStream, RecoStep::TPCDecompression), krnlRunRangeNone, krnlEventNone); + runKernel(GetGridAutoStep(unattachedStream, RecoStep::TPCDecompression)); const ClusterNativeAccess* decoded = mIOPtrs.clustersNative; - for (unsigned int i = 0; i < NSLICES; i++) { - for (unsigned int j = 0; j < GPUCA_ROW_COUNT; j++) { - ClusterNative* begin = mInputsHost->mPclusterNativeOutput + decoded->clusterOffset[i][j]; - ClusterNative* end = begin + decoded->nClusters[i][j]; - std::sort(begin, end); + if (doGPU) { + for (unsigned int i = 0; i < NSLICES; i++) { + for (unsigned int j = 0; j < GPUCA_ROW_COUNT; j++) { + ClusterNative* begin = mInputsHost->mPclusterNativeOutput + decoded->clusterOffset[i][j]; + ClusterNative* end = begin + decoded->nClusters[i][j]; + std::sort(begin, end); + } } } } mRec->PopNonPersistentMemory(RecoStep::TPCDecompression, qStr2Tag("TPCDCMPR")); } -//#endif - auto end = std::chrono::high_resolution_clock::now(); - std::chrono::duration duration = end - start; - LOGP(info,"Exec time: {} ms", duration.count() * 1e3); +#endif return 0; } diff --git a/GPU/GPUTracking/kernels.cmake b/GPU/GPUTracking/kernels.cmake index 51668dfff42a5..272890ac8df78 100644 --- a/GPU/GPUTracking/kernels.cmake +++ b/GPU/GPUTracking/kernels.cmake @@ -106,7 +106,7 @@ o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, buffered64" "GPUTPCCom o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, buffered128" "GPUTPCCompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCCompressionGatherKernels, multiBlock" "GPUTPCCompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCDecompressionKernels, step0attached" "= TPCDECOMPRESSION" LB simple int trackStart int trackEnd) -o2_gpu_add_kernel("GPUTPCDecompressionKernels, step1unattached" "= TPCDECOMPRESSION" LB simple int iSlice) +o2_gpu_add_kernel("GPUTPCDecompressionKernels, step1unattached" "= TPCDECOMPRESSION" LB simple int sliceStart int nSlices) o2_gpu_add_kernel("GPUTPCDecompressionUtilKernels, sortPerSectorRow" "GPUTPCDecompressionKernels" LB simple) o2_gpu_add_kernel("GPUTPCCFCheckPadBaseline" "= TPCCLUSTERFINDER" LB single) o2_gpu_add_kernel("GPUTPCCFChargeMapFiller, fillIndexMap" "= TPCCLUSTERFINDER" LB single) From a1917c36e3e291057fb7a34679aa0a4e6287becb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 27 May 2024 10:26:00 +0200 Subject: [PATCH 0258/2997] Drop support for arrow < 11 --- dependencies/O2Dependencies.cmake | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dependencies/O2Dependencies.cmake b/dependencies/O2Dependencies.cmake index bd0085e8c8cfc..53cd7167e0e41 100644 --- a/dependencies/O2Dependencies.cmake +++ b/dependencies/O2Dependencies.cmake @@ -30,11 +30,7 @@ include(FeatureSummary) include(FindThreads) find_package(Arrow CONFIG) -if(${Arrow_VERSION} VERSION_LESS 11) -find_package(Gandiva CONFIG PATHS ${Arrow_DIR} QUIET) -else() find_package(Gandiva CONFIG) -endif() set_package_properties(Arrow PROPERTIES TYPE REQUIRED) set_package_properties(Gandiva PROPERTIES TYPE REQUIRED) From 09a4bfb06a92e6b30b0e8a25ca9345e09cd276c8 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 27 May 2024 14:51:26 +0200 Subject: [PATCH 0259/2997] GPU: Minor code clarification --- GPU/GPUTracking/Refit/GPUTrackingRefit.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx index 6f8450385ea54..5b42ad462cc84 100644 --- a/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx +++ b/GPU/GPUTracking/Refit/GPUTrackingRefit.cxx @@ -335,7 +335,9 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) IgnoreErrors(trk.GetSinPhi()); return -2; } - if (lastSector != -1 && (lastSector < 18) != (sector < 18)) { + if (resetCov) { + trk.ResetCovariance(); + } else if (lastSector != -1 && (lastSector < 18) != (sector < 18)) { if (mPparam->rec.tpc.addErrorsCECrossing) { if (mPparam->rec.tpc.addErrorsCECrossing >= 2) { trk.AddCovDiagErrorsWithCorrelations(mPparam->rec.tpc.errorsCECrossing); @@ -346,9 +348,6 @@ GPUd() int GPUTrackingRefit::RefitTrack(T& trkX, bool outward, bool resetCov) trk.Cov()[2] = 0.5f; } } - if (resetCov) { - trk.ResetCovariance(); - } CADEBUG(printf("\t%21sPropaga Alpha %8.3f , X %8.3f - Y %8.3f, Z %8.3f - QPt %7.2f (%7.2f), SP %5.2f (%5.2f) --- Res %8.3f %8.3f --- Cov sY %8.3f sZ %8.3f sSP %8.3f sPt %8.3f - YPt %8.3f\n", "", prop.GetAlpha(), x, trk.Par()[0], trk.Par()[1], trk.Par()[4], prop.GetQPt0(), trk.Par()[2], prop.GetSinPhi0(), trk.Par()[0] - y, trk.Par()[1] - z, sqrtf(trk.Cov()[0]), sqrtf(trk.Cov()[2]), sqrtf(trk.Cov()[5]), sqrtf(trk.Cov()[14]), trk.Cov()[10])); lastSector = sector; if (prop.Update(y, z, row, *mPparam, clusterState, 0, nullptr, true, sector, time, invAvgCharge, invCharge)) { From 4ada9fb44c2ba7c2d0b94f02873c9a54fe7352e9 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 27 May 2024 14:51:48 +0200 Subject: [PATCH 0260/2997] GPU Display: Fix argument description, load GRP from CCDB --- GPU/Workflow/src/O2GPUDPLDisplay.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/GPU/Workflow/src/O2GPUDPLDisplay.cxx b/GPU/Workflow/src/O2GPUDPLDisplay.cxx index 4d3510391046d..bb46bd440d399 100644 --- a/GPU/Workflow/src/O2GPUDPLDisplay.cxx +++ b/GPU/Workflow/src/O2GPUDPLDisplay.cxx @@ -50,7 +50,7 @@ void customize(std::vector& workflowOptions) {"disable-mc", o2::framework::VariantType::Bool, false, {"disable visualization of MC data"}}, // for compatibility, overrides enable-mc {"display-clusters", VariantType::String, "ITS,TPC,TRD,TOF", {"comma-separated list of clusters to display"}}, {"display-tracks", VariantType::String, "TPC,ITS,ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF", {"comma-separated list of tracks to display"}}, - {"read-from-files", o2::framework::VariantType::Bool, false, {"comma-separated list of tracks to display"}}, + {"read-from-files", o2::framework::VariantType::Bool, false, {"Automatically create readers for input"}}, {"disable-root-input", o2::framework::VariantType::Bool, false, {"Disable root input overriding read-from-files"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; @@ -98,8 +98,7 @@ void O2GPUDPLDisplaySpec::init(InitContext& ic) void O2GPUDPLDisplaySpec::run(ProcessingContext& pc) { GRPGeomHelper::instance().checkUpdates(pc); - const auto grp = o2::parameters::GRPObject::loadFrom(); - if (GRPGeomHelper::instance().getGRPECS()->isDetReadOut(o2::detectors::DetID::TPC) && mConfParam->tpcTriggeredMode ^ !grp->isDetContinuousReadOut(o2::detectors::DetID::TPC)) { + if (GRPGeomHelper::instance().getGRPECS()->isDetReadOut(o2::detectors::DetID::TPC) && mConfParam->tpcTriggeredMode ^ !GRPGeomHelper::instance().getGRPECS()->isDetContinuousReadOut(o2::detectors::DetID::TPC)) { LOG(fatal) << "configKeyValue tpcTriggeredMode does not match GRP isDetContinuousReadOut(TPC) setting"; } if (mDisplayShutDown) { @@ -114,7 +113,7 @@ void O2GPUDPLDisplaySpec::run(ProcessingContext& pc) if (mGRPGeomUpdated) { mGRPGeomUpdated = false; - mConfig->configGRP.solenoidBzNominalGPU = GPUO2InterfaceUtils::getNominalGPUBz(*grp); + mConfig->configGRP.solenoidBzNominalGPU = GPUO2InterfaceUtils::getNominalGPUBz(*GRPGeomHelper::instance().getGRPMagField()); if (mAutoContinuousMaxTimeBin) { mConfig->configGRP.continuousMaxTimeBin = (mTFSettings->nHBFPerTF * o2::constants::lhc::LHCMaxBunches + 2 * o2::tpc::constants::LHCBCPERTIMEBIN - 2) / o2::tpc::constants::LHCBCPERTIMEBIN; } From 356ba3df62a439c10ab9259e34ecf511e35ad464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Fri, 24 May 2024 17:42:29 +0200 Subject: [PATCH 0261/2997] Update store MC collision time --- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 3f5acad91fcbf..70eb67c4a880b 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -1923,9 +1923,9 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) mcCollisionsCursor.reserve(totalNParts); for (int iCol = 0; iCol < nMCCollisions; iCol++) { - auto time = mcRecords[iCol].getTimeNS(); - auto globalBC = mcRecords[iCol].toLong(); - auto item = bcsMap.find(globalBC); + const auto time = mcRecords[iCol].getTimeOffsetWrtBC(); + const auto globalBC = mcRecords[iCol].toLong(); + const auto item = bcsMap.find(globalBC); int bcID = -1; if (item != bcsMap.end()) { bcID = item->second; @@ -1934,17 +1934,17 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) << "for MC collision; BC = " << globalBC << ", mc collision = " << iCol; } - auto& colParts = mcParts[iCol]; - auto nParts = colParts.size(); - for (auto colPart : colParts) { - auto eventID = colPart.entryID; - auto sourceID = colPart.sourceID; + const auto& colParts = mcParts[iCol]; + const auto nParts = colParts.size(); + for (const auto colPart : colParts) { + const auto eventID = colPart.entryID; + const auto sourceID = colPart.sourceID; // enable embedding: if several colParts exist, then they are // saved as one collision if (nParts == 1 || sourceID == 0) { // FIXME: // use generators' names for generatorIDs (?) - auto& header = mcReader->getMCEventHeader(sourceID, eventID); + const auto& header = mcReader->getMCEventHeader(sourceID, eventID); updateMCHeader(mcCollisionsCursor.cursor, hepmcXSectionsCursor.cursor, hepmcPdfInfosCursor.cursor, From 0e34ac0c1bd343e1706a3a4ef5e052a1fcd3f734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Mon, 27 May 2024 09:59:53 +0200 Subject: [PATCH 0262/2997] Update AODProducerWorkflowSpec.cxx --- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 70eb67c4a880b..8fac28a303af3 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -1924,8 +1924,8 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) for (int iCol = 0; iCol < nMCCollisions; iCol++) { const auto time = mcRecords[iCol].getTimeOffsetWrtBC(); - const auto globalBC = mcRecords[iCol].toLong(); - const auto item = bcsMap.find(globalBC); + auto globalBC = mcRecords[iCol].toLong(); + auto item = bcsMap.find(globalBC); int bcID = -1; if (item != bcsMap.end()) { bcID = item->second; @@ -1934,11 +1934,11 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) << "for MC collision; BC = " << globalBC << ", mc collision = " << iCol; } - const auto& colParts = mcParts[iCol]; - const auto nParts = colParts.size(); + auto& colParts = mcParts[iCol]; + auto nParts = colParts.size(); for (const auto colPart : colParts) { - const auto eventID = colPart.entryID; - const auto sourceID = colPart.sourceID; + auto eventID = colPart.entryID; + auto sourceID = colPart.sourceID; // enable embedding: if several colParts exist, then they are // saved as one collision if (nParts == 1 || sourceID == 0) { From 3b0a46991f06a8661f5ceab3d28e000b513bccce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Mon, 27 May 2024 10:01:09 +0200 Subject: [PATCH 0263/2997] Update AODProducerWorkflowSpec.cxx --- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 8fac28a303af3..da76ad0bb7738 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -1936,7 +1936,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) } auto& colParts = mcParts[iCol]; auto nParts = colParts.size(); - for (const auto colPart : colParts) { + for (auto colPart : colParts) { auto eventID = colPart.entryID; auto sourceID = colPart.sourceID; // enable embedding: if several colParts exist, then they are @@ -1944,7 +1944,7 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) if (nParts == 1 || sourceID == 0) { // FIXME: // use generators' names for generatorIDs (?) - const auto& header = mcReader->getMCEventHeader(sourceID, eventID); + auto& header = mcReader->getMCEventHeader(sourceID, eventID); updateMCHeader(mcCollisionsCursor.cursor, hepmcXSectionsCursor.cursor, hepmcPdfInfosCursor.cursor, From be5cdb91997e62878dc2b74ce75f8a3594a6ec95 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 28 May 2024 12:55:21 +0200 Subject: [PATCH 0264/2997] SIM: Adding experiment versions and dynamic library loading (#13148) * SIM: Add detectorList option: Gaining more flexibility with detector geometries. (a) Allows to select a detector list from a pre-defined list of ALICE2, ALICE2.1, ALICE3 (corresponding to Run3, Run4, Run5). Arguments for -m, --skipModules, --readoutDetectors will then be checked against that list. `o2-sim -n 1 --detectorList ALICE2.1 -m IT3 -o bar2` (b) Allows to define a custom detector list "MyList" in a JSON file, and following the notation: `o2-sim --detectorList MyList:${PWD}/myDetector.json` * SIM: Add dynamic detector library loading This commit also adds the possibility to instantiate/construct detector modules as a dynamic plugin. The benefit is that we no longer need to link all possible detector libraries into the simulation executable. --- Common/SimConfig/CMakeLists.txt | 9 +- .../include/SimConfig/DetectorLists.h | 37 +++ .../SimConfig/include/SimConfig/SimConfig.h | 82 +++--- .../SimConfig/include/SimConfig/SimDLLoader.h | 27 ++ Common/SimConfig/src/DetectorLists.cxx | 78 +++++ Common/SimConfig/src/SimConfig.cxx | 119 +++++++- Common/SimConfig/src/SimDLLoader.cxx | 13 + Common/Utils/CMakeLists.txt | 2 + .../Utils/include/CommonUtils/DLLoaderBase.h | 266 ++++++++++++++++++ Common/Utils/src/DLLoaderBase.cxx | 12 + .../include/ITSSimulation/Detector.h | 6 + .../ITSMFT/ITS/simulation/src/Detector.cxx | 8 + .../include/TPCSimulation/Detector.h | 24 +- Detectors/TPC/simulation/src/Detector.cxx | 8 + .../include/TRKSimulation/Detector.h | 8 +- .../ALICE3/TRK/simulation/src/Detector.cxx | 8 + macro/CMakeLists.txt | 8 +- macro/build_geometry.C | 18 +- run/CMakeLists.txt | 2 + run/o2simdefaultdetectorlist.json | 64 +++++ 20 files changed, 725 insertions(+), 74 deletions(-) create mode 100644 Common/SimConfig/include/SimConfig/DetectorLists.h create mode 100644 Common/SimConfig/include/SimConfig/SimDLLoader.h create mode 100644 Common/SimConfig/src/DetectorLists.cxx create mode 100644 Common/SimConfig/src/SimDLLoader.cxx create mode 100644 Common/Utils/include/CommonUtils/DLLoaderBase.h create mode 100644 Common/Utils/src/DLLoaderBase.cxx create mode 100644 run/o2simdefaultdetectorlist.json diff --git a/Common/SimConfig/CMakeLists.txt b/Common/SimConfig/CMakeLists.txt index 80e40284b6e28..f8e007209eacc 100644 --- a/Common/SimConfig/CMakeLists.txt +++ b/Common/SimConfig/CMakeLists.txt @@ -12,8 +12,11 @@ o2_add_library(SimConfig SOURCES src/SimConfig.cxx src/SimParams.cxx + src/SimDLLoader.cxx src/SimUserDecay.cxx - src/DigiParams.cxx src/G4Params.cxx + src/DigiParams.cxx + src/G4Params.cxx + src/DetectorLists.cxx src/MatMapParams.cxx src/InteractionDiamondParam.cxx src/GlobalProcessCutSimParam.cxx @@ -25,10 +28,12 @@ o2_add_library(SimConfig o2_target_root_dictionary(SimConfig HEADERS include/SimConfig/SimConfig.h include/SimConfig/SimParams.h + include/SimConfig/SimDLLoader.h include/SimConfig/SimUserDecay.h include/SimConfig/InteractionDiamondParam.h - include/SimConfig/DigiParams.h + include/SimConfig/DigiParams.h include/SimConfig/G4Params.h + include/SimConfig/DetectorLists.h include/SimConfig/GlobalProcessCutSimParam.h include/SimConfig/MatMapParams.h) diff --git a/Common/SimConfig/include/SimConfig/DetectorLists.h b/Common/SimConfig/include/SimConfig/DetectorLists.h new file mode 100644 index 0000000000000..bdabe71db0872 --- /dev/null +++ b/Common/SimConfig/include/SimConfig/DetectorLists.h @@ -0,0 +1,37 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_DETECTORLISTS_H_ +#define O2_DETECTORLISTS_H_ + +#include +#include +#include + +#include "Framework/Logger.h" + +namespace o2::conf +{ +// Container defining different general evolutions of the ALICE experiment. Each +// evolution is given a name and a list defining the names of the detectors and +// passive elements present. +using DetectorList_t = std::vector; +using DetectorMap_t = std::unordered_map; + +// Parse the detector map from a JSON file. +// Return false if parsing failed. +bool parseDetectorMapfromJSON(const std::string& path, DetectorMap_t& map); + +// Print the DetetectorMap +void printDetMap(const DetectorMap_t& map, const std::string& list = ""); +} // namespace o2::conf + +#endif // O2_DETECTORLISTS_H_ diff --git a/Common/SimConfig/include/SimConfig/SimConfig.h b/Common/SimConfig/include/SimConfig/SimConfig.h index b288083098d6c..b215f22546c8e 100644 --- a/Common/SimConfig/include/SimConfig/SimConfig.h +++ b/Common/SimConfig/include/SimConfig/SimConfig.h @@ -48,43 +48,43 @@ enum class TimeStampMode { // configuration struct (which can be passed around) struct SimConfigData { - std::vector mActiveModules; // list of active modules - std::vector mReadoutDetectors; // list of readout detectors - std::string mMCEngine; // chosen VMC engine - std::string mGenerator; // chosen VMC generator - std::string mTrigger; // chosen VMC generator trigger - unsigned int mNEvents; // number of events to be simulated - std::string mExtKinFileName; // file name of external kinematics file (needed for ext kinematics generator) - std::string mEmbedIntoFileName; // filename containing the reference events to be used for the embedding - unsigned int mStartEvent; // index of first event to be taken - float mBMax; // maximum for impact parameter sampling - bool mIsMT; // chosen MT mode (Geant4 only) - std::string mOutputPrefix; // prefix to be used for output files - std::string mLogSeverity; // severity for FairLogger - std::string mLogVerbosity; // loglevel for FairLogger - std::string mKeyValueTokens; // a string holding arbitrary sequence of key-value tokens - // Foo.parameter1=x,Bar.parameter2=y,Baz.paramter3=hello - // (can be used to **loosely** change any configuration parameter from command-line) - std::string mConfigFile; // path to a JSON or INI config file (file extension is required to determine type). - // values within the config file will override values set in code by the param classes - // but will themselves be overridden by any values given in mKeyValueTokens. - int mPrimaryChunkSize; // defining max granularity for input primaries of a sim job - int mInternalChunkSize; // - ULong_t mStartSeed; // base for random number seeds - int mSimWorkers = 1; // number of parallel sim workers (when it applies) - bool mFilterNoHitEvents = false; // whether to filter out events not leaving any response - std::string mCCDBUrl; // the URL where to find CCDB - uint64_t mTimestamp; // timestamp in ms to anchor transport simulation to + std::vector mActiveModules; // list of active modules + std::vector mReadoutDetectors; // list of readout detectors + std::string mMCEngine; // chosen VMC engine + std::string mGenerator; // chosen VMC generator + std::string mTrigger; // chosen VMC generator trigger + unsigned int mNEvents; // number of events to be simulated + std::string mExtKinFileName; // file name of external kinematics file (needed for ext kinematics generator) + std::string mEmbedIntoFileName; // filename containing the reference events to be used for the embedding + unsigned int mStartEvent; // index of first event to be taken + float mBMax; // maximum for impact parameter sampling + bool mIsMT; // chosen MT mode (Geant4 only) + std::string mOutputPrefix; // prefix to be used for output files + std::string mLogSeverity; // severity for FairLogger + std::string mLogVerbosity; // loglevel for FairLogger + std::string mKeyValueTokens; // a string holding arbitrary sequence of key-value tokens + // Foo.parameter1=x,Bar.parameter2=y,Baz.paramter3=hello + // (can be used to **loosely** change any configuration parameter from command-line) + std::string mConfigFile; // path to a JSON or INI config file (file extension is required to determine type). + // values within the config file will override values set in code by the param classes + // but will themselves be overridden by any values given in mKeyValueTokens. + unsigned int mPrimaryChunkSize; // defining max granularity for input primaries of a sim job + int mInternalChunkSize; // + ULong_t mStartSeed; // base for random number seeds + int mSimWorkers = 1; // number of parallel sim workers (when it applies) + bool mFilterNoHitEvents = false; // whether to filter out events not leaving any response + std::string mCCDBUrl; // the URL where to find CCDB + uint64_t mTimestamp; // timestamp in ms to anchor transport simulation to TimeStampMode mTimestampMode = TimeStampMode::kNow; // telling of timestamp was given as option or defaulted to now - int mRunNumber = -1; // ALICE run number (if set != -1); the timestamp should be compatible - int mField; // L3 field setting in kGauss: +-2,+-5 and 0 - SimFieldMode mFieldMode = SimFieldMode::kDefault; // uniform magnetic field - bool mAsService = false; // if simulation should be run as service/deamon (does not exit after run) - bool mNoGeant = false; // if Geant transport should be turned off (when one is only interested in the generated events) - bool mIsUpgrade = false; // true if the simulation is for Run 5 - std::string mFromCollisionContext = ""; // string denoting a collision context file; If given, this file will be used to determine number of events - bool mForwardKine = false; // true if tracks and event headers are to be published on a FairMQ channel (for reading by other consumers) - bool mWriteToDisc = true; // whether we write simulation products (kine, hits) to disc + int mRunNumber = -1; // ALICE run number (if set != -1); the timestamp should be compatible + int mField; // L3 field setting in kGauss: +-2,+-5 and 0 + SimFieldMode mFieldMode = SimFieldMode::kDefault; // uniform magnetic field + bool mAsService = false; // if simulation should be run as service/deamon (does not exit after run) + bool mNoGeant = false; // if Geant transport should be turned off (when one is only interested in the generated events) + bool mIsUpgrade = false; // true if the simulation is for Run 5 + std::string mFromCollisionContext = ""; // string denoting a collision context file; If given, this file will be used to determine number of events + bool mForwardKine = false; // true if tracks and event headers are to be published on a FairMQ channel (for reading by other consumers) + bool mWriteToDisc = true; // whether we write simulation products (kine, hits) to disc VertexMode mVertexMode = VertexMode::kDiamondParam; // by default we should use die InteractionDiamond parameter ClassDefNV(SimConfigData, 4); @@ -140,6 +140,7 @@ class SimConfig // static helper functions to determine list of active / readout modules // can also be used from outside static void determineActiveModules(std::vector const& input, std::vector const& skipped, std::vector& active, bool isUpgrade = false); + static bool determineActiveModulesList(const std::string& version, std::vector const& input, std::vector const& skipped, std::vector& active); static void determineReadoutDetectors(std::vector const& active, std::vector const& enabledRO, std::vector const& skippedRO, std::vector& finalRO); // helper to parse field option @@ -179,6 +180,9 @@ class SimConfig private: SimConfigData mConfigData; //! + // Filter out skipped elements in the list + static bool filterSkippedElements(std::vector& elements, std::vector const& skipped); + // adjust/overwrite some option settings when collision context is used void adjustFromCollContext(std::string const& collcontextfile, std::string const& prefix); @@ -206,9 +210,9 @@ struct SimReconfigData { std::string configFile; // path to a JSON or INI config file (file extension is required to determine type). // values within the config file will override values set in code by the param classes // but will themselves be overridden by any values given in mKeyValueTokens. - unsigned int primaryChunkSize; // defining max granularity for input primaries of a sim job - ULong_t startSeed; // base for random number seeds - bool stop; // to shut down the service + unsigned int primaryChunkSize; // defining max granularity for input primaries of a sim job + ULong_t startSeed; // base for random number seeds + bool stop; // to shut down the service std::string mFromCollisionContext = ""; // string denoting a collision context file; If given, this file will be used to determine number of events ClassDefNV(SimReconfigData, 1); diff --git a/Common/SimConfig/include/SimConfig/SimDLLoader.h b/Common/SimConfig/include/SimConfig/SimDLLoader.h new file mode 100644 index 0000000000000..e778023b28276 --- /dev/null +++ b/Common/SimConfig/include/SimConfig/SimDLLoader.h @@ -0,0 +1,27 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef SIMDLLOADER_H_ +#define SIMDLLOADER_H_ + +#include "CommonUtils/DLLoaderBase.h" + +namespace o2::conf +{ + +class SimDLLoader : public o2::utils::DLLoaderBase +{ + O2DLLoaderDef(SimDLLoader) +}; + +} // namespace o2::conf + +#endif // SIMDLLOADER_H_ diff --git a/Common/SimConfig/src/DetectorLists.cxx b/Common/SimConfig/src/DetectorLists.cxx new file mode 100644 index 0000000000000..c9132a3cb84a5 --- /dev/null +++ b/Common/SimConfig/src/DetectorLists.cxx @@ -0,0 +1,78 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "SimConfig/DetectorLists.h" +#include +#include +#include +#include +#include + +namespace o2::conf +{ + +bool parseDetectorMapfromJSON(const std::string& path, DetectorMap_t& map) +{ + // Parse JSON file to build map + std::ifstream fileStream(path, std::ios::in); + if (!fileStream.is_open()) { + LOGP(error, "Cannot open '{}'!", path); + return false; + } + rapidjson::IStreamWrapper isw(fileStream); + rapidjson::Document doc; + doc.ParseStream(isw); + if (doc.HasParseError()) { + LOGP(error, "Error parsing provided json file '{}':", path); + LOGP(error, " - Error -> {}", rapidjson::GetParseError_En(doc.GetParseError())); + LOGP(error, " - Offset -> {}", doc.GetErrorOffset()); + return false; + } + + // Clear and rebuild map + map.clear(); + try { + for (auto verItr = doc.MemberBegin(); verItr != doc.MemberEnd(); ++verItr) { + const auto& version = verItr->name.GetString(); + DetectorList_t list; + const auto& elements = doc[version]; + for (const auto& ele : elements.GetArray()) { + list.emplace_back(ele.GetString()); + } + map.emplace(version, list); + } + } catch (const std::exception& e) { + LOGP(error, "Failed to build detector map from file '{}' with '{}'", path, e.what()); + return false; + } + + return true; +} + +void printDetMap(const DetectorMap_t& map, const std::string& list) +{ + if (list.empty()) { + LOGP(error, "List of all available versions including their detectors:"); + for (int i{0}; const auto& [version, elements] : map) { + LOGP(error, " - {: >2d}. {}:", i++, version); + for (int j{0}; const auto& element : elements) { + LOGP(error, "\t\t* {: >2d}.\t{}", j++, element); + } + } + } else { + LOGP(error, "List of available modules for version {}:", list); + for (int j{0}; const auto& element : map.at(list)) { + LOGP(error, "\t* {: >2d}.\t{}", j++, element); + } + } +} + +} // namespace o2::conf diff --git a/Common/SimConfig/src/SimConfig.cxx b/Common/SimConfig/src/SimConfig.cxx index ce5d2687979e1..b7c48bf734924 100644 --- a/Common/SimConfig/src/SimConfig.cxx +++ b/Common/SimConfig/src/SimConfig.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include using namespace o2::conf; namespace bpo = boost::program_options; @@ -34,6 +36,15 @@ void SimConfig::initOptions(boost::program_options::options_description& options "skipModules", bpo::value>()->multitoken()->default_value(std::vector({""}), ""), "list of modules excluded in geometry (precendence over -m")( "readoutDetectors", bpo::value>()->multitoken()->default_value(std::vector(), ""), "list of detectors creating hits, all if not given; added to to active modules")( "skipReadoutDetectors", bpo::value>()->multitoken()->default_value(std::vector(), ""), "list of detectors to skip hit creation (precendence over --readoutDetectors")( + "detectorList", bpo::value()->default_value("ALICE2"), + "Use a specific version of ALICE, e.g., a predefined list." + "There is an 'official' list provided with:" + "\nALICE2 : The default configuration for Run 3" + "\nALICE2.1: The future configuration for Run 4" + "\nALICE3 : The far-future configuration for Run 5-6" + "\nAdditionally one can provide their own custom list of modules which should be included in the geometry." + "\nBy specifiying LIST:JSONFILE where LIST is a list present in JSONFILE." + "\nOne limitation is that LIST cannot have ':' in their name!")( "nEvents,n", bpo::value()->default_value(0), "number of events")( "startEvent", bpo::value()->default_value(0), "index of first event to be used (when applicable)")( "extKinFile", bpo::value()->default_value("Kinematics.root"), @@ -142,14 +153,64 @@ void SimConfig::determineActiveModules(std::vector const& inputargs #endif } } - // now we take out detectors listed as skipped - for (auto& s : skippedModules) { - auto iter = std::find(activeModules.begin(), activeModules.end(), s); - if (iter != activeModules.end()) { - // take it out - activeModules.erase(iter); + filterSkippedElements(activeModules, skippedModules); +} + +bool SimConfig::determineActiveModulesList(const std::string& version, std::vector const& inputargs, std::vector const& skippedModules, std::vector& activeModules) +{ + DetectorList_t modules; + DetectorMap_t map; + if (auto pos = version.find(':'); pos != std::string::npos) { + auto pversion = version.substr(0, pos); + auto ppath = version.substr(pos + 1); + if (!parseDetectorMapfromJSON(ppath, map)) { + LOGP(error, "Could not parse {}; check errors above!", ppath); + return false; + } + if (map.find(pversion) == map.end()) { + LOGP(error, "List {} is not defined in custom JSON file!", pversion); + printDetMap(map); + return false; + } + modules = map[pversion]; + LOGP(info, "Running with version {} from custom detector list '{}'", pversion, ppath); + } else { + // Otherwise check 'official' versions which provided in config + auto o2env = std::getenv("O2_ROOT"); + if (!o2env) { + LOGP(error, "O2_ROOT environment not defined"); + return false; } + const std::string rootpath(fmt::format("{}/share/config/o2simdefaultdetectorlist.json", o2env)); + if (!parseDetectorMapfromJSON(rootpath, map)) { + LOGP(error, "Could not parse {} -> check errors above!", rootpath); + return false; + } + if (map.find(version) == map.end()) { + LOGP(error, "List {} is not defined in 'official' JSON file!", version); + printDetMap(map); + return false; + } + modules = map[version]; + LOGP(info, "Running with official detector version '{}'", version); } + // check if specified modules are in list + if (inputargs.size() != 1 || inputargs[0] != "all") { + std::vector diff; + std::set_difference(inputargs.begin(), inputargs.end(), modules.begin(), modules.end(), std::back_inserter(diff)); + if (!diff.empty()) { + LOGP(error, "Modules specified that are not present in detector list {}", version); + for (int j{0}; const auto& m : diff) { + LOGP(info, " - {: <2}. {}", j++, m); + } + printDetMap(map, version); + return false; + } + } + // Insert into active modules if module is built buy -m or insert all if default for -m is used ("all") + std::copy_if(modules.begin(), modules.end(), std::back_inserter(activeModules), + [&inputargs](const auto& e) { return (inputargs.size() == 1 && inputargs[0] == "all") || (std::find(inputargs.begin(), inputargs.end(), e) != inputargs.end()); }); + return filterSkippedElements(activeModules, skippedModules); } void SimConfig::determineReadoutDetectors(std::vector const& activeModules, std::vector const& enableReadout, std::vector const& disableReadout, std::vector& readoutDetectors) @@ -206,8 +267,20 @@ bool SimConfig::resetFromParsedMap(boost::program_options::variables_map const& mConfigData.mMCEngine = vm["mcEngine"].as(); mConfigData.mNoGeant = vm["noGeant"].as(); - // get final set of active Modules - determineActiveModules(vm["modules"].as>(), vm["skipModules"].as>(), mConfigData.mActiveModules, mConfigData.mIsUpgrade); + // Reset modules and detectors as they are anyway re-parsed + mConfigData.mReadoutDetectors.clear(); + mConfigData.mActiveModules.clear(); + + if (vm["detectorList"].defaulted()) { + // get final set of active Modules + determineActiveModules(vm["modules"].as>(), vm["skipModules"].as>(), mConfigData.mActiveModules, mConfigData.mIsUpgrade); + } else { + // Check for a specific detector version + if (!determineActiveModulesList(vm["detectorList"].as(), vm["modules"].as>(), vm["skipModules"].as>(), mConfigData.mActiveModules)) { + return false; + } + } + if (mConfigData.mNoGeant) { // CAVE is all that's needed (and that will be built either way), so clear all modules and set the O2TrivialMCEngine mConfigData.mActiveModules.clear(); @@ -333,6 +406,34 @@ bool SimConfig::parseFieldString(std::string const& fieldstring, int& fieldvalue return true; } +bool SimConfig::filterSkippedElements(std::vector& elements, std::vector const& skipped) +{ + for (auto& s : skipped) { + if (s.empty()) { // nothing to skip here + continue; + } + auto iter = std::find(elements.begin(), elements.end(), s); + if (iter != elements.end()) { + // take it out + elements.erase(iter); + } else { + LOGP(error, "Skipped modules specified that are not present in built modules!"); + LOGP(error, "Built modules:"); + for (int j{0}; const auto& m : elements) { + LOGP(error, " + {: <2}. {}", j++, m); + } + std::vector diff; + std::set_difference(skipped.begin(), skipped.end(), elements.begin(), elements.end(), std::back_inserter(diff)); + LOGP(error, "Specified skipped modules not present in built modules:"); + for (int j{0}; const auto& m : diff) { + LOGP(error, " - {: <2}. {}", j++, m); + } + return false; + } + } + return true; +} + void SimConfig::adjustFromCollContext(std::string const& collcontextfile, std::string const& prefix) { // When we use pregenerated collision contexts, some options @@ -384,8 +485,6 @@ void SimConfig::adjustFromCollContext(std::string const& collcontextfile, std::s bool SimConfig::resetFromArguments(int argc, char* argv[]) { - namespace bpo = boost::program_options; - // Arguments parsing bpo::variables_map vm; bpo::options_description desc("Allowed options"); diff --git a/Common/SimConfig/src/SimDLLoader.cxx b/Common/SimConfig/src/SimDLLoader.cxx new file mode 100644 index 0000000000000..ed15a8b0cef6a --- /dev/null +++ b/Common/SimConfig/src/SimDLLoader.cxx @@ -0,0 +1,13 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "SimConfig/SimDLLoader.h" +O2DLLoaderImpl(o2::conf::SimDLLoader) diff --git a/Common/Utils/CMakeLists.txt b/Common/Utils/CMakeLists.txt index 7f650b973990b..786ccc8f784fe 100644 --- a/Common/Utils/CMakeLists.txt +++ b/Common/Utils/CMakeLists.txt @@ -24,6 +24,7 @@ o2_add_library(CommonUtils src/NameConf.cxx src/IRFrameSelector.cxx src/DebugStreamer.cxx + src/DLLoaderBase.cxx PUBLIC_LINK_LIBRARIES ROOT::Hist ROOT::Tree Boost::iostreams O2::CommonDataFormat O2::Headers FairLogger::FairLogger O2::MathUtils TBB::tbb) @@ -45,6 +46,7 @@ o2_target_root_dictionary(CommonUtils include/CommonUtils/KeyValParam.h include/CommonUtils/VerbosityConfig.h include/CommonUtils/FileFetcher.h + include/CommonUtils/DLLoaderBase.h include/CommonUtils/NameConf.h include/CommonUtils/IRFrameSelector.h include/CommonUtils/DebugStreamer.h) diff --git a/Common/Utils/include/CommonUtils/DLLoaderBase.h b/Common/Utils/include/CommonUtils/DLLoaderBase.h new file mode 100644 index 0000000000000..61d349876c92e --- /dev/null +++ b/Common/Utils/include/CommonUtils/DLLoaderBase.h @@ -0,0 +1,266 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// \brief A thin wrapper to manage dynamic library loading, based around boost::dll + +#ifndef DLLOADER_H_ +#define DLLOADER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "dlfcn.h" + +#if defined(__APPLE__) +#define DLLOADER_MAC_LINUX(mac, linux) mac +#else +#define DLLOADER_MAC_LINUX(mac, linux) linux +#endif + +#include "Framework/Logger.h" + +namespace o2::utils +{ + +// Manages dynamic loading and unloading (or rather ensuring they are not +// unloaded for the duration of the program) of libraries and symbol lookups. It +// ensures thread-safety through the use of a mutex and implements the Meyers +// Singleton pattern to provide a single instance of the manager. +template +class DLLoaderBase +{ + public: + struct filename_decorations { + static constexpr const char* prefix = "lib"; // same prefix on mac and linux + static constexpr const char* suffix = DLLOADER_MAC_LINUX(".dylib", ".so"); + }; + enum Options { + none = 0, + global = RTLD_GLOBAL, + local = RTLD_LOCAL, + no_delete = RTLD_NODELETE, + no_load = RTLD_NOLOAD, + lazy = RTLD_LAZY, + }; + using handle_t = void; + using handle_ptr_t = handle_t*; + struct HandleDeleter { + void operator()(handle_ptr_t p) + { + if (p != nullptr) { + dlclose(p); + } + } + }; + using library_t = std::unique_ptr; + + // Returns the singleton instance of the manager. Any function should only be + // accessed through an instance. This being a singleton serves two purposes: + // 1. Libraries are loaded only once. + // 2. Once loaded they are not again unloaded until the end of the program. + static DerivedType& Instance() + { + return DerivedType::sInstance; + } + + // Loads a dynamic library by its name and stores its handle. Returns true + // if the library is successfully loaded or already loaded. + bool addLibrary(const std::string& library) + { + const std::lock_guard lock(mLock); + + if (mLibraries.find(library) != mLibraries.end()) { + return true; // Library already loaded + } + + if (mO2Path.empty()) { + if (const auto* path = std::getenv("O2_ROOT")) { + mO2Path = path; + } else { + LOGP(error, "$O2_ROOT not set!"); + return false; + } + } + + auto path = getO2Path(library); + if (!std::filesystem::exists(path)) { + LOGP(error, "Library under '{}' does not exist!", path); + return false; + } + + try { + auto lib = std::unique_ptr(dlopen(path.c_str(), mLoadPolicy)); + if (lib == nullptr) { + throw std::runtime_error("Library handle is nullptr!"); + } + mLibraries[library] = std::move(lib); + LOGP(info, "Loaded dynamic library '{}' from '{}'", library, path); + return true; + } catch (std::exception& e) { + LOGP(error, "Failed to load library (path='{}'), failed reason: '{}'", path, e.what()); + return false; + } catch (...) { + LOGP(error, "Failed to load library (path='{}') for unknown reason!", path.c_str()); + return false; + } + } + + // Unloads a given library returns true if this succeeded. + // + // Nota bene: Actually, we have very little control here when the unloading + // hapens since the linkder decides this based on if there is any reference + // left. And even if the reference counter goes to zero the linker is free to + // leave the library loaded and clean up whenever it wants. + bool unloadLibrary(const std::string& library) + { + const std::lock_guard lock(mLock); + + if (auto it = mLibraries.find(library); it != mLibraries.end()) { + mLibraries.erase(it); + return true; + } + + LOGP(error, "No '{}' library found, cannot unload it!", library); + return false; + } + + // Resets all loaded libraries and O2Path, this invalidates all outside kept + // references. + void reset() + { + mO2Path.clear(); + mLibraries.clear(); + } + + // Checks if a library contains a specific symbol. + bool hasSymbol(const std::string& library, const std::string& symbol) + { + const std::lock_guard lock(mLock); + + if (mLibraries.find(library) == mLibraries.end()) { + // Library not loaded, attempt to load it + if (!addLibrary(library)) { + return false; + } + } + + dlerror(); // clear previous error + + // Checks if the symbol exists but does not load it. + handle_ptr_t ptr = dlsym(mLibraries[library].get(), symbol.c_str()); + if (const auto* err = dlerror(); err != nullptr) { + LOGP(error, "Did not get {} from {}; error: {}", symbol, library, err); + } + + return ptr != nullptr; + } + + // Executes a function from a loaded library or return nullopt + template + std::optional executeFunction(const std::string& library, const std::string& fname, Args... args) + { + using Func_t = Ret (*)(Args...); + + const std::lock_guard lock(mLock); + + if (fname.empty()) { + LOGP(error, "Function name cannot be empty!"); + return std::nullopt; + } + + if (mLibraries.find(library) == mLibraries.end()) { + // Library not loaded, attempt to load it + if (!addLibrary(library)) { + return std::nullopt; + } + } + + const auto& lib = mLibraries[library].get(); + if (!hasSymbol(library, fname)) { + LOGP(error, "Library '{}' does not have a symbol '{}'", library, fname); + return std::nullopt; + } + + dlerror(); // Clear previous error + + auto func = (Func_t)dlsym(lib, fname.c_str()); + if (const auto* err = dlerror(); err != nullptr) { + LOGP(error, "Did not get {} from {}; error: {}", fname, library, err); + return std::nullopt; + } + + if (func == nullptr) { + LOGP(error, "Library '{}' does not have a symbol '{}' with {}", library, fname, getTypeName()); + return std::nullopt; + } + + // Execute function and return its return value + return func(args...); + } + + // Wrapper for function execution which fatals if execution fails + template + Ret executeFunctionAlias(const std::string& library, const std::string& fname, Args... args) + { + if (auto opt = executeFunction(library, fname, args...)) { + return *opt; + } + + LOGP(fatal, "Execution of '{}' from '{}' failed spectaculary!", fname, library); + __builtin_unreachable(); // is this safe, AFACIT only gcc and clang are supported anyway + } + + // Delete copy and move constructors to enforce singleton pattern. + DLLoaderBase(const DLLoaderBase&) = delete; + DLLoaderBase& operator=(const DLLoaderBase&) = delete; + DLLoaderBase(DLLoaderBase&&) = delete; + DLLoaderBase& operator=(DLLoaderBase&&) = delete; + + protected: + // Constructor and destructor are protected to enforce singleton pattern. + DLLoaderBase() = default; + ~DLLoaderBase() = default; + + private: + // Returns the full path to a O2 shared library.. + [[nodiscard]] std::string getO2Path(const std::string& library) const + { + return mO2Path + "/lib/" + filename_decorations::prefix + library + filename_decorations::suffix; + } + + // Returns the demangled type name of a prototype, e.g., for pretty printing. + template + [[nodiscard]] auto getTypeName() -> std::string + { + return typeid(ProtoType).name(); // TODO + } + + std::unordered_map mLibraries{}; // Pointers to loaded libraries, calls `unload()' for each library, e.g., correctly destroy this object + std::recursive_mutex mLock{}; // While a recursive mutex is more expansive it makes locking easier + std::string mO2Path{}; // Holds the path O2 dynamic library determined by $O2_ROOT + Options mLoadPolicy{Options::lazy}; // load resolution policy +}; + +} // namespace o2::utils + +#define O2DLLoaderDef(classname) \ + private: \ + static classname sInstance; \ + classname() = default; \ + friend class o2::utils::DLLoaderBase; + +#define O2DLLoaderImpl(classname) classname classname::sInstance; + +#endif // DLLOADER_H_ diff --git a/Common/Utils/src/DLLoaderBase.cxx b/Common/Utils/src/DLLoaderBase.cxx new file mode 100644 index 0000000000000..1e4ab97604794 --- /dev/null +++ b/Common/Utils/src/DLLoaderBase.cxx @@ -0,0 +1,12 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "CommonUtils/DLLoaderBase.h" diff --git a/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h b/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h index 63a1f36c58fab..c48f0f942d29c 100644 --- a/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h +++ b/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h @@ -79,6 +79,12 @@ class Detector : public o2::base::DetImpl /// kFALSE for inactive detectors Detector(Bool_t active, TString name = "ITS"); + // Factory method + static o2::base::Detector* create(const char* name, bool active) + { + return new Detector(active, name); + } + /// Default constructor Detector(); diff --git a/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx b/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx index c40355f0f34d8..d005c9ea9858a 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx @@ -1317,3 +1317,11 @@ Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TV } ClassImp(o2::its::Detector); + +// Define Factory method for calling from the outside +extern "C" { +o2::base::Detector* create_detector_its(const char* name, bool active) +{ + return o2::its::Detector::create(name, active); +} +} diff --git a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h index 74b9241417be0..507ba992e2715 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h @@ -63,11 +63,17 @@ class Detector : public o2::base::DetImpl kAlumina1 = 26 }; /** Name : Detector Name - * Active: kTRUE for active detectors (ProcessHits() will be called) - * kFALSE for inactive detectors - */ + * Active: kTRUE for active detectors (ProcessHits() will be called) + * kFALSE for inactive detectors + */ Detector(Bool_t Active); + // Factory method + static o2::base::Detector* create(bool active) + { + return new Detector(active); + } + /** default constructor */ Detector(); @@ -78,8 +84,8 @@ class Detector : public o2::base::DetImpl void InitializeO2Detector() override; /** this method is called for each step during simulation - * (see FairMCApplication::Stepping()) - */ + * (see FairMCApplication::Stepping()) + */ // virtual Bool_t ProcessHitsOrig( FairVolume* v=0); Bool_t ProcessHits(FairVolume* v = nullptr) override; @@ -105,8 +111,8 @@ class Detector : public o2::base::DetImpl void ConstructGeometry() override; /** This method is an example of how to add your own point - * of type DetectorPoint to the clones array - */ + * of type DetectorPoint to the clones array + */ Point* addHit(float x, float y, float z, float time, float nElectrons, float trackID, float detID); /// Copied from AliRoot - should go to someplace else @@ -130,8 +136,8 @@ class Detector : public o2::base::DetImpl Double_t Gamma(Double_t k); /** The following methods can be implemented if you need to make - * any optional action in your detector during the transport. - */ + * any optional action in your detector during the transport. + */ void EndOfEvent() override; void FinishPrimary() override { ; } diff --git a/Detectors/TPC/simulation/src/Detector.cxx b/Detectors/TPC/simulation/src/Detector.cxx index 60dcc542c70ff..367abdc1a753a 100644 --- a/Detectors/TPC/simulation/src/Detector.cxx +++ b/Detectors/TPC/simulation/src/Detector.cxx @@ -3216,3 +3216,11 @@ std::string Detector::getHitBranchNames(int probe) const } ClassImp(o2::tpc::Detector); + +// Define Factory method for calling from the outside +extern "C" { +o2::base::Detector* create_detector_tpc(bool active) +{ + return o2::tpc::Detector::create(active); +} +} diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h index 47a48167e0562..5b777641dbe99 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h @@ -34,6 +34,12 @@ class Detector : public o2::base::DetImpl Detector(); ~Detector(); + // Factory method + static o2::base::Detector* create(bool active) + { + return new Detector(active); + } + void ConstructGeometry() override; o2::itsmft::Hit* addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos, @@ -104,4 +110,4 @@ struct UseShm { } // namespace base } // namespace o2 #endif -#endif \ No newline at end of file +#endif diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index d6c4613b6b589..7a16d0643942c 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -366,3 +366,11 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP } // namespace o2 ClassImp(o2::trk::Detector); + +// Define Factory method for calling from the outside +extern "C" { +o2::base::Detector* create_detector_trk(bool active) +{ + return o2::trk::Detector::create(active); +} +} diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index ca4d8126a84d5..826cb0ea06ade 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -114,7 +114,6 @@ if(ENABLE_UPGRADES) set(upgradeTargets O2::Alice3DetectorsPassive O2::ITS3Simulation - O2::TRKSimulation O2::FT3Simulation O2::FCTSimulation O2::IOTOFSimulation @@ -124,10 +123,9 @@ if(ENABLE_UPGRADES) endif() o2_add_test_root_macro(build_geometry.C - PUBLIC_LINK_LIBRARIES O2::DetectorsPassive + PUBLIC_LINK_LIBRARIES O2::SimConfig + O2::DetectorsPassive O2::Field - O2::TPCSimulation - O2::ITSSimulation O2::MFTSimulation O2::MCHSimulation O2::MIDSimulation @@ -183,8 +181,6 @@ o2_add_test_root_macro(o2sim.C PUBLIC_LINK_LIBRARIES O2::Generators O2::DetectorsPassive O2::Field - O2::TPCSimulation - O2::ITSSimulation O2::MFTSimulation O2::MCHSimulation O2::MIDSimulation diff --git a/macro/build_geometry.C b/macro/build_geometry.C index 3712f6bf85a93..aebfbee7ce283 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -23,8 +23,6 @@ #include "DetectorsPassive/Hall.h" #include "DetectorsPassive/Pipe.h" #include -#include -#include #include #include #include @@ -47,10 +45,10 @@ #include #include "DetectorsCommonDataFormats/UpgradesStatus.h" #include +#include #endif #ifdef ENABLE_UPGRADES -#include #include #include #include @@ -62,6 +60,8 @@ #include #endif +using Return = o2::base::Detector*; + void finalize_geometry(FairRunSim* run); bool isActivated(std::string s) @@ -221,17 +221,20 @@ void build_geometry(FairRunSim* run = nullptr) if (isActivated("TPC")) { // tpc - addReadoutDetector(new o2::tpc::Detector(isReadout("TPC"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2TPCSimulation", "create_detector_tpc", isReadout("TPC"))); } #ifdef ENABLE_UPGRADES if (isActivated("IT3")) { // IT3 - addReadoutDetector(new o2::its::Detector(isReadout("IT3"), "IT3")); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2ITSSimulation", "create_detector_its", "IT3", isReadout("IT3"))); } if (isActivated("TRK")) { // ALICE 3 TRK - addReadoutDetector(new o2::trk::Detector(isReadout("TRK"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2TRKSimulation", "create_detector_trk", isReadout("TRK"))); } if (isActivated("FT3")) { @@ -267,7 +270,8 @@ void build_geometry(FairRunSim* run = nullptr) if (isActivated("ITS")) { // its - addReadoutDetector(new o2::its::Detector(isReadout("ITS"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2ITSSimulation", "create_detector_its", "ITS", isReadout("ITS"))); } if (isActivated("MFT")) { diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index 4881df6ea27a2..b1d09db4d02c8 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -148,6 +148,8 @@ o2_add_dpl_workflow(mctracks-to-aod-simple-task o2_data_file(COPY o2simtopology_template.json DESTINATION config) +o2_data_file(COPY o2simdefaultdetectorlist.json DESTINATION config) + # * # add a complex simulation as a unit test (if simulation was enabled) # perform # * # some checks on kinematics and track references diff --git a/run/o2simdefaultdetectorlist.json b/run/o2simdefaultdetectorlist.json new file mode 100644 index 0000000000000..752d3633672ac --- /dev/null +++ b/run/o2simdefaultdetectorlist.json @@ -0,0 +1,64 @@ +{ + "ALICE2": [ + "ITS", + "TPC", + "TRD", + "TOF", + "PHS", + "EMC", + "HMP", + "MFT", + "MCH", + "MID", + "ZDC", + "FT0", + "FV0", + "FDD", + "CTP", + "HALL", + "MAG", + "DIPO", + "COMP", + "PIPE", + "ABSO", + "SHIL" + ], + "ALICE2.1": [ + "IT3", + "TPC", + "TRD", + "TOF", + "PHS", + "EMC", + "HMP", + "MFT", + "MCH", + "MID", + "ZDC", + "FT0", + "FV0", + "FDD", + "CTP", + "FOC", + "HALL", + "MAG", + "DIPO", + "COMP", + "PIPE", + "ABSO", + "SHIL" + ], + "ALICE3": [ + "TRK", + "FT3", + "FCT", + "RCH", + "MI3", + "ECL", + "HALL", + "MAG", + "A3IP", + "A3ABSO", + "A3MAG" + ] +} From fdef300edea5a56c73437904979754690d3986fa Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 28 May 2024 13:24:13 +0200 Subject: [PATCH 0265/2997] AOD: Disable MC tables for data (#13105) Now MC tables (even empty ones) are only written to disk when MC is active. Signed-off-by: Felix Schlepper --- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 66 ++++++++++++------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index da76ad0bb7738..466f883948bce 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -1788,15 +1788,6 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto fwdTracksCursor = createTableCursor(pc); auto fwdTracksCovCursor = createTableCursor(pc); auto fwdTrkClsCursor = createTableCursor(pc); - auto mcColLabelsCursor = createTableCursor(pc); - auto mcCollisionsCursor = createTableCursor(pc); - auto hepmcXSectionsCursor = createTableCursor(pc); - auto hepmcPdfInfosCursor = createTableCursor(pc); - auto hepmcHeavyIonsCursor = createTableCursor(pc); - auto mcMFTTrackLabelCursor = createTableCursor(pc); - auto mcFwdTrackLabelCursor = createTableCursor(pc); - auto mcParticlesCursor = createTableCursor(pc); - auto mcTrackLabelCursor = createTableCursor(pc); auto mftTracksCursor = createTableCursor(pc); auto tracksCursor = createTableCursor(pc); auto tracksCovCursor = createTableCursor(pc); @@ -1810,10 +1801,33 @@ void AODProducerWorkflowDPL::run(ProcessingContext& pc) auto hmpCursor = createTableCursor(pc); auto caloCellsCursor = createTableCursor(pc); auto caloCellsTRGTableCursor = createTableCursor(pc); - auto mcCaloLabelsCursor = createTableCursor(pc); auto cpvClustersCursor = createTableCursor(pc); auto originCursor = createTableCursor(pc); + // Declare MC cursors type without adding the output for a table + o2::framework::Produces mcColLabelsCursor; + o2::framework::Produces mcCollisionsCursor; + o2::framework::Produces hepmcXSectionsCursor; + o2::framework::Produces hepmcPdfInfosCursor; + o2::framework::Produces hepmcHeavyIonsCursor; + o2::framework::Produces mcMFTTrackLabelCursor; + o2::framework::Produces mcFwdTrackLabelCursor; + o2::framework::Produces mcParticlesCursor; + o2::framework::Produces mcTrackLabelCursor; + o2::framework::Produces mcCaloLabelsCursor; + if (mUseMC) { // This creates the actual writercursor + mcColLabelsCursor = createTableCursor(pc); + mcCollisionsCursor = createTableCursor(pc); + hepmcXSectionsCursor = createTableCursor(pc); + hepmcPdfInfosCursor = createTableCursor(pc); + hepmcHeavyIonsCursor = createTableCursor(pc); + mcMFTTrackLabelCursor = createTableCursor(pc); + mcFwdTrackLabelCursor = createTableCursor(pc); + mcParticlesCursor = createTableCursor(pc); + mcTrackLabelCursor = createTableCursor(pc); + mcCaloLabelsCursor = createTableCursor(pc); + } + std::unique_ptr mcReader; if (mUseMC) { mcReader = std::make_unique("collisioncontext.root"); @@ -2926,14 +2940,6 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo OutputForTable::spec(), OutputForTable::spec(), OutputForTable::spec(), - OutputForTable::spec(), - OutputForTable::spec(), - OutputForTable::spec(), - OutputForTable::spec(), - OutputForTable::spec(), - OutputForTable::spec(), - OutputForTable::spec(), - OutputForTable::spec(), OutputForTable::spec(), OutputForTable::spec(), OutputForTable::spec(), @@ -2952,18 +2958,30 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo OutputForTable::spec(), OutputForTable::spec(), OutputForTable::spec(), - OutputForTable::spec(), OutputForTable::spec(), - // todo: use addTableToOuput helper? - // currently the description is MCCOLLISLABEL, so - // the name in AO2D would be O2mccollislabel - // addTableToOutput(outputs); - {OutputLabel{"McCollisionLabels"}, "AOD", "MCCOLLISIONLABEL", 0, Lifetime::Timeframe}, OutputSpec{"TFN", "TFNumber"}, OutputSpec{"TFF", "TFFilename"}, OutputSpec{"AMD", "AODMetadataKeys"}, OutputSpec{"AMD", "AODMetadataVals"}}; + if (useMC) { + outputs.insert(outputs.end(), + {OutputForTable::spec(), + OutputForTable::spec(), + OutputForTable::spec(), + OutputForTable::spec(), + OutputForTable::spec(), + OutputForTable::spec(), + OutputForTable::spec(), + OutputForTable::spec(), + OutputForTable::spec(), + // todo: use addTableToOuput helper? + // currently the description is MCCOLLISLABEL, so + // the name in AO2D would be O2mccollislabel + // addTableToOutput(outputs); + {OutputLabel{"McCollisionLabels"}, "AOD", "MCCOLLISIONLABEL", 0, Lifetime::Timeframe}}); + } + return DataProcessorSpec{ "aod-producer-workflow", dataRequest->inputs, From ce408db49eea3662f2fa2ac7a5d719078078b359 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 28 May 2024 12:37:28 +0200 Subject: [PATCH 0266/2997] Cleanup headers --- Detectors/ZDC/calib/src/InterCalibSpec.cxx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Detectors/ZDC/calib/src/InterCalibSpec.cxx b/Detectors/ZDC/calib/src/InterCalibSpec.cxx index 1a22fc1fe17c1..2c2184b6bca75 100644 --- a/Detectors/ZDC/calib/src/InterCalibSpec.cxx +++ b/Detectors/ZDC/calib/src/InterCalibSpec.cxx @@ -17,7 +17,6 @@ #include #include #include -#include "CCDB/BasicCCDBManager.h" #include "CCDB/CCDBTimeStampUtils.h" #include "CCDB/CcdbApi.h" #include "Framework/Logger.h" @@ -35,7 +34,6 @@ #include "ZDCBase/ModuleConfig.h" #include "CommonUtils/NameConf.h" #include "CommonUtils/MemFileHelper.h" -#include "CCDB/BasicCCDBManager.h" #include "CCDB/CCDBTimeStampUtils.h" #include "ZDCReconstruction/RecoConfigZDC.h" #include "ZDCReconstruction/ZDCEnergyParam.h" @@ -45,9 +43,7 @@ using namespace o2::framework; -namespace o2 -{ -namespace zdc +namespace o2::zdc { InterCalibSpec::InterCalibSpec() @@ -234,5 +230,4 @@ framework::DataProcessorSpec getInterCalibSpec() Options{{"verbosity-level", o2::framework::VariantType::Int, 1, {"Verbosity level"}}}}; } -} // namespace zdc } // namespace o2 From 68e0e4fdae52f2e5795954f0baf1c1fb7b7ae4c7 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 28 May 2024 12:34:49 +0200 Subject: [PATCH 0267/2997] DPL: drop unneeded signpost protection --- Framework/Core/src/DataProcessingDevice.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 6b926d92353be..f256b49bcc3af 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -1828,10 +1828,8 @@ void DataProcessingDevice::handleData(ServiceRegistryRef ref, InputChannelInfo& // We only deal with the tracking of parts if the log is enabled. // This is because in principle we should track the size of each of // the parts and sum it up. Not for now. - if (O2_LOG_ENABLED(parts) == true) { - O2_SIGNPOST_ID_FROM_POINTER(pid, parts, headerData); - O2_SIGNPOST_START(parts, pid, "parts", "Processing DataHeader with splitPayloadParts %d and splitPayloadIndex %d", dh->splitPayloadParts, dh->splitPayloadIndex); - } + O2_SIGNPOST_ID_FROM_POINTER(pid, parts, headerData); + O2_SIGNPOST_START(parts, pid, "parts", "Processing DataHeader with splitPayloadParts %d and splitPayloadIndex %d", dh->splitPayloadParts, dh->splitPayloadIndex); if (!dph) { insertInputInfo(pi, 2, InputType::Invalid, info.id); O2_SIGNPOST_EVENT_EMIT_ERROR(device, cid, "handle_data", "Header stack does not contain DataProcessingHeader"); From 5b5abc2382d6cf7e86689512e0ac48dc42d1ee25 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 28 May 2024 17:41:43 +0200 Subject: [PATCH 0268/2997] SIM: Fix detectorList parsing set_difference only accepts sorted lists, when testing I think I only ever tested with ITS/IT3 which is the first detector and thus it worked always fine... Signed-off-by: Felix Schlepper --- Common/SimConfig/src/SimConfig.cxx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Common/SimConfig/src/SimConfig.cxx b/Common/SimConfig/src/SimConfig.cxx index b7c48bf734924..eede95c89997b 100644 --- a/Common/SimConfig/src/SimConfig.cxx +++ b/Common/SimConfig/src/SimConfig.cxx @@ -20,7 +20,6 @@ #include #include #include -#include using namespace o2::conf; namespace bpo = boost::program_options; @@ -197,7 +196,11 @@ bool SimConfig::determineActiveModulesList(const std::string& version, std::vect // check if specified modules are in list if (inputargs.size() != 1 || inputargs[0] != "all") { std::vector diff; - std::set_difference(inputargs.begin(), inputargs.end(), modules.begin(), modules.end(), std::back_inserter(diff)); + for (const auto& in : inputargs) { + if (std::find(modules.begin(), modules.end(), in) == std::end(modules)) { + diff.emplace_back(in); + } + } if (!diff.empty()) { LOGP(error, "Modules specified that are not present in detector list {}", version); for (int j{0}; const auto& m : diff) { @@ -423,7 +426,11 @@ bool SimConfig::filterSkippedElements(std::vector& elements, std::v LOGP(error, " + {: <2}. {}", j++, m); } std::vector diff; - std::set_difference(skipped.begin(), skipped.end(), elements.begin(), elements.end(), std::back_inserter(diff)); + for (const auto& skip : skipped) { + if (std::find(elements.begin(), elements.end(), skip) == std::end(elements)) { + diff.emplace_back(skip); + } + } LOGP(error, "Specified skipped modules not present in built modules:"); for (int j{0}; const auto& m : diff) { LOGP(error, " - {: <2}. {}", j++, m); From 9ddc990c75e898ac6c0e39cd5b45c01328c6a1b0 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 28 May 2024 16:21:28 +0200 Subject: [PATCH 0269/2997] o2-sim: Apply dynamic detector lib loading to all detectors * code reduction: - automatic factory method via DetImpl base class - helper macro to implement extern "C" hooks * application of dynamic loading during geometry construction and in the HitMerger * removal of detector linking to o2-sim in CMakeFile The benefit is ~60MB of memory reduction when only simulating single detectors `o2-sim-serial -m TPC` and a faster load time in general. --- .../Base/include/DetectorsBase/Detector.h | 23 +++++ Detectors/CPV/simulation/src/Detector.cxx | 1 + Detectors/EMCAL/simulation/src/Detector.cxx | 1 + Detectors/FIT/FDD/simulation/src/Detector.cxx | 1 + Detectors/FIT/FT0/simulation/src/Detector.cxx | 1 + Detectors/FIT/FV0/simulation/src/Detector.cxx | 1 + Detectors/HMPID/simulation/src/Detector.cxx | 1 + .../include/ITSSimulation/Detector.h | 6 -- .../ITSMFT/ITS/simulation/src/Detector.cxx | 5 +- .../ITSMFT/MFT/simulation/src/Detector.cxx | 1 + .../MUON/MCH/Simulation/src/Detector.cxx | 1 + .../MUON/MID/Simulation/src/Detector.cxx | 1 + Detectors/PHOS/simulation/src/Detector.cxx | 1 + Detectors/TOF/simulation/src/Detector.cxx | 1 + .../include/TPCSimulation/Detector.h | 6 -- Detectors/TPC/simulation/src/Detector.cxx | 8 +- Detectors/TRD/simulation/src/Detector.cxx | 1 + .../ALICE3/ECal/simulation/src/Detector.cxx | 3 +- .../ALICE3/FCT/simulation/src/Detector.cxx | 1 + .../ALICE3/FT3/simulation/src/Detector.cxx | 1 + .../ALICE3/MID/simulation/src/Detector.cxx | 3 +- .../ALICE3/RICH/simulation/src/Detector.cxx | 3 +- .../include/TRKSimulation/Detector.h | 6 -- .../ALICE3/TRK/simulation/src/Detector.cxx | 9 +- Detectors/ZDC/simulation/src/Detector.cxx | 1 + macro/build_geometry.C | 78 +++++++-------- run/CMakeLists.txt | 23 ----- run/O2HitMerger.h | 96 +++++++++---------- 28 files changed, 134 insertions(+), 150 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/Detector.h b/Detectors/Base/include/DetectorsBase/Detector.h index 1432d93c53821..4a44a7bf84154 100644 --- a/Detectors/Base/include/DetectorsBase/Detector.h +++ b/Detectors/Base/include/DetectorsBase/Detector.h @@ -41,6 +41,16 @@ #include +// macro implementation helper to code unmanged "C" function +// constructing a detector +#define O2DetectorCreatorImpl(creatorfuncname, detname) \ + extern "C" { \ + o2::base::Detector* create_detector_##detname(bool active) \ + { \ + return creatorfuncname(active); \ + } \ + } + namespace o2::base { @@ -302,6 +312,19 @@ class DetImpl : public o2::base::Detector // offer same constructors as base using Detector::Detector; + /// automatic implementation of static Detector factory functions + template + static o2::base::Detector* create(Args&&... args) + { + if constexpr (std::is_constructible_v) { + return new Det(std::forward(args)...); + } else { + static_assert(std::is_constructible_v, + "No matching constructor found in Derived class."); + return nullptr; + } + } + // default implementation for getHitBranchNames std::string getHitBranchNames(int probe) const override { diff --git a/Detectors/CPV/simulation/src/Detector.cxx b/Detectors/CPV/simulation/src/Detector.cxx index fda5751464f01..e4b4e3554ccd4 100644 --- a/Detectors/CPV/simulation/src/Detector.cxx +++ b/Detectors/CPV/simulation/src/Detector.cxx @@ -37,6 +37,7 @@ using namespace o2::cpv; ClassImp(Detector); +O2DetectorCreatorImpl(o2::cpv::Detector::create, cpv); Detector::Detector(Bool_t active) : o2::base::DetImpl("CPV", active), diff --git a/Detectors/EMCAL/simulation/src/Detector.cxx b/Detectors/EMCAL/simulation/src/Detector.cxx index e5163dbda8288..c6ed34935dd96 100644 --- a/Detectors/EMCAL/simulation/src/Detector.cxx +++ b/Detectors/EMCAL/simulation/src/Detector.cxx @@ -38,6 +38,7 @@ using namespace o2::emcal; ClassImp(Detector); +O2DetectorCreatorImpl(o2::emcal::Detector::create, emc); Detector::Detector(Bool_t active) : o2::base::DetImpl("EMC", active), diff --git a/Detectors/FIT/FDD/simulation/src/Detector.cxx b/Detectors/FIT/FDD/simulation/src/Detector.cxx index 3bb945ddd1bba..f4777e18bb72d 100644 --- a/Detectors/FIT/FDD/simulation/src/Detector.cxx +++ b/Detectors/FIT/FDD/simulation/src/Detector.cxx @@ -39,6 +39,7 @@ using o2::fdd::Geometry; using o2::fdd::Hit; ClassImp(o2::fdd::Detector); +O2DetectorCreatorImpl(o2::fdd::Detector::create, fdd); //_____________________________________________________________________________ Detector::Detector(Bool_t Active) diff --git a/Detectors/FIT/FT0/simulation/src/Detector.cxx b/Detectors/FIT/FT0/simulation/src/Detector.cxx index ea856eb204802..462e56e7d2e61 100644 --- a/Detectors/FIT/FT0/simulation/src/Detector.cxx +++ b/Detectors/FIT/FT0/simulation/src/Detector.cxx @@ -42,6 +42,7 @@ using namespace o2::ft0; using o2::ft0::Geometry; ClassImp(Detector); +O2DetectorCreatorImpl(o2::ft0::Detector::create, ft0); Detector::Detector(Bool_t Active) : o2::base::DetImpl("FT0", Active), mIdSens1(0), mPMTeff(nullptr), mHits(o2::utils::createSimVector()), mTrackIdTop(-1), mTrackIdMCPtop(-1) diff --git a/Detectors/FIT/FV0/simulation/src/Detector.cxx b/Detectors/FIT/FV0/simulation/src/Detector.cxx index 8cf1f5530e93d..c2e0fa1a06853 100644 --- a/Detectors/FIT/FV0/simulation/src/Detector.cxx +++ b/Detectors/FIT/FV0/simulation/src/Detector.cxx @@ -30,6 +30,7 @@ using namespace o2::fv0; using o2::fv0::Geometry; ClassImp(Detector); +O2DetectorCreatorImpl(o2::fv0::Detector::create, fv0); Detector::Detector() : o2::base::DetImpl("FV0", kTRUE), diff --git a/Detectors/HMPID/simulation/src/Detector.cxx b/Detectors/HMPID/simulation/src/Detector.cxx index 83bab71e7177d..0bb076a1ddee5 100644 --- a/Detectors/HMPID/simulation/src/Detector.cxx +++ b/Detectors/HMPID/simulation/src/Detector.cxx @@ -1379,3 +1379,4 @@ void Detector::defineOpticalProperties() } // end namespace o2 ClassImp(o2::hmpid::Detector); +O2DetectorCreatorImpl(o2::hmpid::Detector::create, hmp); \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h b/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h index c48f0f942d29c..63a1f36c58fab 100644 --- a/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h +++ b/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h @@ -79,12 +79,6 @@ class Detector : public o2::base::DetImpl /// kFALSE for inactive detectors Detector(Bool_t active, TString name = "ITS"); - // Factory method - static o2::base::Detector* create(const char* name, bool active) - { - return new Detector(active, name); - } - /// Default constructor Detector(); diff --git a/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx b/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx index d005c9ea9858a..188fb7b7394b2 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx @@ -1318,10 +1318,9 @@ Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TV ClassImp(o2::its::Detector); -// Define Factory method for calling from the outside extern "C" { o2::base::Detector* create_detector_its(const char* name, bool active) { - return o2::its::Detector::create(name, active); -} + return o2::its::Detector::create(active, name); } +} \ No newline at end of file diff --git a/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx b/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx index 7a5243fde8063..9e5cefc990aec 100644 --- a/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx +++ b/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx @@ -38,6 +38,7 @@ using o2::itsmft::Hit; using namespace o2::mft; ClassImp(o2::mft::Detector); +O2DetectorCreatorImpl(o2::mft::Detector::create, mft); //_____________________________________________________________________________ Detector::Detector() diff --git a/Detectors/MUON/MCH/Simulation/src/Detector.cxx b/Detectors/MUON/MCH/Simulation/src/Detector.cxx index 6e664b8f036b3..50b614ede448d 100644 --- a/Detectors/MUON/MCH/Simulation/src/Detector.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Detector.cxx @@ -20,6 +20,7 @@ #include "TGeoManager.h" ClassImp(o2::mch::Detector); +O2DetectorCreatorImpl(o2::mch::Detector::create, mch); namespace o2 { diff --git a/Detectors/MUON/MID/Simulation/src/Detector.cxx b/Detectors/MUON/MID/Simulation/src/Detector.cxx index 0adb4e40d07cf..3bbbae1789ba3 100644 --- a/Detectors/MUON/MID/Simulation/src/Detector.cxx +++ b/Detectors/MUON/MID/Simulation/src/Detector.cxx @@ -17,6 +17,7 @@ #include "FairVolume.h" ClassImp(o2::mid::Detector); +O2DetectorCreatorImpl(o2::mid::Detector::create, mid); namespace o2 { diff --git a/Detectors/PHOS/simulation/src/Detector.cxx b/Detectors/PHOS/simulation/src/Detector.cxx index 449e05b70cc75..11b9bfe94515d 100644 --- a/Detectors/PHOS/simulation/src/Detector.cxx +++ b/Detectors/PHOS/simulation/src/Detector.cxx @@ -37,6 +37,7 @@ using namespace o2::phos; ClassImp(Detector); +O2DetectorCreatorImpl(o2::phos::Detector::create, phs); Detector::Detector(Bool_t active) : o2::base::DetImpl("PHS", active), diff --git a/Detectors/TOF/simulation/src/Detector.cxx b/Detectors/TOF/simulation/src/Detector.cxx index 2bfb76613dae5..4f4287b061bda 100644 --- a/Detectors/TOF/simulation/src/Detector.cxx +++ b/Detectors/TOF/simulation/src/Detector.cxx @@ -26,6 +26,7 @@ using namespace o2::tof; ClassImp(Detector); +O2DetectorCreatorImpl(o2::tof::Detector::create, tof); Detector::Detector(Bool_t active) : o2::base::DetImpl("TOF", active), mEventNr(0), mTOFHoles(kTRUE), mHits(o2::utils::createSimVector()) diff --git a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h index 507ba992e2715..a6124bc80426c 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h @@ -68,12 +68,6 @@ class Detector : public o2::base::DetImpl */ Detector(Bool_t Active); - // Factory method - static o2::base::Detector* create(bool active) - { - return new Detector(active); - } - /** default constructor */ Detector(); diff --git a/Detectors/TPC/simulation/src/Detector.cxx b/Detectors/TPC/simulation/src/Detector.cxx index 367abdc1a753a..4d27a7e918217 100644 --- a/Detectors/TPC/simulation/src/Detector.cxx +++ b/Detectors/TPC/simulation/src/Detector.cxx @@ -3217,10 +3217,4 @@ std::string Detector::getHitBranchNames(int probe) const ClassImp(o2::tpc::Detector); -// Define Factory method for calling from the outside -extern "C" { -o2::base::Detector* create_detector_tpc(bool active) -{ - return o2::tpc::Detector::create(active); -} -} +O2DetectorCreatorImpl(o2::tpc::Detector::create, tpc) \ No newline at end of file diff --git a/Detectors/TRD/simulation/src/Detector.cxx b/Detectors/TRD/simulation/src/Detector.cxx index 8429f249aaecd..3377fa83ba692 100644 --- a/Detectors/TRD/simulation/src/Detector.cxx +++ b/Detectors/TRD/simulation/src/Detector.cxx @@ -526,3 +526,4 @@ void Detector::addAlignableVolumes() const } ClassImp(Detector); +O2DetectorCreatorImpl(o2::trd::Detector::create, trd) \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx index aeb58649fa4c5..f9711a0873747 100644 --- a/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx @@ -241,4 +241,5 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP } // namespace ecal } // namespace o2 -ClassImp(o2::ecal::Detector); \ No newline at end of file +ClassImp(o2::ecal::Detector); +O2DetectorCreatorImpl(o2::ecal::Detector::create, ecl); \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx index 458df289d0bb2..f50da1840f138 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx @@ -575,3 +575,4 @@ Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TV } ClassImp(o2::fct::Detector); +O2DetectorCreatorImpl(o2::fct::Detector::create, fct); diff --git a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx index 296bec8aa8922..638c6ec3ea986 100644 --- a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx @@ -761,3 +761,4 @@ Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TV } ClassImp(o2::ft3::Detector); +O2DetectorCreatorImpl(o2::ft3::Detector::create, ft3); diff --git a/Detectors/Upgrades/ALICE3/MID/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/MID/simulation/src/Detector.cxx index 36f5b376563c0..ff4ba6b7a2ff9 100644 --- a/Detectors/Upgrades/ALICE3/MID/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/MID/simulation/src/Detector.cxx @@ -233,4 +233,5 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP return &(mHits->back()); } } // namespace o2::mi3 -ClassImp(o2::mi3::Detector); \ No newline at end of file +ClassImp(o2::mi3::Detector); +O2DetectorCreatorImpl(o2::mi3::Detector::create, mi3); \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx index de5c1817a515a..35b90361562ff 100644 --- a/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx @@ -428,4 +428,5 @@ void Detector::prepareLayout() } // namespace rich } // namespace o2 -ClassImp(o2::rich::Detector); \ No newline at end of file +ClassImp(o2::rich::Detector); +O2DetectorCreatorImpl(o2::rich::Detector::create, rch); \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h index 5b777641dbe99..18d2787248524 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h @@ -34,12 +34,6 @@ class Detector : public o2::base::DetImpl Detector(); ~Detector(); - // Factory method - static o2::base::Detector* create(bool active) - { - return new Detector(active); - } - void ConstructGeometry() override; o2::itsmft::Hit* addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos, diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 7a16d0643942c..17f50aedb4b23 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -366,11 +366,4 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP } // namespace o2 ClassImp(o2::trk::Detector); - -// Define Factory method for calling from the outside -extern "C" { -o2::base::Detector* create_detector_trk(bool active) -{ - return o2::trk::Detector::create(active); -} -} +O2DetectorCreatorImpl(o2::trk::Detector::create, trk); diff --git a/Detectors/ZDC/simulation/src/Detector.cxx b/Detectors/ZDC/simulation/src/Detector.cxx index c6f91d9c2164f..cb25acdd65768 100644 --- a/Detectors/ZDC/simulation/src/Detector.cxx +++ b/Detectors/ZDC/simulation/src/Detector.cxx @@ -39,6 +39,7 @@ using namespace o2::zdc; ClassImp(o2::zdc::Detector); +O2DetectorCreatorImpl(o2::zdc::Detector::create, zdc); #define kRaddeg TMath::RadToDeg() //_____________________________________________________________________________ diff --git a/macro/build_geometry.C b/macro/build_geometry.C index aebfbee7ce283..7de1a6a7df2d7 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -14,6 +14,8 @@ #include "TString.h" #include "TSystem.h" +#include "DetectorsCommonDataFormats/DetID.h" +#include "DetectorsBase/Detector.h" #include "DetectorsPassive/Cave.h" #include "DetectorsPassive/Magnet.h" #include "DetectorsPassive/Dipole.h" @@ -23,19 +25,6 @@ #include "DetectorsPassive/Hall.h" #include "DetectorsPassive/Pipe.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -49,12 +38,6 @@ #endif #ifdef ENABLE_UPGRADES -#include -#include -#include -#include -#include -#include #include #include #include @@ -211,12 +194,14 @@ void build_geometry(FairRunSim* run = nullptr) if (isActivated("TOF")) { // TOF - addReadoutDetector(new o2::tof::Detector(isReadout("TOF"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2TOFSimulation", "create_detector_tof", isReadout("TOF"))); } if (isActivated("TRD")) { // TRD - addReadoutDetector(new o2::trd::Detector(isReadout("TRD"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2TRDSimulation", "create_detector_trd", isReadout("TRD"))); } if (isActivated("TPC")) { @@ -239,32 +224,38 @@ void build_geometry(FairRunSim* run = nullptr) if (isActivated("FT3")) { // ALICE 3 FT3 - addReadoutDetector(new o2::ft3::Detector(isReadout("FT3"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FT3Simulation", "create_detector_ft3", isReadout("FT3"))); } if (isActivated("FCT")) { // ALICE 3 FCT - addReadoutDetector(new o2::fct::Detector(isReadout("FCT"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FCTSimulation", "create_detector_fct", isReadout("FCT"))); } if (isActivated("TF3")) { // ALICE 3 tofs - addReadoutDetector(new o2::iotof::Detector(isReadout("TF3"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2IOTOFSimulation", "create_detector_tf3", isReadout("TF3"))); } if (isActivated("RCH")) { // ALICE 3 RICH - addReadoutDetector(new o2::rich::Detector(isReadout("RCH"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2RICHSimulation", "create_detector_rch", isReadout("RCH"))); } if (isActivated("ECL")) { // ALICE 3 ECAL - addReadoutDetector(new o2::ecal::Detector(isReadout("ECL"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2ECalSimulation", "create_detector_ecl", isReadout("ECL"))); } if (isActivated("MI3")) { // ALICE 3 MID - addReadoutDetector(new o2::mi3::Detector(isReadout("MI3"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2MI3Simulation", "create_detector_mi3", isReadout("MI3"))); } #endif @@ -276,57 +267,68 @@ void build_geometry(FairRunSim* run = nullptr) if (isActivated("MFT")) { // mft - addReadoutDetector(new o2::mft::Detector(isReadout("MFT"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2MFTSimulation", "create_detector_mft", isReadout("MFT"))); } if (isActivated("MCH")) { // mch - addReadoutDetector(new o2::mch::Detector(isReadout("MCH"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2MCHSimulation", "create_detector_mch", isReadout("MCH"))); } if (isActivated("MID")) { // mid - addReadoutDetector(new o2::mid::Detector(isReadout("MID"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2MIDSimulation", "create_detector_mid", isReadout("MID"))); } if (isActivated("EMC")) { // emcal - addReadoutDetector(new o2::emcal::Detector(isReadout("EMC"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2EMCALSimulation", "create_detector_emc", isReadout("EMC"))); } if (isActivated("PHS")) { // phos - addReadoutDetector(new o2::phos::Detector(isReadout("PHS"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2PHOSSimulation", "create_detector_phs", isReadout("PHS"))); } if (isActivated("CPV")) { // cpv - addReadoutDetector(new o2::cpv::Detector(isReadout("CPV"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2CPVSimulation", "create_detector_cpv", isReadout("CPV"))); } if (isActivated("FT0")) { // FIT-T0 - addReadoutDetector(new o2::ft0::Detector(isReadout("FT0"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FT0Simulation", "create_detector_ft0", isReadout("FT0"))); } if (isActivated("FV0")) { // FIT-V0 - addReadoutDetector(new o2::fv0::Detector(isReadout("FV0"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FV0Simulation", "create_detector_fv0", isReadout("FV0"))); } if (isActivated("FDD")) { // FIT-FDD - addReadoutDetector(new o2::fdd::Detector(isReadout("FDD"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FDDSimulation", "create_detector_fdd", isReadout("FDD"))); } if (isActivated("HMP")) { // HMP - addReadoutDetector(new o2::hmpid::Detector(isReadout("HMP"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2HMPIDSimulation", "create_detector_hmp", isReadout("HMP"))); } if (isActivated("ZDC")) { // ZDC - addReadoutDetector(new o2::zdc::Detector(isReadout("ZDC"))); + addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2ZDCSimulation", "create_detector_zdc", isReadout("ZDC"))); } if (geomonly) { diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index b1d09db4d02c8..b08c59bb85c36 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -20,32 +20,9 @@ target_link_libraries(allsim O2::SimSetup O2::SimulationDataFormat FairMQ::FairMQ - O2::CPVSimulation O2::DetectorsPassive - O2::EMCALSimulation - O2::FDDSimulation O2::Field - O2::HMPIDSimulation - O2::ITSSimulation - O2::MCHSimulation - O2::MFTSimulation - O2::MIDSimulation - O2::PHOSSimulation - O2::FT0Simulation - O2::TOFSimulation - O2::TPCSimulation - O2::TRDSimulation - O2::FV0Simulation - O2::ZDCSimulation $<$:O2::Alice3DetectorsPassive> - $<$:O2::ITS3Simulation> - $<$:O2::TRKSimulation> - $<$:O2::FT3Simulation> - $<$:O2::FCTSimulation> - $<$:O2::IOTOFSimulation> - $<$:O2::RICHSimulation> - $<$:O2::ECalSimulation> - $<$:O2::MI3Simulation> O2::Generators) add_library(internal::allsim ALIAS allsim) diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index 543aa9f48cae7..3ed81a8a34610 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -41,21 +41,6 @@ #include "O2HitMerger.h" #include "O2SimDevice.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "CommonUtils/ShmManager.h" #include @@ -67,18 +52,6 @@ #include #include "SimPublishChannelHelper.h" - -#ifdef ENABLE_UPGRADES -#include -#include -#include -#include -#include -#include -#include -#include -#endif - #include namespace o2 @@ -923,96 +896,119 @@ void O2HitMerger::initDetInstances() } if (i == DetID::TPC) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2TPCSimulation", "create_detector_tpc", true)); counter++; } if (i == DetID::ITS) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2ITSSimulation", "create_detector_its", "ITS", true)); counter++; } if (i == DetID::MFT) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2MFTSimulation", "create_detector_mft", true)); counter++; } if (i == DetID::TRD) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2TRDSimulation", "create_detector_trd", true)); counter++; } if (i == DetID::PHS) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2PHOSSimulation", "create_detector_phs", true)); counter++; } if (i == DetID::CPV) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2CPVSimulation", "create_detector_cpv", true)); counter++; } if (i == DetID::EMC) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2EMCALSimulation", "create_detector_emc", true)); counter++; } if (i == DetID::HMP) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2HMPIDSimulation", "create_detector_hmp", true)); counter++; } if (i == DetID::TOF) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2TOFSimulation", "create_detector_tof", true)); counter++; } if (i == DetID::FT0) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FT0Simulation", "create_detector_ft0", true)); counter++; } if (i == DetID::FV0) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FV0Simulation", "create_detector_fv0", true)); counter++; } if (i == DetID::FDD) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FDDSimulation", "create_detector_fdd", true)); counter++; } if (i == DetID::MCH) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2MCHSimulation", "create_detector_mch", true)); counter++; } if (i == DetID::MID) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2MIDSimulation", "create_detector_mid", true)); counter++; } if (i == DetID::ZDC) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2ZDCSimulation", "create_detector_zdc", true)); counter++; } #ifdef ENABLE_UPGRADES if (i == DetID::IT3) { - mDetectorInstances[i] = std::move(std::make_unique(true, "IT3")); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2ITSSimulation", "create_detector_its", "IT3", true)); counter++; } if (i == DetID::TRK) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2TRKSimulation", "create_detector_trk", "TRK", true)); counter++; } if (i == DetID::FT3) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FT3Simulation", "create_detector_ft3", true)); counter++; } if (i == DetID::FCT) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2FCTSimulation", "create_detector_fct", true)); counter++; } if (i == DetID::TF3) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2IOTOFSimulation", "create_detector_tf3", true)); counter++; } if (i == DetID::RCH) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2RICHSimulation", "create_detector_rch", true)); counter++; } if (i == DetID::MI3) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2MI3Simulation", "create_detector_mi3", true)); counter++; } if (i == DetID::ECL) { - mDetectorInstances[i] = std::move(std::make_unique(true)); + mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( + "O2ECalSimulation", "create_detector_ecl", true)); counter++; } #endif From 591181ae928f0aa447c466631d9a6ea6a2fc93f8 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 29 May 2024 13:08:37 +0200 Subject: [PATCH 0270/2997] GPU TPC: Track time constrain must consider TPCFastTransform::getT0() --- GPU/GPUTracking/Merger/GPUTPCGMO2Output.cxx | 7 ++++--- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMO2Output.cxx b/GPU/GPUTracking/Merger/GPUTPCGMO2Output.cxx index 616a6b70b435a..8945f8bef889c 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMO2Output.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMO2Output.cxx @@ -234,20 +234,21 @@ GPUdii() void GPUTPCGMO2Output::Thread(int nBlocks, in // estimate max/min time increments which still keep track in the physical limits of the TPC const float tmin = CAMath::Min(t1, t2); const float maxDriftTime = merger.GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->getMaxDriftTime(t1 > t2 ? sector1 : sector2); + const float clusterT0 = merger.GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->getT0(); const float tmax = CAMath::Min(tmin + maxDriftTime, CAMath::Max(t1, t2)); float delta = 0.f; if (time0 + maxDriftTime < tmax) { delta = tmax - time0 - maxDriftTime; } - if (tmin < time0 + delta) { - delta = tmin - time0; + if (tmin - clusterT0 < time0 + delta) { + delta = tmin - clusterT0 - time0; } if (delta != 0.f) { time0 += delta; const float deltaZ = merger.GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->convDeltaTimeToDeltaZinTimeFrame(sector2, delta); oTrack.setZ(oTrack.getZ() + deltaZ); } - tFwd = tmin - time0; + tFwd = tmin - clusterT0 - time0; tBwd = time0 - tmax + maxDriftTime; } } diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 5473814610be0..249e99f240ca0 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -1015,7 +1015,7 @@ GPUd() void GPUTPCGMTrackParam::ShiftZ(const GPUTPCGMMerger* GPUrestrict() merge float deltaT = merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->convDeltaZtoDeltaTimeInTimeFrame(slice, deltaZ); mTZOffset += deltaT; mP[1] -= deltaZ; - const float maxT = CAMath::Min(tz1, tz2); + const float maxT = CAMath::Min(tz1, tz2) - merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->getT0(); const float minT = CAMath::Max(tz1, tz2) - merger->GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->getMaxDriftTime(slice); // printf("T Check: Clusters %f %f, min %f max %f vtx %f\n", tz1, tz2, minT, maxT, mTZOffset); deltaT = 0.f; From 877eba6e317acc2675671c22fdd97126494ecd59 Mon Sep 17 00:00:00 2001 From: Marian Ivanov Date: Wed, 29 May 2024 21:40:45 +0200 Subject: [PATCH 0271/2997] #13173 - fixing DCA for combined tracking + adding nshared clusters (#13176) * #13173 - fixing DCA * #13173 - using clang-format --------- Co-authored-by: miranov25 --- Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx index f508140581138..81f12756e5dc7 100644 --- a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx +++ b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx @@ -1199,6 +1199,7 @@ class TPCTimeSeries : public Task if (contributeToVertex) { if (propagator->propagateToDCA(vertex.getXYZ(), trackITSTPCTmp, propagator->getNominalBz(), mFineStep, mMatType, &dcaITSTPCTmp)) { phiITSTPCAtVertex = trackITSTPCTmp.getPhi(); + dcaITSTPC = dcaITSTPCTmp; } // propagate TPC track to vertex @@ -1373,6 +1374,7 @@ class TPCTimeSeries : public Task << "tpc_timebin=" << trkOrig.getTime0() << "qpt=" << trkOrig.getParam(4) << "ncl=" << trkOrig.getNClusters() + << "ncl_shared=" << trkOrig.getNClusters() << "tgl=" << trkOrig.getTgl() << "side_type=" << typeSide << "phi=" << trkOrig.getPhi() From 8630309283163f8c411730ecdca581c6461d8c1f Mon Sep 17 00:00:00 2001 From: sevdokim Date: Wed, 29 May 2024 12:26:41 +0200 Subject: [PATCH 0272/2997] PHS: fix seg faults in TRU decoding (AltroDecoder.cxx) --- .../PHOS/reconstruction/src/AltroDecoder.cxx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx index 6471a824d344e..78cd76a258fee 100644 --- a/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx +++ b/Detectors/PHOS/reconstruction/src/AltroDecoder.cxx @@ -306,21 +306,28 @@ void AltroDecoder::readTRUFlags(short hwAddress, int payloadSize) int currentsample = 0; while (currentsample < payloadSize) { int bunchlength = mBunchwords[currentsample] - 2; // remove words for bunchlength and starttime - if (bunchlength < 1) { // corrupted sample: add error and ignore the reast of bunchwords + if (bunchlength < 1) { // corrupted sample: add error and ignore the rest of bunchwords // 1: wrong TRU header mOutputHWErrors.emplace_back(mddl, kGeneralTRUErr, static_cast(1)); return; } int timeBin = mBunchwords[currentsample + 1] + 1; // +1 for further convenience - if (timeBin > 128) { // corrupted sample: add error and ignore the reast of bunchwords - // 1: wrong TRU header - mOutputHWErrors.emplace_back(mddl, kGeneralTRUErr, static_cast(2)); // PAYLOAD_DECODING - return; - } int istart = currentsample + 2; int iend = istart + std::min(bunchlength, static_cast(mBunchwords.size()) - currentsample - 2); currentsample += bunchlength + 2; + if (timeBin >= 128 || timeBin < 1) { // corrupted sample: add error and try to read next + // 2: wrong TRU payload + mOutputHWErrors.emplace_back(mddl, kGeneralTRUErr, static_cast(2)); // PAYLOAD_DECODING + continue; + } + + if (timeBin <= iend - istart) { + // 2: wrong TRU payload + mOutputHWErrors.emplace_back(mddl, kGeneralTRUErr, static_cast(2)); // PAYLOAD_DECODING + continue; + } + for (int i = iend - 1; i >= istart; i--) { --timeBin; short a = mBunchwords[i]; From 726b845ccf531e3f8ce82109b37f690533cd02ae Mon Sep 17 00:00:00 2001 From: iravasen Date: Thu, 30 May 2024 00:16:45 +0200 Subject: [PATCH 0273/2997] Update ITS DCSParserSpec.cxx: use of STF and ETF (#13165) * Update ITS DCSParserSpec.cxx: use of STF and ETF Use of STF and ETF from RCT info with 2 minutes margin as proposed by O2/DPG coordinators. * use of getRunDuration to include fallback solutions --- .../ITS/workflow/include/ITSWorkflow/DCSParserSpec.h | 1 + Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSParserSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSParserSpec.h index 29cb5a660dab1..eaacfab10f886 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSParserSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSParserSpec.h @@ -60,6 +60,7 @@ #include "DetectorsCalibration/Utils.h" #include "CCDB/CcdbObjectInfo.h" #include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" #include "DataFormatsDCS/DCSConfigObject.h" #include "ITSMFTReconstruction/ChipMappingITS.h" #include "DataFormatsITSMFT/NoiseMap.h" diff --git a/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx index 12e9c9dd80346..99bf1827116f1 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx @@ -482,8 +482,9 @@ void ITSDCSParser::pushToCCDB(ProcessingContext& pc) tstart = o2::ccdb::getCurrentTimestamp(); tend = tstart + 365L * 24 * 3600 * 1000; } else { - tstart = std::stol(headers["SOR"]); - tend = std::stol(headers["EOR"]); + auto ts = o2::ccdb::BasicCCDBManager::instance().getRunDuration(mRunNumber); + tstart = ts.first; + tend = ts.second; } auto class_name = o2::utils::MemFileHelper::getClassName(mConfigDCS); @@ -497,8 +498,8 @@ void ITSDCSParser::pushToCCDB(ProcessingContext& pc) const char* filename = "dcs_config.root"; long current_time = o2::ccdb::getCurrentTimestamp(); std::string filename_deadMap = "o2-itsmft-NoiseMap_" + std::to_string(current_time) + ".root"; - o2::ccdb::CcdbObjectInfo info(path, "dcs_config", filename, metadata, tstart, tend); - o2::ccdb::CcdbObjectInfo info_deadMap(path_deadMap, "noise_map", filename_deadMap, metadata, tstart - o2::ccdb::CcdbObjectInfo::MINUTE, tend + 5 * o2::ccdb::CcdbObjectInfo::MINUTE); + o2::ccdb::CcdbObjectInfo info(path, "dcs_config", filename, metadata, tstart - 2 * o2::ccdb::CcdbObjectInfo::MINUTE, tend + 2 * o2::ccdb::CcdbObjectInfo::MINUTE); + o2::ccdb::CcdbObjectInfo info_deadMap(path_deadMap, "noise_map", filename_deadMap, metadata, tstart - 2 * o2::ccdb::CcdbObjectInfo::MINUTE, tend + 2 * o2::ccdb::CcdbObjectInfo::MINUTE); auto image = o2::ccdb::CcdbApi::createObjectImage(&mConfigDCS, &info); auto image_deadMap = o2::ccdb::CcdbApi::createObjectImage(&mDeadMap, &info_deadMap); info.setFileName(filename); From 5650d334facd9d7aec412aaf0b6e283597847f1d Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 29 May 2024 14:22:24 +0200 Subject: [PATCH 0274/2997] GPU Workflow: print GPU_ configKeyValues only for pipeline index 0 by default --- GPU/GPUTracking/Definitions/GPUSettingsList.h | 2 +- GPU/Workflow/src/GPUWorkflowSpec.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index cf91f7ce45f88..1dcdffb558608 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -39,7 +39,7 @@ BeginSubConfig(GPUSettingsRecTPC, tpc, configStandalone.rec, "RECTPC", 0, "Recon AddOptionRTC(rejectQPtB5, float, 1.f / GPUCA_MIN_TRACK_PTB5_REJECT_DEFAULT, "", 0, "QPt threshold to reject clusters of TPC tracks (Inverse Pt, scaled to B=0.5T!!!)") AddOptionRTC(hitPickUpFactor, float, 1.f, "", 0, "multiplier for the combined cluster+track error during track following") AddOptionRTC(hitSearchArea2, float, 2.f, "", 0, "square of maximum search road of hits during seeding") -AddOptionRTC(neighboursSearchArea, float, 3.f, "", 0, "area in cm for the search of neighbours, only used if searchWindowDZDR = 0") +AddOptionRTC(neighboursSearchArea, float, 3.f, "", 0, "area in cm for the search of neighbours, for z only used if searchWindowDZDR = 0") AddOptionRTC(clusterError2CorrectionY, float, 1.f, "", 0, "correction (multiplicative) for the squared cluster error during tracking") AddOptionRTC(clusterError2CorrectionZ, float, 1.f, "", 0, "correction (multiplicative) for the squared cluster error during tracking") AddOptionRTC(clusterError2AdditionalY, float, 0.f, "", 0, "correction (additive) for the squared cluster error during track fitting") diff --git a/GPU/Workflow/src/GPUWorkflowSpec.cxx b/GPU/Workflow/src/GPUWorkflowSpec.cxx index af65de4ce5c48..1898e2e939295 100644 --- a/GPU/Workflow/src/GPUWorkflowSpec.cxx +++ b/GPU/Workflow/src/GPUWorkflowSpec.cxx @@ -274,7 +274,7 @@ void GPURecoWorkflowSpec::init(InitContext& ic) mConfig->configProcessing.o2PropagatorUseGPUField = true; - if (mConfParam->printSettings) { + if (mConfParam->printSettings && (mConfParam->printSettings > 1 || ic.services().get().inputTimesliceId == 0)) { mConfig->PrintParam(); } From 2ce9d0ed7c8cad262baf4d2e279d64b97ff7267b Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 29 May 2024 14:38:20 +0200 Subject: [PATCH 0275/2997] GPU: Print additional settings with GPU_global.printSettings --- .../Interface/GPUO2InterfaceConfigurableParam.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx index bbd0d16c943f9..06aadc2b09484 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceConfigurableParam.cxx @@ -139,4 +139,10 @@ void GPUO2InterfaceConfiguration::PrintParam_internal() { qConfigPrint(configProcessing, "proc."); qConfigPrint(configReconstruction, "rec."); + qConfigPrint(configQA, "QA."); + qConfigPrint(configDisplay, "display."); + std::cout << "\n\tGPUSettingsDeviceBackend:\n" + << "\tdeviceType = " << (int)configDeviceBackend.deviceType << "\n" + << "\tforceDeviceType = " << (configDeviceBackend.forceDeviceType ? "true" : "false") << "\n" + << "\tslave = " << (configDeviceBackend.master ? "true" : "false") << "\n"; } From a291fe699ff16198c12d94c1410e0f2483cb1df8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 29 May 2024 10:26:49 +0200 Subject: [PATCH 0276/2997] DPL: introduce helper functions to detect only timers / generate --- Framework/Core/src/DataProcessingDevice.cxx | 31 +++++++++++---------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index f256b49bcc3af..2aa239b974136 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -117,6 +117,16 @@ void on_idle_timer(uv_timer_t* handle) state->loopReason |= DeviceState::TIMER_EXPIRED; } +bool hasOnlyTimers(DeviceSpec const& spec) +{ + return std::all_of(spec.inputs.cbegin(), spec.inputs.cend(), [](InputRoute const& route) -> bool { return route.matcher.lifetime == Lifetime::Timer; }); +} + +bool hasOnlyGenerated(DeviceSpec const& spec) +{ + return (spec.inputChannels.size() == 1) && (spec.inputs[0].matcher.lifetime == Lifetime::Timer || spec.inputs[0].matcher.lifetime == Lifetime::Enumeration); +} + void on_transition_requested_expired(uv_timer_t* handle) { auto* state = (DeviceState*)handle->data; @@ -1281,15 +1291,8 @@ void DataProcessingDevice::Run() auto& deviceContext = ref.get(); auto timeout = deviceContext.exitTransitionTimeout; // Check if we only have timers - bool onlyTimers = true; auto& spec = ref.get(); - for (auto& route : spec.inputs) { - if (route.matcher.lifetime != Lifetime::Timer) { - onlyTimers = false; - break; - } - } - if (onlyTimers) { + if (hasOnlyTimers(spec)) { state.streaming = StreamingState::EndOfStreaming; } if (timeout != 0 && state.streaming != StreamingState::Idle) { @@ -1689,9 +1692,11 @@ void DataProcessingDevice::doRun(ServiceRegistryRef ref) // I guess we will see. /// Besides flushing the queues we must make sure we do not have only /// timers as they do not need to be further processed. - bool hasOnlyGenerated = (spec.inputChannels.size() == 1) && (spec.inputs[0].matcher.lifetime == Lifetime::Timer || spec.inputs[0].matcher.lifetime == Lifetime::Enumeration); auto& relayer = ref.get(); - while (DataProcessingDevice::tryDispatchComputation(ref, context.completed) && hasOnlyGenerated == false) { + + bool shouldProcess = hasOnlyGenerated(spec) == false; + + while (DataProcessingDevice::tryDispatchComputation(ref, context.completed) && shouldProcess) { relayer.processDanglingInputs(context.expirationHandlers, *context.registry, false); } EndOfStreamContext eosContext{*context.registry, ref.get()}; @@ -1710,11 +1715,7 @@ void DataProcessingDevice::doRun(ServiceRegistryRef ref) // This is needed because the transport is deleted before the device. relayer.clear(); switchState(StreamingState::Idle); - if (hasOnlyGenerated) { - *context.wasActive = false; - } else { - *context.wasActive = true; - } + *context.wasActive = shouldProcess; // On end of stream we shut down all output pollers. O2_SIGNPOST_EVENT_EMIT(device, dpid, "state", "Shutting down output pollers."); for (auto& poller : state.activeOutputPollers) { From e4f99fe7c382c839517d3097a7e4f7c0b5dac26b Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 30 May 2024 14:31:01 +0200 Subject: [PATCH 0277/2997] Fix typo in getPhiAt method --- DataFormats/Reconstruction/src/TrackParametrization.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Reconstruction/src/TrackParametrization.cxx b/DataFormats/Reconstruction/src/TrackParametrization.cxx index fe6c8f7d89cbb..d79b6dcb7b474 100644 --- a/DataFormats/Reconstruction/src/TrackParametrization.cxx +++ b/DataFormats/Reconstruction/src/TrackParametrization.cxx @@ -534,7 +534,7 @@ GPUd() typename TrackParametrization::value_t TrackParametrization(phi); } return phi; From aede8b4f3f49b5011837033e0da1db43f9d8e211 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 30 May 2024 15:23:11 +0200 Subject: [PATCH 0278/2997] ZDC: Demote bogus error message to warning --- DataFormats/Detectors/ZDC/src/RecEventFlat.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Detectors/ZDC/src/RecEventFlat.cxx b/DataFormats/Detectors/ZDC/src/RecEventFlat.cxx index cb49905ea57da..cb2e298eee317 100644 --- a/DataFormats/Detectors/ZDC/src/RecEventFlat.cxx +++ b/DataFormats/Detectors/ZDC/src/RecEventFlat.cxx @@ -648,7 +648,7 @@ void RecEventFlat::centroidZPC(float& x, float& rms) if (d >= 0) { d = TMath::Sqrt(d); } else { - LOGF(error, "%s FOP exception @ %d", __FILE__, __LINE__); + LOGF(warn, "%s FOP exception @ %d", __FILE__, __LINE__); d = -std::numeric_limits::infinity(); } } From 3a39b254899ba709cef28d5535f6ede48f213657 Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 30 May 2024 11:05:08 +0200 Subject: [PATCH 0279/2997] Revert "o2-sim: Apply dynamic detector lib loading to all detectors" This reverts commit 9ddc990c75e898ac6c0e39cd5b45c01328c6a1b0. There are some other things (e.g., correct order of initialization of ConfigKey parameters) , affected by this commit, which need to be addressed and worked out first. --- .../Base/include/DetectorsBase/Detector.h | 23 ----- Detectors/CPV/simulation/src/Detector.cxx | 1 - Detectors/EMCAL/simulation/src/Detector.cxx | 1 - Detectors/FIT/FDD/simulation/src/Detector.cxx | 1 - Detectors/FIT/FT0/simulation/src/Detector.cxx | 1 - Detectors/FIT/FV0/simulation/src/Detector.cxx | 1 - Detectors/HMPID/simulation/src/Detector.cxx | 1 - .../include/ITSSimulation/Detector.h | 6 ++ .../ITSMFT/ITS/simulation/src/Detector.cxx | 5 +- .../ITSMFT/MFT/simulation/src/Detector.cxx | 1 - .../MUON/MCH/Simulation/src/Detector.cxx | 1 - .../MUON/MID/Simulation/src/Detector.cxx | 1 - Detectors/PHOS/simulation/src/Detector.cxx | 1 - Detectors/TOF/simulation/src/Detector.cxx | 1 - .../include/TPCSimulation/Detector.h | 6 ++ Detectors/TPC/simulation/src/Detector.cxx | 8 +- Detectors/TRD/simulation/src/Detector.cxx | 1 - .../ALICE3/ECal/simulation/src/Detector.cxx | 3 +- .../ALICE3/FCT/simulation/src/Detector.cxx | 1 - .../ALICE3/FT3/simulation/src/Detector.cxx | 1 - .../ALICE3/MID/simulation/src/Detector.cxx | 3 +- .../ALICE3/RICH/simulation/src/Detector.cxx | 3 +- .../include/TRKSimulation/Detector.h | 6 ++ .../ALICE3/TRK/simulation/src/Detector.cxx | 9 +- Detectors/ZDC/simulation/src/Detector.cxx | 1 - macro/build_geometry.C | 78 ++++++++------- run/CMakeLists.txt | 23 +++++ run/O2HitMerger.h | 96 ++++++++++--------- 28 files changed, 150 insertions(+), 134 deletions(-) diff --git a/Detectors/Base/include/DetectorsBase/Detector.h b/Detectors/Base/include/DetectorsBase/Detector.h index 4a44a7bf84154..1432d93c53821 100644 --- a/Detectors/Base/include/DetectorsBase/Detector.h +++ b/Detectors/Base/include/DetectorsBase/Detector.h @@ -41,16 +41,6 @@ #include -// macro implementation helper to code unmanged "C" function -// constructing a detector -#define O2DetectorCreatorImpl(creatorfuncname, detname) \ - extern "C" { \ - o2::base::Detector* create_detector_##detname(bool active) \ - { \ - return creatorfuncname(active); \ - } \ - } - namespace o2::base { @@ -312,19 +302,6 @@ class DetImpl : public o2::base::Detector // offer same constructors as base using Detector::Detector; - /// automatic implementation of static Detector factory functions - template - static o2::base::Detector* create(Args&&... args) - { - if constexpr (std::is_constructible_v) { - return new Det(std::forward(args)...); - } else { - static_assert(std::is_constructible_v, - "No matching constructor found in Derived class."); - return nullptr; - } - } - // default implementation for getHitBranchNames std::string getHitBranchNames(int probe) const override { diff --git a/Detectors/CPV/simulation/src/Detector.cxx b/Detectors/CPV/simulation/src/Detector.cxx index e4b4e3554ccd4..fda5751464f01 100644 --- a/Detectors/CPV/simulation/src/Detector.cxx +++ b/Detectors/CPV/simulation/src/Detector.cxx @@ -37,7 +37,6 @@ using namespace o2::cpv; ClassImp(Detector); -O2DetectorCreatorImpl(o2::cpv::Detector::create, cpv); Detector::Detector(Bool_t active) : o2::base::DetImpl("CPV", active), diff --git a/Detectors/EMCAL/simulation/src/Detector.cxx b/Detectors/EMCAL/simulation/src/Detector.cxx index c6ed34935dd96..e5163dbda8288 100644 --- a/Detectors/EMCAL/simulation/src/Detector.cxx +++ b/Detectors/EMCAL/simulation/src/Detector.cxx @@ -38,7 +38,6 @@ using namespace o2::emcal; ClassImp(Detector); -O2DetectorCreatorImpl(o2::emcal::Detector::create, emc); Detector::Detector(Bool_t active) : o2::base::DetImpl("EMC", active), diff --git a/Detectors/FIT/FDD/simulation/src/Detector.cxx b/Detectors/FIT/FDD/simulation/src/Detector.cxx index f4777e18bb72d..3bb945ddd1bba 100644 --- a/Detectors/FIT/FDD/simulation/src/Detector.cxx +++ b/Detectors/FIT/FDD/simulation/src/Detector.cxx @@ -39,7 +39,6 @@ using o2::fdd::Geometry; using o2::fdd::Hit; ClassImp(o2::fdd::Detector); -O2DetectorCreatorImpl(o2::fdd::Detector::create, fdd); //_____________________________________________________________________________ Detector::Detector(Bool_t Active) diff --git a/Detectors/FIT/FT0/simulation/src/Detector.cxx b/Detectors/FIT/FT0/simulation/src/Detector.cxx index 462e56e7d2e61..ea856eb204802 100644 --- a/Detectors/FIT/FT0/simulation/src/Detector.cxx +++ b/Detectors/FIT/FT0/simulation/src/Detector.cxx @@ -42,7 +42,6 @@ using namespace o2::ft0; using o2::ft0::Geometry; ClassImp(Detector); -O2DetectorCreatorImpl(o2::ft0::Detector::create, ft0); Detector::Detector(Bool_t Active) : o2::base::DetImpl("FT0", Active), mIdSens1(0), mPMTeff(nullptr), mHits(o2::utils::createSimVector()), mTrackIdTop(-1), mTrackIdMCPtop(-1) diff --git a/Detectors/FIT/FV0/simulation/src/Detector.cxx b/Detectors/FIT/FV0/simulation/src/Detector.cxx index c2e0fa1a06853..8cf1f5530e93d 100644 --- a/Detectors/FIT/FV0/simulation/src/Detector.cxx +++ b/Detectors/FIT/FV0/simulation/src/Detector.cxx @@ -30,7 +30,6 @@ using namespace o2::fv0; using o2::fv0::Geometry; ClassImp(Detector); -O2DetectorCreatorImpl(o2::fv0::Detector::create, fv0); Detector::Detector() : o2::base::DetImpl("FV0", kTRUE), diff --git a/Detectors/HMPID/simulation/src/Detector.cxx b/Detectors/HMPID/simulation/src/Detector.cxx index 0bb076a1ddee5..83bab71e7177d 100644 --- a/Detectors/HMPID/simulation/src/Detector.cxx +++ b/Detectors/HMPID/simulation/src/Detector.cxx @@ -1379,4 +1379,3 @@ void Detector::defineOpticalProperties() } // end namespace o2 ClassImp(o2::hmpid::Detector); -O2DetectorCreatorImpl(o2::hmpid::Detector::create, hmp); \ No newline at end of file diff --git a/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h b/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h index 63a1f36c58fab..c48f0f942d29c 100644 --- a/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h +++ b/Detectors/ITSMFT/ITS/simulation/include/ITSSimulation/Detector.h @@ -79,6 +79,12 @@ class Detector : public o2::base::DetImpl /// kFALSE for inactive detectors Detector(Bool_t active, TString name = "ITS"); + // Factory method + static o2::base::Detector* create(const char* name, bool active) + { + return new Detector(active, name); + } + /// Default constructor Detector(); diff --git a/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx b/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx index 188fb7b7394b2..d005c9ea9858a 100644 --- a/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx +++ b/Detectors/ITSMFT/ITS/simulation/src/Detector.cxx @@ -1318,9 +1318,10 @@ Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TV ClassImp(o2::its::Detector); +// Define Factory method for calling from the outside extern "C" { o2::base::Detector* create_detector_its(const char* name, bool active) { - return o2::its::Detector::create(active, name); + return o2::its::Detector::create(name, active); +} } -} \ No newline at end of file diff --git a/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx b/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx index 9e5cefc990aec..7a5243fde8063 100644 --- a/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx +++ b/Detectors/ITSMFT/MFT/simulation/src/Detector.cxx @@ -38,7 +38,6 @@ using o2::itsmft::Hit; using namespace o2::mft; ClassImp(o2::mft::Detector); -O2DetectorCreatorImpl(o2::mft::Detector::create, mft); //_____________________________________________________________________________ Detector::Detector() diff --git a/Detectors/MUON/MCH/Simulation/src/Detector.cxx b/Detectors/MUON/MCH/Simulation/src/Detector.cxx index 50b614ede448d..6e664b8f036b3 100644 --- a/Detectors/MUON/MCH/Simulation/src/Detector.cxx +++ b/Detectors/MUON/MCH/Simulation/src/Detector.cxx @@ -20,7 +20,6 @@ #include "TGeoManager.h" ClassImp(o2::mch::Detector); -O2DetectorCreatorImpl(o2::mch::Detector::create, mch); namespace o2 { diff --git a/Detectors/MUON/MID/Simulation/src/Detector.cxx b/Detectors/MUON/MID/Simulation/src/Detector.cxx index 3bbbae1789ba3..0adb4e40d07cf 100644 --- a/Detectors/MUON/MID/Simulation/src/Detector.cxx +++ b/Detectors/MUON/MID/Simulation/src/Detector.cxx @@ -17,7 +17,6 @@ #include "FairVolume.h" ClassImp(o2::mid::Detector); -O2DetectorCreatorImpl(o2::mid::Detector::create, mid); namespace o2 { diff --git a/Detectors/PHOS/simulation/src/Detector.cxx b/Detectors/PHOS/simulation/src/Detector.cxx index 11b9bfe94515d..449e05b70cc75 100644 --- a/Detectors/PHOS/simulation/src/Detector.cxx +++ b/Detectors/PHOS/simulation/src/Detector.cxx @@ -37,7 +37,6 @@ using namespace o2::phos; ClassImp(Detector); -O2DetectorCreatorImpl(o2::phos::Detector::create, phs); Detector::Detector(Bool_t active) : o2::base::DetImpl("PHS", active), diff --git a/Detectors/TOF/simulation/src/Detector.cxx b/Detectors/TOF/simulation/src/Detector.cxx index 4f4287b061bda..2bfb76613dae5 100644 --- a/Detectors/TOF/simulation/src/Detector.cxx +++ b/Detectors/TOF/simulation/src/Detector.cxx @@ -26,7 +26,6 @@ using namespace o2::tof; ClassImp(Detector); -O2DetectorCreatorImpl(o2::tof::Detector::create, tof); Detector::Detector(Bool_t active) : o2::base::DetImpl("TOF", active), mEventNr(0), mTOFHoles(kTRUE), mHits(o2::utils::createSimVector()) diff --git a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h index a6124bc80426c..507ba992e2715 100644 --- a/Detectors/TPC/simulation/include/TPCSimulation/Detector.h +++ b/Detectors/TPC/simulation/include/TPCSimulation/Detector.h @@ -68,6 +68,12 @@ class Detector : public o2::base::DetImpl */ Detector(Bool_t Active); + // Factory method + static o2::base::Detector* create(bool active) + { + return new Detector(active); + } + /** default constructor */ Detector(); diff --git a/Detectors/TPC/simulation/src/Detector.cxx b/Detectors/TPC/simulation/src/Detector.cxx index 4d27a7e918217..367abdc1a753a 100644 --- a/Detectors/TPC/simulation/src/Detector.cxx +++ b/Detectors/TPC/simulation/src/Detector.cxx @@ -3217,4 +3217,10 @@ std::string Detector::getHitBranchNames(int probe) const ClassImp(o2::tpc::Detector); -O2DetectorCreatorImpl(o2::tpc::Detector::create, tpc) \ No newline at end of file +// Define Factory method for calling from the outside +extern "C" { +o2::base::Detector* create_detector_tpc(bool active) +{ + return o2::tpc::Detector::create(active); +} +} diff --git a/Detectors/TRD/simulation/src/Detector.cxx b/Detectors/TRD/simulation/src/Detector.cxx index 3377fa83ba692..8429f249aaecd 100644 --- a/Detectors/TRD/simulation/src/Detector.cxx +++ b/Detectors/TRD/simulation/src/Detector.cxx @@ -526,4 +526,3 @@ void Detector::addAlignableVolumes() const } ClassImp(Detector); -O2DetectorCreatorImpl(o2::trd::Detector::create, trd) \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx index f9711a0873747..aeb58649fa4c5 100644 --- a/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/ECal/simulation/src/Detector.cxx @@ -241,5 +241,4 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP } // namespace ecal } // namespace o2 -ClassImp(o2::ecal::Detector); -O2DetectorCreatorImpl(o2::ecal::Detector::create, ecl); \ No newline at end of file +ClassImp(o2::ecal::Detector); \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx index f50da1840f138..458df289d0bb2 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx @@ -575,4 +575,3 @@ Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TV } ClassImp(o2::fct::Detector); -O2DetectorCreatorImpl(o2::fct::Detector::create, fct); diff --git a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx index 638c6ec3ea986..296bec8aa8922 100644 --- a/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FT3/simulation/src/Detector.cxx @@ -761,4 +761,3 @@ Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TV } ClassImp(o2::ft3::Detector); -O2DetectorCreatorImpl(o2::ft3::Detector::create, ft3); diff --git a/Detectors/Upgrades/ALICE3/MID/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/MID/simulation/src/Detector.cxx index ff4ba6b7a2ff9..36f5b376563c0 100644 --- a/Detectors/Upgrades/ALICE3/MID/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/MID/simulation/src/Detector.cxx @@ -233,5 +233,4 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP return &(mHits->back()); } } // namespace o2::mi3 -ClassImp(o2::mi3::Detector); -O2DetectorCreatorImpl(o2::mi3::Detector::create, mi3); \ No newline at end of file +ClassImp(o2::mi3::Detector); \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx index 35b90361562ff..de5c1817a515a 100644 --- a/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx @@ -428,5 +428,4 @@ void Detector::prepareLayout() } // namespace rich } // namespace o2 -ClassImp(o2::rich::Detector); -O2DetectorCreatorImpl(o2::rich::Detector::create, rch); \ No newline at end of file +ClassImp(o2::rich::Detector); \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h index 18d2787248524..5b777641dbe99 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h @@ -34,6 +34,12 @@ class Detector : public o2::base::DetImpl Detector(); ~Detector(); + // Factory method + static o2::base::Detector* create(bool active) + { + return new Detector(active); + } + void ConstructGeometry() override; o2::itsmft::Hit* addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos, diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 17f50aedb4b23..7a16d0643942c 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -366,4 +366,11 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP } // namespace o2 ClassImp(o2::trk::Detector); -O2DetectorCreatorImpl(o2::trk::Detector::create, trk); + +// Define Factory method for calling from the outside +extern "C" { +o2::base::Detector* create_detector_trk(bool active) +{ + return o2::trk::Detector::create(active); +} +} diff --git a/Detectors/ZDC/simulation/src/Detector.cxx b/Detectors/ZDC/simulation/src/Detector.cxx index cb25acdd65768..c6f91d9c2164f 100644 --- a/Detectors/ZDC/simulation/src/Detector.cxx +++ b/Detectors/ZDC/simulation/src/Detector.cxx @@ -39,7 +39,6 @@ using namespace o2::zdc; ClassImp(o2::zdc::Detector); -O2DetectorCreatorImpl(o2::zdc::Detector::create, zdc); #define kRaddeg TMath::RadToDeg() //_____________________________________________________________________________ diff --git a/macro/build_geometry.C b/macro/build_geometry.C index 7de1a6a7df2d7..aebfbee7ce283 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -14,8 +14,6 @@ #include "TString.h" #include "TSystem.h" -#include "DetectorsCommonDataFormats/DetID.h" -#include "DetectorsBase/Detector.h" #include "DetectorsPassive/Cave.h" #include "DetectorsPassive/Magnet.h" #include "DetectorsPassive/Dipole.h" @@ -25,6 +23,19 @@ #include "DetectorsPassive/Hall.h" #include "DetectorsPassive/Pipe.h" #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -38,6 +49,12 @@ #endif #ifdef ENABLE_UPGRADES +#include +#include +#include +#include +#include +#include #include #include #include @@ -194,14 +211,12 @@ void build_geometry(FairRunSim* run = nullptr) if (isActivated("TOF")) { // TOF - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2TOFSimulation", "create_detector_tof", isReadout("TOF"))); + addReadoutDetector(new o2::tof::Detector(isReadout("TOF"))); } if (isActivated("TRD")) { // TRD - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2TRDSimulation", "create_detector_trd", isReadout("TRD"))); + addReadoutDetector(new o2::trd::Detector(isReadout("TRD"))); } if (isActivated("TPC")) { @@ -224,38 +239,32 @@ void build_geometry(FairRunSim* run = nullptr) if (isActivated("FT3")) { // ALICE 3 FT3 - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FT3Simulation", "create_detector_ft3", isReadout("FT3"))); + addReadoutDetector(new o2::ft3::Detector(isReadout("FT3"))); } if (isActivated("FCT")) { // ALICE 3 FCT - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FCTSimulation", "create_detector_fct", isReadout("FCT"))); + addReadoutDetector(new o2::fct::Detector(isReadout("FCT"))); } if (isActivated("TF3")) { // ALICE 3 tofs - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2IOTOFSimulation", "create_detector_tf3", isReadout("TF3"))); + addReadoutDetector(new o2::iotof::Detector(isReadout("TF3"))); } if (isActivated("RCH")) { // ALICE 3 RICH - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2RICHSimulation", "create_detector_rch", isReadout("RCH"))); + addReadoutDetector(new o2::rich::Detector(isReadout("RCH"))); } if (isActivated("ECL")) { // ALICE 3 ECAL - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2ECalSimulation", "create_detector_ecl", isReadout("ECL"))); + addReadoutDetector(new o2::ecal::Detector(isReadout("ECL"))); } if (isActivated("MI3")) { // ALICE 3 MID - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2MI3Simulation", "create_detector_mi3", isReadout("MI3"))); + addReadoutDetector(new o2::mi3::Detector(isReadout("MI3"))); } #endif @@ -267,68 +276,57 @@ void build_geometry(FairRunSim* run = nullptr) if (isActivated("MFT")) { // mft - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2MFTSimulation", "create_detector_mft", isReadout("MFT"))); + addReadoutDetector(new o2::mft::Detector(isReadout("MFT"))); } if (isActivated("MCH")) { // mch - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2MCHSimulation", "create_detector_mch", isReadout("MCH"))); + addReadoutDetector(new o2::mch::Detector(isReadout("MCH"))); } if (isActivated("MID")) { // mid - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2MIDSimulation", "create_detector_mid", isReadout("MID"))); + addReadoutDetector(new o2::mid::Detector(isReadout("MID"))); } if (isActivated("EMC")) { // emcal - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2EMCALSimulation", "create_detector_emc", isReadout("EMC"))); + addReadoutDetector(new o2::emcal::Detector(isReadout("EMC"))); } if (isActivated("PHS")) { // phos - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2PHOSSimulation", "create_detector_phs", isReadout("PHS"))); + addReadoutDetector(new o2::phos::Detector(isReadout("PHS"))); } if (isActivated("CPV")) { // cpv - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2CPVSimulation", "create_detector_cpv", isReadout("CPV"))); + addReadoutDetector(new o2::cpv::Detector(isReadout("CPV"))); } if (isActivated("FT0")) { // FIT-T0 - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FT0Simulation", "create_detector_ft0", isReadout("FT0"))); + addReadoutDetector(new o2::ft0::Detector(isReadout("FT0"))); } if (isActivated("FV0")) { // FIT-V0 - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FV0Simulation", "create_detector_fv0", isReadout("FV0"))); + addReadoutDetector(new o2::fv0::Detector(isReadout("FV0"))); } if (isActivated("FDD")) { // FIT-FDD - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FDDSimulation", "create_detector_fdd", isReadout("FDD"))); + addReadoutDetector(new o2::fdd::Detector(isReadout("FDD"))); } if (isActivated("HMP")) { // HMP - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2HMPIDSimulation", "create_detector_hmp", isReadout("HMP"))); + addReadoutDetector(new o2::hmpid::Detector(isReadout("HMP"))); } if (isActivated("ZDC")) { // ZDC - addReadoutDetector(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2ZDCSimulation", "create_detector_zdc", isReadout("ZDC"))); + addReadoutDetector(new o2::zdc::Detector(isReadout("ZDC"))); } if (geomonly) { diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index b08c59bb85c36..b1d09db4d02c8 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -20,9 +20,32 @@ target_link_libraries(allsim O2::SimSetup O2::SimulationDataFormat FairMQ::FairMQ + O2::CPVSimulation O2::DetectorsPassive + O2::EMCALSimulation + O2::FDDSimulation O2::Field + O2::HMPIDSimulation + O2::ITSSimulation + O2::MCHSimulation + O2::MFTSimulation + O2::MIDSimulation + O2::PHOSSimulation + O2::FT0Simulation + O2::TOFSimulation + O2::TPCSimulation + O2::TRDSimulation + O2::FV0Simulation + O2::ZDCSimulation $<$:O2::Alice3DetectorsPassive> + $<$:O2::ITS3Simulation> + $<$:O2::TRKSimulation> + $<$:O2::FT3Simulation> + $<$:O2::FCTSimulation> + $<$:O2::IOTOFSimulation> + $<$:O2::RICHSimulation> + $<$:O2::ECalSimulation> + $<$:O2::MI3Simulation> O2::Generators) add_library(internal::allsim ALIAS allsim) diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index 3ed81a8a34610..543aa9f48cae7 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -41,6 +41,21 @@ #include "O2HitMerger.h" #include "O2SimDevice.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "CommonUtils/ShmManager.h" #include @@ -52,6 +67,18 @@ #include #include "SimPublishChannelHelper.h" + +#ifdef ENABLE_UPGRADES +#include +#include +#include +#include +#include +#include +#include +#include +#endif + #include namespace o2 @@ -896,119 +923,96 @@ void O2HitMerger::initDetInstances() } if (i == DetID::TPC) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2TPCSimulation", "create_detector_tpc", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::ITS) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2ITSSimulation", "create_detector_its", "ITS", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::MFT) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2MFTSimulation", "create_detector_mft", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::TRD) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2TRDSimulation", "create_detector_trd", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::PHS) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2PHOSSimulation", "create_detector_phs", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::CPV) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2CPVSimulation", "create_detector_cpv", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::EMC) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2EMCALSimulation", "create_detector_emc", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::HMP) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2HMPIDSimulation", "create_detector_hmp", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::TOF) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2TOFSimulation", "create_detector_tof", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::FT0) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FT0Simulation", "create_detector_ft0", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::FV0) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FV0Simulation", "create_detector_fv0", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::FDD) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FDDSimulation", "create_detector_fdd", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::MCH) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2MCHSimulation", "create_detector_mch", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::MID) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2MIDSimulation", "create_detector_mid", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::ZDC) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2ZDCSimulation", "create_detector_zdc", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } #ifdef ENABLE_UPGRADES if (i == DetID::IT3) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2ITSSimulation", "create_detector_its", "IT3", true)); + mDetectorInstances[i] = std::move(std::make_unique(true, "IT3")); counter++; } if (i == DetID::TRK) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2TRKSimulation", "create_detector_trk", "TRK", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::FT3) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FT3Simulation", "create_detector_ft3", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::FCT) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2FCTSimulation", "create_detector_fct", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::TF3) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2IOTOFSimulation", "create_detector_tf3", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::RCH) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2RICHSimulation", "create_detector_rch", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::MI3) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2MI3Simulation", "create_detector_mi3", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } if (i == DetID::ECL) { - mDetectorInstances[i].reset(o2::conf::SimDLLoader::Instance().executeFunctionAlias( - "O2ECalSimulation", "create_detector_ecl", true)); + mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } #endif From 6870d550010b135d5426302a34f67f3c6139e17e Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 30 May 2024 18:19:23 +0200 Subject: [PATCH 0280/2997] TPCTrackStudy extracts final scaled correction instead of nominal map one --- Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx index 0e1dc7baaa69c..a549a402055e1 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx @@ -263,7 +263,6 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) clY.clear(); clZ.clear(); int count = tr.getNClusters(); - const auto* corrMap = this->mTPCCorrMapsLoader.getCorrMap(); const o2::tpc::ClusterNative* cl = nullptr; for (int ic = count; ic--;) { uint8_t sector, row; @@ -271,7 +270,7 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) clSector.push_back(sector); clRow.push_back(row); float x, y, z; - corrMap->Transform(sector, row, cl->getPad(), cl->getTime(), x, y, z, t); // nominal time of the track + mTPCCorrMapsLoader.Transform(sector, row, cl->getPad(), cl->getTime(), x, y, z, t); // nominal time of the track clX.push_back(x); clY.push_back(y); clZ.push_back(z); From 009a79f48fa1f8f799fd71043a5baf2562ac289d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 30 May 2024 13:09:18 +0200 Subject: [PATCH 0281/2997] DPL: add signposts for forwarding --- Framework/Core/src/DataProcessingDevice.cxx | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 2aa239b974136..93940ef5ec21a 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -94,6 +94,8 @@ O2_DECLARE_DYNAMIC_LOG(device); O2_DECLARE_DYNAMIC_LOG(parts); // Special log to track the async queue behavior O2_DECLARE_DYNAMIC_LOG(async_queue); +// Special log to track the forwarding requests +O2_DECLARE_DYNAMIC_LOG(forwarding); using namespace o2::framework; using ConfigurationInterface = o2::configuration::ConfigurationInterface; @@ -636,6 +638,9 @@ static auto forwardInputs = [](ServiceRegistryRef registry, TimesliceSlot slot, std::vector forwardedParts; forwardedParts.resize(proxy.getNumForwards()); std::vector cachedForwardingChoices{}; + O2_SIGNPOST_ID_GENERATE(sid, forwarding); + O2_SIGNPOST_START(forwarding, sid, "forwardInputs", "Starting forwarding for slot %zu with oldestTimeslice %zu %{public}s%{public}s%{public}s", + slot.index, oldestTimeslice.timeslice.value, copy ? "with copy" : "", copy && consume ? " and " : "", consume ? "with consume" : ""); for (size_t ii = 0, ie = currentSetOfInputs.size(); ii < ie; ++ii) { auto& messageSet = currentSetOfInputs[ii]; @@ -663,9 +668,14 @@ static auto forwardInputs = [](ServiceRegistryRef registry, TimesliceSlot slot, if (cachedForwardingChoices.size() > 1) { copy = true; } + auto* dh = o2::header::get(header->GetData()); + auto* dph = o2::header::get(header->GetData()); + if (copy) { for (auto& cachedForwardingChoice : cachedForwardingChoices) { auto&& newHeader = header->GetTransport()->CreateMessage(); + O2_SIGNPOST_EVENT_EMIT(forwarding, sid, "forwardInputs", "Forwarding a copy of %{public}s to route %d.", + fmt::format("{}/{}/{}@timeslice:{} tfCounter:{}", dh->dataOrigin, dh->dataDescription, dh->subSpecification, dph->startTime, dh->tfCounter).c_str(), cachedForwardingChoice.value); newHeader->Copy(*header); forwardedParts[cachedForwardingChoice.value].AddPart(std::move(newHeader)); @@ -676,6 +686,8 @@ static auto forwardInputs = [](ServiceRegistryRef registry, TimesliceSlot slot, } } } else { + O2_SIGNPOST_EVENT_EMIT(forwarding, sid, "forwardInputs", "Forwarding %{public}s to route %d.", + fmt::format("{}/{}/{}@timeslice:{} tfCounter:{}", dh->dataOrigin, dh->dataDescription, dh->subSpecification, dph->startTime, dh->tfCounter).c_str(), cachedForwardingChoices.back().value); forwardedParts[cachedForwardingChoices.back().value].AddPart(std::move(messageSet.header(pi))); for (size_t payloadIndex = 0; payloadIndex < messageSet.getNumberOfPayloads(pi); ++payloadIndex) { forwardedParts[cachedForwardingChoices.back().value].AddPart(std::move(messageSet.payload(pi, payloadIndex))); @@ -683,19 +695,18 @@ static auto forwardInputs = [](ServiceRegistryRef registry, TimesliceSlot slot, } } } - LOG(debug) << "Forwarding " << forwardedParts.size() << " messages"; + O2_SIGNPOST_EVENT_EMIT(forwarding, sid, "forwardInputs", "Forwarding %zu messages", forwardedParts.size()); for (int fi = 0; fi < proxy.getNumForwardChannels(); fi++) { if (forwardedParts[fi].Size() == 0) { continue; } ForwardChannelInfo info = proxy.getForwardChannelInfo(ChannelIndex{fi}); - LOG(debug) << "Forwarding to " << info.name << " " << fi; - // in DPL we are using subchannel 0 only auto& parts = forwardedParts[fi]; if (info.policy == nullptr) { - LOG(error) << "Forwarding to " << info.name << " " << fi << " has no policy"; + O2_SIGNPOST_EVENT_EMIT_ERROR(forwarding, sid, "forwardInputs", "Forwarding to %{public}s %d has no policy.", info.name.c_str(), fi); continue; } + O2_SIGNPOST_EVENT_EMIT(forwarding, sid, "forwardInputs", "Forwarding to %{public}s %d", info.name.c_str(), fi); info.policy->forward(parts, ChannelIndex{fi}, registry); } @@ -729,7 +740,7 @@ static auto forwardInputs = [](ServiceRegistryRef registry, TimesliceSlot slot, } }, oldestTimeslice.timeslice, -1); - LOG(debug) << "Forwarding done"; + O2_SIGNPOST_END(forwarding, sid, "forwardInputs", "Forwarding done"); }; extern volatile int region_read_global_dummy_variable; volatile int region_read_global_dummy_variable; From 039939a66f0e1efa44cd95374d5d3850a0ebe068 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 30 May 2024 11:46:53 +0200 Subject: [PATCH 0282/2997] calib-workflow: Use add_W to add tpc calib workflows --- prodtests/full-system-test/calib-workflow.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/prodtests/full-system-test/calib-workflow.sh b/prodtests/full-system-test/calib-workflow.sh index e37f5e248aa88..ccc934b2ff470 100755 --- a/prodtests/full-system-test/calib-workflow.sh +++ b/prodtests/full-system-test/calib-workflow.sh @@ -46,19 +46,18 @@ if [[ $CALIB_TOF_INTEGRATEDCURR == 1 ]]; then add_W o2-tof-integrate-cluster-wor # for async calibrations if [[ $CALIB_EMC_ASYNC_RECALIB == 1 ]]; then add_W o2-emcal-emc-offline-calib-workflow "--input-subspec 1 --applyGainCalib"; fi -: ${ARGS_EXTRA_PROCESS_o2_tpc_integrate_cluster_workflow:=""} if [[ $CALIB_ASYNC_EXTRACTTPCCURRENTS == 1 ]]; then - add_comma_separated ADD_EXTRA_WORKFLOW "o2-tpc-integrate-cluster-workflow" + CONFIG_CTPTPC= if [[ $CALIB_ASYNC_DISABLE3DCURRENTS != 1 ]]; then - export ARGS_EXTRA_PROCESS_o2_tpc_integrate_cluster_workflow="$ARGS_EXTRA_PROCESS_o2_tpc_integrate_cluster_workflow--process-3D-currents --nSlicesTF 1" + CONFIG_CTPTPC="--process-3D-currents --nSlicesTF 1" fi + add_W o2-tpc-integrate-cluster-workflow "${CONFIG_CTPTPC}" fi if [[ $CALIB_ASYNC_EXTRACTTIMESERIES == 1 ]] ; then - : ${ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow:=""} + CONFIG_TPCTIMESERIES= : ${CALIB_ASYNC_SAMPLINGFACTORTIMESERIES:=0.001} - add_comma_separated ADD_EXTRA_WORKFLOW "o2-tpc-time-series-workflow" if [[ ! -z "$CALIB_ASYNC_ENABLEUNBINNEDTIMESERIES" ]]; then - export ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow="$ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow --enable-unbinned-root-output --sample-unbinned-tsallis --threads 1" + CONFIG_TPCTIMESERIES+=" --enable-unbinned-root-output --sample-unbinned-tsallis --threads 1" fi if [[ $ON_SKIMMED_DATA == 1 ]] || [[ ! -z "$CALIB_ASYNC_SAMPLINGFACTORTIMESERIES" ]]; then if [[ $ON_SKIMMED_DATA == 1 ]]; then @@ -67,8 +66,9 @@ if [[ $CALIB_ASYNC_EXTRACTTIMESERIES == 1 ]] ; then if [[ ! -z "$CALIB_ASYNC_SAMPLINGFACTORTIMESERIES" ]]; then # this takes priority, even if we were on skimmed data SAMPLINGFACTORTIMESERIES=${CALIB_ASYNC_SAMPLINGFACTORTIMESERIES} fi - export ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow="$ARGS_EXTRA_PROCESS_o2_tpc_time_series_workflow --sampling-factor ${SAMPLINGFACTORTIMESERIES}" + CONFIG_TPCTIMESERIES+=" --sampling-factor ${SAMPLINGFACTORTIMESERIES}" fi + add_W o2-tpc-time-series-workflow "${CONFIG_TPCTIMESERIES}" fi # output-proxy for aggregator From a82ab47069e7b37e67b657f39dd764a26afd8cee Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 30 May 2024 14:22:22 +0200 Subject: [PATCH 0283/2997] DPL: Fix detection of first device in topology --- Framework/Core/src/CommonServices.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 7f145fe4318ff..57621ecaa8f33 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -541,8 +541,8 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() .init = [](ServiceRegistryRef services, DeviceState&, fair::mq::ProgOptions& options) -> ServiceHandle { auto* decongestion = new DecongestionService(); for (auto& input : services.get().inputs) { - if (input.matcher.lifetime == Lifetime::Timeframe) { - LOGP(detail, "Found a Timeframe input, we cannot update the oldest possible timeslice"); + if (input.matcher.lifetime == Lifetime::Timeframe || input.matcher.lifetime == Lifetime::QA || input.matcher.lifetime == Lifetime::Sporadic || input.matcher.lifetime == Lifetime::Optional) { + LOGP(detail, "Found a real data input, we cannot update the oldest possible timeslice when sending messages"); decongestion->isFirstInTopology = false; break; } From 2ca79e08739836675ef4ab76cdc332d3f84c4aa6 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 30 May 2024 14:48:05 +0200 Subject: [PATCH 0284/2997] DPL: Improve some signpost messages --- Framework/Core/src/DataRelayer.cxx | 2 +- Framework/Core/src/TimesliceIndex.cxx | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index 703043477639e..e408632723741 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -373,7 +373,7 @@ void DataRelayer::pruneCache(TimesliceSlot slot, OnDropCallback onDrop) bool anyDropped = std::any_of(dropped.begin(), dropped.end(), [](auto& m) { return m.size(); }); if (anyDropped) { O2_SIGNPOST_ID_GENERATE(aid, data_relayer); - O2_SIGNPOST_EVENT_EMIT(data_relayer, aid, "pruneCache", "Dropping stuff from slot %zu %zu", slot.index, oldestPossibleTimeslice.timeslice.value); + O2_SIGNPOST_EVENT_EMIT(data_relayer, aid, "pruneCache", "Dropping stuff from slot %zu with timeslice %zu", slot.index, oldestPossibleTimeslice.timeslice.value); onDrop(slot, dropped, oldestPossibleTimeslice); } } diff --git a/Framework/Core/src/TimesliceIndex.cxx b/Framework/Core/src/TimesliceIndex.cxx index 2ddf2007d0100..73a9e5b154f67 100644 --- a/Framework/Core/src/TimesliceIndex.cxx +++ b/Framework/Core/src/TimesliceIndex.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. #include "Framework/TimesliceIndex.h" #include "Framework/Signpost.h" +#include O2_DECLARE_DYNAMIC_LOG(timeslice_index); @@ -162,11 +163,11 @@ TimesliceIndex::OldestInputInfo TimesliceIndex::setOldestPossibleInput(Timeslice } } if (changed && mOldestPossibleInput.timeslice.value != result.timeslice.value) { - O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "setOldestPossibleInput", "Success: Oldest possible input is %zu due to channel %d", - result.timeslice.value, result.channel.value); + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "setOldestPossibleInput", "Success (channel %d): Oldest possible input is %zu due to channel %d", + channel.value, result.timeslice.value, result.channel.value); } else if (mOldestPossibleInput.timeslice.value != result.timeslice.value) { - O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "setOldestPossibleInput", "Oldest possible input updated from timestamp: %zu --> %zu", - mOldestPossibleInput.timeslice.value, result.timeslice.value); + O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "setOldestPossibleInput", "channel %d: Oldest possible input updated from timestamp: %zu --> %zu", + channel.value, mOldestPossibleInput.timeslice.value, result.timeslice.value); } else { O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "setOldestPossibleInput", "No change in oldest possible input"); } From 725befe6c463d17b02a4bbeb198164dd42c91098 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 30 May 2024 14:48:39 +0200 Subject: [PATCH 0285/2997] DPL: Throw error messages when the oldestPossibleTimeframe is incorrectly decreased --- Framework/Core/src/TimesliceIndex.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Framework/Core/src/TimesliceIndex.cxx b/Framework/Core/src/TimesliceIndex.cxx index 73a9e5b154f67..5707a66bac4e4 100644 --- a/Framework/Core/src/TimesliceIndex.cxx +++ b/Framework/Core/src/TimesliceIndex.cxx @@ -171,6 +171,9 @@ TimesliceIndex::OldestInputInfo TimesliceIndex::setOldestPossibleInput(Timeslice } else { O2_SIGNPOST_EVENT_EMIT(timeslice_index, tid, "setOldestPossibleInput", "No change in oldest possible input"); } + if (mOldestPossibleInput.timeslice.value > result.timeslice.value) { + LOG(error) << "DPL internal error - oldestPossibleInput of channel " << channel.value << ": " << getChannelInfo(channel).channel->GetName().c_str() << " decreased from " << mOldestPossibleOutput.timeslice.value << " to " << result.timeslice.value; + } mOldestPossibleInput = result; return mOldestPossibleInput; } @@ -220,6 +223,9 @@ TimesliceIndex::OldestOutputInfo TimesliceIndex::updateOldestPossibleOutput() mOldestPossibleOutput.timeslice.value, result.timeslice.value); } } + if (mOldestPossibleOutput.timeslice.value > result.timeslice.value) { + LOG(error) << "DPL internal error - oldestPossibleOutput decreased from " << mOldestPossibleOutput.timeslice.value << " to " << result.timeslice.value; + } mOldestPossibleOutput = result; return result; From 62859c83eb64adc8d3f611ab979eb9ec447096cf Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Thu, 30 May 2024 13:58:27 +0200 Subject: [PATCH 0286/2997] Correctly set WITH_OPENMP to ITS tracking lib --- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 5 +++++ Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index d11660a116a2f..d3667294d6c61 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -38,6 +38,11 @@ o2_add_library(ITStracking O2::DataFormatsITS) +if (OpenMP_CXX_FOUND) + target_compile_definitions(${targetName} PRIVATE WITH_OPENMP) + target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX) +endif() + o2_add_library(ITSTrackingInterface TARGETVARNAME targetName SOURCES src/TrackingInterface.cxx diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index 079ac3a775c12..672e7370035e0 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -1031,10 +1031,5 @@ void TrackerTraits::adoptTimeFrame(TimeFrame* tf) mTimeFrame = tf; } -// bool TrackerTraits::checkTFMemory(const int iteration) -// { -// return mTimeFrame->checkMemory(mTrkParams[iteration].MaxMemory); -// } - } // namespace its } // namespace o2 From f371d8955a7b8b92863db7e2655a236241065da8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 1 Jun 2024 09:12:52 +0200 Subject: [PATCH 0287/2997] DPL: improve message when signpost is enabled --- Framework/Core/src/runDataProcessing.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 930132e972881..137f17152cc01 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -3068,7 +3068,7 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, auto* selectedName = (char const*)context; std::string prefix = "ch.cern.aliceo2."; if (strcmp(name, (prefix + selectedName).data()) == 0) { - LOGP(info, "Enabling signposts for {}", *selectedName); + LOGP(info, "Enabling signposts for stream \"ch.cern.aliceo2.{}\"", selectedName); _o2_log_set_stacktrace(log, 1); return false; } else { From 66a4d7a4ef7963889b526702d6bfa86134d5d28e Mon Sep 17 00:00:00 2001 From: Benedikt Volkel Date: Fri, 31 May 2024 16:24:29 +0200 Subject: [PATCH 0288/2997] [OTF Sim] Allow for a lot more events --- run/dpl_eventgen.cxx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/run/dpl_eventgen.cxx b/run/dpl_eventgen.cxx index 66dd1c8342990..c033aafddc367 100644 --- a/run/dpl_eventgen.cxx +++ b/run/dpl_eventgen.cxx @@ -27,8 +27,10 @@ using namespace o2::framework; struct GeneratorTask { + // For readability to indicate where counting certain things (such as events or timeframes) should be of the same order of magnitude + typedef uint64_t GenCount; Configurable generator{"generator", "boxgen", "Name of generator"}; - Configurable eventNum{"nEvents", 1, "Number of events"}; + Configurable eventNum{"nEvents", 1, "Number of events"}; Configurable trigger{"trigger", "", "Trigger type"}; // Configurable iniFile{"configFile", "", "INI file containing configurable parameters"}; Configurable params{"configKeyValues", "", "configurable params - configuring event generation internals"}; @@ -37,9 +39,9 @@ struct GeneratorTask { Configurable vtxModeArg{"vertexMode", "kDiamondParam", "Where the beam-spot vertex should come from. Must be one of kNoVertex, kDiamondParam, kCCDB"}; Configurable ttl{"time-limit", -1, "Maximum run time limit in seconds (default no limit)"}; Configurable outputPrefix{"output", "", "Optional prefix for kinematics files written on disc. If non-empty, files _Kine.root + _MCHeader.root will be created."}; - int nEvents = 0; - int eventCounter = 0; - int tfCounter = 0; + GenCount nEvents = 0; + GenCount eventCounter = 0; + GenCount tfCounter = 0; std::unique_ptr outfile{}; std::unique_ptr outtree{}; @@ -88,7 +90,7 @@ struct GeneratorTask { br->SetAddress(&mctrack_ptr); } - for (auto i = 0; i < std::min((int)aggregate, nEvents - eventCounter); ++i) { + for (auto i = 0; i < std::min((GenCount)aggregate, nEvents - eventCounter); ++i) { mctracks.clear(); genservice->generateEvent_MCTracks(mctracks, mcheader); pc.outputs().snapshot(Output{"MC", "MCHEADER", 0}, mcheader); From 178c1e95fe96aa84775dc9502a20a7a76c68b1e1 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Fri, 31 May 2024 16:28:35 +0200 Subject: [PATCH 0289/2997] Simulation: change LOG output from info to debug @sawenzel this should take care of https://its.cern.ch/jira/browse/O2-5009, will keep as draft for now --- run/o2sim_mctracks_to_aod.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/run/o2sim_mctracks_to_aod.cxx b/run/o2sim_mctracks_to_aod.cxx index e2293338e8058..74807fd2a3ce9 100644 --- a/run/o2sim_mctracks_to_aod.cxx +++ b/run/o2sim_mctracks_to_aod.cxx @@ -89,13 +89,13 @@ struct MctracksToAod { auto bcCounter = 0UL; size_t offset = 0; for (auto i = 0U; i < nParts; ++i) { - LOG(info) << "--- Loop over " << nParts << " parts ---"; + LOG(debug) << "--- Loop over " << nParts << " parts ---"; auto record = mSampler.generateCollisionTime(); auto header = pc.inputs().get("mcheader", i); auto tracks = pc.inputs().get("mctracks", i); - LOG(info) << "Updating collision table"; + LOG(debug) << "Updating collision table"; auto genID = updateMCCollisions(mCollisions.cursor, bcCounter, record.timeInBCNS * 1.e-3, @@ -103,12 +103,12 @@ struct MctracksToAod { 0, i); - LOG(info) << "Updating HepMC tables"; + LOG(debug) << "Updating HepMC tables"; updateHepMCXSection(mXSections.cursor, bcCounter, genID, *header); updateHepMCPdfInfo(mPdfInfos.cursor, bcCounter, genID, *header); updateHepMCHeavyIon(mHeavyIons.cursor, bcCounter, genID, *header); - LOG(info) << "Updating particles table"; + LOG(debug) << "Updating particles table"; TrackToIndex preselect; offset = updateParticles(mParticles.cursor, bcCounter, @@ -118,7 +118,7 @@ struct MctracksToAod { mFilter, false); - LOG(info) << "Increment BC counter"; + LOG(debug) << "Increment BC counter"; bcCounter++; } using o2::framework::Lifetime; From 06e375079fac9bd45b1190c2f6bb8b5d47a885b1 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 31 May 2024 15:14:34 +0200 Subject: [PATCH 0290/2997] Fix for HepMC: Actually take into account mEventsToSkip The option HepMC.eventsToSkip existed with the purpose to skip the first couple of events. This is useful to share an HepMC file among multiple timeframes or MC-jobs. Jobs can skip ahead to the correct event. Unfortunately, the skipping itself was not implemented and the option had no effect. This commit is fixing this. In addition, this commit avoids a potential infinite hang under error conditions. --- Generators/src/GeneratorHepMC.cxx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Generators/src/GeneratorHepMC.cxx b/Generators/src/GeneratorHepMC.cxx index 28fab2588787d..0af9363665bb5 100644 --- a/Generators/src/GeneratorHepMC.cxx +++ b/Generators/src/GeneratorHepMC.cxx @@ -87,6 +87,11 @@ void GeneratorHepMC::setup(const GeneratorFileOrCmdParam& param0, mPrune = param.prune; setEventsToSkip(param.eventsToSkip); + // we are skipping ahead in the HepMC stream now + for (int i = 0; i < mEventsToSkip; ++i) { + generateEvent(); + } + if (param.version != 0 and mCmd.empty()) { LOG(warn) << "The key \"HepMC.version\" is no longer used when " << "reading from files. The format version of the input files " @@ -100,8 +105,9 @@ Bool_t GeneratorHepMC::generateEvent() LOG(debug) << "Generating an event"; /** generate event **/ int tries = 0; + constexpr int max_tries = 3; do { - LOG(debug) << " try # " << ++tries; + LOG(debug) << " try # " << tries; if (not mReader and not makeReader()) { return false; } @@ -114,8 +120,13 @@ Bool_t GeneratorHepMC::generateEvent() mEvent->set_units(HepMC3::Units::GEV, HepMC3::Units::MM); LOG(debug) << "Read one event " << mEvent->event_number(); return true; + } else { + LOG(error) << "Event reading from HepMC failed ..."; } - } while (true); + tries++; + } while (tries < max_tries); + + LOG(fatal) << "HepMC event gen failed (Does the file/stream have enough events)?"; /** failure **/ return false; From 5592ca626ffebd3c278ac415d3d481398a37f467 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Wed, 29 May 2024 14:57:34 +0200 Subject: [PATCH 0291/2997] [EMCAL-1144] Fix operator+ in EMCAL Hit - operator+ must be declared outside the class as binary operator - Return object should be copy of the lhs hit and sum of the two energy losses In addition: - Fixing namespace of operator<< - Updating doxymodules.h with new features in calibration part. --- Detectors/EMCAL/base/include/EMCALBase/Hit.h | 17 ++++++++++++----- Detectors/EMCAL/base/src/Hit.cxx | 10 +++++----- Detectors/EMCAL/doxymodules.h | 11 +++++++++-- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Detectors/EMCAL/base/include/EMCALBase/Hit.h b/Detectors/EMCAL/base/include/EMCALBase/Hit.h index 640001a64872d..345a0918c3831 100644 --- a/Detectors/EMCAL/base/include/EMCALBase/Hit.h +++ b/Detectors/EMCAL/base/include/EMCALBase/Hit.h @@ -22,6 +22,8 @@ namespace emcal /// \class Hit /// \brief EMCAL simulation hit information /// \ingroup EMCALbase +/// \author Markus Fasel , Oak Ridge National Laboratory +/// \since August 31st, 2017 class Hit : public o2::BasicXYZEHit { public: @@ -63,11 +65,6 @@ class Hit : public o2::BasicXYZEHit /// \return This point with the summed energy loss Hit& operator+=(const Hit& rhs); - /// \brief Creates a new point base on this point but adding the energy loss of the right hand side - /// \param rhs Hit to add to - /// \return New EMAL point base on this point - Hit operator+(const Hit& rhs) const; - /// \brief Destructor ~Hit() = default; @@ -99,6 +96,16 @@ class Hit : public o2::BasicXYZEHit ClassDefNV(Hit, 1); }; +/// \brief Creates a new point base on this point but adding the energy loss of the right hand side +/// \param lhs Left hand side of the sum +/// \param rhs Right hand side of the sum +/// \return New EMAL point base on this point +Hit operator+(const Hit& lhs, const Hit& rhs); + +/// \brief Output stream operator for EMCAL hits +/// \param stream Stream to write on +/// \param point Hit to be printed +/// \return Stream after printing std::ostream& operator<<(std::ostream& stream, const Hit& point); } // namespace emcal } // namespace o2 diff --git a/Detectors/EMCAL/base/src/Hit.cxx b/Detectors/EMCAL/base/src/Hit.cxx index 39edba54e6b12..898d86dc2e2c4 100644 --- a/Detectors/EMCAL/base/src/Hit.cxx +++ b/Detectors/EMCAL/base/src/Hit.cxx @@ -32,7 +32,7 @@ Bool_t Hit::operator<(const Hit& rhs) const Bool_t Hit::operator==(const Hit& rhs) const { - return (GetDetectorID() == GetDetectorID()) && (GetTrackID() == rhs.GetTrackID()); + return (GetDetectorID() == rhs.GetDetectorID()) && (GetTrackID() == rhs.GetTrackID()); } Hit& Hit::operator+=(const Hit& rhs) @@ -41,14 +41,14 @@ Hit& Hit::operator+=(const Hit& rhs) return *this; } -Hit Hit::operator+(const Hit& rhs) const +Hit o2::emcal::operator+(const Hit& lhs, const Hit& rhs) { - Hit result(*this); + Hit result(lhs); result.SetEnergyLoss(result.GetEnergyLoss() + rhs.GetEnergyLoss()); - return *this; + return result; } -std::ostream& operator<<(std::ostream& stream, const Hit& p) +std::ostream& o2::emcal::operator<<(std::ostream& stream, const Hit& p) { p.PrintStream(stream); return stream; diff --git a/Detectors/EMCAL/doxymodules.h b/Detectors/EMCAL/doxymodules.h index 9c2df257fc25c..90c822264f6cd 100644 --- a/Detectors/EMCAL/doxymodules.h +++ b/Detectors/EMCAL/doxymodules.h @@ -35,8 +35,13 @@ * EMCAL calibration objects for * - Bad channel map * - Time calibration + * - Time slewing parameters * - Gain calibration * - Temperature calibration + * - FEE DCS parameters + * - Pedestal data + * In addition providing an interface convenient CCDB access and methods + * to recalibrate add cell level. */ /** @@ -44,8 +49,10 @@ * @brief EMCAL bad channel calibration * @ingroup DetectorEMCAL * - * Performs the EMCal bad channel calibration. - * + * EMCAL calibrator performing + * - Bad channel calibration + * - Time calibration + * and corresponding workflows for calibration tasks. */ /** From bc032165591b91788062f91a39f9f469c027f338 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Mon, 3 Jun 2024 10:32:00 +0200 Subject: [PATCH 0292/2997] [FOCAL-77] First version of the FOCAL hit (#13181) * [FOCAL-77] First version of the FOCAL hit Basic hit implementation based on the EMCAL hit, with additional information of the FOCAL subsystem In addition basic FOCAL doxygen module structure based on the EMCAL doxygen module structure --- Detectors/FOCAL/base/CMakeLists.txt | 4 +- Detectors/FOCAL/base/include/FOCALBase/Hit.h | 136 +++++++++++++++++++ Detectors/FOCAL/base/src/FOCALBaseLinkDef.h | 1 + Detectors/FOCAL/base/src/Hit.cxx | 64 +++++++++ Detectors/FOCAL/doxymodules.h | 72 ++++++++++ 5 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 Detectors/FOCAL/base/include/FOCALBase/Hit.h create mode 100644 Detectors/FOCAL/base/src/Hit.cxx create mode 100644 Detectors/FOCAL/doxymodules.h diff --git a/Detectors/FOCAL/base/CMakeLists.txt b/Detectors/FOCAL/base/CMakeLists.txt index 3154e7cc2b773..9bbf041f6d3c0 100644 --- a/Detectors/FOCAL/base/CMakeLists.txt +++ b/Detectors/FOCAL/base/CMakeLists.txt @@ -13,8 +13,9 @@ o2_add_library(FOCALBase SOURCES src/Composition.cxx src/EventReader.cxx src/Geometry.cxx + src/Hit.cxx src/TestbeamAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::DataFormatsFOCAL ROOT::RIO ROOT::Tree ROOT::TreePlayer + PUBLIC_LINK_LIBRARIES O2::DataFormatsFOCAL O2::SimulationDataFormat O2::CommonUtils ROOT::RIO ROOT::Tree ROOT::TreePlayer Microsoft.GSL::GSL) o2_target_root_dictionary( @@ -22,5 +23,6 @@ o2_target_root_dictionary( HEADERS include/FOCALBase/Composition.h include/FOCALBase/EventReader.h include/FOCALBase/Geometry.h + include/FOCALBase/Hit.h include/FOCALBase/TestbeamAnalysis.h ) \ No newline at end of file diff --git a/Detectors/FOCAL/base/include/FOCALBase/Hit.h b/Detectors/FOCAL/base/include/FOCALBase/Hit.h new file mode 100644 index 0000000000000..31d6054386b36 --- /dev/null +++ b/Detectors/FOCAL/base/include/FOCALBase/Hit.h @@ -0,0 +1,136 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef ALICEO2_FOCAL_HIT_H +#define ALICEO2_FOCAL_HIT_H + +#include +#include "SimulationDataFormat/BaseHits.h" +#include "CommonUtils/ShmAllocator.h" + +namespace o2::focal +{ + +/// \class Hit +/// \brief Common FOCAL hit class for the detector simulation +/// \ingroup FOCALbase +/// \author Markus Fasel , Oak Ridge National Laboratory +/// \since May 29, 2024 +class Hit : public o2::BasicXYZEHit +{ + public: + /// \enum Subsystem_t + /// \brief Subsystem index of the Hit + enum class Subsystem_t { + EPADS, ///< ECAL pads + EPIXELS, ///< ECAL pixels + HCAL, ///< HCAL + UNKNOWN ///< Undefined + }; + + /// \brief Dummy constructor + Hit() = default; + + /// \brief Construction of the FOCAL hit with full information + /// \param primary Index of the incoming primary particle + /// \param trackID Index of the MC particle (also shower particle) responsible for the energy loss + /// \param detID Module index inside the subsystem + /// \param subsystem FOCAL Subdetector (E-Pads, E-Pixels, HCAL) + /// \param pos Geometric hit position (global coordintate system) + /// \param tof Time-of-flight of the particle to the FOCAL + /// \param eLoss Energy loss + Hit(int primary, int trackID, int detID, Subsystem_t subsystem, double initialEnergy, const math_utils::Point3D& pos, + double tof, double eLoss); + + /// \brief Destructor + ~Hit() = default; + + /// \brief Comparison operator for equalness + /// \param other Hit to compare to + /// \return True if subsytem, module and MC particle ID match, false otherwise + bool operator==(const Hit& other) const; + + /// \brief Comparison operator for smaller + /// \param other Hit to compare to + /// \return True if other hit is smaller (first track ID, then, subsystem ID, then module ID), false otherwise + bool operator<(const Hit& other) const; + + /// \brief Operator for incremental sum, adding energy loss of the other hit to this energy loss + /// \param other Hit to add to this one + /// \return This hit containing the sum of the two energy losses + Hit& operator+=(const Hit& other); + + /// \brief Get the type of the subsystem for which the hit was created + /// \return Subsystem type + Subsystem_t getSubsystem() const { return mSubSystem; } + + /// \brief Check if the hit is a FOCAL-E pixel hit + /// \return True if the hit is a FOCAL-E pixel hit, false otherwise + bool isPixelHit() const { return mSubSystem == Subsystem_t::EPIXELS; } + + /// \brief Check if the hit is a FOCAL-E pad hit + /// \return True if the hit is a FOCAL-E pad hit, false otherwise + bool isPadHit() const { return mSubSystem == Subsystem_t::EPADS; } + + /// \brief Check if the hit is a FOCAL-H hit + /// \return True if the hit is a FOCAL-H, false otherwise + bool isHCALHit() const { return mSubSystem == Subsystem_t::HCAL; } + + /// \brief Get index of the incomimg primary particle associated with the hit + /// \return Associated primary particle + int getPrimary() const { return mPrimary; } + + /// \brief Get energy of the incoming primary particle at the entrance of FOCAL + /// \return Initial energy + double getInitialEnergy() const { return mInitialEnergy; } + + /// \brief Set energy of the incoming primary particle at the entrance of FOCAL + /// \param energy Initial energy + void setInitialEnergy(double energy) { mInitialEnergy = energy; } + + /// \brief Set index of the incomimg primary particle associated with the hit + /// \param primary Associated primary particle + void setPrimary(int primary) { mPrimary = primary; } + + /// \brief Print information of this hit on the output stream + /// \param stream Stream to print on + void printStream(std::ostream& stream) const; + + private: + Subsystem_t mSubSystem = Subsystem_t::UNKNOWN; ///< FOCAL subdetector + int mPrimary = -1; ///< Primary particles at the origin of the hit + double mInitialEnergy = 0.; ///< Energy of the parent particle that entered the EMCAL + + ClassDefNV(Hit, 1); +}; + +/// @brief Sum operator, creating a new hit with the sum of the two energy losses +/// @param lhs Left-hand side of the sum +/// @param rhs Right-hand side of the sum +/// @return New hit with the properties of the lhs hit and the summed energy loss of the two hits +Hit operator+(const Hit& lhs, const Hit& rhs); + +/// \brief Output stream operator for FOCAL hits +/// \param stream Stream to write on +/// \param point Hit to be printed +/// \return Stream after printing +std::ostream& operator<<(std::ostream& stream, const Hit& point); +} // namespace o2::focal + +#ifdef USESHM +namespace std +{ +template <> +class allocator : public o2::utils::ShmAllocator +{ +}; +} // namespace std +#endif +#endif \ No newline at end of file diff --git a/Detectors/FOCAL/base/src/FOCALBaseLinkDef.h b/Detectors/FOCAL/base/src/FOCALBaseLinkDef.h index d37fad38a9364..b39e551e8ed27 100644 --- a/Detectors/FOCAL/base/src/FOCALBaseLinkDef.h +++ b/Detectors/FOCAL/base/src/FOCALBaseLinkDef.h @@ -19,4 +19,5 @@ #pragma link C++ class o2::focal::TestbeamAnalysis + ; #pragma link C++ class o2::focal::Geometry + ; #pragma link C++ class o2::focal::Composition + ; +#pragma link C++ class o2::focal::Hit + ; #endif diff --git a/Detectors/FOCAL/base/src/Hit.cxx b/Detectors/FOCAL/base/src/Hit.cxx new file mode 100644 index 0000000000000..4155cdc3988a7 --- /dev/null +++ b/Detectors/FOCAL/base/src/Hit.cxx @@ -0,0 +1,64 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#include +#include "FOCALBase/Hit.h" + +using namespace o2::focal; + +Hit::Hit(int primary, int trackID, int detID, Subsystem_t subsystem, double initialEnergy, const math_utils::Point3D& pos, + double tof, double eLoss) : o2::BasicXYZEHit(pos.X(), pos.Y(), pos.Z(), tof, eLoss, trackID, detID), + mSubSystem(subsystem), + mInitialEnergy(initialEnergy) + +{ +} + +bool Hit::operator==(const Hit& other) const +{ + return (GetDetectorID() == other.GetDetectorID()) && (GetTrackID() == other.GetTrackID() && mSubSystem == other.mSubSystem); +} + +bool Hit::operator<(const Hit& other) const +{ + if (GetTrackID() != other.GetTrackID()) { + return GetTrackID() < other.GetTrackID(); + } + if (mSubSystem != other.mSubSystem) { + return mSubSystem < other.mSubSystem; + } + return GetDetectorID() < other.GetDetectorID(); +} + +Hit& Hit::operator+=(const Hit& other) +{ + SetEnergyLoss(GetEnergyLoss() + other.GetEnergyLoss()); + return *this; +} + +void Hit::printStream(std::ostream& stream) const +{ + stream << "FOCAL point: Track " << GetTrackID() << " in detector segment " << GetDetectorID() + << " at position (" << GetX() << "|" << GetY() << "|" << GetZ() << "), energy loss " << GetEnergyLoss() + << ", initial (parent) energy " << mInitialEnergy << " from primary " << mPrimary; +} + +Hit o2::focal::operator+(const Hit& lhs, const Hit& rhs) +{ + Hit summed(lhs); + summed += rhs; + return summed; +} + +std::ostream& o2::focal::operator<<(std::ostream& stream, const o2::focal::Hit& point) +{ + point.printStream(stream); + return stream; +} \ No newline at end of file diff --git a/Detectors/FOCAL/doxymodules.h b/Detectors/FOCAL/doxymodules.h new file mode 100644 index 0000000000000..5fee41475ce28 --- /dev/null +++ b/Detectors/FOCAL/doxymodules.h @@ -0,0 +1,72 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/** + * @defgroup DetectorFOCAL FOCAL + * @brief FOCAL simulation and reconstruction + * + * See \ref refDetectorsFOCAL for more information + */ + +/** + * @defgroup FOCALbase FOCAL base + * @brief Main FOCAL components + * @ingroup DetectorFOCAL + * + * Main FOCAL components used in various libraries + * - Geometry + * - Mapping + * - Basic data types not part of the FOCAL format + */ + +/** + * @defgroup FOCALcalibration FOCAL calibration + * @brief FOCAL calibration objects + * @ingroup DetectorFOCAL + * + * FOCAL calibration objects + */ + +/** + * @defgroup FOCALcalib FOCAL calib + * @brief FOCAL bad channel calibration + * @ingroup DetectorFOCAL + * + * FOCAL calibrators and calibration workflows + * + */ + +/** + * @defgroup FOCALsimulation FOCAL simulation + * @brief FOCAL simulation code + * @ingroup DetectorFOCAL + * + * FOCAL simulation package. See \ref refFOCALsimulation + * for more information + */ + +/** + * @defgroup FOCALreconstruction FOCAL reconstruction + * @brief FOCAL reconstruction code + * @ingroup DetectorFOCAL + * + * FOCAL reconstruction package. See \ref refFOCALreconstruction + * for more information + */ + +/** + * @defgroup FOCALworkflow FOCAL workflow + * @brief FOCAL reconstruction workflow + * @ingroup DetectorFOCAL + * + * FOCAL reconstruction workflow package. See \ref refFOCALworkflow + * for more information. + */ \ No newline at end of file From 53c5a42f2987ef3b261e13d5cfa50bb1af90bda9 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 31 May 2024 18:03:33 +0200 Subject: [PATCH 0293/2997] Add separate upload and download timemouts for CCDBApi --- CCDB/include/CCDB/CcdbApi.h | 3 ++- CCDB/src/CcdbApi.cxx | 39 +++++++++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index 3c1cfe71a5035..ea396a5b49402 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -629,7 +629,8 @@ class CcdbApi //: public DatabaseInterface static std::unique_ptr mJAlienCredentials; // access JAliEn credentials int mCurlRetries = 3; int mCurlDelayRetries = 100000; // in microseconds - size_t mCurlTimeout = 15; // in seconds, can be configured via ALICEO2_CCDB_CURL_TIMEOUT, updated according to the deployment mode + size_t mCurlTimeoutDownload = 15; // download timeout in seconds, can be configured via ALICEO2_CCDB_CURL_TIMEOUT_DOWNLOAD, updated according to the deployment mode + size_t mCurlTimeoutUpload = 15; // upload timeout in seconds, can be configured via ALICEO2_CCDB_CURL_TIMEOUT_UPLOAD, updated according to the deployment mode ClassDefNV(CcdbApi, 1); }; diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index bd34b50dcd648..98e0adf7611c3 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -217,25 +217,48 @@ void CcdbApi::init(std::string const& host) mNeedAlienToken = (host.find("https://") != std::string::npos) || (host.find("alice-ccdb.cern.ch") != std::string::npos); // Set the curl timeout. It can be forced with an env var or it has different defaults based on the deployment mode. - if (getenv("ALICEO2_CCDB_CURL_TIMEOUT")) { - auto timeout = atoi(getenv("ALICEO2_CCDB_CURL_TIMEOUT")); + if (getenv("ALICEO2_CCDB_CURL_TIMEOUT_DOWNLOAD")) { + auto timeout = atoi(getenv("ALICEO2_CCDB_CURL_TIMEOUT_DOWNLOAD")); if (timeout >= 0) { // if valid int - mCurlTimeout = timeout; + mCurlTimeoutDownload = timeout; } } else { // set a default depending on the deployment mode o2::framework::DeploymentMode deploymentMode = o2::framework::DefaultsHelpers::deploymentMode(); if (deploymentMode == o2::framework::DeploymentMode::OnlineDDS || deploymentMode == o2::framework::DeploymentMode::OnlineAUX || deploymentMode == o2::framework::DeploymentMode::OnlineECS) { - mCurlTimeout = 5; + mCurlTimeoutDownload = 5; } else if (deploymentMode == o2::framework::DeploymentMode::Grid || deploymentMode == o2::framework::DeploymentMode::FST) { - mCurlTimeout = 15; + mCurlTimeoutDownload = 15; } else if (deploymentMode == o2::framework::DeploymentMode::Local) { - mCurlTimeout = 1; + mCurlTimeoutDownload = 1; } } - LOG(debug) << "Curl timeout set to " << mCurlTimeout << " seconds"; + + if (getenv("ALICEO2_CCDB_CURL_TIMEOUT_UPLOAD")) { + auto timeout = atoi(getenv("ALICEO2_CCDB_CURL_TIMEOUT_UPLOAD")); + if (timeout >= 0) { // if valid int + mCurlTimeoutUpload = timeout; + } + } else { // set a default depending on the deployment mode + o2::framework::DeploymentMode deploymentMode = o2::framework::DefaultsHelpers::deploymentMode(); + if (deploymentMode == o2::framework::DeploymentMode::OnlineDDS || + deploymentMode == o2::framework::DeploymentMode::OnlineAUX || + deploymentMode == o2::framework::DeploymentMode::OnlineECS) { + mCurlTimeoutUpload = 3; + } else if (deploymentMode == o2::framework::DeploymentMode::Grid || + deploymentMode == o2::framework::DeploymentMode::FST) { + mCurlTimeoutUpload = 20; + } else if (deploymentMode == o2::framework::DeploymentMode::Local) { + mCurlTimeoutUpload = 20; + } + } + if (mDownloader) { + mDownloader->setRequestTimeoutTime(mCurlTimeoutDownload * 1000L); + } + + LOGP(debug, "Curl timeouts are set to: download={:2}, upload={:2} seconds", mCurlTimeoutDownload, mCurlTimeoutUpload); LOGP(info, "Init CcdApi with UserAgentID: {}, Host: {}{}", mUniqueAgentID, host, mInSnapshotMode ? "(snapshot readonly mode)" : snapshotReport.c_str()); @@ -403,7 +426,7 @@ int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::strin curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_USERAGENT, mUniqueAgentID.c_str()); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, mCurlTimeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, mCurlTimeoutUpload); CURLcode res = CURL_LAST; From 03683e1ff8584c197aca06d973bb366982d4d6c5 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 3 Jun 2024 13:52:45 +0200 Subject: [PATCH 0294/2997] Do not throw on merging non-initialized flat histors --- DataFormats/common/src/FlatHisto1D.cxx | 5 +++-- DataFormats/common/src/FlatHisto2D.cxx | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/DataFormats/common/src/FlatHisto1D.cxx b/DataFormats/common/src/FlatHisto1D.cxx index 1313da72da8b7..8e04c2c58614e 100644 --- a/DataFormats/common/src/FlatHisto1D.cxx +++ b/DataFormats/common/src/FlatHisto1D.cxx @@ -40,9 +40,10 @@ FlatHisto1D& FlatHisto1D::operator=(const FlatHisto1D& rhs) if (this == &rhs) { return *this; } - if (!rhs.canFill()) { + if (!rhs.canFill() && rhs.getNBins()) { // was initialized throw std::runtime_error("trying to copy read-only histogram"); - } else { + } + if (rhs.getNBins()) { mContainer = rhs.mContainer; init(gsl::span(mContainer.data(), mContainer.size())); } diff --git a/DataFormats/common/src/FlatHisto2D.cxx b/DataFormats/common/src/FlatHisto2D.cxx index b06241ff8d193..aa064eee10bca 100644 --- a/DataFormats/common/src/FlatHisto2D.cxx +++ b/DataFormats/common/src/FlatHisto2D.cxx @@ -43,9 +43,10 @@ FlatHisto2D& FlatHisto2D::operator=(const FlatHisto2D& rhs) if (this == &rhs) { return *this; } - if (!rhs.canFill()) { + if (!rhs.canFill() && rhs.getNBins()) { // was initialized throw std::runtime_error("trying to copy read-only histogram"); - } else { + } + if (rhs.getNBins()) { mContainer = rhs.mContainer; init(gsl::span(mContainer.data(), mContainer.size())); } From 15d915ff7eed3bb2500053091a2a5342edc0e9b1 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 3 Jun 2024 10:10:21 +0200 Subject: [PATCH 0295/2997] DPL Analysis: disable metadata lookup if not found immediately --- Framework/AnalysisSupport/src/Plugin.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Framework/AnalysisSupport/src/Plugin.cxx b/Framework/AnalysisSupport/src/Plugin.cxx index c69e5c8c56bdd..e5197e6977835 100644 --- a/Framework/AnalysisSupport/src/Plugin.cxx +++ b/Framework/AnalysisSupport/src/Plugin.cxx @@ -99,7 +99,8 @@ struct DiscoverMetadataInAOD : o2::framework::ConfigDiscoveryPlugin { // Get the metadata, if any auto m = (TMap*)currentFile->Get("metaData"); if (!m) { - LOGP(warning, "No metadata found in file \"{}\"", filename); + LOGP(info, "No metadata found in file \"{}\"", filename); + results.push_back(ConfigParamSpec{"aod-metadata-disable", VariantType::String, "1", {"Metadata not found in AOD"}}); return results; } auto it = m->MakeIterator(); From 29e3e7a32bc7f1191a29925a33edcff3011e7303 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 30 May 2024 10:47:10 +0200 Subject: [PATCH 0296/2997] OCTRL-870 DPL: correctly double-escape argument values in ECS templates --- Framework/Core/src/O2ControlHelpers.cxx | 5 ++++- Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/O2ControlHelpers.cxx b/Framework/Core/src/O2ControlHelpers.cxx index 88132572a6210..7167ce3dce38a 100644 --- a/Framework/Core/src/O2ControlHelpers.cxx +++ b/Framework/Core/src/O2ControlHelpers.cxx @@ -21,6 +21,7 @@ #include #include #include +#include namespace bfs = std::filesystem; @@ -303,7 +304,9 @@ void dumpCommand(std::ostream& dumpOut, const DeviceExecution& execution, std::s // todo: check if '' are there already. dumpOut << indLevel << indScheme << R"(- ")" << option << "\"\n"; if (value) { - dumpOut << indLevel << indScheme << R"(- "')" << value << "'\"\n"; + std::ostringstream oss; + oss << std::quoted(value, '\''); + dumpOut << indLevel << indScheme << R"(- )" << std::quoted(oss.str(), '"') << "\n"; } } } diff --git a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx index 4aca1bd9680a1..ee50158121f9e 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx @@ -49,6 +49,7 @@ WorkflowSpec defineDataProcessing() .options = {ConfigParamSpec{"a-param", VariantType::Int, 1, {"A parameter which should not be escaped"}}, ConfigParamSpec{"b-param", VariantType::String, "", {"a parameter which will be escaped"}}, ConfigParamSpec{"c-param", VariantType::String, "foo;bar", {"another parameter which will be escaped"}}, + ConfigParamSpec{"d-param", VariantType::String, "[\"foo\",\"bar\"]", {"a parameter with double quotes"}}, ConfigParamSpec{"channel-config", VariantType::String, // raw output channel "name=outta_dpl,type=push,method=bind,address=ipc:///tmp/pipe-outta-dpl,transport=shmem,rateLogging=10", {"Out-of-band channel config"}}}, @@ -523,6 +524,8 @@ const std::vector expectedTasks{ - "''" - "--c-param" - "'foo;bar'" + - "--d-param" + - "'[\"foo\",\"bar\"]'" )EXPECTED"}; TEST_CASE("TestO2ControlDump") From c0f70087189d91ebe3bb327f8b7efa6d53b1b1d4 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 30 May 2024 13:13:21 +0200 Subject: [PATCH 0297/2997] escaped string literal can be written as a raw string literal --- Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx index ee50158121f9e..4cda5fd76336a 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx @@ -49,7 +49,7 @@ WorkflowSpec defineDataProcessing() .options = {ConfigParamSpec{"a-param", VariantType::Int, 1, {"A parameter which should not be escaped"}}, ConfigParamSpec{"b-param", VariantType::String, "", {"a parameter which will be escaped"}}, ConfigParamSpec{"c-param", VariantType::String, "foo;bar", {"another parameter which will be escaped"}}, - ConfigParamSpec{"d-param", VariantType::String, "[\"foo\",\"bar\"]", {"a parameter with double quotes"}}, + ConfigParamSpec{"d-param", VariantType::String, R"(["foo","bar"])", {"a parameter with double quotes"}}, ConfigParamSpec{"channel-config", VariantType::String, // raw output channel "name=outta_dpl,type=push,method=bind,address=ipc:///tmp/pipe-outta-dpl,transport=shmem,rateLogging=10", {"Out-of-band channel config"}}}, From 2693afee708b1ec425e767cd7ea3c4db98a88626 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Thu, 30 May 2024 15:11:47 +0200 Subject: [PATCH 0298/2997] use fmt::format --- Framework/Core/src/O2ControlHelpers.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/O2ControlHelpers.cxx b/Framework/Core/src/O2ControlHelpers.cxx index 7167ce3dce38a..ad539dc4af03f 100644 --- a/Framework/Core/src/O2ControlHelpers.cxx +++ b/Framework/Core/src/O2ControlHelpers.cxx @@ -21,7 +21,7 @@ #include #include #include -#include +#include namespace bfs = std::filesystem; @@ -304,9 +304,7 @@ void dumpCommand(std::ostream& dumpOut, const DeviceExecution& execution, std::s // todo: check if '' are there already. dumpOut << indLevel << indScheme << R"(- ")" << option << "\"\n"; if (value) { - std::ostringstream oss; - oss << std::quoted(value, '\''); - dumpOut << indLevel << indScheme << R"(- )" << std::quoted(oss.str(), '"') << "\n"; + dumpOut << indLevel << indScheme << R"(- )" << fmt::format("{:?}", fmt::format("'{}'", value)) << "\n"; } } } From 2cee1d0bc62471b37d074ec8536ca4167ceee1ab Mon Sep 17 00:00:00 2001 From: wiechula Date: Mon, 3 Jun 2024 14:49:58 +0200 Subject: [PATCH 0299/2997] Updates to compile with gcc14 --- Common/Utils/include/CommonUtils/BoostHistogramUtils.h | 2 +- Detectors/ITSMFT/MFT/alignment/src/AlignPointHelper.cxx | 6 +++--- Framework/Foundation/include/Framework/FunctionalHelpers.h | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Common/Utils/include/CommonUtils/BoostHistogramUtils.h b/Common/Utils/include/CommonUtils/BoostHistogramUtils.h index 9b61bc839ddec..0d20e97adf7a7 100644 --- a/Common/Utils/include/CommonUtils/BoostHistogramUtils.h +++ b/Common/Utils/include/CommonUtils/BoostHistogramUtils.h @@ -313,7 +313,7 @@ std::vector fitGaus(Iterator first, Iterator last, BinCenterView axisfir if (nbins > 1) { // dont take bins with 0 entries or bins with nan into account // if y-value (*iter) is 1, log(*iter) will be 0. Exclude these cases - if (isnan(*axisiter) || isinf(*axisiter) || *iter <= 0 || *iter == 1) { + if (std::isnan(*axisiter) || std::isinf(*axisiter) || *iter <= 0 || *iter == 1) { continue; } double x = *axisiter; diff --git a/Detectors/ITSMFT/MFT/alignment/src/AlignPointHelper.cxx b/Detectors/ITSMFT/MFT/alignment/src/AlignPointHelper.cxx index b49377c680c99..c2be8ce838712 100644 --- a/Detectors/ITSMFT/MFT/alignment/src/AlignPointHelper.cxx +++ b/Detectors/ITSMFT/MFT/alignment/src/AlignPointHelper.cxx @@ -348,7 +348,7 @@ void AlignPointHelper::setGlobalRecoPosition(o2::mft::TrackMFT& mftTrack) mftTrack.getX(), mftTrack.getY(), mftTrack.getZ()); mGlobalRecoPosition.SetXYZ(mftTrack.getX(), mftTrack.getY(), mftTrack.getZ()); mIsAlignPointSet = true; - if (isnan(mGlobalRecoPosition.X()) || isnan(mGlobalRecoPosition.Y()) || isnan(mGlobalRecoPosition.Z())) { + if (std::isnan(mGlobalRecoPosition.X()) || std::isnan(mGlobalRecoPosition.Y()) || std::isnan(mGlobalRecoPosition.Z())) { LOGF(error, "AlignPointHelper::setGlobalRecoPosition() - track x = %.3e, y = %.3e, z = %.3e, point x = %.3e, y = %.3e, z = %.3e", mftTrack.getX(), mftTrack.getY(), mftTrack.getZ(), @@ -367,7 +367,7 @@ void AlignPointHelper::setMeasuredPosition(const o2::BaseCluster& localC mLocalMeasuredPosition.SetXYZ( localCluster.getX(), localCluster.getY(), localCluster.getZ()); - if (isnan(mLocalMeasuredPosition.X()) || isnan(mLocalMeasuredPosition.Y()) || isnan(mLocalMeasuredPosition.Z())) { + if (std::isnan(mLocalMeasuredPosition.X()) || std::isnan(mLocalMeasuredPosition.Y()) || std::isnan(mLocalMeasuredPosition.Z())) { LOGF(error, "AlignPointHelper::setMeasuredPosition() - sr %4d local x = %.3e, y = %.3e, z = %.3e", chipID, @@ -378,7 +378,7 @@ void AlignPointHelper::setMeasuredPosition(const o2::BaseCluster& localC mGlobalMeasuredPosition.SetXYZ( globalCluster.getX(), globalCluster.getY(), globalCluster.getZ()); - if (isnan(mGlobalMeasuredPosition.X()) || isnan(mGlobalMeasuredPosition.Y()) || isnan(mGlobalMeasuredPosition.Z())) { + if (std::isnan(mGlobalMeasuredPosition.X()) || std::isnan(mGlobalMeasuredPosition.Y()) || std::isnan(mGlobalMeasuredPosition.Z())) { LOGF(error, "AlignPointHelper::setMeasuredPosition() - sr %4d global x = %.3e, y = %.3e, z = %.3e", chipID, diff --git a/Framework/Foundation/include/Framework/FunctionalHelpers.h b/Framework/Foundation/include/Framework/FunctionalHelpers.h index 12470a7eb0f1c..bede9596d1131 100644 --- a/Framework/Foundation/include/Framework/FunctionalHelpers.h +++ b/Framework/Foundation/include/Framework/FunctionalHelpers.h @@ -12,6 +12,7 @@ #define O2_FRAMEWORK_FUNCTIONALHELPERS_H_ #include "Framework/Pack.h" +#include #include namespace o2::framework From 2f8759bd14b8374d20fd33509e46f641324a55ee Mon Sep 17 00:00:00 2001 From: miranov25 Date: Wed, 5 Jun 2024 09:49:54 +0200 Subject: [PATCH 0300/2997] ATO-615 - increase number of bins in phi, and decrease multiplicity range --- Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx index 81f12756e5dc7..f0fb7efee507c 100644 --- a/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx +++ b/Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx @@ -1780,10 +1780,10 @@ o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, {"refX-for-sector", VariantType::Float, 108.475f, {"Reference local x position for the sector information (default centre of IROC)"}}, {"refX-for-outer-ITS", VariantType::Float, 60.f, {"Reference local x position for matching at outer ITS"}}, {"tgl-bins", VariantType::Int, 30, {"Number of tgl bins for time series variables"}}, - {"phi-bins", VariantType::Int, 18, {"Number of phi bins for time series variables"}}, + {"phi-bins", VariantType::Int, 54, {"Number of phi bins for time series variables"}}, {"qPt-bins", VariantType::Int, 18, {"Number of qPt bins for time series variables"}}, - {"mult-bins", VariantType::Int, 20, {"Number of multiplicity bins for time series variables"}}, - {"mult-max", VariantType::Int, 80000, {"MAximum multiplicity bin"}}, + {"mult-bins", VariantType::Int, 25, {"Number of multiplicity bins for time series variables"}}, + {"mult-max", VariantType::Int, 50000, {"MAximum multiplicity bin"}}, {"threads", VariantType::Int, 4, {"Number of parallel threads"}}, {"max-ITS-TPC-DCAr", VariantType::Float, 0.2f, {"Maximum absolut DCAr value for ITS-TPC tracks"}}, {"max-ITS-TPC-DCAz", VariantType::Float, 10.f, {"Maximum absolut DCAz value for ITS-TPC tracks - larger due to vertex spread"}}, From 8dbd237ff4b28bb31267f97735706c3d3fdb3d72 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 5 Jun 2024 11:51:33 +0200 Subject: [PATCH 0301/2997] Prevent segfault in GeneratorFromFile There was a segfault when trying to fetch Mass of a TParticle that does not have an entry in the PDG database. This commit fixes this by avoiding the call to the Mass function. --- Generators/src/GeneratorFromFile.cxx | 7 +++++++ Generators/src/PrimaryGenerator.cxx | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Generators/src/GeneratorFromFile.cxx b/Generators/src/GeneratorFromFile.cxx index 069c92ec86c70..df8efc29bd1e4 100644 --- a/Generators/src/GeneratorFromFile.cxx +++ b/Generators/src/GeneratorFromFile.cxx @@ -63,6 +63,13 @@ void GeneratorFromFile::SetStartEvent(int start) bool GeneratorFromFile::rejectOrFixKinematics(TParticle& p) { + // avoid compute if the particle is not known in the PDG database + if (!p.GetPDG()) { + LOG(warn) << "Particle with pdg " << p.GetPdgCode() << " not known in DB (not fixing mass)"; + // still returning true here ... primary will be flagged as non-trackable by primary event generator + return true; + } + const auto nominalmass = p.GetMass(); auto mom2 = p.Px() * p.Px() + p.Py() * p.Py() + p.Pz() * p.Pz(); auto calculatedmass = p.Energy() * p.Energy() - mom2; diff --git a/Generators/src/PrimaryGenerator.cxx b/Generators/src/PrimaryGenerator.cxx index b07b0b181652e..6fc12ed32980a 100644 --- a/Generators/src/PrimaryGenerator.cxx +++ b/Generators/src/PrimaryGenerator.cxx @@ -140,7 +140,7 @@ void PrimaryGenerator::AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t // check the status encoding if (!mcgenstatus::isEncoded(generatorStatus) && proc == TMCProcess::kPPrimary) { - LOG(fatal) << "Generatror status " << generatorStatus << " of particle is not encoded properly."; + LOG(fatal) << "Generator status " << generatorStatus << " of particle is not encoded properly."; } /** add event vertex to track vertex **/ @@ -151,7 +151,7 @@ void PrimaryGenerator::AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t /** check if particle to be tracked exists in PDG database **/ auto particlePDG = TDatabasePDG::Instance()->GetParticle(pdgid); if (wanttracking && !particlePDG) { - LOG(warn) << "Particle to be tracked is not defined in PDG: pdg = " << pdgid; + LOG(warn) << "Particle to be tracked is not defined in PDG: pdg = " << pdgid << " (disabling tracking)"; wanttracking = false; } From e001ba36eab9a6a8ad11d9c7aadf69493361c9ab Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 5 Jun 2024 22:15:05 +0200 Subject: [PATCH 0302/2997] DPL: do not print internal error in case we rewinded When rewinding the timeframe because no data was actually sent, we expect that the oldest possible timeframe can go back and the message is therefore wrong. --- Framework/Core/include/Framework/TimesliceIndex.h | 3 +-- Framework/Core/src/CommonServices.cxx | 4 ++-- Framework/Core/src/DataRelayer.cxx | 2 +- Framework/Core/src/LifetimeHelpers.cxx | 9 ++++----- Framework/Core/src/TimesliceIndex.cxx | 4 ++-- Framework/Core/test/test_TimesliceIndex.cxx | 10 +++++----- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Framework/Core/include/Framework/TimesliceIndex.h b/Framework/Core/include/Framework/TimesliceIndex.h index c3f3c82bdeb6e..ac3970bec00ee 100644 --- a/Framework/Core/include/Framework/TimesliceIndex.h +++ b/Framework/Core/include/Framework/TimesliceIndex.h @@ -26,7 +26,6 @@ namespace o2::framework { - /// This class keeps the information relative to a given slot in the cache, in /// particular which variables are associated to it (and indirectly which /// timeslice which is always mapped to the variable 0) and wether we should @@ -130,7 +129,7 @@ class TimesliceIndex /// and the oldest possible timeslice in-fly which is still dirty. [[nodiscard]] OldestInputInfo getOldestPossibleInput() const; [[nodiscard]] OldestOutputInfo getOldestPossibleOutput() const; - OldestOutputInfo updateOldestPossibleOutput(); + OldestOutputInfo updateOldestPossibleOutput(bool rewinded); [[nodiscard]] InputChannelInfo const& getChannelInfo(ChannelIndex channel) const; // Reset the TimesliceIndex to its initial state diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 57621ecaa8f33..7b3febca7be09 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -560,7 +560,7 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "postForwardingCallbacks", "We are the first one in the topology, we need to update the oldest possible timeslice"); auto& timesliceIndex = ctx.services().get(); auto& relayer = ctx.services().get(); - timesliceIndex.updateOldestPossibleOutput(); + timesliceIndex.updateOldestPossibleOutput(decongestion->nextEnumerationTimesliceRewinded); auto& proxy = ctx.services().get(); auto oldestPossibleOutput = relayer.getOldestPossibleOutput(); if (decongestion->nextEnumerationTimesliceRewinded && decongestion->nextEnumerationTimeslice < oldestPossibleOutput.timeslice.value) { @@ -632,7 +632,7 @@ o2::framework::ServiceSpec CommonServices::decongestionSpec() O2_SIGNPOST_EVENT_EMIT(data_processor_context, cid, "oldest_possible_timeslice", "Received oldest possible timeframe %" PRIu64 " from channel %d", (uint64_t)oldestPossibleTimeslice, channel.value); relayer.setOldestPossibleInput({oldestPossibleTimeslice}, channel); - timesliceIndex.updateOldestPossibleOutput(); + timesliceIndex.updateOldestPossibleOutput(decongestion.nextEnumerationTimesliceRewinded); auto oldestPossibleOutput = relayer.getOldestPossibleOutput(); if (oldestPossibleOutput.timeslice.value == decongestion.lastTimeslice) { diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index e408632723741..b974a51fe82e1 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -759,7 +759,7 @@ void DataRelayer::getReadyToProcess(std::vector& comp break; } } - mTimesliceIndex.updateOldestPossibleOutput(); + mTimesliceIndex.updateOldestPossibleOutput(false); LOGP(debug, "DataRelayer::getReadyToProcess results notDirty:{}, consume:{}, consumeExisting:{}, process:{}, discard:{}, wait:{}", notDirty, countConsume, countConsumeExisting, countProcess, countDiscard, countWait); diff --git a/Framework/Core/src/LifetimeHelpers.cxx b/Framework/Core/src/LifetimeHelpers.cxx index 8c8605d41849c..657bdcb40326b 100644 --- a/Framework/Core/src/LifetimeHelpers.cxx +++ b/Framework/Core/src/LifetimeHelpers.cxx @@ -98,7 +98,7 @@ ExpirationHandler::Creator LifetimeHelpers::enumDrivenCreation(size_t start, siz // associated with this. LOG(debug) << "Oldest possible input is " << decongestion.nextEnumerationTimeslice; [[maybe_unused]] auto newOldest = index.setOldestPossibleInput({decongestion.nextEnumerationTimeslice}, channelIndex); - index.updateOldestPossibleOutput(); + index.updateOldestPossibleOutput(decongestion.nextEnumerationTimesliceRewinded); return slot; } } @@ -143,7 +143,7 @@ ExpirationHandler::Creator LifetimeHelpers::timeDrivenCreation(std::vectorGetData() = *counter; ref.payload = std::move(payload); (*counter)++; - }; } diff --git a/Framework/Core/src/TimesliceIndex.cxx b/Framework/Core/src/TimesliceIndex.cxx index 5707a66bac4e4..df98eea3cc9d0 100644 --- a/Framework/Core/src/TimesliceIndex.cxx +++ b/Framework/Core/src/TimesliceIndex.cxx @@ -192,7 +192,7 @@ bool TimesliceIndex::validateSlot(TimesliceSlot slot, TimesliceId currentOldest) return true; } -TimesliceIndex::OldestOutputInfo TimesliceIndex::updateOldestPossibleOutput() +TimesliceIndex::OldestOutputInfo TimesliceIndex::updateOldestPossibleOutput(bool rewinded) { auto oldestInput = getOldestPossibleInput(); OldestOutputInfo result{oldestInput.timeslice, oldestInput.channel}; @@ -223,7 +223,7 @@ TimesliceIndex::OldestOutputInfo TimesliceIndex::updateOldestPossibleOutput() mOldestPossibleOutput.timeslice.value, result.timeslice.value); } } - if (mOldestPossibleOutput.timeslice.value > result.timeslice.value) { + if (rewinded == false && mOldestPossibleOutput.timeslice.value > result.timeslice.value) { LOG(error) << "DPL internal error - oldestPossibleOutput decreased from " << mOldestPossibleOutput.timeslice.value << " to " << result.timeslice.value; } mOldestPossibleOutput = result; diff --git a/Framework/Core/test/test_TimesliceIndex.cxx b/Framework/Core/test/test_TimesliceIndex.cxx index bafba24d17a8c..3a63a9f518e58 100644 --- a/Framework/Core/test/test_TimesliceIndex.cxx +++ b/Framework/Core/test/test_TimesliceIndex.cxx @@ -119,7 +119,7 @@ TEST_CASE("TestOldestPossibleTimeslice") bool invalidated = index.validateSlot(TimesliceSlot{i}, oldest.timeslice); INFO("Slot " << i << " valid: " << invalidated); } - index.updateOldestPossibleOutput(); + index.updateOldestPossibleOutput(false); REQUIRE(slot.index == 1); REQUIRE(action == TimesliceIndex::ActionTaken::ReplaceUnused); } @@ -142,21 +142,21 @@ TEST_CASE("TestOldestPossibleTimeslice") for (size_t i = 0; i < 3; ++i) { bool invalidated = index.validateSlot(TimesliceSlot{i}, oldest.timeslice); } - index.updateOldestPossibleOutput(); + index.updateOldestPossibleOutput(false); REQUIRE(index.getOldestPossibleInput().timeslice.value == 10); REQUIRE(index.getOldestPossibleOutput().timeslice.value == 9); oldest = index.setOldestPossibleInput({11}, {1}); for (size_t i = 0; i < 3; ++i) { bool invalidated = index.validateSlot(TimesliceSlot{i}, oldest.timeslice); } - index.updateOldestPossibleOutput(); + index.updateOldestPossibleOutput(false); REQUIRE(index.getOldestPossibleInput().timeslice.value == 10); REQUIRE(index.getOldestPossibleOutput().timeslice.value == 9); // We fake the fact that we have processed the slot 0; index.markAsDirty({1}, false); - index.updateOldestPossibleOutput(); + index.updateOldestPossibleOutput(false); REQUIRE(index.getOldestPossibleOutput().timeslice.value == 9); index.markAsInvalid({1}); - index.updateOldestPossibleOutput(); + index.updateOldestPossibleOutput(false); REQUIRE(index.getOldestPossibleOutput().timeslice.value == 10); } From bdf72ddfaa0bbbb2e3905378b73a647a1e24ecb5 Mon Sep 17 00:00:00 2001 From: Maximilian Horst Date: Fri, 5 Apr 2024 10:31:11 +0200 Subject: [PATCH 0303/2997] Added Separation Power Plot for Pions and electrons Formatting Comments clang format naming Convention Added Separation Power Plot for Pions and electrons Comments last changes --- Detectors/TPC/qc/include/TPCQC/PID.h | 3 +++ Detectors/TPC/qc/src/PID.cxx | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Detectors/TPC/qc/include/TPCQC/PID.h b/Detectors/TPC/qc/include/TPCQC/PID.h index 3dc4db891823b..f07e795afe6a0 100644 --- a/Detectors/TPC/qc/include/TPCQC/PID.h +++ b/Detectors/TPC/qc/include/TPCQC/PID.h @@ -88,6 +88,7 @@ class PID } std::unordered_map>>& getMapOfHisto() { return mMapHist; } std::unordered_map>>& getMapOfCanvas() { return mMapCanvas; } + TCanvas* getSeparationPowerCanvas() { return mSeparationPowerCanvas.get(); } const std::unordered_map>>& getMapOfHisto() const { return mMapHist; } const std::unordered_map>>& getMapOfCanvas() const { return mMapCanvas; } @@ -107,6 +108,8 @@ class PID std::unordered_map>> mMapCanvas; // Map for Histograms which will be put onto the canvases, and not published separately std::unordered_map>> mMapHistCanvas; + // Canvas for Trending Separation Power + std::unique_ptr mSeparationPowerCanvas; ClassDefNV(PID, 1) }; } // namespace qc diff --git a/Detectors/TPC/qc/src/PID.cxx b/Detectors/TPC/qc/src/PID.cxx index 482ab83acd6a4..2936d80c338a0 100644 --- a/Detectors/TPC/qc/src/PID.cxx +++ b/Detectors/TPC/qc/src/PID.cxx @@ -102,6 +102,7 @@ void PID::initializeHistograms() mMapCanvas["CdEdxPIDHypothesisVsp"].emplace_back(std::make_unique("CdEdxPIDHypothesisVsp", "PID Hypothesis Ratio")); mMapCanvas["CdEdxPIDHypothesisVsp"].at(0)->Divide(5, 2); } + mSeparationPowerCanvas.reset(new TCanvas("CSeparationPower", "Separation Power")); } //______________________________________________________________________________ @@ -225,6 +226,7 @@ bool PID::processTrack(const o2::tpc::TrackTPC& track, size_t nTracks) } } } + if (mCreateCanvas) { for (auto const& pairC : mMapCanvas) { for (auto& canv : pairC.second) { From 869ceeb08f4b43923d11fa1e8ef94f296203ad32 Mon Sep 17 00:00:00 2001 From: Markus Fasel Date: Thu, 6 Jun 2024 11:17:14 +0200 Subject: [PATCH 0304/2997] [FOCAL-66, FOCAL-67, FOCAL-68] Skeleton for FOCAL detector simulation - Basic detector class - Incoming particle handling from EMCAL - Material definition from AliFOCAL package - New FOCALsimulation library --- Detectors/FOCAL/CMakeLists.txt | 1 + Detectors/FOCAL/simulation/CMakeLists.txt | 21 ++ .../include/FOCALSimulation/Detector.h | 145 +++++++++ Detectors/FOCAL/simulation/src/Detector.cxx | 279 ++++++++++++++++++ .../simulation/src/FOCALSimulationLinkDef.h | 21 ++ 5 files changed, 467 insertions(+) create mode 100644 Detectors/FOCAL/simulation/CMakeLists.txt create mode 100644 Detectors/FOCAL/simulation/include/FOCALSimulation/Detector.h create mode 100644 Detectors/FOCAL/simulation/src/Detector.cxx create mode 100644 Detectors/FOCAL/simulation/src/FOCALSimulationLinkDef.h diff --git a/Detectors/FOCAL/CMakeLists.txt b/Detectors/FOCAL/CMakeLists.txt index 34db833d6d9e9..d19010da9ac76 100644 --- a/Detectors/FOCAL/CMakeLists.txt +++ b/Detectors/FOCAL/CMakeLists.txt @@ -12,5 +12,6 @@ add_subdirectory(base) add_subdirectory(calib) add_subdirectory(calibration) +add_subdirectory(simulation) add_subdirectory(reconstruction) add_subdirectory(workflow) \ No newline at end of file diff --git a/Detectors/FOCAL/simulation/CMakeLists.txt b/Detectors/FOCAL/simulation/CMakeLists.txt new file mode 100644 index 0000000000000..a75a0795584f6 --- /dev/null +++ b/Detectors/FOCAL/simulation/CMakeLists.txt @@ -0,0 +1,21 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2_add_library(FOCALSimulation + SOURCES src/Detector.cxx + PUBLIC_LINK_LIBRARIES ROOT::TreePlayer O2::FOCALBase O2::DetectorsBase O2::SimConfig O2::SimulationDataFormat O2::Headers O2::DataFormatsFOCAL + AliceO2::InfoLogger + Microsoft.GSL::GSL) + +o2_target_root_dictionary( + FOCALSimulation + HEADERS include/FOCALSimulation/Detector.h +) \ No newline at end of file diff --git a/Detectors/FOCAL/simulation/include/FOCALSimulation/Detector.h b/Detectors/FOCAL/simulation/include/FOCALSimulation/Detector.h new file mode 100644 index 0000000000000..170b6ed0f595d --- /dev/null +++ b/Detectors/FOCAL/simulation/include/FOCALSimulation/Detector.h @@ -0,0 +1,145 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef ALICEO2_FOCAL_DETECTOR_H_ +#define ALICEO2_FOCAL_DETECTOR_H_ + +#include + +#include "DetectorsBase/Detector.h" +#include "FOCALBase/Hit.h" + +class FairVolume; + +namespace o2::focal +{ + +/// \struct Parent +/// \brief Information about superparent (particle entering any FOCAL volume) +/// \ingroup FOCALsimulation +struct Parent { + int mPDG; ///< PDG code + double mEnergy; ///< Total energy + bool mHasTrackReference; ///< Flag indicating whether parent has a track reference +}; + +/// \class Detector +/// \brief FOCAL detector simulation +/// \ingroup FOCALsimulation +/// \author Markus Fasel , Oak Ridge National Laboratory +/// \since June 6, 2024 +class Detector : public o2::base::DetImpl +{ + public: + enum MediumType_t { ID_TUNGSTEN = 0, + ID_SILICON = 1, + ID_G10 = 2, + ID_COPPER = 3, + ID_STEEL = 4, + ID_ALLOY = 5, + ID_CERAMIC = 6, + ID_PB = 7, + ID_SC = 8, + ID_SIINSENS = 9, + ID_VAC = 10, + ID_AIR = 11 }; + /// \brief Dummy constructor + Detector() = default; + + /// \brief Destructor + ~Detector() override; + + /// \brief Initializing detector + void InitializeO2Detector() override; + + /// \brief Processing hit creation in the FOCAL sensitive volume + /// \param v Current sensitive volume + Bool_t ProcessHits(FairVolume* v = nullptr) final; + + /// \brief register container with hits + void Register() override; + + /// \brief Get access to the hits + /// \return Hit collection + std::vector* getHits(Int_t iColl) const + { + if (iColl == 0) { + return mHits; + } + return nullptr; + } + + /// \brief Clean point collection + void Reset() final; + + /// \brief Steps to be carried out at the end of the event + /// + /// For FOCAL cleaning the hit collection and the lookup table + void EndOfEvent() final; + + /// \brief Begin primaray + /// + /// Caching current primary ID and set current parent ID to the + /// current primary ID + void BeginPrimary() override; + + /// \brief Finish current primary + /// + /// Reset caches for current primary, current parent and current cell + void FinishPrimary() override; + + protected: + /// \brief Creating detector materials for the FOCAL detector + void CreateMaterials(); + + void ConstructGeometry() override; + + /// \brief Add new superparent to the container + /// \param trackID Track ID of the superparent + /// \param pdg PDG code of the superparent + /// \param energy Energy of the superparent + Parent* AddSuperparent(int trackID, int pdg, double energy); + + private: + /// \brief Copy constructor (used in MT) + Detector(const Detector& rhs); + + std::vector* mHits; ///< Container with hits + + std::unordered_map mSuperParentsIndices; //! mSuperParents; //! + friend class o2::base::DetImpl; + ClassDefOverride(Detector, 1); +}; +} // namespace o2::focal + +#ifdef USESHM +namespace o2 +{ +namespace base +{ +template <> +struct UseShm { + static constexpr bool value = true; +}; +} // namespace base +} // namespace o2 +#endif + +#endif // ALICEO2_FOCAL_DETECTOR_H_ \ No newline at end of file diff --git a/Detectors/FOCAL/simulation/src/Detector.cxx b/Detectors/FOCAL/simulation/src/Detector.cxx new file mode 100644 index 0000000000000..acc4454b010ca --- /dev/null +++ b/Detectors/FOCAL/simulation/src/Detector.cxx @@ -0,0 +1,279 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include + +#include + +#include "FOCALSimulation/Detector.h" + +using namespace o2::focal; + +Detector::Detector(const Detector& rhs) +{ +} + +Detector::~Detector() +{ + o2::utils::freeSimVector(mHits); +} + +void Detector::InitializeO2Detector() +{ +} + +Bool_t Detector::ProcessHits(FairVolume* v) +{ + int track = fMC->GetStack()->GetCurrentTrackNumber(), + directparent = fMC->GetStack()->GetCurrentParentTrackNumber(); + // Like other calorimeters FOCAL will create a huge amount of shower particles during tracking + // Instead, the hits should be assigned to the incoming particle in FOCAL. + // Implementation of the incoming particle search taken from implementation in EMCAL. + if (track != mCurrentTrack) { + LOG(debug4) << "Doing new track " << track << " current (" << mCurrentTrack << "), direct parent (" << directparent << ")" << std::endl; + // new current track - check parentage + auto hasSuperParent = mSuperParentsIndices.find(directparent); + if (hasSuperParent != mSuperParentsIndices.end()) { + // same superparent as direct parent + mCurrentParentID = hasSuperParent->second; + mSuperParentsIndices[track] = hasSuperParent->second; + auto superparent = mSuperParents.find(mCurrentParentID); + if (superparent != mSuperParents.end()) { + mCurrentSuperparent = &(superparent->second); + } else { + LOG(error) << "Attention: No superparent object found (parent " << mCurrentParentID << ")"; + mCurrentSuperparent = nullptr; + } + LOG(debug4) << "Found superparent " << mCurrentParentID << std::endl; + } else { + // start of new chain + // for new incoming tracks the super parent index is equal to the track ID (for recursion) + mSuperParentsIndices[track] = track; + mCurrentSuperparent = AddSuperparent(track, fMC->TrackPid(), fMC->Etot()); + mCurrentParentID = track; + } + mCurrentTrack = track; + } + return true; +} + +Parent* Detector::AddSuperparent(int trackID, int pdg, double energy) +{ + LOG(debug3) << "Adding superparent for track " << trackID << " with PID " << pdg << " and energy " << energy; + auto entry = mSuperParents.insert({trackID, {pdg, energy, false}}); + return &(entry.first->second); +} + +void Detector::EndOfEvent() { Reset(); } + +void Detector::Register() +{ + FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, kTRUE); +} + +void Detector::Reset() +{ + LOG(debug) << "Cleaning FOCAL hits ..."; + if (!o2::utils::ShmManager::Instance().isOperational()) { + mHits->clear(); + } + + mSuperParentsIndices.clear(); + mSuperParents.clear(); + mCurrentTrack = -1; + mCurrentParentID = -1; +} + +void Detector::CreateMaterials() +{ + + // --- Define the various materials for GEANT --- + + /// Silicon + float aSi = 28.09; + float zSi = 14.0; + float dSi = 2.33; + float x0Si = 9.36; + Material(1, "Si $", aSi, zSi, dSi, x0Si, 18.5); + + //// W Tungsten + float aW = 183.84; + float zW = 74.0; + float dW = 19.3; + float x0W = 0.35; + Material(0, "W $", aW, zW, dW, x0W, 17.1); + + // Cu + Material(3, "Cu $", 63.54, 29., 8.96, 1.43, 15.); + + //// Pb + Material(10, "Pb $", 207.19, 82., 11.35, .56, 18.5); + + //// Scintillator (copied from EMCal) + // --- The polysterene scintillator (CH) --- + float aP[2] = {12.011, 1.00794}; + float zP[2] = {6.0, 1.0}; + float wP[2] = {1.0, 1.0}; + float dP = 1.032; + Mixture(11, "Polystyrene$", aP, zP, dP, -2, wP); + + // G10 + + float aG10[4] = {1., 12.011, 15.9994, 28.086}; + float zG10[4] = {1., 6., 8., 14.}; + // PH float wG10[4]={0.148648649,0.104054054,0.483499056,0.241666667}; + float wG10[4] = {0.15201, 0.10641, 0.49444, 0.24714}; + Mixture(2, "G10 $", aG10, zG10, 1.7, 4, wG10); + + //// 94W-4Ni-2Cu + float aAlloy[3] = {183.84, 58.6934, 63.54}; + float zAlloy[3] = {74.0, 28, 29}; + float wAlloy[3] = {0.94, 0.04, 0.02}; + float dAlloy = wAlloy[0] * 19.3 + wAlloy[1] * 8.908 + wAlloy[2] * 8.96; + Mixture(5, "Alloy $", aAlloy, zAlloy, dAlloy, 3, wAlloy); + + // Steel + float aSteel[4] = {55.847, 51.9961, 58.6934, 28.0855}; + float zSteel[4] = {26., 24., 28., 14.}; + float wSteel[4] = {.715, .18, .1, .005}; + float dSteel = 7.88; + Mixture(4, "STAINLESS STEEL$", aSteel, zSteel, dSteel, 4, wSteel); + + // Air + float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948}; + float zAir[4] = {6., 7., 8., 18.}; + float wAir[4] = {0.000124, 0.755268, 0.231781, 0.012827}; + float dAir1 = 1.20479E-10; + float dAir = 1.20479E-3; + Mixture(98, "Vacum$", aAir, zAir, dAir1, 4, wAir); + Mixture(99, "Air $", aAir, zAir, dAir, 4, wAir); + + // Ceramic + // Ceramic 97.2% Al2O3 , 2.8% SiO2 + // float wcer[2]={0.972,0.028}; // Not used + float aal2o3[2] = {26.981539, 15.9994}; + float zal2o3[2] = {13., 8.}; + float wal2o3[2] = {2., 3.}; + float denscer = 3.6; + // SiO2 + float aglass[2] = {28.0855, 15.9994}; + float zglass[2] = {14., 8.}; + float wglass[2] = {1., 2.}; + float dglass = 2.65; + Mixture(6, "Al2O3 $", aal2o3, zal2o3, denscer, -2, wal2o3); + Mixture(7, "glass $", aglass, zglass, dglass, -2, wglass); + + // Ceramic is a mixtur of glass and Al2O3 ? + // Not clear how to do this with AliMixture + // Not needed; so skip for now + + /* +float acer[2],zcer[2]; +char namate[21]=""; +float a,z,d,radl,absl,buf[1]; +Int_t nbuf; +gMC->Gfmate((*fIdmate)[6], namate, a, z, d, radl, absl, buf, nbuf); +acer[0]=a; +zcer[0]=z; +gMC->Gfmate((*fIdmate)[7], namate, a, z, d, radl, absl, buf, nbuf); +acer[1]=a; +zcer[1]=z; + +AliMixture( 8, "Ceramic $", acer, zcer, denscer, 2, wcer); +*/ + + // Use Al2O3 instead: + + Mixture(8, "Ceramic $", aal2o3, zal2o3, denscer, -2, wal2o3); + + // Define tracking media + // format + + float tmaxfdSi = 10.0; // 0.1; // .10000E+01; // Degree + float stemaxSi = 0.1; // .10000E+01; // cm + float deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0 idtmed[3599]; + Medium(ID_TUNGSTEN, "W conv.$", 0, 0, + isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, nullptr, 0); + /// Si plate -> idtmed[3600]; + Medium(ID_SILICON, "Si sens$", 1, 0, + isxfld, sxmgmx, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi, nullptr, 0); + + //// G10 plate -> idtmed[3601]; + Medium(ID_G10, "G10 plate$", 2, 0, + isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.01, nullptr, 0); + + //// Cu plate --> idtmed[3602]; + Medium(ID_COPPER, "Cu $", 3, 0, + isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.0001, nullptr, 0); + + //// S steel --> idtmed[3603]; + Medium(ID_STEEL, "S steel$", 4, 0, + isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.0001, nullptr, 0); + + //// Alloy --> idtmed[3604]; + Medium(ID_ALLOY, "Alloy conv.$", 5, 0, + isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, nullptr, 0); + + //// Ceramic --> idtmed[3607] + Medium(ID_CERAMIC, "Ceramic$", 8, 0, + isxfld, sxmgmx, 10.0, 0.01, 0.1, 0.003, 0.003, nullptr, 0); + + // HCAL materials // Need to double-check tracking pars for this + /// Pb plate --> idtmed[3608] + Medium(ID_PB, "Pb $", 10, 0, + isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, nullptr, 0); + /// Scintillator --> idtmed[3609] + Medium(ID_SC, "Scint $", 11, 0, + isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.001, 0.001, nullptr, 0); + + /// Si plate -> idtmed[3610]; + Medium(ID_SIINSENS, "Si insens$", 1, 0, + 10.0, 0.1, 0.1, epsil, 0.001, 0, 0); + + /// idtmed[3697] + Medium(ID_VAC, "Vacuum $", 98, 0, + isxfld, sxmgmx, 10.0, 1.0, 0.1, 0.1, 1.0, nullptr, 0); + + /// idtmed[3698] + Medium(ID_AIR, "Air gaps$", 99, 0, + isxfld, sxmgmx, 10.0, 1.0, 0.1, epsil, 0.001, nullptr, 0); +} + +void Detector::ConstructGeometry() +{ +} + +void Detector::BeginPrimary() +{ + mCurrentPrimaryID = fMC->GetStack()->GetCurrentTrackNumber(); + LOG(debug) << "Starting primary " << mCurrentPrimaryID << " with energy " << fMC->GetStack()->GetCurrentTrack()->Energy(); +} + +void Detector::FinishPrimary() +{ + LOG(debug) << "Finishing primary " << mCurrentPrimaryID << std::endl; + // Resetting primary and parent ID + mCurrentPrimaryID = -1; +} \ No newline at end of file diff --git a/Detectors/FOCAL/simulation/src/FOCALSimulationLinkDef.h b/Detectors/FOCAL/simulation/src/FOCALSimulationLinkDef.h new file mode 100644 index 0000000000000..3105f04ae2c99 --- /dev/null +++ b/Detectors/FOCAL/simulation/src/FOCALSimulationLinkDef.h @@ -0,0 +1,21 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::focal::Detector + ; +#pragma link C++ class o2::base::DetImpl < o2::focal::Detector> + ; + +#endif From 7cf6732d54ef50e83507373fc7fcb24ba9b13388 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 7 Jun 2024 12:59:34 +0200 Subject: [PATCH 0305/2997] Add MCtruth + extra info to SVStudy and TrackMCStudy output --- .../study/include/GlobalTrackingStudy/V0Ext.h | 7 +- .../study/src/SVStudy.cxx | 23 ++++- .../study/src/TrackMCStudy.cxx | 92 +++++++++++++++---- 3 files changed, 101 insertions(+), 21 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/V0Ext.h b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/V0Ext.h index 1beddf693c458..99b35247081e6 100644 --- a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/V0Ext.h +++ b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/V0Ext.h @@ -15,6 +15,7 @@ #define ALICEO2_V0EXT_H #include "ReconstructionDataFormats/V0.h" +#include "SimulationDataFormat/MCCompLabel.h" namespace o2 { @@ -27,7 +28,11 @@ struct ProngInfoExt { int nClITS = 0; int pattITS = 0; float chi2ITSTPC = 0.f; - ClassDefNV(ProngInfoExt, 1); + int8_t corrGlo = -1; + int8_t corrITSTPC = -1; + int8_t corrITS = -1; + int8_t corrTPC = -1; + ClassDefNV(ProngInfoExt, 2); }; struct V0Ext { diff --git a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx index e61f6067912c5..8ce1c1cec3e01 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/SVStudy.cxx @@ -161,22 +161,35 @@ o2::dataformats::V0Ext SVStudySpec::processV0(int iv, o2::globaltracking::RecoCo v0ext.v0 = v0sel; } v0ext.v0ID = v0id; + o2::MCCompLabel lb; for (int ip = 0; ip < 2; ip++) { auto& prInfo = v0ext.prInfo[ip]; auto gid = v0ext.v0ID.getProngID(ip); auto gidset = recoData.getSingleDetectorRefs(gid); + lb = recoData.getTrackMCLabel(gid); + if (lb.isValid()) { + prInfo.corrGlo = !lb.isFake(); + } // get TPC tracks, if any if (gidset[GTrackID::TPC].isSourceSet()) { const auto& tpcTr = recoData.getTPCTrack(gidset[GTrackID::TPC]); prInfo.trackTPC = tpcTr; prInfo.nClTPC = tpcTr.getNClusters(); + lb = recoData.getTrackMCLabel(gidset[GTrackID::TPC]); + if (lb.isValid()) { + prInfo.corrTPC = !lb.isFake(); + } } // get ITS tracks, if any if (gid.includesDet(DetID::ITS)) { auto gidITS = recoData.getITSContributorGID(gid); if (gidset[GTrackID::ITS].isSourceSet()) { - const auto& itsTr = recoData.getITSTrack(recoData.getITSContributorGID(gid)); + const auto& itsTr = recoData.getITSTrack(gidset[GTrackID::ITS]); prInfo.nClITS = itsTr.getNClusters(); + lb = recoData.getTrackMCLabel(gidset[GTrackID::ITS]); + if (lb.isValid()) { + prInfo.corrITS = !lb.isFake(); + } for (int il = 0; il < 7; il++) { if (itsTr.hasHitOnLayer(il)) { prInfo.pattITS |= 0x1 << il; @@ -185,6 +198,10 @@ o2::dataformats::V0Ext SVStudySpec::processV0(int iv, o2::globaltracking::RecoCo } else { const auto& itsTrf = recoData.getITSABRefs()[gidset[GTrackID::ITSAB]]; prInfo.nClITS = itsTrf.getNClusters(); + lb = recoData.getTrackMCLabel(gidset[GTrackID::ITSAB]); + if (lb.isValid()) { + prInfo.corrITS = !lb.isFake(); + } for (int il = 0; il < 7; il++) { if (itsTrf.hasHitOnLayer(il)) { prInfo.pattITS |= 0x1 << il; @@ -194,7 +211,11 @@ o2::dataformats::V0Ext SVStudySpec::processV0(int iv, o2::globaltracking::RecoCo } if (gidset[GTrackID::ITSTPC].isSourceSet()) { auto mtc = recoData.getTPCITSTrack(gidset[GTrackID::ITSTPC]); + lb = recoData.getTrackMCLabel(gidset[GTrackID::ITSTPC]); prInfo.chi2ITSTPC = mtc.getChi2Match(); + if (lb.isValid()) { + prInfo.corrITSTPC = !lb.isFake(); + } } } } diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx index b4ad366c291cb..4a20e3d2e022d 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx @@ -170,6 +170,29 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) prepareITSData(recoData); } + auto getITSPatt = [&](GTrackID gid, uint8_t& ncl) { + int16_t patt = 0; + if (gid.getSource() == VTIndex::ITSAB) { + const auto& itsTrf = recoData.getITSABRefs()[gid]; + ncl = itsTrf.getNClusters(); + for (int il = 0; il < 7; il++) { + if (itsTrf.hasHitOnLayer(il)) { + patt |= 0x1 << il; + } + } + patt = -patt; + } else { + const auto& itsTr = recoData.getITSTrack(gid); + for (int il = 0; il < 7; il++) { + if (itsTr.hasHitOnLayer(il)) { + patt |= 0x1 << il; + ncl++; + } + } + } + return patt; + }; + auto getLowestPadrow = [&recoData](const o2::tpc::TrackTPC& trc) { if (recoData.inputsTPCclusters) { uint8_t clSect = 0, clRow = 0; @@ -232,10 +255,18 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) std::vector recGIDs; std::vector recFakes; std::vector lowestPadrows; - + std::vector itsPatterns; + std::vector tpcNcls; + std::vector itsNcls; + LOGP(info, "Recorded {} reconstructed tracks", MCTRMap.size()); + size_t count = 0; for (auto ent : MCTRMap) { + count++; auto lbl = ent.first; if (lbl.getEventID() != prevLbl.getEventID() || lbl.getSourceID() != prevLbl.getSourceID()) { + if (mVerbose > 0) { + LOGP(info, "Loading MC Event={} / Src={}", lbl.getEventID(), lbl.getSourceID()); + } mcTracks = &mcReader.getTracks(lbl.getSourceID(), lbl.getEventID()); prevLbl = lbl; } @@ -245,7 +276,7 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) std::array pxyz{(float)mcPart.GetStartVertexMomentumX(), (float)mcPart.GetStartVertexMomentumY(), (float)mcPart.GetStartVertexMomentumZ()}; TParticlePDG* pPDG = TDatabasePDG::Instance()->GetParticle(pdg); if (!pPDG) { - LOGP(error, "Unknown particle {}, skip", pdg); + LOGP(error, "Unknown particle {}, skip. Was at {} of {}", pdg, count, MCTRMap.size()); continue; } o2::track::TrackPar mctrO2(xyz, pxyz, TMath::Nint(pPDG->Charge() / 3), false); @@ -265,40 +296,55 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) recGIDs.clear(); recFakes.clear(); lowestPadrows.clear(); + itsPatterns.clear(); + itsNcls.clear(); + tpcNcls.clear(); if (mVerbose > 1) { LOGP(info, "[{}] Lbl:{} PDG:{:+5d} (par: {:+5d}) | MC: {}", vgids.size(), lbl.asString(), pdg, pdgParent, mctrO2.asString()); } - bool itstpcMatch = false; int entITS = -1, entTPC = -1, entITSTPC = -1; for (size_t i = 0; i < vgids.size(); i++) { auto vid = vgids[i].second; auto lbl = recoData.getTrackMCLabel(vid); const auto& trc = recoData.getTrackParam(vid); + int16_t itsPatt = 0; + uint8_t nclITS = 0; + uint8_t nclTPC = 0; if (mVerbose > 1) { LOGP(info, " :{} {:22} | [{}] {}", lbl.asString(), vid.asString(), i, ((const o2::track::TrackPar&)trc).asString()); } recTracks.push_back(trc); recGIDs.push_back(vid); recFakes.push_back(recoData.getTrackMCLabel(vid).isFake()); + auto msk = vid.getSourceDetectorsMask(); if (mCheckMatching) { lowestPadrows.push_back(-1); - auto msk = vid.getSourceDetectorsMask(); - if (msk[DetID::TPC]) { - lowestPadrows.back() = getLowestPadrow(recoData.getTPCTrack(recoData.getTPCContributorGID(vid))); + } + if (msk[DetID::ITS]) { + auto gidITS = recoData.getITSContributorGID(vid); + itsPatt = getITSPatt(gidITS, nclITS); + if (vid.getSource() == VTIndex::ITS) { + entITS = i; } - if (msk[DetID::ITS] && msk[DetID::TPC]) { - itstpcMatch = true; + if (msk[DetID::TPC]) { entITSTPC = i; - } else { - if (vid.getSource() == VTIndex::ITS) { - entITS = i; - } else { - if (msk[DetID::TPC]) { - entTPC = i; - } - } } } + if (msk[DetID::TPC]) { + if (vid.getSource() == VTIndex::TPC) { + entTPC = i; + } + auto gidTPC = recoData.getTPCContributorGID(vid); + const auto& trtpc = recoData.getTPCTrack(gidTPC); + nclTPC = trtpc.getNClusters(); + if (mCheckMatching) { + auto& lr = lowestPadrows.back(); + lr = getLowestPadrow(recoData.getTPCTrack(recoData.getTPCContributorGID(vid))); + } + } + tpcNcls.push_back(nclTPC); + itsNcls.push_back(nclITS); + itsPatterns.push_back(itsPatt); } (*mDBGOut) << "tracks" << "lbl=" << lbl @@ -307,7 +353,10 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) << "pdgPar=" << pdgParent << "recTr=" << recTracks << "recGID=" << recGIDs - << "recFake=" << recFakes; + << "recFake=" << recFakes + << "itsPatt=" << itsPatterns + << "nClITS=" << itsNcls + << "nClTPC=" << tpcNcls; if (mCheckMatching) { (*mDBGOut) << "tracks" << "lowestPadRow=" << lowestPadrows; @@ -317,7 +366,7 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) // special ITS-TPC matching failure output while (mCheckMatching) { - if (!itstpcMatch && entITS > -1 && entTPC > -1) { // ITS and TPC were found but matching failed + if (entITSTPC < 0 && entITS > -1 && entTPC > -1) { // ITS and TPC were found but matching failed auto vidITS = vgids[entITS].second; auto vidTPC = recoData.getTPCContributorGID(vgids[entTPC].second); // might be TPC match to outer detector, extract TPC auto trcTPC = recoData.getTrackParam(vidTPC); @@ -345,9 +394,10 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) << "tpcRef=" << trcTPC << "itsOrig=" << trcITSOrig << "tpcOrig=" << trcTPCOrig + << "itsPatt=" << itsPatterns[entITS] << "tpcLowestRow=" << lowestTPCRow << "\n"; - } else if (itstpcMatch) { // match was found + } else if (entITSTPC > -1) { // match was found auto contribIDs = recoData.getSingleDetectorRefs(vgids[entITSTPC].second); auto vidMatch = contribIDs[VTIndex::ITSTPC]; auto vidTPC = contribIDs[VTIndex::TPC]; @@ -376,7 +426,11 @@ void TrackMCStudy::process(o2::globaltracking::RecoContainer& recoData) << "gidTPC=" << vidTPC << "gidITS=" << vidITS << "tpcOrig=" << trcTPCOrig + << "nClITS=" << itsNcls[entITSTPC] + << "itsPatt=" << itsPatterns[entITSTPC] << "itstpc=" << ((o2::track::TrackParCov&)trackITSTPC) + << "matchChi2=" << trackITSTPC.getChi2Match() + << "refitChi2=" << trackITSTPC.getChi2Refit() << "timeTB=" << timeTB << "tpcLowestRow=" << lowestTPCRow << "\n"; From fc75fcc0115564de75207884067140a93fe5a009 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sun, 9 Jun 2024 10:32:20 +0200 Subject: [PATCH 0306/2997] AOD: Fix aod-thinner for new-ish datamodel changes (#13210) --- Framework/AODMerger/src/aodThinner.cxx | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Framework/AODMerger/src/aodThinner.cxx b/Framework/AODMerger/src/aodThinner.cxx index 6d474aae511c6..1f1fb2978d91d 100644 --- a/Framework/AODMerger/src/aodThinner.cxx +++ b/Framework/AODMerger/src/aodThinner.cxx @@ -214,7 +214,9 @@ int main(int argc, char* argv[]) uint8_t tpcNClsFindable = 0; bool bTPClsFindable = false; uint8_t ITSClusterMap = 0; + UInt_t ITSClusterSizes = 0; bool bITSClusterMap = false; + bool bITSClusterSizes = false; uint8_t TRDPattern = 0; bool bTRDPattern = false; float_t TOFChi2 = 0; @@ -231,6 +233,9 @@ int main(int argc, char* argv[]) } else if (brName == "fITSClusterMap") { trackExtraTree->SetBranchAddress("fITSClusterMap", &ITSClusterMap); bITSClusterMap = true; + } else if (brName == "fITSClusterSizes") { + trackExtraTree->SetBranchAddress("fITSClusterSizes", &ITSClusterSizes); + bITSClusterSizes = true; } else if (brName == "fTRDPattern") { trackExtraTree->SetBranchAddress("fTRDPattern", &TRDPattern); bTRDPattern = true; @@ -240,6 +245,15 @@ int main(int argc, char* argv[]) } } + // Sanity-Check + // If any (%ITSClusterMap or %ITSClusterSizes) of these are not found, continuation is not possible, hence fataling + if (!bTPClsFindable || !bTRDPattern || !bTOFChi2 || + (!bITSClusterMap && !bITSClusterSizes)) { + printf(" *** FATAL *** Branch detection failed in %s for trackextra.[(fITSClusterMap=%d,fITSClusterSizes=%d),fTPCNClsFindable=%d,fTRDPattern=%d,fTOFChi2=%d]\n", dfName, bITSClusterMap, bITSClusterSizes, bTPClsFindable, bTRDPattern, bTOFChi2); + exitCode = 10; + break; + } + int fIndexCollisions = 0; track_iu->SetBranchAddress("fIndexCollisions", &fIndexCollisions); @@ -253,11 +267,10 @@ int main(int argc, char* argv[]) // Flag collisions hasCollision[i] = (fIndexCollisions >= 0); - // Remove TPC only tracks, if (opt.) they are not assoc. to a V0 - if ((!bTPClsFindable || tpcNClsFindable > 0.) && + // Remove TPC only tracks, if they are not assoc. to a V0 + if (tpcNClsFindable > 0 && TRDPattern == 0 && TOFChi2 < -1. && (!bITSClusterMap || ITSClusterMap == 0) && - (!bTRDPattern || TRDPattern == 0) && - (!bTOFChi2 || TOFChi2 < -1.) && + (!bITSClusterSizes || ITSClusterSizes == 0) && (keepV0TPCs.find(i) == keepV0TPCs.end())) { counter++; } else { @@ -410,6 +423,7 @@ int main(int argc, char* argv[]) if (exitCode != 0) { printf("Removing incomplete output file %s.\n", outputFile->GetName()); gSystem->Unlink(outputFile->GetName()); + return exitCode; // skip output below } clock.Stop(); From 4c32a26aafea4db3f885cfd2fa40f8f7fa90664d Mon Sep 17 00:00:00 2001 From: Ivana Hrivnacova Date: Mon, 3 Jun 2024 18:23:22 +0200 Subject: [PATCH 0307/2997] Update doxygen configuration: - Fixing Illegal format for option FILTER_PATTERNS - Removed obsolete keywords --- doc/doxyfile-with-graphs.in | 8 +++----- doc/doxyfile.in | 6 ++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/doc/doxyfile-with-graphs.in b/doc/doxyfile-with-graphs.in index 75f18b7c54e72..1ee15ff2bab83 100644 --- a/doc/doxyfile-with-graphs.in +++ b/doc/doxyfile-with-graphs.in @@ -28,7 +28,6 @@ INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 2 ALIASES = -TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO @@ -110,14 +109,14 @@ EXCLUDE = .git/ \ html-docs/ \ doxygen cmake config gconfig geometry input parameters .svn vis EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = G__* ClassImp build_* CHANGELOG* +EXCLUDE_PATTERNS = G__* ClassImp build_* CHANGELOG* EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO IMAGE_PATH = -INPUT_FILTER = @CMAKE_SOURCE_DIR@/doc/scripts/filter_for_doxygen.sh -FILTER_PATTERNS = *.md +INPUT_FILTER = +FILTER_PATTERNS = *.md=@CMAKE_SOURCE_DIR@/doc/scripts/filter_for_doxygen.sh FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = @CMAKE_SOURCE_DIR@/README.md @@ -137,7 +136,6 @@ VERBATIM_HEADERS = YES # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = .git #--------------------------------------------------------------------------- # Configuration options related to the HTML output diff --git a/doc/doxyfile.in b/doc/doxyfile.in index 1e89f1ac1d958..f42c631e3f935 100644 --- a/doc/doxyfile.in +++ b/doc/doxyfile.in @@ -28,7 +28,6 @@ INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 2 ALIASES = -TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO @@ -116,8 +115,8 @@ EXAMPLE_PATH = EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO IMAGE_PATH = -INPUT_FILTER = @CMAKE_SOURCE_DIR@/doc/scripts/filter_for_doxygen.sh -FILTER_PATTERNS = *.md +INPUT_FILTER = +FILTER_PATTERNS = *.md=@CMAKE_SOURCE_DIR@/doc/scripts/filter_for_doxygen.sh FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = @CMAKE_SOURCE_DIR@/README.md @@ -137,7 +136,6 @@ VERBATIM_HEADERS = YES # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = .git #--------------------------------------------------------------------------- # Configuration options related to the HTML output From c0842415269e7319527cfd0da76099b23890222d Mon Sep 17 00:00:00 2001 From: swenzel Date: Mon, 10 Jun 2024 15:12:46 +0200 Subject: [PATCH 0308/2997] Fix memory leak related to SerializedInfo/RootSerializableKeyValues SerializedInfo leaked buffer data. This should now be fixed by employing a unique_ptr strategy (making it clear that SerializedInfo takes ownership) and adding a destructor. Fixes https://its.cern.ch/jira/browse/O2-5029 --- .../RootSerializableKeyValueStore.h | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h index c29a3024de6e1..25205ce05ab40 100644 --- a/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h +++ b/Common/Utils/include/CommonUtils/RootSerializableKeyValueStore.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace o2 { @@ -39,14 +40,19 @@ class RootSerializableKeyValueStore /// Structure encapsulating the stored information: raw buffers and attached type information (combination of type_index_hash and TClass information) struct SerializedInfo { SerializedInfo() = default; - SerializedInfo(void* o, int N, char* b, TClass* cl, std::string const& s) : objptr(o), N(N), bufferptr(b), cl(cl), typeinfo_name(s) {} + SerializedInfo(int N, + std::unique_ptr buffer, TClass const* cl, std::string const& s) : N(N), cl(cl), typeinfo_name(s) + { + bufferptr = buffer.get(); + buffer.release(); + } SerializedInfo(SerializedInfo const& other) { // we do a deep copy N = other.N; bufferptr = new char[N]; + std::memcpy(bufferptr, other.bufferptr, sizeof(char) * N); - objptr = nullptr; cl = other.cl; typeinfo_name = other.typeinfo_name; } @@ -56,13 +62,18 @@ class RootSerializableKeyValueStore std::swap(*this, temp); return *this; } + ~SerializedInfo() + { + // we are the owner of this ... so delete it + delete bufferptr; + } - void* objptr = nullptr; //! pointer to existing object in memory + void* objptr = nullptr; //! pointer for "caching" Int_t N = 0; char* bufferptr = nullptr; //[N] pointer to serialized buffer // we use the TClass and/or the type_index_hash for type idendification - TClass* cl = nullptr; + TClass const* cl = nullptr; std::string typeinfo_name; // typeinfo name that can be used to store type if TClass not available (for PODs!) ClassDefNV(SerializedInfo, 1); }; @@ -160,21 +171,21 @@ class RootSerializableKeyValueStore { // make sure we have a TClass for this // if there is a TClass, we'll use ROOT serialization to encode into the buffer - auto ptr = new T(value); + auto ptr = std::make_unique(T{value}); auto cl = TClass::GetClass(typeid(value)); if (!cl) { state = GetState::kNOTCLASS; return; } - char* bufferptr = nullptr; + std::unique_ptr bufferptr(nullptr); TBufferFile buff(TBuffer::kWrite); - buff.WriteObjectAny(ptr, cl); + buff.WriteObjectAny(ptr.get(), cl); int N = buff.Length(); - bufferptr = new char[N]; - memcpy(bufferptr, buff.Buffer(), sizeof(char) * N); + bufferptr.reset(new char[N]); + memcpy(bufferptr.get(), buff.Buffer(), sizeof(char) * N); auto name = std::type_index(typeid(value)).name(); - mStore.insert(std::pair(key, SerializedInfo((void*)ptr, N, (char*)bufferptr, cl, name))); + mStore.insert(std::pair(key, SerializedInfo(N, std::move(bufferptr), cl, name))); } // implementation for put for trivial types @@ -184,13 +195,13 @@ class RootSerializableKeyValueStore // we forbid pointers static_assert(!std::is_pointer::value); // serialization of trivial types is easy (not based on ROOT) - auto ptr = new T(value); + auto ptr = std::make_unique(T{value}); int N = sizeof(T); - auto bufferptr = new char[N]; - memcpy(bufferptr, (char*)ptr, sizeof(char) * N); + std::unique_ptr bufferptr(new char[N]); + memcpy(bufferptr.get(), (char*)ptr.get(), sizeof(char) * N); auto name = std::type_index(typeid(value)).name(); - mStore.insert(std::pair(key, SerializedInfo((void*)ptr, N, (char*)bufferptr, nullptr, name))); + mStore.insert(std::pair(key, SerializedInfo(N, std::move(bufferptr), nullptr, name))); } // generic implementation for get relying on TClass From 44f6af346dff9656a6a3766a3ef2299e5a8f2735 Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Mon, 10 Jun 2024 18:28:30 +0200 Subject: [PATCH 0309/2997] [EMCAL-565, EMCAL-566] Keep start TS info in case of across-run calib. - The calibration objects for the bad and time calibration are stored in a root file at the end of run, and loaded at the start of the new run - Here, the timestamp was not propagated and as such, the timestamps in the ccdb were not covering the actual ranges of the corresponding data - This (rarely) leads to some seftover bad channels at the end of the run, or for short runs - Now, the timestamp is saved in the root-file with a granularity of seconds, and read in during the next run. - As the previous histograms did not contain the timestamp in seconds, a protection is implemented that, if the histogram only contains 3 bins, the start TS is neglected (This will only happen once!) --- .../EMCALCalibration/EMCALCalibParams.h | 1 + .../EMCALCalibration/EMCALChannelCalibrator.h | 64 ++++++++++++------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h index 2a13fb8ca569e..0de733dd953ab 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h @@ -88,6 +88,7 @@ struct EMCALCalibParams : public o2::conf::ConfigurableParamHelper::finalizeSlot(o2::calibration } } + // get the start timestamp of the slot. Either use the manually set start ts if available, or just the start time of the slot. + long tsStart = slot.getStartTimeMS(); + if (EMCALCalibParams::Instance().useStaticStartTimeSlot && slot.getStaticStartTimeMS() > 0) { + tsStart = slot.getStaticStartTimeMS(); + LOG(info) << "Adjusting the start TS of the slot from " << slot.getStartTimeMS() << " to " << slot.getStaticStartTimeMS(); + } + std::map md; if constexpr (std::is_same::value) { LOG(debug) << "Launching the calibration."; @@ -195,7 +202,7 @@ void EMCALChannelCalibrator::finalizeSlot(o2::calibration // for the CCDB entry auto clName = o2::utils::MemFileHelper::getClassName(bcm); auto flName = o2::ccdb::CcdbApi::generateFileName(clName); - mInfoVector.emplace_back(CalibDB::getCDBPathBadChannelMap(), clName, flName, md, slot.getStartTimeMS(), slot.getEndTimeMS() + EMCALCalibParams::Instance().endTimeMargin, true); + mInfoVector.emplace_back(CalibDB::getCDBPathBadChannelMap(), clName, flName, md, tsStart, slot.getEndTimeMS() + EMCALCalibParams::Instance().endTimeMargin, true); mCalibObjectVector.push_back(bcm); if ((EMCALCalibParams::Instance().localRootFilePath).find(".root") != std::string::npos) { @@ -205,15 +212,15 @@ void EMCALChannelCalibrator::finalizeSlot(o2::calibration fLocalStorage.cd(); TH2F* histBCMap = (TH2F*)bcm.getHistogramRepresentation(); - std::string nameBCHist = "BadChannels_" + std::to_string(slot.getStartTimeMS()); + std::string nameBCHist = "BadChannels_" + std::to_string(tsStart); histBCMap->Write(nameBCHist.c_str(), TObject::kOverwrite); TH2F hCalibHist = o2::utils::TH2FFromBoost(c->getHisto()); - std::string nameBCInputHist = "EnergyVsCellID_" + std::to_string(slot.getStartTimeMS()); + std::string nameBCInputHist = "EnergyVsCellID_" + std::to_string(tsStart); hCalibHist.Write(nameBCInputHist.c_str(), TObject::kOverwrite); TH2F hCalibHistTime = o2::utils::TH2FFromBoost(c->getHistoTime()); - std::string nameBCInputHistTime = "TimeVsCellID_" + std::to_string(slot.getStartTimeMS()); + std::string nameBCInputHistTime = "TimeVsCellID_" + std::to_string(tsStart); hCalibHistTime.Write(nameBCInputHistTime.c_str(), TObject::kOverwrite); fLocalStorage.Close(); @@ -226,7 +233,7 @@ void EMCALChannelCalibrator::finalizeSlot(o2::calibration auto flName = o2::ccdb::CcdbApi::generateFileName(clName); // prepareCCDBobjectInfo - mInfoVector.emplace_back(CalibDB::getCDBPathTimeCalibrationParams(), clName, flName, md, slot.getStartTimeMS(), slot.getEndTimeMS() + EMCALCalibParams::Instance().endTimeMargin, true); + mInfoVector.emplace_back(CalibDB::getCDBPathTimeCalibrationParams(), clName, flName, md, tsStart, slot.getEndTimeMS() + EMCALCalibParams::Instance().endTimeMargin, true); mCalibObjectVector.push_back(tcd); if ((EMCALCalibParams::Instance().localRootFilePath).find(".root") != std::string::npos) { @@ -235,15 +242,15 @@ void EMCALChannelCalibrator::finalizeSlot(o2::calibration TFile fLocalStorage((EMCALCalibParams::Instance().localRootFilePath).c_str(), ffile.good() == true ? "update" : "recreate"); fLocalStorage.cd(); TH1F* histTCparams = (TH1F*)tcd.getHistogramRepresentation(false); // high gain calibration - std::string nameTCHist = "TCParams_HG_" + std::to_string(slot.getStartTimeMS()); + std::string nameTCHist = "TCParams_HG_" + std::to_string(tsStart); histTCparams->Write(nameTCHist.c_str(), TObject::kOverwrite); TH1F* histTCparams_LG = (TH1F*)tcd.getHistogramRepresentation(true); // low gain calibration - std::string nameTCHist_LG = "TCParams_LG_" + std::to_string(slot.getStartTimeMS()); + std::string nameTCHist_LG = "TCParams_LG_" + std::to_string(tsStart); histTCparams_LG->Write(nameTCHist_LG.c_str(), TObject::kOverwrite); TH2F hCalibHist = o2::utils::TH2FFromBoost(c->getHisto()); - std::string nameTCInputHist = "TimeVsCellID_" + std::to_string(slot.getStartTimeMS()); + std::string nameTCInputHist = "TimeVsCellID_" + std::to_string(tsStart); hCalibHist.Write(nameTCInputHist.c_str(), TObject::kOverwrite); fLocalStorage.Close(); } @@ -270,8 +277,25 @@ bool EMCALChannelCalibrator::saveLastSlotData(TFile& fl) auto& slot = cont.at(0); DataInput* c = slot.getContainer(); - // timestamp in hours - int timeNow = static_cast(o2::ccdb::getCurrentTimestamp() / o2::ccdb::CcdbObjectInfo::HOUR); + // get the start timestamp of the slot. Either use the manually set start ts if available, or just the start time of the slot. + long tsStart = slot.getStartTimeMS(); + if (EMCALCalibParams::Instance().useStaticStartTimeSlot && slot.getStaticStartTimeMS() > 0) { + tsStart = slot.getStaticStartTimeMS(); + } + // timestamp in hours and seconds + int timeNowHour = static_cast(tsStart / o2::ccdb::CcdbObjectInfo::HOUR); + int timeNowSec = static_cast(tsStart / o2::ccdb::CcdbObjectInfo::SECOND); + + // create global event properties histogram. Same for both calibration types + TH1I hGlobalProperties("hGlobalProperties", "hGlobalProperties", 4, -0.5, 3.5); + hGlobalProperties.GetXaxis()->SetBinLabel(1, "Fill nr."); + hGlobalProperties.GetXaxis()->SetBinLabel(2, "run type"); + hGlobalProperties.GetXaxis()->SetBinLabel(3, "ts in hours"); + hGlobalProperties.GetXaxis()->SetBinLabel(4, "ts in seconds"); + hGlobalProperties.SetBinContent(1, mFillNr); + hGlobalProperties.SetBinContent(2, mRunType); + hGlobalProperties.SetBinContent(3, timeNowHour); + hGlobalProperties.SetBinContent(4, timeNowSec); if constexpr (std::is_same::value) { auto hist = c->getHisto(); @@ -281,31 +305,18 @@ bool EMCALChannelCalibrator::saveLastSlotData(TFile& fl) TH2F hTime = o2::utils::TH2FFromBoost(histTime, "histTime"); TH1D hNEvents("hNEvents", "hNEvents", 1, 0, 1); hNEvents.SetBinContent(1, c->getNEvents()); - TH1I hGlobalProperties("hGlobalProperties", "hGlobalProperties", 3, -0.5, 2.5); - hGlobalProperties.GetXaxis()->SetBinLabel(1, "Fill nr."); - hGlobalProperties.GetXaxis()->SetBinLabel(2, "run type"); - hGlobalProperties.GetXaxis()->SetBinLabel(3, "ts in hours"); - hGlobalProperties.SetBinContent(1, mFillNr); - hGlobalProperties.SetBinContent(2, mRunType); - hGlobalProperties.SetBinContent(3, timeNow); fl.cd(); hEnergy.Write("EnergyVsCellID"); hTime.Write("TimeVsCellID"); hNEvents.Write("NEvents"); hGlobalProperties.Write("GlobalProperties"); + } else if constexpr (std::is_same::value) { auto histTime = c->getHisto(); TH2F hTime = o2::utils::TH2FFromBoost(histTime); TH1D hNEvents("hNEvents", "hNEvents", 1, 0, 1); hNEvents.SetBinContent(1, c->getNEvents()); - TH1I hGlobalProperties("hGlobalProperties", "hGlobalProperties", 3, -0.5, 2.5); - hGlobalProperties.GetXaxis()->SetBinLabel(1, "Fill nr."); - hGlobalProperties.GetXaxis()->SetBinLabel(2, "run type"); - hGlobalProperties.GetXaxis()->SetBinLabel(3, "ts in hours"); - hGlobalProperties.SetBinContent(1, mFillNr); - hGlobalProperties.SetBinContent(2, mRunType); - hGlobalProperties.SetBinContent(3, timeNow); fl.cd(); hTime.Write("TimeVsCellID"); @@ -344,6 +355,7 @@ bool EMCALChannelCalibrator::adoptSavedData(const o2::cal int fillNr = hGlobalProperties->GetBinContent(1); int runType = hGlobalProperties->GetBinContent(2); int tsOld = hGlobalProperties->GetBinContent(3); + int tsOldSec = (hGlobalProperties->GetNbinsX() > 3) ? hGlobalProperties->GetBinContent(4) : 0; // Protection as 4th bin was only added later int tsDiff = (mStartTSCalib > 0 ? mStartTSCalib : static_cast(o2::ccdb::getCurrentTimestamp() / o2::ccdb::CcdbObjectInfo::HOUR)) - tsOld; // get current timestamp if mStartTSCalib is not set LOG(debug) << "tsOld " << tsOld << " tsNow " << (mStartTSCalib > 0 ? mStartTSCalib : static_cast(o2::ccdb::getCurrentTimestamp() / o2::ccdb::CcdbObjectInfo::HOUR)) << " tsDiff " << tsDiff; @@ -359,6 +371,10 @@ bool EMCALChannelCalibrator::adoptSavedData(const o2::cal LOG(info) << "adoptSavedData: Maximum difference in ts is: " << EMCALCalibParams::Instance().tsDiffMax << " but " << tsDiff << " is given"; return false; } + if (EMCALCalibParams::Instance().useStaticStartTimeSlot && tsOldSec > 0) { + slot.setStaticStartTimeMS(static_cast(tsOldSec * o2::ccdb::CcdbObjectInfo::SECOND)); + LOG(info) << "adoptSavedData: Setting the start timestamp to " << static_cast(tsOldSec * o2::ccdb::CcdbObjectInfo::SECOND); + } } if constexpr (std::is_same::value) { From 9e0af1b305cfa710a2c15dc93bd855180fc528cb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 12 Jun 2024 08:44:08 +0200 Subject: [PATCH 0310/2997] DPL Analysis: provide dpl-metadata-tables ArrayString of tables in the first AOD to be read. --- Framework/AnalysisSupport/src/Plugin.cxx | 24 +++++++++++++++++++ .../TestWorkflows/src/o2TestHistograms.cxx | 13 +++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Framework/AnalysisSupport/src/Plugin.cxx b/Framework/AnalysisSupport/src/Plugin.cxx index e5197e6977835..baa1b36dd41a5 100644 --- a/Framework/AnalysisSupport/src/Plugin.cxx +++ b/Framework/AnalysisSupport/src/Plugin.cxx @@ -65,6 +65,25 @@ struct RunSummary : o2::framework::ServicePlugin { } }; +std::vector getListOfTables(TFile* f) +{ + std::vector r; + TList* keyList = f->GetListOfKeys(); + + for (auto key : *keyList) { + if (!std::string_view(key->GetName()).starts_with("DF_")) { + continue; + } + auto* d = (TDirectory*)f->Get(key->GetName()); + TList* branchList = d->GetListOfKeys(); + for (auto b : *branchList) { + r.emplace_back(b->GetName()); + } + break; + } + return r; +} + struct DiscoverMetadataInAOD : o2::framework::ConfigDiscoveryPlugin { ConfigDiscovery* create() override { @@ -118,6 +137,11 @@ struct DiscoverMetadataInAOD : o2::framework::ConfigDiscoveryPlugin { char const* value = strdup(objString->String()); results.push_back(ConfigParamSpec{key, VariantType::String, value, {"Metadata in AOD"}}); } + + auto tables = getListOfTables(currentFile); + if (tables.empty() == false) { + results.push_back(ConfigParamSpec{"aod-metadata-tables", VariantType::ArrayString, tables, {"Tables in first AOD"}}); + } return results; }}; } diff --git a/Framework/TestWorkflows/src/o2TestHistograms.cxx b/Framework/TestWorkflows/src/o2TestHistograms.cxx index 4dbea06d03679..15e7e5235837c 100644 --- a/Framework/TestWorkflows/src/o2TestHistograms.cxx +++ b/Framework/TestWorkflows/src/o2TestHistograms.cxx @@ -49,12 +49,23 @@ struct EtaAndClsHistogramsFull { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { std::string runType = "3"; + std::vector tables; if (cfgc.options().hasOption("aod-metadata-Run")) { runType = cfgc.options().get("aod-metadata-Run"); } + if (cfgc.options().hasOption("aod-metadata-tables")) { + tables = cfgc.options().get>("aod-metadata-tables"); + } LOGP(info, "Runtype is {}", runType); + bool hasTrackCov = false; + for (auto& table : tables) { + if (table.starts_with("O2trackcov")) { + hasTrackCov = true; + } + LOGP(info, "- {} present.", table); + } // Notice it's important for the tasks to use the same name, otherwise topology generation will be confused. - if (runType == "2") { + if (runType == "2" || !hasTrackCov) { LOGP(info, "Using only tracks {}", runType); return WorkflowSpec{ adaptAnalysisTask(cfgc, TaskName{"simple-histos"}), From db59272402b55902036907fdaa7cc9ee9bb8cb52 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli Date: Wed, 12 Jun 2024 22:50:01 +0200 Subject: [PATCH 0311/2997] Adding K0s Qc to GLO matching QC, and move to a different location (#13144) * Adding K0s Qc to GLO matching QC, and move to a different location * To make it compile with QC master, without my changes * First round of comments * Possibility to specify the track sources --- Detectors/CMakeLists.txt | 1 + Detectors/GLOQC/CMakeLists.txt | 26 + .../include/GLOQC/ITSTPCMatchingQCParams.h | 42 + Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h | 405 ++++++ Detectors/GLOQC/src/GLOQCLinkDef.h | 21 + .../GLOQC/src/ITSTPCMatchingQCParams.cxx | 16 + Detectors/GLOQC/src/MatchITSTPCQC.cxx | 1228 +++++++++++++++++ Detectors/GlobalTracking/CMakeLists.txt | 10 +- .../src/GlobalTrackingLinkDef.h | 4 +- .../GlobalTrackingWorkflow/CMakeLists.txt | 1 + .../GlobalTrackingWorkflow/qc/CMakeLists.txt | 3 +- .../ITSTPCMatchingQCSpec.h | 10 +- .../qc/src/ITSTPCMatchingQCSpec.cxx | 48 +- .../qc/src/itstpc-matching-qc-workflow.cxx | 10 +- 14 files changed, 1797 insertions(+), 28 deletions(-) create mode 100644 Detectors/GLOQC/CMakeLists.txt create mode 100644 Detectors/GLOQC/include/GLOQC/ITSTPCMatchingQCParams.h create mode 100644 Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h create mode 100644 Detectors/GLOQC/src/GLOQCLinkDef.h create mode 100644 Detectors/GLOQC/src/ITSTPCMatchingQCParams.cxx create mode 100644 Detectors/GLOQC/src/MatchITSTPCQC.cxx diff --git a/Detectors/CMakeLists.txt b/Detectors/CMakeLists.txt index a7cbccc7f0be8..eef692ff18ca7 100644 --- a/Detectors/CMakeLists.txt +++ b/Detectors/CMakeLists.txt @@ -36,6 +36,7 @@ add_subdirectory(FOCAL) add_subdirectory(GlobalTracking) add_subdirectory(GlobalTrackingWorkflow) add_subdirectory(Vertexing) +add_subdirectory(GLOQC) if(BUILD_ANALYSIS) add_subdirectory(AOD) diff --git a/Detectors/GLOQC/CMakeLists.txt b/Detectors/GLOQC/CMakeLists.txt new file mode 100644 index 0000000000000..cdb307a6515c8 --- /dev/null +++ b/Detectors/GLOQC/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. +# add_compile_options(-O0 -g -fPIC) + +o2_add_library(GLOQC + TARGETVARNAME targetName + SOURCES src/MatchITSTPCQC.cxx + src/ITSTPCMatchingQCParams.cxx + + PUBLIC_LINK_LIBRARIES O2::DetectorsVertexing) + +o2_target_root_dictionary(GLOQC + HEADERS include/GLOQC/MatchITSTPCQC.h + include/GLOQC/ITSTPCMatchingQCParams.h + +) + + diff --git a/Detectors/GLOQC/include/GLOQC/ITSTPCMatchingQCParams.h b/Detectors/GLOQC/include/GLOQC/ITSTPCMatchingQCParams.h new file mode 100644 index 0000000000000..001996feb4c69 --- /dev/null +++ b/Detectors/GLOQC/include/GLOQC/ITSTPCMatchingQCParams.h @@ -0,0 +1,42 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \author Chiara.Zampolli@cern.ch + +#ifndef ALICEO2_ITSTPCMATCHINGQC_PARAMS_H +#define ALICEO2_ITSTPCMATCHINGQC_PARAMS_H + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2 +{ +namespace gloqc +{ + +// There are configurable params for TPC-ITS matching +struct ITSTPCMatchingQCParams : public o2::conf::ConfigurableParamHelper { + + float minPtCut = 0.1f; + float etaCut = 1.4f; + int32_t minNTPCClustersCut = 60; + float minDCACut = 100.f; + float minDCACutY = 10.f; + float cutK0Mass = 0.05f; + float maxEtaK0 = 0.8f; + + O2ParamDef(ITSTPCMatchingQCParams, "ITSTPCMatchingQC"); +}; + +} // namespace gloqc +} // end namespace o2 + +#endif diff --git a/Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h b/Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h new file mode 100644 index 0000000000000..ca4d2678722c6 --- /dev/null +++ b/Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h @@ -0,0 +1,405 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MatchITSTPCQC.h +/// \brief Class to perform QC for ITSTPC matching +/// \author chiara.zampolli@cern.ch + +#ifndef ALICEO2_GLOQC_MATCHITSTPC_QC_ +#define ALICEO2_GLOQC_MATCHITSTPC_QC_ + +#include +#include +#include +#include +#include +#include "DataFormatsGlobalTracking/RecoContainer.h" +#include "Framework/ProcessingContext.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/MCTrack.h" +#include "Steer/MCKinematicsReader.h" +#include "ReconstructionDataFormats/PID.h" +#include "DCAFitter/DCAFitterN.h" +#include +#include +#include +#include + +namespace o2 +{ + +namespace gloqc +{ + +using GID = o2::dataformats::GlobalTrackID; + +struct LblInfo { + + int mIdx = -1; + bool mIsPhysicalPrimary = false; +}; + +class MatchITSTPCQC +{ + public: + enum matchType : int { TPC = 0, + ITS, + SIZE }; + + MatchITSTPCQC() = default; + ~MatchITSTPCQC(); + + bool init(); + void initDataRequest(); + void run(o2::framework::ProcessingContext& ctx); + void setDataRequest(const std::shared_ptr& dr) { mDataRequest = dr; } + void finalize(); + void reset(); + bool processV0(int iv, o2::globaltracking::RecoContainer& recoData); + bool refitV0(const o2::dataformats::V0Index& id, o2::dataformats::V0& v0, o2::globaltracking::RecoContainer& recoData); + + TH1D* getHistoPtNum(matchType m) const { return mPtNum[m]; } + TH1D* getHistoPtDen(matchType m) const { return mPtDen[m]; } + TEfficiency* getFractionITSTPCmatch(matchType m) const { return mFractionITSTPCmatch[m]; } + + TH1D* getHistoPtNumNoEta0(matchType m) const { return mPtNum_noEta0[m]; } + TH1D* getHistoPtDenNoEta0(matchType m) const { return mPtDen_noEta0[m]; } + TEfficiency* getFractionITSTPCmatchNoEta0(matchType m) const { return mFractionITSTPCmatch_noEta0[m]; } + + TH1F* getHistoPhiNum(matchType m) const { return mPhiNum[m]; } + TH1F* getHistoPhiDen(matchType m) const { return mPhiDen[m]; } + TEfficiency* getFractionITSTPCmatchPhi(matchType m) const { return mFractionITSTPCmatchPhi[m]; } + + TH2F* getHistoPhiVsPtNum(matchType m) const { return mPhiVsPtNum[m]; } + TH2F* getHistoPhiVsPtDen(matchType m) const { return mPhiVsPtDen[m]; } + TEfficiency* getFractionITSTPCmatchPhiVsPt(matchType m) const { return mFractionITSTPCmatchPhiVsPt[m]; } + + TH1F* getHistoEtaNum(matchType m) const { return mEtaNum[m]; } + TH1F* getHistoEtaDen(matchType m) const { return mEtaDen[m]; } + TEfficiency* getFractionITSTPCmatchEta(matchType m) const { return mFractionITSTPCmatchEta[m]; } + + TH2F* getHistoEtaVsPtNum(matchType m) const { return mEtaVsPtNum[m]; } + TH2F* getHistoEtaVsPtDen(matchType m) const { return mEtaVsPtDen[m]; } + TEfficiency* getFractionITSTPCmatchEtaVsPt(matchType m) const { return mFractionITSTPCmatchEtaVsPt[m]; } + + TH2F* getHistoClsVsPtNum(matchType m) const { return mClsVsPtNum[m]; } + TH2F* getHistoClsVsPtDen(matchType m) const { return mClsVsPtDen[m]; } + TEfficiency* getFractionITSTPCmatchClsVsPt(matchType m) const { return mFractionITSTPCmatchClsVsPt[m]; } + + TH2F* getHistoChi2VsPtNum(matchType m) const { return mChi2VsPtNum[m]; } + TH2F* getHistoChi2VsPtDen(matchType m) const { return mChi2VsPtDen[m]; } + TEfficiency* getFractionITSTPCmatchChi2VsPt(matchType m) const { return mFractionITSTPCmatchChi2VsPt[m]; } + + TH1F* getHistoPtPhysPrimNum(matchType m) const { return mPtPhysPrimNum[m]; } + TH1F* getHistoPtPhysPrimDen(matchType m) const { return mPtPhysPrimDen[m]; } + TEfficiency* getFractionITSTPCmatchPhysPrim(matchType m) const { return mFractionITSTPCmatchPhysPrim[m]; } + + TH1F* getHistoPhiPhysPrimNum(matchType m) const { return mPhiPhysPrimNum[m]; } + TH1F* getHistoPhiPhysPrimDen(matchType m) const { return mPhiPhysPrimDen[m]; } + TEfficiency* getFractionITSTPCmatchPhiPhysPrim(matchType m) const { return mFractionITSTPCmatchPhiPhysPrim[m]; } + + TH1F* getHistoEtaPhysPrimNum(matchType m) const { return mEtaPhysPrimNum[m]; } + TH1F* getHistoEtaPhysPrimDen(matchType m) const { return mEtaPhysPrimDen[m]; } + TEfficiency* getFractionITSTPCmatchEtaPhysPrim(matchType m) const { return mFractionITSTPCmatchEtaPhysPrim[m]; } + + TH2F* getHistoResidualPt() const { return mResidualPt; } + TH2F* getHistoResidualPhi() const { return mResidualPhi; } + TH2F* getHistoResidualEta() const { return mResidualEta; } + + TH1F* getHistoChi2Matching() const { return mChi2Matching; } + TH1F* getHistoChi2Refit() const { return mChi2Refit; } + TH2F* getHistoTimeResVsPt() const { return mTimeResVsPt; } + TH1F* getHistoDCAr() const { return mDCAr; } + TH2F* getHistoDCArVsPtNum() const { return mDCArVsPtNum; } + TH2F* getHistoDCArVsPtDen() const { return mDCArVsPtDen; } + TEfficiency* getFractionITSTPCmatchDCArVsPt() const { return mFractionITSTPCmatchDCArVsPt; } + + TH1D* getHisto1OverPtNum(matchType m) const { return m1OverPtNum[m]; } + TH1D* getHisto1OverPtDen(matchType m) const { return m1OverPtDen[m]; } + TEfficiency* getFractionITSTPCmatch1OverPt(matchType m) const { return mFractionITSTPCmatch1OverPt[m]; } + + TH1D* getHisto1OverPtPhysPrimNum(matchType m) const { return m1OverPtPhysPrimNum[m]; } + TH1D* getHisto1OverPtPhysPrimDen(matchType m) const { return m1OverPtPhysPrimDen[m]; } + TEfficiency* getFractionITSTPCmatchPhysPrim1OverPt(matchType m) const { return mFractionITSTPCmatchPhysPrim1OverPt[m]; } + + TH2F* getHistoK0MassVsPt() const { return mK0MassVsPt; } + + void getHistos(TObjArray& objar); + + /// \brief Publishes the histograms to the publisher e.g. the one provided by the QC task + /// \tparam T type of the publisher + /// \param publisher the publisher e.g. getObjectsManager() + template + void publishHistograms(const std::shared_ptr& publisher) + { + for (int i = 0; i < matchType::SIZE; ++i) { + // Pt + publisher->startPublishing(mPtNum[i]); + publisher->startPublishing(mPtDen[i]); + publisher->startPublishing(mFractionITSTPCmatch[i]); + + publisher->startPublishing(mPtNum_noEta0[i]); + publisher->startPublishing(mPtDen_noEta0[i]); + publisher->startPublishing(mFractionITSTPCmatch_noEta0[i]); + + // Phi + publisher->startPublishing(mPhiNum[i]); + publisher->startPublishing(mPhiDen[i]); + publisher->startPublishing(mFractionITSTPCmatchPhi[i]); + + publisher->startPublishing(mPhiVsPtNum[i]); + publisher->startPublishing(mPhiVsPtDen[i]); + publisher->startPublishing(mFractionITSTPCmatchPhiVsPt[i]); + + // Eta + publisher->startPublishing(mEtaNum[i]); + publisher->startPublishing(mEtaDen[i]); + publisher->startPublishing(mFractionITSTPCmatchEta[i]); + + publisher->startPublishing(mEtaVsPtNum[i]); + publisher->startPublishing(mEtaVsPtDen[i]); + publisher->startPublishing(mFractionITSTPCmatchEtaVsPt[i]); + + // Clusters + publisher->startPublishing(mClsVsPtNum[i]); + publisher->startPublishing(mClsVsPtDen[i]); + publisher->startPublishing(mFractionITSTPCmatchClsVsPt[i]); + + // Chi2 + publisher->startPublishing(mChi2VsPtNum[i]); + publisher->startPublishing(mChi2VsPtDen[i]); + publisher->startPublishing(mFractionITSTPCmatchChi2VsPt[i]); + + // 1/pt + publisher->startPublishing(m1OverPtNum[i]); + publisher->startPublishing(m1OverPtDen[i]); + publisher->startPublishing(mFractionITSTPCmatch1OverPt[i]); + + if (mUseTrkPID) { // Vs Tracking PID hypothesis + for (int j = 0; j < o2::track::PID::NIDs; ++j) { + // Pt + publisher->startPublishing(mPtNumVsTrkPID[i][j]); + publisher->startPublishing(mPtDenVsTrkPID[i][j]); + publisher->startPublishing(mFractionITSTPCmatchPtVsTrkPID[i][j]); + + // Phi + publisher->startPublishing(mPhiNumVsTrkPID[i][j]); + publisher->startPublishing(mPhiDenVsTrkPID[i][j]); + publisher->startPublishing(mFractionITSTPCmatchPhiVsTrkPID[i][j]); + + // Eta + publisher->startPublishing(mEtaNumVsTrkPID[i][j]); + publisher->startPublishing(mEtaDenVsTrkPID[i][j]); + publisher->startPublishing(mFractionITSTPCmatchEtaVsTrkPID[i][j]); + } + } + + if (mUseMC) { + publisher->startPublishing(mPhiPhysPrimNum[i]); + publisher->startPublishing(mPhiPhysPrimDen[i]); + publisher->startPublishing(mFractionITSTPCmatchPhiPhysPrim[i]); + publisher->startPublishing(mPtPhysPrimNum[i]); + publisher->startPublishing(mPtPhysPrimDen[i]); + publisher->startPublishing(mFractionITSTPCmatchPhysPrim[i]); + publisher->startPublishing(mEtaPhysPrimNum[i]); + publisher->startPublishing(mEtaPhysPrimDen[i]); + publisher->startPublishing(mFractionITSTPCmatchEtaPhysPrim[i]); + publisher->startPublishing(m1OverPtPhysPrimNum[i]); + publisher->startPublishing(m1OverPtPhysPrimDen[i]); + publisher->startPublishing(mFractionITSTPCmatchPhysPrim1OverPt[i]); + } + } + publisher->startPublishing(mChi2Matching); + publisher->startPublishing(mChi2Refit); + publisher->startPublishing(mTimeResVsPt); + publisher->startPublishing(mResidualPt); + publisher->startPublishing(mResidualPhi); + publisher->startPublishing(mResidualEta); + publisher->startPublishing(mDCAr); + publisher->startPublishing(mDCArVsPtNum); + publisher->startPublishing(mDCArVsPtDen); + publisher->startPublishing(mFractionITSTPCmatchDCArVsPt); + if (mDoK0QC) { + publisher->startPublishing(mK0MassVsPt); + } + } + + void setTrkSources(GID::mask_t src) { mSrc = src; } + void setUseTrkPID(bool b) { mUseTrkPID = b; } + bool getUseTrkPID() const { return mUseTrkPID; } + void setUseMC(bool b) { mUseMC = b; } + bool getUseMC() const { return mUseMC; } + void deleteHistograms(); + void setBz(float bz) { mBz = bz; } + void setDoK0QC(bool v) { mDoK0QC = v; } + bool getDoK0QC() const { return mDoK0QC; } + + // ITS track + void setMinPtITSCut(float v) { mPtITSCut = v; }; + void setEtaITSCut(float v) { mEtaITSCut = v; }; // TODO: define 2 different values for min and max (**) + void setMinNClustersITS(float v) { mMinNClustersITS = v; } + void setMaxChi2PerClusterITS(float v) { mMaxChi2PerClusterITS = v; } + // TO DO: define an agreed way to implement the setter for ITS matching (min. # layers, which layers) + // [...] --> exploit the method TrackCuts::setRequireHitsInITSLayers(...) + // TPC track + void setMinPtTPCCut(float v) { mPtTPCCut = v; }; + void setEtaTPCCut(float v) { mEtaTPCCut = v; }; // TODO: define 2 different values for min and max (***) + void setMinNTPCClustersCut(float v) { mNTPCClustersCut = v; } + void setMinDCAtoBeamPipeCut(std::array v) + { + setMinDCAtoBeamPipeDistanceCut(v[0]); + setMinDCAtoBeamPipeYCut(v[1]); + } + void setMinDCAtoBeamPipeDistanceCut(float v) { mDCATPCCut = v; } + void setMinDCAtoBeamPipeYCut(float v) { mDCATPCCutY = v; } + // ITS-TPC kinematics + void setPtCut(float v) { mPtCut = v; } + void setMaxPtCut(float v) { mPtMaxCut = v; } + void setEtaCut(float v) { mEtaCut = v; } // TODO: define 2 different values for min and max (*) + + // K0 + void setMaxK0Eta(float v) { mMaxEtaK0 = v; } + void setRefitK0(bool v) { mRefit = v; } + void setCutK0Mass(bool v) { mCutK0Mass = v; } + + private: + std::shared_ptr mDataRequest; + o2::globaltracking::RecoContainer mRecoCont; + std::string mRequestedSources = "ITS,TPC,ITS-TPC"; + GID::mask_t mSrc = GID::getSourcesMask("ITS,TPC,ITS-TPC"); + GID::mask_t mAllowedSources = GID::getSourcesMask("all"); + // TPC + gsl::span mTPCTracks; + // ITS + gsl::span mITSTracks; + // ITS-TPC + gsl::span mITSTPCTracks; + bool mUseMC = false; // Usage of the MC information + bool mUseTrkPID = false; // Usage of the PID hypothesis in tracking + float mBz = 0; ///< nominal Bz + std::array, matchType::SIZE> mMapLabels; // map with labels that have been found for the matched ITSTPC tracks; key is the label, + // value is the LbLinfo with the id of the track with the highest pT found with that label so far, + // and the flag to say if it is a physical primary or not + std::array, matchType::SIZE> mMapRefLabels; // map with labels that have been found for the unmatched TPC tracks; key is the label, + // value is the LblInfo with the id of the track with the highest number of TPC clusters found + // with that label so far, and the flag to say if it is a physical primary or not + o2::steer::MCKinematicsReader mcReader; // reader of MC information + + // Pt + TH1D* mPtNum[matchType::SIZE] = {}; + TH1D* mPtDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatch[matchType::SIZE] = {}; + TH1D* mPtNum_noEta0[matchType::SIZE] = {}; + TH1D* mPtDen_noEta0[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatch_noEta0[matchType::SIZE] = {}; + TH1F* mPtPhysPrimNum[matchType::SIZE] = {}; + TH1F* mPtPhysPrimDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchPhysPrim[matchType::SIZE] = {}; + // Pt split per PID hypothesis in tracking + TH1D* mPtNumVsTrkPID[matchType::SIZE][track::PID::NIDs] = {}; + TH1D* mPtDenVsTrkPID[matchType::SIZE][track::PID::NIDs] = {}; + TEfficiency* mFractionITSTPCmatchPtVsTrkPID[matchType::SIZE][track::PID::NIDs] = {}; + // Phi + TH1F* mPhiNum[matchType::SIZE] = {}; + TH1F* mPhiDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchPhi[matchType::SIZE] = {}; + TH1F* mPhiPhysPrimNum[matchType::SIZE] = {}; + TH1F* mPhiPhysPrimDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchPhiPhysPrim[matchType::SIZE] = {}; + TH2F* mPhiVsPtNum[matchType::SIZE] = {}; + TH2F* mPhiVsPtDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchPhiVsPt[matchType::SIZE] = {}; + // Phi split per PID hypothesis in tracking + TH1D* mPhiNumVsTrkPID[matchType::SIZE][track::PID::NIDs] = {}; + TH1D* mPhiDenVsTrkPID[matchType::SIZE][track::PID::NIDs] = {}; + TEfficiency* mFractionITSTPCmatchPhiVsTrkPID[matchType::SIZE][track::PID::NIDs] = {}; + // Eta + TH1F* mEtaNum[matchType::SIZE] = {}; + TH1F* mEtaDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchEta[matchType::SIZE] = {}; + TH1F* mEtaPhysPrimNum[matchType::SIZE] = {}; + TH1F* mEtaPhysPrimDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchEtaPhysPrim[matchType::SIZE] = {}; + TH2F* mEtaVsPtNum[matchType::SIZE] = {}; + TH2F* mEtaVsPtDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchEtaVsPt[matchType::SIZE] = {}; + // Clusters + TH2F* mClsVsPtNum[matchType::SIZE] = {}; + TH2F* mClsVsPtDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchClsVsPt[matchType::SIZE] = {}; + // Chi2 + TH2F* mChi2VsPtNum[matchType::SIZE] = {}; + TH2F* mChi2VsPtDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchChi2VsPt[matchType::SIZE] = {}; + // Eta split per PID hypothesis in tracking + TH1D* mEtaNumVsTrkPID[matchType::SIZE][track::PID::NIDs] = {}; + TH1D* mEtaDenVsTrkPID[matchType::SIZE][track::PID::NIDs] = {}; + TEfficiency* mFractionITSTPCmatchEtaVsTrkPID[matchType::SIZE][track::PID::NIDs] = {}; + // Residuals + TH2F* mResidualPt = nullptr; + TH2F* mResidualPhi = nullptr; + TH2F* mResidualEta = nullptr; + // Others + TH1F* mChi2Matching = nullptr; + TH1F* mChi2Refit = nullptr; + TH2F* mTimeResVsPt = nullptr; + TH1F* mDCAr = nullptr; + TH2F* mDCArVsPtNum = nullptr; + TH2F* mDCArVsPtDen = nullptr; + TEfficiency* mFractionITSTPCmatchDCArVsPt = nullptr; + // 1/Pt + TH1D* m1OverPtNum[matchType::SIZE] = {}; + TH1D* m1OverPtDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatch1OverPt[matchType::SIZE] = {}; + TH1D* m1OverPtPhysPrimNum[matchType::SIZE] = {}; + TH1D* m1OverPtPhysPrimDen[matchType::SIZE] = {}; + TEfficiency* mFractionITSTPCmatchPhysPrim1OverPt[matchType::SIZE] = {}; + + void setEfficiency(TEfficiency* eff, TH1* hnum, TH1* hden, bool is2D = false); + + int mNTPCSelectedTracks = 0; + int mNITSSelectedTracks = 0; + int mNITSTPCSelectedTracks[matchType::SIZE] = {0, 0}; + + // cut values + // ITS track + float mPtITSCut = 0.f; // min pT for ITS track + float mEtaITSCut = 1e10f; // eta window for ITS track --> TODO: define 2 different values for min and max (**) + int mMinNClustersITS = 0; // min number of ITS clusters + float mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster + std::vector>> mRequiredITSHits{}; // vector of ITS requirements (minNRequiredHits in specific requiredLayers) + // TPC track + float mPtTPCCut = 0.1f; // min pT for TPC track + float mEtaTPCCut = 1.4f; // eta window for TPC track --> TODO: define 2 different values for min and max (***) + int32_t mNTPCClustersCut = 60; // minimum number of TPC clusters for TPC track + float mDCATPCCut = 100.f; // max DCA 3D to PV for TPC track + float mDCATPCCutY = 10.f; // max DCA xy to PV for TPC track + // ITS-TPC kinematics + float mPtCut = 0.1f; + float mPtMaxCut = 1e10f; + float mEtaCut = 1e10f; // 1e10f as defaults of Detectors/GlobalTracking/include/GlobalTracking/TrackCuts.h + // TODO: define 2 different values for min and max (*) + + // for V0s + o2::vertexing::DCAFitterN<2> mFitterV0; + TH2F* mK0MassVsPt = nullptr; + bool mDoK0QC = false; // whether to fill the K0 QC plot(s) + float mCutK0Mass = 0.05; // cut on the difference between the K0 mass and the PDG mass + bool mRefit = false; // whether to refit or not + float mMaxEtaK0 = 0.8; // cut on the K0 eta + long int mTimestamp = -1; // timestamp used to load the SVertexParam object: if differnt from -1, we don't load (it means we already did it) + + ClassDefNV(MatchITSTPCQC, 3); +}; +} // namespace gloqc +} // namespace o2 + +#endif diff --git a/Detectors/GLOQC/src/GLOQCLinkDef.h b/Detectors/GLOQC/src/GLOQCLinkDef.h new file mode 100644 index 0000000000000..f7092a4394d08 --- /dev/null +++ b/Detectors/GLOQC/src/GLOQCLinkDef.h @@ -0,0 +1,21 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::gloqc::ITSTPCMatchingQCParams> + ; +#pragma link C++ class o2::gloqc::ITSTPCMatchingQCParams + ; + +#endif diff --git a/Detectors/GLOQC/src/ITSTPCMatchingQCParams.cxx b/Detectors/GLOQC/src/ITSTPCMatchingQCParams.cxx new file mode 100644 index 0000000000000..b5c9f6842dfc3 --- /dev/null +++ b/Detectors/GLOQC/src/ITSTPCMatchingQCParams.cxx @@ -0,0 +1,16 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file ITSTPCMatchingQCParams.h +/// \brief Configurable params for ITSTPC matching QC + +#include "GLOQC/ITSTPCMatchingQCParams.h" +O2ParamImpl(o2::gloqc::ITSTPCMatchingQCParams); diff --git a/Detectors/GLOQC/src/MatchITSTPCQC.cxx b/Detectors/GLOQC/src/MatchITSTPCQC.cxx new file mode 100644 index 0000000000000..f810a5d2d4ef2 --- /dev/null +++ b/Detectors/GLOQC/src/MatchITSTPCQC.cxx @@ -0,0 +1,1228 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "GLOQC/MatchITSTPCQC.h" +#include "ReconstructionDataFormats/TrackTPCITS.h" +#include "DataFormatsTPC/TrackTPC.h" +#include "Framework/InputSpec.h" +#include "ReconstructionDataFormats/TrackParametrization.h" +#include "DetectorsBase/Propagator.h" +#include "SimulationDataFormat/MCUtils.h" +#include +#include "TGraphAsymmErrors.h" +#include "GlobalTracking/TrackCuts.h" +#include +#include "ReconstructionDataFormats/PrimaryVertex.h" +#include "ReconstructionDataFormats/V0.h" +// #include "GlobalTrackingStudy/V0Ext.h" +#include "DetectorsVertexing/SVertexerParams.h" +#include "Framework/InputRecord.h" +#include "Framework/TimingInfo.h" + +using namespace o2::gloqc; +using namespace o2::mcutils; +using MCTrack = o2::MCTrackT; + +MatchITSTPCQC::~MatchITSTPCQC() +{ + + deleteHistograms(); +} + +//_______________________________________________________ + +void MatchITSTPCQC::deleteHistograms() +{ + + for (int i = 0; i < matchType::SIZE; ++i) { + // Pt + delete mPtNum[i]; + delete mPtDen[i]; + delete mFractionITSTPCmatch[i]; + delete mPtNum_noEta0[i]; + delete mPtDen_noEta0[i]; + delete mFractionITSTPCmatch_noEta0[i]; + delete mPtPhysPrimNum[i]; + delete mPtPhysPrimDen[i]; + delete mFractionITSTPCmatchPhysPrim[i]; + + // Phi + delete mPhiNum[i]; + delete mPhiDen[i]; + delete mFractionITSTPCmatchPhi[i]; + delete mPhiPhysPrimNum[i]; + delete mPhiPhysPrimDen[i]; + delete mFractionITSTPCmatchPhiPhysPrim[i]; + delete mPhiVsPtNum[i]; + delete mPhiVsPtDen[i]; + delete mFractionITSTPCmatchPhiVsPt[i]; + + // Eta + delete mEtaNum[i]; + delete mEtaDen[i]; + delete mFractionITSTPCmatchEta[i]; + delete mEtaPhysPrimNum[i]; + delete mEtaPhysPrimDen[i]; + delete mFractionITSTPCmatchEtaPhysPrim[i]; + delete mEtaVsPtNum[i]; + delete mEtaVsPtDen[i]; + delete mFractionITSTPCmatchEtaVsPt[i]; + + // Clusters + delete mClsVsPtNum[i]; + delete mClsVsPtDen[i]; + delete mFractionITSTPCmatchClsVsPt[i]; + + // Chi2 + delete mChi2VsPtNum[i]; + delete mChi2VsPtDen[i]; + delete mFractionITSTPCmatchChi2VsPt[i]; + + for (int j = 0; j < o2::track::PID::NIDs; ++j) { + // Pt + delete mPtNumVsTrkPID[i][j]; + delete mPtDenVsTrkPID[i][j]; + delete mFractionITSTPCmatchPtVsTrkPID[i][j]; + // Phi + delete mPhiNumVsTrkPID[i][j]; + delete mPhiDenVsTrkPID[i][j]; + delete mFractionITSTPCmatchPhiVsTrkPID[i][j]; + // Eta + delete mEtaNumVsTrkPID[i][j]; + delete mEtaDenVsTrkPID[i][j]; + delete mFractionITSTPCmatchEtaVsTrkPID[i][j]; + } + + // 1/Pt + delete m1OverPtNum[i]; + delete m1OverPtDen[i]; + delete mFractionITSTPCmatch1OverPt[i]; + delete m1OverPtPhysPrimNum[i]; + delete m1OverPtPhysPrimDen[i]; + delete mFractionITSTPCmatchPhysPrim1OverPt[i]; + } + + // Residuals + delete mResidualPt; + delete mResidualPhi; + delete mResidualEta; + // Others + delete mChi2Matching; + delete mChi2Refit; + delete mTimeResVsPt; + delete mDCAr; + delete mDCArVsPtNum; + delete mDCArVsPtDen; + delete mFractionITSTPCmatchDCArVsPt; + + // K0 + delete mK0MassVsPt; +} + +//__________________________________________________________ + +void MatchITSTPCQC::reset() +{ + for (int i = 0; i < matchType::SIZE; ++i) { + // Pt + mPtNum[i]->Reset(); + mPtDen[i]->Reset(); + mPtNum_noEta0[i]->Reset(); + mPtDen_noEta0[i]->Reset(); + + // Phi + mPhiNum[i]->Reset(); + mPhiDen[i]->Reset(); + mPhiVsPtNum[i]->Reset(); + mPhiVsPtDen[i]->Reset(); + + // Eta + mEtaNum[i]->Reset(); + mEtaDen[i]->Reset(); + mEtaVsPtNum[i]->Reset(); + mEtaVsPtDen[i]->Reset(); + + // Clusters + mClsVsPtNum[i]->Reset(); + mClsVsPtDen[i]->Reset(); + + // Chi2 + mChi2VsPtNum[i]->Reset(); + mChi2VsPtDen[i]->Reset(); + + // 1/Pt + m1OverPtNum[i]->Reset(); + m1OverPtDen[i]->Reset(); + + if (mUseTrkPID) { // Vs Tracking PID hypothesis + for (int j = 0; j < o2::track::PID::NIDs; ++j) { + // Pt + mPtNumVsTrkPID[i][j]->Reset(); + mPtDenVsTrkPID[i][j]->Reset(); + // Phi + mPhiNumVsTrkPID[i][j]->Reset(); + mPhiDenVsTrkPID[i][j]->Reset(); + // Eta + mEtaNumVsTrkPID[i][j]->Reset(); + mEtaDenVsTrkPID[i][j]->Reset(); + } + } + + if (mUseMC) { + mPtPhysPrimNum[i]->Reset(); + mPtPhysPrimDen[i]->Reset(); + + mPhiPhysPrimNum[i]->Reset(); + mPhiPhysPrimDen[i]->Reset(); + + mEtaPhysPrimNum[i]->Reset(); + mEtaPhysPrimDen[i]->Reset(); + + m1OverPtPhysPrimNum[i]->Reset(); + m1OverPtPhysPrimDen[i]->Reset(); + } + } + + // Residuals + mResidualPt->Reset(); + mResidualPhi->Reset(); + mResidualEta->Reset(); + // Others + mChi2Matching->Reset(); + mChi2Refit->Reset(); + mTimeResVsPt->Reset(); + mDCAr->Reset(); + mDCArVsPtNum->Reset(); + mDCArVsPtDen->Reset(); + + // K0 + if (mDoK0QC) { + mK0MassVsPt->Reset(); + } +} + +//__________________________________________________________ +bool MatchITSTPCQC::init() +{ + LOGP(debug, "Creating Variable Binning"); + std::array title{"TPC", "ITS"}; + std::array etaSel{"", ", |eta| < 0.9"}; + std::array maxNCls{156, 7}; + // log binning for pT + const Int_t nbinsPt = 100; + const Double_t xminPt = 0.01; + const Double_t xmaxPt = 20; + Double_t* xbinsPt = new Double_t[nbinsPt + 1]; + Double_t xlogminPt = TMath::Log10(xminPt); + Double_t xlogmaxPt = TMath::Log10(xmaxPt); + Double_t dlogxPt = (xlogmaxPt - xlogminPt) / nbinsPt; + for (int i = 0; i <= nbinsPt; i++) { + Double_t xlogPt = xlogminPt + i * dlogxPt; + xbinsPt[i] = TMath::Exp(TMath::Log(10) * xlogPt); + } + + LOGP(debug, "Creating Histograms"); + // Data and MC + for (int i = 0; i < matchType::SIZE; ++i) { + // Pt + mPtNum[i] = new TH1D(Form("mPtNum_%s", title[i].c_str()), Form("Pt distribution of ITSTPC matched tracks, wrt %s tracks %s; Pt [GeV/c]; dNdPt", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 20.f); + mPtNum[i]->Sumw2(); + mPtNum[i]->SetOption("logy"); + mPtNum[i]->GetYaxis()->SetTitleOffset(1.4); + mPtDen[i] = new TH1D(Form("mPtDen_%s", title[i].c_str()), Form("Pt distribution of %s tracks %s; Pt [GeV/c]; dNdPt", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 20.f); + mPtDen[i]->Sumw2(); + mPtDen[i]->SetOption("logy"); + mPtDen[i]->GetYaxis()->SetTitleOffset(1.4); + mFractionITSTPCmatch[i] = new TEfficiency(Form("mFractionITSTPCmatch_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks wrt %s tracks vs Pt %s; Pt [GeV/c]; Eff", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 20.f); + mPtNum_noEta0[i] = new TH1D(Form("mPtNum_noEta0_%s", title[i].c_str()), Form("Pt distribution of ITSTPC matched tracks without |eta| < 0.05, wrt %s tracks %s; Pt [GeV/c]; dNdPt", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 20.f); + mPtNum_noEta0[i]->Sumw2(); + mPtNum_noEta0[i]->SetOption("logy"); + mPtNum_noEta0[i]->GetYaxis()->SetTitleOffset(1.4); + mPtDen_noEta0[i] = new TH1D(Form("mPtDen_noEta0_%s", title[i].c_str()), Form("Pt distribution of %s tracks without |eta| < 0.05 %s; Pt [GeV/c]; dNdPt", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 20.f); + mPtDen_noEta0[i]->Sumw2(); + mPtDen_noEta0[i]->SetOption("logy"); + mPtDen_noEta0[i]->GetYaxis()->SetTitleOffset(1.4); + mFractionITSTPCmatch_noEta0[i] = new TEfficiency(Form("mFractionITSTPCmatch_noEta0_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks wrt %s tracks vs Pt without |eta| < 0.05 %s; Pt [GeV/c]; Eff", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 20.f); + + // Phi + mPhiNum[i] = new TH1F(Form("mPhiNum_%s", title[i].c_str()), Form("Phi distribution of ITSTPC matched tracks, wrt %s tracks %s; Phi [rad]; dNdPhi", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 2 * TMath::Pi()); + mPhiNum[i]->Sumw2(); + mPhiDen[i] = new TH1F(Form("mPhiDen_%s", title[i].c_str()), Form("Phi distribution of %s tracks %s; Phi [rad]; dNdPhi", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 2 * TMath::Pi()); + mPhiDen[i]->Sumw2(); + mFractionITSTPCmatchPhi[i] = new TEfficiency(Form("mFractionITSTPCmatchPhi_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks vs Phi wrt %s tracks %s; Phi [rad]; Eff", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 2 * TMath::Pi()); + mPhiVsPtNum[i] = new TH2F(Form("mPhiVsPtNum_%s", title[i].c_str()), Form("Phi vs Pt distribution of ITSTPC matched tracks wrt %s %s; #it{p}_{T} [GeV#it{c}]; Phi [rad]; dNdPhi", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 20.f, 100, 0.f, 2 * TMath::Pi()); + mPhiVsPtNum[i]->Sumw2(); + mPhiVsPtDen[i] = new TH2F(Form("mPhiVsPtDen_%s", title[i].c_str()), Form("Phi vs Pt distribution of %s tracks %s; #it{p}_{T} [GeV#it{c}]; Phi [rad]; dNdPhi", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 20.f, 100, 0.f, 2 * TMath::Pi()); + mPhiVsPtDen[i]->Sumw2(); + mFractionITSTPCmatchPhiVsPt[i] = new TEfficiency(Form("mFractionITSTPCmatchPhiVsPt_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks wrt %s tracks %s, Phi vs Pt; #it{p}_{T} [GeV#it{c}]; Phi [rad]; Eff", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 20.f, 100, 0.f, 2 * TMath::Pi()); + + // Eta + mEtaNum[i] = new TH1F(Form("mEtaNum_%s", title[i].c_str()), Form("Eta distribution of ITSTPC matched tracks, wrt %s tracks; Eta; dNdEta", title[i].c_str()), 100, -2.f, 2.f); + mEtaNum[i]->Sumw2(); + mEtaNum[i]->GetYaxis()->SetTitleOffset(1.4); + mEtaDen[i] = new TH1F(Form("mEtaDen_%s", title[i].c_str()), Form("Eta distribution of %s tracks; Eta; dNdEta", title[i].c_str()), 100, -2.f, 2.f); + mEtaDen[i]->Sumw2(); + mEtaDen[i]->GetYaxis()->SetTitleOffset(1.4); + mFractionITSTPCmatchEta[i] = new TEfficiency(Form("mFractionITSTPCmatchEta_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks , wrt %s tracks, vs Eta; Eta; Eff", title[i].c_str()), 100, -2.f, 2.f); + mEtaVsPtNum[i] = new TH2F(Form("mEtaVsPtNum_%s", title[i].c_str()), Form("Eta vs Pt distribution of ITSTPC matched tracks, wrt %s tracks; #it{p}_{T} [GeV#it{c}]; Eta", title[i].c_str()), 100, 0.f, 20.f, 100, -2.f, 2.f); + mEtaVsPtNum[i]->Sumw2(); + mEtaVsPtDen[i] = new TH2F(Form("mEtaVsPtDen_%s", title[i].c_str()), Form("Eta vs Pt distribution of %s tracks; #it{p}_{T} [GeV#it{c}]; Eta", title[i].c_str()), 100, 0.f, 20.f, 100, -2.f, 2.f); + mEtaVsPtDen[i]->Sumw2(); + mFractionITSTPCmatchEtaVsPt[i] = new TEfficiency(Form("mFractionITSTPCmatchEtaVsPt_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks, wrt %s tracks, Eta vs Pt; #it{p}_{T} [GeV#it{c}]; Eta; Eff", title[i].c_str()), 100, 0.f, 20.f, 100, -2.f, 2.f); + + // Clusters + mClsVsPtNum[i] = new TH2F(Form("mClsVsPtNum_%s", title[i].c_str()), Form("#Clusters vs Pt distribution of ITSTPC matched tracks, wrt %s tracks; #it{p}_{T} [GeV#it{c}]; #Clusters", title[i].c_str()), 100, 0.f, 20.f, maxNCls[i], 0, maxNCls[i]); + mClsVsPtNum[i]->Sumw2(); + mClsVsPtDen[i] = new TH2F(Form("mClsVsPtDen_%s", title[i].c_str()), Form("#Clusters vs Pt distribution of %s tracks; #it{p}_{T} [GeV#it{c}]; #Clusters", title[i].c_str()), 100, 0.f, 20.f, maxNCls[i], 0, maxNCls[i]); + mClsVsPtDen[i]->Sumw2(); + mFractionITSTPCmatchClsVsPt[i] = new TEfficiency(Form("mFractionITSTPCmatchClsVsPt_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks, wrt %s tracks, #Clusters vs Pt; #it{p}_{T} [GeV#it{c}]; #Clusters; Eff", title[i].c_str()), 100, 0.f, 20.f, maxNCls[i], 0, maxNCls[i]); + + // Chi2 + mChi2VsPtNum[i] = new TH2F(Form("mChi2VsPtNum_%s", title[i].c_str()), Form("Chi2 vs Pt distribution of ITSTPC matched tracks, wrt %s tracks; #it{p}_{T} [GeV#it{c}]; Chi2", title[i].c_str()), 100, 0.f, 20.f, 200, 0, 300); + mChi2VsPtNum[i]->Sumw2(); + mChi2VsPtDen[i] = new TH2F(Form("mChi2VsPtDen_%s", title[i].c_str()), Form("Chi2 vs Pt distribution of %s tracks; #it{p}_{T} [GeV#it{c}]; Chi2", title[i].c_str()), 100, 0.f, 20.f, 200, 0, 300); + mChi2VsPtDen[i]->Sumw2(); + mFractionITSTPCmatchChi2VsPt[i] = new TEfficiency(Form("mFractionITSTPCmatchChi2VsPt_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks, wrt %s tracks, Chi2 vs Pt; #it{p}_{T} [GeV#it{c}]; Chi2; Eff", title[i].c_str()), 100, 0.f, 20.f, 200, 0, 300); + + // 1/pt + m1OverPtNum[i] = new TH1D(Form("m1OverPtNum_%s", title[i].c_str()), Form("1/Pt distribution of matched tracks, wrt %s tracks %s; 1/Pt [c/GeV]; dNdPt", title[i].c_str(), etaSel[i].c_str()), 100, -20.f, 20.f); + m1OverPtNum[i]->Sumw2(); + m1OverPtDen[i] = new TH1D(Form("m1OverPtDen_%s", title[i].c_str()), Form("1/Pt distribution of %s tracks %s; 1/Pt [c/GeV]; dNdPt", title[i].c_str(), etaSel[i].c_str()), 100, -20.f, 20.f); + m1OverPtDen[i]->Sumw2(); + mFractionITSTPCmatch1OverPt[i] = new TEfficiency(Form("mFractionITSTPCmatch1OverPt_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks vs 1/Pt, wrt %s tracks %s; 1/Pt [c/GeV]; Eff", title[i].c_str(), etaSel[i].c_str()), 100, -20.f, 20.f); + + if (mUseTrkPID) { // Vs Tracking PID hypothesis + for (int j = 0; j < o2::track::PID::NIDs; ++j) { + // Pt + mPtNumVsTrkPID[i][j] = new TH1D(Form("mPtNumVsTrkPID_%s_PID%i", title[i].c_str(), j), Form("Pt distribution of ITSTPC matched tracks, wrt %s tracks %s, TrkPID %i; Pt [GeV/c]; dNdPt", title[i].c_str(), etaSel[i].c_str(), j), 100, 0.f, 20.f); + mPtNumVsTrkPID[i][j]->Sumw2(); + mPtDenVsTrkPID[i][j] = new TH1D(Form("mPtDenVsTrkPID_%s_PID%i", title[i].c_str(), j), Form("Pt distribution of %s tracks %s, TrkPID %i; Pt [GeV/c]; dNdPt", title[i].c_str(), etaSel[i].c_str(), j), 100, 0.f, 20.f); + mPtDenVsTrkPID[i][j]->Sumw2(); + mFractionITSTPCmatchPtVsTrkPID[i][j] = new TEfficiency(Form("mFractionITSTPCmatchPtVsTrkPID_%s_PID%i", title[i].c_str(), j), Form("Fraction of ITSTPC matched tracks wrt %s tracks vs Pt %s, TrkPID %i; Pt [GeV/c]; Eff", title[i].c_str(), etaSel[i].c_str(), j), 100, 0.f, 20.f); + + // Phi + mPhiNumVsTrkPID[i][j] = new TH1D(Form("mPhiNumVsTrkPID_%s_PID%i", title[i].c_str(), j), Form("Phi distribution of ITSTPC matched tracks, wrt %s tracks %s, TrkPID %i; Phi [rad]; dNdPhi", title[i].c_str(), etaSel[i].c_str(), j), 100, 0.f, 2 * TMath::Pi()); + mPhiNumVsTrkPID[i][j]->Sumw2(); + mPhiDenVsTrkPID[i][j] = new TH1D(Form("mPhiDenVsTrkPID_%s_PID%i", title[i].c_str(), j), Form("Phi distribution of %s tracks %s, TrkPID %i; Phi [rad]; dNdPhi", title[i].c_str(), etaSel[i].c_str(), j), 100, 0.f, 2 * TMath::Pi()); + mPhiDenVsTrkPID[i][j]->Sumw2(); + mFractionITSTPCmatchPhiVsTrkPID[i][j] = new TEfficiency(Form("mFractionITSTPCmatchPhiVsTrkPID_%s_PID%i", title[i].c_str(), j), Form("Fraction of ITSTPC matched tracks wrt %s tracks vs Phi %s, TrkPID %i; Phi [rad]; Eff", title[i].c_str(), etaSel[i].c_str(), j), 100, 0.f, 2 * TMath::Pi()); + + // Eta + mEtaNumVsTrkPID[i][j] = new TH1D(Form("mEtaNumVsTrkPID_%s_PID%i", title[i].c_str(), j), Form("Eta distribution of ITSTPC matched tracks, wrt %s tracks %s, TrkPID %i; Eta; dNdEta", title[i].c_str(), etaSel[i].c_str(), j), 100, -2.f, 2.f); + mEtaNumVsTrkPID[i][j]->Sumw2(); + mEtaDenVsTrkPID[i][j] = new TH1D(Form("mEtaDenVsTrkPID_%s_PID%i", title[i].c_str(), j), Form("Eta distribution of %s tracks %s, TrkPID %i; Eta; dNdEta", title[i].c_str(), etaSel[i].c_str(), j), 100, -2.f, 2.f); + mEtaDenVsTrkPID[i][j]->Sumw2(); + mFractionITSTPCmatchEtaVsTrkPID[i][j] = new TEfficiency(Form("mFractionITSTPCmatchEtaVsTrkPID_%s_PID%i", title[i].c_str(), j), Form("Fraction of ITSTPC matched tracks wrt %s tracks vs Eta %s, TrkPID %i; Eta; Eff", title[i].c_str(), etaSel[i].c_str(), j), 100, -2.f, 2.f); + } + } + } + + mResidualPt = new TH2F("mResidualPt", "Residuals of ITS-TPC matching in #it{p}_{T}; #it{p}_{T}^{ITS-TPC} [GeV/c]; #it{p}_{T}^{ITS-TPC} - #it{p}_{T}^{TPC} [GeV/c]", 100, 0.f, 20.f, 100, -1.f, 1.f); + mResidualPhi = new TH2F("mResidualPhi", "Residuals of ITS-TPC matching in #it{#phi}; #it{#phi}^{ITS-TPC} [rad]; #it{#phi}^{ITS-TPC} - #it{#phi}^{TPC} [rad]", 100, 0.f, 2 * TMath::Pi(), 100, -1.f, 1.f); + mResidualEta = new TH2F("mResidualEta", "Residuals of ITS-TPC matching in #it{#eta}; #it{#eta}^{ITS-TPC}; #it{#eta}^{ITS-TPC} - #it{#eta}^{TPC}", 100, -2.f, 2.f, 100, -1.f, 1.f); + mChi2Matching = new TH1F("mChi2Matching", "Chi2 of matching; chi2", 200, 0, 300); + mChi2Matching->SetOption("logy"); + mChi2Matching->GetYaxis()->SetTitleOffset(1.4); + mChi2Refit = new TH1F("mChi2Refit", "Chi2 of refit; chi2", 200, 0, 300); + mChi2Refit->SetOption("logy"); + mChi2Refit->GetYaxis()->SetTitleOffset(1.4); + mDCAr = new TH1F("mDCAr", "DCA of TPC tracks; DCAr", 200, -100, 100); + mDCArVsPtNum = new TH2F("mDCArVsPtNum", "DCA of TPC tracks Vs Pt Num; #it{p}_{T} [GeV/c]; DCAr", 100, 0, 20., 200, -30, 30); + mDCArVsPtNum->Sumw2(); + mDCArVsPtDen = new TH2F("mDCArVsPtDen", "DCA of TPC tracks Vs Pt Den; #it{p}_{T} [GeV/c]; DCAr", 100, 0, 20., 200, -30, 30); + mDCArVsPtDen->Sumw2(); + mFractionITSTPCmatchDCArVsPt = new TEfficiency("mFractionITSTPCmatchDCArVsPt", "Fraction of ITSTPC matched tracks wrt TPC vs DCAr; #it{p}_{T} [GeV#it{c}]; DCAr; Eff", 100, 0, 20., 200, -30, 30); + + mTimeResVsPt = new TH2F("mTimeResVsPt", "Time resolution vs Pt; Pt [GeV/c]; time res [us]", nbinsPt, xbinsPt, 100, 0.f, 2.f); + mTimeResVsPt->SetOption("colz logz logy logx"); + mTimeResVsPt->GetYaxis()->SetTitleOffset(1.4); + + if (mUseMC) { + mcReader.initFromDigitContext("collisioncontext.root"); + + for (int i = 0; i < matchType::SIZE; ++i) { + mPtPhysPrimNum[i] = new TH1F(Form("mPtPhysPrimNum_%s", title[i].c_str()), Form("Pt distribution of matched tracks (physical primary), wrt %s tracks %s; Pt [GeV/c]; dNdPt", title[i].c_str(), etaSel[i].c_str()), nbinsPt, xbinsPt); + mPtPhysPrimNum[i]->Sumw2(); + mPtPhysPrimDen[i] = new TH1F(Form("mPtPhysPrimDen_%s", title[i].c_str()), Form("Pt distribution of %s tracks (physical primary) %s; Pt [GeV/c]; dNdPt", title[i].c_str(), etaSel[i].c_str()), nbinsPt, xbinsPt); + mPtPhysPrimDen[i]->Sumw2(); + mFractionITSTPCmatchPhiPhysPrim[i] = new TEfficiency(Form("mFractionITSTPCmatchPhiPhysPrim_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks vs Phi (physical primary), wrt %s tracks %s; Phi [rad]; Eff", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 2 * TMath::Pi()); + + mEtaPhysPrimNum[i] = new TH1F(Form("mEtaPhysPrimNum_%s", title[i].c_str()), Form("Eta distribution of matched tracks (physical primary), wrt %s tracks; Eta; dNdEta", title[i].c_str()), 100, -2.f, 2.f); + mEtaPhysPrimNum[i]->Sumw2(); + mEtaPhysPrimDen[i] = new TH1F(Form("mEtaPhysPrimDen_%s", title[i].c_str()), Form("Eta distribution of %s tracks (physical primary); Eta; dNdEta", title[i].c_str()), 100, -2.f, 2.f); + mEtaPhysPrimDen[i]->Sumw2(); + mFractionITSTPCmatchEtaPhysPrim[i] = new TEfficiency(Form("mFractionITSTPCmatchEtaPhysPrim_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks vs Eta (physical primary), wrt %s tracks; Eta; Eff", title[i].c_str()), 100, -2.f, 2.f); + + mPhiPhysPrimNum[i] = new TH1F(Form("mPhiPhysPrimNum_%s", title[i].c_str()), Form("Phi distribution of matched tracks (physical primary), wrt %s tracks %s; Phi [rad]; dNdPhi", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 2 * TMath::Pi()); + mPhiPhysPrimNum[i]->Sumw2(); + mPhiPhysPrimDen[i] = new TH1F(Form("mPhiPhysPrimDen_%s", title[i].c_str()), Form("Phi distribution of %s tracks (physical primary) %s; Phi [rad]; dNdPhi", title[i].c_str(), etaSel[i].c_str()), 100, 0.f, 2 * TMath::Pi()); + mPhiPhysPrimDen[i]->Sumw2(); + mFractionITSTPCmatchPhysPrim[i] = new TEfficiency(Form("mFractionITSTPCmatchPhysPrim_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks vs Pt (physical primary), wrt %s tracks %s; Pt [GeV/c]; Eff", title[i].c_str(), etaSel[i].c_str()), nbinsPt, xbinsPt); + + m1OverPtPhysPrimNum[i] = new TH1D(Form("m1OverPtPhysPrimNum_%s", title[i].c_str()), Form("1/Pt distribution of matched tracks (physical primary), wrt %s tracks %s; 1/Pt [c/GeV]; dNd1/Pt", title[i].c_str(), etaSel[i].c_str()), 100, -20.f, 20.f); + m1OverPtPhysPrimNum[i]->Sumw2(); + m1OverPtPhysPrimDen[i] = new TH1D(Form("m1OverPtPhysPrimDen_%s", title[i].c_str()), Form("1/PtPt distribution of %s tracks (physical primary) %s; 1/Pt [c/GeV]; dNd1/Pt", title[i].c_str(), etaSel[i].c_str()), 100, -20.f, 20.f); + m1OverPtPhysPrimDen[i]->Sumw2(); + mFractionITSTPCmatchPhysPrim1OverPt[i] = new TEfficiency(Form("mFractionITSTPCmatchPhysPrim1OverPt_%s", title[i].c_str()), Form("Fraction of ITSTPC matched tracks vs 1/Pt (physical primary), wrt %s tracks %s; 1/Pt [c/GeV]; Eff", title[i].c_str(), etaSel[i].c_str()), 100, -20.f, 20.f); + } + } + + if (mDoK0QC) { + // V0s + mK0MassVsPt = new TH2F("mK0MassVsPt", "K0 invariant mass vs Pt", 100, 0.3, 0.7, 100, 0.f, 20.f); + } + + return true; +} + +//__________________________________________________________ + +void MatchITSTPCQC::initDataRequest() +{ + + // initialize data request, if it was not already done + + mSrc &= mAllowedSources; + + if (mSrc[GID::Source::ITSTPC] == 0 || mSrc[GID::Source::TPC] == 0 || mSrc[GID::Source::ITS] == 0) { + LOG(fatal) << "We cannot do ITSTPC QC, some sources are missing, check sources in " << mSrc; + } + + mDataRequest = std::make_shared(); + mDataRequest->requestTracks(mSrc, mUseMC); + if (mDoK0QC) { + mDataRequest->requestPrimaryVertices(mUseMC); + mDataRequest->requestSecondaryVertices(mUseMC); + } +} + +//__________________________________________________________ + +void MatchITSTPCQC::run(o2::framework::ProcessingContext& ctx) +{ + + // Getting the B field + mBz = o2::base::Propagator::Instance()->getNominalBz(); + + // Getting the SVertexer config params + if (mTimestamp == -1 && mDoK0QC) { + // we have not yet initialized the SVertexer params; let's do it + ctx.inputs().get("SVParam"); + mTimestamp = ctx.services().get().creation; + } + + static int evCount = 0; + mRecoCont.collectData(ctx, *mDataRequest.get()); + mTPCTracks = mRecoCont.getTPCTracks(); + mITSTracks = mRecoCont.getITSTracks(); + mITSTPCTracks = mRecoCont.getTPCITSTracks(); + + LOG(debug) << "****** Number of found ITSTPC tracks = " << mITSTPCTracks.size(); + LOG(debug) << "****** Number of found TPC tracks = " << mTPCTracks.size(); + LOG(debug) << "****** Number of found ITS tracks = " << mITSTracks.size(); + + // cache selection for TPC and ITS tracks + std::vector isTPCTrackSelectedEntry(mTPCTracks.size(), false); + std::vector isITSTrackSelectedEntry(mITSTracks.size(), false); + TrackCuts cuts; + // ITS track + cuts.setMinPtITSCut(mPtITSCut); + cuts.setEtaITSCut(mEtaITSCut); + cuts.setMinNClustersITS(mMinNClustersITS); + cuts.setMaxChi2PerClusterITS(mMaxChi2PerClusterITS); + for (auto it = mRequiredITSHits.begin(); it != mRequiredITSHits.end(); it++) { + cuts.setRequireHitsInITSLayers((*it).first, (*it).second); + } + // TPC track + cuts.setMinPtTPCCut(mPtTPCCut); + cuts.setEtaTPCCut(mEtaTPCCut); + cuts.setMinNTPCClustersCut(mNTPCClustersCut); + cuts.setMaxDCATPCCut(mDCATPCCut); + cuts.setMaxDCATPCCutY(mDCATPCCutY); + // ITS-TPC track kinematics + cuts.setMinPtCut(mPtCut); + cuts.setMaxPtCut(mPtMaxCut); + cuts.setEtaCut(-mEtaCut, mEtaCut); + + for (size_t itrk = 0; itrk < mTPCTracks.size(); ++itrk) { + auto const& trkTpc = mTPCTracks[itrk]; + o2::dataformats::GlobalTrackID id(itrk, GID::TPC); + if (cuts.isSelected(id, mRecoCont)) { + // NB: same cuts for numerator and denominator tracks of ITS-TPC matching + // To change cuts only for numerator, something like o2::dataformats::GlobalTrackID id(itrk, GID::ITSTPC) is necessary + isTPCTrackSelectedEntry[itrk] = true; + } + } + + for (size_t itrk = 0; itrk < mITSTracks.size(); ++itrk) { + auto const& trkIts = mITSTracks[itrk]; + o2::dataformats::GlobalTrackID id(itrk, GID::ITS); + if (cuts.isSelected(id, mRecoCont)) { + // NB: same cuts for numerator and denominator tracks of ITS-TPC matching + // To change cuts only for numerator, something like o2::dataformats::GlobalTrackID id(itrk, GID::ITSTPC) is necessary + isITSTrackSelectedEntry[itrk] = true; + } + } + + // numerator + eta, chi2... + if (mUseMC) { + for (int i = 0; i < matchType::SIZE; ++i) { + mMapLabels[i].clear(); + } + for (int itrk = 0; itrk < static_cast(mITSTPCTracks.size()); ++itrk) { + auto const& trk = mITSTPCTracks[itrk]; + auto idxTrkTpc = trk.getRefTPC().getIndex(); + if (trk.getRefITS().getSource() != GID::ITS) { + continue; + } + if (isTPCTrackSelectedEntry[idxTrkTpc] == true) { + auto lbl = mRecoCont.getTrackMCLabel({(unsigned int)(itrk), GID::Source::ITSTPC}); + if (!lbl.isValid()) { + continue; + } + if (mMapLabels[matchType::TPC].find(lbl) == mMapLabels[matchType::TPC].end()) { + int source = lbl.getSourceID(); + int event = lbl.getEventID(); + const std::vector& pcontainer = mcReader.getTracks(source, event); + const o2::MCTrack& p = pcontainer[lbl.getTrackID()]; + if (MCTrackNavigator::isPhysicalPrimary(p, pcontainer)) { + mMapLabels[matchType::TPC].insert({lbl, {itrk, true}}); + } else { + mMapLabels[matchType::TPC].insert({lbl, {itrk, false}}); + } + } else { + // winner (if more tracks have the same label) has the highest pt + if (mITSTPCTracks[mMapLabels[matchType::TPC].at(lbl).mIdx].getPt() < trk.getPt()) { + mMapLabels[matchType::TPC].at(lbl).mIdx = itrk; + } + } + } + auto idxTrkIts = trk.getRefITS().getIndex(); + if (isITSTrackSelectedEntry[idxTrkIts] == true) { + auto lbl = mRecoCont.getTrackMCLabel({(unsigned int)(itrk), GID::Source::ITSTPC}); + if (!lbl.isValid()) { + continue; + } + if (mMapLabels[matchType::ITS].find(lbl) == mMapLabels[matchType::ITS].end()) { + int source = lbl.getSourceID(); + int event = lbl.getEventID(); + const std::vector& pcontainer = mcReader.getTracks(source, event); + const o2::MCTrack& p = pcontainer[lbl.getTrackID()]; + if (MCTrackNavigator::isPhysicalPrimary(p, pcontainer)) { + mMapLabels[matchType::ITS].insert({lbl, {itrk, true}}); + } else { + mMapLabels[matchType::ITS].insert({lbl, {itrk, false}}); + } + } else { + // winner (if more tracks have the same label) has the highest pt + if (mITSTPCTracks[mMapLabels[matchType::ITS].at(lbl).mIdx].getPt() < trk.getPt()) { + mMapLabels[matchType::ITS].at(lbl).mIdx = itrk; + } + } + } + } + LOG(info) << "number of entries in map for nominator (without duplicates) = " << mMapLabels.size(); + // now we use only the tracks in the map to fill the histograms (--> tracks have passed the + // track selection and there are no duplicated tracks wrt the same MC label) + for (int i = 0; i < matchType::SIZE; ++i) { + for (auto const& el : mMapLabels[i]) { + auto const& trk = mITSTPCTracks[el.second.mIdx]; + o2::track::TrackParCov trkDen; + bool isEtaITSOk = true; + if (i == matchType::TPC) { + trkDen = mTPCTracks[trk.getRefTPC()]; + } else { + trkDen = mITSTracks[trk.getRefITS()]; + if (std::abs(trkDen.getEta()) > 0.9) { + // ITS track outside |eta | < 0.9, we don't fill pt, nor phi , nor phi vs pt histos + isEtaITSOk = false; + } + } + if (isEtaITSOk) { + mPtNum[i]->Fill(trkDen.getPt()); + if (std::abs(trkDen.getEta()) > 0.05) { + mPtNum_noEta0[i]->Fill(trkDen.getPt()); + } + mPhiNum[i]->Fill(trkDen.getPhi()); + mPhiVsPtNum[i]->Fill(trkDen.getPt(), trkDen.getPhi()); + m1OverPtNum[i]->Fill(trkDen.getSign() * trkDen.getPtInv()); + // we fill also the denominator + mPtDen[i]->Fill(trkDen.getPt()); + if (std::abs(trkDen.getEta()) > 0.05) { + mPtDen_noEta0[i]->Fill(trkDen.getPt()); + } + mPhiDen[i]->Fill(trkDen.getPhi()); + mPhiVsPtDen[i]->Fill(trkDen.getPt(), trkDen.getPhi()); + m1OverPtDen[i]->Fill(trkDen.getSign() * trkDen.getPtInv()); + if (mUseTrkPID) { // Vs Tracking PID hypothesis + mPtNumVsTrkPID[i][trkDen.getPID()]->Fill(trkDen.getPt()); + mPhiNumVsTrkPID[i][trkDen.getPID()]->Fill(trkDen.getPhi()); + // we fill also the denominator + mPtDenVsTrkPID[i][trkDen.getPID()]->Fill(trkDen.getPt()); + mPhiDenVsTrkPID[i][trkDen.getPID()]->Fill(trkDen.getPhi()); + } + } + mEtaNum[i]->Fill(trkDen.getEta()); + mEtaVsPtNum[i]->Fill(trkDen.getPt(), trkDen.getEta()); + // we fill also the denominator + mEtaDen[i]->Fill(trkDen.getEta()); + mEtaVsPtDen[i]->Fill(trkDen.getPt(), trkDen.getEta()); + if (i == matchType::TPC) { + auto tpcTrk = mTPCTracks[trk.getRefTPC()]; + mClsVsPtNum[i]->Fill(tpcTrk.getPt(), tpcTrk.getNClusters()); + mChi2VsPtNum[i]->Fill(tpcTrk.getPt(), tpcTrk.getChi2()); + mClsVsPtDen[i]->Fill(tpcTrk.getPt(), tpcTrk.getNClusters()); + mChi2VsPtDen[i]->Fill(tpcTrk.getPt(), tpcTrk.getChi2()); + math_utils::Point3D v{}; + std::array dca{}; + if (tpcTrk.propagateParamToDCA(v, mBz, &dca)) { + mDCArVsPtNum->Fill(tpcTrk.getPt(), dca[0]); + mDCArVsPtDen->Fill(tpcTrk.getPt(), dca[0]); + } + } else { + const auto& itsTrk = mITSTracks[trk.getRefITS()]; + mClsVsPtNum[i]->Fill(itsTrk.getPt(), itsTrk.getNClusters()); + mChi2VsPtNum[i]->Fill(itsTrk.getPt(), itsTrk.getChi2()); + mClsVsPtDen[i]->Fill(itsTrk.getPt(), itsTrk.getNClusters()); + mChi2VsPtDen[i]->Fill(itsTrk.getPt(), itsTrk.getChi2()); + } + if (mUseTrkPID) { // Vs Tracking PID hypothesis + mEtaNumVsTrkPID[i][trkDen.getPID()]->Fill(trkDen.getEta()); + // we fill also the denominator + mEtaDenVsTrkPID[i][trkDen.getPID()]->Fill(trkDen.getEta()); + } + if (el.second.mIsPhysicalPrimary) { + if (isEtaITSOk) { + mPtPhysPrimNum[i]->Fill(trkDen.getPt()); + mPhiPhysPrimNum[i]->Fill(trkDen.getPhi()); + m1OverPtPhysPrimNum[i]->Fill(trkDen.getSign() * trkDen.getPtInv()); + // we fill also the denominator + mPtPhysPrimDen[i]->Fill(trkDen.getPt()); + mPhiPhysPrimDen[i]->Fill(trkDen.getPhi()); + m1OverPtPhysPrimDen[i]->Fill(trkDen.getSign() * trkDen.getPtInv()); + } + mEtaPhysPrimNum[i]->Fill(trkDen.getEta()); + // we fill also the denominator + mEtaPhysPrimDen[i]->Fill(trkDen.getEta()); + } + ++mNITSTPCSelectedTracks[i]; + } + } + } + int iITSTPC = 0; + for (auto const& trk : mITSTPCTracks) { + if (trk.getRefTPC().getIndex() >= mTPCTracks.size()) { + LOG(fatal) << "******************** ATTENTION! for TPC track associated to matched track: idx = " << trk.getRefTPC().getIndex() << ", size of container = " << mTPCTracks.size() << " in TF " << evCount; + } + std::array title{"TPC", "ITS"}; + for (int i = 0; i < matchType::SIZE; ++i) { + o2::track::TrackParCov trkRef; + int idxTrkRef; + bool fillHisto = false; + bool isEtaITSOk = true; + if (i == matchType::TPC) { + trkRef = mTPCTracks[trk.getRefTPC()]; + idxTrkRef = trk.getRefTPC().getIndex(); + if (isTPCTrackSelectedEntry[idxTrkRef] == true) { + fillHisto = true; + ++mNITSTPCSelectedTracks[i]; + } + } else { + idxTrkRef = trk.getRefITS().getIndex(); + if (trk.getRefITS().getSource() == GID::ITSAB) { + // do not use afterburner tracks + LOG(debug) << "Track (ITS) with id " << idxTrkRef << " for ITSTPC track " << iITSTPC << " is from afterburner"; + continue; + } + if (idxTrkRef >= mITSTracks.size()) { + LOG(fatal) << "******************** ATTENTION! for ITS track associated to matched track (NOT from AB): idx = " << trk.getRefITS().getIndex() << ", size of container = " << mITSTracks.size() << " in TF " << evCount; + } + trkRef = mITSTracks[trk.getRefITS()]; + LOG(debug) << "Checking track (ITS) with id " << idxTrkRef << " for ITSTPC track " << iITSTPC << " and pt = " << trkRef.getPt(); + if (isITSTrackSelectedEntry[idxTrkRef] == true) { + LOG(debug) << "Track was selected (ITS), with id " << idxTrkRef << " for ITSTPC track " << iITSTPC << " , we keep it in the numerator, pt = " << trkRef.getPt(); + fillHisto = true; + ++mNITSTPCSelectedTracks[i]; + } else { + LOG(debug) << "Track was not selected (ITS), with id " << idxTrkRef << " for ITSTPC track " << iITSTPC << " , we don't keep it in the numerator, pt = " << trkRef.getPt(); + } + if (std::abs(trkRef.getEta()) > 0.9) { + // ITS track outside |eta | < 0.9, we don't fill pt, nor phi , nor phi vs pt histos + isEtaITSOk = false; + LOG(debug) << "Track (ITS), with id " << idxTrkRef << " for ITSTPC track " << iITSTPC << " will be discarded when filling pt of phi related histograms, since eta = " << trkRef.getEta() << " , we don't keep it in the numerator, pt = " << trkRef.getPt(); + } + } + if (fillHisto == true) { + if (!mUseMC) { + LOG(debug) << "Filling num (" << title[i] << ") with track with id " << idxTrkRef << " for ITSTPC track " << iITSTPC << " with pt = " << trkRef.getPt(); + if (isEtaITSOk) { + mPtNum[i]->Fill(trkRef.getPt()); + if (std::abs(trkRef.getEta()) > 0.05) { + mPtNum_noEta0[i]->Fill(trkRef.getPt()); + } + mPhiNum[i]->Fill(trkRef.getPhi()); + if (mUseTrkPID) { // Vs Tracking PID hypothesis + mPtNumVsTrkPID[i][trkRef.getPID()]->Fill(trkRef.getPt()); + mPhiNumVsTrkPID[i][trkRef.getPID()]->Fill(trkRef.getPhi()); + } + mPhiVsPtNum[i]->Fill(trkRef.getPt(), trkRef.getPhi()); + m1OverPtNum[i]->Fill(trkRef.getSign() * trkRef.getPtInv()); + } + mEtaNum[i]->Fill(trkRef.getEta()); + if (mUseTrkPID) { // Vs Tracking PID hypothesis + mEtaNumVsTrkPID[i][trkRef.getPID()]->Fill(trkRef.getEta()); + } + mEtaVsPtNum[i]->Fill(trkRef.getPt(), trkRef.getEta()); + if (i == matchType::TPC) { + const auto& tpcTrk = mTPCTracks[trk.getRefTPC()]; + mClsVsPtNum[i]->Fill(tpcTrk.getPt(), tpcTrk.getNClusters()); + mChi2VsPtNum[i]->Fill(tpcTrk.getPt(), tpcTrk.getChi2()); + } else { + const auto& itsTrk = mITSTracks[trk.getRefITS()]; + mClsVsPtNum[i]->Fill(itsTrk.getPt(), itsTrk.getNClusters()); + mChi2VsPtNum[i]->Fill(itsTrk.getPt(), itsTrk.getChi2()); + } + } + if (i == matchType::TPC) { + mResidualPt->Fill(trk.getPt(), trk.getPt() - trkRef.getPt()); + mResidualPhi->Fill(trk.getPhi(), trk.getPhi() - trkRef.getPhi()); + mResidualEta->Fill(trk.getEta(), trk.getEta() - trkRef.getEta()); + mChi2Matching->Fill(trk.getChi2Match()); + mChi2Refit->Fill(trk.getChi2Refit()); + mTimeResVsPt->Fill(trkRef.getPt(), trk.getTimeMUS().getTimeStampError()); + math_utils::Point3D v{}; + std::array dca; + if (trkRef.propagateParamToDCA(v, mBz, &dca)) { + mDCAr->Fill(dca[0]); + if (!mUseMC) { + mDCArVsPtNum->Fill(trkRef.getPt(), dca[0]); + } + } + LOG(debug) << "*** chi2Matching = " << trk.getChi2Match() << ", chi2refit = " << trk.getChi2Refit() << ", timeResolution = " << trk.getTimeMUS().getTimeStampError(); + } + } else { + LOG(debug) << "Not filling num (" << title[i] << ") for ITSTPC track " << iITSTPC << " for track with pt " << trkRef.getPt(); + } + } + ++iITSTPC; + } + + // now filling the denominator for the efficiency calculation + if (mUseMC) { + for (int i = 0; i < matchType::SIZE; ++i) { + mMapRefLabels[i].clear(); + } + // filling the map where we store for each MC label, the track id of the reconstructed + // track with the highest number of TPC clusters + for (int itrk = 0; itrk < static_cast(mTPCTracks.size()); ++itrk) { + auto const& trk = mTPCTracks[itrk]; + if (isTPCTrackSelectedEntry[itrk] == true) { + auto lbl = mRecoCont.getTrackMCLabel({(unsigned int)(itrk), GID::Source::TPC}); + if (!lbl.isValid()) { + continue; + } + if (mMapLabels[matchType::TPC].find(lbl) != mMapLabels[matchType::TPC].end()) { + // the track was already added to the denominator + continue; + } + if (mMapRefLabels[matchType::TPC].find(lbl) == mMapRefLabels[matchType::TPC].end()) { + int source = lbl.getSourceID(); + int event = lbl.getEventID(); + const std::vector& pcontainer = mcReader.getTracks(source, event); + const o2::MCTrack& p = pcontainer[lbl.getTrackID()]; + if (MCTrackNavigator::isPhysicalPrimary(p, pcontainer)) { + mMapRefLabels[matchType::TPC].insert({lbl, {itrk, true}}); + } else { + mMapRefLabels[matchType::TPC].insert({lbl, {itrk, false}}); + } + } else { + // winner (if more tracks have the same label) has the highest number of TPC clusters + if (mTPCTracks[mMapRefLabels[matchType::TPC].at(lbl).mIdx].getNClusters() < trk.getNClusters()) { + mMapRefLabels[matchType::TPC].at(lbl).mIdx = itrk; + } + } + } + } + // same for ITS + // filling the map where we store for each MC label, the track id of the reconstructed + // track with the highest number of ITS clusters + for (int itrk = 0; itrk < static_cast(mITSTracks.size()); ++itrk) { + auto const& trk = mITSTracks[itrk]; + if (isITSTrackSelectedEntry[itrk] == true) { + auto lbl = mRecoCont.getTrackMCLabel({(unsigned int)(itrk), GID::Source::ITS}); + if (!lbl.isValid()) { + continue; + } + if (mMapLabels[matchType::ITS].find(lbl) != mMapLabels[matchType::ITS].end()) { + // the track was already added to the denominator + continue; + } + if (mMapRefLabels[matchType::ITS].find(lbl) == mMapRefLabels[matchType::ITS].end()) { + int source = lbl.getSourceID(); + int event = lbl.getEventID(); + const std::vector& pcontainer = mcReader.getTracks(source, event); + const o2::MCTrack& p = pcontainer[lbl.getTrackID()]; + if (MCTrackNavigator::isPhysicalPrimary(p, pcontainer)) { + mMapRefLabels[matchType::ITS].insert({lbl, {itrk, true}}); + } else { + mMapRefLabels[matchType::ITS].insert({lbl, {itrk, false}}); + } + } else { + // winner (if more tracks have the same label) has the highest number of ITS clusters + if (mITSTracks[mMapRefLabels[matchType::ITS].at(lbl).mIdx].getNClusters() < trk.getNClusters()) { + mMapRefLabels[matchType::ITS].at(lbl).mIdx = itrk; + } + } + } + } + LOG(info) << "number of entries in map for denominator of TPC tracks (without duplicates) = " << mMapRefLabels[matchType::TPC].size() + mMapLabels[matchType::TPC].size(); + LOG(info) << "number of entries in map for denominator of ITS tracks (without duplicates) = " << mMapRefLabels[matchType::ITS].size() + mMapLabels[matchType::ITS].size(); + // now we use only the tracks in the map to fill the histograms (--> tracks have passed the + // track selection and there are no duplicated tracks wrt the same MC label) + for (auto const& el : mMapRefLabels[matchType::TPC]) { + auto const& trk = mTPCTracks[el.second.mIdx]; + mPtDen[matchType::TPC]->Fill(trk.getPt()); + if (std::abs(trk.getEta()) > 0.05) { + mPtDen_noEta0[matchType::TPC]->Fill(trk.getPt()); + } + mPhiDen[matchType::TPC]->Fill(trk.getPhi()); + mPhiVsPtDen[matchType::TPC]->Fill(trk.getPt(), trk.getPhi()); + mEtaDen[matchType::TPC]->Fill(trk.getEta()); + mEtaVsPtDen[matchType::TPC]->Fill(trk.getPt(), trk.getEta()); + m1OverPtDen[matchType::TPC]->Fill(trk.getSign() * trk.getPtInv()); + mClsVsPtDen[matchType::TPC]->Fill(trk.getPt(), trk.getNClusters()); + mChi2VsPtDen[matchType::TPC]->Fill(trk.getPt(), trk.getChi2()); + math_utils::Point3D v{}; + std::array dca{}; + if (auto trc = trk; trc.propagateParamToDCA(v, mBz, &dca)) { + mDCArVsPtDen->Fill(trc.getPt(), dca[0]); + } + if (el.second.mIsPhysicalPrimary) { + mPtPhysPrimDen[matchType::TPC]->Fill(trk.getPt()); + mPhiPhysPrimDen[matchType::TPC]->Fill(trk.getPhi()); + mEtaPhysPrimDen[matchType::TPC]->Fill(trk.getEta()); + m1OverPtPhysPrimDen[matchType::TPC]->Fill(trk.getSign() * trk.getPtInv()); + } + ++mNTPCSelectedTracks; + } + for (auto const& el : mMapRefLabels[matchType::ITS]) { + auto const& trk = mITSTracks[el.second.mIdx]; + if (std::abs(trk.getEta()) < 0.9) { + mPtDen[matchType::ITS]->Fill(trk.getPt()); + if (std::abs(trk.getEta()) > 0.05) { + mPtDen_noEta0[matchType::ITS]->Fill(trk.getPt()); + } + mPhiDen[matchType::ITS]->Fill(trk.getPhi()); + mPhiVsPtDen[matchType::ITS]->Fill(trk.getPt(), trk.getPhi()); + m1OverPtDen[matchType::ITS]->Fill(trk.getSign() * trk.getPtInv()); + } + mEtaDen[matchType::ITS]->Fill(trk.getEta()); + mEtaVsPtDen[matchType::ITS]->Fill(trk.getPt(), trk.getEta()); + mClsVsPtDen[matchType::ITS]->Fill(trk.getPt(), trk.getNClusters()); + mChi2VsPtDen[matchType::ITS]->Fill(trk.getPt(), trk.getChi2()); + if (el.second.mIsPhysicalPrimary) { + if (std::abs(trk.getEta()) < 0.9) { + mPtPhysPrimDen[matchType::ITS]->Fill(trk.getPt()); + mPhiPhysPrimDen[matchType::ITS]->Fill(trk.getPhi()); + m1OverPtPhysPrimDen[matchType::ITS]->Fill(trk.getSign() * trk.getPtInv()); + } + mEtaPhysPrimDen[matchType::ITS]->Fill(trk.getEta()); + } + ++mNITSSelectedTracks; + } + } else { + // if we are in data, we loop over all tracks (no check on the label) + for (size_t itrk = 0; itrk < mTPCTracks.size(); ++itrk) { + auto const& trk = mTPCTracks[itrk]; + if (isTPCTrackSelectedEntry[itrk] == true) { + LOG(debug) << "Filling den (TPC) with track with pt = " << trk.getPt(); + mPtDen[matchType::TPC]->Fill(trk.getPt()); + if (std::abs(trk.getEta()) > 0.05) { + mPtDen_noEta0[matchType::TPC]->Fill(trk.getPt()); + } else { + LOG(debug) << "Track (ITS) " << itrk << " with pt = " << trk.getPt() << " and eta = " << trk.getEta() << " not used for den pt, phi, phi vs pt, 1.pt histos"; + } + mPhiDen[matchType::TPC]->Fill(trk.getPhi()); + mPhiVsPtDen[matchType::TPC]->Fill(trk.getPt(), trk.getPhi()); + mEtaDen[matchType::TPC]->Fill(trk.getEta()); + mEtaVsPtDen[matchType::TPC]->Fill(trk.getPt(), trk.getEta()); + m1OverPtDen[matchType::TPC]->Fill(trk.getSign() * trk.getPtInv()); + mClsVsPtDen[matchType::TPC]->Fill(trk.getPt(), trk.getNClusters()); + mChi2VsPtDen[matchType::TPC]->Fill(trk.getPt(), trk.getChi2()); + math_utils::Point3D v{}; + std::array dca{}; + if (auto trc = trk; trc.propagateParamToDCA(v, mBz, &dca)) { + mDCArVsPtDen->Fill(trc.getPt(), dca[0]); + } + ++mNTPCSelectedTracks; + } + } + for (size_t itrk = 0; itrk < mITSTracks.size(); ++itrk) { + auto const& trk = mITSTracks[itrk]; + LOG(debug) << "Checking den for track (ITS) " << itrk << " with pt " << trk.getPt() << " and eta = " << trk.getEta(); + if (isITSTrackSelectedEntry[itrk] == true) { + if (std::abs(trk.getEta()) < 0.9) { + LOG(debug) << "Filling den for track (ITS) " << itrk << " with pt = " << trk.getPt() << " and eta = " << trk.getEta(); + mPtDen[matchType::ITS]->Fill(trk.getPt()); + if (std::abs(trk.getEta()) > 0.05) { + mPtDen_noEta0[matchType::ITS]->Fill(trk.getPt()); + } + mPhiDen[matchType::ITS]->Fill(trk.getPhi()); + mPhiVsPtDen[matchType::ITS]->Fill(trk.getPt(), trk.getPhi()); + m1OverPtDen[matchType::ITS]->Fill(trk.getSign() * trk.getPtInv()); + } else { + LOG(debug) << "Track (ITS) " << itrk << " with pt = " << trk.getPt() << " and eta = " << trk.getEta() << " not used for num pt, phi, phi vs pt, 1.pt histos"; + } + mEtaDen[matchType::ITS]->Fill(trk.getEta()); + mEtaVsPtDen[matchType::ITS]->Fill(trk.getPt(), trk.getEta()); + mClsVsPtDen[matchType::ITS]->Fill(trk.getPt(), trk.getNClusters()); + mChi2VsPtDen[matchType::ITS]->Fill(trk.getPt(), trk.getChi2()); + ++mNITSSelectedTracks; + } else { + LOG(debug) << "Not filling for this track (ITS) " << itrk << " with pt = " << trk.getPt(); + } + } + } + + if (mDoK0QC) { + // now doing K0S + const auto pvertices = mRecoCont.getPrimaryVertices(); + LOG(info) << "Found " << pvertices.size() << " primary vertices"; + + auto v0IDs = mRecoCont.getV0sIdx(); + auto nv0 = v0IDs.size(); + if (nv0 > mRecoCont.getV0s().size()) { + mRefit = true; + } + LOG(info) << "Found " << mRecoCont.getV0s().size() << " V0s in reco container"; + LOG(info) << "Found " << nv0 << " V0s ids"; + // associating sec vtxs to prim vtx + std::map> pv2sv; + static int tfID = 0; + for (int iv = 0; iv < nv0; iv++) { + const auto v0id = v0IDs[iv]; + pv2sv[v0id.getVertexID()].push_back(iv); + } + int nV0sOk = 0; + // processing every sec vtx for each prim vtx + for (auto it : pv2sv) { + int pvID = it.first; + auto& vv = it.second; + if (pvID < 0 || vv.size() == 0) { + continue; + } + for (int iv0 : vv) { + nV0sOk += processV0(iv0, mRecoCont) ? 1 : 0; + } + } + + LOG(info) << "Processed " << nV0sOk << " V0s"; + } + evCount++; +} + +//__________________________________________________________ +bool MatchITSTPCQC::processV0(int iv, o2::globaltracking::RecoContainer& recoData) +{ + o2::dataformats::V0 v0; + auto v0s = recoData.getV0s(); + auto v0IDs = recoData.getV0sIdx(); + static int tfID = 0; + + const auto& v0id = v0IDs[iv]; + if (mRefit && !refitV0(v0id, v0, recoData)) { + return false; + } + const auto& v0sel = mRefit ? v0 : v0s[iv]; + if (mMaxEtaK0 < std::abs(v0sel.getEta())) { + return false; + } + if (mCutK0Mass > 0 && std::abs(std::sqrt(v0sel.calcMass2AsK0()) - 0.497) > mCutK0Mass) { + return false; + } + mK0MassVsPt->Fill(std::sqrt(v0sel.calcMass2AsK0()), v0sel.getPt()); + return true; +} + +//__________________________________________________________ +bool MatchITSTPCQC::refitV0(const o2::dataformats::V0Index& id, o2::dataformats::V0& v0, o2::globaltracking::RecoContainer& recoData) +{ + if (!recoData.isTrackSourceLoaded(id.getProngID(0).getSource()) || !recoData.isTrackSourceLoaded(id.getProngID(1).getSource())) { + return false; + } + auto seedP = recoData.getTrackParam(id.getProngID(0)); + auto seedN = recoData.getTrackParam(id.getProngID(1)); + bool isTPConly = (id.getProngID(0).getSource() == o2::dataformats::GlobalTrackID::TPC) || (id.getProngID(1).getSource() == o2::dataformats::GlobalTrackID::TPC); + const auto& svparam = o2::vertexing::SVertexerParams::Instance(); + if (svparam.mTPCTrackPhotonTune && isTPConly) { + mFitterV0.setMaxDZIni(svparam.mTPCTrackMaxDZIni); + mFitterV0.setMaxDXYIni(svparam.mTPCTrackMaxDXYIni); + mFitterV0.setMaxChi2(svparam.mTPCTrackMaxChi2); + mFitterV0.setCollinear(true); + } + int nCand = mFitterV0.process(seedP, seedN); + if (svparam.mTPCTrackPhotonTune && isTPConly) { // restore + // Reset immediately to the defaults + mFitterV0.setMaxDZIni(svparam.maxDZIni); + mFitterV0.setMaxDXYIni(svparam.maxDXYIni); + mFitterV0.setMaxChi2(svparam.maxChi2); + mFitterV0.setCollinear(false); + } + if (nCand == 0) { // discard this pair + return false; + } + const int cand = 0; + if (!mFitterV0.isPropagateTracksToVertexDone(cand) && !mFitterV0.propagateTracksToVertex(cand)) { + return false; + } + const auto& trPProp = mFitterV0.getTrack(0, cand); + const auto& trNProp = mFitterV0.getTrack(1, cand); + std::array pP{}, pN{}; + trPProp.getPxPyPzGlo(pP); + trNProp.getPxPyPzGlo(pN); + std::array pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]}; + auto p2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1] + pV0[2] * pV0[2]; + const auto& pv = recoData.getPrimaryVertex(id.getVertexID()); + const auto v0XYZ = mFitterV0.getPCACandidatePos(cand); + float dx = v0XYZ[0] - pv.getX(), dy = v0XYZ[1] - pv.getY(), dz = v0XYZ[2] - pv.getZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; + float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); + new (&v0) o2::dataformats::V0(v0XYZ, pV0, mFitterV0.calcPCACovMatrixFlat(cand), trPProp, trNProp); + v0.setDCA(mFitterV0.getChi2AtPCACandidate(cand)); + v0.setCosPA(cosPA); + return true; +} + +//__________________________________________________________ +void MatchITSTPCQC::finalize() +{ + + std::array title{"TPC", "ITS"}; + + // first we use denominators and nominators to set the TEfficiency; later they are scaled + + // some checks + for (int ti = 0; ti < matchType::SIZE; ++ti) { + for (int i = 0; i < mPtDen[ti]->GetNbinsX(); ++i) { + if (mPtDen[ti]->GetBinContent(i + 1) < mPtNum[ti]->GetBinContent(i + 1)) { + LOG(error) << title[ti] << ": bin " << i + 1 << " in [" << mPtNum[ti]->GetBinLowEdge(i + 1) << " , " << mPtNum[ti]->GetBinLowEdge(i + 1) + mPtNum[ti]->GetBinWidth(i + 1) << "]: mPtDen[i] = " << mPtDen[ti]->GetBinContent(i + 1) << ", mPtNum[i] = " << mPtNum[ti]->GetBinContent(i + 1); + } + } + for (int i = 0; i < mPtDen_noEta0[ti]->GetNbinsX(); ++i) { + if (mPtDen_noEta0[ti]->GetBinContent(i + 1) < mPtNum_noEta0[ti]->GetBinContent(i + 1)) { + LOG(error) << title[ti] << ": bin " << i + 1 << " in [" << mPtNum_noEta0[ti]->GetBinLowEdge(i + 1) << " , " << mPtNum_noEta0[ti]->GetBinLowEdge(i + 1) + mPtNum_noEta0[ti]->GetBinWidth(i + 1) << "]: mPtDen_noEta0[i] = " << mPtDen_noEta0[ti]->GetBinContent(i + 1) << ", mPtNum_noEta0[i] = " << mPtNum_noEta0[ti]->GetBinContent(i + 1); + } + } + for (int i = 0; i < mPhiDen[ti]->GetNbinsX(); ++i) { + if (mPhiDen[ti]->GetBinContent(i + 1) < mPhiNum[ti]->GetBinContent(i + 1)) { + LOG(error) << title[ti] << ": bin " << i + 1 << " in [" << mPhiNum[ti]->GetBinLowEdge(i + 1) << " , " << mPhiNum[ti]->GetBinLowEdge(i + 1) + mPhiNum[ti]->GetBinWidth(i + 1) << "]: mPhiDen[i] = " << mPhiDen[ti]->GetBinContent(i + 1) << ", mPhiNum[i] = " << mPhiNum[ti]->GetBinContent(i + 1); + } + } + for (int i = 0; i < mEtaDen[ti]->GetNbinsX(); ++i) { + if (mEtaDen[ti]->GetBinContent(i + 1) < mEtaNum[ti]->GetBinContent(i + 1)) { + LOG(error) << title[ti] << ": bin " << i + 1 << " in [" << mEtaNum[ti]->GetBinLowEdge(i + 1) << " , " << mEtaNum[ti]->GetBinLowEdge(i + 1) + mEtaNum[ti]->GetBinWidth(i + 1) << "]: mEtaDen[i] = " << mEtaDen[ti]->GetBinContent(i + 1) << ", mEtaNum[i] = " << mEtaNum[ti]->GetBinContent(i + 1); + } + } + + // filling the efficiency + setEfficiency(mFractionITSTPCmatch[ti], mPtNum[ti], mPtDen[ti]); + setEfficiency(mFractionITSTPCmatch_noEta0[ti], mPtNum_noEta0[ti], mPtDen_noEta0[ti]); + setEfficiency(mFractionITSTPCmatchPhi[ti], mPhiNum[ti], mPhiDen[ti]); + setEfficiency(mFractionITSTPCmatchEta[ti], mEtaNum[ti], mEtaDen[ti]); + setEfficiency(mFractionITSTPCmatchPhiVsPt[ti], mPhiVsPtNum[ti], mPhiVsPtDen[ti], true); + setEfficiency(mFractionITSTPCmatchEtaVsPt[ti], mEtaVsPtNum[ti], mEtaVsPtDen[ti], true); + setEfficiency(mFractionITSTPCmatch1OverPt[ti], m1OverPtNum[ti], m1OverPtDen[ti]); + setEfficiency(mFractionITSTPCmatchClsVsPt[ti], mClsVsPtNum[ti], mClsVsPtDen[ti], true); + setEfficiency(mFractionITSTPCmatchChi2VsPt[ti], mChi2VsPtNum[ti], mChi2VsPtDen[ti], true); + if (mUseTrkPID) { // Vs Tracking PID hypothesis + for (int j = 0; j < o2::track::PID::NIDs; ++j) { + setEfficiency(mFractionITSTPCmatchPtVsTrkPID[ti][j], mPtNumVsTrkPID[ti][j], mPtDenVsTrkPID[ti][j]); + setEfficiency(mFractionITSTPCmatchPhiVsTrkPID[ti][j], mPhiNumVsTrkPID[ti][j], mPhiDenVsTrkPID[ti][j]); + setEfficiency(mFractionITSTPCmatchEtaVsTrkPID[ti][j], mEtaNumVsTrkPID[ti][j], mEtaDenVsTrkPID[ti][j]); + } + } + if (mUseMC) { + setEfficiency(mFractionITSTPCmatchPhysPrim[ti], mPtPhysPrimNum[ti], mPtPhysPrimDen[ti]); + setEfficiency(mFractionITSTPCmatchPhiPhysPrim[ti], mPhiPhysPrimNum[ti], mPhiPhysPrimDen[ti]); + setEfficiency(mFractionITSTPCmatchEtaPhysPrim[ti], mEtaPhysPrimNum[ti], mEtaPhysPrimDen[ti]); + setEfficiency(mFractionITSTPCmatchPhysPrim1OverPt[ti], m1OverPtPhysPrimNum[ti], m1OverPtPhysPrimDen[ti]); + } + } + setEfficiency(mFractionITSTPCmatchDCArVsPt, mDCArVsPtNum, mDCArVsPtDen, true); + /* + mPtTPC->Scale(scaleFactTPC); + mPt->Scale(scaleFactITSTPC); + mPhiTPC->Scale(scaleFactTPC); + mPhi->Scale(scaleFactITSTPC); + if (mUseMC) { + mPtTPCPhysPrim->Scale(scaleFactTPC); + mPtPhysPrim->Scale(scaleFactITSTPC); + mPhiTPCPhysPrim->Scale(scaleFactTPC); + mPhiPhysPrim->Scale(scaleFactITSTPC); + } + mEta->Scale(scaleFactITSTPC); + mChi2Matching->Scale(scaleFactITSTPC); + mChi2Refit->Scale(scaleFactITSTPC); + //mTimeResVsPt->Scale(scaleFactITSTPC); // if to few entries, one sees nothing after normalization --> let's not normalize + */ +} + +//__________________________________________________________ + +void MatchITSTPCQC::setEfficiency(TEfficiency* eff, TH1* hnum, TH1* hden, bool is2D) +{ + if (eff == nullptr) { + LOG(fatal) << "Cannot get TEfficiency object "; + } + if (hnum == nullptr) { + LOG(fatal) << "Cannot get numerator histogram for TEfficiency object " << eff->GetName(); + } + if (hden == nullptr) { + LOG(fatal) << "Cannot get denominator histogram for TEfficiency object " << eff->GetName(); + } + + // we need to force to replace the total histogram, otherwise it will compare it to the previous passed one, and it might get an error of inconsistency in the bin contents + if constexpr (false) { // checking + bool bad{false}; + LOG(info) << "Setting efficiency " << eff->GetName() << " from " << hnum->GetName() << " and " << hden->GetName(); + LOG(info) << "Num " << hnum->GetName() << " " << hnum->GetNbinsX() << " " << hnum->GetNbinsY() << " with " << hnum->GetEntries() << " entries"; + LOG(info) << "Den " << hden->GetName() << " " << hden->GetNbinsX() << " " << hden->GetNbinsY() << " with " << hden->GetEntries() << " entries"; + if (hnum->GetDimension() != hden->GetDimension()) { + LOGP(warning, "Histograms have different dimensions (num={} to den={})", hnum->GetDimension(), hden->GetDimension()); + bad = true; + } + if (!TEfficiency::CheckBinning(*hnum, *hden)) { + LOGP(warning, "Histograms do not have a compatible binning"); + bad = true; + } + if (!is2D) { + for (int i = 1; i <= hden->GetNbinsX(); i++) { + if (hden->GetBinContent(i) < hnum->GetBinContent(i)) { + LOG(warning) << "bin " << i << " den: " << hden->GetBinContent(i) << " < num: " << hnum->GetBinContent(i) << " should be the opposite"; + bad = true; + } + } + } else { + for (int i = 1; i <= hden->GetNbinsX(); i++) { + for (int j = 1; j <= hden->GetNbinsY(); j++) { + if (hden->GetBinContent(i, j) < hnum->GetBinContent(i, j)) { + LOGP(warning, "bin {}/{} -> den: {} < num: {}", i, j, hden->GetBinContent(i, j), hnum->GetBinContent(i, j)); + bad = true; + } + } + } + } + if (bad) { + return; + } + } + // we need to force to replace the total histogram, otherwise it will compare it to the previous passed one, and it might get an error of inconsistency in the bin contents + if (!eff->SetTotalHistogram(*hden, "f")) { + LOG(fatal) << "Something went wrong when defining the efficiency denominator " << eff->GetName() << " from " << hnum->GetName(); + } + if (!eff->SetPassedHistogram(*hnum, "")) { + LOG(fatal) << "Something went wrong when defining the efficiency numerator " << eff->GetName() << " from " << hnum->GetName(); + } + if (is2D) { + eff->SetTitle(Form("%s;%s;%s;%s", eff->GetTitle(), hnum->GetXaxis()->GetTitle(), hnum->GetYaxis()->GetTitle(), "Efficiency")); + } else { + eff->SetTitle(Form("%s;%s;%s", eff->GetTitle(), hnum->GetXaxis()->GetTitle(), "Efficiency")); + } +} + +//__________________________________________________________ + +void MatchITSTPCQC::getHistos(TObjArray& objar) +{ + + for (int i = 0; i < matchType::SIZE; ++i) { + objar.Add(mPtNum[i]); + objar.Add(mPtDen[i]); + objar.Add(mFractionITSTPCmatch[i]); + + objar.Add(mPtNum_noEta0[i]); + objar.Add(mPtDen_noEta0[i]); + objar.Add(mFractionITSTPCmatch_noEta0[i]); + + objar.Add(mPtPhysPrimNum[i]); + objar.Add(mPtPhysPrimDen[i]); + objar.Add(mFractionITSTPCmatchPhysPrim[i]); + + objar.Add(mPhiNum[i]); + objar.Add(mPhiDen[i]); + objar.Add(mFractionITSTPCmatchPhi[i]); + + if (mUseTrkPID) { // Vs Tracking PID hypothesis + for (int j = 0; j < o2::track::PID::NIDs; ++j) { + // Pt + objar.Add(mPtNumVsTrkPID[i][j]); + objar.Add(mPtDenVsTrkPID[i][j]); + objar.Add(mFractionITSTPCmatchPtVsTrkPID[i][j]); + // Phi + objar.Add(mPhiNumVsTrkPID[i][j]); + objar.Add(mPhiDenVsTrkPID[i][j]); + objar.Add(mFractionITSTPCmatchPhiVsTrkPID[i][j]); + // Eta + objar.Add(mEtaNumVsTrkPID[i][j]); + objar.Add(mEtaDenVsTrkPID[i][j]); + objar.Add(mFractionITSTPCmatchEtaVsTrkPID[i][j]); + } + } + + objar.Add(mPhiPhysPrimNum[i]); + objar.Add(mPhiPhysPrimDen[i]); + objar.Add(mFractionITSTPCmatchPhiPhysPrim[i]); + + objar.Add(mPhiVsPtNum[i]); + objar.Add(mPhiVsPtDen[i]); + objar.Add(mFractionITSTPCmatchPhiVsPt[i]); + + objar.Add(mEtaNum[i]); + objar.Add(mEtaDen[i]); + objar.Add(mFractionITSTPCmatchEta[i]); + + objar.Add(mEtaPhysPrimNum[i]); + objar.Add(mEtaPhysPrimDen[i]); + objar.Add(mFractionITSTPCmatchEtaPhysPrim[i]); + + objar.Add(mEtaVsPtNum[i]); + objar.Add(mEtaVsPtDen[i]); + objar.Add(mFractionITSTPCmatchEtaVsPt[i]); + + objar.Add(mClsVsPtNum[i]); + objar.Add(mClsVsPtDen[i]); + objar.Add(mFractionITSTPCmatchClsVsPt[i]); + + objar.Add(mChi2VsPtNum[i]); + objar.Add(mChi2VsPtDen[i]); + objar.Add(mFractionITSTPCmatchChi2VsPt[i]); + + objar.Add(m1OverPtNum[i]); + objar.Add(m1OverPtDen[i]); + objar.Add(mFractionITSTPCmatch1OverPt[i]); + + objar.Add(m1OverPtPhysPrimNum[i]); + objar.Add(m1OverPtPhysPrimDen[i]); + objar.Add(mFractionITSTPCmatchPhysPrim1OverPt[i]); + } + objar.Add(mChi2Matching); + objar.Add(mChi2Refit); + objar.Add(mTimeResVsPt); + objar.Add(mResidualPt); + objar.Add(mResidualPhi); + objar.Add(mResidualEta); + objar.Add(mDCAr); + objar.Add(mDCArVsPtNum); + objar.Add(mDCArVsPtDen); + objar.Add(mFractionITSTPCmatchDCArVsPt); + + // V0 + objar.Add(mK0MassVsPt); +} diff --git a/Detectors/GlobalTracking/CMakeLists.txt b/Detectors/GlobalTracking/CMakeLists.txt index cc62bac02a1cb..2aaad95eba313 100644 --- a/Detectors/GlobalTracking/CMakeLists.txt +++ b/Detectors/GlobalTracking/CMakeLists.txt @@ -20,10 +20,10 @@ o2_add_library(GlobalTracking src/MatchCosmicsParams.cxx src/MatchGlobalFwd.cxx src/MatchGlobalFwdAssessment.cxx - src/MatchITSTPCQC.cxx - src/ITSTPCMatchingQCParams.cxx src/MatchGlobalFwdParam.cxx src/MatchTOFParams.cxx + src/MatchITSTPCQC.cxx + src/ITSTPCMatchingQCParams.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsTPC O2::DataFormatsITSMFT @@ -63,10 +63,10 @@ o2_target_root_dictionary(GlobalTracking include/GlobalTracking/MatchHMP.h include/GlobalTracking/MatchCosmics.h include/GlobalTracking/MatchCosmicsParams.h - include/GlobalTracking/MatchITSTPCQC.h - include/GlobalTracking/ITSTPCMatchingQCParams.h include/GlobalTracking/TrackMethods.h - include/GlobalTracking/TrackCuts.h) + include/GlobalTracking/TrackCuts.h + include/GlobalTracking/MatchITSTPCQC.h + include/GlobalTracking/ITSTPCMatchingQCParams.h) if (OpenMP_CXX_FOUND) diff --git a/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h b/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h index cd463aedf963e..8125147add297 100644 --- a/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h +++ b/Detectors/GlobalTracking/src/GlobalTrackingLinkDef.h @@ -29,8 +29,6 @@ #pragma link C++ class o2::globaltracking::MatchTOFParams + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::globaltracking::MatchTOFParams> + ; -#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::globaltracking::ITSTPCMatchingQCParams> + ; - #pragma link C++ class o2::globaltracking::GloFwdAssessment + ; #pragma link C++ class o2::globaltracking::GlobalFwdMatchingParam + ; @@ -45,4 +43,6 @@ #pragma link C++ class std::vector < std::tuple < float, float, float>> + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::globaltracking::ITSTPCMatchingQCParams> + ; + #endif diff --git a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt index 6b0c5a7285c15..1f530f30d238a 100644 --- a/Detectors/GlobalTrackingWorkflow/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/CMakeLists.txt @@ -49,6 +49,7 @@ o2_add_library(GlobalTrackingWorkflow O2::SimulationDataFormat O2::DetectorsVertexing O2::StrangenessTracking) + o2_add_executable(driver-workflow COMPONENT_NAME reader SOURCES src/reader-driver-workflow.cxx diff --git a/Detectors/GlobalTrackingWorkflow/qc/CMakeLists.txt b/Detectors/GlobalTrackingWorkflow/qc/CMakeLists.txt index 4a72fb8cede77..cca69282d20cf 100644 --- a/Detectors/GlobalTrackingWorkflow/qc/CMakeLists.txt +++ b/Detectors/GlobalTrackingWorkflow/qc/CMakeLists.txt @@ -14,9 +14,10 @@ o2_add_library(GlobalTrackingWorkflowQC PUBLIC_LINK_LIBRARIES O2::DataFormatsGlobalTracking O2::GlobalTracking ROOT::Core + O2::GLOQC ) -o2_add_executable(match-qc +o2_add_executable(matching-qc COMPONENT_NAME itstpc SOURCES src/itstpc-matching-qc-workflow.cxx PUBLIC_LINK_LIBRARIES O2::GlobalTrackingWorkflowQC diff --git a/Detectors/GlobalTrackingWorkflow/qc/include/GlobalTrackingWorkflowQC/ITSTPCMatchingQCSpec.h b/Detectors/GlobalTrackingWorkflow/qc/include/GlobalTrackingWorkflowQC/ITSTPCMatchingQCSpec.h index 48d96921287c6..6ffd38c8a1c1b 100644 --- a/Detectors/GlobalTrackingWorkflow/qc/include/GlobalTrackingWorkflowQC/ITSTPCMatchingQCSpec.h +++ b/Detectors/GlobalTrackingWorkflow/qc/include/GlobalTrackingWorkflowQC/ITSTPCMatchingQCSpec.h @@ -17,7 +17,7 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/Task.h" -#include "GlobalTracking/MatchITSTPCQC.h" +#include "GLOQC/MatchITSTPCQC.h" #include "DetectorsBase/GRPGeomHelper.h" using namespace o2::framework; @@ -29,7 +29,7 @@ namespace globaltracking class ITSTPCMatchingQCDevice : public Task { public: - ITSTPCMatchingQCDevice(std::shared_ptr dr, std::shared_ptr req, bool useMC) : mDataRequest(dr), mCCDBRequest(req), mUseMC(useMC){}; + ITSTPCMatchingQCDevice(std::shared_ptr dr, std::shared_ptr req, bool useMC, bool doK0QC, std::string trkSources) : mDataRequest(dr), mCCDBRequest(req), mUseMC(useMC), mDoK0QC(doK0QC), mTrkSources(trkSources){}; void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; void endOfStream(o2::framework::EndOfStreamContext& ec) final; @@ -37,17 +37,19 @@ class ITSTPCMatchingQCDevice : public Task private: void sendOutput(DataAllocator& output); - std::unique_ptr mMatchITSTPCQC; + std::unique_ptr mMatchITSTPCQC; std::shared_ptr mDataRequest; std::shared_ptr mCCDBRequest; bool mUseMC = true; + bool mDoK0QC = true; + std::string mTrkSources = "ITS,TPC,ITS-TPC"; }; } // namespace globaltracking namespace framework { -DataProcessorSpec getITSTPCMatchingQCDevice(bool useMC); +DataProcessorSpec getITSTPCMatchingQCDevice(bool useMC, bool doK0QC, std::string trkSources); } // namespace framework } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/qc/src/ITSTPCMatchingQCSpec.cxx b/Detectors/GlobalTrackingWorkflow/qc/src/ITSTPCMatchingQCSpec.cxx index 7b48a6c30ffbc..f1de9698d9e70 100644 --- a/Detectors/GlobalTrackingWorkflow/qc/src/ITSTPCMatchingQCSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/qc/src/ITSTPCMatchingQCSpec.cxx @@ -15,10 +15,11 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/Logger.h" #include "GlobalTrackingWorkflowQC/ITSTPCMatchingQCSpec.h" -#include "GlobalTracking/ITSTPCMatchingQCParams.h" +#include "GLOQC/ITSTPCMatchingQCParams.h" #include "DataFormatsGlobalTracking/RecoContainer.h" #include "DetectorsBase/Propagator.h" - +#include "DetectorsVertexing/SVertexerParams.h" +#include "Framework/CCDBParamSpec.h" #include "CommonUtils/NameConf.h" #include @@ -31,20 +32,26 @@ namespace globaltracking void ITSTPCMatchingQCDevice::init(InitContext& /*ic*/) { - const o2::globaltracking::ITSTPCMatchingQCParams& params = o2::globaltracking::ITSTPCMatchingQCParams::Instance(); + const o2::gloqc::ITSTPCMatchingQCParams& params = o2::gloqc::ITSTPCMatchingQCParams::Instance(); - mMatchITSTPCQC = std::make_unique(); - mMatchITSTPCQC->init(); + mMatchITSTPCQC = std::make_unique(); mMatchITSTPCQC->setDataRequest(mDataRequest); + mMatchITSTPCQC->setTrkSources(o2::dataformats::GlobalTrackID::getSourcesMask(mTrkSources)); mMatchITSTPCQC->setPtCut(params.minPtCut); mMatchITSTPCQC->setEtaCut(params.etaCut); mMatchITSTPCQC->setMinNTPCClustersCut(params.minNTPCClustersCut); mMatchITSTPCQC->setMinDCAtoBeamPipeDistanceCut(params.minDCACut); mMatchITSTPCQC->setMinDCAtoBeamPipeYCut(params.minDCACutY); + mMatchITSTPCQC->setCutK0Mass(params.cutK0Mass); + mMatchITSTPCQC->setMaxK0Eta(params.maxEtaK0); o2::base::GRPGeomHelper::instance().setRequest(mCCDBRequest); if (mUseMC) { mMatchITSTPCQC->setUseMC(mUseMC); } + if (mDoK0QC) { + mMatchITSTPCQC->setDoK0QC(mDoK0QC); + } + mMatchITSTPCQC->init(); } //_____________________________________________________________ @@ -52,6 +59,11 @@ void ITSTPCMatchingQCDevice::init(InitContext& /*ic*/) void ITSTPCMatchingQCDevice::run(o2::framework::ProcessingContext& pc) { o2::base::GRPGeomHelper::instance().checkUpdates(pc); + static bool wasSVParamInitialized = false; + if (!wasSVParamInitialized) { + pc.inputs().get("SVParam"); + wasSVParamInitialized = true; + } mMatchITSTPCQC->run(pc); } @@ -87,6 +99,10 @@ void ITSTPCMatchingQCDevice::finaliseCCDB(ConcreteDataMatcher& matcher, void* ob if (o2::base::GRPGeomHelper::instance().finaliseCCDB(matcher, obj)) { return; } + if (matcher == ConcreteDataMatcher("GLO", "SVPARAM", 0)) { + LOG(info) << "SVertexer Params updated from ccdb - but it should not happen... PLEASE CHECK"; + return; + } } } // namespace globaltracking @@ -94,14 +110,18 @@ namespace framework { using GID = o2::dataformats::GlobalTrackID; -DataProcessorSpec getITSTPCMatchingQCDevice(bool useMC) +DataProcessorSpec getITSTPCMatchingQCDevice(bool useMC, bool doK0QC, std::string trkSources) { std::vector outputs; outputs.emplace_back("GLO", "ITSTPCMATCHQC", 0, Lifetime::Sporadic); auto dataRequest = std::make_shared(); - GID::mask_t mSrc = GID::getSourcesMask("TPC,ITS-TPC"); - dataRequest->requestTracks(mSrc, useMC); + GID::mask_t srcMask = GID::getSourcesMask(trkSources); + dataRequest->requestTracks(srcMask, useMC); + if (doK0QC) { + dataRequest->requestPrimaryVertices(useMC); + dataRequest->requestSecondaryVertices(useMC); + } auto ccdbRequest = std::make_shared(false, // orbitResetTime false, // GRPECS=true false, // GRPLHCIF @@ -109,12 +129,14 @@ DataProcessorSpec getITSTPCMatchingQCDevice(bool useMC) false, // askMatLUT o2::base::GRPGeomRequest::None, // geometry dataRequest->inputs); + + dataRequest->inputs.emplace_back("SVParam", "GLO", "SVPARAM", 0, Lifetime::Condition, ccdbParamSpec("GLO/Config/SVertexerParam")); return DataProcessorSpec{ - "itstpc-matching-qc", - dataRequest->inputs, - outputs, - AlgorithmSpec{adaptFromTask(dataRequest, ccdbRequest, useMC)}, - Options{{}}}; + .name = "itstpc-matching-qc", + .inputs = dataRequest->inputs, + .outputs = outputs, + .algorithm = AlgorithmSpec{adaptFromTask(dataRequest, ccdbRequest, useMC, doK0QC, trkSources)}, + }; } } // namespace framework diff --git a/Detectors/GlobalTrackingWorkflow/qc/src/itstpc-matching-qc-workflow.cxx b/Detectors/GlobalTrackingWorkflow/qc/src/itstpc-matching-qc-workflow.cxx index 16bd2d78d77e2..e3107bedbf1d4 100644 --- a/Detectors/GlobalTrackingWorkflow/qc/src/itstpc-matching-qc-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/qc/src/itstpc-matching-qc-workflow.cxx @@ -21,6 +21,8 @@ void customize(std::vector& workflowOptions) // option allowing to set parameters std::vector options{ {"disable-mc", o2::framework::VariantType::Bool, false, {"disable use of MC information even if available"}}, + {"disable-k0-qc", o2::framework::VariantType::Bool, false, {"disable K0 QC"}}, + {"track-sources", o2::framework::VariantType::String, "ITS,TPC,ITS-TPC", {"comma-separated list of track sources to use"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}}; std::swap(workflowOptions, options); } @@ -33,12 +35,14 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) { // Update the (declared) parameters if changed from the command line o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); - // write the configuration used for the workflow - o2::conf::ConfigurableParam::writeINI("o2-itstpc-matching-qc.ini"); LOG(info) << "ITSTPC matching QC: disable-mc = " << configcontext.options().get("disable-mc"); auto useMC = !configcontext.options().get("disable-mc"); + LOG(info) << "ITSTPC matching QC: disable-k0-qc = " << configcontext.options().get("disable-k0-qc"); + auto doK0QC = !configcontext.options().get("disable-k0-qc"); + LOG(info) << "ITSTPC matching QC: track-sources = " << configcontext.options().get("track-sources"); + std::string trkSources = configcontext.options().get("track-sources"); WorkflowSpec specs; - specs.emplace_back(getITSTPCMatchingQCDevice(useMC)); + specs.emplace_back(getITSTPCMatchingQCDevice(useMC, doK0QC, trkSources)); return specs; } From bc32b5a3fe4ca3ca40b41233e1ee42af2ce3d994 Mon Sep 17 00:00:00 2001 From: Ruben Shahoyan Date: Thu, 13 Jun 2024 13:24:02 +0200 Subject: [PATCH 0312/2997] rct-updater discards TFs with creationtime-vs-orbit inonsistencies (#13215) --- .../workflows/src/rct-updater-workflow.cxx | 34 ++++++++++++++----- .../full-system-test/aggregator-workflow.sh | 3 +- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Detectors/GRP/workflows/src/rct-updater-workflow.cxx b/Detectors/GRP/workflows/src/rct-updater-workflow.cxx index 8b75091520724..624e89ec4076d 100644 --- a/Detectors/GRP/workflows/src/rct-updater-workflow.cxx +++ b/Detectors/GRP/workflows/src/rct-updater-workflow.cxx @@ -48,6 +48,8 @@ class RCTUpdaterSpec : public o2::framework::Task } else { LOGP(warn, "No ccdb server provided, no RCT update will be done"); } + mTimeToleranceMS = ic.options().get("max-diff-orbit-creationtime"); + mMaxWarnings = ic.options().get("max-warn-tf-discard"); } void run(ProcessingContext& pc) final @@ -83,15 +85,25 @@ class RCTUpdaterSpec : public o2::framework::Task } } if (mEnabled) { - if (tinfo.firstTForbit < mMinOrbit) { - mMinOrbit = tinfo.firstTForbit; - } - if (tinfo.firstTForbit > mMaxOrbit) { - mMaxOrbit = tinfo.firstTForbit; - } - if (tinfo.tfCounter > mLastTFUpdate + mUpdateIntervalTF) { // need to update - mLastTFUpdate = tinfo.tfCounter; - updateRCT(); + // make sure that the orbit makes sense, since sometimes at the EOR bogus TFs are sent. + long ts = mOrbitReset + long(tinfo.firstTForbit * o2::constants::lhc::LHCOrbitMUS * 1e-3); + if (mTimeToleranceMS > 0 && std::abs(int64_t(tinfo.creation) - ts) < mTimeToleranceMS) { + if (tinfo.firstTForbit < mMinOrbit) { + mMinOrbit = tinfo.firstTForbit; + } + if (tinfo.firstTForbit > mMaxOrbit) { + mMaxOrbit = tinfo.firstTForbit; + } + if (tinfo.tfCounter > mLastTFUpdate + mUpdateIntervalTF) { // need to update + mLastTFUpdate = tinfo.tfCounter; + updateRCT(); + } + } else { + static int nWarn = 0; + if (nWarn < mMaxWarnings) { + nWarn++; + LOGP(warn, "timestamp {} for orbit {} and orbit reset time {} differs by >{} from the TF creation time {}, ignore TF {}", ts, tinfo.firstTForbit, mOrbitReset / 1000, mTimeToleranceMS, tinfo.creation, tinfo.tfCounter); + } } } } @@ -148,9 +160,11 @@ class RCTUpdaterSpec : public o2::framework::Task uint32_t mMinOrbit = 0xffffffff; uint32_t mMaxOrbit = 0; uint32_t mLastTFUpdate = 0; + long mTimeToleranceMS = 5000; long mOrbitReset = 0; int mRunNumber = 0; int mNHBFPerTF = 32; + int mMaxWarnings = 0; std::shared_ptr mGGCCDBRequest; std::unique_ptr mCCDBApi; }; @@ -183,6 +197,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) AlgorithmSpec{adaptFromTask(ggRequest)}, Options{ {"update-interval", VariantType::Float, 1.f, {"update every ... seconds"}}, + {"max-diff-orbit-creationtime", VariantType::Int, -1, {"max difference between TF creation-time and orbit-time to discard TF, do not check if negative"}}, + {"max-warn-tf-discard", VariantType::Int, 10, {"max N warnings about discarding bad TFs"}}, {"ccdb-server", VariantType::String, "http://ccdb-test.cern.ch:8080", {"CCDB to update"}}}}); return specs; } diff --git a/prodtests/full-system-test/aggregator-workflow.sh b/prodtests/full-system-test/aggregator-workflow.sh index 2c0a4de6dcf70..4bd093b5a7fc6 100755 --- a/prodtests/full-system-test/aggregator-workflow.sh +++ b/prodtests/full-system-test/aggregator-workflow.sh @@ -220,7 +220,8 @@ fi if [[ $AGGREGATOR_TASKS == BARREL_TF ]] || [[ $AGGREGATOR_TASKS == ALL ]]; then # RCT updater if [[ ${CALIB_RCT_UPDATER:-} == 1 ]]; then - add_W o2-rct-updater-workflow "--ccdb-server $CCDB_POPULATOR_UPLOAD_PATH" + [[ -z ${TDIFFCHECK:-} ]] && [[ $EPNSYNCMODE == 1 ]] && TDIFFCHECK=15000 + add_W o2-rct-updater-workflow "--ccdb-server $CCDB_POPULATOR_UPLOAD_PATH --max-diff-orbit-creationtime ${TDIFFCHECK:--1}" fi # PrimaryVertex if [[ $CALIB_PRIMVTX_MEANVTX == 1 ]]; then From e7065d9ceb6d05d71423237cee4d93f88d15d680 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 4 Jun 2024 16:46:29 +0200 Subject: [PATCH 0313/2997] Add shared cluster number to debug output --- Detectors/GlobalTracking/src/MatchTPCITS.cxx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Detectors/GlobalTracking/src/MatchTPCITS.cxx b/Detectors/GlobalTracking/src/MatchTPCITS.cxx index afb26ddcf47c9..3528a94b1adea 100644 --- a/Detectors/GlobalTracking/src/MatchTPCITS.cxx +++ b/Detectors/GlobalTracking/src/MatchTPCITS.cxx @@ -2831,9 +2831,22 @@ void MatchTPCITS::dumpTPCOrig(bool acc, int tpcIndex) ///< fill debug tree for TPC original tracks (passing pT cut) mTimer[SWDBG].Start(false); const auto& tpcOrig = mTPCTracksArray[tpcIndex]; - uint8_t clSect = 0, clRow = 0; + uint8_t clSect = 0, clRow = 0, prevRow = 0xff; uint32_t clIdx = 0; - tpcOrig.getClusterReference(mTPCTrackClusIdx, tpcOrig.getNClusterReferences() - 1, clSect, clRow, clIdx); + int nshared = 0; + std::array shMap{}; + bool prevRawShared = false; + for (int i = 0; i < tpcOrig.getNClusterReferences(); i++) { + tpcOrig.getClusterReference(mTPCTrackClusIdx, i, clSect, clRow, clIdx); + unsigned int absoluteIndex = mTPCClusterIdxStruct->clusterOffset[clSect][clRow] + clIdx; + if (mTPCRefitterShMap[absoluteIndex] & GPUCA_NAMESPACE::gpu::GPUTPCGMMergedTrackHit::flagShared) { + if (!(prevRow == clRow && prevRawShared)) { + nshared++; + } + prevRow = clRow; + prevRawShared = true; + } + } int tb = tpcOrig.getTime0() * mNTPCOccBinLengthInv; float mltTPC = tb < 0 ? mTBinClOcc[0] : (tb >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[tb]); (*mDBGOut) << "tpcOrig" @@ -2842,6 +2855,7 @@ void MatchTPCITS::dumpTPCOrig(bool acc, int tpcIndex) << "acc=" << acc << "chi2TPC=" << tpcOrig.getChi2() << "nClus=" << tpcOrig.getNClusters() + << "nShared=" << nshared << "time0=" << tpcOrig.getTime0() << "trc=" << ((o2::track::TrackParCov&)tpcOrig) << "minRow=" << clRow From ca9d1a7d54f800b2252f11b136c8911221178e7e Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 13 Jun 2024 10:41:49 +0200 Subject: [PATCH 0314/2997] Fix timeout message and report used value --- CCDB/src/CcdbApi.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index 98e0adf7611c3..72db59af50b73 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -260,8 +260,8 @@ void CcdbApi::init(std::string const& host) LOGP(debug, "Curl timeouts are set to: download={:2}, upload={:2} seconds", mCurlTimeoutDownload, mCurlTimeoutUpload); - LOGP(info, "Init CcdApi with UserAgentID: {}, Host: {}{}", mUniqueAgentID, host, - mInSnapshotMode ? "(snapshot readonly mode)" : snapshotReport.c_str()); + LOGP(info, "Init CcdApi with UserAgentID: {}, Host: {}{}, Curl timeouts: upload:{} download:{}", mUniqueAgentID, host, + mInSnapshotMode ? "(snapshot readonly mode)" : snapshotReport.c_str(), mCurlTimeoutUpload, mCurlTimeoutDownload); } void CcdbApi::runDownloaderLoop(bool noWait) @@ -441,7 +441,7 @@ int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::strin /* Check for errors */ if (res != CURLE_OK) { if (res == CURLE_OPERATION_TIMEDOUT) { - LOGP(alarm, "curl_easy_perform() timed out. Consider increasing the timeout using the env var `ALICEO2_CCDB_CURL_TIMEOUT` (seconds)"); + LOGP(alarm, "curl_easy_perform() timed out. Consider increasing the timeout using the env var `ALICEO2_CCDB_CURL_TIMEOUT_UPLOAD` (seconds), current one is {}", mCurlTimeoutUpload); } else { // generic message LOGP(alarm, "curl_easy_perform() failed: {}", curl_easy_strerror(res)); } From 2963f34ded9f13ad595a57bb9c822388442c9056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20von=20Haller?= Date: Thu, 13 Jun 2024 08:58:53 +0200 Subject: [PATCH 0315/2997] Add include to please ROOT 6.32 --- Framework/Core/include/Framework/HistogramRegistry.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 1bd3bf9ece00c..839ad4fd552ff 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -25,6 +25,7 @@ #include #include +#include #include From 1b1afadc0fecd7b644c2373f7eacee4eee23a7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9l=C3=A9my=20von=20Haller?= Date: Thu, 13 Jun 2024 10:53:55 +0200 Subject: [PATCH 0316/2997] formatting --- Framework/Core/include/Framework/HistogramRegistry.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/HistogramRegistry.h b/Framework/Core/include/Framework/HistogramRegistry.h index 839ad4fd552ff..c88525368e88a 100644 --- a/Framework/Core/include/Framework/HistogramRegistry.h +++ b/Framework/Core/include/Framework/HistogramRegistry.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include From f8b68b366913fe0dddd7148b4a0abddd97416d4d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 14 Jun 2024 10:56:31 +0200 Subject: [PATCH 0317/2997] DPL: correctly handle aod-metadata-table if more than one workflow is involved --- Framework/Core/src/Plugin.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/Plugin.cxx b/Framework/Core/src/Plugin.cxx index 2298896821dab..2edf2e62a3633 100644 --- a/Framework/Core/src/Plugin.cxx +++ b/Framework/Core/src/Plugin.cxx @@ -14,6 +14,7 @@ #include "Framework/Logger.h" #include "Framework/Capability.h" #include "Framework/Signpost.h" +#include "Framework/VariantJSONHelpers.h" #include O2_DECLARE_DYNAMIC_LOG(capabilities); @@ -86,7 +87,13 @@ struct DiscoverMetadataInCommandLine : o2::framework::ConfigDiscoveryPlugin { std::string value = argv[i + 1]; O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInCommandLine", "Found %{public}s with value %{public}s.", key.c_str(), value.c_str()); - results.push_back(ConfigParamSpec{key, VariantType::String, value, {"Metadata in command line"}}); + if (key == "aod-metadata-tables") { + std::stringstream is(value); + auto arrayValue = VariantJSONHelpers::read(is); + results.push_back(ConfigParamSpec{key, VariantType::ArrayString, arrayValue, {"Metadata in command line"}}); + } else { + results.push_back(ConfigParamSpec{key, VariantType::String, value, {"Metadata in command line"}}); + } } return results; }}; From d909c3dafcea573f302419f5e510ece2c33d9a76 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:19:16 +0200 Subject: [PATCH 0318/2997] DPL: improve Graphviz topology visualization - General refresh of the code - Add labels to better debug issues with expendable tasks --- Framework/Core/src/GraphvizHelpers.cxx | 22 ++++++++++++++-------- Framework/Core/src/GraphvizHelpers.h | 15 ++++++--------- Framework/Core/src/runDataProcessing.cxx | 6 +----- Framework/Core/test/test_Graphviz.cxx | 14 +++++++------- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/Framework/Core/src/GraphvizHelpers.cxx b/Framework/Core/src/GraphvizHelpers.cxx index 47411235faba6..3bae0bdaef598 100644 --- a/Framework/Core/src/GraphvizHelpers.cxx +++ b/Framework/Core/src/GraphvizHelpers.cxx @@ -14,9 +14,7 @@ #include #include -namespace o2 -{ -namespace framework +namespace o2::framework { namespace @@ -25,13 +23,22 @@ std::string quote(std::string const& s) { return R"(")" + s + R"(")"; } } // namespace /// Helper to dump a workflow as a graphviz file -void GraphvizHelpers::dumpDataProcessorSpec2Graphviz(std::ostream& out, const std::vector& specs) +void GraphvizHelpers::dumpDataProcessorSpec2Graphviz(std::ostream& out, const std::vector& specs, + std::vector> const& edges) { out << "digraph structs {\n"; out << " node[shape=record]\n"; for (auto& spec : specs) { - out << R"( struct [label=")" << spec.name << R"("];)" - << "\n"; + std::string labels = " xlabel=\""; + for (auto& label : spec.labels) { + labels += labels == " xlabel=\"" ? "" : ","; + labels += label.value; + } + labels += "\""; + out << fmt::format(" \"{}\" [label=\"{}\"{}];\n", spec.name, spec.name, labels != " xlabel=\"\"" ? labels : ""); + } + for (auto& e : edges) { + out << fmt::format(" \"{}\" -> \"{}\"\n", specs[e.first].name, specs[e.second].name); } out << "}\n"; } @@ -86,5 +93,4 @@ void GraphvizHelpers::dumpDeviceSpec2Graphviz(std::ostream& out, const std::vect out << "}\n"; } -} // namespace framework -} // namespace o2 +} // namespace o2::framework diff --git a/Framework/Core/src/GraphvizHelpers.h b/Framework/Core/src/GraphvizHelpers.h index 1f6fadfac10ba..194cfdaddcd67 100644 --- a/Framework/Core/src/GraphvizHelpers.h +++ b/Framework/Core/src/GraphvizHelpers.h @@ -8,25 +8,22 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef FRAMEWORK_GRAPHVIZHELPERS_H -#define FRAMEWORK_GRAPHVIZHELPERS_H +#ifndef O2_FRAMEWORK_GRAPHVIZHELPERS_H +#define O2_FRAMEWORK_GRAPHVIZHELPERS_H #include "Framework/WorkflowSpec.h" #include "Framework/DeviceSpec.h" #include #include -namespace o2 -{ -namespace framework +namespace o2::framework { struct GraphvizHelpers { using Devices = std::vector; - static void dumpDataProcessorSpec2Graphviz(std::ostream&, const WorkflowSpec& specs); + static void dumpDataProcessorSpec2Graphviz(std::ostream&, const WorkflowSpec& specs, std::vector> const& edges = {}); static void dumpDeviceSpec2Graphviz(std::ostream&, const Devices& specs); }; -} // namespace framework -} // namespace o2 -#endif // FRAMEWORK_GRAPHVIZHELPERS_H +} // namespace o2::framework +#endif // O2_FRAMEWORK_GRAPHVIZHELPERS_H diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 137f17152cc01..89737483fc813 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -2722,11 +2722,7 @@ std::string debugTopoInfo(std::vector const& specs, for (auto& d : specs) { out << "- " << d.name << std::endl; } - out << "digraph G {\n"; - for (auto& e : edges) { - out << fmt::format(" \"{}\" -> \"{}\"\n", specs[e.first].name, specs[e.second].name); - } - out << "}\n"; + GraphvizHelpers::dumpDataProcessorSpec2Graphviz(out, specs, edges); return out.str(); } diff --git a/Framework/Core/test/test_Graphviz.cxx b/Framework/Core/test/test_Graphviz.cxx index 1d5774630451a..aaebc2b62d1ef 100644 --- a/Framework/Core/test/test_Graphviz.cxx +++ b/Framework/Core/test/test_Graphviz.cxx @@ -89,10 +89,10 @@ TEST_CASE("TestGraphviz") std::ostringstream str; auto expectedResult = R"EXPECTED(digraph structs { node[shape=record] - struct [label="A"]; - struct [label="B"]; - struct [label="C"]; - struct [label="D"]; + "A" [label="A"]; + "B" [label="B"]; + "C" [label="C"]; + "D" [label="D"]; } )EXPECTED"; GraphvizHelpers::dumpDataProcessorSpec2Graphviz(str, workflow); @@ -130,9 +130,9 @@ TEST_CASE("TestGraphvizWithPipeline") std::ostringstream str; auto expectedResult = R"EXPECTED(digraph structs { node[shape=record] - struct [label="A"]; - struct [label="B"]; - struct [label="C"]; + "A" [label="A"]; + "B" [label="B"]; + "C" [label="C"]; } )EXPECTED"; GraphvizHelpers::dumpDataProcessorSpec2Graphviz(str, workflow); From 7f7b2c2d70697d54885a1632b471c850f46baa4f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 31 May 2024 20:03:26 +0200 Subject: [PATCH 0319/2997] dpl-workflow: Use more conservative memory estimation also for async reco on the GPU --- prodtests/full-system-test/dpl-workflow.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 6ae605e86cd58..f84159a312f2b 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -215,13 +215,16 @@ if [[ $EPNSYNCMODE == 1 ]]; then fi fi if [[ $SYNCRAWMODE == 1 ]]; then - GPU_CONFIG_KEY+="GPU_proc.tpcIncreasedMinClustersPerRow=500000;GPU_proc.ignoreNonFatalGPUErrors=1;GPU_proc.throttleAlarms=1;GPU_proc.conservativeMemoryEstimate=1;" + GPU_CONFIG_KEY+="GPU_proc.tpcIncreasedMinClustersPerRow=500000;GPU_proc.ignoreNonFatalGPUErrors=1;GPU_proc.throttleAlarms=1;" if [[ $RUNTYPE == "PHYSICS" || $RUNTYPE == "COSMICS" || $RUNTYPE == "TECHNICAL" ]]; then GPU_CONFIG_KEY+="GPU_global.checkFirstTfOrbit=1;" fi # option for avoinding masking problematic channels from previous calibrations TOF_CONFIG+=" --for-calib" fi +if [[ $SYNCRAWMODE == 1 ]] || [[ $SYNCMODE == 0 && $CTFINPUT == 1 && $GPUTYPE != "CPU" ]]; then + GPU_CONFIG_KEY+="GPU_proc.conservativeMemoryEstimate=1;" +fi if [[ $SYNCMODE == 1 && "0${ED_NO_ITS_ROF_FILTER:-}" != "01" && $BEAMTYPE == "PbPb" ]] && has_detector ITS; then EVE_CONFIG+=" --filter-its-rof" From 0ec1a04a5ce2fda4284b3aa23f13c0dc3f7eced1 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 5 Jun 2024 00:03:05 +0200 Subject: [PATCH 0320/2997] modify TPC sector tracklet selection --- GPU/GPUTracking/Definitions/GPUSettingsList.h | 2 ++ GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 1dcdffb558608..fba8539bc4fc7 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -99,6 +99,8 @@ AddOptionRTC(trackMergerFactor2K, float, 2.0f * 2.0f, "", 0, "factor2K for track AddOptionRTC(trackMergerFactor2General, float, 3.5f * 3.5f, "", 0, "General factor for track merging") AddOptionRTC(rejectEdgeClustersMargin, float, 0.f, "", 0, "Margin in cm of Y position when rejecting edge clusters based on uncorrected track Y") AddOptionRTC(rejectEdgeClustersSigmaMargin, float, 0.f, "", 0, "Margin factor for trackSigmaY when rejecting edge clusters based on uncorrected track Y") +AddOptionRTC(trackletMaxSharedFraction, float, 0.1f, "", 0, "Max fraction of shared clusters for tracklet") +AddOptionRTC(trackletMinSharedNormFactor, float, 0.f, "", 0, "Max shared defined as trackletMinSharedNormFactor*max(current_nhits,trackletMinSharedNormFactor*minHits,1)") AddOptionRTC(maxTimeBinAboveThresholdIn1000Bin, unsigned short, 500, "", 0, "Except pad from cluster finding if total number of charges in a fragment is above this baseline (disable = 0)") AddOptionRTC(maxConsecTimeBinAboveThreshold, unsigned short, 200, "", 0, "Except pad from cluster finding if number of consecutive charges in a fragment is above this baseline (disable = 0)") AddOptionRTC(noisyPadSaturationThreshold, unsigned short, 700, "", 0, "Threshold where a timebin is considered saturated, disabling the noisy pad check for that pad") diff --git a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx index 4f406d5dd57d4..747667b9b68ed 100644 --- a/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx +++ b/GPU/GPUTracking/SliceTracker/GPUTPCTrackletSelector.cxx @@ -34,12 +34,12 @@ GPUdii() void GPUTPCTrackletSelector::Thread<0>(int nBlocks, int nThreads, int i GPUbarrier(); GPUTPCHitId trackHits[GPUCA_ROW_COUNT - GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE]; + const float maxSharedFrac = tracker.Param().rec.tpc.trackletMaxSharedFraction; for (int itr = s.mItr0 + iThread; itr < s.mNTracklets; itr += s.mNThreadsTotal) { GPUbarrierWarp(); GPUglobalref() MEM_GLOBAL(GPUTPCTracklet) & GPUrestrict() tracklet = tracker.Tracklets()[itr]; - const float kMaxShared = .1f; int firstRow = tracklet.FirstRow(); int lastRow = tracklet.LastRow(); @@ -52,6 +52,8 @@ GPUdii() void GPUTPCTrackletSelector::Thread<0>(int nBlocks, int nThreads, int i int nShared = 0; int nHits = 0; const int minHits = tracker.Param().rec.tpc.minNClustersTrackSeed == -1 ? GPUCA_TRACKLET_SELECTOR_MIN_HITS_B5(tracklet.Param().QPt() * tracker.Param().qptB5Scaler) : tracker.Param().rec.tpc.minNClustersTrackSeed; + const int sharingMinNorm = minHits * tracker.Param().rec.tpc.trackletMinSharedNormFactor; + float maxShared = maxSharedFrac * sharingMinNorm; GPUCA_UNROLL(, U(1)) for (irow = firstRow; irow <= lastRow && lastRow - irow + nHits >= minHits; irow++) { @@ -62,7 +64,7 @@ GPUdii() void GPUTPCTrackletSelector::Thread<0>(int nBlocks, int nThreads, int i if (ih != CALINK_INVAL && ih != CALINK_DEAD_CHANNEL) { GPUglobalref() const MEM_GLOBAL(GPUTPCRow)& row = tracker.Row(irow); bool own = (tracker.HitWeight(row, ih) <= w); - bool sharedOK = ((nShared < nHits * kMaxShared)); + bool sharedOK = nShared <= (nHits < sharingMinNorm ? maxShared : nHits * maxSharedFrac); if (own || sharedOK) { // SG!!! gap = 0; #if GPUCA_TRACKLET_SELECTOR_HITS_REG_SIZE != 0 From 0519d36294acef0811513c6c8c42b38873beba7f Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 17 Jun 2024 19:36:08 +0200 Subject: [PATCH 0321/2997] Store side ID in the TPC study output --- .../GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx index a549a402055e1..ca28aa24c9115 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TPCTrackStudy.cxx @@ -223,10 +223,11 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) for (size_t itr = 0; itr < mTPCTracksArray.size(); itr++) { auto tr = mTPCTracksArray[itr]; // create track copy + int side = 0; if (tr.hasBothSidesClusters()) { continue; } - + side = tr.hasASideClustersOnly() ? 1 : -1; //========================================================================= // create refitted copy auto trackRefit = [itr, this](o2::track::TrackParCov& trc, float t) -> bool { @@ -296,6 +297,7 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) << "counter=" << counter << "iniTrack=" << tr << "iniTrackRef=" << trf + << "side=" << side << "time=" << tr.getTime0() << "clSector=" << clSector << "clRow=" << clRow @@ -347,6 +349,7 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) << "counter=" << counter << "movTrackRef=" << trfm << "mcTrack=" << mctrO2 + << "side=" << side << "imposedTB=" << bcTB << "dz=" << dz << "clX=" << clX @@ -385,6 +388,7 @@ void TPCTrackStudySpec::process(o2::globaltracking::RecoContainer& recoData) << "iniTrackRef=" << trf << "time=" << tr.getTime0(); } (*mDBGOut) << "tpcMov" + << "side=" << side << "imposedTB=" << tb << "dz=" << dz << "clX=" << clX From 594e3ed8edb5a2451ef9a2dca4d54e658253c8f2 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 18 Jun 2024 10:57:58 +0200 Subject: [PATCH 0322/2997] Fix access to CCDB for ITS DCSParserSpec --- .../ITSMFT/ITS/workflow/src/DCSParserSpec.cxx | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx index 99bf1827116f1..4eaf16f32ba3f 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx @@ -470,19 +470,15 @@ void ITSDCSParser::pushToCCDB(ProcessingContext& pc) // Timestamps for CCDB entry long tstart = 0, tend = 0; // retireve run start/stop times from CCDB - o2::ccdb::CcdbApi api; - api.init(mCcdbUrlRct); - // Initialize empty metadata object for search - std::map metadata; - std::map headers = api.retrieveHeaders( - "RCT/Info/RunInformation", metadata, this->mRunNumber); - if (headers.empty()) { // No CCDB entry is found - LOG(error) << "Failed to retrieve headers from CCDB with run number " << this->mRunNumber - << "\nWill default to using the current time for timestamp information"; + auto& cdbman = o2::ccdb::BasicCCDBManager::instance(); + cdbman.setURL(mCcdbUrlRct); + cdbman.setFatalWhenNull(false); + auto ts = o2::ccdb::BasicCCDBManager::instance().getRunDuration(mRunNumber); + if (ts.first < 0 || ts.second < 0) { + LOGP(error, "Failed to retrieve headers from CCDB with run number {}, << this->mRunNumber, will default to using the current time for timestamp information", mRunNumber); tstart = o2::ccdb::getCurrentTimestamp(); tend = tstart + 365L * 24 * 3600 * 1000; } else { - auto ts = o2::ccdb::BasicCCDBManager::instance().getRunDuration(mRunNumber); tstart = ts.first; tend = ts.second; } @@ -491,8 +487,7 @@ void ITSDCSParser::pushToCCDB(ProcessingContext& pc) auto class_name_deadMap = o2::utils::MemFileHelper::getClassName(mDeadMap); // Create metadata for database object - metadata = {{"runtype", std::to_string(this->mRunType)}, {"confDBversion", std::to_string(this->mConfigVersion)}, {"runNumber", std::to_string(this->mRunNumber)}}; - + std::map metadata{{"runtype", std::to_string(mRunType)}, {"confDBversion", std::to_string(mConfigVersion)}, {"runNumber", std::to_string(mRunNumber)}}; std::string path("ITS/Calib/DCS_CONFIG"); std::string path_deadMap("ITS/Calib/DeadMap"); const char* filename = "dcs_config.root"; From 93a3d19d3058ed9b91b1294450fb83769b43d5bd Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 5 Jun 2024 17:25:57 +0200 Subject: [PATCH 0323/2997] More consistently apply external ion pdg table It appears that sometimes the external ion table was not loaded (only when users got hold of the singleton instance). This should now be fixed. --- .../SimulationDataFormat/O2DatabasePDG.h | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/O2DatabasePDG.h b/DataFormats/simulation/include/SimulationDataFormat/O2DatabasePDG.h index dcc50bb8276df..d89443150e199 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/O2DatabasePDG.h +++ b/DataFormats/simulation/include/SimulationDataFormat/O2DatabasePDG.h @@ -38,10 +38,6 @@ class O2DatabasePDG auto db = TDatabasePDG::Instance(); if (!initialized) { addALICEParticles(db); - if (const char* o2Root = std::getenv("O2_ROOT")) { - auto inputExtraPDGs = std::string(o2Root) + "/share/Detectors/gconfig/data/extra_ions_pdg_table.dat"; - db->ReadPDGTable(inputExtraPDGs.c_str()); - } initialized = true; } return db; @@ -49,6 +45,7 @@ class O2DatabasePDG // adds ALICE particles to a given TDatabasePDG instance static void addALICEParticles(TDatabasePDG* db = TDatabasePDG::Instance()); + static void addParticlesFromExternalFile(TDatabasePDG* db); // get particle's (if any) mass static Double_t MassImpl(TParticlePDG* particle, bool& success) @@ -655,6 +652,26 @@ inline void O2DatabasePDG::addALICEParticles(TDatabasePDG* db) if (!db->GetParticle(-ionCode)) { db->AddParticle("AntiSexaquark", "AntiSexaquark", 2.0, kTRUE, 0.0, 0, "Special", -ionCode); } + + // lastly, add particle from the the extra text file + addParticlesFromExternalFile(db); +} + +inline void O2DatabasePDG::addParticlesFromExternalFile(TDatabasePDG* db) +{ + static bool initialized = false; + if (!initialized) { + // allow user to specify custom file + if (const char* custom = std::getenv("O2_SIM_CUSTOM_PDG")) { + // TODO: make sure this is a file + db->ReadPDGTable(custom); + } else if (const char* o2Root = std::getenv("O2_ROOT")) { + // take the maintained file from O2 + auto inputExtraPDGs = std::string(o2Root) + "/share/Detectors/gconfig/data/extra_ions_pdg_table.dat"; + db->ReadPDGTable(inputExtraPDGs.c_str()); + } + initialized = true; + } } } // namespace o2 From 13e3d51a4de47b68c9cc44a24bffedb6f55e4708 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 18 Jun 2024 15:23:40 +0200 Subject: [PATCH 0324/2997] Prevent calling fatal on query for non-existing CCDB --- Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx index 4eaf16f32ba3f..533592df20f23 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx @@ -473,7 +473,7 @@ void ITSDCSParser::pushToCCDB(ProcessingContext& pc) auto& cdbman = o2::ccdb::BasicCCDBManager::instance(); cdbman.setURL(mCcdbUrlRct); cdbman.setFatalWhenNull(false); - auto ts = o2::ccdb::BasicCCDBManager::instance().getRunDuration(mRunNumber); + auto ts = o2::ccdb::BasicCCDBManager::instance().getRunDuration(mRunNumber, false); if (ts.first < 0 || ts.second < 0) { LOGP(error, "Failed to retrieve headers from CCDB with run number {}, << this->mRunNumber, will default to using the current time for timestamp information", mRunNumber); tstart = o2::ccdb::getCurrentTimestamp(); From bde774e452a5ddd0d93d4ca268b45310006cf8ba Mon Sep 17 00:00:00 2001 From: Benedikt Volkel Date: Tue, 18 Jun 2024 16:47:44 +0200 Subject: [PATCH 0325/2997] [Gen] Abort if sub-generator is not configured correctly --- Generators/src/Generator.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Generators/src/Generator.cxx b/Generators/src/Generator.cxx index 530e418add7c4..377ca291662f6 100644 --- a/Generators/src/Generator.cxx +++ b/Generators/src/Generator.cxx @@ -86,13 +86,11 @@ Bool_t } if (mSubGeneratorsIdToDesc.empty() && mSubGeneratorId > -1) { - LOG(error) << "ReadEvent failed because no SubGenerator description given"; - return kFALSE; + LOG(fatal) << "ReadEvent failed because no SubGenerator description given"; } if (!mSubGeneratorsIdToDesc.empty() && mSubGeneratorId < 0) { - LOG(error) << "ReadEvent failed because SubGenerator description given but sub-generator not set"; - return kFALSE; + LOG(fatal) << "ReadEvent failed because SubGenerator description given but sub-generator not set"; } /** trigger event **/ From 37c0a56c74faf29099c7b7c64ec99ecd4decf7ad Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 19 Jun 2024 14:24:24 +0200 Subject: [PATCH 0326/2997] Add module to properly find AliceGridUtils --- dependencies/FindAliceGridUtils.cmake | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 dependencies/FindAliceGridUtils.cmake diff --git a/dependencies/FindAliceGridUtils.cmake b/dependencies/FindAliceGridUtils.cmake new file mode 100644 index 0000000000000..ca364101432d5 --- /dev/null +++ b/dependencies/FindAliceGridUtils.cmake @@ -0,0 +1,7 @@ +include(FindPackageHandleStandardArgs) +find_path(ALICE_GRID_UTILS_INCLUDE_DIR "TAliceCollection.h" + PATH_SUFFIXES "include" + HINTS "${ALICE_GRID_UTILS_ROOT}") +#get_filename_component(ALICE_GRID_UTILS_INCLUDE_DIR ${ALICE_GRID_UTILS_INCLUDE_DIR} DIRECTORY) +find_package_handle_standard_args(AliceGridUtils DEFAULT_MSG ALICE_GRID_UTILS_INCLUDE_DIR) +include_directories(${ALICE_GRID_UTILS_INCLUDE_DIR}) From 4b1e09fc7eca79f3566d4fb94f10a7375268756c Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Thu, 20 Jun 2024 06:21:17 +0200 Subject: [PATCH 0327/2997] Common/Constants: Add K*(892)0,+ masses --- Common/Constants/include/CommonConstants/PhysicsConstants.h | 4 ++++ Common/Constants/include/CommonConstants/make_pdg_header.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Common/Constants/include/CommonConstants/PhysicsConstants.h b/Common/Constants/include/CommonConstants/PhysicsConstants.h index 8253eaf6a0c7e..3b00789b6d818 100644 --- a/Common/Constants/include/CommonConstants/PhysicsConstants.h +++ b/Common/Constants/include/CommonConstants/PhysicsConstants.h @@ -48,6 +48,8 @@ enum Pdg { kLambdaB0 = 5122, kLambdaCPlus = 4122, kOmegaC0 = 4332, + kK0Star892 = 313, + kKPlusStar892 = 323, kPhi = 333, kSigmaC0 = 4112, kSigmaCPlusPlus = 4222, @@ -84,6 +86,8 @@ constexpr double MassJPsi = 3.0969; constexpr double MassLambdaB0 = 5.6196; constexpr double MassLambdaCPlus = 2.28646; constexpr double MassOmegaC0 = 2.6952; +constexpr double MassK0Star892 = 0.89555; +constexpr double MassKPlusStar892 = 0.89167; constexpr double MassPhi = 1.019461; constexpr double MassSigmaC0 = 2.45375; constexpr double MassSigmaCPlusPlus = 2.45397; diff --git a/Common/Constants/include/CommonConstants/make_pdg_header.py b/Common/Constants/include/CommonConstants/make_pdg_header.py index d42596b3bd7d8..b848de0d2e46d 100755 --- a/Common/Constants/include/CommonConstants/make_pdg_header.py +++ b/Common/Constants/include/CommonConstants/make_pdg_header.py @@ -103,6 +103,8 @@ class Pdg(Enum): kLambdaB0 = 5122 kLambdaCPlus = 4122 kOmegaC0 = 4332 + kK0Star892 = 313 + kKPlusStar892 = 323 kPhi = 333 kSigmaC0 = 4112 kSigmaCPlusPlus = 4222 From 3f4ab8f2e386e7ba46fb8bed67130d89cdb7c68e Mon Sep 17 00:00:00 2001 From: Hadi Hassan Date: Mon, 17 Jun 2024 15:41:11 +0300 Subject: [PATCH 0328/2997] Construction of the FOCAL-H geometry and Hit simulation for HCAL sensitive volumes --- .../DetectorsCommonDataFormats/SimTraits.h | 9 +- .../FOCAL/base/include/FOCALBase/Geometry.h | 2 +- Detectors/FOCAL/base/src/Geometry.cxx | 24 +- Detectors/FOCAL/simulation/CMakeLists.txt | 5 +- Detectors/FOCAL/simulation/data/simcuts.dat | 16 + .../simulation/geometryFiles/geometry.txt | 86 ++++ .../geometryFiles/geometry_Spaghetti.txt | 84 +++ .../include/FOCALSimulation/Detector.h | 56 +- Detectors/FOCAL/simulation/src/Detector.cxx | 487 +++++++++++++++++- macro/CMakeLists.txt | 1 + macro/build_geometry.C | 6 + run/CMakeLists.txt | 1 + run/O2HitMerger.h | 9 +- run/o2simdefaultdetectorlist.json | 1 + 14 files changed, 768 insertions(+), 19 deletions(-) create mode 100644 Detectors/FOCAL/simulation/data/simcuts.dat create mode 100644 Detectors/FOCAL/simulation/geometryFiles/geometry.txt create mode 100644 Detectors/FOCAL/simulation/geometryFiles/geometry_Spaghetti.txt diff --git a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h index 3521991070583..8f9cbcfbdba43 100644 --- a/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h +++ b/DataFormats/Detectors/Common/include/DetectorsCommonDataFormats/SimTraits.h @@ -167,7 +167,10 @@ namespace tpc { class HitGroup; } - +namespace focal +{ +class Hit; +} namespace detectors { @@ -231,6 +234,10 @@ template <> struct DetIDToHitTypes { using HitType = o2::tpc::HitGroup; }; +template <> +struct DetIDToHitTypes { + using HitType = o2::focal::Hit; +}; #ifdef ENABLE_UPGRADES template <> struct DetIDToHitTypes { diff --git a/Detectors/FOCAL/base/include/FOCALBase/Geometry.h b/Detectors/FOCAL/base/include/FOCALBase/Geometry.h index be1eb5132f977..4938ebb1925dd 100644 --- a/Detectors/FOCAL/base/include/FOCALBase/Geometry.h +++ b/Detectors/FOCAL/base/include/FOCALBase/Geometry.h @@ -135,7 +135,7 @@ class Geometry bool getInsertFrontPadLayers() const { return mInsertFrontPadLayers; } bool getInsertHCalReadoutMaterial() const { return mInsertFrontHCalReadoutMaterial; } - // TObjArray* getFOCALMicroModule(int layer) const; // NOTE: Check if needed, otherwise remove + std::vector getFOCALMicroModule(int layer) const; const Composition* getComposition(int layer, int stack) const; std::string_view getTowerGapMaterial() const { return mGlobal_Gap_Material; } diff --git a/Detectors/FOCAL/base/src/Geometry.cxx b/Detectors/FOCAL/base/src/Geometry.cxx index 714d51ab5efdd..c58745a681c6c 100644 --- a/Detectors/FOCAL/base/src/Geometry.cxx +++ b/Detectors/FOCAL/base/src/Geometry.cxx @@ -578,8 +578,8 @@ void Geometry::setParameters(std::string geometryfile) } } } // end for itowerY - } // end for itowerX - } // end else + } // end for itowerX + } // end else center_z += tmpComp.getThickness(); } // end loop over pad layer compositions LOG(debug) << "============ Created all pad layer compositions (" << mPadCompositionBase.size() << " volumes)"; @@ -646,6 +646,26 @@ const Composition* Geometry::getComposition(int layer, int stack) const return nullptr; } +//_________________________________________________________________________ +std::vector Geometry::getFOCALMicroModule(int layer) const +{ + + std::vector layerComposition; + + if (layer == -1) { + for (auto& icomp : mGeometryComposition) { + layerComposition.push_back(&icomp); + } + } else { + for (auto& icomp : mGeometryComposition) { + if (icomp.layer() == layer) { + layerComposition.push_back(&icomp); + } + } + } + return layerComposition; +} + //_________________________________________________________________________ /// this gives global position of the center of tower std::tuple Geometry::getGeoTowerCenter(int tower, int segment) const diff --git a/Detectors/FOCAL/simulation/CMakeLists.txt b/Detectors/FOCAL/simulation/CMakeLists.txt index a75a0795584f6..b838f563a2e0d 100644 --- a/Detectors/FOCAL/simulation/CMakeLists.txt +++ b/Detectors/FOCAL/simulation/CMakeLists.txt @@ -18,4 +18,7 @@ o2_add_library(FOCALSimulation o2_target_root_dictionary( FOCALSimulation HEADERS include/FOCALSimulation/Detector.h -) \ No newline at end of file +) + +o2_data_file(COPY geometryFiles DESTINATION Detectors/Geometry/FOC/) +o2_data_file(COPY data DESTINATION Detectors/FOC/simulation) diff --git a/Detectors/FOCAL/simulation/data/simcuts.dat b/Detectors/FOCAL/simulation/data/simcuts.dat new file mode 100644 index 0000000000000..3154dc4472e68 --- /dev/null +++ b/Detectors/FOCAL/simulation/data/simcuts.dat @@ -0,0 +1,16 @@ +* FOCAL +* ==== +* +* Med GAM ELEC NHAD CHAD MUON EBREM MUHAB EDEL MUDEL MUPA ANNI BREM COMP DCAY DRAY HADR LOSS MULS PAIR PHOT RAYL STRA +* Tungsten +FOC 0 5.e-5 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 -1. -1 -1 -1 -1 1 -1 3 -1 -1 -1 -1 -1 +* Si sensor +FOC 1 1.e-5 1.e-5 1.e-5 1.e-5 1.e-5 1.e-5 1.e-5 1.e-5 1.e-5 -1. -1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 -1 +* G10 plate +FOC 2 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 -1. -1 -1 -1 -1 1 -1 3 -1 -1 -1 -1 -1 +* Alloy +FOC 5 5.e-5 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 -1. -1 -1 -1 -1 1 -1 3 -1 -1 -1 -1 -1 +* Aluminium +FOC 10 5.e-5 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 -1. -1 -1 -1 -1 1 -1 3 -1 -1 -1 -1 -1 +* G10 plate +FOC 12 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 1.e-4 -1. -1 -1 -1 -1 1 -1 3 -1 -1 -1 -1 -1 diff --git a/Detectors/FOCAL/simulation/geometryFiles/geometry.txt b/Detectors/FOCAL/simulation/geometryFiles/geometry.txt new file mode 100644 index 0000000000000..c6ca6d4f8a64b --- /dev/null +++ b/Detectors/FOCAL/simulation/geometryFiles/geometry.txt @@ -0,0 +1,86 @@ +# Pad layer materials updated to match the setup used in test beams. Total thickness is 8.5mm +# Volume Name Material C-X C-Y X Y Z + COMPOSITION_PAD_S0 Alloy 0 0 9. 8. 0.35 + COMPOSITION_PAD_S1 G10 0 0 9. 8. 0.08 + COMPOSITION_PAD_S2 SiPad 0 0 9. 8. 0.03 + COMPOSITION_PAD_S3 G10 0 0 9. 8. 0.08 + COMPOSITION_PAD_S4 Cu 0 0 9. 8. 0.014 + COMPOSITION_PAD_S5 Air 0 0 9. 8. 0.296 + # Replica of above pad layers to 50 layers + COMMAND_NUMBER_OF_PAD_LAYERS 18 +# HCAL layers +# Volume Name Material C-X C-Y X Y Z + COMPOSITION_HCAL_S0 Pb 0 0 2.5 2.5 3.0 + COMPOSITION_HCAL_S1 Scint 0 0 2.5 2.5 0.2 + COMMAND_NUMBER_OF_HCAL_LAYERS 34 + COMMAND_NUMBER_OF_SEGMENTS 54 +# Pixel layers total thickness is 8.5mm as in test beam simulation. +# TODO: change G10 material to Al and remove copper ground (requires changes in AliFOCALv2.cxx) +# Volume Name Material C-X C-Y X Y Z + COMPOSITION_PIX_S0 Alloy 0 0 3.0 2.74 0.35 + COMPOSITION_PIX_S1 G10 0 0 3.0 2.74 0.1 + COMPOSITION_PIX_S2 Si 0 0 3.0 2.74 0.047 + COMPOSITION_PIX_S3 SiPix 0 0 3.0 2.74 0.003 + COMPOSITION_PIX_S4 G10 0 0 3.0 2.74 0.1 + COMPOSITION_PIX_S5 Cu 0 0 3.0 2.74 0.001 + COMPOSITION_PIX_S6 Air 0 0 3.0 2.74 0.249 +COMMAND_INSERT_PIX_AT_L4 +COMMAND_INSERT_PIX_AT_L9 +# COMMAND_INSERT_STR_AT_L4 +# COMMAND_INSERT_STR_AT_L6 +# COMMAND_INSERT_STR_AT_L8 +#Front Matter definition + COMPOSITION_FM_S0 G10 0 0 5. 5. 0.01 + COMPOSITION_FM_S1 SiStripX 0 0 5. 5. 0.05 + COMPOSITION_FM_S2 G10 0 0 5. 5. 0.05 + COMPOSITION_FM_S3 Air 0 0 5. 5. 0.01 + COMPOSITION_FM_S4 G10 0 0 5. 5. 0.01 + COMPOSITION_FM_S5 SiStripY 0 0 5. 5. 0.05 + COMPOSITION_FM_S6 G10 0 0 5. 5. 0.05 +# PIXEL readout + GLOBAL_PIX_NX 15 + GLOBAL_PIX_NY 3 + GLOBAL_PIX_OffsetX 1.2 + GLOBAL_PIX_OffsetY 0.09 + GLOBAL_PIX_SKIN 0.004 +# pxel size in cm + COMMAND_PIXEL_READOUT_ON 0.005 +# Pad information + GLOBAL_PAD_SIZE_X_Y 1 + GLOBAL_PAD_NX_NY 8 + GLOBAL_PAD_NX 9 + GLOBAL_PAD_NY 8 + GLOBAL_PAD_PPTOL 0. + GLOBAL_PAD_SKIN 0.2 +# Global information (TOL:1cm of T-T space filled with "AIR") + GLOBAL_PAD_SUPERMODULE_X 5 + GLOBAL_PAD_SUPERMODULE_Y 1 + GLOBAL_SUPERMODULE_TOLX 0. Air + GLOBAL_SUPERMODULE_TOLY 0. Air + GLOBAL_TOWER_TOL 0. Air + GLOBAL_TOWER_TOLX 0.02 Air + GLOBAL_TOWER_TOLY 0.8 Al + GLOBAL_FOCAL_Z 762.9 + GLOBAL_Tower_NX 2 + GLOBAL_Tower_NY 11 + GLOBAL_MIDDLE_TOWER_OFFSET 5 + GLOBAL_NSTRIPS 128 + GLOBAL_STRIPSIZE_LONG 9.0 + GLOBAL_STRIPSIZE_WIDTH 0.07 + GLOBAL_HCAL_TOWER_SIZE 2.5 + GLOBAL_HCAL_TOWER_NY 40 + GLOBAL_HCAL_TOWER_NX 38 +# COMMAND_INSERT_FRONT_PAD_LAYERS +# COMMAND_INSERT_HCAL_READOUT +# New VIRTUAL settings + VIRTUAL_N_SEGMENTS 7 + # N Start End PadSize RelThickness IsPixel PixelTreshold [eV] + # Layer Layer + VIRTUAL_SEGMENT_LAYOUT_N0 0 3 1.0 1.0 0 300000 + VIRTUAL_SEGMENT_LAYOUT_N1 4 4 0.05 1.0 1 4000 + VIRTUAL_SEGMENT_LAYOUT_N2 5 8 1.0 1.0 0 300000 + VIRTUAL_SEGMENT_LAYOUT_N3 9 9 0.05 1.0 1 4000 + VIRTUAL_SEGMENT_LAYOUT_N4 10 14 1.0 1.0 0 375000 + VIRTUAL_SEGMENT_LAYOUT_N5 15 19 1.0 1.0 0 375000 + VIRTUAL_SEGMENT_LAYOUT_N6 20 53 2.5 1.0 2 5000 +#EOF diff --git a/Detectors/FOCAL/simulation/geometryFiles/geometry_Spaghetti.txt b/Detectors/FOCAL/simulation/geometryFiles/geometry_Spaghetti.txt new file mode 100644 index 0000000000000..f66ef50ad5ea4 --- /dev/null +++ b/Detectors/FOCAL/simulation/geometryFiles/geometry_Spaghetti.txt @@ -0,0 +1,84 @@ +# Volume Name Material C-X C-Y X Y Z + COMPOSITION_PAD_S0 Alloy 0 0 9. 8. 0.35 + COMPOSITION_PAD_S1 G10 0 0 9. 8. 0.08 + COMPOSITION_PAD_S2 SiPad 0 0 9. 8. 0.03 + COMPOSITION_PAD_S3 G10 0 0 9. 8. 0.08 + COMPOSITION_PAD_S4 Cu 0 0 9. 8. 0.014 + COMPOSITION_PAD_S5 Air 0 0 9. 8. 0.296 + # Replica of above pad layers to 50 layers + COMMAND_NUMBER_OF_PAD_LAYERS 18 +# HCAL layers +# Volume Name Material C-X C-Y X Y Z + COMPOSITION_HCAL_S1 Scint 0 0 0.1 0.1 110 + COMPOSITION_HCAL_S0 CuHCAL 0 0 0.25 0.25 110 + COMMAND_NUMBER_OF_HCAL_LAYERS 1 + COMMAND_NUMBER_OF_SEGMENTS 21 +# Strip sectors +# Volume Name Material C-X C-Y X Y Z + COMPOSITION_PIX_S0 Alloy 0 0 3.0 2.74 0.35 + COMPOSITION_PIX_S1 G10 0 0 3.0 2.74 0.1 + COMPOSITION_PIX_S2 Si 0 0 3.0 2.74 0.047 + COMPOSITION_PIX_S3 SiPix 0 0 3.0 2.74 0.003 + COMPOSITION_PIX_S4 G10 0 0 3.0 2.74 0.1 + COMPOSITION_PIX_S5 Cu 0 0 3.0 2.74 0.001 + COMPOSITION_PIX_S6 Air 0 0 3.0 2.74 0.249 +COMMAND_INSERT_PIX_AT_L4 +COMMAND_INSERT_PIX_AT_L9 +# COMMAND_INSERT_STR_AT_L4 +# COMMAND_INSERT_STR_AT_L6 +# COMMAND_INSERT_STR_AT_L8 +#Front Matter definition + COMPOSITION_FM_S0 G10 0 0 5. 5. 0.01 + COMPOSITION_FM_S1 SiStripX 0 0 5. 5. 0.05 + COMPOSITION_FM_S2 G10 0 0 5. 5. 0.05 + COMPOSITION_FM_S3 Air 0 0 5. 5. 0.01 + COMPOSITION_FM_S4 G10 0 0 5. 5. 0.01 + COMPOSITION_FM_S5 SiStripY 0 0 5. 5. 0.05 + COMPOSITION_FM_S6 G10 0 0 5. 5. 0.05 +# PIXEL readout + GLOBAL_PIX_NX 15 + GLOBAL_PIX_NY 3 + GLOBAL_PIX_OffsetX 1.2 + GLOBAL_PIX_OffsetY 0.09 + GLOBAL_PIX_SKIN 0.004 +# pxel size in cm + COMMAND_PIXEL_READOUT_ON 0.005 +# Pad information + GLOBAL_PAD_SIZE_X_Y 1 + GLOBAL_PAD_NX_NY 8 + GLOBAL_PAD_NX 9 + GLOBAL_PAD_NY 8 + GLOBAL_PAD_PPTOL 0. + GLOBAL_PAD_SKIN 0.2 +# Global information (TOL:1cm of T-T space filled with "AIR") + GLOBAL_PAD_SUPERMODULE_X 5 + GLOBAL_PAD_SUPERMODULE_Y 1 + GLOBAL_SUPERMODULE_TOLX 0. Air + GLOBAL_SUPERMODULE_TOLY 0. Air + GLOBAL_TOWER_TOL 0. Air + GLOBAL_TOWER_TOLX 0.02 Air + GLOBAL_TOWER_TOLY 0.8 Al + GLOBAL_FOCAL_Z 764.47 + GLOBAL_Tower_NX 2 + GLOBAL_Tower_NY 11 + GLOBAL_MIDDLE_TOWER_OFFSET 5 + GLOBAL_NSTRIPS 128 + GLOBAL_STRIPSIZE_LONG 9.0 + GLOBAL_STRIPSIZE_WIDTH 0.07 + GLOBAL_HCAL_TOWER_SIZE 6.55 + GLOBAL_HCAL_TOWER_NY 15 + GLOBAL_HCAL_TOWER_NX 15 +# COMMAND_INSERT_FRONT_PAD_LAYERS +# COMMAND_INSERT_HCAL_READOUT +# New VIRTUAL settings + VIRTUAL_N_SEGMENTS 7 + # N Start End PadSize RelThickness IsPixel PixelTreshold [eV] + # Layer Layer + VIRTUAL_SEGMENT_LAYOUT_N0 0 3 1.0 1.0 0 300000 + VIRTUAL_SEGMENT_LAYOUT_N1 4 4 0.05 1.0 1 4000 + VIRTUAL_SEGMENT_LAYOUT_N2 5 8 1.0 1.0 0 300000 + VIRTUAL_SEGMENT_LAYOUT_N3 9 9 0.05 1.0 1 4000 + VIRTUAL_SEGMENT_LAYOUT_N4 10 14 1.0 1.0 0 375000 + VIRTUAL_SEGMENT_LAYOUT_N5 15 19 1.0 1.0 0 375000 + VIRTUAL_SEGMENT_LAYOUT_N6 20 20 0.25 1.0 2 5000 +#EOF diff --git a/Detectors/FOCAL/simulation/include/FOCALSimulation/Detector.h b/Detectors/FOCAL/simulation/include/FOCALSimulation/Detector.h index 170b6ed0f595d..6c8017bd28f68 100644 --- a/Detectors/FOCAL/simulation/include/FOCALSimulation/Detector.h +++ b/Detectors/FOCAL/simulation/include/FOCALSimulation/Detector.h @@ -16,12 +16,15 @@ #include "DetectorsBase/Detector.h" #include "FOCALBase/Hit.h" +#include "FOCALBase/Geometry.h" class FairVolume; namespace o2::focal { +class Geometry; + /// \struct Parent /// \brief Information about superparent (particle entering any FOCAL volume) /// \ingroup FOCALsimulation @@ -49,11 +52,17 @@ class Detector : public o2::base::DetImpl ID_PB = 7, ID_SC = 8, ID_SIINSENS = 9, - ID_VAC = 10, - ID_AIR = 11 }; + ID_ALUMINIUM = 10, + ID_VAC = 11, + ID_AIR = 12 }; /// \brief Dummy constructor Detector() = default; + /// \brief Main constructor + /// + /// \param isActive Switch whether detector is active in simulation + Detector(Bool_t isActive, std::string geofilename = "default"); + /// \brief Destructor ~Detector() override; @@ -64,6 +73,21 @@ class Detector : public o2::base::DetImpl /// \param v Current sensitive volume Bool_t ProcessHits(FairVolume* v = nullptr) final; + /// \brief Add FOCAL hit + /// \param trackID Index of the track in the MC stack + /// \param primary Index of the primary particle in the MC stack + /// \param initialEnergy Energy of the particle entering the FOCAL + /// \param detID Index of the detector (cell) for which the hit is created + /// \param pos Position vector of the particle at the hit + /// \param mom Momentum vector of the particle at the hit + /// \param time Time of the hit + /// \param energyloss Energy deposit in FOCAL + /// \return Pointer to the current hit + /// + /// Internally adding hits coming from the same track + Hit* AddHit(int trackID, int primary, double initialEnergy, int detID, o2::focal::Hit::Subsystem_t subsystem, + const math_utils::Point3D& pos, double time, double energyloss); + /// \brief register container with hits void Register() override; @@ -96,12 +120,31 @@ class Detector : public o2::base::DetImpl /// Reset caches for current primary, current parent and current cell void FinishPrimary() override; + /// \brief Get the FOCAL geometry desciption + /// \return Access to the FOCAL Geometry description + /// + /// Will be created the first time the function is called + Geometry* getGeometry(std::string name = ""); + + /// \brief Try to find hit with same cell and parent track ID + /// \param parentID ID of the parent track + /// \param col Column of the cell + /// \param row Row of the cell + /// \param Layer Layer of cell + Hit* FindHit(int parentID, int col, int row, int layer); + protected: /// \brief Creating detector materials for the FOCAL detector void CreateMaterials(); + virtual void addAlignableVolumes() const override; + void addAlignableVolumesHCAL() const; + void ConstructGeometry() override; + virtual void CreateHCALSpaghetti(); + virtual void CreateHCALSandwich(); + /// \brief Add new superparent to the container /// \param trackID Track ID of the superparent /// \param pdg PDG code of the superparent @@ -112,6 +155,12 @@ class Detector : public o2::base::DetImpl /// \brief Copy constructor (used in MT) Detector(const Detector& rhs); + Geometry* mGeometry; //! mGeoCompositions; //!* mHits; ///< Container with hits std::unordered_map mSuperParentsIndices; //! Int_t mCurrentPrimaryID; //! mSensitiveHCAL; //! friend class o2::base::DetImpl; ClassDefOverride(Detector, 1); diff --git a/Detectors/FOCAL/simulation/src/Detector.cxx b/Detectors/FOCAL/simulation/src/Detector.cxx index acc4454b010ca..813821efa86ab 100644 --- a/Detectors/FOCAL/simulation/src/Detector.cxx +++ b/Detectors/FOCAL/simulation/src/Detector.cxx @@ -11,15 +11,42 @@ #include #include +#include +#include +#include +#include #include +#include "DetectorsBase/Stack.h" #include "FOCALSimulation/Detector.h" using namespace o2::focal; +Detector::Detector(bool active, std::string geofilename) + : o2::base::DetImpl("FOC", active), + mHits(o2::utils::createSimVector()), + mGeometry(nullptr), + mMedSensHCal(-1), + mGeoCompositions(0x0), + mSuperParentsIndices(), + mSuperParents(), + mCurrentSuperparent(nullptr), + mCurrentTrack(-1), + mCurrentPrimaryID(-1), + mCurrentParentID(-1), + mVolumeIDScintillator(-1) +{ + mGeometry = getGeometry(geofilename); +} + Detector::Detector(const Detector& rhs) + : o2::base::DetImpl(rhs) { + mGeometry = rhs.mGeometry; + mMedSensHCal = rhs.mMedSensHCal; + mSensitiveHCAL = rhs.mSensitiveHCAL; + mVolumeIDScintillator = rhs.mVolumeIDScintillator; } Detector::~Detector() @@ -27,14 +54,40 @@ Detector::~Detector() o2::utils::freeSimVector(mHits); } +Geometry* Detector::getGeometry(std::string name) +{ + if (!mGeometry) { + mGeometry = Geometry::getInstance(name); + } + if (!mGeometry) { + LOG(error) << "Failure accessing geometry"; + } + return mGeometry; +} + void Detector::InitializeO2Detector() { + + LOG(info) << "Intializing FOCAL detector"; + + // All FOCAL volumes must be declared as sensitive, otherwise + // the decay chains are broken by volumes not processed in ProceeHits + for (const auto& child : mSensitiveHCAL) { + LOG(debug1) << "Adding sensitive volume " << child; + auto svolID = registerSensitiveVolumeAndGetVolID(child); + if (child == "ScintFiber" || child == "HScint") { + LOG(debug1) << "Adding ScintFiber/HScint volume as sensitive volume with ID " << svolID; + mVolumeIDScintillator = svolID; + } + } + + mMedSensHCal = getMediumID(ID_SC); } Bool_t Detector::ProcessHits(FairVolume* v) { - int track = fMC->GetStack()->GetCurrentTrackNumber(), - directparent = fMC->GetStack()->GetCurrentParentTrackNumber(); + int track = gMC->GetStack()->GetCurrentTrackNumber(), + directparent = gMC->GetStack()->GetCurrentParentTrackNumber(); // Like other calorimeters FOCAL will create a huge amount of shower particles during tracking // Instead, the hits should be assigned to the incoming particle in FOCAL. // Implementation of the incoming particle search taken from implementation in EMCAL. @@ -58,14 +111,88 @@ Bool_t Detector::ProcessHits(FairVolume* v) // start of new chain // for new incoming tracks the super parent index is equal to the track ID (for recursion) mSuperParentsIndices[track] = track; - mCurrentSuperparent = AddSuperparent(track, fMC->TrackPid(), fMC->Etot()); + mCurrentSuperparent = AddSuperparent(track, gMC->TrackPid(), gMC->Etot()); mCurrentParentID = track; } mCurrentTrack = track; } + + // Processing HCAL hits + if (gMC->CurrentMedium() == mMedSensHCal) { + LOG(debug) << "We are in sensitive volume " << v->GetName() << ": " << gMC->CurrentVolPath() << std::endl; + + double eloss = gMC->Edep() * 1e9; // energy in eV (GeV->eV) + if (eloss < DBL_EPSILON) { + return false; // only process hits which actually deposit some energy in the FOCAL + } + + // In case of new parent track create new track reference + auto o2stack = static_cast(gMC->GetStack()); + if (!mCurrentSuperparent->mHasTrackReference) { + float x, y, z, px, py, pz, e; + gMC->TrackPosition(x, y, z); + gMC->TrackMomentum(px, py, pz, e); + o2::TrackReference trackref(x, y, z, px, py, pz, gMC->TrackLength(), gMC->TrackTime(), mCurrentParentID, GetDetId()); + o2stack->addTrackReference(trackref); + mCurrentSuperparent->mHasTrackReference = true; + } + + float posX, posY, posZ; + gMC->TrackPosition(posX, posY, posZ); + + auto [indetector, col, row, layer, segment] = mGeometry->getVirtualInfo(posX, posY, posZ); + + if (!indetector) { + // particle outside the detector + return true; + } + + auto currenthit = FindHit(mCurrentParentID, col, row, layer); + if (!currenthit) { + // Condition for new hit: + // - Processing different partent track (parent track must be produced outside FOCAL) + // - Inside different cell + // - First track of the event + Double_t time = gMC->TrackTime() * 1e9; // time in ns + LOG(debug3) << "Adding new hit for parent " << mCurrentParentID << " and cell Col: " << col << " Row: " << row << " segment: " << segment << std::endl; + + /// check handling of primary particles + AddHit(mCurrentParentID, mCurrentPrimaryID, mCurrentSuperparent->mEnergy, row * col + col, o2::focal::Hit::Subsystem_t::HCAL, math_utils::Point3D(posX, posY, posZ), time, eloss); + o2stack->addHit(GetDetId()); + } else { + LOG(debug3) << "Adding energy to the current hit" << std::endl; + currenthit->SetEnergyLoss(currenthit->GetEnergyLoss() + eloss); + } + } + return true; } +Hit* Detector::AddHit(int trackID, int primary, double initialEnergy, int detID, o2::focal::Hit::Subsystem_t subsystem, + const math_utils::Point3D& pos, double time, double eLoss) +{ + LOG(debug3) << "Adding hit for track " << trackID << " with position (" << pos.X() << ", " + << pos.Y() << ", " << pos.Z() << ") with energy " << initialEnergy << " loosing " << eLoss; + mHits->emplace_back(primary, trackID, detID, subsystem, initialEnergy, pos, time, eLoss); + return &(mHits->back()); +} + +Hit* Detector::FindHit(int parentID, int col, int row, int layer) +{ + + auto HitComparison = [&](const Hit& hit) { + auto information = mGeometry->getVirtualInfo(hit.GetX(), hit.GetY(), hit.GetZ()); + // FIXME Should we compare segments instead of layers ??? + return hit.GetTrackID() == parentID && col == std::get<1>(information) && row == std::get<2>(information) && layer == std::get<3>(information); + }; + + auto result = std::find_if(mHits->begin(), mHits->end(), HitComparison); + if (result == mHits->end()) { + return nullptr; + } + return &(*result); +} + Parent* Detector::AddSuperparent(int trackID, int pdg, double energy) { LOG(debug3) << "Adding superparent for track " << trackID << " with PID " << pdg << " and energy " << energy; @@ -115,6 +242,9 @@ void Detector::CreateMaterials() // Cu Material(3, "Cu $", 63.54, 29., 8.96, 1.43, 15.); + // Al + Material(9, "Al$", 26.98, 13.0, 2.7, 8.9, 37.2); + //// Pb Material(10, "Pb $", 207.19, 82., 11.35, .56, 18.5); @@ -209,8 +339,8 @@ AliMixture( 8, "Ceramic $", acer, zcer, denscer, 2, wcer); // MvL: need to look up itdmed dynamically? // or move to TGeo: uses pointers for medium - Int_t isxfld = 2; - Float_t sxmgmx = 10.0; + int isxfld = 2; + float sxmgmx = 10.0; o2::base::Detector::initFieldTrackingParams(isxfld, sxmgmx); /// W plate -> idtmed[3599]; @@ -225,7 +355,7 @@ AliMixture( 8, "Ceramic $", acer, zcer, denscer, 2, wcer); isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.01, nullptr, 0); //// Cu plate --> idtmed[3602]; - Medium(ID_COPPER, "Cu $", 3, 0, + Medium(ID_COPPER, "Cu$", 3, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.0001, nullptr, 0); //// S steel --> idtmed[3603]; @@ -242,16 +372,20 @@ AliMixture( 8, "Ceramic $", acer, zcer, denscer, 2, wcer); // HCAL materials // Need to double-check tracking pars for this /// Pb plate --> idtmed[3608] - Medium(ID_PB, "Pb $", 10, 0, + Medium(ID_PB, "Pb // The Scintillator must be first in order in vector for Rin to be set$", 10, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, nullptr, 0); /// Scintillator --> idtmed[3609] - Medium(ID_SC, "Scint $", 11, 0, + Medium(ID_SC, "Scint$", 11, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.001, 0.001, nullptr, 0); /// Si plate -> idtmed[3610]; Medium(ID_SIINSENS, "Si insens$", 1, 0, 10.0, 0.1, 0.1, epsil, 0.001, 0, 0); + // Al for the cold plates + Medium(ID_ALUMINIUM, "Aluminium$", 9, 0, + isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0); + /// idtmed[3697] Medium(ID_VAC, "Vacuum $", 98, 0, isxfld, sxmgmx, 10.0, 1.0, 0.1, 0.1, 1.0, nullptr, 0); @@ -261,14 +395,347 @@ AliMixture( 8, "Ceramic $", acer, zcer, denscer, 2, wcer); isxfld, sxmgmx, 10.0, 1.0, 0.1, epsil, 0.001, nullptr, 0); } +//____________________________________________________________________________ +void Detector::addAlignableVolumes() const +{ + // Create entries for alignable volumes associating the symbolic volume + // name with the corresponding volume path. Needs to be syncronized with + // eventual changes in the geometry + // Alignable volumes are: + + // AddAlignableVolumesECAL(); + addAlignableVolumesHCAL(); +} + +//____________________________________________________________________________ +void Detector::addAlignableVolumesHCAL() const +{ + TString vpsector = "/cave_1/barrel_1/FOCAL_1/HCAL_1"; + TString snsector = "FOCAL/HCAL"; + + if (!gGeoManager->SetAlignableEntry(snsector.Data(), vpsector.Data())) { + LOG(fatal) << (Form("Alignable entry %s not created. Volume path %s not valid", snsector.Data(), vpsector.Data())); + } +} + void Detector::ConstructGeometry() { + + LOG(debug) << "Creating FOCAL geometry\n"; + + CreateMaterials(); + + /// -1 means get all the material object + mGeoCompositions = mGeometry->getFOCALMicroModule(-1); + if (!mGeoCompositions.size()) { + LOG(error) << "FOCAL compositions not found!!"; + return; + } + + float pars[4]; + pars[0] = (mGeometry->getFOCALSizeX() + 2 * mGeometry->getMiddleTowerOffset()) / 2; + pars[1] = mGeometry->getFOCALSizeY() / 2; + pars[2] = mGeometry->getFOCALSizeZ() / 2; + // Add space to place 2 SiPad layers in front of ECAL + // The global position of ECAL and HCAL remains the same, but the FOCAL box needs to be slightly larger to accomodate + // the 2 SiPad layers which will sit at z=698 and 699cm (2 and 1 cm in front of ECAL) + if (mGeometry->getInsertFrontPadLayers()) { + pars[2] += 1.0; + } + if (mGeometry->getInsertHCalReadoutMaterial()) { + pars[2] += (1.0 + 0.5); // place Aluminium 1cm thick box (0.5 means half) at 2cm behind HCal to simulate SiPM readout material + pars[1] += (10.0 + 1.0); // place Aluminium 1cm thick box at 10 cm below FOCAL + } + pars[3] = 0; + + LOG(info) << "Creating FOCAL with dimensions X: " << (mGeometry->getFOCALSizeX() + 2 * mGeometry->getMiddleTowerOffset()) << ", Y: " + << mGeometry->getFOCALSizeY() << ", Z: " << mGeometry->getFOCALSizeZ() + (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) + (mGeometry->getInsertHCalReadoutMaterial() ? 3.0 : 0.0) << std::endl; + + gMC->Gsvolu("FOCAL", "BOX", getMediumID(ID_AIR), pars, 4); + mSensitiveHCAL.push_back("FOCAL"); + + if (mGeometry->getUseHCALSandwich()) { + CreateHCALSandwich(); + } else { + CreateHCALSpaghetti(); + } + + gMC->Gspos("FOCAL", 1, "barrel", 0, 0, mGeometry->getFOCALZ0() - (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) + (mGeometry->getInsertHCalReadoutMaterial() ? 1.5 : 0.0), 0, "ONLY"); +} + +void Detector::CreateHCALSpaghetti() +{ + TGeoVolumeAssembly* volHCAL = new TGeoVolumeAssembly("HCAL"); + + TGeoVolumeAssembly* HcalTube = gGeoManager->MakeVolumeAssembly("ScintCuTubes"); + + TGeoVolume* volCuTube; + TGeoVolume* volSciFi; + + float RScint = 0.; + float Rin = 0.; + float Rout = 0.; + float Length = 0.; + + for (auto& icomp : mGeoCompositions) { + Length = icomp->sizeZ() / 2; + + if (icomp->material() == "Pb") { + Rout = icomp->sizeX() / 2; + TGeoMedium* medium = gGeoManager->GetMedium(getMediumID(ID_PB)); + volCuTube = gGeoManager->MakeTube("Tube", medium, Rin, Rout, Length); // The Scintillator must be first in order in vector for Rin to be set + volCuTube->SetLineWidth(2); + volCuTube->SetLineColor(kRed); + mSensitiveHCAL.push_back(volCuTube->GetName()); + HcalTube->AddNode(volCuTube, 1, 0x0); + } + if (icomp->material() == "Scint") { + RScint = icomp->sizeX() / 2; + Rin = RScint + 0.005; + TGeoMedium* medium = gGeoManager->GetMedium(getMediumID(ID_SC)); + volSciFi = gGeoManager->MakeTube("ScintFiber", medium, 0., RScint, Length); + volSciFi->SetLineWidth(2); + volSciFi->SetLineColor(kBlue); + mSensitiveHCAL.push_back(volSciFi->GetName()); + HcalTube->AddNode(volSciFi, 1, 0x0); + } + if (icomp->material() == "CuHCAL") { + Rout = icomp->sizeX() / 2; + TGeoMedium* medium = gGeoManager->GetMedium(getMediumID(ID_COPPER)); + volCuTube = gGeoManager->MakeTube("Tube", medium, Rin, Rout, Length); // The Scintillator must be first in order in vector for Rin to be set + volCuTube->SetLineWidth(2); + volCuTube->SetLineColor(kRed); + mSensitiveHCAL.push_back(volCuTube->GetName()); + HcalTube->AddNode(volCuTube, 1, 0x0); + } + } + + double TowerSize = mGeometry->getHCALTowerSize(); + double CuBoxThickness = 0.3; // Thickness of the Cu box carrying capillary tubes + + TGeoBBox* ODBox = new TGeoBBox("TowerOD", TowerSize / 2, TowerSize / 2, Length); + TGeoBBox* IDBox = new TGeoBBox("TowerID", (TowerSize - CuBoxThickness) / 2, (TowerSize - CuBoxThickness) / 2, Length + 0.01); + TGeoCompositeShape* TowerHCAL = new TGeoCompositeShape("TowerHCAL", "TowerOD - TowerID"); + TGeoVolume* volTower = new TGeoVolume("volTower", TowerHCAL, gGeoManager->GetMedium(getMediumID(ID_COPPER))); + volTower->SetLineWidth(2); + volTower->SetLineColor(42); + mSensitiveHCAL.push_back(volTower->GetName()); + + TGeoVolumeAssembly* volTowerHCAL = new TGeoVolumeAssembly("volTowerHCAL"); + volTowerHCAL->AddNode(volTower, 1, 0x0); + + int Rows = 0; + float RowPos = 0.; + int Columns = 0; + int NumTubes = 1; + + // Packing circles in Hexagonal shape + while (RowPos + CuBoxThickness / 2 + Rout + 2 * Rout < TowerSize) { + Columns = 0; + float ColumnPos = (Rows % 2 == 0) ? 0. : Rout; + while (ColumnPos + CuBoxThickness / 2 + Rout + 2 * Rout < TowerSize) { + + TGeoTranslation* trans = new TGeoTranslation(ColumnPos - TowerSize / 2 + CuBoxThickness / 2 + Rout, RowPos - TowerSize / 2 + CuBoxThickness / 2 + Rout, 0.); + + trans->SetName(Form("trans_Num_%d", NumTubes)); + trans->RegisterYourself(); + + volTowerHCAL->AddNode(HcalTube, NumTubes, trans); + // volTowerHCAL->AddNode(volCuTube, NumTubes, trans); + // volTowerHCAL->AddNode(volSciFi, NumTubes, trans); + + Columns++; + ColumnPos = Columns * 2 * Rout + ((Rows % 2 == 0) ? 0. : Rout); + NumTubes++; + } + + Rows++; + RowPos = Rows * 2 * Rout * TMath::Sin(TMath::Pi() / 3); + } + + // Define the distance from the beam pipe in which towers will ommitted + Double_t BeamPipeRadius = 3.0; // in cm To be changed later + Double_t TowerHalfDiag = TMath::Sqrt2() * 0.5 * TowerSize; // tower half diagonal + Double_t MinRadius = BeamPipeRadius + TowerSize / 2; + + float SizeXHCAL = mGeometry->getHCALTowersInX() * TowerSize; + float SizeYHCAL = mGeometry->getHCALTowersInY() * TowerSize; + + int nTowersX = mGeometry->getHCALTowersInX(); + int nTowersY = mGeometry->getHCALTowersInY(); + + Rows = 0; + Columns = 0; + RowPos = 0.; + Int_t NumTowers = 1; + for (Rows = 0; Rows < nTowersY; Rows++) { + + float ColumnPos = 0.; + RowPos = Rows * TowerSize; + for (Columns = 0; Columns < nTowersX; Columns++) { + ColumnPos = Columns * TowerSize; + TGeoTranslation* trans = new TGeoTranslation(ColumnPos - SizeXHCAL / 2 + TowerSize / 2, RowPos - SizeYHCAL / 2 + TowerSize / 2, 0.); + + // Remove the Towers that overlaps with the beam pipe + Double_t RadialDistance = TMath::Power(trans->GetTranslation()[0], 2) + TMath::Power(trans->GetTranslation()[1], 2); + + if (RadialDistance < MinRadius * MinRadius || TMath::Abs(trans->GetTranslation()[0]) > SizeXHCAL / 2) { + continue; + } + + // Adding the Tower to the HCAL + volHCAL->AddNode(volTowerHCAL, NumTowers, trans); + + NumTowers++; + } + } + + std::cout << "Number of Towers is: " << (NumTowers - 1) << std::endl; + std::cout << "Number of tubes is: " << (NumTubes - 1) * (NumTowers - 1) << std::endl; + + // Create Aluminium plate at the back of HCal to simulate the electronics readout material + // Hardcoded thickness of 1cm and placement at 2 cm behind HCAL + TGeoBBox* alHcalBox = new TGeoBBox("AlHCalBox", SizeXHCAL / 2.0, SizeYHCAL / 2.0, 0.5 / 2.0); + TGeoVolume* volumeAlHcalBox = new TGeoVolume("volAlHcalBox", alHcalBox, gGeoManager->GetMedium(getMediumID(ID_ALUMINIUM))); + volumeAlHcalBox->SetLineColor(kOrange); + if (mGeometry->getInsertHCalReadoutMaterial()) { + gMC->Gspos("volAlHcalBox", 9999, "FOCAL", 0.0, 0.0, +1.0 * mGeometry->getFOCALSizeZ() / 2.0 + 1.0, 0, "ONLY"); + mSensitiveHCAL.push_back("volAlHcalBox"); + } + TGeoBBox* alUnderBox = new TGeoBBox("AlUnderBox", SizeXHCAL / 2.0, 0.5, mGeometry->getFOCALSizeZ() / 2.0 + 1.5); + TGeoVolume* volumeAlUnderBox = new TGeoVolume("volAlUnderBox", alUnderBox, gGeoManager->GetMedium(getMediumID(ID_ALUMINIUM))); + volumeAlUnderBox->SetLineColor(kOrange); + if (mGeometry->getInsertHCalReadoutMaterial()) { + gMC->Gspos("volAlUnderBox", 9999, "FOCAL", 0.0, -1.0 * mGeometry->getFOCALSizeY() / 2 - 10.5, 0.0, 0, "ONLY"); + mSensitiveHCAL.push_back("volAlUnderBox"); + } + + gMC->Gspos("HCAL", 1, "FOCAL", 0, 0, mGeometry->getHCALCenterZ() - mGeometry->getFOCALSizeZ() / 2 + 0.01 + (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) - (mGeometry->getInsertHCalReadoutMaterial() ? 1.5 : 0.0), 0, "ONLY"); +} + +//_____________________________________________________________________________ +void Detector::CreateHCALSandwich() +{ + TGeoVolumeAssembly* volHCAL = new TGeoVolumeAssembly("HCAL"); + + /// make big volume containing all the longitudinal layers + Float_t pars[4]; // this is HMSC Assembly + pars[0] = mGeometry->getHCALTowerSize() / 2; + pars[1] = mGeometry->getHCALTowerSize() / 2; + pars[2] = mGeometry->getECALSizeZ() + mGeometry->getHCALSizeZ() / 2; // ECAL sizeZ is already added to the HCAL materials CenterZ, so it is also treated as offset + pars[3] = 0; + + float offset = pars[2]; + + TGeoVolumeAssembly* volTower = new TGeoVolumeAssembly("Tower"); + + int iCu(0), iScint(0); + for (auto& icomp : mGeoCompositions) { + + pars[0] = icomp->sizeX() / 2; + pars[1] = icomp->sizeY() / 2; + pars[2] = icomp->sizeZ() / 2; + pars[3] = 0; + + // HCal materials + + if (icomp->material() == "Pb") { + iCu++; + const TGeoMedium* medium = gGeoManager->GetMedium(getMediumID(ID_PB)); + const TGeoBBox* HPadBox = new TGeoBBox("HPadBox", pars[0], pars[1], pars[2]); + TGeoVolume* HPad = new TGeoVolume("HPad", HPadBox, medium); + HPad->SetLineColor(kGray); + mSensitiveHCAL.push_back(HPad->GetName()); + TGeoTranslation* trans = new TGeoTranslation(icomp->centerX(), icomp->centerY(), icomp->centerZ() - offset); + volTower->AddNode(HPad, iCu, trans); + } + if (icomp->material() == "Scint") { + iScint++; + const TGeoMedium* medium = gGeoManager->GetMedium(getMediumID(ID_SC)); + const TGeoBBox* HScintBox = new TGeoBBox("HScintBox", pars[0], pars[1], pars[2]); + TGeoVolume* HScint = new TGeoVolume("HScint", HScintBox, medium); + HScint->SetLineColor(kBlue); + mSensitiveHCAL.push_back(HScint->GetName()); + TGeoTranslation* trans = new TGeoTranslation(icomp->centerX(), icomp->centerY(), icomp->centerZ() - offset); + volTower->AddNode(HScint, iScint, trans); + } + if (icomp->material() == "CuHCAL") { + iCu++; + const TGeoMedium* medium = gGeoManager->GetMedium(getMediumID(ID_COPPER)); + const TGeoBBox* HPadBox = new TGeoBBox("HPadBox", pars[0], pars[1], pars[2]); + TGeoVolume* HPad = new TGeoVolume("HPad", HPadBox, medium); + HPad->SetLineColor(kRed); + mSensitiveHCAL.push_back(HPad->GetName()); + TGeoTranslation* trans = new TGeoTranslation(icomp->centerX(), icomp->centerY(), icomp->centerZ() - offset); + volTower->AddNode(HPad, iCu, trans); + } + } + double TowerSize = mGeometry->getHCALTowerSize(); + + // Define the distance from the beam pipe in which towers will ommitted + double BeamPipeRadius = 3.6; // in cm + double TowerHalfDiag = TMath::Sqrt2() * 0.5 * TowerSize; // tower half diagonal + double MinRadius = BeamPipeRadius + TowerHalfDiag; + + float SizeXHCAL = mGeometry->getHCALTowersInX() * TowerSize; + float SizeYHCAL = mGeometry->getHCALTowersInY() * TowerSize; + + int nTowersX = mGeometry->getHCALTowersInX(); + int nTowersY = mGeometry->getHCALTowersInY(); + + int Rows = 0; + int Columns = 0; + double RowPos = 0.; + int NumTowers = 1; + + // Arranging towers + for (Rows = 0; Rows < nTowersY; Rows++) { + Columns = 0; + float ColumnPos = 0.; + RowPos = Rows * TowerSize; + for (Columns = 0; Columns < nTowersX; Columns++) { + ColumnPos = Columns * TowerSize; + + TGeoTranslation* trans = new TGeoTranslation(ColumnPos - SizeXHCAL / 2 + TowerSize / 2, RowPos - SizeYHCAL / 2 + TowerSize / 2, 0.); + + // Remove the Towers that overlaps with the beam pipe + double RadialDistance = TMath::Power(ColumnPos - SizeXHCAL / 2 + TowerSize / 2, 2) + TMath::Power(RowPos - SizeYHCAL / 2 + TowerSize / 2, 2); + + if (RadialDistance < MinRadius * MinRadius) { + continue; + } + + // Adding the Tower to the HCAL + volHCAL->AddNode(volTower, NumTowers, trans); + + NumTowers++; + } + } + std::cout << "Number of Towers is: " << (NumTowers - 1) << std::endl; + + // Create an Aluminium plate at the back of HCal to simulate the electronics readout material + // Hardcoded thickness of 1cm and placement at 2 cm behind HCAL + TGeoBBox* alHcalBox = new TGeoBBox("AlHCalBox", SizeXHCAL / 2.0, SizeYHCAL / 2.0, 0.5 / 2.0); + TGeoVolume* volumeAlHcalBox = new TGeoVolume("volAlHcalBox", alHcalBox, gGeoManager->GetMedium(getMediumID(ID_ALUMINIUM))); + volumeAlHcalBox->SetLineColor(kOrange); + if (mGeometry->getInsertHCalReadoutMaterial()) { + gMC->Gspos("volAlHcalBox", 9999, "FOCAL", 0.0, 0.0, +1.0 * mGeometry->getFOCALSizeZ() / 2.0 + 1.0, 0, "ONLY"); + } + TGeoBBox* alUnderBox = new TGeoBBox("AlUnderBox", SizeXHCAL / 2.0, 0.5, mGeometry->getFOCALSizeZ() / 2.0 + 1.5); + TGeoVolume* volumeAlUnderBox = new TGeoVolume("volAlUnderBox", alUnderBox, gGeoManager->GetMedium(getMediumID(ID_ALUMINIUM))); + volumeAlUnderBox->SetLineColor(kOrange); + if (mGeometry->getInsertHCalReadoutMaterial()) { + gMC->Gspos("volAlUnderBox", 9999, "FOCAL", 0.0, -1.0 * mGeometry->getFOCALSizeY() / 2 - 10.5, 0.0, 0, "ONLY"); + } + + TGeoVolume* volFOCAL = gGeoManager->GetVolume("FOCAL"); + volFOCAL->AddNode(volHCAL, 1, new TGeoTranslation(0, 0, mGeometry->getHCALCenterZ() - mGeometry->getFOCALSizeZ() / 2 + 0.01 + (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) - (mGeometry->getInsertHCalReadoutMaterial() ? 1.5 : 0.0))); // 0.01 to avoid overlap with ECAL } void Detector::BeginPrimary() { - mCurrentPrimaryID = fMC->GetStack()->GetCurrentTrackNumber(); - LOG(debug) << "Starting primary " << mCurrentPrimaryID << " with energy " << fMC->GetStack()->GetCurrentTrack()->Energy(); + mCurrentPrimaryID = gMC->GetStack()->GetCurrentTrackNumber(); + LOG(debug) << "Starting primary " << mCurrentPrimaryID << " with energy " << gMC->GetStack()->GetCurrentTrack()->Energy(); } void Detector::FinishPrimary() diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index 826cb0ea06ade..ac50fd5775875 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -139,6 +139,7 @@ o2_add_test_root_macro(build_geometry.C O2::PHOSSimulation O2::CPVSimulation O2::ZDCSimulation + O2::FOCALSimulation ${upgradeTargets}) o2_add_test_root_macro(checkTOFMatching.C diff --git a/macro/build_geometry.C b/macro/build_geometry.C index aebfbee7ce283..e7361c499d3b5 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -329,6 +330,11 @@ void build_geometry(FairRunSim* run = nullptr) addReadoutDetector(new o2::zdc::Detector(isReadout("ZDC"))); } + if (isActivated("FOC")) { + // FOCAL + addReadoutDetector(new o2::focal::Detector(isReadout("FOC"), gSystem->ExpandPathName("$GEOMPATH/FOC/geometryFiles/geometry_Spaghetti.txt"))); + } + if (geomonly) { run->Init(); } diff --git a/run/CMakeLists.txt b/run/CMakeLists.txt index b1d09db4d02c8..fccb3f0085642 100644 --- a/run/CMakeLists.txt +++ b/run/CMakeLists.txt @@ -37,6 +37,7 @@ target_link_libraries(allsim O2::TRDSimulation O2::FV0Simulation O2::ZDCSimulation + O2::FOCALSimulation $<$:O2::Alice3DetectorsPassive> $<$:O2::ITS3Simulation> $<$:O2::TRKSimulation> diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index 543aa9f48cae7..d2260e634005d 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -56,6 +56,7 @@ #include #include #include +#include #include "CommonUtils/ShmManager.h" #include @@ -837,8 +838,8 @@ class O2HitMerger : public fair::mq::Device std::string mOutFileName; //! // structures for the final flush - TFile* mOutFile; //! outfile for kinematics - TTree* mOutTree; //! tree (kinematics) associated to mOutFile + TFile* mOutFile; //! outfile for kinematics + TTree* mOutTree; //! tree (kinematics) associated to mOutFile TFile* mMCHeaderOnlyOutFile; //! outfile for header only information TTree* mMCHeaderTree; //! tree to hold MCHeader branch in mMCHeaderOnlyOutFile; @@ -982,6 +983,10 @@ void O2HitMerger::initDetInstances() mDetectorInstances[i] = std::move(std::make_unique(true)); counter++; } + if (i == DetID::FOC) { + mDetectorInstances[i] = std::move(std::make_unique(true, gSystem->ExpandPathName("$VMCWORKDIR/Detectors/Geometry/FOC/geometryFiles/geometry_Spaghetti.txt"))); + counter++; + } #ifdef ENABLE_UPGRADES if (i == DetID::IT3) { mDetectorInstances[i] = std::move(std::make_unique(true, "IT3")); diff --git a/run/o2simdefaultdetectorlist.json b/run/o2simdefaultdetectorlist.json index 752d3633672ac..001df688c91f7 100644 --- a/run/o2simdefaultdetectorlist.json +++ b/run/o2simdefaultdetectorlist.json @@ -11,6 +11,7 @@ "MCH", "MID", "ZDC", + "FOC", "FT0", "FV0", "FDD", From c78296cf6393a3d8b40e40d4bfded0b4857980e4 Mon Sep 17 00:00:00 2001 From: Hadi Hassan Date: Tue, 18 Jun 2024 14:59:08 +0300 Subject: [PATCH 0329/2997] changing gMC to fMC and moving FOCAL to caveRB24 --- Detectors/FOCAL/base/src/Geometry.cxx | 4 +- Detectors/FOCAL/simulation/data/simcuts.dat | 2 +- .../simulation/geometryFiles/geometry.txt | 12 ++-- .../geometryFiles/geometry_Spaghetti.txt | 16 ++--- Detectors/FOCAL/simulation/src/Detector.cxx | 70 ++++++++++--------- macro/build_geometry.C | 2 +- run/O2HitMerger.h | 2 +- run/o2simdefaultdetectorlist.json | 1 - 8 files changed, 55 insertions(+), 54 deletions(-) diff --git a/Detectors/FOCAL/base/src/Geometry.cxx b/Detectors/FOCAL/base/src/Geometry.cxx index c58745a681c6c..94d8c2cee049c 100644 --- a/Detectors/FOCAL/base/src/Geometry.cxx +++ b/Detectors/FOCAL/base/src/Geometry.cxx @@ -578,8 +578,8 @@ void Geometry::setParameters(std::string geometryfile) } } } // end for itowerY - } // end for itowerX - } // end else + } // end for itowerX + } // end else center_z += tmpComp.getThickness(); } // end loop over pad layer compositions LOG(debug) << "============ Created all pad layer compositions (" << mPadCompositionBase.size() << " volumes)"; diff --git a/Detectors/FOCAL/simulation/data/simcuts.dat b/Detectors/FOCAL/simulation/data/simcuts.dat index 3154dc4472e68..1ef7260bc34be 100644 --- a/Detectors/FOCAL/simulation/data/simcuts.dat +++ b/Detectors/FOCAL/simulation/data/simcuts.dat @@ -1,4 +1,4 @@ -* FOCAL +* FOCAL * ==== * * Med GAM ELEC NHAD CHAD MUON EBREM MUHAB EDEL MUDEL MUPA ANNI BREM COMP DCAY DRAY HADR LOSS MULS PAIR PHOT RAYL STRA diff --git a/Detectors/FOCAL/simulation/geometryFiles/geometry.txt b/Detectors/FOCAL/simulation/geometryFiles/geometry.txt index c6ca6d4f8a64b..a0508ab16e408 100644 --- a/Detectors/FOCAL/simulation/geometryFiles/geometry.txt +++ b/Detectors/FOCAL/simulation/geometryFiles/geometry.txt @@ -1,5 +1,5 @@ # Pad layer materials updated to match the setup used in test beams. Total thickness is 8.5mm -# Volume Name Material C-X C-Y X Y Z +# Volume Name Material C-X C-Y X Y Z COMPOSITION_PAD_S0 Alloy 0 0 9. 8. 0.35 COMPOSITION_PAD_S1 G10 0 0 9. 8. 0.08 COMPOSITION_PAD_S2 SiPad 0 0 9. 8. 0.03 @@ -9,7 +9,7 @@ # Replica of above pad layers to 50 layers COMMAND_NUMBER_OF_PAD_LAYERS 18 # HCAL layers -# Volume Name Material C-X C-Y X Y Z +# Volume Name Material C-X C-Y X Y Z COMPOSITION_HCAL_S0 Pb 0 0 2.5 2.5 3.0 COMPOSITION_HCAL_S1 Scint 0 0 2.5 2.5 0.2 COMMAND_NUMBER_OF_HCAL_LAYERS 34 @@ -24,8 +24,8 @@ COMPOSITION_PIX_S4 G10 0 0 3.0 2.74 0.1 COMPOSITION_PIX_S5 Cu 0 0 3.0 2.74 0.001 COMPOSITION_PIX_S6 Air 0 0 3.0 2.74 0.249 -COMMAND_INSERT_PIX_AT_L4 -COMMAND_INSERT_PIX_AT_L9 +COMMAND_INSERT_PIX_AT_L4 +COMMAND_INSERT_PIX_AT_L9 # COMMAND_INSERT_STR_AT_L4 # COMMAND_INSERT_STR_AT_L6 # COMMAND_INSERT_STR_AT_L8 @@ -63,8 +63,8 @@ COMMAND_INSERT_PIX_AT_L9 GLOBAL_FOCAL_Z 762.9 GLOBAL_Tower_NX 2 GLOBAL_Tower_NY 11 - GLOBAL_MIDDLE_TOWER_OFFSET 5 - GLOBAL_NSTRIPS 128 + GLOBAL_MIDDLE_TOWER_OFFSET 5 + GLOBAL_NSTRIPS 128 GLOBAL_STRIPSIZE_LONG 9.0 GLOBAL_STRIPSIZE_WIDTH 0.07 GLOBAL_HCAL_TOWER_SIZE 2.5 diff --git a/Detectors/FOCAL/simulation/geometryFiles/geometry_Spaghetti.txt b/Detectors/FOCAL/simulation/geometryFiles/geometry_Spaghetti.txt index f66ef50ad5ea4..ff24f0bfec34a 100644 --- a/Detectors/FOCAL/simulation/geometryFiles/geometry_Spaghetti.txt +++ b/Detectors/FOCAL/simulation/geometryFiles/geometry_Spaghetti.txt @@ -1,4 +1,4 @@ -# Volume Name Material C-X C-Y X Y Z +# Volume Name Material C-X C-Y X Y Z COMPOSITION_PAD_S0 Alloy 0 0 9. 8. 0.35 COMPOSITION_PAD_S1 G10 0 0 9. 8. 0.08 COMPOSITION_PAD_S2 SiPad 0 0 9. 8. 0.03 @@ -8,12 +8,12 @@ # Replica of above pad layers to 50 layers COMMAND_NUMBER_OF_PAD_LAYERS 18 # HCAL layers -# Volume Name Material C-X C-Y X Y Z +# Volume Name Material C-X C-Y X Y Z COMPOSITION_HCAL_S1 Scint 0 0 0.1 0.1 110 COMPOSITION_HCAL_S0 CuHCAL 0 0 0.25 0.25 110 COMMAND_NUMBER_OF_HCAL_LAYERS 1 COMMAND_NUMBER_OF_SEGMENTS 21 -# Strip sectors +# Strip sectors # Volume Name Material C-X C-Y X Y Z COMPOSITION_PIX_S0 Alloy 0 0 3.0 2.74 0.35 COMPOSITION_PIX_S1 G10 0 0 3.0 2.74 0.1 @@ -21,9 +21,9 @@ COMPOSITION_PIX_S3 SiPix 0 0 3.0 2.74 0.003 COMPOSITION_PIX_S4 G10 0 0 3.0 2.74 0.1 COMPOSITION_PIX_S5 Cu 0 0 3.0 2.74 0.001 - COMPOSITION_PIX_S6 Air 0 0 3.0 2.74 0.249 -COMMAND_INSERT_PIX_AT_L4 -COMMAND_INSERT_PIX_AT_L9 + COMPOSITION_PIX_S6 Air 0 0 3.0 2.74 0.249 +COMMAND_INSERT_PIX_AT_L4 +COMMAND_INSERT_PIX_AT_L9 # COMMAND_INSERT_STR_AT_L4 # COMMAND_INSERT_STR_AT_L6 # COMMAND_INSERT_STR_AT_L8 @@ -61,8 +61,8 @@ COMMAND_INSERT_PIX_AT_L9 GLOBAL_FOCAL_Z 764.47 GLOBAL_Tower_NX 2 GLOBAL_Tower_NY 11 - GLOBAL_MIDDLE_TOWER_OFFSET 5 - GLOBAL_NSTRIPS 128 + GLOBAL_MIDDLE_TOWER_OFFSET 5 + GLOBAL_NSTRIPS 128 GLOBAL_STRIPSIZE_LONG 9.0 GLOBAL_STRIPSIZE_WIDTH 0.07 GLOBAL_HCAL_TOWER_SIZE 6.55 diff --git a/Detectors/FOCAL/simulation/src/Detector.cxx b/Detectors/FOCAL/simulation/src/Detector.cxx index 813821efa86ab..e67615901a885 100644 --- a/Detectors/FOCAL/simulation/src/Detector.cxx +++ b/Detectors/FOCAL/simulation/src/Detector.cxx @@ -86,13 +86,13 @@ void Detector::InitializeO2Detector() Bool_t Detector::ProcessHits(FairVolume* v) { - int track = gMC->GetStack()->GetCurrentTrackNumber(), - directparent = gMC->GetStack()->GetCurrentParentTrackNumber(); + int track = fMC->GetStack()->GetCurrentTrackNumber(), + directparent = fMC->GetStack()->GetCurrentParentTrackNumber(); // Like other calorimeters FOCAL will create a huge amount of shower particles during tracking // Instead, the hits should be assigned to the incoming particle in FOCAL. // Implementation of the incoming particle search taken from implementation in EMCAL. if (track != mCurrentTrack) { - LOG(debug4) << "Doing new track " << track << " current (" << mCurrentTrack << "), direct parent (" << directparent << ")" << std::endl; + LOG(debug4) << "Doing new track " << track << " current (" << mCurrentTrack << "), direct parent (" << directparent << ")"; // new current track - check parentage auto hasSuperParent = mSuperParentsIndices.find(directparent); if (hasSuperParent != mSuperParentsIndices.end()) { @@ -106,39 +106,39 @@ Bool_t Detector::ProcessHits(FairVolume* v) LOG(error) << "Attention: No superparent object found (parent " << mCurrentParentID << ")"; mCurrentSuperparent = nullptr; } - LOG(debug4) << "Found superparent " << mCurrentParentID << std::endl; + LOG(debug4) << "Found superparent " << mCurrentParentID; } else { // start of new chain // for new incoming tracks the super parent index is equal to the track ID (for recursion) mSuperParentsIndices[track] = track; - mCurrentSuperparent = AddSuperparent(track, gMC->TrackPid(), gMC->Etot()); + mCurrentSuperparent = AddSuperparent(track, fMC->TrackPid(), fMC->Etot()); mCurrentParentID = track; } mCurrentTrack = track; } // Processing HCAL hits - if (gMC->CurrentMedium() == mMedSensHCal) { - LOG(debug) << "We are in sensitive volume " << v->GetName() << ": " << gMC->CurrentVolPath() << std::endl; + if (fMC->CurrentMedium() == mMedSensHCal) { + LOG(debug) << "We are in sensitive volume " << v->GetName() << ": " << fMC->CurrentVolPath(); - double eloss = gMC->Edep() * 1e9; // energy in eV (GeV->eV) + double eloss = fMC->Edep() * 1e9; // energy in eV (GeV->eV) if (eloss < DBL_EPSILON) { return false; // only process hits which actually deposit some energy in the FOCAL } // In case of new parent track create new track reference - auto o2stack = static_cast(gMC->GetStack()); + auto o2stack = static_cast(fMC->GetStack()); if (!mCurrentSuperparent->mHasTrackReference) { float x, y, z, px, py, pz, e; - gMC->TrackPosition(x, y, z); - gMC->TrackMomentum(px, py, pz, e); - o2::TrackReference trackref(x, y, z, px, py, pz, gMC->TrackLength(), gMC->TrackTime(), mCurrentParentID, GetDetId()); + fMC->TrackPosition(x, y, z); + fMC->TrackMomentum(px, py, pz, e); + o2::TrackReference trackref(x, y, z, px, py, pz, fMC->TrackLength(), fMC->TrackTime(), mCurrentParentID, GetDetId()); o2stack->addTrackReference(trackref); mCurrentSuperparent->mHasTrackReference = true; } float posX, posY, posZ; - gMC->TrackPosition(posX, posY, posZ); + fMC->TrackPosition(posX, posY, posZ); auto [indetector, col, row, layer, segment] = mGeometry->getVirtualInfo(posX, posY, posZ); @@ -153,14 +153,14 @@ Bool_t Detector::ProcessHits(FairVolume* v) // - Processing different partent track (parent track must be produced outside FOCAL) // - Inside different cell // - First track of the event - Double_t time = gMC->TrackTime() * 1e9; // time in ns - LOG(debug3) << "Adding new hit for parent " << mCurrentParentID << " and cell Col: " << col << " Row: " << row << " segment: " << segment << std::endl; + Double_t time = fMC->TrackTime() * 1e9; // time in ns + LOG(debug3) << "Adding new hit for parent " << mCurrentParentID << " and cell Col: " << col << " Row: " << row << " segment: " << segment; /// check handling of primary particles AddHit(mCurrentParentID, mCurrentPrimaryID, mCurrentSuperparent->mEnergy, row * col + col, o2::focal::Hit::Subsystem_t::HCAL, math_utils::Point3D(posX, posY, posZ), time, eloss); o2stack->addHit(GetDetId()); } else { - LOG(debug3) << "Adding energy to the current hit" << std::endl; + LOG(debug3) << "Adding energy to the current hit"; currenthit->SetEnergyLoss(currenthit->GetEnergyLoss() + eloss); } } @@ -311,10 +311,10 @@ float acer[2],zcer[2]; char namate[21]=""; float a,z,d,radl,absl,buf[1]; Int_t nbuf; -gMC->Gfmate((*fIdmate)[6], namate, a, z, d, radl, absl, buf, nbuf); +fMC->Gfmate((*fIdmate)[6], namate, a, z, d, radl, absl, buf, nbuf); acer[0]=a; zcer[0]=z; -gMC->Gfmate((*fIdmate)[7], namate, a, z, d, radl, absl, buf, nbuf); +fMC->Gfmate((*fIdmate)[7], namate, a, z, d, radl, absl, buf, nbuf); acer[1]=a; zcer[1]=z; @@ -410,7 +410,7 @@ void Detector::addAlignableVolumes() const //____________________________________________________________________________ void Detector::addAlignableVolumesHCAL() const { - TString vpsector = "/cave_1/barrel_1/FOCAL_1/HCAL_1"; + TString vpsector = "/cave_1/caveRB24_1/FOCAL_1/HCAL_1"; TString snsector = "FOCAL/HCAL"; if (!gGeoManager->SetAlignableEntry(snsector.Data(), vpsector.Data())) { @@ -449,9 +449,9 @@ void Detector::ConstructGeometry() pars[3] = 0; LOG(info) << "Creating FOCAL with dimensions X: " << (mGeometry->getFOCALSizeX() + 2 * mGeometry->getMiddleTowerOffset()) << ", Y: " - << mGeometry->getFOCALSizeY() << ", Z: " << mGeometry->getFOCALSizeZ() + (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) + (mGeometry->getInsertHCalReadoutMaterial() ? 3.0 : 0.0) << std::endl; + << mGeometry->getFOCALSizeY() << ", Z: " << mGeometry->getFOCALSizeZ() + (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) + (mGeometry->getInsertHCalReadoutMaterial() ? 3.0 : 0.0); - gMC->Gsvolu("FOCAL", "BOX", getMediumID(ID_AIR), pars, 4); + TVirtualMC::GetMC()->Gsvolu("FOCAL", "BOX", getMediumID(ID_AIR), pars, 4); mSensitiveHCAL.push_back("FOCAL"); if (mGeometry->getUseHCALSandwich()) { @@ -459,8 +459,8 @@ void Detector::ConstructGeometry() } else { CreateHCALSpaghetti(); } - - gMC->Gspos("FOCAL", 1, "barrel", 0, 0, mGeometry->getFOCALZ0() - (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) + (mGeometry->getInsertHCalReadoutMaterial() ? 1.5 : 0.0), 0, "ONLY"); + const float z0 = 1312.5; // center of caveRB24 mother volume + TVirtualMC::GetMC()->Gspos("FOCAL", 1, "caveRB24", 0, 0, mGeometry->getFOCALZ0() - (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) + (mGeometry->getInsertHCalReadoutMaterial() ? 1.5 : 0.0) - z0, 0, "ONLY"); } void Detector::CreateHCALSpaghetti() @@ -590,8 +590,8 @@ void Detector::CreateHCALSpaghetti() } } - std::cout << "Number of Towers is: " << (NumTowers - 1) << std::endl; - std::cout << "Number of tubes is: " << (NumTubes - 1) * (NumTowers - 1) << std::endl; + LOG(info) << "Number of Towers is: " << (NumTowers - 1); + LOG(info) << "Number of tubes is: " << (NumTubes - 1) * (NumTowers - 1); // Create Aluminium plate at the back of HCal to simulate the electronics readout material // Hardcoded thickness of 1cm and placement at 2 cm behind HCAL @@ -599,18 +599,20 @@ void Detector::CreateHCALSpaghetti() TGeoVolume* volumeAlHcalBox = new TGeoVolume("volAlHcalBox", alHcalBox, gGeoManager->GetMedium(getMediumID(ID_ALUMINIUM))); volumeAlHcalBox->SetLineColor(kOrange); if (mGeometry->getInsertHCalReadoutMaterial()) { - gMC->Gspos("volAlHcalBox", 9999, "FOCAL", 0.0, 0.0, +1.0 * mGeometry->getFOCALSizeZ() / 2.0 + 1.0, 0, "ONLY"); + TVirtualMC::GetMC()->Gspos("volAlHcalBox", 9999, "FOCAL", 0.0, 0.0, +1.0 * mGeometry->getFOCALSizeZ() / 2.0 + 1.0, 0, "ONLY"); mSensitiveHCAL.push_back("volAlHcalBox"); } TGeoBBox* alUnderBox = new TGeoBBox("AlUnderBox", SizeXHCAL / 2.0, 0.5, mGeometry->getFOCALSizeZ() / 2.0 + 1.5); TGeoVolume* volumeAlUnderBox = new TGeoVolume("volAlUnderBox", alUnderBox, gGeoManager->GetMedium(getMediumID(ID_ALUMINIUM))); volumeAlUnderBox->SetLineColor(kOrange); if (mGeometry->getInsertHCalReadoutMaterial()) { - gMC->Gspos("volAlUnderBox", 9999, "FOCAL", 0.0, -1.0 * mGeometry->getFOCALSizeY() / 2 - 10.5, 0.0, 0, "ONLY"); + TVirtualMC::GetMC()->Gspos("volAlUnderBox", 9999, "FOCAL", 0.0, -1.0 * mGeometry->getFOCALSizeY() / 2 - 10.5, 0.0, 0, "ONLY"); mSensitiveHCAL.push_back("volAlUnderBox"); } - gMC->Gspos("HCAL", 1, "FOCAL", 0, 0, mGeometry->getHCALCenterZ() - mGeometry->getFOCALSizeZ() / 2 + 0.01 + (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) - (mGeometry->getInsertHCalReadoutMaterial() ? 1.5 : 0.0), 0, "ONLY"); + volHCAL->SetVisibility(); + volHCAL->SetVisDaughters(); + TVirtualMC::GetMC()->Gspos("HCAL", 1, "FOCAL", 0, 0, mGeometry->getHCALCenterZ() - mGeometry->getFOCALSizeZ() / 2 + 0.01 + (mGeometry->getInsertFrontPadLayers() ? 2.0 : 0.0) - (mGeometry->getInsertHCalReadoutMaterial() ? 1.5 : 0.0), 0, "ONLY"); } //_____________________________________________________________________________ @@ -711,7 +713,7 @@ void Detector::CreateHCALSandwich() NumTowers++; } } - std::cout << "Number of Towers is: " << (NumTowers - 1) << std::endl; + LOG(info) << "Number of Towers is: " << (NumTowers - 1); // Create an Aluminium plate at the back of HCal to simulate the electronics readout material // Hardcoded thickness of 1cm and placement at 2 cm behind HCAL @@ -719,13 +721,13 @@ void Detector::CreateHCALSandwich() TGeoVolume* volumeAlHcalBox = new TGeoVolume("volAlHcalBox", alHcalBox, gGeoManager->GetMedium(getMediumID(ID_ALUMINIUM))); volumeAlHcalBox->SetLineColor(kOrange); if (mGeometry->getInsertHCalReadoutMaterial()) { - gMC->Gspos("volAlHcalBox", 9999, "FOCAL", 0.0, 0.0, +1.0 * mGeometry->getFOCALSizeZ() / 2.0 + 1.0, 0, "ONLY"); + TVirtualMC::GetMC()->Gspos("volAlHcalBox", 9999, "FOCAL", 0.0, 0.0, +1.0 * mGeometry->getFOCALSizeZ() / 2.0 + 1.0, 0, "ONLY"); } TGeoBBox* alUnderBox = new TGeoBBox("AlUnderBox", SizeXHCAL / 2.0, 0.5, mGeometry->getFOCALSizeZ() / 2.0 + 1.5); TGeoVolume* volumeAlUnderBox = new TGeoVolume("volAlUnderBox", alUnderBox, gGeoManager->GetMedium(getMediumID(ID_ALUMINIUM))); volumeAlUnderBox->SetLineColor(kOrange); if (mGeometry->getInsertHCalReadoutMaterial()) { - gMC->Gspos("volAlUnderBox", 9999, "FOCAL", 0.0, -1.0 * mGeometry->getFOCALSizeY() / 2 - 10.5, 0.0, 0, "ONLY"); + TVirtualMC::GetMC()->Gspos("volAlUnderBox", 9999, "FOCAL", 0.0, -1.0 * mGeometry->getFOCALSizeY() / 2 - 10.5, 0.0, 0, "ONLY"); } TGeoVolume* volFOCAL = gGeoManager->GetVolume("FOCAL"); @@ -734,13 +736,13 @@ void Detector::CreateHCALSandwich() void Detector::BeginPrimary() { - mCurrentPrimaryID = gMC->GetStack()->GetCurrentTrackNumber(); - LOG(debug) << "Starting primary " << mCurrentPrimaryID << " with energy " << gMC->GetStack()->GetCurrentTrack()->Energy(); + mCurrentPrimaryID = fMC->GetStack()->GetCurrentTrackNumber(); + LOG(debug) << "Starting primary " << mCurrentPrimaryID << " with energy " << fMC->GetStack()->GetCurrentTrack()->Energy(); } void Detector::FinishPrimary() { - LOG(debug) << "Finishing primary " << mCurrentPrimaryID << std::endl; + LOG(debug) << "Finishing primary " << mCurrentPrimaryID; // Resetting primary and parent ID mCurrentPrimaryID = -1; } \ No newline at end of file diff --git a/macro/build_geometry.C b/macro/build_geometry.C index e7361c499d3b5..af74e7860ba3d 100644 --- a/macro/build_geometry.C +++ b/macro/build_geometry.C @@ -332,7 +332,7 @@ void build_geometry(FairRunSim* run = nullptr) if (isActivated("FOC")) { // FOCAL - addReadoutDetector(new o2::focal::Detector(isReadout("FOC"), gSystem->ExpandPathName("$GEOMPATH/FOC/geometryFiles/geometry_Spaghetti.txt"))); + addReadoutDetector(new o2::focal::Detector(isReadout("FOC"), gSystem->ExpandPathName("$O2_ROOT/share/Detectors/Geometry/FOC/geometryFiles/geometry_Spaghetti.txt"))); } if (geomonly) { diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index d2260e634005d..bd905548b58f3 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -984,7 +984,7 @@ void O2HitMerger::initDetInstances() counter++; } if (i == DetID::FOC) { - mDetectorInstances[i] = std::move(std::make_unique(true, gSystem->ExpandPathName("$VMCWORKDIR/Detectors/Geometry/FOC/geometryFiles/geometry_Spaghetti.txt"))); + mDetectorInstances[i] = std::move(std::make_unique(true, gSystem->ExpandPathName("$O2_ROOT/share/Detectors/Geometry/FOC/geometryFiles/geometry_Spaghetti.txt"))); counter++; } #ifdef ENABLE_UPGRADES diff --git a/run/o2simdefaultdetectorlist.json b/run/o2simdefaultdetectorlist.json index 001df688c91f7..752d3633672ac 100644 --- a/run/o2simdefaultdetectorlist.json +++ b/run/o2simdefaultdetectorlist.json @@ -11,7 +11,6 @@ "MCH", "MID", "ZDC", - "FOC", "FT0", "FV0", "FDD", From 5b3489da7e1799c31075f80f4aa5aa8ec3b5ced9 Mon Sep 17 00:00:00 2001 From: Hadi Hassan Date: Wed, 19 Jun 2024 15:31:01 +0300 Subject: [PATCH 0330/2997] Formatting --- Detectors/FOCAL/simulation/src/Detector.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Detectors/FOCAL/simulation/src/Detector.cxx b/Detectors/FOCAL/simulation/src/Detector.cxx index e67615901a885..b93e3294d0045 100644 --- a/Detectors/FOCAL/simulation/src/Detector.cxx +++ b/Detectors/FOCAL/simulation/src/Detector.cxx @@ -28,7 +28,7 @@ Detector::Detector(bool active, std::string geofilename) mHits(o2::utils::createSimVector()), mGeometry(nullptr), mMedSensHCal(-1), - mGeoCompositions(0x0), + mGeoCompositions(), mSuperParentsIndices(), mSuperParents(), mCurrentSuperparent(nullptr), @@ -380,11 +380,11 @@ AliMixture( 8, "Ceramic $", acer, zcer, denscer, 2, wcer); /// Si plate -> idtmed[3610]; Medium(ID_SIINSENS, "Si insens$", 1, 0, - 10.0, 0.1, 0.1, epsil, 0.001, 0, 0); + isxfld, sxmgmx, 10.0, 0.1, 0.1, epsil, 0.001, nullptr, 0); // Al for the cold plates Medium(ID_ALUMINIUM, "Aluminium$", 9, 0, - isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0); + isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, nullptr, 0); /// idtmed[3697] Medium(ID_VAC, "Vacuum $", 98, 0, @@ -487,7 +487,7 @@ void Detector::CreateHCALSpaghetti() volCuTube->SetLineWidth(2); volCuTube->SetLineColor(kRed); mSensitiveHCAL.push_back(volCuTube->GetName()); - HcalTube->AddNode(volCuTube, 1, 0x0); + HcalTube->AddNode(volCuTube, 1, nullptr); } if (icomp->material() == "Scint") { RScint = icomp->sizeX() / 2; @@ -497,7 +497,7 @@ void Detector::CreateHCALSpaghetti() volSciFi->SetLineWidth(2); volSciFi->SetLineColor(kBlue); mSensitiveHCAL.push_back(volSciFi->GetName()); - HcalTube->AddNode(volSciFi, 1, 0x0); + HcalTube->AddNode(volSciFi, 1, nullptr); } if (icomp->material() == "CuHCAL") { Rout = icomp->sizeX() / 2; @@ -506,7 +506,7 @@ void Detector::CreateHCALSpaghetti() volCuTube->SetLineWidth(2); volCuTube->SetLineColor(kRed); mSensitiveHCAL.push_back(volCuTube->GetName()); - HcalTube->AddNode(volCuTube, 1, 0x0); + HcalTube->AddNode(volCuTube, 1, nullptr); } } @@ -522,7 +522,7 @@ void Detector::CreateHCALSpaghetti() mSensitiveHCAL.push_back(volTower->GetName()); TGeoVolumeAssembly* volTowerHCAL = new TGeoVolumeAssembly("volTowerHCAL"); - volTowerHCAL->AddNode(volTower, 1, 0x0); + volTowerHCAL->AddNode(volTower, 1, nullptr); int Rows = 0; float RowPos = 0.; From 67d4c675a3b4d8b51cdfc94feca64d833ccf4b9b Mon Sep 17 00:00:00 2001 From: KirillVNaumov <43657972+KirillVNaumov@users.noreply.github.com> Date: Thu, 20 Jun 2024 13:27:28 +0200 Subject: [PATCH 0331/2997] ITS: Fix placement of REGION HEADERS during ALPIDE data encoding (#13229) * ITS: Fix placement of REGION HEADERS during ALPIDE data encoding REGION HEADERS must be placed exactly once per region with detected hits, not before every hit within a region. * Fix missing braces --------- Co-authored-by: Kirill Naumov Co-authored-by: Giulio Eulisse <10544+ktf@users.noreply.github.com> --- .../common/reconstruction/src/AlpideCoder.cxx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx b/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx index f557e1141fd2f..cfea32eb383a9 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/AlpideCoder.cxx @@ -53,7 +53,15 @@ int AlpideCoder::encodeChip(PayLoadCont& buffer, const o2::itsmft::ChipPixelData } buffer.addFast(makeChipHeader(chipInModule, bc)); // chip header for (int ir = 0; ir < NRegions; ir++) { - nfound += procRegion(buffer, ir); + // For each region, we encode a REGION HEADER flag immediately + // to ensure its uniqueness. + buffer.addFast(makeRegion(ir)); + int nfoundInRegion = procRegion(buffer, ir); + nfound += nfoundInRegion; + // If the region was unpopulated, we remove REGION HEADER flag. + if (!nfoundInRegion) { + buffer.erase(1); + } } buffer.addFast(makeChipTrailer(roflags)); resetMap(); @@ -114,10 +122,6 @@ int AlpideCoder::procDoubleCol(PayLoadCont& buffer, short reg, short dcol) } // int ih = 0; - if (nHits) { - buffer.addFast(makeRegion(reg)); // flag region start - } - while ((ih < nHits)) { short addrE, addrW = hits[ih++]; // address of the reference hit uint8_t mask = 0; From 4d2f4aa37639b4622e00fa748d85ef8f178f4a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Thu, 20 Jun 2024 13:11:54 +0200 Subject: [PATCH 0332/2997] MC: Remove unsupported parameter from Pythia 8 example --- run/SimExamples/McTracksToAOD/run_Pythia8.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run/SimExamples/McTracksToAOD/run_Pythia8.sh b/run/SimExamples/McTracksToAOD/run_Pythia8.sh index 104c1d97ebaf3..8bac774c5892b 100755 --- a/run/SimExamples/McTracksToAOD/run_Pythia8.sh +++ b/run/SimExamples/McTracksToAOD/run_Pythia8.sh @@ -9,7 +9,7 @@ NEVENTS=1000 # --aggregate-timeframe 10 is used to combine 10 generated events into a timeframe that is then converted to AOD tables # note that if you need special configuration for the analysis tasks, it needs to be passed to proxy and converter as well -o2-sim-dpl-eventgen -b --nEvents ${NEVENTS} --aggregate-timeframe 10 --generator pythia8pp --confKeyValues "${CONFKEY}" --vertexMode kNoVertex |\ +o2-sim-dpl-eventgen -b --nEvents ${NEVENTS} --aggregate-timeframe 10 --generator pythia8pp --vertexMode kNoVertex |\ o2-sim-mctracks-to-aod -b | o2-analysis-mctracks-to-aod-simple-task -b &> pythia8.log # the very same analysis task can also directly run on an AO2D with McCollisions and McParticles: From 1ff11386421db7e4178501da8ec98e92053c503a Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 21 Jun 2024 08:37:10 +0200 Subject: [PATCH 0333/2997] CCDB: Ensure CCDBDownloader's libuv loop is properly deleted (#13238) My valgrind checks were showing that the internal CCDBDownloader's libuv loop resources were not fully released. With this fix, valgrind is happy. The change is based on the following premises: - `uv_loop_alive` returns true if there are *active* handles - `uv_loop_close` returns `UV_EBUSY` if there are *open* handles. - we need to succesfully call `uv_loop_close` to clear `mUVLoop` resources Thus, in case that we would not have *active* handles, we would never close *open* ones, and consequently would not manage to call `uv_loop_close` without getting `UV_EBUSY`. --- CCDB/src/CCDBDownloader.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CCDB/src/CCDBDownloader.cxx b/CCDB/src/CCDBDownloader.cxx index 8d13368688cb7..3f24d7db130a6 100644 --- a/CCDB/src/CCDBDownloader.cxx +++ b/CCDB/src/CCDBDownloader.cxx @@ -114,7 +114,7 @@ CCDBDownloader::~CCDBDownloader() if (!mExternalLoop) { // Schedule all handles to close. Execute loop to allow them to execute their destructors. - while (uv_loop_alive(mUVLoop) && uv_loop_close(mUVLoop) == UV_EBUSY) { + while (uv_loop_alive(mUVLoop) || (uv_loop_close(mUVLoop) == UV_EBUSY)) { uv_walk(mUVLoop, closeHandles, this); uv_run(mUVLoop, UV_RUN_ONCE); } From 01674840b6b44c0d87bb507464203e404be2e4ea Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 21 Jun 2024 18:53:05 +0200 Subject: [PATCH 0334/2997] Remove the obsolete NotBadFlagExample (#13152) * Remove the obsolete NotBadFlagExamply * remove from the test --- DataFormats/QualityControl/etc/flagTypes.csv | 1 - .../QualityControl/test/testQualityControlFlagCollection.cxx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/DataFormats/QualityControl/etc/flagTypes.csv b/DataFormats/QualityControl/etc/flagTypes.csv index b4504b0f8f896..97107cd15a9e7 100644 --- a/DataFormats/QualityControl/etc/flagTypes.csv +++ b/DataFormats/QualityControl/etc/flagTypes.csv @@ -12,4 +12,3 @@ 12,"BadEMCalorimetry","Bad EM Calorimetry",1,0 13,"BadPhotonCalorimetry","Bad Photon Calorimetry",1,0 14,"Unknown","Unknown",1,0 -65501,"NotBadFlagExample","Not bad flag example",0,0 \ No newline at end of file diff --git a/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx b/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx index 198ae29bc53a6..4eabfc5908741 100644 --- a/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx +++ b/DataFormats/QualityControl/test/testQualityControlFlagCollection.cxx @@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(test_QualityControlFlagCollection_IO) qcfc1.insert({51, 77, FlagTypeFactory::Invalid()}); qcfc1.insert({1234, 3434, FlagTypeFactory::LimitedAcceptanceMCNotReproducible()}); qcfc1.insert({50, 77, FlagTypeFactory::LimitedAcceptanceMCNotReproducible()}); - qcfc1.insert({43434, 63421, FlagTypeFactory::NotBadFlagExample()}); + qcfc1.insert({43434, 63421, FlagTypeFactory::Good()}); std::stringstream store; qcfc1.streamTo(store); From f5fb7afcf7cb163c7f229cede08408dae7bf6ccc Mon Sep 17 00:00:00 2001 From: iravasen Date: Fri, 21 Jun 2024 19:13:16 +0200 Subject: [PATCH 0335/2997] ITS Calib: log changes in noisecalib + new finalize-eor flag for thr calibration (#13222) * LOG info to important to make some useful logs to appear in infologger at the end of the run * changed finalized-eor calculations + new small fixes --- .../calibration/src/NoiseCalibratorSpec.cxx | 14 +-- .../ITSWorkflow/ThresholdCalibratorSpec.h | 4 +- .../workflow/src/ThresholdCalibratorSpec.cxx | 87 ++++++++++++++----- 3 files changed, 76 insertions(+), 29 deletions(-) diff --git a/Detectors/ITSMFT/ITS/calibration/src/NoiseCalibratorSpec.cxx b/Detectors/ITSMFT/ITS/calibration/src/NoiseCalibratorSpec.cxx index 700f38674eb7b..e50f5be3edf5e 100644 --- a/Detectors/ITSMFT/ITS/calibration/src/NoiseCalibratorSpec.cxx +++ b/Detectors/ITSMFT/ITS/calibration/src/NoiseCalibratorSpec.cxx @@ -105,13 +105,13 @@ void NoiseCalibratorSpec::run(ProcessingContext& pc) done = (++mNPartsDone == partInfo[1]); mStrobeCounter += partInfo[2]; mCalibrator->setNStrobes(mStrobeCounter); - LOGP(info, "Received accumulated map {} of {} with {} ROFs, total number of maps = {} and strobes = {}", partInfo[0] + 1, partInfo[1], partInfo[2], mNPartsDone, mCalibrator->getNStrobes()); + LOGP(important, "Received accumulated map {} of {} with {} ROFs, total number of maps = {} and strobes = {}", partInfo[0] + 1, partInfo[1], partInfo[2], mNPartsDone, mCalibrator->getNStrobes()); } if (done || pc.transitionState() == TransitionHandlingState::Requested) { if (done) { - LOG(info) << "Minimum number of noise counts has been reached !"; + LOG(important) << "Minimum number of noise counts has been reached !"; } else { - LOG(info) << "Run stop is requested, sending output"; + LOG(important) << "Run stop is requested, sending output"; } if (mMode == ProcessingMode::Full || mMode == ProcessingMode::Normalize) { sendOutput(pc.outputs()); @@ -134,7 +134,7 @@ void NoiseCalibratorSpec::sendAccumulatedMap(DataAllocator& output) outInf.push_back(mCalibrator->getNInstances()); outInf.push_back(mCalibrator->getNStrobes()); output.snapshot(Output{"ITS", "NOISEMAPPARTINF", (unsigned int)mCalibrator->getInstanceID()}, outInf); - LOGP(info, "Sending accumulated map with {} ROFs processed", mCalibrator->getNStrobes()); + LOGP(important, "Sending accumulated map with {} ROFs processed", mCalibrator->getNStrobes()); } void NoiseCalibratorSpec::sendOutput(DataAllocator& output) @@ -271,9 +271,9 @@ DataProcessorSpec getNoiseCalibratorSpec(bool useClusters, int pmode) inputs.emplace_back("ROframes", "ITS", "DIGITSROF", 0, Lifetime::Timeframe); } } else { - useClusters = false; // not needed for normalization - inputs.emplace_back("mapspart", ConcreteDataTypeMatcher{"ITS", "NOISEMAPPART"}, Lifetime::Sporadic); // for normalization of multiple inputs only - inputs.emplace_back("mapspartInfo", ConcreteDataTypeMatcher{"ITS", "NOISEMAPPARTINF"}, Lifetime::Sporadic); // for normalization of multiple inputs only + useClusters = false; // not needed for normalization + inputs.emplace_back("mapspart", ConcreteDataTypeMatcher{"ITS", "NOISEMAPPART"}, Lifetime::Sporadic); // for normalization of multiple inputs only + inputs.emplace_back("mapspartInfo", ConcreteDataTypeMatcher{"ITS", "NOISEMAPPARTINF"}, Lifetime::Sporadic); // for normalization of multiple inputs only } if (md == NoiseCalibratorSpec::ProcessingMode::Full || md == NoiseCalibratorSpec::ProcessingMode::Normalize) { inputs.emplace_back("confdbmap", "ITS", "CONFDBMAP", 0, Lifetime::Condition, ccdbParamSpec("ITS/Calib/Confdbmap")); diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h index d40c8a2cafce6..03340cd65faeb 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/ThresholdCalibratorSpec.h @@ -217,7 +217,7 @@ class ITSThresholdCalibrator : public Task int mTFCounter = 0; bool mVerboseOutput = false; - bool isFinalizeEos = false; + bool isForceEor = false; std::string mMetaType; std::string mOutputDir; std::string mMetafileDir = "/dev/null"; @@ -284,7 +284,7 @@ class ITSThresholdCalibrator : public Task // To set min and max ITHR and VCASN in the tuning scans short int inMinVcasn = 30; short int inMaxVcasn = 100; - short int inMinIthr = 30; + short int inMinIthr = 15; short int inMaxIthr = 100; // Flag to enable most-probable value calculation diff --git a/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx index 890a6633732ab..e78c419b78879 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/ThresholdCalibratorSpec.cxx @@ -205,7 +205,7 @@ void ITSThresholdCalibrator::init(InitContext& ic) nInjScaled = nInj; // Flag to enable the call of the finalize() method at end of stream - isFinalizeEos = ic.options().get("finalize-at-eos"); + isForceEor = ic.options().get("force-calculation-eor"); // flag to set the url ccdb mgr this->mCcdbMgrUrl = ic.options().get("ccdb-mgr-url"); @@ -1564,9 +1564,7 @@ void ITSThresholdCalibrator::run(ProcessingContext& pc) } if (!(this->mRunTypeUp)) { - if (!isFinalizeEos) { - finalize(); - } + finalize(); LOG(info) << "Shipping all outputs to aggregator (before endOfStream arrival!)"; pc.outputs().snapshot(Output{"ITS", "TSTR", (unsigned int)mChipModSel}, this->mTuning); pc.outputs().snapshot(Output{"ITS", "PIXTYP", (unsigned int)mChipModSel}, this->mPixStat); @@ -1582,9 +1580,7 @@ void ITSThresholdCalibrator::run(ProcessingContext& pc) } else if (pc.transitionState() == TransitionHandlingState::Requested) { LOG(info) << "Run stop requested during the scan, sending output to aggregator and then stopping to process new data"; mRunStopRequested = true; - if (!isFinalizeEos) { - finalize(); // calculating average thresholds based on what's collected up to this moment - } + finalize(); pc.outputs().snapshot(Output{"ITS", "TSTR", (unsigned int)mChipModSel}, this->mTuning); // dummy here pc.outputs().snapshot(Output{"ITS", "PIXTYP", (unsigned int)mChipModSel}, this->mPixStat); pc.outputs().snapshot(Output{"ITS", "RUNT", (unsigned int)mChipModSel}, this->mRunType); @@ -1812,7 +1808,22 @@ void ITSThresholdCalibrator::finalize() name = "VCASN"; auto it = this->mThresholds.cbegin(); while (it != this->mThresholds.cend()) { - if (!isFinalizeEos && (!mRunStopRequested && this->mRunTypeChip[it->first] < nInj)) { + int iRU = 0; + std::vector linkChips; + bool extractChip = false; + if (isForceEor && mRunTypeChip[it->first] < nInj) { + iRU = getRUID(it->first); + linkChips = getChipBoundariesFromRu(iRU, mActiveLinks[iRU]); + // check whether at least one chip on the same link reached the end of the scan + for (size_t i = 0; i < linkChips.size(); i++) { + if (mRunTypeChip[linkChips[i]] > nInj && linkChips[i] != it->first) { + extractChip = true; + break; + } + } + } + + if (!extractChip && (!mRunStopRequested && this->mRunTypeChip[it->first] < nInj)) { ++it; continue; } @@ -1835,7 +1846,21 @@ void ITSThresholdCalibrator::finalize() name = "ITHR"; auto it = this->mThresholds.cbegin(); while (it != this->mThresholds.cend()) { - if (!isFinalizeEos && (!mRunStopRequested && this->mRunTypeChip[it->first] < nInj)) { + int iRU = 0; + std::vector linkChips; + bool extractChip = false; + if (isForceEor && mRunTypeChip[it->first] < nInj) { + iRU = getRUID(it->first); + linkChips = getChipBoundariesFromRu(iRU, mActiveLinks[iRU]); + // check whether at least one chip on the same link reached the end of the scan + for (size_t i = 0; i < linkChips.size(); i++) { + if (mRunTypeChip[linkChips[i]] > nInj && linkChips[i] != it->first) { + extractChip = true; + break; + } + } + } + if (!extractChip && (!mRunStopRequested && this->mRunTypeChip[it->first] < nInj)) { ++it; continue; } @@ -1858,7 +1883,21 @@ void ITSThresholdCalibrator::finalize() name = "THR"; auto it = this->mThresholds.cbegin(); while (it != this->mThresholds.cend()) { - if (!isFinalizeEos && (!mRunStopRequested && this->mRunTypeChip[it->first] < nInj)) { + int iRU = 0; + std::vector linkChips; + bool extractChip = false; + if (isForceEor && mRunTypeChip[it->first] < nInj) { + iRU = getRUID(it->first); + linkChips = getChipBoundariesFromRu(iRU, mActiveLinks[iRU]); + // check whether at least one chip on the same link reached the end of the scan + for (size_t i = 0; i < linkChips.size(); i++) { + if (mRunTypeChip[linkChips[i]] > nInj && linkChips[i] != it->first) { + extractChip = true; + break; + } + } + } + if (!extractChip && (!mRunStopRequested && this->mRunTypeChip[it->first] < nInj)) { ++it; continue; } @@ -1881,7 +1920,21 @@ void ITSThresholdCalibrator::finalize() // Extract hits from the full matrix auto itchip = this->mPixelHits.cbegin(); while (itchip != this->mPixelHits.cend()) { // loop over chips collected - if (!isFinalizeEos && (!mRunStopRequested && this->mRunTypeChip[itchip->first] < nInj)) { + int iRU = 0; + std::vector linkChips; + bool extractChip = false; + if (isForceEor && mRunTypeChip[itchip->first] < nInj) { + iRU = getRUID(itchip->first); + linkChips = getChipBoundariesFromRu(iRU, mActiveLinks[iRU]); + // check whether at least one chip on the same link reached the end of the scan + for (size_t i = 0; i < linkChips.size(); i++) { + if (mRunTypeChip[linkChips[i]] > nInj && linkChips[i] != itchip->first) { + extractChip = true; + break; + } + } + } + if (!extractChip && (!mRunStopRequested && this->mRunTypeChip[itchip->first] < nInj)) { ++itchip; continue; } @@ -1929,7 +1982,7 @@ void ITSThresholdCalibrator::finalize() auto itchip = this->mPixelHits.cbegin(); while (itchip != mPixelHits.cend()) { int iRU = getRUID(itchip->first); - if (!isFinalizeEos && (!mRunStopRequested && mRunTypeRU[iRU] < nInj * getActiveLinks(mActiveLinks[iRU]))) { + if (!mRunStopRequested && mRunTypeRU[iRU] < nInj * getActiveLinks(mActiveLinks[iRU])) { ++itchip; continue; } @@ -1964,9 +2017,6 @@ void ITSThresholdCalibrator::endOfStream(EndOfStreamContext& ec) { if (!isEnded && !mRunStopRequested) { LOGF(info, "endOfStream report:", mSelfName); - if (isFinalizeEos) { - finalize(); - } this->finalizeOutput(); isEnded = true; } @@ -1979,9 +2029,6 @@ void ITSThresholdCalibrator::stop() { if (!isEnded) { LOGF(info, "stop() report:", mSelfName); - if (isFinalizeEos) { - finalize(); - } this->finalizeOutput(); isEnded = true; } @@ -2024,7 +2071,7 @@ DataProcessorSpec getITSThresholdCalibratorSpec(const ITSCalibInpConf& inpConf) {"ccdb-mgr-url", VariantType::String, "", {"CCDB url to download confDBmap"}}, {"min-vcasn", VariantType::Int, 30, {"Min value of VCASN in vcasn scan, default is 30"}}, {"max-vcasn", VariantType::Int, 100, {"Max value of VCASN in vcasn scan, default is 80"}}, - {"min-ithr", VariantType::Int, 30, {"Min value of ITHR in ithr scan, default is 30"}}, + {"min-ithr", VariantType::Int, 15, {"Min value of ITHR in ithr scan, default is 15"}}, {"max-ithr", VariantType::Int, 100, {"Max value of ITHR in ithr scan, default is 100"}}, {"manual-mode", VariantType::Bool, false, {"Flag to activate the manual mode in case run type is not recognized"}}, {"manual-min", VariantType::Int, 0, {"Min value of the variable used for the scan: use only in manual mode"}}, @@ -2044,7 +2091,7 @@ DataProcessorSpec getITSThresholdCalibratorSpec(const ITSCalibInpConf& inpConf) {"max-dump", VariantType::Int, -1, {"Maximum number of s-curves to dump in ROOT file per chip. Works with fit option and dump-scurves flag enabled. Default: dump all"}}, {"chip-dump", VariantType::String, "", {"Dump s-curves only for these Chip IDs (0 to 24119). If multiple IDs, write them separated by comma. Default is empty string: dump all"}}, {"calculate-slope", VariantType::Bool, false, {"For Pulse Shape 2D: if enabled it calculate the slope of the charge vs strobe delay trend for each pixel and fill it in the output tree"}}, - {"finalize-at-eos", VariantType::Bool, false, {"Call the finalize() method at the end of stream: to be used in case end-of-run flags are not available so to force calculations at end of run"}}, + {"force-calculation-eor", VariantType::Bool, false, {"Calculate the avg quantities (thr, noise, vcasn, etc) at EOR ignoring the number of EOR flags from ITSComm"}}, {"charge-a", VariantType::Int, 0, {"To use with --calculate-slope, it defines the charge (in DAC) for the 1st point used for the slope calculation"}}, {"charge-b", VariantType::Int, 0, {"To use with --calculate-slope, it defines the charge (in DAC) for the 2nd point used for the slope calculation"}}, {"meb-select", VariantType::Int, -1, {"Select from which multi-event buffer consider the hits: 0,1 or 2"}}, From 22a32c92e9b2347fbb9c7011d3b9ddbcbcd79f1b Mon Sep 17 00:00:00 2001 From: Chiara Zampolli Date: Fri, 21 Jun 2024 09:09:06 +0200 Subject: [PATCH 0336/2997] Bug fixes (bool --> float, histo filling) and a few improvements --- .../include/GLOQC/ITSTPCMatchingQCParams.h | 11 ++++++++-- Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h | 20 ++++++++++++++++++- Detectors/GLOQC/src/MatchITSTPCQC.cxx | 8 ++++++-- .../qc/src/ITSTPCMatchingQCSpec.cxx | 12 ++++++++--- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/Detectors/GLOQC/include/GLOQC/ITSTPCMatchingQCParams.h b/Detectors/GLOQC/include/GLOQC/ITSTPCMatchingQCParams.h index 001996feb4c69..799f9c526bec6 100644 --- a/Detectors/GLOQC/include/GLOQC/ITSTPCMatchingQCParams.h +++ b/Detectors/GLOQC/include/GLOQC/ITSTPCMatchingQCParams.h @@ -25,11 +25,18 @@ namespace gloqc // There are configurable params for TPC-ITS matching struct ITSTPCMatchingQCParams : public o2::conf::ConfigurableParamHelper { - float minPtCut = 0.1f; - float etaCut = 1.4f; + float minPtITSCut = 0.f; + float etaITSCut = 1e10f; + int32_t minNITSClustersCut = 0; + int32_t maxChi2PerClusterITS = 100000; + float minPtTPCCut = 0.1f; + float etaTPCCut = 0.9f; int32_t minNTPCClustersCut = 60; float minDCACut = 100.f; float minDCACutY = 10.f; + float minPtCut = 0.f; + float maxPtCut = 1e10f; + float etaCut = 1.e10f; float cutK0Mass = 0.05f; float maxEtaK0 = 0.8f; diff --git a/Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h b/Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h index ca4d2678722c6..035aada3a765f 100644 --- a/Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h +++ b/Detectors/GLOQC/include/GLOQC/MatchITSTPCQC.h @@ -268,7 +268,25 @@ class MatchITSTPCQC // K0 void setMaxK0Eta(float v) { mMaxEtaK0 = v; } void setRefitK0(bool v) { mRefit = v; } - void setCutK0Mass(bool v) { mCutK0Mass = v; } + void setCutK0Mass(float v) { mCutK0Mass = v; } + + void printParams() + { + LOG(info) << "minPtITSCut = " << mPtITSCut; + LOG(info) << "etaITSCut = " << mEtaITSCut; + LOG(info) << "minNITSClustersCut = " << mMinNClustersITS; + LOG(info) << "maxChi2PerClusterITS = " << mMaxChi2PerClusterITS; + LOG(info) << "minPtTPCCut = " << mPtTPCCut; + LOG(info) << "etaTPCCut = " << mEtaTPCCut; + LOG(info) << "minNTPCClustersCut = " << mNTPCClustersCut; + LOG(info) << "minDCACut = " << mDCATPCCut; + LOG(info) << "minDCACutY = " << mDCATPCCutY; + LOG(info) << "minPtCut = " << mPtCut; + LOG(info) << "maxPtCut = " << mPtMaxCut; + LOG(info) << "etaCut = " << mEtaCut; + LOG(info) << "cutK0Mass = " << mCutK0Mass; + LOG(info) << "maxEtaK0 = " << mMaxEtaK0; + } private: std::shared_ptr mDataRequest; diff --git a/Detectors/GLOQC/src/MatchITSTPCQC.cxx b/Detectors/GLOQC/src/MatchITSTPCQC.cxx index f810a5d2d4ef2..a0ae896105d2d 100644 --- a/Detectors/GLOQC/src/MatchITSTPCQC.cxx +++ b/Detectors/GLOQC/src/MatchITSTPCQC.cxx @@ -377,9 +377,12 @@ bool MatchITSTPCQC::init() if (mDoK0QC) { // V0s - mK0MassVsPt = new TH2F("mK0MassVsPt", "K0 invariant mass vs Pt", 100, 0.3, 0.7, 100, 0.f, 20.f); + mK0MassVsPt = new TH2F("mK0MassVsPt", "K0 invariant mass vs Pt; Pt [GeV/c]; K0s mass [GeV/c^2]", 100, 0.f, 20.f, 100, 0.3, 0.7); } + LOG(info) << "Printing configuration cuts"; + printParams(); + return true; } @@ -945,10 +948,11 @@ bool MatchITSTPCQC::processV0(int iv, o2::globaltracking::RecoContainer& recoDat if (mMaxEtaK0 < std::abs(v0sel.getEta())) { return false; } + LOG(info) << "Find K0 with mass " << std::sqrt(v0sel.calcMass2AsK0()); if (mCutK0Mass > 0 && std::abs(std::sqrt(v0sel.calcMass2AsK0()) - 0.497) > mCutK0Mass) { return false; } - mK0MassVsPt->Fill(std::sqrt(v0sel.calcMass2AsK0()), v0sel.getPt()); + mK0MassVsPt->Fill(v0sel.getPt(), std::sqrt(v0sel.calcMass2AsK0())); return true; } diff --git a/Detectors/GlobalTrackingWorkflow/qc/src/ITSTPCMatchingQCSpec.cxx b/Detectors/GlobalTrackingWorkflow/qc/src/ITSTPCMatchingQCSpec.cxx index f1de9698d9e70..fad4f9d36fb31 100644 --- a/Detectors/GlobalTrackingWorkflow/qc/src/ITSTPCMatchingQCSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/qc/src/ITSTPCMatchingQCSpec.cxx @@ -37,11 +37,18 @@ void ITSTPCMatchingQCDevice::init(InitContext& /*ic*/) mMatchITSTPCQC = std::make_unique(); mMatchITSTPCQC->setDataRequest(mDataRequest); mMatchITSTPCQC->setTrkSources(o2::dataformats::GlobalTrackID::getSourcesMask(mTrkSources)); - mMatchITSTPCQC->setPtCut(params.minPtCut); - mMatchITSTPCQC->setEtaCut(params.etaCut); + mMatchITSTPCQC->setMinPtITSCut(params.minPtITSCut); + mMatchITSTPCQC->setEtaITSCut(params.etaITSCut); + mMatchITSTPCQC->setMinNClustersITS(params.minNITSClustersCut); + mMatchITSTPCQC->setMaxChi2PerClusterITS(params.maxChi2PerClusterITS); + mMatchITSTPCQC->setMinPtTPCCut(params.minPtTPCCut); + mMatchITSTPCQC->setEtaTPCCut(params.etaTPCCut); mMatchITSTPCQC->setMinNTPCClustersCut(params.minNTPCClustersCut); mMatchITSTPCQC->setMinDCAtoBeamPipeDistanceCut(params.minDCACut); mMatchITSTPCQC->setMinDCAtoBeamPipeYCut(params.minDCACutY); + mMatchITSTPCQC->setPtCut(params.minPtCut); + mMatchITSTPCQC->setMaxPtCut(params.maxPtCut); + mMatchITSTPCQC->setEtaCut(params.etaCut); mMatchITSTPCQC->setCutK0Mass(params.cutK0Mass); mMatchITSTPCQC->setMaxK0Eta(params.maxEtaK0); o2::base::GRPGeomHelper::instance().setRequest(mCCDBRequest); @@ -100,7 +107,6 @@ void ITSTPCMatchingQCDevice::finaliseCCDB(ConcreteDataMatcher& matcher, void* ob return; } if (matcher == ConcreteDataMatcher("GLO", "SVPARAM", 0)) { - LOG(info) << "SVertexer Params updated from ccdb - but it should not happen... PLEASE CHECK"; return; } } From a067a54d92388c737205032f5520d6da3dc2f0ac Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 23 Jun 2024 22:46:45 +0200 Subject: [PATCH 0337/2997] Use voids to select packs --- Framework/Foundation/include/Framework/Pack.h | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/Framework/Foundation/include/Framework/Pack.h b/Framework/Foundation/include/Framework/Pack.h index f03476f4fdc0e..7f5d79d761666 100644 --- a/Framework/Foundation/include/Framework/Pack.h +++ b/Framework/Foundation/include/Framework/Pack.h @@ -99,17 +99,43 @@ constexpr auto interleave_pack(pack, pack) template using interleaved_pack_t = decltype(interleave_pack(P1{}, P2{})); +/// Marks as void the types that do not satisfy the condition +template