From 53449fbd947df4bf4f388dd5f7c264a20bbc68fd Mon Sep 17 00:00:00 2001 From: Felix Bartusch Date: Thu, 9 Oct 2025 15:28:33 +0200 Subject: [PATCH 1/3] Add files to ro-crate-metadata.json * add execution_report.html * add execution_timeline.html * add execution_trace.txt * add pipeline_dag.html Still missing: * params.json mqc_versions.yml begins with "file://" as id, but could be represented with relative path. --- .../prov/renderers/WrrocRenderer.groovy | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/main/groovy/nextflow/prov/renderers/WrrocRenderer.groovy b/src/main/groovy/nextflow/prov/renderers/WrrocRenderer.groovy index 33272bf..4f632d5 100644 --- a/src/main/groovy/nextflow/prov/renderers/WrrocRenderer.groovy +++ b/src/main/groovy/nextflow/prov/renderers/WrrocRenderer.groovy @@ -19,6 +19,7 @@ package nextflow.prov.renderers import java.nio.file.FileSystems import java.nio.file.Files import java.nio.file.Path +import java.nio.file.Paths import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -91,6 +92,12 @@ class WrrocRenderer implements Renderer { final nextflowVersion = metadata.nextflow.version.toString() final params = session.params + // get various pipeline_info configurations + final reportOpts = session.config.navigate('report', [:]) as Map + final timelineOpts = session.config.navigate('timeline', [:]) as Map + final dagOpts = session.config.navigate('dag', [:]) as Map + final traceOpts = session.config.navigate('trace', [:]) as Map + // parse wrroc configuration final wrrocOpts = session.config.navigate('prov.formats.wrroc', [:]) as Map final agent = getAgentInfo(wrrocOpts) @@ -208,6 +215,51 @@ class WrrocRenderer implements Renderer { ] as Map } + // -- pipeline_info files + if(reportOpts.enabled) { + Path relativeReportPath = crateDir.relativize(Paths.get(reportOpts.file.toString())) + datasetParts.add([ + "@id" : relativeReportPath.toString(), + "@type" : "File", + "name" : relativeReportPath.getFileName().toString(), + "description" : "Nextflow execution report", + "encodingFormat": "text/html" + ]) + } + + if(timelineOpts.enabled) { + Path relativeTimelinePath = crateDir.relativize(Paths.get(timelineOpts.file.toString())) + datasetParts.add([ + "@id" : relativeTimelinePath.toString(), + "@type" : "File", + "name" : relativeTimelinePath.getFileName().toString(), + "description" : "Nextflow execution timeline", + "encodingFormat": "text/html" + ]) + } + + if(dagOpts.enabled) { + Path relativeDagPath = crateDir.relativize(Paths.get(dagOpts.file.toString())) + datasetParts.add([ + "@id" : relativeDagPath.toString(), + "@type" : "File", + "name" : relativeDagPath.getFileName().toString(), + "description" : "Nextflow execution DAG", + "encodingFormat": "text/html" + ]) + } + + if(traceOpts.enabled) { + Path relativeTracePath = crateDir.relativize(Paths.get(traceOpts.file.toString())) + datasetParts.add([ + "@id" : relativeTracePath.toString(), + "@type" : "File", + "name" : relativeTracePath.getFileName().toString(), + "description" : "Nextflow execution DAG", + "encodingFormat": "text/plain" + ]) + } + // -- input files Map paramInputFiles = [:] From bcbc846311daf52ffd82bacb24f23aa1e90c21af Mon Sep 17 00:00:00 2001 From: Ben Sherman Date: Tue, 21 Oct 2025 13:15:10 -0500 Subject: [PATCH 2/3] Save WC_SAMPLE output in nf-prov-test as a workflow output (#52) --- nf-prov-test/main.nf | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/nf-prov-test/main.nf b/nf-prov-test/main.nf index 21583df..11420f5 100644 --- a/nf-prov-test/main.nf +++ b/nf-prov-test/main.nf @@ -37,10 +37,14 @@ process WC_SAMPLE { input: tuple val(id), path(fastq_1), path(fastq_2) + output: + tuple val(id), path('counts.txt') + script: """ - wc -l ${fastq_1} - wc -l ${fastq_2} + touch counts.txt + wc -l ${fastq_1} >> counts.txt + wc -l ${fastq_2} >> counts.txt """ } @@ -53,11 +57,12 @@ workflow { ECHO_EXEC(inputs_ch) samples_ch = channel.fromPath(params.input).splitCsv(header: true) - WC_SAMPLE(samples_ch) + counts_ch = WC_SAMPLE(samples_ch) publish: script = ECHO_SCRIPT.out exec = ECHO_EXEC.out + counts = counts_ch } output { @@ -74,4 +79,8 @@ output { path 'exec.json' } } + + counts { + path '.' + } } From 2357d851fc2e46efd7fc2b6e500e1e780a0a5142 Mon Sep 17 00:00:00 2001 From: Felix Bartusch Date: Thu, 23 Oct 2025 11:16:26 +0200 Subject: [PATCH 3/3] Fix bug in WRROC processLookup Partially solves #49 WRROC parts are still missing from metadata if for processes using exec. --- src/main/groovy/nextflow/prov/renderers/WrrocRenderer.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/groovy/nextflow/prov/renderers/WrrocRenderer.groovy b/src/main/groovy/nextflow/prov/renderers/WrrocRenderer.groovy index 4f632d5..f03f165 100644 --- a/src/main/groovy/nextflow/prov/renderers/WrrocRenderer.groovy +++ b/src/main/groovy/nextflow/prov/renderers/WrrocRenderer.groovy @@ -399,7 +399,7 @@ class WrrocRenderer implements Renderer { // HACK: when the owner script of a processor defines only one process, that must be the definition final meta = ScriptMeta.get(processor.getOwnerScript()) final defs = meta.getDefinitions().findAll { defn -> defn instanceof ProcessDef } as List - final processDef = defs.size() == 1 ? defs.first() : null + final processDef = defs.find { it.name == processor.name } if( !processDef ) log.warn "Could not identify process definition for `${processor.name}` -- resulting RO-Crate may be invalid (hint: define each process in a separate module script to fix this issue)" acc[processor] = processDef