NfcoreCitationUtils
Citation management and topic channel utilities for nf-core pipelines.
Overview
The NfcoreCitationUtils utility provides comprehensive citation management functionality for nf-core pipelines, supporting both traditional file-based approaches and modern topic channel patterns. This utility enables progressive migration from legacy meta.yml citation files to the more efficient and accurate topic channel system.
Topic Channel Migration Strategy for Citations
Similar to version management, the citation system supports a three-phase migration approach:
- Legacy Stage: Traditional meta.yml file processing with manual collection
- Transition Stage: Mixed approach supporting both files and topic channels
- Modern Stage: Pure topic channel approach with automatic runtime citation collection
This migration strategy ensures backward compatibility while enabling pipelines to benefit from runtime-accurate citations where only tools that actually execute are included in the final reports.
Available Functions
Modern Approach Functions (Recommended)
getCitation()
Description:
Extracts citation information from a module’s meta.yml file and formats it for topic channel emission. This is the modern approach for automatic citation collection that only includes citations for tools that actually execute.
Function Signature:
List getCitation(String metaYmlPath)Parameters:
metaYmlPath(String): Path to the module’s meta.yml file, typically"${moduleDir}/meta.yml"
Returns:
List: Citation data formatted for topic channel emission[module, tool, citation_data]
Usage in Process:
include { getCitation } from 'plugin/nf-core-utils'
process FASTQC { input: tuple val(meta), path(reads)
output: tuple val(meta), path("*.html"), emit: html tuple val(meta), path("*.zip"), emit: zip val citation_data, topic: citations
script: citation_data = getCitation("${moduleDir}/meta.yml") """ fastqc --quiet --threads ${task.cpus} ${reads} """}Pipeline Integration:
workflow { FASTQC(samples) MULTIQC(reports)
// Collect all citations automatically - only from processes that executed citation_ch = channel.topic('citations').collect()
// Generate citation text and bibliography citation_ch.map { citations -> def citationText = autoToolCitationText(citations) def bibliography = autoToolBibliographyText(citations)
// Write to MultiQC template files file("${params.outdir}/multiqc_citations.txt").text = citationText file("${params.outdir}/multiqc_bibliography.html").text = bibliography }}autoToolCitationText()
Description:
Automatically generates formatted citation text from topic channel citation data. This processes the automatic citation collection from executed processes, ensuring runtime accuracy.
Function Signature:
String autoToolCitationText(List topicCitations = [])Parameters:
topicCitations(List): Citation data collected from topic channel
Returns:
String: Formatted citation text for methods descriptions
Usage Example:
include { autoToolCitationText } from 'plugin/nf-core-utils'
workflow { // Process data and collect citations PROCESS_SAMPLES(samples)
// Collect all citations from topic channel def citation_ch = channel.topic('citations').collect()
citation_ch.map { citations -> def citationText = autoToolCitationText(citations) log.info "Generated citations: ${citationText}" // Returns: "Tools used in the workflow included: fastqc (Andrews et al. 2010), multiqc (Ewels et al. 2016)." }}autoToolBibliographyText()
Description:
Automatically generates HTML bibliography from topic channel citation data. Creates bibliography entries for tools that were actually executed.
Function Signature:
String autoToolBibliographyText(List topicCitations = [])Parameters:
topicCitations(List): Citation data collected from topic channel
Returns:
String: HTML bibliography for MultiQC reports
Usage Example:
include { autoToolBibliographyText } from 'plugin/nf-core-utils'
workflow { // After processing with citation-enabled modules def citation_ch = channel.topic('citations').collect()
citation_ch.map { citations -> def bibliography = autoToolBibliographyText(citations) // Write bibliography for MultiQC file("${params.outdir}/multiqc_bibliography.html").text = bibliography }}Legacy Functions (Still Supported)
generateModuleToolCitation()
Description:
Extracts citation information from a module’s meta.yml file using the traditional approach. This function processes all tools in the meta.yml regardless of execution.
Function Signature:
Map generateModuleToolCitation(Object metaFilePath)Parameters:
metaFilePath(String|File): Path to the meta.yml file
Returns:
Map: Citations map with tool names as keys and citation/bibliography data as values
Usage Example:
include { generateModuleToolCitation } from 'plugin/nf-core-utils'
// Extract citations from specific moduledef fastqcCitations = generateModuleToolCitation('modules/nf-core/fastqc/meta.yml')// Returns: [fastqc: [citation: 'fastqc (Andrews et al. 2010)', bibliography: '<li>Andrews S...</li>']]
log.info "FASTQC citations: ${fastqcCitations}"toolCitationText()
Description:
Generates formatted citation text from collected citations map (legacy approach).
Function Signature:
String toolCitationText(Map collectedCitations)Parameters:
collectedCitations(Map): Map of tool citations fromgenerateModuleToolCitation()
Returns:
String: Formatted citation text for use in methods descriptions
Usage Example:
include { generateModuleToolCitation; toolCitationText } from 'plugin/nf-core-utils'
// Collect citations from multiple modulesdef allCitations = [:]allCitations.putAll(generateModuleToolCitation('modules/nf-core/fastqc/meta.yml'))allCitations.putAll(generateModuleToolCitation('modules/nf-core/multiqc/meta.yml'))
def citationText = toolCitationText(allCitations)log.info "Citations: ${citationText}"// Returns: "Tools used in the workflow included: fastqc (Andrews et al. 2010), multiqc (Ewels et al. 2016)."toolBibliographyText()
Description:
Generates HTML bibliography from collected citations (legacy approach).
Function Signature:
String toolBibliographyText(Map collectedCitations)Parameters:
collectedCitations(Map): Map of tool citations
Returns:
String: HTML bibliography for MultiQC reports
Usage Example:
include { collectCitationsFromFiles; toolBibliographyText } from 'plugin/nf-core-utils'
def citationFiles = ['modules/nf-core/fastqc/meta.yml', 'modules/nf-core/multiqc/meta.yml']def citations = collectCitationsFromFiles(citationFiles)def bibliography = toolBibliographyText(citations)
file("${params.outdir}/bibliography.html").text = bibliographymethodsDescriptionText()
Description:
Generates methods description text using collected citations and a MultiQC methods template. This function substitutes citation and bibliography variables into the template.
Function Signature:
String methodsDescriptionText(String mqcMethodsYamlPath, Map collectedCitations = [:], Map meta = [:])Parameters:
mqcMethodsYamlPath(String): Path to MultiQC methods YAML template filecollectedCitations(Map, optional): Map containing all tool citationsmeta(Map, optional): Additional metadata for template substitution
Returns:
String: Formatted methods description HTML
Usage Example:
include { collectCitationsFromFiles; methodsDescriptionText } from 'plugin/nf-core-utils'
// Collect citations and generate methods descriptiondef citations = collectCitationsFromFiles(['modules/nf-core/fastqc/meta.yml'])def methodsYaml = "${projectDir}/assets/methods_description_template.yml"
def methodsDescription = methodsDescriptionText(methodsYaml, citations, [ 'pipeline_name': workflow.manifest.name, 'pipeline_version': workflow.manifest.version])
file("${params.outdir}/methods_description.html").text = methodsDescriptionTemplate Example (methods_description_template.yml):
id: "custom-methods"section_name: "nf-core/rnaseq Methods Description"description: | <h4>Methods</h4> <p>Data was processed using nf-core/rnaseq v${pipeline_version}. ${tool_citations_text}</p>
<h4>References</h4> ${tool_bibliography_text}collectCitationsFromFiles()
Description:
Collects citations from multiple meta.yml files (legacy batch processing approach).
Function Signature:
Map collectCitationsFromFiles(List<String> metaFilePaths)Parameters:
metaFilePaths(List): List of paths to module meta.yml files
Returns:
Map: Combined citations from all files
Usage Example:
include { collectCitationsFromFiles } from 'plugin/nf-core-utils'
// Batch collect citations from multiple modulesdef metaFiles = [ 'modules/nf-core/fastqc/meta.yml', 'modules/nf-core/multiqc/meta.yml', 'modules/local/custom_tool/meta.yml']
def allCitations = collectCitationsFromFiles(metaFiles)log.info "Collected ${allCitations.size()} tool citations"Migration Functions
processMixedCitationSources()
Description:
Processes citations from both topic channels (modern approach) and legacy files for progressive migration.
Function Signature:
Map processMixedCitationSources(List<List> topicCitations, List<String> citationFiles)Parameters:
topicCitations(List- ): Citation data from topic channels
citationFiles(List): List of meta.yml file paths
Returns:
Map: Combined citations from both sources
Migration Example:
include { processMixedCitationSources } from 'plugin/nf-core-utils'
workflow { // Modern processes using topic channels MODERN_PROCESS(input_modern)
// Legacy processes still using file-based citations LEGACY_PROCESS(input_legacy)
// Collect from both sources def topicCitations = channel.topic('citations').collect() def legacyFiles = ['modules/legacy/old_tool/meta.yml']
// Combine both approaches during migration def allCitations = processMixedCitationSources(topicCitations, legacyFiles)
// Generate final citation text def citationText = toolCitationText(allCitations)}convertMetaYamlToTopicFormat()
Description:
Converts legacy meta.yml data to new topic channel format for migration purposes.
Function Signature:
List<List> convertMetaYamlToTopicFormat(String metaFilePath, String moduleName = null)Parameters:
metaFilePath(String): Path to meta.yml filemoduleName(String, optional): Name of the module (defaults to filename)
Returns:
List<List>: List of[module, tool, citation_data]tuples
Migration Usage:
include { convertMetaYamlToTopicFormat } from 'plugin/nf-core-utils'
// Convert existing meta.yml to topic format for consistencydef legacyMetaPath = 'modules/legacy/old_tool/meta.yml'def topicFormatCitations = convertMetaYamlToTopicFormat(legacyMetaPath, 'OLD_TOOL')
// Emit to topic channel for unified processingchannel.fromList(topicFormatCitations) .set { converted_citations_ch }Topic Channel Processing Functions
processCitationsFromTopic()
Description:
Processes citations exclusively from topic channel format (modern approach).
Function Signature:
Map processCitationsFromTopic(List<List> topicData)Parameters:
topicData(List- ): List of
[module, tool, citation_data]tuples
Returns:
Map: Processed citations map
Usage Example:
include { processCitationsFromTopic } from 'plugin/nf-core-utils'
workflow { // Pure topic channel approach PROCESS_A(input_a) PROCESS_B(input_b)
// Collect topic channel citations def citations_ch = channel.topic('citations').collect()
citations_ch.map { topicCitations -> def citations = processCitationsFromTopic(topicCitations) def citationText = toolCitationText(citations)
file("${params.outdir}/citations.txt").text = citationText }}processCitationsFromFile()
Description:
Processes citations exclusively from traditional YAML files (legacy approach).
Function Signature:
Map processCitationsFromFile(List<String> citationFiles)Parameters:
citationFiles(List): List of file paths to meta.yml files
Returns:
Map: Tool citations from files
Legacy Usage:
include { processCitationsFromFile } from 'plugin/nf-core-utils'
// Legacy file-based processingdef citationFiles = [ 'modules/nf-core/fastqc/meta.yml', 'modules/nf-core/multiqc/meta.yml']
def citations = processCitationsFromFile(citationFiles)def citationText = toolCitationText(citations)Topic Channel Migration Guide
Stage 1: Legacy File-Based Approach
Traditional approach collecting citations from all meta.yml files:
include { collectCitationsFromFiles; toolCitationText; toolBibliographyText } from 'plugin/nf-core-utils'
workflow { // Process samples with various tools FASTQC(samples) MULTIQC(reports)
// Manually collect citations from all potential modules def metaFiles = [ 'modules/nf-core/fastqc/meta.yml', 'modules/nf-core/multiqc/meta.yml' ]
// Problem: Citations included even if process didn't execute def citations = collectCitationsFromFiles(metaFiles) def citationText = toolCitationText(citations) def bibliography = toolBibliographyText(citations)}Stage 2: Mixed Migration Approach
Gradual migration supporting both approaches:
include { processMixedCitationSources; toolCitationText } from 'plugin/nf-core-utils'
workflow { // Modern processes using topic channels MODERN_FASTQC(samples) // Emits to citations topic
// Legacy processes still using manual collection LEGACY_MULTIQC(reports) // No topic channel emission
// Collect from both sources def topicCitations = channel.topic('citations').collect() def legacyFiles = ['modules/nf-core/multiqc/meta.yml']
// Combine approaches during migration def allCitations = processMixedCitationSources(topicCitations, legacyFiles) def citationText = toolCitationText(allCitations)}Stage 3: Modern Topic Channel Approach
Fully migrated with automatic runtime-accurate citations:
include { getCitation; autoToolCitationText; autoToolBibliographyText } from 'plugin/nf-core-utils'
process FASTQC { output: val citation_data, topic: citations
script: citation_data = getCitation("${moduleDir}/meta.yml") """ fastqc ${reads} """}
workflow { // All processes automatically emit citations when they execute FASTQC(samples) MULTIQC(reports)
// Automatic collection - only includes executed tools def citation_ch = channel.topic('citations').collect()
citation_ch.map { citations -> def citationText = autoToolCitationText(citations) def bibliography = autoToolBibliographyText(citations)
// Zero-maintenance: accurate citations without manual collection file("${params.outdir}/citations.txt").text = citationText file("${params.outdir}/bibliography.html").text = bibliography }}Best Practices
1. Progressive Module Migration
Migrate modules gradually to topic channels:
// Phase 1: High-priority modules firstprocess CRITICAL_ANALYSIS { output: val citation_data, topic: citations // Modernize first
script: citation_data = getCitation("${moduleDir}/meta.yml") """ # Critical analysis here """}
// Phase 2: Supporting modulesprocess SUPPORTING_TOOL { // Still using legacy approach temporarily script: """ # Supporting analysis """}
// Phase 3: Utility modules lastprocess UTILITY_PROCESS { // Convert when convenient}2. Runtime Citation Accuracy
Ensure citations reflect actual tool execution:
workflow { // Conditional processing with accurate citations if (params.run_fastqc) { FASTQC(samples) // Only emits citation if it runs }
if (params.run_multiqc) { MULTIQC(reports) // Only emits citation if it runs }
// Citations automatically match actual execution channel.topic('citations').collect().map { citations -> autoToolCitationText(citations) // Only includes tools that ran }}3. Error Handling and Graceful Degradation
Handle missing citation data gracefully:
include { getCitation; autoToolCitationText } from 'plugin/nf-core-utils'
process ROBUST_PROCESS { output: val citation_data, topic: citations
script: try { citation_data = getCitation("${moduleDir}/meta.yml") } catch (Exception e) { log.warn "Citation extraction failed for ${task.process}: ${e.message}" citation_data = ['UNKNOWN', 'unknown_tool', [description: 'Citation unavailable']] } """ # Process execution """}4. Testing Citation Functions
Test citation processing across migration stages:
test("Modern topic channel citations") { when { def topicCitations = [ ['FASTQC', 'fastqc', [doi: '10.1093/bioinformatics/btv033', author: 'Andrews S']], ['MULTIQC', 'multiqc', [doi: '10.1093/bioinformatics/btw354', author: 'Ewels P']] ] def result = autoToolCitationText(topicCitations) }
then { assert result.contains('fastqc') assert result.contains('multiqc') assert result.contains('Andrews') }}
test("Legacy file citations") { when { def citations = generateModuleToolCitation('test_meta.yml') def result = toolCitationText(citations) }
then { assert result.contains('Tools used in the workflow') assert citations.size() > 0 }}
test("Mixed citation processing") { when { def topicCitations = [['MODERN', 'modern_tool', [doi: 'test']]] def legacyFiles = ['test_legacy_meta.yml'] def result = processMixedCitationSources(topicCitations, legacyFiles) }
then { assert result.containsKey('modern_tool') // Also contains legacy citations }}Integration Examples
Complete Modern Pipeline Integration
#!/usr/bin/env nextflow
include { getCitation; autoToolCitationText; autoToolBibliographyText } from 'plugin/nf-core-utils'
// Modern citation-enabled processesprocess FASTQC { input: tuple val(meta), path(reads)
output: tuple val(meta), path("*.html"), emit: html val citation_data, topic: citations
script: citation_data = getCitation("${moduleDir}/meta.yml") """ fastqc --quiet --threads ${task.cpus} ${reads} """}
process MULTIQC { input: path('*')
output: path("multiqc_report.html"), emit: report val citation_data, topic: citations
script: citation_data = getCitation("${moduleDir}/meta.yml") """ multiqc . """}
workflow { // Process samples FASTQC(samples)
// Only run MultiQC if reports exist if (params.skip_multiqc == false) { MULTIQC(FASTQC.out.html.collect()) }
// Automatic citation collection - runtime accurate def citation_ch = channel.topic('citations').collect()
citation_ch.map { citations -> // Generate citation components def citationText = autoToolCitationText(citations) def bibliography = autoToolBibliographyText(citations)
// Write files for MultiQC template substitution file("${params.outdir}/pipeline_info/citations.txt").text = citationText file("${params.outdir}/pipeline_info/bibliography.html").text = bibliography
log.info "Generated citations for ${citations.size()} tools" }}MultiQC Methods Template Integration
include { autoToolCitationText; methodsDescriptionText } from 'plugin/nf-core-utils'
workflow { // Process with citation-enabled modules ANALYSIS_PROCESSES(data)
// Collect citations and generate methods description def citation_ch = channel.topic('citations').collect()
citation_ch.map { citations -> // Generate components def citationText = autoToolCitationText(citations) def bibliography = autoToolBibliographyText(citations)
// Create comprehensive methods description def methodsYaml = "${projectDir}/assets/methods_description_template.yml" def methodsDescription = methodsDescriptionText( methodsYaml, [ tool_citations_text: citationText, tool_bibliography_text: bibliography ], [ pipeline_name: workflow.manifest.name, pipeline_version: workflow.manifest.version, pipeline_doi: workflow.manifest.doi ?: 'N/A' ] )
// Write for MultiQC inclusion file("${params.outdir}/multiqc_methods_description.html").text = methodsDescription }}Common Issues and Solutions
Issue: Empty Citation Output
Problem:
def citations = autoToolCitationText([])// Result: "Tools used in the workflow included: ."Solution:
// Verify citations are being emittedchannel.topic('citations').view { "Citation collected: $it" }
// Check citation collectionchannel.topic('citations').collect().view { "All citations: $it" }
// Handle empty case gracefullydef citations = channel.topic('citations').collect().map { citationList -> if (citationList.isEmpty()) { return "No tool citations available." } else { return autoToolCitationText(citationList) }}Issue: Missing Module Citations
Problem:
Process doesn’t emit citations even with getCitation() call
Solution:
process DEBUG_CITATIONS { output: val citation_data, topic: citations
script: citation_data = getCitation("${moduleDir}/meta.yml")
// Debug: Log citation data log.info "Citation data for ${task.process}: ${citation_data}"
""" # Check if meta.yml exists ls -la ${moduleDir}/ """}Issue: Legacy to Modern Migration Errors
Problem: Mixed processing produces inconsistent citation formats
Solution:
// Validate citation data format before processingdef validatedCitations = topicCitations.findAll { citation -> citation instanceof List && citation.size() == 3 && citation[0] && citation[1] && citation[2]}
def citations = processCitationsFromTopic(validatedCitations)Performance Considerations
Topic Channel Benefits
- Runtime Accuracy: Only tools that execute appear in citations
- Zero Maintenance: No manual citation file management
- Better Performance: No file I/O for citation collection
- Automatic Updates: Citations update when modules change
Migration Performance
// Optimize citation processing during migrationworkflow { // Collect in parallel def topicFuture = channel.topic('citations').collect() def legacyFiles = legacy_citation_files.collect()
// Process efficiently tuple(topicFuture, legacyFiles).map { topic, files -> processMixedCitationSources(topic, files) }.set { final_citations }}For more information on citation management and topic channels, see the Nextflow documentation and nf-core modules documentation.