Add a custom transformation strategy to the registry for use with optimize_panel() and evaluate_panel().

register_feature_transform(name, fun, description = name, overwrite = FALSE)

Arguments

name

Unique identifier for the transform.

fun

Function implementing the transform. Must accept a matrix x with column names and return a transformed matrix.

description

Human-readable description of the transform.

overwrite

Logical; set to TRUE to replace an existing registration.

Value

Invisibly, the registered name.

Examples

# Register a custom centering transform
register_feature_transform(
  "center",
  function(x) scale(x, center = TRUE, scale = FALSE),
  "Center each feature (subtract column means)"
)

# List all registered transforms
feature_transform_registry()
#> $center
#> $center$fun
#> function (x) 
#> scale(x, center = TRUE, scale = FALSE)
#> <environment: 0x55ab90209a40>
#> 
#> $center$description
#> [1] "Center each feature (subtract column means)"
#> 
#> 
#> $none
#> $none$fun
#> function (x) 
#> {
#>     x
#> }
#> <bytecode: 0x55ab8a239ba0>
#> <environment: namespace:MOBID>
#> 
#> $none$description
#> [1] "No transformation (identity)"
#> 
#> 
#> $pairwise_log_ratios
#> $pairwise_log_ratios$fun
#> function (x) 
#> {
#>     if (ncol(x) < 2L) {
#>         stop("Transform 'pairwise_log_ratios' requires at least two features. ", 
#>             "Input matrix has ", ncol(x), " column(s). ", "Use feature_transform = 'none' if pairwise log-ratios are not needed.", 
#>             call. = FALSE)
#>     }
#>     if (is.null(colnames(x))) {
#>         stop("x must have column names", call. = FALSE)
#>     }
#>     if (any(x <= 0, na.rm = TRUE)) {
#>         n_nonpositive <- sum(x <= 0, na.rm = TRUE)
#>         stop("Input matrix contains ", n_nonpositive, " non-positive value(s). ", 
#>             "Log-ratios require strictly positive values. ", 
#>             "Either add a pseudocount (x + 1), use 'pairwise_ratios' for log-transformed data, ", 
#>             "or remove/impute non-positive values.", call. = FALSE)
#>     }
#>     pairwise_col_diff(log(x))
#> }
#> <bytecode: 0x55ab8a239a18>
#> <environment: namespace:MOBID>
#> 
#> $pairwise_log_ratios$description
#> [1] "Pairwise log-ratios log(A / B) for all feature pairs"
#> 
#> 
#> $pairwise_ratios
#> $pairwise_ratios$fun
#> function (x) 
#> {
#>     if (ncol(x) < 2L) {
#>         stop("Transform 'pairwise_ratios' requires at least two features. ", 
#>             "Input matrix has ", ncol(x), " column(s). ", "Use feature_transform = 'none' if pairwise ratios are not needed.", 
#>             call. = FALSE)
#>     }
#>     pairwise_col_diff(x)
#> }
#> <bytecode: 0x55ab8a23e3f0>
#> <environment: namespace:MOBID>
#> 
#> $pairwise_ratios$description
#> [1] "Pairwise differences (A - B) for all feature pairs"
#> 
#> 
#> $reference_norm
#> $reference_norm$fun
#> function (x) 
#> {
#>     ref_feature <- attr(x, "reference_feature")
#>     if (is.null(ref_feature)) {
#>         stop("Transform 'reference_norm' requires 'reference_feature' attribute. ", 
#>             "Set via: attr(x, 'reference_feature') <- 'FeatureName'", 
#>             call. = FALSE)
#>     }
#>     if (!ref_feature %in% colnames(x)) {
#>         stop("Reference feature '", ref_feature, "' not found in data. ", 
#>             "Available: ", paste(colnames(x), collapse = ", "), 
#>             call. = FALSE)
#>     }
#>     col_names <- colnames(x)
#>     other_cols <- setdiff(col_names, ref_feature)
#>     if (length(other_cols) == 0L) {
#>         warning("Transform 'reference_norm' requires at least one non-reference feature; ", 
#>             "returning original matrix.", call. = FALSE)
#>         return(x)
#>     }
#>     ref_col <- x[, ref_feature]
#>     other_matrix <- x[, other_cols, drop = FALSE]
#>     .reference_diff_cpp(other_matrix, ref_col, ref_feature, other_cols)
#> }
#> <bytecode: 0x55ab8a23dbd8>
#> <environment: namespace:MOBID>
#> 
#> $reference_norm$description
#> [1] "Reference normalization (A - ref) for each feature relative to reference"
#> 
#>