Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 62 additions & 79 deletions modules/nf-core/rmarkdownnotebook/main.nf
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
include { dump_params_yml; indent_code_block } from "./parametrize"

process RMARKDOWNNOTEBOOK {
tag "$meta.id"
label 'process_low'
Expand All @@ -18,93 +16,34 @@ process RMARKDOWNNOTEBOOK {
path input_files

output:
tuple val(meta), path("*.html") , emit: report
tuple val(meta), path("*.parameterised.Rmd") , emit: parameterised_notebook, optional: true
tuple val(meta), path("artifacts/*") , emit: artifacts, optional: true
tuple val(meta), path("session_info.log") , emit: session_info
path "versions.yml" , emit: versions
tuple val(meta), path("*.html") , emit: report
tuple val(meta), path("*.parameterised.Rmd"), emit: parameterised_notebook, optional: true
tuple val(meta), path("artifacts/*") , emit: artifacts, optional: true
tuple val(meta), path("session_info.log") , emit: session_info
path "versions.yml" , emit: versions

when:
task.ext.when == null || task.ext.when

script:
def prefix = task.ext.prefix ?: "${meta.id}"
def parametrize = (task.ext.parametrize == null) ? true : task.ext.parametrize
def implicit_params = (task.ext.implicit_params == null) ? true : task.ext.implicit_params
def meta_params = (task.ext.meta_params == null) ? true : task.ext.meta_params
notebook_parameters = [
meta: meta,
cpus: task.cpus,
] + (parameters ?: [:])

// Dump parameters to yaml file.
// Using a yaml file over using the CLI params because
// * no issue with escaping
// * allows to pass nested maps instead of just single values
def params_cmd = ""
def render_cmd = ""
if (parametrize) {
nb_params = [:]
if (implicit_params) {
nb_params["cpus"] = task.cpus
nb_params["artifact_dir"] = "artifacts"
nb_params["input_dir"] = "./"
}
if (meta_params) {
nb_params["meta"] = meta
}
nb_params += parameters
params_cmd = dump_params_yml(nb_params)
render_cmd = """\
params = yaml::read_yaml('.params.yml')

# Instead of rendering with params, produce a version of the R
# markdown with param definitions set, so the notebook itself can
# be reused
rmd_content <- readLines('${prefix}.Rmd')

# Extract YAML content between the first two '---'
start_idx <- which(rmd_content == "---")[1]
end_idx <- which(rmd_content == "---")[2]
rmd_yaml_content <- paste(rmd_content[(start_idx+1):(end_idx-1)], collapse = "\\n")
rmd_params <- yaml::yaml.load(rmd_yaml_content)

# Override the params
rmd_params[['params']] <- modifyList(rmd_params[['params']], params)

# Recursive function to add 'value' to list elements, except for top-level
add_value_recursively <- function(lst, is_top_level = FALSE) {
if (!is.list(lst)) {
return(lst)
}

lst <- lapply(lst, add_value_recursively)
if (!is_top_level) {
lst <- list(value = lst)
}
return(lst)
}

# Reformat nested lists under 'params' to have a 'value' key recursively
rmd_params[['params']] <- add_value_recursively(rmd_params[['params']], is_top_level = TRUE)

# Convert back to YAML string
updated_yaml_content <- as.character(yaml::as.yaml(rmd_params))

# Remove the old YAML content
rmd_content <- rmd_content[-((start_idx+1):(end_idx-1))]

# Insert the updated YAML content at the right position
rmd_content <- append(rmd_content, values = unlist(strsplit(updated_yaml_content, split = "\\n")), after = start_idx)

writeLines(rmd_content, '${prefix}.parameterised.Rmd')

# Render based on the updated file
rmarkdown::render('${prefix}.parameterised.Rmd', output_file='${prefix}.html', envir = new.env())
"""
} else {
render_cmd = "rmarkdown::render('${prefix}.Rmd', output_file='${prefix}.html')"
}

def yamlBuilder = new groovy.yaml.YamlBuilder()
yamlBuilder.call(notebook_parameters)
def yaml_content = yamlBuilder.toString().tokenize('\n').join("\n ")
"""
# Dump .params.yml heredoc (section will be empty if parametrization is disabled)
${indent_code_block(params_cmd, 4)}
# Dump parameters to yaml file
cat <<- END_YAML_PARAMS > params.yml
${yaml_content}
END_YAML_PARAMS

# Create output directory
mkdir artifacts
Expand All @@ -122,8 +61,52 @@ process RMARKDOWNNOTEBOOK {

# Render notebook
Rscript - <<EOF
${indent_code_block(render_cmd, 8)}
writeLines(capture.output(sessionInfo()), "session_info.log")
params = yaml::read_yaml('params.yml')

# Instead of rendering with params, produce a version of the R
# markdown with param definitions set, so the notebook itself can
# be reused
rmd_content <- readLines('${prefix}.Rmd')

# Extract YAML content between the first two '---'
start_idx <- which(rmd_content == "---")[1]
end_idx <- which(rmd_content == "---")[2]
rmd_yaml_content <- paste(rmd_content[(start_idx+1):(end_idx-1)], collapse = "\\n")
rmd_params <- yaml::yaml.load(rmd_yaml_content)

# Override the params
rmd_params[['params']] <- modifyList(rmd_params[['params']], params)

# Recursive function to add 'value' to list elements, except for top-level
add_value_recursively <- function(lst, is_top_level = FALSE) {
if (!is.list(lst)) {
return(lst)
}

lst <- lapply(lst, add_value_recursively)
if (!is_top_level) {
lst <- list(value = lst)
}
return(lst)
}

# Reformat nested lists under 'params' to have a 'value' key recursively
rmd_params[['params']] <- add_value_recursively(rmd_params[['params']], is_top_level = TRUE)

# Convert back to YAML string
updated_yaml_content <- as.character(yaml::as.yaml(rmd_params))

# Remove the old YAML content
rmd_content <- rmd_content[-((start_idx+1):(end_idx-1))]

# Insert the updated YAML content at the right position
rmd_content <- append(rmd_content, values = unlist(strsplit(updated_yaml_content, split = "\\n")), after = start_idx)

writeLines(rmd_content, '${prefix}.parameterised.Rmd')

# Render based on the updated file
rmarkdown::render('${prefix}.parameterised.Rmd', output_file='${prefix}.html', envir = new.env())
writeLines(capture.output(sessionInfo()), "session_info.log")
EOF

cat <<-END_VERSIONS > versions.yml
Expand Down
25 changes: 5 additions & 20 deletions modules/nf-core/rmarkdownnotebook/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,9 @@ tools:
homepage: https://rmarkdown.rstudio.com/
documentation: https://rmarkdown.rstudio.com/lesson-1.html
tool_dev_url: https://github.com/rstudio/rmarkdown
licence: ["GPL-3"]
licence:
- "GPL-3"
identifier: ""
params:
- parametrize:
type: boolean
description: If true, parametrize the notebook
- implicit_params:
type: boolean
description: |
If true (default), include the implicit params
* `input_dir`, which points to the directory containing the files added via `input_files`,
* `artifact_dir`, which points to the directory where the notebook should place output files, and
* `cpus`, which contains the value of ${task.cpus}
- meta_params:
type: boolean
description: |
If true, include a parameter `meta` which contains the information specified
via the `meta` input channel.
input:
- - meta:
type: map
Expand All @@ -39,7 +24,7 @@ input:
description: Rmarkdown file
pattern: "*.{Rmd}"
ontologies:
- edam: http://edamontology.org/format_4000 # R markdown
- edam: http://edamontology.org/format_4000
- parameters:
type: map
description: |
Expand Down Expand Up @@ -73,7 +58,7 @@ output:
description: Parameterised Rmarkdown file
pattern: "*.parameterised.Rmd"
ontologies:
- edam: http://edamontology.org/format_4000 # R markdown
- edam: http://edamontology.org/format_4000
artifacts:
- - meta:
type: map
Expand Down Expand Up @@ -102,7 +87,7 @@ output:
description: File containing software versions
pattern: "versions.yml"
ontologies:
- edam: http://edamontology.org/format_3750 # YAML
- edam: http://edamontology.org/format_3750
authors:
- "@grst"
maintainers:
Expand Down
32 changes: 0 additions & 32 deletions modules/nf-core/rmarkdownnotebook/parametrize.nf

This file was deleted.

11 changes: 1 addition & 10 deletions modules/nf-core/rmarkdownnotebook/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ nextflow_process {
test("test_rmarkdownnotebook") {

when {
params{
module_args = false
}
process {
"""
input[0] = [
Expand Down Expand Up @@ -43,16 +40,13 @@ nextflow_process {
test("test_rmarkdownnotebook_parametrize") {

when {
params{
module_args = true
}
process {
"""
input[0] = [
[ id:'test_rmd' ],
file(params.modules_testdata_base_path + 'generic/notebooks/rmarkdown/rmarkdown_notebook.Rmd', checkIfExists: true)
]
input[1] = [input_filename: "hello.txt", n_iter: 12]
input[1] = [input_filename: "hello.txt", n_iter: 12, input_dir: "./"]
input[2] = file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)
"""
}
Expand All @@ -77,9 +71,6 @@ nextflow_process {
options "-stub"

when {
params{
module_args = false
}
process {
"""
input[0] = [
Expand Down
24 changes: 12 additions & 12 deletions modules/nf-core/rmarkdownnotebook/tests/main.nf.test.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
"content": [
"test_rmd.html",
[

[
{
"id": "test_rmd"
},
"test_rmd.parameterised.Rmd:md5,54d7d6576e3d8432effd8f449d018604"
]
],
[

Expand All @@ -15,9 +20,9 @@
],
"meta": {
"nf-test": "0.9.2",
"nextflow": "24.10.4"
"nextflow": "25.10.4"
},
"timestamp": "2025-02-17T12:51:28.269874594"
"timestamp": "2026-03-18T13:10:53.025617"
},
"test_rmarkdownnotebook_parametrize": {
"content": [
Expand All @@ -27,16 +32,11 @@
{
"id": "test_rmd"
},
"test_rmd.parameterised.Rmd:md5,59e184e50aadb66a821a2acce6a7c27c"
"test_rmd.parameterised.Rmd:md5,841b2c0d847c191b92547ae5b77e09ab"
]
],
[
[
{
"id": "test_rmd"
},
"artifact.txt:md5,b10a8db164e0754105b7a99be72e3fe5"
]

],
"session_info.log",
[
Expand All @@ -45,9 +45,9 @@
],
"meta": {
"nf-test": "0.9.2",
"nextflow": "24.10.4"
"nextflow": "25.10.4"
},
"timestamp": "2025-02-17T12:51:36.802094082"
"timestamp": "2026-03-18T13:10:59.388999"
},
"test_rmarkdownnotebook - stub": {
"content": [
Expand Down
3 changes: 0 additions & 3 deletions modules/nf-core/rmarkdownnotebook/tests/nextflow.config
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
process {
ext.parametrize = params.module_args
}
Loading