From 1fb62d41dff786492b3299106ed9f378d679fcfa Mon Sep 17 00:00:00 2001 From: Neil Horner Date: Thu, 14 May 2026 14:53:08 +0000 Subject: [PATCH] Rename log2Fold_contrast column [CW-7233] --- bin/workflow_glue_r/R/de_analysis.R | 49 ++++++++++++++----- .../tests/testthat/test_de_analysis.R | 28 +++++++++++ 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/bin/workflow_glue_r/R/de_analysis.R b/bin/workflow_glue_r/R/de_analysis.R index e5ce5d7..b096cdf 100644 --- a/bin/workflow_glue_r/R/de_analysis.R +++ b/bin/workflow_glue_r/R/de_analysis.R @@ -514,6 +514,37 @@ de_run_dexseq_result <- function( result } +de_dtu_transcript_columns <- c( + "featureID", + "groupID", + "log2FoldChange", + "pvalue", + "padj", + "exonBaseMean" +) + +#' Extract transcript-level DTU columns for TSV output. +#' +#' Renames the contrast-specific DEXSeq fold-change column to +#' `log2FoldChange`, normalizes data for TSV output +#' and returns only the transcript output columns. +#' +#' @param dex_df DEXSeq results as a data frame. +#' @param contrast_name Contrast suffix used in the DEXSeq fold-change column. +#' +#' @return A normalized data frame ready for `results_dtu_transcript.tsv`. +de_extract_dtu_transcript_table <- function(dex_df, contrast_name) { + log2fold_column <- paste0("log2fold_", contrast_name) + if (log2fold_column %in% names(dex_df)) { + names(dex_df)[names(dex_df) == log2fold_column] <- "log2FoldChange" + } + tx_dtu <- dex_df[, intersect( + de_dtu_transcript_columns, + names(dex_df) + ), drop = FALSE] + workflow_glue_r_normalise_tsv_df(tx_dtu) +} + main_run_de_analysis <- function(argv) { set.seed(42) dir.create(argv$out_dir, showWarnings = FALSE, recursive = TRUE) @@ -764,14 +795,7 @@ main_run_de_analysis <- function(argv) { ) if (is.null(dex_res)) { - dex_df <- workflow_glue_r_empty_tsv(c( - "featureID", - "groupID", - "log2fold", - "pvalue", - "padj", - "exonBaseMean" - )) + dex_df <- workflow_glue_r_empty_tsv(de_dtu_transcript_columns) tx_dtu <- dex_df gene_dtu <- workflow_glue_r_empty_tsv(c("GENEID", "qval")) de_write_placeholder_pdf( @@ -793,11 +817,10 @@ main_run_de_analysis <- function(argv) { } dex_df <- as.data.frame(dex_res$dxr) dex_df <- workflow_glue_r_normalise_tsv_df(dex_df) - tx_dtu <- dex_df[, intersect( - c("featureID", "groupID", "log2fold", "pvalue", "padj", "exonBaseMean"), - names(dex_df) - ), drop = FALSE] - tx_dtu <- workflow_glue_r_normalise_tsv_df(tx_dtu) + tx_dtu <- de_extract_dtu_transcript_table( + dex_df, + paste(target_level, reference_level, sep = "_") + ) gene_q <- DEXSeq::perGeneQValue(dex_res$dxr) gene_dtu <- data.frame( diff --git a/bin/workflow_glue_r/tests/testthat/test_de_analysis.R b/bin/workflow_glue_r/tests/testthat/test_de_analysis.R index d58dddd..263e487 100644 --- a/bin/workflow_glue_r/tests/testthat/test_de_analysis.R +++ b/bin/workflow_glue_r/tests/testthat/test_de_analysis.R @@ -92,6 +92,34 @@ testthat::test_that("formula-unsafe column names rejected", { ) }) +testthat::test_that("DTU transcript output renames contrast-specific log2fold column", { + contrast_name <- "treated_control" + dex_df <- data.frame( + featureID = "tx1", + groupID = "gene1", + log2fold_treated_control = 1.5, + pvalue = 0.01, + padj = 0.05, + exonBaseMean = 100, + stringsAsFactors = FALSE, + check.names = FALSE + ) + + dtu_tx <- de_extract_dtu_transcript_table(dex_df, contrast_name) + + testthat::expect_equal( + names(dtu_tx), + c( + "featureID", + "groupID", + "log2FoldChange", + "pvalue", + "padj", + "exonBaseMean" + ) + ) +}) + # Sample aliases CAN have spaces/hyphens (they're not used in formulas, just for matching). # Sample sheet rows can be in different order than SE columns - should reorder automatically. testthat::test_that("non-syntactic aliases allowed, sheets reordered", {