Skip to content

Commit 82bcde2

Browse files
authored
Merge pull request #8 from legend-exp/dev
Bug Fixes
2 parents b4e1d79 + 20c73a5 commit 82bcde2

File tree

7 files changed

+95
-71
lines changed

7 files changed

+95
-71
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
fail-fast: false
2626
matrix:
2727
version:
28-
- '1.9'
28+
- '1.10'
2929
- '1'
3030
- 'nightly'
3131
os:

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ PropertyFunctions = "0.2.1"
2323
StructArrays = "0.4, 0.5, 0.6"
2424
Tables = "1"
2525
Unitful = "1.6"
26-
julia = "1.9"
26+
julia = "1.10"

src/LegendEventAnalysis.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ using LegendDataManagement
1212

1313
using IntervalSets: AbstractInterval, ClosedInterval, leftendpoint, rightendpoint
1414
using ProgressMeter: @showprogress
15-
using PropertyFunctions: PropertyFunction, @pf, filterby
15+
using PropertyFunctions: PropertyFunction, @pf, filterby, PropSelFunction
1616

1717
using Tables: columns
1818
using Unitful: RealOrRealQuantity as RealQuantity
@@ -23,7 +23,7 @@ include("flatten_over_channels.jl")
2323
include("build_global_events.jl")
2424
include("calibrate_geds.jl")
2525
include("calibrate_smps.jl")
26-
include("calibrate_puls.jl")
26+
include("calibrate_aux.jl")
2727
include("calibrate_all.jl")
2828

2929
end # module

src/calibrate_all.jl

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,32 @@
77
Calibrate all channels in the given datastore, using the metadata
88
processing configuration for `data` and `sel`.
99
"""
10-
function calibrate_all(data::LegendData, sel::AnyValiditySelection, datastore::AbstractDict; tier::DataTierLike=:jldsp)
10+
function calibrate_all(data::LegendData, sel::AnyValiditySelection, datastore::AbstractDict, tier::DataTierLike=:jldsp)
1111
ds = datastore
1212

13+
@debug "Calibrating all channels in for `ValiditySelection` $(sel) in `DataTier` $(tier)"
1314
chinfo = channelinfo(data, sel)
14-
geds_channels::Vector{ChannelId} = filterby(@pf $system == :geds && $processable && $usability != :off && $is_blinded)(chinfo).channel
15-
spms_channels::Vector{ChannelId} = filterby(@pf $system == :spms && $processable)(chinfo).channel
16-
puls_channels::Vector{ChannelId} = filterby(@pf $system in [:puls, :bsln])(chinfo).channel
17-
15+
geds_channels::Vector{ChannelId} = filterby(get_ged_evt_chsel_propfunc(data, sel))(chinfo).channel
16+
@debug "Loaded $(length(geds_channels)) HPGe channels"
17+
hitgeds_channels::Vector{ChannelId} = filterby(get_ged_evt_hitchsel_propfunc(data, sel))(chinfo).channel
18+
@debug "Loaded $(length(hitgeds_channels)) HPGe hit channels"
19+
spms_channels::Vector{ChannelId} = filterby(get_spms_evt_chsel_propfunc(data, sel))(chinfo).channel
20+
@debug "Loaded $(length(spms_channels)) SiPM channels"
21+
aux_channels::Vector{ChannelId} = filterby(get_aux_evt_chsel_propfunc(data, sel))(chinfo).channel
22+
@debug "Loaded auxiliary channels: $(join(string.(filterby(get_aux_evt_chsel_propfunc(data, sel))(chinfo).detector), ", "))"
1823

1924
# HPGe:
20-
21-
ged_caldata = Dict([
22-
let detector = channelinfo(data, sel, channel).detector,
23-
chdata = ds[channel, tier][:]
24-
channel => calibrate_ged_channel_data(data, sel, detector, chdata)
25+
@debug "Calibrating HPGe channels"
26+
ged_kwargs = get_ged_evt_kwargs(data, sel)
27+
ged_caldata_v = Vector{StructVector}(undef, length(geds_channels))
28+
Threads.@threads for i in eachindex(geds_channels)
29+
let detector = channelinfo(data, sel, geds_channels[i]).detector, chdata = ds[geds_channels[i], tier][:]
30+
ged_caldata_v[i] = calibrate_ged_channel_data(data, sel, detector, chdata; ged_kwargs...)
2531
end
26-
for channel in geds_channels
27-
])
32+
end
33+
ged_caldata = Dict(geds_channels .=> ged_caldata_v)
2834

35+
@debug "Building global events for HPGe channels"
2936
ged_events_pre = build_global_events(ged_caldata, geds_channels)
3037

3138
min_t0(t0::AbstractVector{<:Number}) = isempty(t0) ? eltype(t0)(NaN) : minimum(t0)
@@ -47,23 +54,29 @@ function calibrate_all(data::LegendData, sel::AnyValiditySelection, datastore::A
4754

4855
maximum_with_init(A) = maximum(A, init=zero(eltype((A))))
4956

57+
is_valid_hit(trig_chs::AbstractVector{<:Int}, hit_channels::AbstractVector{<:Int}) = all(x -> x in hit_channels, trig_chs)
58+
# Main.@infiltrate
59+
5060
ged_additional_cols = (
5161
t0_start = min_t0.(trig_t0),
5262
trig_t0 = trig_t0,
5363
multiplicity = n_trig,
54-
max_e_ch = max_e_ch,
64+
max_e_ch_idxs = max_e_ch,
65+
max_e_ch = only.(getindex.(ged_events_pre.channel, max_e_ch)),
5566
max_e_trap_cal = maximum_with_init.(trig_e_trap_cal),
5667
max_e_cusp_cal = maximum_with_init.(trig_e_cusp_cal),
5768
max_e_trap_ctc_cal = maximum_with_init.(trig_e_trap_ctc_cal),
5869
max_e_cusp_ctc_cal = maximum_with_init.(trig_e_cusp_ctc_cal),
5970
max_e_short_cal = maximum_with_init.(trig_e_short_cal),
60-
trig_e_ch = trig_e_ch,
71+
trig_e_ch_idxs = trig_e_ch,
72+
trig_e_ch = getindex.(ged_events_pre.channel, trig_e_ch),
6173
trig_e_trap_cal = trig_e_trap_cal,
6274
trig_e_cusp_cal = trig_e_cusp_cal,
6375
trig_e_trap_ctc_cal = trig_e_trap_ctc_cal,
6476
trig_e_cusp_ctc_cal = trig_e_cusp_ctc_cal,
6577
trig_e_short_cal = trig_e_short_cal,
6678
is_valid_qc = count.(ged_events_pre.is_baseline) .== n_expected_baseline,
79+
is_valid_hit = is_valid_hit.(getindex.(ged_events_pre.channel, trig_e_ch), Ref(Int.(hitgeds_channels))),
6780
is_discharge_recovery = any.(ged_events_pre.is_discharge_recovery_ml),
6881
is_saturated = any.(ged_events_pre.is_saturated),
6982
is_discharge = any.(ged_events_pre.is_discharge),
@@ -72,41 +85,41 @@ function calibrate_all(data::LegendData, sel::AnyValiditySelection, datastore::A
7285

7386

7487
# SiPM:
75-
76-
spm_caldata = Dict([
77-
let detector = channelinfo(data, sel, channel).detector,
78-
chdata = ds[channel, tier][:]
79-
channel => calibrate_spm_channel_data(data, sel, detector, chdata)
88+
@debug "Calibrating SiPM channels"
89+
spm_caldata_v = Vector{StructVector}(undef, length(spms_channels))
90+
Threads.@threads for i in eachindex(spms_channels)
91+
let detector = channelinfo(data, sel, spms_channels[i]).detector, chdata = ds[spms_channels[i], tier][:]
92+
spm_caldata_v[i] = calibrate_spm_channel_data(data, sel, detector, chdata)
8093
end
81-
for channel in spms_channels
82-
])
94+
end
95+
spm_caldata = Dict(spms_channels .=> spm_caldata_v)
96+
@debug "Building global events for SiPM channels"
8397
spm_events_novov = build_global_events(spm_caldata, spms_channels)
8498
spm_events = StructArray(map(_fix_vov, columns(spm_events_novov)))
8599

86-
87-
# Pulser:
88-
89-
pls_caldata = Dict([
90-
let detector = channelinfo(data, sel, channel).detector,
91-
chdata = ds[channel, tier][:]
92-
channel => calibrate_pls_channel_data(data, sel, detector, chdata)
93-
end
94-
for channel in puls_channels if haskey(ds, string(channel))
95-
])
96-
pls_events = build_global_events(pls_caldata, puls_channels)
97100

101+
@debug "Calibrating auxiliary channels"
102+
# aux & Forced Trigger
103+
aux_caldata =
104+
[Dict(
105+
let detector = channelinfo(data, sel, channel).detector,
106+
chdata = ds[channel, tier][:]
107+
channel => calibrate_aux_channel_data(data, sel, detector, chdata)
108+
end
109+
) for channel in aux_channels]
110+
@debug "Building global events for auxiliary channels"
111+
aux_events = NamedTuple{Tuple(get_aux_evt_levelname_propfunc.(Ref(data), Ref(sel), reduce(vcat, collect.(keys.(aux_caldata)))))}(build_global_events.(aux_caldata))
98112

99113
# Cross-system:
100-
101-
system_events = (
114+
@debug "Building cross-system events"
115+
system_events = merge((
102116
geds = ged_events,
103117
spms = spm_events,
104-
puls = pls_events,
105-
)
118+
), aux_events)
106119

107120
global_events_pre = build_cross_system_events(system_events)
108-
single_pls_col = StructVector(map(Broadcast.BroadcastFunction(only), columns(global_events_pre.puls)))
109-
global_events = StructVector(merge(columns(global_events_pre), (puls = single_pls_col,)))
121+
aux_cols = NamedTuple{keys(aux_events)}([StructVector(map(Broadcast.BroadcastFunction(only), columns(getproperty(global_events_pre, k)))) for k in keys(aux_events)])
122+
global_events = StructVector(merge(Base.structdiff(columns(global_events_pre), NamedTuple{keys(aux_events)}), (aux = StructArray(aux_cols),)))
110123

111124
cross_systems_cols = (
112125
ged_spm = _build_lar_cut(global_events),
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
# This file is a part of LegendEventAnalysis.jl, licensed under the MIT License (MIT).
22

33
"""
4-
calibrate_pls_channel_data(data::LegendData, sel::ValiditySelection, detector::DetectorId, channel_data::AbstractVector)
4+
calibrate_aux_channel_data(data::LegendData, sel::ValiditySelection, detector::DetectorId, channel_data::AbstractVector)
55
6-
Apply the calibration specified by `data` and `sel` for pulser referred to
6+
Apply the calibration specified by `data` and `sel` for aux channel referred to
77
by the `detector` ID to the single-channel `channel_data` for that detector.
88
99
Also calculates the configured cut/flag values.
1010
"""
11-
function calibrate_pls_channel_data(data::LegendData, sel::AnyValiditySelection, detector::DetectorId, channel_data::AbstractVector)
11+
function calibrate_aux_channel_data(data::LegendData, sel::AnyValiditySelection, detector::DetectorId, channel_data::AbstractVector)
1212
chdata = channel_data[:]
1313

1414
# get calibration function for the detector
15-
pulsercal_pf = get_pulser_cal_propfunc(data, sel, detector)
15+
auxcal_pf = get_aux_cal_propfunc(data, sel, detector)
1616

1717
# get additional cols to be parsed into the event tier
18-
chdata_output_pf = get_ged_evt_chdata_propfunc(data, sel, detector)
18+
chdata_output_pf = get_aux_evt_chdata_propfunc(data, sel, detector)
1919

2020
# get additional columns
2121
chdata_output = chdata_output_pf.(chdata)
2222

2323
# apply calibrations
24-
cal_output = pulsercal_pf.(chdata)
24+
cal_output = auxcal_pf.(chdata)
2525

2626
return StructVector(merge(columns(chdata_output), columns(cal_output)))
2727
end
28-
export calibrate_pls_channel_data
28+
export calibrate_aux_channel_data

src/calibrate_geds.jl

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
# This file is a part of LegendEventAnalysis.jl, licensed under the MIT License (MIT).
22

33
"""
4-
calibrate_ged_channel_data(data::LegendData, sel::ValiditySelection, detector::DetectorId, channel_data::AbstractVector)
4+
calibrate_ged_channel_data(data::LegendData, sel::AnyValiditySelection, detector::DetectorId, channel_data::AbstractVector;
5+
psd_cal_pars_type::Symbol=:ppars, psd_cal_pars_cat::Symbol=:aoe, psd_cut_pars_type::Symbol=:ppars, psd_cut_pars_cat::Symbol=:aoe,
6+
keep_chdata::Bool=false)
57
68
Apply the calibration specified by `data` and `sel` for the given HPGe
79
`detector` to the single-channel `channel_data` for that detector.
810
911
Also calculates the configured cut/flag values.
1012
"""
11-
function calibrate_ged_channel_data(data::LegendData, sel::AnyValiditySelection, detector::DetectorId, channel_data::AbstractVector)
13+
function calibrate_ged_channel_data(data::LegendData, sel::AnyValiditySelection, detector::DetectorId, channel_data::AbstractVector;
14+
psd_cal_pars_type::Symbol=:ppars, psd_cal_pars_cat::Symbol=:aoe, psd_cut_pars_type::Symbol=:ppars, psd_cut_pars_cat::Symbol=:aoe,
15+
keep_chdata::Bool=false)
16+
17+
# get all chdata
1218
chdata = channel_data[:]
1319

1420
# get energy and psd calibration functions for the detector
1521
cal_pf = get_ged_cal_propfunc(data, sel, detector)
22+
psd_pf = get_ged_psd_propfunc(data, sel, detector; pars_type=psd_cal_pars_type, pars_cat=psd_cal_pars_cat)
1623

1724
# get qc labels
1825
cut_pf = get_ged_qc_cuts_propfunc(data, sel, detector)
@@ -23,29 +30,29 @@ function calibrate_ged_channel_data(data::LegendData, sel::AnyValiditySelection,
2330
cut_is_trig_pf = get_ged_qc_is_trig_propfunc(data, sel, detector)
2431

2532
# get additional cols to be parsed into the event tier
26-
chdata_output_pf = get_ged_evt_chdata_propfunc(data, sel, detector)
33+
chdata_output_pf = if keep_chdata
34+
PropSelFunction{propertynames(chdata)}()
35+
else
36+
get_ged_evt_chdata_propfunc(data, sel)
37+
end
2738

2839
# get postcal psd flags
29-
postcal_pf = let aoe_window = dataprod_pars_aoe_window(data, sel, detector)
30-
@pf (
31-
aeo_low_cut = $aoe_classifier > leftendpoint(aoe_window),
32-
aoe_ds_cut = $aoe_classifier in aoe_window,
33-
)
34-
end
40+
postcal_pf = get_ged_aoe_cut_propfunc(data, sel, detector; pars_type=psd_cut_pars_type, pars_cat=psd_cut_pars_cat)
3541

3642
# apply calibrations
3743
cal_output = cal_pf.(chdata)
38-
cal_chdata = StructArray(merge(columns(cal_output), columns(chdata)))
44+
psd_output = psd_pf.(StructArray(merge(columns(cal_output), columns(chdata))))
45+
cal_chdata = StructArray(merge(columns(cal_output), columns(psd_output), columns(chdata)))
3946

4047
# get cut labels
4148
cut_output = cut_pf.(cal_chdata)
4249

43-
# get additional columns
44-
chdata_output = chdata_output_pf.(chdata)
45-
4650
# get postcal data
4751
postcal_data = postcal_pf.(cal_chdata)
4852

53+
# get additional columns
54+
chdata_output = chdata_output_pf.(chdata)
55+
4956
# get cut flags
5057
is_physical = cut_is_physical_pf.(cut_output)
5158
is_baseline = cut_is_baseline_pf.(cut_output)
@@ -57,6 +64,6 @@ function calibrate_ged_channel_data(data::LegendData, sel::AnyValiditySelection,
5764
is_physical_trig = is_physical_trig,
5865
)
5966

60-
return StructVector(merge(columns(chdata_output), columns(cal_output), columns(postcal_data), columns(cut_output), additional_cols))
67+
return StructVector(merge(columns(chdata_output), columns(cal_output), columns(psd_output), columns(postcal_data), columns(cut_output), additional_cols))
6168
end
6269
export calibrate_ged_channel_data

src/calibrate_smps.jl

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,25 @@ Apply the calibration specified by `data` and `sel` for the given SiPM
88
99
Also calculates the configured cut/flag values.
1010
"""
11-
function calibrate_spm_channel_data(data::LegendData, sel::AnyValiditySelection, detector::DetectorId, channel_data::AbstractVector)
11+
function calibrate_spm_channel_data(data::LegendData, sel::AnyValiditySelection, detector::DetectorId, channel_data::AbstractVector;
12+
keep_chdata::Bool=false)
1213
chdata = channel_data[:]
1314

1415
spmcal_pf = get_spm_cal_propfunc(data, sel, detector)
1516

16-
# ToDo: Make channel output configurable:
17-
chdata_output = (
18-
timestamp = chdata.timestamp,
19-
trig_pos = VectorOfArrays(chdata.trig_pos),
20-
)
17+
# get additional cols to be parsed into the event tier
18+
chdata_output_pf = if keep_chdata
19+
PropSelFunction{propertynames(chdata)}()
20+
else
21+
get_spms_evt_chdata_propfunc(data, sel)
22+
end
2123

2224
cal_output_novv = spmcal_pf.(chdata)
2325
cal_output = StructArray(map(VectorOfArrays, columns(cal_output_novv)))
2426

25-
return StructVector(merge(chdata_output, columns(cal_output)))
27+
chdata_output = chdata_output_pf.(chdata)
28+
29+
return StructVector(merge(columns(cal_output), columns(chdata_output)))
2630
end
2731
export calibrate_spm_channel_data
2832

@@ -58,7 +62,7 @@ function _lar_cut(
5862

5963
lar_cut = n_over_thresh >= 4 || pe_sum >= 4
6064

61-
return (lar_cut = lar_cut, smps_win_pe_sum = pe_sum)
65+
return (lar_cut = lar_cut, spms_win_pe_sum = pe_sum, spms_win_multiplicity = n_over_thresh)
6266
end
6367

6468

0 commit comments

Comments
 (0)