From 9869c38530d1154957cc7e432742f460a3d5d069 Mon Sep 17 00:00:00 2001 From: Tamas Gal <tgal@km3net.de> Date: Mon, 3 Feb 2025 21:51:46 +0000 Subject: [PATCH] Add JSON I/O --- Project.toml | 1 + src/KM3io.jl | 2 ++ src/exports.jl | 3 +++ src/hardware.jl | 1 + src/json.jl | 56 +++++++++++++++++++++++++++++++++++++++++++++++ test/json.jl | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 1 + 7 files changed, 121 insertions(+) create mode 100644 src/json.jl create mode 100644 test/json.jl diff --git a/Project.toml b/Project.toml index 8492bec2..d6002054 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ version = "0.17.9" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Requires = "ae029012-a4dd-5104-9daa-d747884805df" diff --git a/src/KM3io.jl b/src/KM3io.jl index c3f8394f..3b6a91b8 100644 --- a/src/KM3io.jl +++ b/src/KM3io.jl @@ -8,6 +8,7 @@ using Dates: DateTime, datetime2unix, unix2datetime using Sockets using UUIDs using TOML +using JSON if !isdefined(Base, :get_extension) using Requires @@ -69,6 +70,7 @@ include("daq.jl") include("acoustics.jl") include("calibration.jl") include("controlhost.jl") +include("json.jl") include("tools/general.jl") include("tools/daq.jl") diff --git a/src/exports.jl b/src/exports.jl index 984ddd05..643187f4 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -80,6 +80,9 @@ Trk, XCalibratedHit, FitInformation, +# Misc I/O +tojson, + # Calibration AbstractCalibratedHit, K40Rates, diff --git a/src/hardware.jl b/src/hardware.jl index 54fc88cf..9f8b75cd 100644 --- a/src/hardware.jl +++ b/src/hardware.jl @@ -282,6 +282,7 @@ struct Detector comments::Vector{String} _pmt_id_module_map::Dict{Int, DetectorModule} end + """ Return a vector of all modules of a given detector. """ diff --git a/src/json.jl b/src/json.jl new file mode 100644 index 00000000..d1250c57 --- /dev/null +++ b/src/json.jl @@ -0,0 +1,56 @@ +""" + function tojson(filename::AbstractString, e::Evt) + +Writes an offline event ([`Evt`]@ref) as a JSON string to a file. +""" +function tojson(filename::AbstractString, event::Evt, detector::Detector) + open(filename, "w") do io + tojson(io, event, detector) + end +end + +function tojson(io::IO, event::Evt, detector::Detector) + bt = bestjppmuon(event) + tâ‚€ = first(event.hits).t + + hits = [ + ( + dom_id = h.dom_id, + channel_id = h.channel_id, + floor = detector[h.dom_id].location.floor, + detection_unit = detector[h.dom_id].location.string, + tdc = h.tdc, + t = h.t - tâ‚€, + tot = h.tot, + pos_x = h.pos.x, pos_y = h.pos.y, pos_z = h.pos.z, + dir_x = h.dir.x, dir_y = h.dir.y, dir_z = h.dir.z, + triggered = h.trigger_mask > 0 + ) for h in event.hits + ] + if !ismissing(bt) + bt = ( + pos_x = bt.pos.x, pos_y = bt.pos.y, pos_z = bt.pos.z, + dir_x = bt.dir.x, dir_y = bt.dir.y, dir_z = bt.dir.z, + t = bt.t - tâ‚€ + ) + end + + JSON.print(io, (utc_timestamp=event.t.s + (event.t.ns + tâ‚€)/1e9, hits=hits, reconstructed_track=bt)) +end + +function tojson(filename::AbstractString, detector::Detector) + open(filename, "w") do io + tojson(io, detector) + end +end + +function tojson(io::IO, detector::Detector) + modules = [ + ( + id=m.id, detection_unit=m.location.string, floor=m.location.floor, pos_x = m.pos.x, pos_y = m.pos.y, pos_z = m.pos.z, + pmts=[(id=channel_id - 1, pos_x=p.pos.x, pos_y=p.pos.y, pos_z=p.pos.z, dir_x=p.dir.x, dir_y=p.dir.y, dir_z=p.dir.z) for (channel_id, p) in enumerate(m)] + ) + for m in detector + ] + JSON.print(io, modules) +end diff --git a/test/json.jl b/test/json.jl new file mode 100644 index 00000000..be8be391 --- /dev/null +++ b/test/json.jl @@ -0,0 +1,57 @@ +using KM3io +using JSON +using KM3NeTTestData +using Test + + +const OFFLINEFILE = datapath("offline", "km3net_offline.root") + + +@testset "JSON output" begin + f = ROOTFile(OFFLINEFILE) + e = f.offline[1] + d = Detector(datapath("detx", "km3net_offline.detx")) + + outfile = tempname() + tojson(outfile, e, d) + + json_evt = JSON.parsefile(outfile) + json_hits = json_evt["hits"] + @test 1.567036818270104e9 == json_evt["utc_timestamp"] + + tâ‚€ = first(e.hits).t + + bt = bestjppmuon(e) + json_bt = json_evt["reconstructed_track"] + @test bt.pos.x == json_bt["pos_x"] + @test bt.pos.y == json_bt["pos_y"] + @test bt.pos.z == json_bt["pos_z"] + @test bt.dir.x == json_bt["dir_x"] + @test bt.dir.y == json_bt["dir_y"] + @test bt.dir.z == json_bt["dir_z"] + @test bt.t == json_bt["t"] + tâ‚€ + + @test 176 == length(json_hits) + for idx in 1:length(json_hits) + orig_hit = e.hits[idx] + json_hit = json_hits[idx] + @test orig_hit.t == json_hit["t"] + tâ‚€ + @test orig_hit.pos.x == json_hit["pos_x"] + @test orig_hit.pos.y == json_hit["pos_y"] + @test orig_hit.pos.z == json_hit["pos_z"] + @test orig_hit.dir.x == json_hit["dir_x"] + @test orig_hit.dir.y == json_hit["dir_y"] + @test orig_hit.dir.z == json_hit["dir_z"] + @test orig_hit.channel_id == json_hit["channel_id"] + @test (orig_hit.trigger_mask > 0) == json_hit["triggered"] + + orig_dom_id = orig_hit.dom_id + dom_id = json_hit["dom_id"] + @test dom_id == orig_dom_id + m = d[dom_id] + @test json_hit["floor"] == m.location.floor + @test json_hit["detection_unit"] == m.location.string + end + + +end diff --git a/test/runtests.jl b/test/runtests.jl index 10c19d7f..8a277144 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,6 +2,7 @@ using Test include("root.jl") include("hdf5.jl") +include("json.jl") include("daq.jl") include("tools.jl") include("hardware.jl") -- GitLab