API Reference

Complete reference for Ronin's exported API, grouped by topic. See the Concepts and Workflow Guide pages for how these fit together.

Configuration

The ModelConfig struct is the single source of truth; the rest construct, persist, reload, and migrate it.

Ronin.ModelConfigType

Stuct used to store configuration information for a given model

Required arguments

num_models:::Int64

Number of ML models in the model chain. Can be one or more.

model_output_paths::Vector{String}

Vector containing paths to each model in the model chain. Should be same length as the number of models

met_probs::Vector{Tuple{Float32,Float32}}

Vector containing the decision range for a gate to be considered meteorological in each model in the chain. Example, if set to (.9, 1), > 90% of trees in the random forest must assign a gate a label of meteorological for it to be considered meteorological. The range is exclusive on both ends. That is, for a gate to be classified as non-meteorological, it must have a probability LESS THAN the low threshold, and for a gate to be classified as meteorological it must have a probability GREATER THAN the high threshold. For multi-pass models, gates between these thresholds (inclusive) will be sent on to the next pass. Form is (lowthreshold, highthreshold)

feature_output_paths::Vector{String}

Vector containing paths representing the locations to output calculated features to for each model in the chain.

input_path::String

Directory containing input radar data

task_mode::String

Selects the feature-engineering regime. Codebase behavior is not agnostic to this value — it branches across training, prediction, QC, and mask generation:

  • task_mode == "convolution" — convolution feature mode. Features are derived from a kernel bank applied to conv_variables (plus appended AHT/ELV/RNG/NRG scalars); see the Convolution Feature Mode documentation. run_hypertuning requires this mode.
  • task_mode == "" (or any value other than "convolution") — legacy hand-tuned predictor mode. Features come from the task_paths / task_weights predictor specification (STD/ISO/AVG/RNG/NRG/PGG/AHT); see the Legacy Hand-Tuned Mode documentation.

regenerate_masks is the only mode-agnostic pass utility.

file_preprocessed::Vector{Bool}

For each model in the chain, contains a boolean value signifying if the correspondant feature output path has already been processed. If true, will open the file at this path instead of re-calculating input features.

Optional arguments

Input tasks and weights

The following arguments are only quasi-optional, one of them must be set.

    task_list::Vector{String} = [""]
    task_weights::Vector{Vector} = [[Matrix{Union{Float32, Missing}}(undef, 0,0)]]
Currently only `task_paths` are supported. Contains a vector of the same length as the number of
models, with each entry being the path to a file contianing the tasks for the pass. Future plans involve
allowing a usesr to specify vectors of tasks in `task_list`.

`task_weights` must be a vector of vectors, with the first dimension the same length as the number of models in the
chain. The second dimension much either be 1, containing the default weight matrix `Matrix{Union{Float32, Missing}}(undef, 0,0)`,
or a secondary vector of matrixes - one matrix for each task in the passs. Sample weight matrixes are defined in RoninConstants.jl
verbose::Bool = true

Whether to print out timing information, etc.

REMOVE_LOW_SIG_QUALITY::Bool = true

Whether to automatically remove gates that do not meet a basic Signal Quality threshold. Variable used to determine this specified in SIG_QUALITY_VAR

REMOVE_HIGH_PGG::Bool = true

Whether to automatically remove gates that do not meet a basic PGG threshold

HAS_INTERACTIVE_QC::Bool = false

Whether the radar data has already had interactive QC applied to it

QC_var::String = "VG"

If radar data has interactive QC already applied, the name of a variable that the QC has been applied to

remove_var::String = "VV"

Name of a raw variable in the radar data that can be used to determine the location of missing gates

FILL_VAL::Float32 = RoninConstants.FILL_VAL

Fill value for output cfradials

replace_missing::Bool = false

For spatial feature (AVG, STD, etc.) calculation, whether or not to replace MISSING gates in the mask area with FILL_VAL

write_out::Bool = true

Whether or not to write the calculated input features to disk, paths specified in featureoutputpaths

QC_mask::Bool = false

For the first model in the chain, whether or not to mask gates considered for feature calculation using a mask specified by mask_name More details elsewhere in the documentation.

mask_names::Vector{String} = [""]

List of names for masks in the model. Must be of same length as number of models in the chain. In the case of a model with QC_mask set to true, the first mask name in this vector should contain a string denoting the name of a field in all cfradial files that is dimensioned the same as the radar sweeps and contains values of missing where data is not to be considred, and values of float otherwise.

VARS_TO_QC::Vector{String} = ["VV", "ZZ"]

List of variables to apply QC to to get mask for next model in chain

QC_SUFFIX::String

Postfix to apply to variable name once QC has been applied.

class_weights::String = ""

Class weighting scheme to apply in the training of RF model. Currently only "balanced" is implemented.

n_trees::Int = 21

Number of trees in the random forest

max_depth::Int = 14

Maximum depth of any one tree in the random forest

overwrite_output::Bool = false

If true, will remove/overwrite existing files when internal functionality attempts to write new data to them

SIG_QUALITY_THRESHOLD::Float32 = .2

If REMOVELOWNCP is set to true, threshold at or below which to remove data.

PGG_THRESHOLD::Float32 = 1.

If REMOVEHIGHPGG is set to true, threshold at or above which to remove data.

SIGNAL_QUALITY_VAR::String = "NCP"

Name of variable in cfradial file representing signal quality. Most commonly "NCP" or "SQI"

source
Ronin.make_configFunction
make_config(; num_models, input_path, experiment_name="experiment", kwargs...)

Convenience constructor for ModelConfig that auto-generates paths and mask names from num_models and experiment_name, reducing boilerplate.

Auto-generated fields (can be overridden via kwargs):

  • model_output_paths: ["trained_model_<name>_<i>.jld2" for i in 1:num_models]
  • feature_output_paths: ["output_features_<name>_<i-1>.h5" for i in 1:num_models]
  • mask_names: ["mask_pass_<i-1>" for i in 1:num_models]
  • met_probs: [(0.1f0, 0.9f0) for _ in 1:num_models]
  • file_preprocessed: [false for _ in 1:num_models]

All other ModelConfig fields can be passed as keyword arguments.

source
Ronin.save_configFunction
save_config(path::String, config::ModelConfig)

Save a ModelConfig to a JLD2 file in dict-keyed format: one key per field.

This format is robust to struct evolution. Adding a field to ModelConfig later just means a new key for fresh files; old files still load via load_config, which fills any missing key with the struct's default. No migration required on every shape change.

Replaces the legacy pattern JLD2.save_object(path, config), which pickled the struct shape and broke on every field addition (see issue #34). The legacy format is still readable by load_config.

source
Ronin.load_configFunction
load_config(path::String) -> ModelConfig

Load a ModelConfig from a JLD2 file, transparently handling both storage formats:

  • Dict-keyed format (written by save_config): each ModelConfig field is stored under its own key. Missing keys fall back to the struct's @kwdef defaults, so future field additions do not break old files.

  • Legacy save_object format (single single_stored_object key holding a pickled struct): JLD2 may load these as a ReconstructedMutable shadow type when the saved struct shape no longer matches the current ModelConfig. Each accessible field is copied via getproperty into a fresh, real ModelConfig instance; defaults fill in any new fields the saved file lacks.

A real, mutable ModelConfig is returned regardless of source format — callers can then assign to fields (config.task_paths = [...]) without hitting setproperty! errors on ReconstructedMutable.

source
Ronin.migrate_model_configFunction
migrate_model_config(infile::String, outfile::String; key=nothing)

One-shot utility: load a legacy save_object-format ModelConfig file and re-save it in the new dict-keyed format written by save_config. Returns the rebuilt ModelConfig.

Migration is not required for loadingload_config reads legacy files inline. Use this helper only when you want to upgrade a long-lived file on disk so future loads skip the legacy path (and the deprecation @info).

key may be passed to select a specific JLD2 key when the file contains multiple stored objects; defaults to the standard single_stored_object key used by JLD2.save_object.

source

Data preparation

Splitting cfradial directories into train/test/(validation) sets and related directory utilities.

Ronin.split_training_testing!Function

Function to split a given directory or set of directories into training and testing files using the configuration described in DesRosiers and Bell 2023. This function assumes that input directories only contain cfradial files that follow standard naming conventions, and are thus implicitly chronologically ordered. The function operates by first dividing file names into training and testing sets following an 80/20 training/testing split, and subsequently softlinking each file to the training and testing directories. Attempts to avoid temporal autocorrelation while maximizing variance by dividing each case into several different training/testing sections.

An important note: Always use absolute paths, relative paths will cause issues with the simlinks

Required Arguments:

DIR_PATHS::Vector{String}

List of directories containing cfradials to be used for model training/testing. Useful if input data is split into several different cases.

TRAINING_PATH::String

Directory to softlink files designated for training into.

TESTING_PATH::String

Directory to softlink files designated for testing into.

source
Ronin.split_training_testing_validation!Function
split_training_testing_validation!(DIR_PATHS::Vector{String},
                                    TRAINING_PATH::String,
                                    TESTING_PATH::String,
                                    VALIDATION_PATH::String)

Split a directory or set of directories of cfradial files into training, testing, and held-out validation sets, following the methodology of DesRosiers and Bell 2023. This is the three-way analogue of split_training_testing!: it additionally carves out a validation partition for unbiased final evaluation.

The default split is 72% training / 20% testing / 8% validation. As with the two-way split, this function assumes input directories contain only cfradial files following standard naming conventions (thus implicitly chronologically ordered), divides each case into several sections to limit temporal autocorrelation while maximizing variance, and softlinks the files into the destination directories.

An important note: always use absolute paths — relative paths break the symlinks.

Required Arguments

  • DIR_PATHS::Vector{String}: directories of cfradials to split. Each directory is treated as a distinct case.
  • TRAINING_PATH::String: directory to softlink training files into.
  • TESTING_PATH::String: directory to softlink testing files into.
  • VALIDATION_PATH::String: directory to softlink the held-out validation files into.

The destination directories are removed and recreated, so any existing contents are discarded.

source
Ronin.remove_validationFunction

Function used to remove a given subset of the rows from a feature set so that they may be used for model validation/tuning.

Currently configured to utilize the 90/10 split described in DesRosiers and Bell 2023.

Required arguments

input_dataset::String

Path to h5 files containing model features

Optional keyword arguments

training_output::String = "train_no_validation_set.h5"

Path to output training features with validation removed to

validation_output::String = "validation.h5"

Path to output validation features to

remove_original::Bool = true

Whether or not to remove the original file described by the input_dataset path.

NOTE: the split is a deterministic stride — every 10th row (indices 1, 11, 21, …) goes to the validation set and the remainder to training. This is not a randomized split; if the feature matrix is ordered (e.g. grouped by sweep/time), the validation set inherits that structure. remove_original=true (the default) deletes the input file after writing the outputs, so pass distinct output paths. See docs/KNOWN_ISSUES.md for the v1.2.1 follow-up (optional seeded random split + path-collision guard).

source
Ronin.parse_directoryFunction
parse_directory(dir_path::String) 

Parses through directory specified by dir_path and ensures that files start with the prefix specified by Ronin.RADAR_FILE_PREFIX

source

Feature calculation — convolution mode

The recommended feature regime: a kernel bank convolved over conv_variables.

Ronin.calculate_features_convFunction
calculate_features_conv(config::ModelConfig, output_file::String;
                         QC_mask::Bool=false, mask_name::String="",
                         write_out::Bool=true, return_idxer::Bool=false)

Convolution-mode feature calculation. Iterates over all files in config.input_path and computes convolution features for each sweep.

source
Ronin.build_kernel_bankFunction
build_kernel_bank(kernel_sizes::Vector{Int})

Build a bank of convolution kernels at the specified scales.

Returns a Vector{ConvolutionKernel} containing:

  • Mean kernels at each scale (uniform weights, normalized)
  • Laplacian 3x3 (edge/texture detection)
  • Sobel-like range gradient 3x3
  • Sobel-like azimuth gradient 3x3
  • Gaussian kernels at scales >= 5
source
Ronin.compute_convolution_featuresFunction
compute_convolution_features(cfrad, conv_variables::Vector{String},
                              kernel_bank::Vector{ConvolutionKernel},
                              valid_mask::AbstractMatrix{Bool},
                              SIG_QUALITY_VAR::String)

Compute the full convolution feature matrix for a single sweep.

For each variable in conv_variables x each kernel in kernel_bank, produces 2 columns:

  1. The convolved value
  2. The valid fraction (ISO equivalent)

Additionally appends scalar (non-convolved) physical features: AHT, ELV, RNG, NRG.

Returns (X::Matrix{Float32}, feature_names::Vector{String}) where X is (numrange * numtime) x numfeatures, with FILLVAL for invalid gates.

source
Ronin.masked_convolveFunction
masked_convolve(data, kernel, valid; neighbor_mask=valid)

Compute a masked convolution over data using kernel.

  • valid controls which center gates receive a computed value (others get FILL_VAL).
  • neighbor_mask controls which neighbors contribute to the convolution (default: same as valid).

Using a separate neighbor_mask enables met_prob-masked convolutions: compute features for all valid gates, but only let high-confidence neighbors contribute to the spatial statistics.

Returns (result, valid_fraction) where:

  • result[i,j] = weighted sum of valid neighbors / sum of weights at valid neighbors
  • valid_fraction[i,j] = fraction of kernel footprint that had valid data (ISO equivalent)

Missing/invalid gates contribute nothing. Edges are zero-padded (treated as invalid).

NOTE: the weighted_sum / weight_sum normalization (where weight_sum is the sum of absolute kernel weights over valid neighbors) is applied uniformly to every kernel, including the zero-sum differential kernels (laplacian, sobel_*). This is intentional and is the behavior validated against real-world data for v1.2.0: for interior gates with a full neighborhood it scales the differential response by sum(abs.(kernel)), and near edges / missing gates it renormalizes by the valid footprint. Changing this normalization would alter every edge/texture feature fed to the classifier, so it must not be "fixed" without re-validation. See the v1.2.1 backlog (docs/KNOWN_ISSUES.md) for the open question of separate smoothing vs. differential normalization.

source
Ronin.get_convolution_feature_countFunction
get_convolution_feature_count(conv_variables, kernel_bank; masked_conv_variables, masked_conv_kernel_bank)

Return the total number of features that will be produced: (nvariables * nkernels * 2) + (nmaskedvariables * nmaskedkernels * 2) + 4 scalar features.

source

Feature calculation — legacy hand-tuned mode

The v1.1.0 hand-crafted predictor pipeline and its spatial reducers.

Ronin.calculate_featuresFunction

Function to process a set of cfradial files and produce input features for training/evaluating a model

Required arguments

input_loc::String

Path to input cfradial or directory of input cfradials

argument_file::String

Path to configuration file containing which features to calculate

output_file::String

Path to output calculated features to (generally ends in .h5)

HAS_INTERACTIVE_QC::Bool

Specifies whether or not the file(s) have already undergone a interactive QC procedure. If true, function will also output a Y array used to verify where interactive QC removed gates. This array is formed by considering where gates with non-missing data in raw scans (specified by remove_variable) are set to missing after QC is performed.

Optional keyword arguments

verbose::Bool=false

If true, will print out timing information as each file is processed

REMOVE_LOW_SIG_QUALITY::Bool=false

If true, will ignore gates with Normalized Coherent Power/Signal Quality Index below a threshold specified in RQCFeatures.jl

SIG_QUALITY_THRESHOLD::Float32 = .2

Theshold at or below which to remove data

SIG_QUALITY_VAR::String = "NCP"

Name of variable containing signal quality parameter

REMOVE_HIGH_PGG::Bool=false

If true, will ignore gates with Probability of Ground Gate (PGG) values at or above a threshold specified in RQCFeatures.jl

PGG_THRESHOLD

Threshold at or above which to remove data

QC_variable::String="VG"

Name of variable in input NetCDF files that has been quality-controlled.

remove_variable::String="VV"

Name of a raw variable in input NetCDF files. Used to determine where missing data exists in the input sweeps. Data at these locations will be removed from the outputted features.

replace_missing::Bool=false

Whether or not to replace MISSING values with FILL_VAL in spatial parameter calculations Default value: False

write_out::Bool=true

Whether or not to write features out to file

return_idxer::Bool = false

If true, will return IDXER, where IDXER is a

weight_matrixes::Vector{Matrix{Union{Missing, Float32}}} = [(undef, 0,0)]

Vector containing a weight matrix for every task in the argument file. For non-spatial parameters, the weights are discarded, and so dummy/placeholder matrixes may be used.

source
Ronin.process_single_fileFunction

###Wrapper version of processsinglefile that allows user to specify a vector of weight matrixes ###In this case will also pass the tasks to complete as a vector ###weight_matrixes are also implicitly the window size

Returns:

-X::Matrix{Float32}: Matrix that is dimensioned (numgates x numfeatures) where numgates is the number of valid (non-missing, meeting NCP/PGG thresholds, non-masked) gates the function finds, and numfeatures is the number of features specified in the argument file to calculate.

-Y::Matrix{Bool} : IF HASINTERACTIVEQC == true, will return Y, array containing 1 if a datapoint was retained during interactive QC, and 0 otherwise. Dimensioned as (num_gates x 1)

-INDEXER::Vector{Bool} : Based on removevariable as described above, contains boolean array specifiying where in the scan features valid data and where does not. Will also contain false where values in `featuremask` are false.

source

Driver function that calculates a set of features from a single CFRadial file. Features are specified in file located at argfile_path.

Will return a tuple of (X, Y, indexer) where X is the features matrix, Y, a matrix containing the verification

  • where human QC determined the gate was meteorological (value of 1), or non-meteorological (value of 0),

and indexer contains a vector of booleans describing which gates met basic quality control thresholds and thus are represented in the X and Y matrixes

Weight matrixes are specified in file header, or passed as explicit argument.

Required arguments

cfrad::NCDataset 

Input NCDataset containing radar scan variables

tasks::Vector{String} 

Vector of inpuit features to calculate

Optional keyword arguments

HAS_INTERACTIVE_QC::Bool = false

If the scan has already had a human apply quality control to it, set to true. Otherwise, false

REMOVE_LOW_SIG_QUALITY::Bool = false

Whether or not to ignore gates that do not meet a minimum NCP/SQI threshold. If true, these gates will be set to false in indexer, and features/verification will not be calculated for them.

SIG_QUALITY_THRESHOLD::Float32 = .2

Theshold at or below which to remove data

SIG_QUALITY_VAR

Name of variable in cfradials containing information about signal quality

REMOVE_HIGH_PGG::Bool = false

Whether or not to ignore gates that exceed a given Probability of Ground Gate(PGG) threshold. If true, these gates will be set to false in indexer, and features/verification will not be calculated for them.

PGG_THRESHOLD

Threshold at or above which to remove data

QC_variable::String = "VG"

Name of a variable in input CFRadial file that has had QC applied to it already. Used to calculate verification Y matrix.

remove_variable::String = "VV" 

Name of raw variable in input CFRadial file that will be used to determine where missing gates exist in the sweep.

replace_missing::Bool = false

For spatial parameters, whether or not to replace missings values with FILL_VAL


Returns:

-X::Matrix{Float32}: Matrix that is dimensioned (num_gates x num_features) where num_gates is the number of valid 
    (non-missing, meeting NCP/PGG thresholds, non-masked) gates the function finds, and num_features is the 
    number of features specified in the argument file to calculate. 

-Y::Matrix{Bool} : IF HAS_INTERACTIVE_QC == true, will return Y, array containing 1 if a datapoint was retained 
    during interactive QC, and 0 otherwise. Dimensioned as (num_gates x 1)

-INDEXER::Vector{Bool} : Based on remove_variable as described above, contains boolean array specifiying
            where in the scan features valid data and where does not. Will also contain `false` where 
            values in `feature_mask` are false.
source
Ronin.get_task_paramsFunction

Function to parse a given task list Also performs checks to ensure that the specified tasks are able to be performed to the specified CFRad file

source

Parses input parameter file for use in outputting feature names to HDF5 file as attributes. NOTE: Cfradial-unaware. If one of the variables is specified incorrectly in the parameter file, will cause errors

source

Passthrough when tasks are already provided as a vector of strings

source
Ronin.get_num_tasksFunction
get_num_tasks(params_file; delimeter = ",")

Count the number of predictor tasks declared in a legacy hand-tuned-mode configuration file.

params_file is a path to a config file (e.g. config.txt) where each non-comment line lists delimeter-separated predictor tasks such as STD(VEL),AVG(ZZ),PGG. Lines beginning with # are treated as comments and skipped; empty tokens are not counted.

Returns the total number of tasks as an Int. This is legacy-mode (task_mode = "") machinery only — convolution mode derives its own feature count via get_convolution_feature_count. A second method, get_num_tasks(tasks::Vector{String}), simply returns length(tasks).

source

Return the number of tasks when tasks are already provided as a vector of strings

source
Ronin.calc_avgFunction
calc_avg(var::Matrix; weights = avg_weights, window = avg_window)

Windowed mean of a radar field — the AVG(var) spatial reducer used by both the convolution and legacy hand-tuned feature modes.

For each gate, the mean is taken over the surrounding window neighbourhood (default Ronin.avg_window) after element-wise multiplication by weights (default Ronin.avg_weights). Gates whose value is missing are excluded from each window; a window that is entirely missing yields Ronin.FILL_VAL. Borders are padded with missing. The global REPLACE_MISSING_WITH_FILL flag, when set, substitutes FILL_VAL for missing inputs before reducing.

Returns a Float32 matrix the same size as var.

source
Ronin.calc_stdFunction
calc_std(var::AbstractMatrix; weights = std_weights, window = std_window)

Windowed standard deviation of a radar field — the STD(var) spatial reducer used by both the convolution and legacy hand-tuned feature modes.

For each gate, the standard deviation is taken over the surrounding window neighbourhood (default Ronin.std_window) after element-wise multiplication by weights (default Ronin.std_weights). Gates whose value is missing are excluded from each window; a window that is entirely missing yields Ronin.FILL_VAL. Borders are padded with missing.

The Union{Missing, Float32} method preserves missing-aware reduction; the generic-matrix method honours the global REPLACE_MISSING_WITH_FILL flag and substitutes FILL_VAL for missing inputs before reducing.

Returns a Float32 matrix the same size as var.

source
Ronin.calc_isoFunction
`calc_iso(var::AbstractMatrix{Union{Missing, T}};
            weights = iso_weights, 
            window  = iso_window)`

Calculates quantity of adjacent gates that contain no data (are missing) 
This will be modulated by weights, and to a lesser degree window. For example, a weight matrix 
with ones along a specific column could be thought of as an isolation calcuation in range 
for a sweep dimensioned as time x range
source
Ronin.airborne_htFunction
airborne_ht(elevation_angle::Float32, antenna_range::Float32, aircraft_height::Float32)

Earth-curvature-corrected height of a radar gate above mean sea level for an airborne (or elevated) platform.

Arguments

  • elevation_angle: beam elevation angle in degrees (positive above the horizon).
  • antenna_range: slant range from the antenna to the gate in metres.
  • aircraft_height: platform height above mean sea level in metres.

Returns

The gate height in kilometres, accounting for the curvature of the Earth (Ronin.EarthRadiusKm) using the standard 4/3-Earth-style geometric relation.

This is the per-gate kernel behind the AHT derived feature; calc_aht applies it across a full sweep grid.

source
Ronin.prob_groundgateFunction
prob_groundgate(elevation_angle, antenna_range, aircraft_height, azimuth)

Geometric probability that a radar gate is contaminated by the ground (the PGG derived feature, per-gate kernel).

Uses the beam/ground intersection geometry of Testud et al. to decide whether the beam can physically reach the surface, then attenuates by a Gaussian beam pattern (half-power beamwidth Ronin.beamwidth) of the offset between the beam axis and the ground-grazing elevation.

Arguments

  • elevation_angle: beam elevation angle in degrees (negative points toward the ground).
  • antenna_range: slant range to the gate in metres.
  • aircraft_height: platform height above the surface in metres.
  • azimuth: beam azimuth in degrees.

Returns

A probability in [0, 1] (1 = certainly ground), or missing if any input is missing. Returns 0 early when the gate geometrically cannot intersect the ground (range shorter than platform height, or elevation at/above the horizon).

calc_pgg applies this across a full sweep grid.

source

Training

Fitting Random Forest classifiers, single-pass and multi-pass.

Ronin.train_modelFunction

Function to train a random forest model using a precalculated set of input and output features (usually output from calculate_features). Returns nothing.

Required arguments

input_h5::String

Location of input features/targets. Input features are expected to have the name "X", and targets the name "Y". This should be taken care of automatically if they are outputs from calculate_features

model_location::String

Path to save the trained model out to. Typically should end in .jld2

Optional keyword arguments

verify::Bool = false

Whether or not to output a separate .h5 file containing the trained models predictions on the training set (Y_PREDICTED) as well as the targets for the training set (Y_ACTUAL)

verify_out::String="model_verification.h5"

If verify, the location to output this verification to.

col_subset=:

Set of columns from input_h5 to train model on. Useful if one wishes to train a model while excluding some features from a training set.

row_subset=:

Set of rows from input_h5 to train on.

n_trees::Int = 21

Number of trees in the Random Forest ensemble

max_depth::Int = 14

Maximum node depth in each tree in RF ensemble

class_weights::Vector{Float32} = Vector{Float32}([1.,2.])

Vector of class weights to apply to each observation. Should be 1 observation per sample in the input data files

source
train_model(X::Matrix, Y::Union{Matrix, Vector}, model_location::String;
             verify=false, verify_out="model_verification.h5",
             n_trees=21, max_depth=14,
             class_weights=Float32[1., 2.], max_threads=Threads.nthreads())

In-memory overload of train_model: fit a DecisionTree RandomForestClassifier directly on a feature matrix X and target vector Y instead of reading them from an HDF5 file.

Arguments

  • X: feature matrix (rows = gates/samples, columns = features).
  • Y: target labels (1/true = meteorological, 0/false = non-met), reshaped to a vector internally.
  • model_location: path the fitted model is written to via save_object.

Keywords

  • n_trees, max_depth: random-forest hyperparameters.
  • class_weights: per-sample weight vector; must match length(Y) or it is ignored (with a warning) and uniform weights are used.
  • verify / verify_out: when verify, write predicted vs. true labels to the verify_out HDF5 file.
  • max_threads: cap on fitting threads (defaults to all available).

Prints training accuracy and timing. The file-path method train_model(input_h5, model_location; ...) simply loads X/Y (with optional row_subset/col_subset) and delegates here.

source
Ronin.train_multi_modelFunction
train_multi_model(config::ModelConfig)

All-in-one function to take in a set of radar data, calculate input features, and train a chain of random forest models for meteorological/non-meteorological gate identification.

#Required arguments

config::ModelConfig

Struct containing configuration info for model training

#Returns -None

source
Ronin.train_single_passFunction
train_single_pass(config::ModelConfig, pass::Int)

Train a single pass of the multi-pass cascade. This is the building block for pass-by-pass tuning workflows:

  • Pass 1: trains on all data (no mask required)
  • Pass 2+: requires masks from prior passes to exist in the CfRadial files (written by train_multi_model or regenerate_masks)

After training, if this is not the final pass, saves met_prob predictions to CfRadials and generates the mask for the next pass.

Returns (X, Y) — the feature matrix and labels used for training.

source

Multi-pass masking

Generating and regenerating the inter-pass met-prob masks.

Ronin.generate_pass_masksFunction
generate_pass_masks(config::ModelConfig, pass::Int; data_path::String="")

Run inference with the trained model for pass and write met_prob_pass_<pass> and mask_pass_<pass+1> to all CfRadial files. This bridges an existing trained pass to the next pass without retraining.

Use this when you have a trained Pass 1 model and want to prepare data for Pass 2 training, or any pass N → pass N+1 transition.

If data_path is provided, it overrides config.input_path (useful for generating masks on both training and testing sets).

The mask threshold is taken from config.met_probs[pass].

source
Ronin.regenerate_masksFunction
regenerate_masks(config::ModelConfig, pass::Int, met_probs_threshold::Tuple{Float32, Float32})

Regenerate the mask for pass+1 using saved met_prob_pass_<pass> fields in CfRadials. This avoids re-running the model — it reads the previously-saved met_prob predictions and applies the new threshold to create an updated mask.

The metprob fields must have been written by a prior `trainmulti_model` call.

source

Feature importance / selection

Permutation and RF-native importance, and feature subsetting.

Ronin.compute_importanceFunction
compute_importance(config::ModelConfig)

Compute permutation-based feature importance for each pass using existing trained models and cached feature files. Does NOT retrain — loads the model from the JLD2 file and features from the HDF5 file.

This is the recommended way to compute importance after initial training (Step 2). It avoids redundant retraining and supports configurable n_importance_repeats and importance_subsample_fraction from the config.

source
Ronin.get_feature_importanceFunction

Uses L1 regression with a variety of λ penalty values to determine the most useful features for

input to the random forest model.


Required Input


input_file_path::String

Path to .h5 file containing model training features under ["X"] parameter, and model targets under ["Y"] parameter. Also expects the h5 file to contain an attribute known as Parameters containing abbreviations for the feature types

λs::Vector{Float32}

Vector of values used to vary the strength of the penalty term in the regularization.

Optional Keyword Arguments


pred_threshold::Float32

Minimum cofidence level for binary classifier when predicting

Returns

Returns a DataFrame with each row containing info about a regression for a specific λ, the values of the regression coefficients for each input feature, and the Root Mean Square Error of the resultant regression.

source
Ronin.select_featuresFunction
select_features(importance_scores::Vector{Float64}, threshold_fraction::Float64)

Given RF feature importance scores, return indices of features whose importance is above threshold_fraction of the maximum importance.

Used during training to prune low-value features. The returned indices are saved with the model for use at inference time.

source
Ronin.compute_rf_feature_importanceFunction
compute_rf_feature_importance(model, X::Matrix{Float32}, Y::Vector;
                               n_repeats::Int=3, subsample_fraction::Float64=1.0)

Compute permutation-based feature importance for a random forest ensemble. For each feature, randomly shuffle that column and measure the drop in accuracy. Higher drop = more important feature.

Performance optimizations:

  • Features are evaluated in parallel using Threads.@threads
  • subsample_fraction < 1.0 evaluates on a random subset (e.g., 0.5 = 50% of samples) This is statistically stable for large datasets and provides significant speedup.
  • Each thread works on its own copy of the subsampled data to avoid race conditions.

Returns a Vector{Float64} of importance scores (accuracy drop), one per feature.

source

Hyperparameter tuning

Sweeping RF hyperparameters and inter-pass thresholds.

Ronin.run_hypertuningFunction
run_hypertuning(config, pass, training_path, testing_path; ...)

Sweep RF hyperparameters (ntrees, maxdepth) for a single pass, evaluating on the testing set with AUC-ROC as the primary metric. Features are computed once, then the sweep trains and evaluates in-memory for each combination.

The caller should set up config.conv_variables, config.selected_features, and masked conv fields for the target pass before calling (e.g., via configure_pass!).

Returns (results=Vector{NamedTuple}, best=NamedTuple, best_model_path=String).

source
Ronin.sweep_pass2_met_probsFunction
sweep_pass2_met_probs(config::ModelConfig, testing_path::String;
                      met_prob_low_grid, met_prob_high_grid,
                      use_met_prob_as_feature::Bool=true,
                      sweep_inference::Bool=true,
                      infer_low_grid, infer_high_grid,
                      nmd_target::Float32=0.99f0,
                      secondary_metric::Symbol=:hss)

Sweep met_prob thresholds for Pass 2 of a multi-pass cascade.

Pass 1 must already be trained (its model and met_prob_pass_1 fields must exist in the CfRadial files). For each threshold combination:

  1. Regenerates the Pass 1→2 mask from saved met_prob_pass_1 fields
  2. Recalculates features on the filtered subset (spatial features change)
  3. Retrains Pass 2 on the "hard" data
  4. Evaluates the full cascade on the testing set

If sweep_inference=true, also sweeps inference thresholds for the best training configuration (cheap — no retraining needed).

Returns a DataFrame of results (requires DataFrames to be loaded).

source

Prediction & QC

Applying a trained cascade to radar data. See Choosing a QC Entry Point for which to use.

Ronin.composite_predictionFunction
composite_prediction(config::ModelConfig; write_features_out::Bool=false, feature_outfile::String="placeholder.h5", return_probs::Bool=false)

Passes feature data through a model or series of models and returns model classifications. Applies configuration such as masking and basic QC (high PGG/low NCP) specified by config

Optional keyword arguments

write_predictions_out::Bool = false

If true, will write the predictions to disk

prediction_outfile::String = "model_predictions.h5"

Location to write predictions to on disk

return_probs::Bool = false

If set to true, will return probability of meteorological gate for all gates. More detail below.


QC_mode::Bool = false

If set to true, the function will instead be used to apply quality control to a (set of) scan(s)

Returns

  • predictions::Vector{Bool} Model classifications for gates that passed basic quality control thresholds

  • values::BitVector Verification gates correspondant to predictions

  • init_idxers::Vector{Vector{Float32}} Information about where original radar data did/did not meet basic quality control thresholds. Each vector contains a flattened vector describing whether or not a given gate was predicted on.

  • total_met_probs::Vector{Float32}If kewyword argument returnprobs is set to true, then `totalmet_probs` will be returned. Each entry into this vector corresponds to the gate represented by predictions and values, and denotes the fraction of trees in the random forest that classified the gate as meteorological.

    All values returned will be only those that passed quality control checks in the first pass of the model minimum NCP / PGG thresholds. In order to reconstruct a scan, user would need to use the values in the returned indexers.

source
Ronin.composite_QCFunction
composite_QC(config::ModelConfig, files::Vector{String},
             models::Vector{Ronin.DecisionTree.RandomForestClassifier},
             metadata::Vector{<:NamedTuple})
composite_QC(config::ModelConfig, files::Vector{String},
             models::Vector{Ronin.DecisionTree.RandomForestClassifier})
composite_QC(config::ModelConfig, files::Vector{String})

Streaming flavor of composite_prediction used to QC sweeps in a realtime setup. Operates on an explicit list of CfRadial files (not config.input_path), runs each pass of the cascade in turn, and writes *<QC_SUFFIX> fields back into each file via QC_scan.

Supports both task_mode = "" (hand-tuned task_paths) and task_mode = "convolution". In convolution mode, per-model metadata (selected_features, conv_variables, masked_conv_*) is read from each model_output_paths JLD2 file; the supplied models vector is used only for predict_proba.

The 4-arg form accepts pre-loaded metadata — a vector of NamedTuples as returned by load_model_with_metadata — and is intended for chunked pipelines (e.g. Sparrow.jl) that cache model and metadata per-worker so the JLD2 reads are paid once rather than per call. The 3-arg form loads the metadata internally and forwards; the 2-arg form loads both models and metadata internally — convenient for operational pipelines where the snippet is just composite_QC(load_config(path), files).

Throws ArgumentError if models or metadata length does not match length(config.model_output_paths).

source
composite_QC(config::ModelConfig, files::Vector{String},
             models::Vector{Ronin.DecisionTree.RandomForestClassifier})

Convenience 3-arg method that loads per-model metadata from config.model_output_paths internally and forwards to the 4-arg form. Preserves the v1.1 calling shape; equivalent to:

metadata = [load_model_with_metadata(p, config.task_mode) for p in config.model_output_paths]
composite_QC(config, files, models, metadata)
source
composite_QC(config::ModelConfig, files::Vector{String})

Convenience 2-arg method that loads both the random forests and their metadata from config.model_output_paths internally and forwards to the 4-arg form. Each JLD2 file is read once (not twice as the previous load_model + load_model_with_metadata sequence did).

source
Ronin.QC_scanFunction

QC_scan(input_cfrad::String, features::Matrix{Float32}, indexer::Vector{Bool}, config::ModelConfig, iter::Int64)

source
QC_scan(config::ModelConfig)

Applies trained composite model to data within scan or set of scans. Will set gates the model deems to be non-meteorological to MISSING, including gates that do not meet initial basic quality control thresholds. Wrapper around composite_prediction.

Returns: None

source
Ronin.write_fieldFunction
write_field(filepath::String, fieldname::String, NEW_FIELD, overwrite::Bool = true, attribs::Dict = Dict(), dim_names::Tuple = ("range", "time"), verbose::Bool=true)
Helper function to write/overwrite a 2D field to a netCDF file
## Required arguments
* `filepath::String` Name of netCDF file to write data to
* `fieldname::String` What to call the data in the netCDF
* `NEW_FIELD` Data dimensioned by `dim_names` to write to netCDF
source

Evaluation & inspection

Scoring models and inspecting saved model files.

Ronin.evaluate_modelFunction
`evaluate_model(predictions::Vector{Bool}, targets::Vector{Bool})`

Given a vector of predictions and targets, calculates various scores and returns them in the order of

* `prec_score::Float32` -> Precision Score, defined as number of true positives divided by sum of true positives and false positives
* `recall::Float32` Recall, defined as number of true positives divided by sum of true positives and false negatives
* `f1::Float32` F1 score
* `true_positives::Int` Number of true positives
* `false_positives::Int` Number of false positives
* `true_negatives::Int` Number of true negatives
* `false_negatives::Int` Number of false negatives
* `num_gates::INt` Total number of classifications
source
`evaluate_model(config::ModelConfig)`

Returns a row of a DataFrame with a variety of metrics about a given model.

#Arguments

```julia
config::ModelConfig
```
Struct containing information about model training

```julia
models_trained::Bool = false
```
source
Ronin.run_evaluationFunction
run_evaluation(config::ModelConfig, dataset_name::String, dataset_path::String,
               met_probs::Vector{Tuple{Float32, Float32}};
               prediction_outfile::String="", verbose::Bool=true)

Run composite_prediction on a dataset and compute classification metrics.

Temporarily sets config.input_path and config.met_probs for the evaluation, then restores them. Returns a NamedTuple with all metrics.

source
Ronin.get_contingencyFunction
get_contingency(predictions::Vector{Bool}, verificaiton::Vector{Bool}; normalize::Bool = true)

Utility to return a DataFrame with the contingency matrix for a binary classificaiton model.
## Required Arguments
* `predictions::Vector{Bool}` Model predicted classes
* `verification::Vector{Bool}` Ground Truth Classes
## Optional Arguments
* `normalize::Bool = true` Whether or not to return the normalized form of the contingency matrix
## Return
* `DataFrame` containing contingency matrix
source
Ronin.compute_auc_rocFunction
compute_auc_roc(probabilities::Vector{Float32}, labels::Vector{<:Integer})

Compute Area Under the ROC Curve from predicted probabilities and binary labels. Uses the trapezoidal rule on (FPR, TPR) points at each distinct threshold.

Labels should be 1 (positive/meteorological) or 0 (negative/non-meteorological). Returns AUC as Float64 in [0, 1], or NaN for empty input, 0.5 for single-class input.

source
Ronin.met_prob_histogramFunction
met_prob_histogram(config::ModelConfig, pass::Int; data_path::String="",
                   met_probs_threshold::Union{Nothing, Tuple{Float32,Float32}}=nothing)

Read saved met_prob_pass_<pass> from CfRadial files and print a histogram of the probability distribution. Uses fine bins near 0 and 1 (where threshold choices are most sensitive) and coarser bins in the middle.

If met_probs_threshold is provided, marks the threshold positions and prints a summary of how many gates fall into each category. Otherwise shows the raw distribution to help choose thresholds.

Prints cumulative percentages from each tail to help identify where thresholds capture the most confident classifications.

source
Ronin.characterize_misclassified_gatesFunction

characterize_misclassified_gates(config::ModelConfig; model_pretrained::Bool = true, features_precalculated::Bool = true)

Function used to apply composite model to a set of gates, returning information about gate classifications and their associated input features

Required inputs

    config::ModelConfig

Model configuration object containing setup information.

Optional Inputs

model_pretrained::Bool = true

Model training in this function not currently implemented, setting to false with untrained models will result in errors.

features_precalculated::Bool = true

Whether or not the input features for the model have already been written to disk.

Not currently implemented.

Returns

Vector of dataframes (one DataFrame for each model "pass"). DataFrames will only contain information about gates reciving their final classification during that pass of the model. That is, if a gate exceeds the met_probs thresholds and is not passed on to the next pass, it will be represented in the DataFrame corresponding to that present pass of the model.

source
Ronin.inspect_model_configurationFunction
inspect_model_configuration(path::String; io::IO=stdout)

Pretty-print the contents of a JLD2 model file without exposing raw model weights. Shows feature names, importances, selected features, and any other saved metadata. Pass io keyword to redirect output (e.g., to an IOBuffer for testing).

source
Ronin.load_modelFunction
load_model(path::String, task_mode::String)

Load a trained model from a JLD2 file, handling both storage formats:

  • save_object format (single key "single_stored_object")
  • JLD2.jldsave format (keyed: "model", "selected_features", etc.)

Returns the model object regardless of which format was used. The task_mode argument is accepted for API compatibility but ignored; layout is inferred from the file's keys.

The return is intentionally untyped: a model file may hold either a DecisionTree.RandomForestClassifier (saved by train_model) or a raw DecisionTree.Ensemble (e.g. built directly via build_forest), so this is polymorphic over the saved representation. A comprehension over model_output_paths therefore infers Vector{Any}; callers that need a concrete Vector{RandomForestClassifier} (to match the composite_QC / composite_prediction signatures) should annotate the comprehension's element type, e.g. RandomForestClassifier[load_model(p, mode) for p in paths].

source
Ronin.load_model_with_metadataFunction
load_model_with_metadata(path::String, task_mode::String)

Load a trained model and its metadata from a JLD2 file. Accepts either storage layout (single-key save_object or multi-key JLD2.jldsave). task_mode is kept for API compatibility but is ignored; layout is inferred from the file's keys.

Returns a NamedTuple with fields:

  • model: the trained RF ensemble
  • selected_features: Vector{Int} of feature indices the model was trained on (empty = all features)
  • recommended_features: Vector{Int} of features recommended by importance analysis (empty if not computed)
  • feature_names: Vector{String} of feature names (empty if not saved)
  • importances: Vector{Float64} of feature importance scores (empty if not saved)
source

Utilities

Ronin.compute_balanced_class_weightsFunction
Helper function to compute balanced weights according to the
algoirthm described in https://scikit-learn.org/stable/modules/generated/sklearn.utils.class_weight.compute_class_weight.html
source