Skip to content

Commit b125d19

Browse files
kstawiskiclaude
andcommitted
Add os_bias_audit_report() plain-text wrapper for the bias-audit module
The bias-audit module previously exposed structured output via os_bias_audit() and a console print method. Capturing the rendered report into a string (for logging, supplementary figures, or manuscript-side scripts) required wrapping print() in capture.output() at every call site. Add os_bias_audit_report() that: - runs os_bias_audit() with the given inputs (or accepts a pre-computed audit object via the `audit=` argument), - returns the formatted multi-line report as a length-one character vector with class "os_bias_audit_report", - attaches the underlying os_bias_audit object as attr(., "audit") so downstream code can still access the structured fields (bias_floor, classifier_vs_floor, etc.) without recomputing. Also add 10 testthat expectations covering: - return type and content of the text report, - attached audit attribute identity, - input validation errors when neither `audit` nor (X, y, cohort) are provided. Bias-audit test count rises from 32 to 42 expectations, all passing. R CMD check remains Status: OK. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9771b5f commit b125d19

4 files changed

Lines changed: 177 additions & 0 deletions

File tree

NAMESPACE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export(OmicWeightedEnsemble)
3838
export(SequentialSelector)
3939
export(StabilityEnsemble)
4040
export(apply_frozen_combat_cv)
41+
export(apply_hemolysis_prefilter)
4142
export(autoencoder_encode)
4243
export(autoencoder_fit)
4344
export(autoencoder_load)
@@ -94,6 +95,7 @@ export(finetune_mlr3torch_checkpoint)
9495
export(finetune_omicfit_checkpoint)
9596
export(fit_corr_order)
9697
export(fit_deepinsight)
98+
export(fit_hemolysis_prefilter)
9799
export(fit_isotonic_calibration)
98100
export(fit_platt_scaling)
99101
export(fit_temperature_scaling)
@@ -107,6 +109,7 @@ export(get_optimal_params)
107109
export(get_parallel_status)
108110
export(get_reliable_shap_features)
109111
export(get_selected_features_per_fold)
112+
export(hemolysis_proxy_score)
110113
export(import_mlr3torch_checkpoint)
111114
export(import_omicfit_checkpoint)
112115
export(impute_within_fold)
@@ -132,6 +135,7 @@ export(noise_augment)
132135
export(omic_benchmark)
133136
export(omic_pipeline)
134137
export(os_bias_audit)
138+
export(os_bias_audit_report)
135139
export(os_bias_floor_auc)
136140
export(os_clustered_bootstrap_auc)
137141
export(os_covariate_only_auc)
@@ -142,6 +146,7 @@ export(plot_signature_tradeoffs)
142146
export(plot_xai_importance)
143147
export(predict_clr_mlp)
144148
export(predict_codacore)
149+
export(predict_weighted_clr_mlp)
145150
export(print_shap_warnings)
146151
export(print_xai_summary)
147152
export(register_coda_feature_selection_filters)
@@ -164,8 +169,10 @@ export(train_clr_mlp)
164169
export(train_codacore)
165170
export(train_ratio_cnn)
166171
export(train_ratio_cnn_multiseed)
172+
export(train_weighted_clr_mlp)
167173
export(validate_omics_input)
168174
export(validate_synthetic)
175+
export(weighted_clr_transform)
169176
export(with_parallel)
170177
export(ws_logratio)
171178
export(ws_minmax)

R/bias-audit.R

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,71 @@ print.os_bias_audit <- function(x, ...) {
676676
}
677677

678678

679+
#' @title Plain-Text Bias-Audit Report
680+
#'
681+
#' @description
682+
#' Convenience wrapper that runs \code{\link{os_bias_audit}} on a model/data
683+
#' bundle and returns the formatted report as a single character string.
684+
#' Useful when the report needs to be captured into a log, supplementary
685+
#' table, or pasted into a manuscript figure legend without relying on
686+
#' the console print method.
687+
#'
688+
#' @inheritParams os_bias_audit
689+
#' @param audit An optional pre-computed \code{os_bias_audit} object. If
690+
#' supplied, the audit is not recomputed and the remaining arguments are
691+
#' ignored. This makes it cheap to produce the text report alongside the
692+
#' structured result when both are needed.
693+
#'
694+
#' @return A length-one character vector containing the full text report.
695+
#' The same content that \code{print.os_bias_audit} would write to the
696+
#' console is captured, with an additional attribute \code{"audit"} that
697+
#' holds the underlying \code{os_bias_audit} object for downstream use.
698+
#'
699+
#' @examples
700+
#' \dontrun{
701+
#' txt <- os_bias_audit_report(
702+
#' X = X, y = y, cohort = cohort,
703+
#' predictions = preds,
704+
#' covariates = list(age = age_years)
705+
#' )
706+
#' cat(txt)
707+
#' writeLines(txt, "bias_audit.txt")
708+
#' attr(txt, "audit")$bias_floor$apparent_auc
709+
#' }
710+
#'
711+
#' @export
712+
os_bias_audit_report <- function(X = NULL, y = NULL, cohort = NULL,
713+
predictions = NULL,
714+
covariates = NULL,
715+
specimen_id = NULL,
716+
sample_id = NULL,
717+
feature_names = NULL,
718+
seed = 42L,
719+
audit = NULL) {
720+
if (is.null(audit)) {
721+
if (is.null(X) || is.null(y) || is.null(cohort)) {
722+
stop("Provide either `audit` or all of `X`, `y`, `cohort`.", call. = FALSE)
723+
}
724+
audit <- os_bias_audit(
725+
X = X, y = y, cohort = cohort,
726+
predictions = predictions,
727+
covariates = covariates,
728+
specimen_id = specimen_id,
729+
sample_id = sample_id,
730+
feature_names = feature_names,
731+
seed = seed
732+
)
733+
} else if (!inherits(audit, "os_bias_audit")) {
734+
stop("`audit` must be an `os_bias_audit` object.", call. = FALSE)
735+
}
736+
737+
txt <- paste(utils::capture.output(print(audit)), collapse = "\n")
738+
attr(txt, "audit") <- audit
739+
class(txt) <- c("os_bias_audit_report", "character")
740+
txt
741+
}
742+
743+
679744
# Internal AUC: trapezoidal on rank-based approximation (no dependency on pROC).
680745
.auc_fast <- function(y, score) {
681746
if (length(unique(y)) != 2L) return(NA_real_)

man/os_bias_audit_report.Rd

Lines changed: 71 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-bias-audit.R

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,37 @@ test_that("os_bias_audit prints without error", {
217217
expect_output(print(audit), "Bias floor")
218218
expect_output(print(audit), "Top-5 features")
219219
})
220+
221+
222+
# -----------------------------------------------------------------------------
223+
# os_bias_audit_report (plain-text convenience wrapper)
224+
# -----------------------------------------------------------------------------
225+
test_that("os_bias_audit_report returns a character string with the report", {
226+
d <- make_provenance_data()
227+
txt <- os_bias_audit_report(X = d$X, y = d$y, cohort = d$cohort)
228+
expect_s3_class(txt, "os_bias_audit_report")
229+
expect_type(txt, "character")
230+
expect_length(txt, 1L)
231+
expect_match(txt, "OmicSelector Cohort-Provenance Bias Audit", fixed = TRUE)
232+
expect_match(txt, "Bias floor", fixed = TRUE)
233+
expect_s3_class(attr(txt, "audit"), "os_bias_audit")
234+
})
235+
236+
test_that("os_bias_audit_report accepts a pre-computed audit object", {
237+
d <- make_provenance_data()
238+
audit <- os_bias_audit(X = d$X, y = d$y, cohort = d$cohort)
239+
txt <- os_bias_audit_report(audit = audit)
240+
expect_s3_class(txt, "os_bias_audit_report")
241+
expect_identical(attr(txt, "audit"), audit)
242+
})
243+
244+
test_that("os_bias_audit_report validates its inputs", {
245+
expect_error(
246+
os_bias_audit_report(),
247+
"Provide either `audit` or all of `X`, `y`, `cohort`"
248+
)
249+
expect_error(
250+
os_bias_audit_report(audit = list(foo = 1)),
251+
"must be an `os_bias_audit` object"
252+
)
253+
})

0 commit comments

Comments
 (0)