API
Modules
Types and constants
Functions and macros
Juleanita.GeBandgap
Juleanita.Ge_Energy_per_eholePair
Juleanita.Ge_NumberChargeCarrier
Juleanita.V_to_electrons
Juleanita._ADC_to_V
Juleanita._ADC_to_electrons
Juleanita._ADC_to_keV
Juleanita._is_valid_datestr
Juleanita.apply_qc
Juleanita.csv_to_lh5
Juleanita.fit_linearity
Juleanita.noise_sweep
Juleanita.process_ctc
Juleanita.process_decaytime
Juleanita.process_dsp
Juleanita.process_energy_calibration
Juleanita.process_filteropt
Juleanita.process_hit
Juleanita.process_peak_split
Juleanita.process_peakfits
Juleanita.process_pulser_linearity
Juleanita.process_qualitycuts
Juleanita.read_csv_metadata
Juleanita.read_folder_csv_oscilloscope
Juleanita.rms
Juleanita.simple_dsp
Juleanita.simple_dsp_pulser
Juleanita.simple_dsp_qc
Juleanita.sktutek_csv_to_lh5
Documentation
Juleanita.electron_charge
— Constantelectron_charge
charge of electron in Coulomb: $e = 1.60217662 10^{-19}$ C
Juleanita.GeBandgap
— MethodGeBandgap(T::Real)
bandgap energy (eV) of germanium as a function of temperature (K)
\[E_\textrm{gap}(T) = 0.744 - \frac{4.774 \cdot 10^{-4} \cdot T^2}{T + 235}\]
Juleanita.Ge_Energy_per_eholePair
— MethodGe_Energy_per_eholePair(T::Real)
energy (eV) required to create an electron-hole pair in germanium as a function of temperature (K)
\[E(T) = 2.2 \cdot E_\textrm{gap}(T) + 1.99 \cdot E_\textrm{gap}(T)^{3/2} \cdot \exp(4.75 \cdot \frac{E_\textrm{gap}(T)}{T})\]
Juleanita.Ge_NumberChargeCarrier
— MethodGe_NumberChargeCarrier(E::Real, T::Real)
number of charge carriers created by an energy E (eV) in germanium at temperature T (K)
Juleanita.V_to_electrons
— MethodV_to_electrons(Voltage_V::Real, capacitance_F::Real; gain::Real = 1.0)
Convert voltage into a charge in electrons based on the capacitance of the system (could be pulser, detector, or combination).
\[Q[e^{-}] = \frac{V}{\textrm{gain}} \cdot \frac{C_{\textrm{inj}}}{e^{-}}\]
Juleanita._ADC_to_V
— Method_ADC_to_V(ADC::Real, dynamicrange_V::Real, bits::Int)
Convert ADC-code from digitizer into voltage. The ADC-code is assumed to be in the range [0, 2^bits]
corresponding to voltages within the dynamic range.
\[V = \frac{V_{\textrm{dynamic range}}}{2^{\textrm{bits}}} \cdot \textrm{ADC}\]
Inputs:
ADC
: ADC-code from digitizerdynamicrange_V
: dynamic range of the DAQ in Voltsbits
: number of bits of the ADC
Juleanita._ADC_to_electrons
— Method_ADC_to_electrons(ADC::Real, capacitance_F::Real; bits::Int = 14, dynamicrange_V::Real = 2.0, gain::Real = 1.0)
Convert ADC-code from pulser into injected charge in pulserADCto_electrons
\[Q[e^{-}] = (\frac{V_{\textrm{dynamic range}}}{2^{\textrm{bits}}} \cdot \textrm{ADC}) \cdot \frac{1}{\textrm{gain}} \cdot \frac{C_{\textrm{inj}}}{e^{-}}\]
Inputs:
ADC
: ADC-code from digitizercapacitance_F
: capacitance of the system (could be pulser, detector, or combination) in Faradbits
: number of bits of the ADCdynamicrange_V
: dynamic range of the DAQ in Voltsgain
: gain of the system
Juleanita._ADC_to_keV
— Methodpulser_ADC_to_keV(ADC::Real, capacitance_F::Real; bits::Int = 14, dynamicrange_V::Real = 2.0, gain::Real = 1.0)
Convert ADC-code from pulser into injected energy in keV. Inputs:
ADC
: ADC-code from digitizercapacitance_F
: capacitance of the system (could be pulser, detector, or combination) in Faradbits
: number of bits of the DAQdynamicrange_V
: dynamic range of the ADC in Voltsgain
: gain of the system
Juleanita._is_valid_datestr
— Method_is_valid_datestr(timestr_file::String; timezone::String = "PT")
check if the time string in the filename is a valid date string
Juleanita.apply_qc
— Methodquality cuts based on dsp parameters
Juleanita.csv_to_lh5
— Methodcsvtolh5(data::LegendData, period::DataPeriod, run::DataRun, category::DataCategoryLike, channel::ChannelId, csv_folder::String; heading::Int = 17, nwvfmax::Union{Int, Float64, Vector{Int64}} = NaN, nChannels::Int = 2, ti::ClosedInterval{<:Quantity} = 0.0u"µs".. 550.0u"µs")
- converts csv files from oscilloscope to lh5 files
- format of csv file matches the one from an oscilloscope...might be different for other systems
- saves the lh5 files in the raw tier defined in "LEGENDDATACONFIG"
INPUTS:
data::LegendData
LegendData object. You need"LEGEND_DATA_CONFIG"
to construct this. this will define later where.lh5
files are savedperiod::DataPeriod
data period that you want to assign your data torun::DataRun
data run that you want to assign your data tocategory::DataCategoryLike
data category that you want to assign your data tochannel::ChannelId
channel id that you want to assign your data tocsv_folder::String
folder where the csv files are locatedcsv_heading::Int
number of lines to skip in csv filenwvfmax::Union{Int, Float64, Vector{Int64}}
number of waveforms to read OR vector of waveforms indices to readnChannels::Int
number of channels in csv files to read (supports only 1 or 2)ti::ClosedInterval{<:Quantity}
time interval to truncate the waveforms towpf::Int
waveforms per files –> number of waveforms to write per.lh5
file
Juleanita.fit_linearity
— Methodfit_linearity(pol_order::Int, µ::AbstractVector{<:Union{Real,Measurement{<:Real}}}, peaks::AbstractVector{<:Union{Real,Measurement{<:Real}}}; pull_t::Vector{<:NamedTuple}=fill(NamedTuple(), pol_order+1), v_init::Vector = [], uncertainty::Bool=true )
Fit the calibration lines with polynomial function of polorder order polorder == 1 -> linear function pol_order == 2 -> quadratic function
Returns
* `result`: NamedTuple with the following fields
* `par`: best-fit parameters
* `gof`: godness of fit
* `report`:
Juleanita.noise_sweep
— Functionnoise_sweep(filter_type::Symbol, wvfs::ArrayOfRDWaveforms, dsp_config::DSPConfig, τ_pz::Quantity{T}; ft::Quantity{T}= 0.0u"µs", τ_cusp::Quantity{<:AbstractFloat} = 10000000.0u"µs", τ_zac::Quantity{<:AbstractFloat} = 10000000.0u"µs" ) where T<:Real
noise_sweep(filter_type::Symbol, wvfs::ArrayOfRDWaveforms, dsp_config::DSPConfig; kwargs... )
Noise sweep function used in DSP filter optimizatio. The goal is to find the optimal rise-time (for a given flat-top time) which minimizes ENC noise. This is an alternative approach to dsp_trap_rt_optimization
.
Strategy:
- Shift waveforms to have a common baseline, and deconvolute them with the pole-zero correction (in case τ_pz > 0.0u"µs" )
- Filter waveforms with given rise-time and flat-top time
- Build histogram out of all samples in baseline from all waveforms. Remove bins at the beginning and end of the waveform to avoid edge effects.
- Calculate the RMS of the baseline noise –> ENC noise
Inputs:
filter_type::Symbol
: filter type (:trap or :cusp)wvfs::ArrayOfRDWaveforms
: raw waveforms to be filtereddsp_config::DSPConfig
: DSP configuration object containing relevant parameters:ft
,grid_rt
,bl_window
,flt_length_cusp
,flt_length_zac
τ_pz::Quantity{T}
: pole-zero decay time. If τ_pz = 0.0u"µs" (or none given), no pole-zero correction is applied.
kwargs:
ft::Quantity{T}
: fixed flat-top time for optimizationτ_cusp::Quantity{<:AbstractFloat}
: cusp decay time; only relevant for cusp filterτ_zac::Quantity{<:AbstractFloat}
: cusp decay time; only relevant for zac filter
Juleanita.process_ctc
— Methodprocess_ctc(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId, ecal_config::PropDict, ctc_config::PropDict;
energy_types::Vector{Symbol} = Symbol.(ctc_config.energy_types), reprocess::Bool = false)
process_ctc(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId; kwargs...)
Calculate charge-trapping correction: by looking at correlation between drift time and energy. Save correction function to rpars. Inputs:
data::LegendData
: LegendData objectperiod::DataPeriod
: data periodrun::DataRun
: data runcategory::Union{Symbol, DataCategory}
: data category, e.g. :calchannel::ChannelId
: channel idecal_config::PropDict
: energy calibration configuration. If not specified use default from metadatactc_config::PropDict
: charge-trapping correction configuration. If not specified use default from metadata
Optional:
energy_types::Vector{Symbol}
: energy types to processreprocess::Bool
: reprocess the files or notjuleana_logo::Bool
: add juleana logo to plots
Juleanita.process_decaytime
— Functionprocess_decaytime(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId, min_τ::Quantity{T}, max_τ::Quantity{T}, nbins::Int, rel_cut_fit::Real, peak::Symbol, bl_window::ClosedInterval{<:Unitful.Time{<:T}}, tail_window::ClosedInterval{<:Unitful.Time{<:T}}; reprocess::Bool = false) where T <: Real
process_decaytime(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId, pz_config::PropDict, bl_window::ClosedInterval{<:Unitful.Time{<:T}}, tail_window::ClosedInterval{<:Unitful.Time{<:T}}; kwargs...) where T <: Real
process_decaytime(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId, pz_config::PropDict, dsp_config::DSPConfig; kwargs...)
process_decaytime(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId; kwargs...)
Goal: calculate decay time used for pole-zero correction Inputs:
data::LegendData
: LegendData objectperiod::DataPeriod
: data periodrun::DataRun
: data runcategory::Union{Symbol, DataCategory}
: data category, e.g. :calchannel::ChannelId
: channel idmin_τ::Quantity{T}
: minimum decay timemax_τ::Quantity{T}
: maximum decay timenbins::Int
: number of bins for histogramrel_cut_fit::Real
: relative cut for truncated gausspeak::Symbol
: peak to use for decay time calculation. Can also be :all to use all :raw instead of :jlpeaks tierbl_window::ClosedInterval{<:Unitful.Time{<:T}}
: baseline windowtail_window::ClosedInterval{<:Unitful.Time{<:T}}
: tail window
Optional:
reprocess::Bool
: reprocess the files or notjuleana_logo::Bool
: add juleana logo to plots
Juleanita.process_dsp
— Functionprocess_dsp(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId, dsp_config::DSPConfig, τ_pz::Quantity{<:Real}, pars_filter::PropDict; reprocess::Bool = false )
process_dsp(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId ; kwargs... )
Goal:
- run the DSP processing for all raw files in the given period, run, category and channel.
- based on
simple_dsp
function - save the results in the jldsp tier
- if reprocess is false, it will skip the files that are already processed
INPUTS: - data::LegendData
LegendData object. You need "LEGEND_DATA_CONFIG"
to construct this, e.g. l200 = LegendData(:l200)
- period::DataPeriod
data period, e.g. DataPeriod(1)
- run::DataRun
data run, e.g. DataRun(1)
- category::Symbol
data category, e.g. DataCategory(:cal)
- channel::ChannelId
channel id, e.g. ChannelId(1)
(depending on your data!) - dsp_config::DSPConfig
DSP configuration object. If not specified will take default from metadata - τ_pz::Quantity{<:Real}
decay time used for pole-zero correction. If not specified will take from rpars.pz - pars_filter::PropDict
optimized filter parameters used in DSP. If not specified will take from rpars.fltopt
KWARGS: - reprocess::Bool
reprocess the files or not
OUTPUTS: - save the DSP results in the jldsp tier - print the progress - print the completion message
Juleanita.process_energy_calibration
— Functionprocess_energy_calibration(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId, source::Symbol; reprocess::Bool = true, ecal_config::PropDict = data.metadata.config.energy.energy_config.default, e_types::Vector{<:Symbol} = [:e_trap, :e_cusp, :e_zac])
perform energy calibration: take uncalibration energy values from dsp files and calibrate them using calibration sources INPUTS:
- data::LegendData: LegendData object
- period::DataPeriod: data period
- run::DataRun: data run
- category::Union{Symbol, DataCategory}: data category, e.g. :cal
- channel::ChannelId: channel id
- source::Symbol: calibration source. :th228 or :co60 are supported at the moment
OPTIONAL:
- reprocess::Bool: reprocess the files or not
- ecal_config::PropDict: energy calibration configuration. if not specified, it will take the default from metadata
- etypes::Vector{<:Symbol}: energy types to calibrate. default is [:etrap, :ecusp, :ezac]
OUTPUT:
- save the calibration parameters as json files to disk (in generated/par/rpars/ecal/...)
- save the calibration plots to disk (in generated/jlplt/rplt/...)
Juleanita.process_filteropt
— Functionprocess_filteropt(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId, dsp_config::DSPConfig, τ_pz::Quantity{T}, peak::Symbol; rt_opt_mode::Symbol = :blnoise, reprocess::Bool = false, filter_types::Vector{Symbol} = [:trap, cusp])
process_filteropt(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId; kwargs...)
Filter optimization for filter_types
- load waveforms from peakfile, shift baseline and pole-zero
- optimize rise-time for minimum baseline noise after filtering
- optimize flat-top time for FWHM of peak
- save results to disk
- sanity plots for rise-time and flat-top time optimization
Inputs:
data::LegendData
: LegendData objectperiod::DataPeriod
: data periodrun::DataRun
: data runcategory::Union{Symbol, DataCategory}
: data category, e.g. :calchannel::ChannelId
: channel id
Optional:
dsp_config::DSPConfig
: DSP configuration object. If not specified will take default from metadataτ_pz::Quantity{T}
: pole-zero decay time. If not specified will take default from metadatapeak::Symbol
: peak to optimize for (needs existing peakfile!). If not specified will take default from metadatart_opt_mode::Symbol
: mode for rise-time optimization (:blnoise or :pickoff) –> two different strategies for optimizationreprocess::Bool
: reprocess the files or notfilter_types::Vector{Symbol}
: filter types to optimize for
Juleanita.process_hit
— Methodprocessing_hit(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId; reprocess::Bool = false, e_types::Vector{<:Symbol} = [:e_trap, :e_cusp, :e_zac])
- run the hit processing for all dsp files in the given period, run, category and channel.
- apply energy calibration to the dsp energy estimator and save the results in the jlhit tier
- no PSD at the moment, will be added in future
- if reprocess is false, it will skip the files that are already processed
INPUTS:
data::LegendData
LegendData objectperiod::DataPeriod
data periodrun::DataRun
data runcategory::Union{Symbol, DataCategory}
data category, e.g. :calchannel::ChannelId
channel idreprocess::Bool
reprocess the files or note_types::Vector{<:Symbol}
energy types to process. default is [:etrap, :ecusp, :e_zac]
OUTPUTS:
- save the hit results in the jlhit tier
Juleanita.process_peak_split
— Functionprocess_peak_split(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId, ecal_config::PropDict, dsp_config::DSPConfig, qc_config::PropDict; reprocess::Bool = false)
process_peak_split(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId; kwargs...)
Create peak files containting only waveforms from peaks in the calibration spectrum.
- Read raw data
- Find peaks in the calibration spectrum using rough energy estimate
data_fk.daqenergy
- Do simple DSP for peaks only
- apply quality cuts based on simple DSP
- Save waveforms after QC to peak files
inputs:
- data: LegendData object
- period: DataPeriod object
- run: DataRun object
- category: Symbol or DataCategory object, e.g. :cal for calibration
- channel: ChannelId for germanium detector
- ecal_config: PropDict, energy calibration configuration
- dsp_config: DSPConfig, DSP configuration
- qc_config: PropDict, quality cut configuration
keyword arguments:
reprocess: Bool, default is false
Output:
- h_uncals histograms of peaksearch
- peakpos
Also, peak files containting only waveforms from peaks in the calibration spectrum are saved to jlpeaks folder.
Juleanita.process_peakfits
— Functionprogress_peakfits(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId; reprocess::Bool = true, e_types::Vector{<:Symbol} = [:e_trap, :e_cusp, :e_zac], juleana_logo::Bool = false)
Process the peak fits for the benchtest data.
Juleanita.process_pulser_linearity
— FunctionJuleanita.process_qualitycuts
— Functionprocess_qualitycuts(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId; reprocess::Bool = false, qc_config::PropDict = data.metadata.config.qc.qc_config.default)
apply quality cuts based on dsp parameters inputs: data: LegendData object period: DataPeriod object run: DataRun object category: Symbol or DataCategory object channel: ChannelId object reprocess: Bool, default false qcconfig: PropDict, default data.metadata.config.qc.qcconfig.default
Juleanita.read_csv_metadata
— Methodread_csv_metadata(filepath::String; heading::Int = 17, nChannels::Int = 2, timezone = "PT")
read metadata from a csv file (as taken from oscilloscope) input:
- filepath::String: file name
- heading::Int: number of lines (beginning at top) in csv file contain metadata
- nChannels::Int: number of channels in csv file
- timezone::String: timezone to which the timekey in filename refers (standard is PT = Pacific Time –> Berkeley)
Juleanita.read_folder_csv_oscilloscope
— Methodread_folder_csv_oscilloscope(csv_folder::String; heading::Int = 17, nwvfmax::Union{Int, Float64, Vector{Int64}} = NaN, nChannels::Int = 2)
read folder with csv files from oscilloscope input:
- csv_folder::String: absolute csv folder path
- heading::Int: number of lines to skip
- nwvfmax::Union{Int, Float64, Vector{Int64}}: number of waveforms to read OR vector of waveforms indices to read
- nChannels::Int: number of channels in csv files to read (1 or 2)
Juleanita.rms
— Methodrms(x::Vector{T}) where {T <: Real}
Calculate the RMS of a vector of real numbers.
Juleanita.simple_dsp
— Methodsimple_dsp(data::Q, dsp_config::DSPConfig; τ_pz::Quantity{T} = 0.0u"µs", pars_filter::PropDict) where {Q <: Table, T<:Real}
dsp routine which calculates all relevant parameters for the waveform analysis
data::Q
: input data, e.g. raw file, peakfiledsp_config::DSPConfig
: DSP configuration objectτ_pz::Quantity{T}
: pole-zero decay time. If τ_pz = 0.0u"µs" (or none given), no pole-zero correction is applied.pars_filter::PropDict
: filter parameters for the different filter types. Use PropDict() to get default values from config.
Juleanita.simple_dsp_pulser
— Methodsimple_dsp_pulser(data::Q, dsp_config::DSPConfig; τ_pz::Quantity{T} = 0.0u"µs", pars_filter::PropDict) where {Q <: Table, T<:Real}
minimal version of simple_dsp
for pulser channel
Juleanita.simple_dsp_qc
— Methodminimal version of simple_dsp
used to calculate quality cuts with peakfiles
Juleanita.sktutek_csv_to_lh5
— Functionskutek_csv_to_lh5(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId, csv_folder::String; timestep::Quantity = 0.01u"µs")
skutek_csv_to_lh5(data::LegendData, period::DataPeriod, run::DataRun, category::Union{Symbol, DataCategory}, channel::ChannelId; kwargs...)
convert csv files from Skutek digitizer "FemtoDAQ Vireo" to lh5 files
- format of csv file matches the one of Skutek digitizer "FemtoDAQ Vireo ...might be different for other systems
inputs:
data::LegendData
LegendData object. You need"LEGEND_DATA_CONFIG"
to construct this. this will define later where.lh5
files are savedperiod::DataPeriod
data period that you want to assign your data torun::DataRun
data run that you want to assign your data tocategory::DataCategoryLike
data category that you want to assign your data tochannel::ChannelId
channel id that you want to assign your data tocsv_folder::String
folder where the csv files are located (optinal). if not defined use the default folder
kwargs
timestep::Quantity
time step of the waveforms. default is 0.01µs –> 100 MHz sampling.- chmode::Symbol = :diff
:diff
ch1 - ch2 is stored asraw/waveform
:diffplus
ch1 - ch2 is stored asraw/waveform
AND both channels are stored asraw/waveform_ch1
andraw/waveform_ch2
(if available in data):single
ch1 is stored asraw/waveform
and ch2 is stored asraw/waveform_ch2
(if available in data):pulser
ch1 is stored asraw/waveform
and ch2 is stored asraw/pulser