diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a8d3fc..ae36549 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### `Fixed` +- Addressed issues with latest GSVA function calls after GSVA >1.5.0 was introduced to be able to use gene score methods accordingly again +- Updated the analysis dependencies in the local module for gene score computation to latest versions of the R Scripts +- Removed container dependency on biocontainers and rather using Wave containers again + +### `Fixed` + - [#151](https://github.com/nf-core/nanostring/pull/151) - Updated modules and subworkflows, and follow nextflow's strict syntax. ### `Changed` diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 85d6b78..75e053a 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,5 +1,5 @@ report_comment: > - This report has been generated by the nf-core/nanostring analysis pipeline. For information about how to interpret these results, please see the documentation. + This report has been generated by the nf-core/nanostring analysis pipeline. For information about how to interpret these results, please see the documentation. report_section_order: BD: order: 970 diff --git a/modules.json b/modules.json index b58c978..91ff1d5 100644 --- a/modules.json +++ b/modules.json @@ -36,7 +36,7 @@ }, "utils_nfschema_plugin": { "branch": "master", - "git_sha": "ff506dcada6fc826ed0c641dc2ed1e98f7345fbe", + "git_sha": "fdc08b8b1ae74f56686ce21f7ea11ad11990ce57", "installed_by": ["subworkflows"] } } diff --git a/modules/local/compute_gene_scores/environment.yml b/modules/local/compute_gene_scores/environment.yml index 0c769bd..db04523 100644 --- a/modules/local/compute_gene_scores/environment.yml +++ b/modules/local/compute_gene_scores/environment.yml @@ -2,12 +2,12 @@ channels: - conda-forge - bioconda dependencies: - - conda-forge::r-yaml=2.3.7 - - conda-forge::r-ggplot2=3.4.4 + - conda-forge::r-yaml=2.3.12 + - conda-forge::r-ggplot2=4.0.1 - conda-forge::r-dplyr=1.1.4 - - conda-forge::r-stringr=1.5.0 - - bioconda::bioconductor-gsva=1.46.0 - - bioconda::bioconductor-singscore=1.18.0 - - conda-forge::r-factominer=2.8.0 - - conda-forge::r-tibble=3.2.1 - - conda-forge::r-matrixstats=1.1.0 + - conda-forge::r-stringr=1.6.0 + - bioconda::bioconductor-gsva=2.0.0 + - bioconda::bioconductor-singscore=1.26.0 + - conda-forge::r-factominer=2.13.0 + - conda-forge::r-tibble=3.3.1 + - conda-forge::r-matrixstats=1.5.0 diff --git a/modules/local/compute_gene_scores/main.nf b/modules/local/compute_gene_scores/main.nf index 805d5e8..42a2fef 100644 --- a/modules/local/compute_gene_scores/main.nf +++ b/modules/local/compute_gene_scores/main.nf @@ -2,9 +2,7 @@ process COMPUTE_GENE_SCORES { label 'process_single' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/mulled-v2-e6920e60d80922852a1b19630ebe16754cf5320d:75e2c0a29159bae8a964e43ae16a45c282fdf651-0' : - 'biocontainers/mulled-v2-e6920e60d80922852a1b19630ebe16754cf5320d:75e2c0a29159bae8a964e43ae16a45c282fdf651-0' }" + container "community.wave.seqera.io/library/bioconductor-gsva_bioconductor-singscore_r-dplyr_r-factominer_pruned:e6f1a5cd9110d36b" input: tuple val(meta), path(normalized_counts) diff --git a/modules/local/compute_gene_scores/resources/usr/bin/compute_gene_scores.R b/modules/local/compute_gene_scores/resources/usr/bin/compute_gene_scores.R index b9d7bea..0807703 100755 --- a/modules/local/compute_gene_scores/resources/usr/bin/compute_gene_scores.R +++ b/modules/local/compute_gene_scores/resources/usr/bin/compute_gene_scores.R @@ -7,29 +7,41 @@ library(stringr) library(dplyr) library(yaml) library(FactoMineR) -library(stringr) library(tibble) +library(data.table) +library(ggplot2) ###Gene Set Functions # helper functions -loadMappingTable <- function(ref.file="./ensembl_86_mpens.txt") { - s2e <- read.delim(file=ref.file, - stringsAsFactors = F, header=F, skip=1) +loadMappingTable <- function(ref.file = "./ensembl_86_mpens.txt") { + s2e <- read.delim( + file = ref.file, + stringsAsFactors = F, + header = F, + skip = 1 + ) colnames(s2e) <- c("ensembl", "genesymbol") return(s2e) } -geneSymbol2Ensembl <- function(x, s2e=NULL) { - if(is.null(s2e)) s2e <- loadMappingTable() +geneSymbol2Ensembl <- function(x, s2e = NULL) { + if (is.null(s2e)) { + s2e <- loadMappingTable() + } # also check for correct colnames (TODO) - ens <- unique(s2e[s2e$genesymbol %in% x,"ensembl"]) + ens <- unique(s2e[s2e$genesymbol %in% x, "ensembl"]) # print(ens) - if(length(ens)0,1] - retSet$downSet <- set[set[,2]<0,1] - retSet$knownDir <- TRUE - } + retSet$knownDir <- FALSE + } else if (is.data.frame(set)) { + if (!is.numeric(set[, 2])) { + stop("Second column of gene set data frame must be numeric.") + } else if (all(set[, 2] == 0)) { + retSet$upSet <- set[, 1] + retSet$downSet <- NULL + retSet$knownDir <- FALSE + } else { + retSet$upSet <- set[set[, 2] > 0, 1] + retSet$downSet <- set[set[, 2] < 0, 1] + retSet$knownDir <- TRUE + } } else { stop("Gene Set must be a character vector or a data.frame") } - if(length(retSet$upSet)==0) retSet$upSet<-NULL - if(length(retSet$downSet)==0) retSet$downSet<-NULL + if (length(retSet$upSet) == 0) { + retSet$upSet <- NULL + } + if (length(retSet$downSet) == 0) { + retSet$downSet <- NULL + } return(retSet) } @@ -110,115 +128,148 @@ geneSetAsList <- function(set) { ## Create an actual Geneset object from GSEABase package ## not used at the moment createGeneset <- function(set, name.set) { - gs <- GeneSet(unique(set), setName=name.set) + gs <- GeneSet(unique(set), setName = name.set) return(gs) } ## Singscore <- function(d, x, ...) { - if(is.list(x) && is.null(x$downSet)) s <- simpleScore(d, upSet = x$upSet, knownDirection=x$knownDir, ...) - if(is.list(x) && !is.null(x$downSet)) s <- simpleScore(d, upSet = x$upSet, downSet=x$downSet, knownDirection = x$knownDir, ...) + if (is.list(x) && is.null(x$downSet)) { + s <- simpleScore(d, upSet = x$upSet, knownDirection = x$knownDir, ...) + } else if (is.list(x) && !is.null(x$downSet)) { + s <- simpleScore( + d, + upSet = x$upSet, + downSet = x$downSet, + knownDirection = x$knownDir, + ... + ) + } return(s) } ## Calculate singscores (use log TPMs or RPKMs) -calculateSingscores <- function(xp, genes, raw=FALSE, ...) { - +calculateSingscores <- function(xp, genes, raw = FALSE, ...) { geneSets <- lapply(genes, geneSetAsList) ranked.exp <- rankGenes(xp) sscore <- lapply(geneSets, function(x) Singscore(ranked.exp, x, ...)) - flattenSingScores <- function(x,n) { - if("TotalScore" %in% colnames(x)) { - one.row <- x[,"TotalScore",drop=F] - return (one.row) - } + flattenSingScores <- function(x, n) { + if ("TotalScore" %in% colnames(x)) { + one.row <- x[, "TotalScore", drop = F] + return(one.row) + } } - sscore.df <- lapply(names(sscore), function(x) flattenSingScores(sscore[[x]],x)) + sscore.df <- lapply(names(sscore), function(x) { + flattenSingScores(sscore[[x]], x) + }) names(sscore.df) <- names(sscore) sscore.f <- bind_cols(sscore.df) colnames(sscore.f) <- names(sscore.df) rownames(sscore.f) <- rownames(sscore.df[[1]]) sscore.f <- t(sscore.f) - if(raw) return(sscore) - else return(sscore.f) + if (raw) { + return(sscore) + } else { + return(sscore.f) + } } ## Calculate GSVA (check kcdf paramater dependent on data) calculateGSVAscores <- function(xp, genes, ...) { - genes.flat <- lapply(genes, geneSetAsVector) - if(is.data.frame(xp)) xp.matrix <- as.matrix.data.frame(xp) - if(is.matrix(xp)) xp.matrix <- xp + if (is.data.frame(xp)) { + xp.matrix <- as.matrix.data.frame(xp) + } + if (is.matrix(xp)) { + xp.matrix <- xp + } - scores <- gsva(xp.matrix, genes.flat, method="gsva", ...) + scores <- gsva(gsvaParam(xp.matrix, genes.flat), ...) return(scores) } ## Calculate SSGSEA (use log TPMs or RPKMs) calculateSSGSEAscores <- function(xp, genes, ...) { - genes.flat <- lapply(genes, geneSetAsVector) - if(is.data.frame(xp)) xp.matrix <- as.matrix.data.frame(xp) - if(is.matrix(xp)) xp.matrix <- xp + if (is.data.frame(xp)) { + xp.matrix <- as.matrix.data.frame(xp) + } + if (is.matrix(xp)) { + xp.matrix <- xp + } - scores <- gsva(xp.matrix, genes.flat, method="ssgsea", ...) + scores <- gsva(ssgseaParam(xp.matrix, genes.flat), ...) return(scores) } ## Calculate PLAGE (probably also TPMs or RPKMs) -calculatePLAGEscores <- function(xp, genes, correct.dir=FALSE, ...) { - +calculatePLAGEscores <- function(xp, genes, correct.dir = FALSE, ...) { genes.flat <- lapply(genes, geneSetAsVector) - if(is.data.frame(xp)) xp.matrix <- as.matrix.data.frame(xp) - if(is.matrix(xp)) xp.matrix <- xp + if (is.data.frame(xp)) { + xp.matrix <- as.matrix.data.frame(xp) + } + if (is.matrix(xp)) { + xp.matrix <- xp + } - plagescores <- gsva(xp.matrix, genes.flat, method="plage", ...) + plagescores <- gsva(plageParam(xp.matrix, genes.flat), ...) - if(correct.dir) { + if (correct.dir) { meanscores <- calculateMeanScores(xp.matrix, genes.flat) i <- intersect(rownames(meanscores), rownames(plagescores)) - if(length(i)!=length(rownames(plagescores))) stop("Correction failed") - plagescores <- plagescores*sign(sapply(i, function(x) cor(plagescores[x,],meanscores[x,]))) + if (length(i) != length(rownames(plagescores))) { + stop("Correction failed") + } + plagescores <- plagescores * + sign(sapply(i, function(x) cor(plagescores[x, ], meanscores[x, ]))) } return(plagescores) } calculateMedianScores <- function(xp, genes, ...) { - genes.flat <- lapply(genes, geneSetAsVector) - if(is.data.frame(xp)) xp.matrix <- as.matrix.data.frame(xp) - if(is.matrix(xp)) xp.matrix <- xp + if (is.data.frame(xp)) { + xp.matrix <- as.matrix.data.frame(xp) + } + if (is.matrix(xp)) { + xp.matrix <- xp + } - median.result <- t(sapply(genes.flat, function(x) apply(xp.matrix[x, ],2,median, ...))) + median.result <- t(sapply(genes.flat, function(x) { + apply(xp.matrix[x, ], 2, median, ...) + })) return(median.result) } calculateMeanScores <- function(xp, genes, ...) { - genes.flat <- lapply(genes, geneSetAsVector) - if(is.data.frame(xp)) xp.matrix <- as.matrix.data.frame(xp) - if(is.matrix(xp)) xp.matrix <- xp + if (is.data.frame(xp)) { + xp.matrix <- as.matrix.data.frame(xp) + } + if (is.matrix(xp)) { + xp.matrix <- xp + } - mean.result <- t(sapply(genes.flat, function(x) apply(xp.matrix[x, ],2,mean, ...))) + mean.result <- t(sapply(genes.flat, function(x) { + apply(xp.matrix[x, ], 2, mean, ...) + })) return(mean.result) } - - ## geometrix mean functions from stackoverflow ## https://stackoverflow.com/questions/2602583/geometric-mean-is-there-a-built-in ## Note, normalized read counts can be < 1 => log2 cpm can be < 0 => geometric mean of log2 cpm values can be infinite and is not well defined @@ -227,133 +278,179 @@ calculateMeanScores <- function(xp, genes, ...) { # Geometric mean # Naive implementation assuming all values are > 0. -gm_mean_naive = function(a){prod(a)^(1/length(a))} +gm_mean_naive = function(a) { + prod(a)^(1 / length(a)) +} # Geometric mean # Implementation including only values > 0. -gm_mean_simple = function(x, na.rm=TRUE){ - exp(sum(log(x[x > 0]), na.rm=na.rm) / length(x)) +gm_mean_simple = function(x, na.rm = TRUE) { + exp(sum(log(x[x > 0]), na.rm = na.rm) / length(x)) } # Geometric mean # Implementation, which allows options. -gm_mean_advanced = function(x, na.rm=TRUE, zero.propagate = FALSE){ - if(any(x < 0, na.rm = TRUE)){ +gm_mean_advanced = function(x, na.rm = TRUE, zero.propagate = FALSE) { + if (any(x < 0, na.rm = TRUE)) { return(NaN) } - if(zero.propagate){ - if(any(x == 0, na.rm = TRUE)){ - return(0) - } - exp(mean(log(x), na.rm = na.rm)) + if (zero.propagate) { + if (any(x == 0, na.rm = TRUE)) { + return(0) + } + return(exp(mean(log(x), na.rm = na.rm))) } else { - exp(sum(log(x[x > 0]), na.rm=na.rm) / length(x)) + return(exp(sum(log(x[x > 0]), na.rm = na.rm) / length(x))) } } # wrapper called by calculateSamsscore to adapt up and down regulation information -Samsscore <- function(xp, x, center_rows = TRUE,geom_mean = FALSE, ...) { - if(is.list(x) && !is.null(x$downSet)) s <- sams_score(xp, up_genes = x$upSet, - down_genes = x$downSet, - center_rows = center_rows, - geom_mean = geom_mean, - ...) - if(is.list(x) && is.null(x$downSet)) s <- sams_score(xp, up_genes = x$upSet, - down_genes = character(length = 0L), - center_rows = center_rows, - geom_mean = geom_mean, - ...) -return(s) +Samsscore <- function(xp, x, center_rows = TRUE, geom_mean = FALSE, ...) { + if (is.list(x) && !is.null(x$downSet)) { + s <- sams_score( + xp, + up_genes = x$upSet, + down_genes = x$downSet, + center_rows = center_rows, + geom_mean = geom_mean, + ... + ) + } else if (is.list(x) && is.null(x$downSet)) { + s <- sams_score( + xp, + up_genes = x$upSet, + down_genes = character(length = 0L), + center_rows = center_rows, + geom_mean = geom_mean, + ... + ) + } + return(s) } # sams score wrapper to match implementation of other scores -calculateSamsscores <- function(xp, genes, raw = FALSE, - which_col = "score_sum", - center_rows = TRUE, - geom_mean = FALSE, - ...) { - -geneSets <- lapply(genes, geneSetAsList) +calculateSamsscores <- function( + xp, + genes, + raw = FALSE, + which_col = "score_sum", + center_rows = TRUE, + geom_mean = FALSE, + ... +) { + geneSets <- lapply(genes, geneSetAsList) -samsscore <- lapply(geneSets, function(x) Samsscore(xp, x, - center_rows = center_rows, - geom_mean = geom_mean, - ...)) -if (raw) return(samsscore) + samsscore <- lapply(geneSets, function(x) { + Samsscore(xp, x, center_rows = center_rows, geom_mean = geom_mean, ...) + }) + if (raw) { + return(samsscore) + } -my_flat <- function(x) { - my_tib <- dplyr::tibble(sample = rownames(samsscore[[x]]), - !!x := samsscore[[x]][, which_col]) - my_tib -} + my_flat <- function(x) { + my_tib <- dplyr::tibble( + sample = rownames(samsscore[[x]]), + !!x := samsscore[[x]][, which_col] + ) + my_tib + } -score_flat <- lapply(names(samsscore), my_flat) + score_flat <- lapply(names(samsscore), my_flat) -score_flat_join <- Reduce(function(...) dplyr::full_join(..., by = "sample"), score_flat) + score_flat_join <- Reduce( + function(...) dplyr::full_join(..., by = "sample"), + score_flat + ) -ret_val <- score_flat_join %>% data.table::as.data.table() %>% - data.table::melt(id.vars = "sample", variable.name = "geneset", value.name = "score") %>% - data.table::dcast(geneset~sample, value.var = "score") %>% - as.matrix(rownames = "geneset") -ret_val[, colnames(xp), drop = FALSE] + ret_val <- score_flat_join %>% + data.table::as.data.table() %>% + data.table::melt( + id.vars = "sample", + variable.name = "geneset", + value.name = "score" + ) %>% + data.table::dcast(geneset ~ sample, value.var = "score") %>% + as.matrix(rownames = "geneset") + return(ret_val[, colnames(xp), drop = FALSE]) } # basic implementation of samsscore -sams_score <- function(expr_mat, - up_genes = character(), - down_genes = character(), - center_rows = TRUE, - geom_mean = FALSE, - method = "sams") { # method "sams" or "median", median is just the column median +sams_score <- function( + expr_mat, + up_genes = character(), + down_genes = character(), + center_rows = TRUE, + geom_mean = FALSE, + method = "sams" +) { + # method "sams" or "median", median is just the column median expr_mat <- as.matrix(expr_mat) - assertthat::assert_that(is.numeric(expr_mat), msg = "expression matix is not numeric") - - assertthat::assert_that(all(up_genes %in% rownames(expr_mat)), - msg = "At least one element in up_genes is not in rownames of expression matrix.") - assertthat::assert_that(all(down_genes %in% rownames(expr_mat)), - msg = "At least one element down_genes is not in rownames of expression matrix.") + assertthat::assert_that( + is.numeric(expr_mat), + msg = "expression matix is not numeric" + ) + + assertthat::assert_that( + all(up_genes %in% rownames(expr_mat)), + msg = "At least one element in up_genes is not in rownames of expression matrix." + ) + assertthat::assert_that( + all(down_genes %in% rownames(expr_mat)), + msg = "At least one element down_genes is not in rownames of expression matrix." + ) if (center_rows) { if (geom_mean) { row_means <- apply(expr_mat, 1, gm_mean_simple) } else { row_means <- rowMeans(expr_mat, na.rm = TRUE) } - expr_mat <- sweep(expr_mat, 1, row_means, "-") + expr_mat <- sweep(expr_mat, 1, row_means, "-") } ## select data for signature - up_matrix <- expr_mat[up_genes, ] + up_matrix <- expr_mat[up_genes, ] down_matrix <- expr_mat[down_genes, ] ##set values, which do not follow up and down-reglation expection to 0 - up_cens <- up_matrix - up_cens[up_matrix < 0] <- matrix(0, nrow = nrow(up_matrix), ncol = ncol(up_matrix))[up_matrix < 0] + up_cens <- up_matrix + up_cens[up_matrix < 0] <- matrix( + 0, + nrow = nrow(up_matrix), + ncol = ncol(up_matrix) + )[up_matrix < 0] down_cens <- down_matrix - down_cens[down_matrix > 0] <- matrix(0, nrow = nrow(down_matrix), ncol = ncol(down_matrix))[down_matrix > 0] + down_cens[down_matrix > 0] <- matrix( + 0, + nrow = nrow(down_matrix), + ncol = ncol(down_matrix) + )[down_matrix > 0] ##calculate fraction of up and down-regulated genes #up_fraction <- apply(up_matrix, 2, function(x) sum(x >= 0) / length(x)) - up_fraction <- apply(up_matrix, 2, function(x) sum(x > 0) / length(x)) + up_fraction <- apply(up_matrix, 2, function(x) sum(x > 0) / length(x)) down_fraction <- apply(down_matrix, 2, function(x) sum(x < 0) / length(x)) - up_score <- colSums(up_cens) * up_fraction + up_score <- colSums(up_cens) * up_fraction down_score <- colSums(down_cens) * down_fraction - if(method == "median") { - up_score <- apply(up_matrix, 2, median, na.rm = TRUE) + if (method == "median") { + up_score <- apply(up_matrix, 2, median, na.rm = TRUE) down_score <- apply(down_matrix, 2, median, na.rm = TRUE) } my_score_mat <- cbind(up_score = up_score, down_score = down_score) - my_row_sums <- rowSums(abs(my_score_mat), na.rm = TRUE) + my_row_sums <- rowSums(abs(my_score_mat), na.rm = TRUE) - if(method == "median") { - my_score_mat_mod <- cbind(up_score = up_score, down_score = down_score * (-1)) - my_row_sums <- rowSums(my_score_mat_mod, na.rm = TRUE) + if (method == "median") { + my_score_mat_mod <- cbind( + up_score = up_score, + down_score = down_score * (-1) + ) + my_row_sums <- rowSums(my_score_mat_mod, na.rm = TRUE) } both_missing <- apply(my_score_mat, 1, function(x) all(is.na(x))) @@ -376,57 +473,87 @@ checkSignatures <- function(xp, genes) { genes.inter <- lapply(g.v, intersect, genes.xp) genes.length <- unlist(lapply(genes.diff, length)) - genes.diff <- lapply(genes.diff, paste0, collapse=", ") + genes.diff <- lapply(genes.diff, paste0, collapse = ", ") genes.diff <- unlist(genes.diff) - genes.inter <- lapply(genes.inter, paste0, collapse=", ") + genes.inter <- lapply(genes.inter, paste0, collapse = ", ") genes.inter <- unlist(genes.inter) l <- unlist(lapply(g.v, length)) - ret.df <- tibble(geneset=names(g.v), - size.geneset=l, - size.missing=genes.length, - size.left=l-genes.length, - genes.missing=genes.diff, - genes.used=genes.inter) + ret.df <- tibble( + geneset = names(g.v), + size.geneset = l, + size.missing = genes.length, + size.left = l - genes.length, + genes.missing = genes.diff, + genes.used = genes.inter + ) return(ret.df) } ## signature overlap warning lengthWarning <- function(x) { - warning("Geneset: ", x[1], ": ", x[3], " of ", x[2], " genes missing: ", x[5], call.=F) + warning( + "Geneset: ", + x[1], + ": ", + x[3], + " of ", + x[2], + " genes missing: ", + x[5], + call. = F + ) } ## global wrapper function -calculateSignatureScores <- function(xp, genes, method, phenotypes=NULL, case=NULL, control=NULL, raw=FALSE, ...) { +calculateSignatureScores <- function( + xp, + genes, + method, + phenotypes = NULL, + case = NULL, + control = NULL, + raw = FALSE, + ... +) { # Report mismatches between matrix and signatures checks <- checkSignatures(xp, genes) # print(checks) # TODO: new function to send warning - checks.filtered <- checks %>% filter(size.missing>0) + checks.filtered <- checks %>% filter(size.missing > 0) apply(checks.filtered, 1, lengthWarning) - - gene.sets.out <- checks %>% filter(size.left==0) %>% pull(geneset) - if(length(gene.sets.out)>0) warning("The following genesets show no overlap with the expression matrix: " , paste0(gene.sets.out,collapse=", "), call.=F) + gene.sets.out <- checks %>% filter(size.left == 0) %>% pull(geneset) + if (length(gene.sets.out) > 0) { + warning( + "The following genesets show no overlap with the expression matrix: ", + paste0(gene.sets.out, collapse = ", "), + call. = F + ) + } # Keep only genesets with at least 1 gene overlapping - gene.sets.left <- checks %>% filter(size.left>0) %>% pull(geneset) + gene.sets.left <- checks %>% filter(size.left > 0) %>% pull(geneset) genes <- genes[gene.sets.left] # Stop if now genesets are left - if(length(genes)==0) stop("No genesets show an overlap with the expression matrix. Please check if identifiers match.") + if (length(genes) == 0) { + stop( + "No genesets show an overlap with the expression matrix. Please check if identifiers match." + ) + } # Use intersection of gene set with expression matrix for further calculations genes <- lapply(genes, intersect, rownames(xp)) - -# Run actual score calculations -switch(method, + # Run actual score calculations + switch( + method, plage = calculatePLAGEscores(xp, genes, ...), plage.dir = calculatePLAGEscores(xp, genes, correct.dir = TRUE, ...), gsva = calculateGSVAscores(xp, genes, ...), @@ -435,43 +562,55 @@ switch(method, median = calculateMedianScores(xp, genes, ...), mean = calculateMeanScores(xp, genes, ...), sams = calculateSamsscores(xp, genes, ...), - stop(method, " is not a valid method for score calculation.")) + stop(method, " is not a valid method for score calculation.") + ) } ## wrapper for multiple methods multipleSignatureScores <- function(xp, genes, methods) { - stopifnot((is.data.frame(xp) || is.matrix(xp)), - is.list(genes), - length(genes)>0, - is.character(methods), length(methods)>0) - - scores <- lapply(methods, function(x) calculateSignatureScores(xp, genes, x)) + stopifnot( + (is.data.frame(xp) || is.matrix(xp)), + is.list(genes), + length(genes) > 0, + is.character(methods), + length(methods) > 0 + ) + + scores <- lapply(methods, function(x) { + calculateSignatureScores(xp, genes, x) + }) names(scores) <- methods return(scores) } - ## Check consistency across scores # add suffix to rownames -reformatRownames <- function(x, n){ - rownames(x) <- rownames(x) %>% str_replace_all("\\s|\\-",".") %>% paste0(".",n) +reformatRownames <- function(x, n) { + rownames(x) <- rownames(x) %>% + str_replace_all("\\s|\\-", ".") %>% + paste0(".", n) return(x) } # generic function to generate a correlation matrix, preferably based on output of multipleSignatureScores -correlationMatrix <- function(score.list, names.list=NULL) { +correlationMatrix <- function(score.list, names.list = NULL) { stopifnot(is.list(score.list)) - if(is.null(names.list)) names.list <- names(score.list) - stopifnot(length(score.list)==length(names.list)) + if (is.null(names.list)) { + names.list <- names(score.list) + } + stopifnot(length(score.list) == length(names.list)) renamed.score.list <- list() - for(i in 1:length(names.list)) { - renamed.score.list[[i]] <- reformatRownames(score.list[[i]], names.list[i]) + for (i in 1:length(names.list)) { + renamed.score.list[[i]] <- reformatRownames( + score.list[[i]], + names.list[i] + ) } names(renamed.score.list) <- names(score.list) @@ -483,15 +622,36 @@ correlationMatrix <- function(score.list, names.list=NULL) { } # legacy function -correlationMatrixOld <- function(plageScores = NULL, gsvaScores = NULL, ssgseaScores = NULL, paiScores = NULL, singScores = NULL) { - - if(!is.null(plageScores)) plageScores <- reformatRownames(plageScores,"PLAGE") - if(!is.null(gsvaScores)) gsvaScores <- reformatRownames(gsvaScores, "GSVA") - if(!is.null(ssgseaScores)) ssgseaScores <- reformatRownames(ssgseaScores, "SSGSEA") - if(!is.null(paiScores)) paiScores <- reformatRownames(paiScores, "PAI") - if(!is.null(singScores)) singScores <- reformatRownames(singScores, "Singscore") +correlationMatrixOld <- function( + plageScores = NULL, + gsvaScores = NULL, + ssgseaScores = NULL, + paiScores = NULL, + singScores = NULL +) { + if (!is.null(plageScores)) { + plageScores <- reformatRownames(plageScores, "PLAGE") + } + if (!is.null(gsvaScores)) { + gsvaScores <- reformatRownames(gsvaScores, "GSVA") + } + if (!is.null(ssgseaScores)) { + ssgseaScores <- reformatRownames(ssgseaScores, "SSGSEA") + } + if (!is.null(paiScores)) { + paiScores <- reformatRownames(paiScores, "PAI") + } + if (!is.null(singScores)) { + singScores <- reformatRownames(singScores, "Singscore") + } - combined.matrix <- rbind(plageScores, gsvaScores, ssgseaScores, paiScores, singScores) + combined.matrix <- rbind( + plageScores, + gsvaScores, + ssgseaScores, + paiScores, + singScores + ) cor.matrix.all <- cor(t(combined.matrix)) @@ -503,9 +663,9 @@ correlationMatrixOld <- function(plageScores = NULL, gsvaScores = NULL, ssgseaSc ## Boxplots -boxplotScores <- function(score.matrix, set, group, title="") { - bp.df <- data.frame(score=score.matrix[set,], group=group) - ggplot(bp.df, aes(x=group, y=score)) + +boxplotScores <- function(score.matrix, set, group, title = "") { + bp.df <- data.frame(score = score.matrix[set, ], group = group) + ggplot(bp.df, aes(x = group, y = score)) + geom_boxplot() + geom_point() + ggtitle(title) @@ -516,9 +676,12 @@ sessionInfo() ####Commandline Argument parsing### -args = commandArgs(trailingOnly=TRUE) +args = commandArgs(trailingOnly = TRUE) if (length(args) < 3) { - stop("Usage: process_nanostring_data.R algorithm", call.=FALSE) + stop( + "Usage: process_nanostring_data.R algorithm", + call. = FALSE + ) } ####Uncomment if debugging @@ -530,7 +693,7 @@ score.method <- args[3] yaml_parsed <- read_yaml(gene_sets_to_compute) #Get GEX into shape for Nanostring pipeline -counts <- read.table(counts_input, sep="\t", check.names=F, header=T) %>% +counts <- read.table(counts_input, sep = "\t", check.names = F, header = T) %>% filter(`CodeClass` == "Endogenous") %>% select(-`CodeClass`) %>% column_to_rownames("Name") @@ -540,52 +703,61 @@ cs <- checkSignatures(counts, yaml_parsed) #Write to multiQC output -qc.file="signature_scores_qc_mqc.txt" -line="# id: nf-core-nanoflow-signature-score-qc +qc.file = "signature_scores_qc_mqc.txt" +line = "# id: nf-core-nanoflow-signature-score-qc # section_name: 'Signature Score QC' # description: 'Compare Signatures to Expression Matrix' # plot_type: 'table' # section_href: 'https://github.com/nf-core/nanoflow'" -write(line, - file = qc.file) -write.table(cs, - file = qc.file, - append=TRUE, - sep="\t", - row.names = FALSE, - quote = FALSE, - na="" - ) +write(line, file = qc.file) +write.table( + cs, + file = qc.file, + append = TRUE, + sep = "\t", + row.names = FALSE, + quote = FALSE, + na = "" +) ## Compute scores we need in our case -scores <- calculateSignatureScores(xp = counts, genes = yaml_parsed, method=score.method) +scores <- calculateSignatureScores( + xp = counts, + genes = yaml_parsed, + method = score.method +) s.r <- 1 s.c <- 1 -if(ncol(scores)>1) { +if (ncol(scores) > 1) { hc <- hclust(dist(t(scores))) s.c <- hc$order } -if(nrow(scores)>1) { +if (nrow(scores) > 1) { hc.r <- hclust(dist(scores)) s.r <- hc.r$order } -scores.df <- as.data.frame.matrix(t(scores[s.r,s.c])) +scores.df <- as.data.frame.matrix(t(scores[s.r, s.c])) scores.df <- rownames_to_column(scores.df, "sample") #Write to multiQC output -score.file="signature_scores_mqc.txt" -line=paste0("# id: nf-core-nanoflow-signature-score +score.file = "signature_scores_mqc.txt" +line = paste0( + "# id: nf-core-nanoflow-signature-score # section_name: 'Signature Scores' -# description: 'Signature Scores: Algorithm: ",score.method,"' +# description: 'Signature Scores: Algorithm: ", + score.method, + "' # plot_type: 'heatmap' -# section_href: 'https://github.com/nf-core/nanoflow'") +# section_href: 'https://github.com/nf-core/nanoflow'" +) write(line, file = score.file) -write.table(scores.df, - file = score.file, - append=TRUE, - sep="\t", - row.names = FALSE, - quote = FALSE, - na="" +write.table( + scores.df, + file = score.file, + append = TRUE, + sep = "\t", + row.names = FALSE, + quote = FALSE, + na = "" ) diff --git a/modules/local/compute_gene_scores/tests/main.nf.test.snap b/modules/local/compute_gene_scores/tests/main.nf.test.snap index 34ae36e..a1a02e9 100644 --- a/modules/local/compute_gene_scores/tests/main.nf.test.snap +++ b/modules/local/compute_gene_scores/tests/main.nf.test.snap @@ -25,7 +25,7 @@ ] ], "1": [ - "versions.yml:md5,267e6a81e12563418edabbdaa1a5ef79" + "versions.yml:md5,e3e9c4a42988d39a5d64477ffb44b256" ], "scores_for_mqc": [ [ @@ -39,7 +39,7 @@ ] ], "versions": [ - "versions.yml:md5,267e6a81e12563418edabbdaa1a5ef79" + "versions.yml:md5,e3e9c4a42988d39a5d64477ffb44b256" ] } ], diff --git a/nextflow.config b/nextflow.config index be31553..0f42faa 100644 --- a/nextflow.config +++ b/nextflow.config @@ -310,7 +310,7 @@ manifest { mainScript = 'main.nf' defaultBranch = 'master' nextflowVersion = '!>=25.10.2' - version = '1.3.2' + version = '1.3.3dev' doi = '' } diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 427db32..c818401 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "Stable", "datePublished": "2026-01-13T18:19:48+00:00", - "description": "

\n \n \n \"nf-core/nanostring\"\n \n

\n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/nanostring)\n[![GitHub Actions CI Status](https://github.com/nf-core/nanostring/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/nanostring/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/nanostring/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/nanostring/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/nanostring/results)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.8028303-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.8028303)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.04.0-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-3.5.1-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/3.5.1)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/nanostring)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23nanostring-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/nanostring)[![Follow on Bluesky](https://img.shields.io/badge/bluesky-%40nf__core-1185fe?labelColor=000000&logo=bluesky)](https://bsky.app/profile/nf-co.re)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core)\n\n## Introduction\n\n**nf-core/nanostring** is a bioinformatics pipeline that can be used to analyze NanoString data. The performed analysis steps include quality control and data normalization.\n\nThe pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. Where possible, these processes have been submitted to and installed from [nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to everyone within the Nextflow community!\n\n## Pipeline summary\n\n1. Quality control with NACHO ([`NACHO`](https://github.com/mcanouil/NACHO/))\n2. Perform normalization with NACHO\n3. Create count tables with provided metadata\n4. Present QC for NanoString data ([`MultiQC`](http://multiqc.info/))\n\n## Pipeline tubemap\n\n![](./assets/nf-core_nanostring_tubemap.png)\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how\n> to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline)\n> with `-profile test` before running the workflow on actual data.\n\nFirst, prepare a samplesheet with your input data that looks as follows:\n\n`samplesheet.csv`:\n\n```csv\nRCC_FILE,RCC_FILE_NAME,SAMPLE_ID\n/path/to/sample1.RCC,sample1.RCC,sample1\n/path/to/sample2.RCC,sample2.RCC,sample2\n```\n\nEach row represents a RCC file with counts.\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run nf-core/nanostring \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/usage/getting_started/configuration#custom-configuration-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/nanostring/usage) and the [parameter documentation](https://nf-co.re/nanostring/parameters).\n\n## Pipeline output\n\nTo see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/nanostring/results) tab on the nf-core website pipeline page.\nFor more details about the output files and reports, please refer to the\n[output documentation](https://nf-co.re/nanostring/output).\n\n## Credits\n\nnf-core/nanostring was originally written by Peltzer, Alexander & Mohr, Christopher. Extensive support was provided from other co-authors on the scientific or technical input required for the pipeline:\n\n- Stadermann, Kai\n- Zwick, Matthias\n- Leparc, Germ\u00e1n\n- Schmid, Ramona\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#nanostring` channel](https://nfcore.slack.com/channels/nanostring) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\nIf you use nf-core/nanostring for your analysis, please cite the publication: [nf-core/nanostring Bioinformatics](https://academic.oup.com/bioinformatics/advance-article/doi/10.1093/bioinformatics/btae019/7517109) and the [Zenodo DOI](https://doi.org/10.5281/zenodo.8028303).\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nYou can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n", + "description": "

\n \n \n \"nf-core/nanostring\"\n \n

\n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/nanostring)\n[![GitHub Actions CI Status](https://github.com/nf-core/nanostring/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/nanostring/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/nanostring/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/nanostring/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/nanostring/results)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.8028303-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.8028303)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.10.2-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-3.5.1-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/3.5.1)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/nanostring)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23nanostring-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/nanostring)[![Follow on Bluesky](https://img.shields.io/badge/bluesky-%40nf__core-1185fe?labelColor=000000&logo=bluesky)](https://bsky.app/profile/nf-co.re)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core)\n\n## Introduction\n\n**nf-core/nanostring** is a bioinformatics pipeline that can be used to analyze NanoString data. The performed analysis steps include quality control and data normalization.\n\nThe pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. Where possible, these processes have been submitted to and installed from [nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to everyone within the Nextflow community!\n\n## Pipeline summary\n\n1. Quality control with NACHO ([`NACHO`](https://github.com/mcanouil/NACHO/))\n2. Perform normalization with NACHO\n3. Create count tables with provided metadata\n4. Present QC for NanoString data ([`MultiQC`](http://multiqc.info/))\n\n## Pipeline tubemap\n\n![](./assets/nf-core_nanostring_tubemap.png)\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how\n> to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline)\n> with `-profile test` before running the workflow on actual data.\n\nFirst, prepare a samplesheet with your input data that looks as follows:\n\n`samplesheet.csv`:\n\n```csv\nRCC_FILE,RCC_FILE_NAME,SAMPLE_ID\n/path/to/sample1.RCC,sample1.RCC,sample1\n/path/to/sample2.RCC,sample2.RCC,sample2\n```\n\nEach row represents a RCC file with counts.\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run nf-core/nanostring \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/usage/getting_started/configuration#custom-configuration-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/nanostring/usage) and the [parameter documentation](https://nf-co.re/nanostring/parameters).\n\n## Pipeline output\n\nTo see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/nanostring/results) tab on the nf-core website pipeline page.\nFor more details about the output files and reports, please refer to the\n[output documentation](https://nf-co.re/nanostring/output).\n\n## Credits\n\nnf-core/nanostring was originally written by Peltzer, Alexander & Mohr, Christopher. Extensive support was provided from other co-authors on the scientific or technical input required for the pipeline:\n\n- Stadermann, Kai\n- Zwick, Matthias\n- Leparc, Germ\u00e1n\n- Schmid, Ramona\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#nanostring` channel](https://nfcore.slack.com/channels/nanostring) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\nIf you use nf-core/nanostring for your analysis, please cite the publication: [nf-core/nanostring Bioinformatics](https://academic.oup.com/bioinformatics/advance-article/doi/10.1093/bioinformatics/btae019/7517109) and the [Zenodo DOI](https://doi.org/10.5281/zenodo.8028303).\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nYou can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n", "hasPart": [ { "@id": "main.nf" diff --git a/subworkflows/local/compute_gene_scores_heatmap/tests/main.nf.test.snap b/subworkflows/local/compute_gene_scores_heatmap/tests/main.nf.test.snap index 018553a..ab472cd 100644 --- a/subworkflows/local/compute_gene_scores_heatmap/tests/main.nf.test.snap +++ b/subworkflows/local/compute_gene_scores_heatmap/tests/main.nf.test.snap @@ -3,7 +3,7 @@ "content": [ [ "versions.yml:md5,63b539ddb8d646a7cf480f3de2e47100", - "versions.yml:md5,6fac9e04824b7752f45abd6b1d4ef0a9" + "versions.yml:md5,fada5495f572217c5a3bf98050dba293" ] ], "meta": { @@ -17,7 +17,7 @@ { "0": [ "versions.yml:md5,63b539ddb8d646a7cf480f3de2e47100", - "versions.yml:md5,6fac9e04824b7752f45abd6b1d4ef0a9" + "versions.yml:md5,fada5495f572217c5a3bf98050dba293" ], "1": [ [ @@ -39,7 +39,7 @@ ], "versions": [ "versions.yml:md5,63b539ddb8d646a7cf480f3de2e47100", - "versions.yml:md5,6fac9e04824b7752f45abd6b1d4ef0a9" + "versions.yml:md5,fada5495f572217c5a3bf98050dba293" ] } ], @@ -67,7 +67,7 @@ "content": [ [ "versions.yml:md5,63b539ddb8d646a7cf480f3de2e47100", - "versions.yml:md5,6fac9e04824b7752f45abd6b1d4ef0a9" + "versions.yml:md5,fada5495f572217c5a3bf98050dba293" ] ], "meta": { diff --git a/subworkflows/nf-core/utils_nfschema_plugin/main.nf b/subworkflows/nf-core/utils_nfschema_plugin/main.nf index acb3972..1df8b76 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/main.nf +++ b/subworkflows/nf-core/utils_nfschema_plugin/main.nf @@ -38,7 +38,7 @@ workflow UTILS_NFSCHEMA_PLUGIN { } log.info paramsHelp( help_options, - params.help instanceof String ? params.help : "", + (params.help instanceof String && params.help != "true") ? params.help : "", ) exit 0 } diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 8185331..96a57b3 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -39,7 +39,7 @@ "r-optparse": "1.7.5" }, "Workflow": { - "nf-core/nanostring": "v1.3.2" + "nf-core/nanostring": "v1.3.3dev" } }, [ @@ -128,8 +128,8 @@ ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.2" + "nextflow": "25.10.3" }, - "timestamp": "2026-01-14T18:49:35.271884067" + "timestamp": "2026-01-27T14:30:12.052623507" } } \ No newline at end of file diff --git a/tests/test.nf.test.snap b/tests/test.nf.test.snap index 18a743f..03551e2 100644 --- a/tests/test.nf.test.snap +++ b/tests/test.nf.test.snap @@ -40,7 +40,7 @@ "r-optparse": "1.7.5" }, "Workflow": { - "nf-core/nanostring": "v1.3.2" + "nf-core/nanostring": "v1.3.3dev" } }, [ @@ -129,8 +129,8 @@ ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.2" + "nextflow": "25.10.3" }, - "timestamp": "2026-01-14T17:35:43.587464854" + "timestamp": "2026-01-27T14:31:33.222342416" } } \ No newline at end of file diff --git a/tests/test_samples.nf.test.snap b/tests/test_samples.nf.test.snap index def6260..ae3b72c 100644 --- a/tests/test_samples.nf.test.snap +++ b/tests/test_samples.nf.test.snap @@ -40,7 +40,7 @@ "r-optparse": "1.7.5" }, "Workflow": { - "nf-core/nanostring": "v1.3.2" + "nf-core/nanostring": "v1.3.3dev" } }, [ @@ -129,8 +129,8 @@ ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.2" + "nextflow": "25.10.3" }, - "timestamp": "2026-01-14T17:36:55.213351086" + "timestamp": "2026-01-27T14:32:51.929654396" } } \ No newline at end of file diff --git a/tests/test_scores.nf.test.snap b/tests/test_scores.nf.test.snap index 6146c77..b7345b4 100644 --- a/tests/test_scores.nf.test.snap +++ b/tests/test_scores.nf.test.snap @@ -4,14 +4,14 @@ 8, { "COMPUTE_GENE_SCORES": { - "r-base": "4.2.3", + "r-base": "4.4.3", "r-dplyr": "1.1.4", - "r-tibble": "3.2.1", - "r-singscore": "1.18.0", - "r-GSVA": "1.46.0", - "r-yaml": "2.3.7", - "r-FactoMineR": 2.8, - "r-stringr": "1.5.0" + "r-tibble": "3.3.1", + "r-singscore": "1.26.0", + "r-GSVA": "2.0.0", + "r-yaml": "2.3.12", + "r-FactoMineR": 2.13, + "r-stringr": "1.6.0" }, "CREATE_ANNOTATED_TABLES": { "r-base": "4.3.3", @@ -50,7 +50,7 @@ "r-optparse": "1.7.5" }, "Workflow": { - "nf-core/nanostring": "v1.3.2" + "nf-core/nanostring": "v1.3.3dev" } }, [ @@ -152,8 +152,8 @@ ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.10.2" + "nextflow": "25.10.3" }, - "timestamp": "2026-01-14T17:39:21.947737179" + "timestamp": "2026-01-28T20:50:21.912254781" } } \ No newline at end of file