diff --git a/src/custom.jl b/src/custom.jl index d808f1db..6668d05d 100644 --- a/src/custom.jl +++ b/src/custom.jl @@ -96,7 +96,7 @@ function interped_data(rawdata, rawoffsets, ::Type{Vector{LVF64}}, ::Type{Offset offset .+= 1 VectorOfVectors(real_data, offset) end -function interped_data(rawdata, rawoffsets, ::Type{LVF64}, ::Type{J}) where {T, J <: JaggType} +function interped_data(rawdata, rawoffsets, ::Type{LVF64}, ::Type{Nojagg}) # even with rawoffsets, we know each TLV is destinied to be 64 bytes [ reinterpret(LVF64, x) for x in Base.Iterators.partition(rawdata, 64) @@ -114,7 +114,10 @@ end function readtype(io::IO, T::Type{_KM3NETDAQHit}) T(readtype(io, Int32), read(io, UInt8), read(io, Int32), read(io, UInt8)) end -function interped_data(rawdata, rawoffsets, ::Type{Vector{_KM3NETDAQHit}}, ::Type{J}) where {T, J <: UnROOT.JaggType} +function interped_data(rawdata, rawoffsets, ::Type{Vector{_KM3NETDAQHit}}, ::Type{Nojagg}) + UnROOT.splitup(rawdata, rawoffsets, _KM3NETDAQHit, skipbytes=10) +end +function interped_data(rawdata, rawoffsets, ::Type{Vector{_KM3NETDAQHit}}, ::Type{Offsetjagg}) UnROOT.splitup(rawdata, rawoffsets, _KM3NETDAQHit, skipbytes=10) end @@ -137,7 +140,10 @@ function readtype(io::IO, T::Type{_KM3NETDAQTriggeredHit}) T(dom_id, channel_id, tdc, tot, trigger_mask) end -function UnROOT.interped_data(rawdata, rawoffsets, ::Type{Vector{_KM3NETDAQTriggeredHit}}, ::Type{J}) where {T, J <: UnROOT.JaggType} +function UnROOT.interped_data(rawdata, rawoffsets, ::Type{Vector{_KM3NETDAQTriggeredHit}}, ::Type{Nojagg}) + UnROOT.splitup(rawdata, rawoffsets, _KM3NETDAQTriggeredHit, skipbytes=10) +end +function UnROOT.interped_data(rawdata, rawoffsets, ::Type{Vector{_KM3NETDAQTriggeredHit}}, ::Type{Offsetjagg}) UnROOT.splitup(rawdata, rawoffsets, _KM3NETDAQTriggeredHit, skipbytes=10) end @@ -169,6 +175,6 @@ function readtype(io::IO, T::Type{_KM3NETDAQEventHeader}) T(detector_id, run, frame_index, UTC_seconds, UTC_16nanosecondcycles, trigger_counter, trigger_mask, overlays) end -function UnROOT.interped_data(rawdata, rawoffsets, ::Type{_KM3NETDAQEventHeader}, ::Type{J}) where {T, J <: UnROOT.JaggType} +function UnROOT.interped_data(rawdata, rawoffsets, ::Type{_KM3NETDAQEventHeader}, ::Type{Nojagg}) UnROOT.splitup(rawdata, rawoffsets, _KM3NETDAQEventHeader, jagged=false) end diff --git a/src/root.jl b/src/root.jl index 5b5adfa4..765c9160 100644 --- a/src/root.jl +++ b/src/root.jl @@ -215,66 +215,68 @@ function interped_data(rawdata, rawoffsets, ::Type{Bool}, ::Type{Nojagg}) # specialized case to get Vector{Bool} instead of BitVector return map(ntoh,reinterpret(Bool, rawdata)) end -function interped_data(rawdata, rawoffsets, ::Type{T}, ::Type{J}) where {T, J<:JaggType} - # there are two possibility, one is the leaf is just normal leaf but the title has "[...]" in it - # magic offsets, seems to be common for a lot of types, see auto.py in uproot3 - # only needs when the jaggedness comes from TLeafElements, not needed when - # the jaggedness comes from having "[]" in TLeaf's title - # the other is where we need to auto detector T bsaed on class name - # we want the fundamental type as `reinterpret` will create vector - if J === Nojagg - return ntoh.(reinterpret(T, rawdata)) - elseif J === Offsetjaggjagg # the branch is doubly jagged - jagg_offset = 10 - subT = eltype(eltype(T)) - out = VectorOfVectors(T(), Int32[1]) - @views for i in 1:(length(rawoffsets)-1) - flat = rawdata[(rawoffsets[i]+1+jagg_offset:rawoffsets[i+1])] - row = VectorOfVectors{subT}() - cursor = 1 - while cursor < length(flat) - n = ntoh(reinterpret(Int32, flat[cursor:cursor+sizeof(Int32)-1])[1]) - cursor += sizeof(Int32) - b = ntoh.(reinterpret(subT, flat[cursor:cursor+n*sizeof(subT)-1])) - cursor += n*sizeof(subT) - push!(row, b) - end - push!(out, row) - end - return out - else # the branch is singly jagged - # for each "event", the index range is `offsets[i] + jagg_offset + 1` to `offsets[i+1]` - # this is why we need to append `rawoffsets` in the `readbranchraw()` call - # when you use this range to index `rawdata`, you will get raw bytes belong to each event - # Say your real data is Int32 and you see 8 bytes after indexing, then this event has [num1, num2] as real data - _size = sizeof(eltype(T)) - if J === Offsetjagg - jagg_offset = 10 - dp = 0 # book keeping for copy_to! - lr = length(rawoffsets) - offset = Vector{Int32}(undef, lr) - offset[1] = 0 - @views @inbounds for i in 1:lr-1 - start = rawoffsets[i]+jagg_offset+1 - stop = rawoffsets[i+1] - l = stop-start+1 - if l > 0 - unsafe_copyto!(rawdata, dp+1, rawdata, start, l) - dp += l - offset[i+1] = offset[i] + l - else - # when we have an empty [] in jagged basket - offset[i+1] = offset[i] - end - end - resize!(rawdata, dp) +function interped_data(rawdata, rawoffsets, ::Type{T}, ::Type{Nojagg}) where T + return ntoh.(reinterpret(T, rawdata)) +end +# there are two possibility, one is the leaf is just normal leaf but the title has "[...]" in it +# magic offsets, seems to be common for a lot of types, see auto.py in uproot3 +# only needs when the jaggedness comes from TLeafElements, not needed when +# the jaggedness comes from having "[]" in TLeaf's title +# the other is where we need to auto detector T bsaed on class name +# we want the fundamental type as `reinterpret` will create vector +function interped_data(rawdata, rawoffsets, ::Type{T}, ::Type{Nooffsetjagg}) where T + _size = sizeof(eltype(T)) + real_data = ntoh.(reinterpret(T, rawdata)) + rawoffsets .= (rawoffsets .÷ _size) .+ 1 + return VectorOfVectors(real_data, rawoffsets, ArraysOfArrays.no_consistency_checks) +end +function interped_data(rawdata, rawoffsets, ::Type{T}, ::Type{Offsetjagg}) where T + # for each "event", the index range is `offsets[i] + jagg_offset + 1` to `offsets[i+1]` + # this is why we need to append `rawoffsets` in the `readbranchraw()` call + # when you use this range to index `rawdata`, you will get raw bytes belong to each event + # Say your real data is Int32 and you see 8 bytes after indexing, then this event has [num1, num2] as real data + _size = sizeof(eltype(T)) + jagg_offset = 10 + dp = 0 # book keeping for copy_to! + lr = length(rawoffsets) + offset = Vector{Int32}(undef, lr) + offset[1] = 0 + @views @inbounds for i in 1:lr-1 + start = rawoffsets[i]+jagg_offset+1 + stop = rawoffsets[i+1] + l = stop-start+1 + if l > 0 + unsafe_copyto!(rawdata, dp+1, rawdata, start, l) + dp += l + offset[i+1] = offset[i] + l else - offset = rawoffsets + # when we have an empty [] in jagged basket + offset[i+1] = offset[i] + end + end + resize!(rawdata, dp) + real_data = ntoh.(reinterpret(T, rawdata)) + offset .= (offset .÷ _size) .+ 1 + return VectorOfVectors(real_data, offset, ArraysOfArrays.no_consistency_checks) +end +function interped_data(rawdata, rawoffsets, ::Type{T}, ::Type{Offsetjaggjagg}) where T + jagg_offset = 10 + subT = eltype(eltype(T)) + out = VectorOfVectors(T(), Int32[1]) + @views for i in 1:(length(rawoffsets)-1) + flat = rawdata[(rawoffsets[i]+1+jagg_offset:rawoffsets[i+1])] + row = VectorOfVectors{subT}() + cursor = 1 + while cursor < length(flat) + n = ntoh(reinterpret(Int32, flat[cursor:cursor+sizeof(Int32)-1])[1]) + cursor += sizeof(Int32) + b = ntoh.(reinterpret(subT, flat[cursor:cursor+n*sizeof(subT)-1])) + cursor += n*sizeof(subT) + push!(row, b) end - real_data = ntoh.(reinterpret(T, rawdata)) - offset .= (offset .÷ _size) .+ 1 - return VectorOfVectors(real_data, offset, ArraysOfArrays.no_consistency_checks) + push!(out, row) end + return out end function _normalize_ftype(fType) diff --git a/test/runtests.jl b/test/runtests.jl index 4768cacd..a651df6e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -355,7 +355,7 @@ end @testset "Branch filtering" begin # Branch selection behavior: if not regex, require exact name match treebranches = ["Muon_pt", "Muon_eta", "Muon_phi", "Muon_charge", "Muon_ptErr", - "Muon_", "_pt", "Muon.pt"] + "Muon_", "_pt", "Muon.pt"] _m(s::AbstractString) = isequal(s) _m(r::Regex) = Base.Fix1(occursin, r) filter_branches(selected) = Set(mapreduce(b->filter(_m(b), treebranches), ∪, selected))