diff --git a/docs/src/api.md b/docs/src/api.md index 71e90560b1f4ea23b6e8ded522e39351e2c27e56..48b315016dcbcb80f4a5b0a8b3f8219df7b9b32c 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -126,6 +126,7 @@ CHClient ### General tools ```@docs +getevent categorize nthbitset most_frequent diff --git a/docs/src/examples/online_data.md b/docs/src/examples/online_data.md index 34b07e4609c8fb4d819326275bac7d3eb67d1204..ce1f62c7ff171cc21181ca45bbcf2f32e6fa949f 100644 --- a/docs/src/examples/online_data.md +++ b/docs/src/examples/online_data.md @@ -57,7 +57,7 @@ event = getevent(f.online, 2) when two numbers are passed, the first one is interpreted as `frame_index` and the second one as `trigger_counter`: ```@example 1 -event = getevent(f.offline, 127, 2) +event = getevent(f.online, 127, 1) ``` !!! note diff --git a/src/exports.jl b/src/exports.jl index a4b7b646278fa1f9e441dc847bdb665ac09124f7..0446c61cd78f9290feb9754107022a4a332075ca 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -117,6 +117,7 @@ isnb, most_frequent, nthbitset, triggered, +getevent, # Physics and math helpers CherenkovPhoton, diff --git a/src/root/offline.jl b/src/root/offline.jl index 6b40407b2531426d639fe8d7d7b84fd8533cd284..5dadd79c0acf99392d6a5f3d7f72897f6e414f27 100644 --- a/src/root/offline.jl +++ b/src/root/offline.jl @@ -152,6 +152,7 @@ end struct OfflineTree{T} _fobj::UnROOT.ROOTFile header::Union{MCHeader, Missing} + _frame_index_trigger_counter_lookup_map::Dict{Tuple{Int, Int}, Int} _t::T # carry the type to ensure type-safety function OfflineTree(fobj::UnROOT.ROOTFile) @@ -201,7 +202,7 @@ struct OfflineTree{T} header = "Head" ∈ keys(fobj) ? MCHeader(fobj["Head"]) : missing - new{typeof(t)}(fobj, header, t) + new{typeof(t)}(fobj, header, Dict{Tuple{Int, Int}, Int}(), t) end end OfflineTree(filename::AbstractString) = OfflineTree(UnROOT.ROOTFile(filename)) @@ -221,6 +222,7 @@ end Base.getindex(f::OfflineTree, r::UnitRange) = [f[idx] for idx ∈ r] Base.getindex(f::OfflineTree, mask::BitArray) = [f[idx] for (idx, selected) ∈ enumerate(mask) if selected] function Base.getindex(f::OfflineTree, idx::Integer) + idx > length(f) && throw(BoundsError(f, idx)) e = f._t[idx] # the event as NamedTuple: struct of arrays skip_mc_event_time = !hasproperty(e, :mc_event_time_Sec) diff --git a/src/root/online.jl b/src/root/online.jl index 248b8a5b783598f62342c9f8ca6695eb4d02c2d6..aa91483aa3559863a917bb7cd798c507a7e4ea70 100644 --- a/src/root/online.jl +++ b/src/root/online.jl @@ -141,6 +141,7 @@ struct OnlineTree _fobj::UnROOT.ROOTFile events::EventContainer summaryslices::SummarysliceContainer + _frame_index_trigger_counter_lookup_map::Dict{Tuple{Int, Int}, Int} function OnlineTree(fobj::UnROOT.ROOTFile) new(fobj, @@ -152,7 +153,8 @@ struct OnlineTree SummarysliceContainer( UnROOT.LazyBranch(fobj, "KM3NET_SUMMARYSLICE/KM3NET_SUMMARYSLICE/KM3NETDAQ::JDAQSummarysliceHeader"), UnROOT.LazyBranch(fobj, "KM3NET_SUMMARYSLICE/KM3NET_SUMMARYSLICE/vector<KM3NETDAQ::JDAQSummaryFrame>") - ) + ), + Dict{Tuple{Int, Int}, Int}() ) end diff --git a/src/tools/helpers.jl b/src/tools/helpers.jl index cfaa44c798fd9c18e60c1ba1935c214619b66ee5..d8149848e54d5d8c0dadc4d950fea7aeb4a25331 100644 --- a/src/tools/helpers.jl +++ b/src/tools/helpers.jl @@ -18,3 +18,43 @@ function Base.iterate(itr::MCEventMatcher, state=1) state > length(itr) && return nothing (itr[state], state + 1) end + + +countevents(tree::OfflineTree) = length(tree) +countevents(tree::OnlineTree) = length(tree.events) +triggercounterof(e::Evt) = e.trigger_counter +frameindexof(e::Evt) = e.frame_index +triggercounterof(e::DAQEvent) = e.header.trigger_counter +frameindexof(e::DAQEvent) = e.header.frame_index + +""" + +Retrieves the event with for a given `frame_index` and `trigger_counter`. + +""" +function getevent(tree::T, frame_index, trigger_counter) where T<:Union{OnlineTree, OfflineTree} + lookup = tree._frame_index_trigger_counter_lookup_map + key = (frame_index, trigger_counter) + if haskey(lookup, key) + event_idx = lookup[key] + return getevent(tree, event_idx) + end + + highest_event_idx = length(lookup) == 0 ? 0 : maximum(values(lookup)) + + for event_idx in (highest_event_idx+1):countevents(tree) + event = getevent(tree, event_idx) + + fi = frameindexof(event) + tc = triggercounterof(event) + lookup[(fi, tc)] = event_idx + + if fi == frame_index && tc == trigger_counter + return event + end + end + + error("No online event found for frame_index=$(frame_index) and trigger_counter=$(trigger_counter).") +end +getevent(tree::OfflineTree, idx) = tree[idx] +getevent(tree::OnlineTree, idx) = tree.events[idx]