Skip to content

Commit 8de1790

Browse files
authored
Merge pull request #13 from legend-exp/patch_spms-geds-calibration
Updated `SiPM` calibration and `LAr` cut definition
2 parents fd2ecdf + d2dab4f commit 8de1790

File tree

3 files changed

+52
-26
lines changed

3 files changed

+52
-26
lines changed

src/calibrate_all.jl

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,38 +43,37 @@ function calibrate_all(data::LegendData, sel::AnyValiditySelection, datastore::A
4343

4444
trig_e_ch = findall.(ged_events_pre.is_physical_trig)
4545

46-
trig_e_trap_cal = _fix_vov(getindex.(ged_events_pre.e_trap_cal, trig_e_ch))
47-
trig_e_cusp_cal = _fix_vov(getindex.(ged_events_pre.e_cusp_cal, trig_e_ch))
46+
trig_e_trap_max_cal = _fix_vov(getindex.(ged_events_pre.e_trap_max_cal, trig_e_ch))
47+
trig_e_cusp_max_cal = _fix_vov(getindex.(ged_events_pre.e_cusp_max_cal, trig_e_ch))
4848
trig_e_trap_ctc_cal = _fix_vov(getindex.(ged_events_pre.e_trap_ctc_cal, trig_e_ch))
4949
trig_e_cusp_ctc_cal = _fix_vov(getindex.(ged_events_pre.e_cusp_ctc_cal, trig_e_ch))
50-
trig_e_short_cal = _fix_vov(getindex.(ged_events_pre.e_313_cal, trig_e_ch))
50+
trig_e_535_cal = _fix_vov(getindex.(ged_events_pre.e_535_cal, trig_e_ch))
5151
trig_t0 = _fix_vov(getindex.(ged_events_pre.t0, trig_e_ch))
5252
n_trig = length.(trig_e_ch)
5353
n_expected_baseline = length.(ged_events_pre.is_baseline) .- length.(trig_e_ch)
5454

5555
maximum_with_init(A) = maximum(A, init=zero(eltype((A))))
5656

5757
is_valid_hit(trig_chs::AbstractVector{<:Int}, hit_channels::AbstractVector{<:Int}) = all(x -> x in hit_channels, trig_chs)
58-
# Main.@infiltrate
5958

6059
ged_additional_cols = (
6160
t0_start = min_t0.(trig_t0),
6261
trig_t0 = trig_t0,
6362
multiplicity = n_trig,
6463
max_e_ch_idxs = max_e_ch,
6564
max_e_ch = only.(getindex.(ged_events_pre.channel, max_e_ch)),
66-
max_e_trap_cal = maximum_with_init.(trig_e_trap_cal),
67-
max_e_cusp_cal = maximum_with_init.(trig_e_cusp_cal),
65+
max_e_trap_cal = maximum_with_init.(trig_e_trap_max_cal),
66+
max_e_cusp_cal = maximum_with_init.(trig_e_cusp_max_cal),
6867
max_e_trap_ctc_cal = maximum_with_init.(trig_e_trap_ctc_cal),
6968
max_e_cusp_ctc_cal = maximum_with_init.(trig_e_cusp_ctc_cal),
70-
max_e_short_cal = maximum_with_init.(trig_e_short_cal),
69+
max_e_short_cal = maximum_with_init.(trig_e_535_cal),
7170
trig_e_ch_idxs = trig_e_ch,
7271
trig_e_ch = getindex.(ged_events_pre.channel, trig_e_ch),
73-
trig_e_trap_cal = trig_e_trap_cal,
74-
trig_e_cusp_cal = trig_e_cusp_cal,
72+
trig_e_trap_max_cal = trig_e_trap_max_cal,
73+
trig_e_cusp_max_cal = trig_e_cusp_max_cal,
7574
trig_e_trap_ctc_cal = trig_e_trap_ctc_cal,
7675
trig_e_cusp_ctc_cal = trig_e_cusp_ctc_cal,
77-
trig_e_short_cal = trig_e_short_cal,
76+
trig_e_535_cal = trig_e_535_cal,
7877
is_valid_qc = count.(ged_events_pre.is_baseline) .== n_expected_baseline,
7978
is_valid_hit = is_valid_hit.(getindex.(ged_events_pre.channel, trig_e_ch), Ref(Int.(hitgeds_channels))),
8079
is_discharge_recovery = any.(ged_events_pre.is_discharge_recovery_ml),
@@ -122,7 +121,7 @@ function calibrate_all(data::LegendData, sel::AnyValiditySelection, datastore::A
122121
global_events = StructVector(merge(Base.structdiff(columns(global_events_pre), NamedTuple{keys(aux_events)}), (aux = StructArray(aux_cols),)))
123122

124123
cross_systems_cols = (
125-
ged_spm = _build_lar_cut(global_events),
124+
ged_spm = _build_lar_cut(data, sel, global_events),
126125
)
127126

128127
result = StructArray(merge(columns(global_events), cross_systems_cols))

src/calibrate_geds.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Apply the calibration specified by `data` and `sel` for the given HPGe
1111
Also calculates the configured cut/flag values.
1212
"""
1313
function calibrate_ged_channel_data(data::LegendData, sel::AnyValiditySelection, detector::DetectorIdLike, channel_data::AbstractVector;
14+
e_cal_pars_type::Symbol=:rpars, e_cal_pars_cat::Symbol=:ecal,
1415
psd_cal_pars_type::Symbol=:ppars, psd_cal_pars_cat::Symbol=:aoe, psd_cut_pars_type::Symbol=:ppars, psd_cut_pars_cat::Symbol=:aoe,
1516
keep_chdata::Bool=false)
1617

@@ -20,7 +21,7 @@ function calibrate_ged_channel_data(data::LegendData, sel::AnyValiditySelection,
2021
chdata = channel_data[:]
2122

2223
# get energy and psd calibration functions for the detector
23-
cal_pf = get_ged_cal_propfunc(data, sel, detector)
24+
cal_pf = get_ged_cal_propfunc(data, sel, detector; pars_type=e_cal_pars_type, pars_cat=e_cal_pars_cat)
2425
psd_pf = get_ged_psd_propfunc(data, sel, detector; pars_type=psd_cal_pars_type, pars_cat=psd_cal_pars_cat)
2526

2627
# get qc labels

src/calibrate_smps.jl

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ function calibrate_spm_channel_data(data::LegendData, sel::AnyValiditySelection,
1313
chdata = channel_data[:]
1414

1515
spmcal_pf = get_spm_cal_propfunc(data, sel, detector)
16+
spmdc_sel_pf = get_spm_dc_sel_propfunc(data, sel, detector)
17+
spmdc_cal_pf = get_spm_dc_cal_propfunc(data, sel, detector)
1618

1719
# get additional cols to be parsed into the event tier
1820
chdata_output_pf = if keep_chdata
@@ -24,9 +26,12 @@ function calibrate_spm_channel_data(data::LegendData, sel::AnyValiditySelection,
2426
cal_output_novv = spmcal_pf.(chdata)
2527
cal_output = StructArray(map(VectorOfArrays, columns(cal_output_novv)))
2628

29+
dc_output_novv = NamedTuple{keys(spmdc_sel_pf)}([spmdc_cal_pf[e_type].(spmdc_sel_pf[e_type].(chdata)) for e_type in keys(spmdc_sel_pf)])
30+
dc_output = StructArray(map(VectorOfArrays, columns(dc_output_novv)))
31+
2732
chdata_output = chdata_output_pf.(chdata)
2833

29-
return StructVector(merge(columns(cal_output), columns(chdata_output)))
34+
return StructVector(merge(columns(cal_output), columns(dc_output), columns(chdata_output)))
3035
end
3136
export calibrate_spm_channel_data
3237

@@ -45,34 +50,55 @@ function _single_fiber_esum(
4550
end
4651

4752

48-
# ToDo: Make cut criteria configurable:
4953
function _lar_cut(
54+
colnames::Tuple{Symbol, Symbol, Symbol},
5055
t_win::AbstractInterval, spm_t::AbstractVector{<:AbstractVector{<:Number}},
51-
spmdc::AbstractVector{<:AbstractVector{<:Number}}, spm_pe::AbstractVector{<:AbstractVector{<:Number}}
56+
spmdc::AbstractVector{<:AbstractVector{<:Number}}, spm_pe::AbstractVector{<:AbstractVector{<:Number}},
57+
pe_ch_threshold::Quantity{<:Real}, pe_sum_threshold::Quantity{<:Real}, multiplicity_threshold::Int
5258
)
5359
n_over_thresh::Int = 0
5460
pe_sum::eltype(eltype(spm_pe)) = zero(eltype(eltype(spm_pe)))
5561
for i in eachindex(spm_t)
5662
s_i = _single_fiber_esum(t_win, spm_t[i], spmdc[i], spm_pe[i])
57-
if s_i > 0.5
63+
if s_i > pe_ch_threshold
5864
n_over_thresh += 1
5965
end
6066
pe_sum += s_i
6167
end
6268

63-
lar_cut = n_over_thresh >= 4 || pe_sum >= 4
69+
lar_cut = Bool(n_over_thresh >= multiplicity_threshold || pe_sum >= pe_sum_threshold)
6470

65-
return (lar_cut = lar_cut, spms_win_pe_sum = pe_sum, spms_win_multiplicity = n_over_thresh)
71+
return NamedTuple{colnames, Tuple{Bool, eltype(eltype(spm_pe)), Int}}([lar_cut, pe_sum, n_over_thresh])
6672
end
6773

68-
69-
# ToDo: Make time window configurable:
70-
function _build_lar_cut(global_events::AbstractVector{<:NamedTuple})
74+
function _build_lar_cut(data::LegendData, sel::AnyValiditySelection, global_events::AbstractVector{<:NamedTuple}, e_filter::Symbol)
7175
geds_t0 = global_events.geds.t0_start
72-
spm_t = global_events.spms.trig_pos
73-
spmdc = global_events.spms.trig_is_dc
74-
spm_pe = global_events.spms.trig_pe
76+
77+
dataprod_larcut = get_spms_evt_lar_cut_props(data, sel)
78+
dataprod_larcut_filter = dataprod_larcut.energy_types[e_filter]
79+
80+
spm_t = getproperty(global_events.spms, Symbol(dataprod_larcut_filter.pos))
81+
spmdc = getproperty(global_events.spms, Symbol(dataprod_larcut_filter.is_dc))
82+
spm_pe = getproperty(global_events.spms, e_filter)
83+
84+
ged_sum_window = dataprod_larcut.ged_sum_window
85+
86+
t_wins = ClosedInterval.(geds_t0 .+ first(ged_sum_window), geds_t0 .+ last(ged_sum_window))
87+
88+
pe_ch_threshold = dataprod_larcut.pe_ch_threshold
89+
pe_sum_threshold = dataprod_larcut.pe_sum_threshold
90+
multiplicity_threshold = dataprod_larcut.multiplicity_threshold
91+
92+
colnames = Tuple(Symbol.("$(e_filter)_" .* ["lar_cut", "spms_win_pe_sum", "spms_win_multiplicity"]))
93+
return StructArray(_lar_cut.(Ref(colnames), t_wins, spm_t, spmdc, spm_pe, Ref(pe_ch_threshold), Ref(pe_sum_threshold), Ref(multiplicity_threshold)))
94+
end
95+
96+
function _build_lar_cut(data::LegendData, sel::AnyValiditySelection, global_events::AbstractVector{<:NamedTuple})
97+
dataprod_larcut = get_spms_evt_lar_cut_props(data, sel)
98+
energy_types = keys(dataprod_larcut.energy_types)
99+
100+
is_valid_lar_propfunc = ljl_propfunc(dataprod_larcut.is_valid_lar)
75101

76-
t_wins = @. ClosedInterval(geds_t0 - 1u"μs", geds_t0 + 5u"μs")
77-
return StructArray(_lar_cut.(t_wins, spm_t, spmdc, spm_pe))
102+
lar_cut = StructArray(merge(columns.(_build_lar_cut.(Ref(data), Ref(sel), Ref(global_events), energy_types))...))
103+
return StructArray(merge((is_valid_lar = is_valid_lar_propfunc.(lar_cut),), columns(lar_cut)))
78104
end

0 commit comments

Comments
 (0)