From 8a089e86949de3a9e3f07d19fca69476efe47126 Mon Sep 17 00:00:00 2001 From: Richard Lupat Date: Wed, 12 Jun 2024 11:27:31 +1000 Subject: [PATCH] Built site for gh-pages --- .nojekyll | 2 +- index.html | 6 +- search.json | 90 +- sessions/1_intro_run_nf.html | 4 + sessions/2_nf_dev_intro.html | 6 +- sitemap.xml | 30 +- workshops/00_setup.html | 4 + workshops/1.1_intro_nextflow.html | 4 + workshops/1.2_intro_nf_core.html | 4 + workshops/2.1_customise_and_run.html | 4 + workshops/2.2_troubleshooting.html | 4 + workshops/2.3_tips_and_tricks.html | 4 + workshops/3.1_creating_a_workflow.html | 4 + workshops/4.1_draft_future_sess.html | 4 + workshops/4.1_modules.html | 4 + workshops/5.1_nf_core_template.html | 1559 +++++++++++++++++ .../media/5.2.1_nf_core_create_github.png | Bin 0 -> 31252 bytes .../5.2.1_nf_core_create_interactive.png | Bin 0 -> 22233 bytes 18 files changed, 1707 insertions(+), 26 deletions(-) create mode 100644 workshops/5.1_nf_core_template.html create mode 100644 workshops/media/5.2.1_nf_core_create_github.png create mode 100644 workshops/media/5.2.1_nf_core_create_interactive.png diff --git a/.nojekyll b/.nojekyll index 1ef0283..f7699b0 100644 --- a/.nojekyll +++ b/.nojekyll @@ -1 +1 @@ -fa94a7b1 \ No newline at end of file +b6e73b4e \ No newline at end of file diff --git a/index.html b/index.html index 82b4eec..510a913 100644 --- a/index.html +++ b/index.html @@ -136,6 +136,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • @@ -214,7 +218,7 @@

    Curre 5th Jun 2024 -To-be-added +Working with nf-core Templates Introduction to developing bioinformatics workflow with Nextflow (Part3) 12th Jun 2024 diff --git a/search.json b/search.json index 80e99c9..c6c51df 100644 --- a/search.json +++ b/search.json @@ -11,7 +11,7 @@ "href": "index.html", "title": "Peter Mac Internal Nextflow Workshops", "section": "", - "text": "These workshops are designed to provide participants with a foundational understanding of Nextflow and nf-core pipelines. Participants are expected to have prior experience with the command-line interface and working with cluster systems like Slurm. The primary goal of the workshop is to equip researchers with the skills needed to use nextflow and nf-core pipelines for their research data.\n\nCourse Developers & Maintainers\n\nRichard Lupat, Bioinformatics Core Facility\nMiriam Yeung, Cancer Genomics Translational Research Centre\nSong Li, Bioinformatics Core Facility\nSanduni Rajapaksa, Research Computing Facility\n\n\n\nCurrent and Future Workshop Sessions\n\n\n\nLesson\nOverview\nDate\n\n\n\n\nBasic to Create a Nextflow Workflow\nIntroduction to developing bioinformatics workflow with Nextflow (Part1)\n29th May 2024\n\n\nDeveloping Modularised Workflows\nIntroduction to developing bioinformatics workflow with Nextflow (Part2)\n5th Jun 2024\n\n\nTo-be-added\nIntroduction to developing bioinformatics workflow with Nextflow (Part3)\n12th Jun 2024\n\n\nTo-be-added\nIntroduction to developing bioinformatics workflow with Nextflow (Part4)\n19th Jun 2024\n\n\n\n\n\nPast Workshop Sessions\n\n\n\nSession\nOverview\nDate\n\n\n\n\nIntroduction to Nextflow and running nf-core workflows\nIntroduction to Nextflow: Introduce nextflow’s core features and concepts + nf-core + how to run it at PeterMac\n22nd Nov 2023\n\n\nIntroduction to Nextflow and running nf-core workflows\n(Re-run) Introduction to Nextflow: Introduce nextflow’s core features and concepts + nf-core + how to run it at PeterMac\n15th May 2024\n\n\n\n\n\nCredits and acknowledgement\nThis workshop is adapted from Customising Nf-Core Workshop materials from Sydney Informatics Hub" + "text": "These workshops are designed to provide participants with a foundational understanding of Nextflow and nf-core pipelines. Participants are expected to have prior experience with the command-line interface and working with cluster systems like Slurm. The primary goal of the workshop is to equip researchers with the skills needed to use nextflow and nf-core pipelines for their research data.\n\nCourse Developers & Maintainers\n\nRichard Lupat, Bioinformatics Core Facility\nMiriam Yeung, Cancer Genomics Translational Research Centre\nSong Li, Bioinformatics Core Facility\nSanduni Rajapaksa, Research Computing Facility\n\n\n\nCurrent and Future Workshop Sessions\n\n\n\nLesson\nOverview\nDate\n\n\n\n\nBasic to Create a Nextflow Workflow\nIntroduction to developing bioinformatics workflow with Nextflow (Part1)\n29th May 2024\n\n\nDeveloping Modularised Workflows\nIntroduction to developing bioinformatics workflow with Nextflow (Part2)\n5th Jun 2024\n\n\nWorking with nf-core Templates\nIntroduction to developing bioinformatics workflow with Nextflow (Part3)\n12th Jun 2024\n\n\nTo-be-added\nIntroduction to developing bioinformatics workflow with Nextflow (Part4)\n19th Jun 2024\n\n\n\n\n\nPast Workshop Sessions\n\n\n\nSession\nOverview\nDate\n\n\n\n\nIntroduction to Nextflow and running nf-core workflows\nIntroduction to Nextflow: Introduce nextflow’s core features and concepts + nf-core + how to run it at PeterMac\n22nd Nov 2023\n\n\nIntroduction to Nextflow and running nf-core workflows\n(Re-run) Introduction to Nextflow: Introduce nextflow’s core features and concepts + nf-core + how to run it at PeterMac\n15th May 2024\n\n\n\n\n\nCredits and acknowledgement\nThis workshop is adapted from Customising Nf-Core Workshop materials from Sydney Informatics Hub" }, { "objectID": "workshops/2.3_tips_and_tricks.html", @@ -35,18 +35,74 @@ "text": "2.2.1. Nextflow log\nIt is important to keep a record of the commands you have run to generate your results. Nextflow helps with this by creating and storing metadata and logs about the run in hidden files and folders in your current directory (unless otherwise specified). This data can be used by Nextflow to generate reports. It can also be queried using the Nextflow log command:\nnextflow log\nThe log command has multiple options to facilitate the queries and is especially useful while debugging a workflow and inspecting execution metadata. You can view all of the possible log options with -h flag:\nnextflow log -h\nTo query a specific execution you can use the RUN NAME or a SESSION ID:\nnextflow log <run name>\nTo get more information, you can use the -f option with named fields. For example:\nnextflow log <run name> -f process,hash,duration\nThere are many other fields you can query. You can view a full list of fields with the -l option:\nnextflow log -l\n\n\n\n\n\n\nChallenge\n\n\n\nUse the log command to view with process, hash, and script fields for your tasks from your most recent Nextflow execution.\n\n\n\n\n\n\n\n\nSolution\n\n\n\n\n\nUse the log command to get a list of you recent executions:\nnextflow log\nTIMESTAMP DURATION RUN NAME STATUS REVISION ID SESSION ID COMMAND \n2023-11-21 22:43:14 14m 17s jovial_angela OK 3bec2331ca 319751c3-25a6-4085-845c-6da28cd771df nextflow run nf-core/rnaseq\n2023-11-21 23:05:49 1m 36s marvelous_shannon OK 3bec2331ca 319751c3-25a6-4085-845c-6da28cd771df nextflow run nf-core/rnaseq\n2023-11-21 23:10:00 1m 35s deadly_babbage OK 3bec2331ca 319751c3-25a6-4085-845c-6da28cd771df nextflow run nf-core/rnaseq\nQuery the process, hash, and script using the -f option for the most recent run:\nnextflow log marvelous_shannon -f process,hash,script\n\n[... truncated ...]\n\nNFCORE_RNASEQ:RNASEQ:SUBREAD_FEATURECOUNTS 7c/f936d4 \n featureCounts \\\n -B -C -g gene_biotype -t exon \\\n -p \\\n -T 2 \\\n -a chr22_with_ERCC92.gtf \\\n -s 2 \\\n -o HBR_Rep1_ERCC.featureCounts.txt \\\n HBR_Rep1_ERCC.markdup.sorted.bam\n\n cat <<-END_VERSIONS > versions.yml\n \"NFCORE_RNASEQ:RNASEQ:SUBREAD_FEATURECOUNTS\":\n subread: $( echo $(featureCounts -v 2>&1) | sed -e \"s/featureCounts v//g\")\n END_VERSIONS\n\n[... truncated ... ]\n\nNFCORE_RNASEQ:RNASEQ:MULTIQC 7a/8449d7 \n multiqc \\\n -f \\\n \\\n \\\n .\n\n cat <<-END_VERSIONS > versions.yml\n \"NFCORE_RNASEQ:RNASEQ:MULTIQC\":\n multiqc: $( multiqc --version | sed -e \"s/multiqc, version //g\" )\n END_VERSIONS\n \n\n\n\n\n\n2.2.2. Execution cache and resume\nTask execution caching is an essential feature of modern workflow managers. As such, Nextflow provides an automated caching mechanism for every execution. When using the Nextflow -resume option, successfully completed tasks from previous executions are skipped and the previously cached results are used in downstream tasks.\nNextflow caching mechanism works by assigning a unique ID to each task. The task unique ID is generated as a 128-bit hash value composing the the complete file path, file size, and last modified timestamp. These ID’s are used to create a separate execution directory where the tasks are executed and the outputs are stored. Nextflow will take care of the inputs and outputs in these folders for you.\nYou can re-launch the previously executed nf-core/rnaseq workflow again, but with a -resume flag, and observe the progress. Notice the time it takes to complete the workflow.\nnextflow run nf-core/rnaseq -r 3.11.1 \\\n --input samplesheet.csv \\\n --outdir ./my_results \\\n --fasta $materials/ref/chr22_with_ERCC92.fa \\\n --gtf $materials/ref/chr22_with_ERCC92.gtf \\\n -profile singularity \\\n --skip_markduplicates true \\\n --save_trimmed true \\\n --save_unaligned true \\\n --max_memory '6.GB' \\\n --max_cpus 2 \\\n -resume \n\n[80/ec6ff8] process > NFCORE_RNASEQ:RNASEQ:PREPARE_GENOME:GTF2BED (chr22_with_ERCC92.gtf) [100%] 1 of 1, cached: 1 ✔\n[1a/7bec9c] process > NFCORE_RNASEQ:RNASEQ:PREPARE_GENOME:GTF_GENE_FILTER (chr22_with_ERCC92.fa) [100%] 1 of 1, cached: 1 ✔\nExecuting this workflow will create a my_results directory with selected results files and add some further sub-directories into the work directory\nIn the schematic above, the hexadecimal numbers, such as 80/ec6ff8, identify the unique task execution. These numbers are also the prefix of the work directories where each task is executed.\nYou can inspect the files produced by a task by looking inside the work directory and using these numbers to find the task-specific execution path:\nls work/80/ec6ff8ba69a8b5b8eede3679e9f978/\nIf you look inside the work directory of a FASTQC task, you will find the files that were staged and created when this task was executed:\n>>> ls -la work/e9/60b2e80b2835a3e1ad595d55ac5bf5/ \n\ntotal 15895\ndrwxrwxr-x 2 rlupat rlupat 4096 Nov 22 03:39 .\ndrwxrwxr-x 4 rlupat rlupat 4096 Nov 22 03:38 ..\n-rw-rw-r-- 1 rlupat rlupat 0 Nov 22 03:39 .command.begin\n-rw-rw-r-- 1 rlupat rlupat 9509 Nov 22 03:39 .command.err\n-rw-rw-r-- 1 rlupat rlupat 9609 Nov 22 03:39 .command.log\n-rw-rw-r-- 1 rlupat rlupat 100 Nov 22 03:39 .command.out\n-rw-rw-r-- 1 rlupat rlupat 10914 Nov 22 03:39 .command.run\n-rw-rw-r-- 1 rlupat rlupat 671 Nov 22 03:39 .command.sh\n-rw-rw-r-- 1 rlupat rlupat 231 Nov 22 03:39 .command.trace\n-rw-rw-r-- 1 rlupat rlupat 1 Nov 22 03:39 .exitcode\nlrwxrwxrwx 1 rlupat rlupat 63 Nov 22 03:39 HBR_Rep1_ERCC_1.fastq.gz -> HBR_Rep1_ERCC-Mix2_Build37-ErccTranscripts-chr22.read1.fastq.gz\n-rw-rw-r-- 1 rlupat rlupat 2368 Nov 22 03:39 HBR_Rep1_ERCC_1.fastq.gz_trimming_report.txt\n-rw-rw-r-- 1 rlupat rlupat 697080 Nov 22 03:39 HBR_Rep1_ERCC_1_val_1_fastqc.html\n-rw-rw-r-- 1 rlupat rlupat 490526 Nov 22 03:39 HBR_Rep1_ERCC_1_val_1_fastqc.zip\n-rw-rw-r-- 1 rlupat rlupat 6735205 Nov 22 03:39 HBR_Rep1_ERCC_1_val_1.fq.gz\nlrwxrwxrwx 1 rlupat rlupat 63 Nov 22 03:39 HBR_Rep1_ERCC_2.fastq.gz -> HBR_Rep1_ERCC-Mix2_Build37-ErccTranscripts-chr22.read2.fastq.gz\n-rw-rw-r-- 1 rlupat rlupat 2688 Nov 22 03:39 HBR_Rep1_ERCC_2.fastq.gz_trimming_report.txt\n-rw-rw-r-- 1 rlupat rlupat 695591 Nov 22 03:39 HBR_Rep1_ERCC_2_val_2_fastqc.html\n-rw-rw-r-- 1 rlupat rlupat 485732 Nov 22 03:39 HBR_Rep1_ERCC_2_val_2_fastqc.zip\n-rw-rw-r-- 1 rlupat rlupat 7088948 Nov 22 03:39 HBR_Rep1_ERCC_2_val_2.fq.gz\nlrwxrwxrwx 1 rlupat rlupat 102 Nov 22 03:39 HBR_Rep1_ERCC-Mix2_Build37-ErccTranscripts-chr22.read1.fastq.gz -> /data/seqliner/test-data/rna-seq/fastq/HBR_Rep1_ERCC-Mix2_Build37-ErccTranscripts-chr22.read1.fastq.gz\nlrwxrwxrwx 1 rlupat rlupat 102 Nov 22 03:39 HBR_Rep1_ERCC-Mix2_Build37-ErccTranscripts-chr22.read2.fastq.gz -> /data/seqliner/test-data/rna-seq/fastq/HBR_Rep1_ERCC-Mix2_Build37-ErccTranscripts-chr22.read2.fastq.gz\n-rw-rw-r-- 1 rlupat rlupat 109 Nov 22 03:39 versions.yml\nThe FASTQC process runs twice, executing in a different work directories for each set of inputs. Therefore, in the previous example, the work directory [e9/60b2e8] represents just one of the four sets of input data that was processed.\nIt’s very likely you will execute a workflow multiple times as you find the parameters that best suit your data. You can save a lot of spaces (and time) by resuming a workflow from the last step that was completed successfully and/or unmodified.\nIn practical terms, the workflow is executed from the beginning. However, before launching the execution of a process, Nextflow uses the task unique ID to check if the work directory already exists and that it contains a valid command exit state with the expected output files. If this condition is satisfied, the task execution is skipped and previously computed results are used as the process results.\nNotably, the -resume functionality is very sensitive. Even touching a file in the work directory can invalidate the cache.\n\n\n\n\n\n\nChallenge\n\n\n\nInvalidate the cache by touching a .fastq.gz file in a FASTQC task work directory (you can use the touch command). Execute the workflow again with the -resume option to show that the cache has been invalidated.\n\n\n\n\n\n\n\n\nSolution\n\n\n\n\n\nExecute the workflow for the first time (if you have not already).\nUse the task ID shown for the FASTQC process and use it to find and touch a the sample1_R1.fastq.gz file:\ntouch work/ff/21abfa87cc7cdec037ce4f36807d32/HBR_Rep1_ERCC_1.fastq.gz\nExecute the workflow again with the -resume command option:\nnextflow run nf-core/rnaseq -r 3.11.1 \\\n --input samplesheet.csv \\\n --outdir ./my_results \\\n --fasta $materials/ref/chr22_with_ERCC92.fa \\\n --gtf $materials/ref/chr22_with_ERCC92.gtf \\\n -profile singularity \\\n --skip_markduplicates true \\\n --save_trimmed true \\\n --save_unaligned true \\\n --max_memory '6.GB' \\\n --max_cpus 2 \\\n -resume \nYou should see that some task were invalid and were executed again.\nWhy did this happen?\nIn this example, the cache of two FASTQC tasks were invalid. The fastq file we touch is used by in the pipeline in multiple places. Thus, touching the symlink for this file and changing the date of last modification disrupted two task executions.\n\n\n\n\n\n2.2.3. Troubleshoot warning and error messages\nWhile our previous workflow execution completed successfully, there were a couple of warning messages that may be cause for concern:\n-[nf-core/rnaseq] Pipeline completed successfully with skipped sampl(es)-\n-[nf-core/rnaseq] Please check MultiQC report: 2/2 samples failed strandedness check.-\nCompleted at: 20-Nov-2023 00:29:04\nDuration : 10m 15s\nCPU hours : 0.3 \nSucceeded : 72\n\n\n\n\n\n\nHandling dodgy error messages 🤬\n\n\n\nThe first warning message isn’t very descriptive (see this pull request). You might come across issues like this when running nf-core pipelines, too. Bug reports and user feedback is very important to open source software communities like nf-core. If you come across any issues, submit a GitHub issue or start a discussion in the relevant nf-core Slack channel so others are aware and it can be addressed by the pipeline’s developers.\n\n\n➤ Take a look at the MultiQC report, as directed by the second message. You can find the MultiQC report in the lesson2.1/ directory:\nls -la lesson2.1/multiqc/star_salmon/\ntotal 1402\ndrwxrwxr-x 4 rlupat rlupat 4096 Nov 22 00:29 .\ndrwxrwxr-x 3 rlupat rlupat 4096 Nov 22 00:29 ..\ndrwxrwxr-x 2 rlupat rlupat 8192 Nov 22 00:29 multiqc_data\ndrwxrwxr-x 5 rlupat rlupat 4096 Nov 22 00:29 multiqc_plots\n-rw-rw-r-- 1 rlupat rlupat 1419998 Nov 22 00:29 multiqc_report.html\n➤ Download the multiqc_report.html the file navigator panel on the left side of your VS Code window by right-clicking on it and then selecting Download. Open the file on your computer.\nTake a look a the section labelled WARNING: Fail Strand Check\nThe warning we have received is indicating that the read strandedness we specified in our samplesheet.csv and inferred strandedness identified by the RSeqQC process in the pipeline do not match. It looks like the test samplesheet have incorrectly specified strandedness as forward in the samplesheet.csv when our raw reads actually show an equal distribution of sense and antisense reads.\nFor those who are not familiar with RNAseq data, incorrectly specified strandedness may negatively impact the read quantification step (process: Salmon quant) and give us inaccurate results. So, let’s clarify how the Salmon quant process is gathering strandedness information for our input files by default and find a way to address this with the parameters provided by the nf-core/rnaseq pipeline.\n\n\n\n2.2.4. Identify the run command for a process\nTo observe exactly what command is being run for a process, we can attempt to infer this information from the module’s main.nf script in the modules/ directory. However, given all the different parameters that may be applied at the process level, this may not be very clear.\n➤ Take a look at the Salmon quant main.nf file:\nnf-core-rnaseq-3.11.1/workflow/modules/nf-core/salmon/quant/main.nf\nUnless you are familiar with developing nf-core pipelines, it can be very hard to see what is actually happening in the code, given all the different variables and conditional arguments inside this script. Above the script block we can see strandedness is being applied using a few different conditional arguments. Instead of trying to infer how the $strandedness variable is being defined and applied to the process, let’s use the hidden command files saved for this task in the work/ directory.\n\n\n\n\n\n\nHidden files in the work directory!\n\n\n\nRemember that the pipeline’s results are cached in the work directory. In addition to the cached files, each task execution directories inside the work directory contains a number of hidden files:\n\n.command.sh: The command script run for the task.\n.command.run: The command wrapped used to run the task.\n.command.out: The task’s standard output log.\n.command.err: The task’s standard error log.\n.command.log: The wrapper execution output.\n.command.begin: A file created as soon as the job is launched.\n.exitcode: A file containing the task exit code (0 if successful)\n\n\n\nWith nextflow log command that we discussed previously, there are multiple options to facilitate the queries and is especially useful while debugging a pipeline and while inspecting pipeline execution metadata.\nTo understand how Salmon quant is interpreting strandedness, we’re going to use this command to track down the hidden .command.sh scripts for each Salmon quant task that was run. This will allow us to find out how Salmon quant handles strandedness and if there is a way for us to override this.\n➤ Use the Nextflow log command to get the unique run name information of the previously executed pipelines:\nnextflow log <run-name>\nThat command will list out all the work subdirectories for all processes run.\nAnd we now need to find the specific hidden.command.sh for Salmon tasks. But how to find them? 🤔\n➤ Let’s add some custom bash code to query a Nextflow run with the run name from the previous lesson. First, save your run name in a bash variable. For example:\nrun_name=marvelous_shannon\n➤ And let’s save the tool of interest (salmon) in another bash variable to pull it from a run command:\ntool=salmon\n➤ Next, run the following bash command:\nnextflow log ${run_name} | while read line;\n do\n cmd=$(ls ${line}/.command.sh 2>/dev/null);\n if grep -q $tool $cmd;\n then \n echo $cmd; \n fi; \n done \nThat will list all process .command.sh scripts containing ‘salmon’. There are a few different processes that run Salmon to perform other steps in the workflow. We are looking for Salmon quant which performs the read quantification:\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/57/fba8f9a2385dac5fa31688ba1afa9b/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/30/0113a58c14ca8d3099df04ebf388f3/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/ec/95d6bd12d578c3bce22b5de4ed43fe/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/49/6fedcb09e666432ae6ddf8b1e8f488/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/b4/2ca8d05b049438262745cde92955e9/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/38/875d68dae270504138bb3d72d511a7/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/72/776810a99695b1c114cbb103f4a0e6/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/1c/dc3f54cc7952bf55e6742dd4783392/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/f3/5116a5b412bde7106645671e4c6ffb/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/17/fb0c791810f42a438e812d5c894ebf/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/4c/931a9b60b2f3cf770028854b1c673b/.command.sh\n/scratch/users/rlupat/nfWorkshop/lesson2.1/work/91/e1c99d8acb5adf295b37fd3bbc86a5/.command.sh\nCompared with the salmon quant main.nf file, we get a lot more fine scale details from the .command.sh process scripts:\n>>> cat main.nf\nsalmon quant \\\\\n --geneMap $gtf \\\\\n --threads $task.cpus \\\\\n --libType=$strandedness \\\\\n $reference \\\\\n $input_reads \\\\\n $args \\\\\n -o $prefix\n>>> cat .command.sh\nsalmon quant \\\n --geneMap chr22_with_ERCC92.gtf \\\n --threads 2 \\\n --libType=ISF \\\n -t genome.transcripts.fa \\\n -a HBR_Rep1_ERCC.Aligned.toTranscriptome.out.bam \\\n \\\n -o HBR_Rep1_ERCC\nLooking at the nf-core/rnaseq Parameter documentation and Salmon documentation, we found that we can override this default using the --salmon_quant_libtype A parameter to indicate our data is unstranded and override samplesheet.csv input.\n\n\n\n\n\n\nHow do I get rid of the strandedness check warning message?\n\n\n\nIf we want to get rid of the warning message Please check MultiQC report: 2/2 samples failed strandedness check, we’ll have to change the strandedness fields in our samplesheet.csv. Keep in mind, doing this will invalidate the pipeline’s cache and cause the pipeline to run from the beginning.\n\n\n\n\n\n2.2.5. Write a parameter file\nFrom the previous section we learn that Nextflow accepts either yaml or json formats for parameter files. Any of the pipeline-specific parameters can be supplied to a Nextflow pipeline in this way.\n\n\n\n\n\n\nChallenge\n\n\n\nFill in the parameters file below and save as workshop-params.yaml. This time, include the --salmon_quant_libtype A parameter.\n💡 YAML formatting tips!\n\nStrings need to be inside double quotes\nBooleans (true/false) and numbers do not require quotes\n\ninput: \"\"\noutdir: \"lesson2.2\"\nfasta: \"\"\ngtf: \"\"\nstar_index: \"\"\nsalmon_index: \"\"\nskip_markduplicates: \nsave_trimmed: \nsave_unaligned: \nsalmon_quant_libtype: \"A\" \n\n\n\n\n2.2.6. Apply the parameter file\n➤ Once your params file has been saved, run:\nnextflow run nf-core/rnaseq -r 3.11.1 \\\n -params-file workshop-params.yaml\n -profile singularity \\\n --max_memory '6.GB' \\\n --max_cpus 2 \\\n -resume \nThe number of pipeline-specific parameters we’ve added to our run command has been significantly reduced. The only -- parameters we’ve provided to the run command relate to how the pipeline is executed on our interative job. These resource limits won’t be applicable to others who will run the pipeline on a different infrastructure.\nAs the workflow runs a second time, you will notice 4 things:\n\nThe command is much tidier thanks to offloading some parameters to the params file\nThe -resume flag. Nextflow has lots of run options including the ability to use cached output!\nSome processes will be pulled from the cache. These processes remain unaffected by our addition of a new parameter.\n\nThis run of the pipeline will complete in a much shorter time.\n\n-[nf-core/rnaseq] Pipeline completed successfully with skipped sampl(es)-\n-[nf-core/rnaseq] Please check MultiQC report: 2/2 samples failed strandedness check.-\nCompleted at: 21-Apr-2023 05:58:06\nDuration : 1m 51s\nCPU hours : 0.3 (82.2% cached)\nSucceeded : 11\nCached : 55\n\n\nThese materials are adapted from Customising Nf-Core Workshop by Sydney Informatics Hub" }, { - "objectID": "workshops/1.1_intro_nextflow.html", - "href": "workshops/1.1_intro_nextflow.html", - "title": "Introduction to Nextflow", + "objectID": "workshops/5.1_nf_core_template.html", + "href": "workshops/5.1_nf_core_template.html", + "title": "Nextflow Development - Developing Modularised Workflows", "section": "", - "text": "Objectives\n\n\n\n\nLearn about the benefits of a workflow manager.\nLearn Nextflow terminology.\nLearn basic commands and options to run a Nextflow workflow" + "text": "Objectives\n\n\n\n\nDevelop a basic Nextflow workflow with nf-core templates\nTest and set up profiles for a Nextflow workflow\nCreate conditional processes, and conditional scripts within a processs\nRead data of different types into a Nextflow workflow" }, { - "objectID": "workshops/1.1_intro_nextflow.html#footnotes", - "href": "workshops/1.1_intro_nextflow.html#footnotes", - "title": "Introduction to Nextflow", - "section": "Footnotes", - "text": "Footnotes\n\n\nhttps://www.lexico.com/definition/workflow↩︎" + "objectID": "workshops/5.1_nf_core_template.html#environment-setup", + "href": "workshops/5.1_nf_core_template.html#environment-setup", + "title": "Nextflow Development - Developing Modularised Workflows", + "section": "Environment Setup", + "text": "Environment Setup\nSet up an interactive shell to run our Nextflow workflow:\nsrun --pty -p prod_short --mem 8GB --mincpus 2 -t 0-2:00 bash\nLoad the required modules to run Nextflow:\nmodule load nextflow/23.04.1\nmodule load singularity/3.7.3\nSet the singularity cache environment variable:\nexport NXF_SINGULARITY_CACHEDIR=/config/binaries/singularity/containers_devel/nextflow\nSingularity images downloaded by workflow executions will now be stored in this directory.\nYou may want to include these, or other environmental variables, in your .bashrc file (or alternate) that is loaded when you log in so you don’t need to export variables every session. A complete list of environment variables can be found here.\nSet up a python virtual environment with nf-core/tools installed:\nmodule load python/3.11.2\npython -m venv /scratch/users/${USER}/nfcorevenv\n\nsource /scratch/users/${USER}/nfcorevenv/bin/activate\n\npip install nf-core==2.14.1" + }, + { + "objectID": "workshops/5.1_nf_core_template.html#nf-core", + "href": "workshops/5.1_nf_core_template.html#nf-core", + "title": "Nextflow Development - Developing Modularised Workflows", + "section": "5. Nf-core", + "text": "5. Nf-core\nnf-core is a community effort to collect a curated set of analysis workflows built using Nextflow.\nnf-core provides a standardized set of best practices, guidelines, and templates for building and sharing bioinformatics workflows. These workflows are designed to be modular, scalable, and portable, allowing researchers to easily adapt and execute them using their own data and compute resources.\nThe community is a diverse group of bioinformaticians, developers, and researchers from around the world who collaborate on developing and maintaining a growing collection of high-quality workflows. These workflows cover a range of applications, including transcriptomics, proteomics, and metagenomics.\nOne of the key benefits of nf-core is that it promotes open development, testing, and peer review, ensuring that the workflows are robust, well-documented, and validated against real-world datasets. This helps to increase the reliability and reproducibility of bioinformatics analyses and ultimately enables researchers to accelerate their scientific discoveries.\nnf-core is published in Nature Biotechnology: Nat Biotechnol 38, 276–278 (2020). Nature Biotechnology\nKey Features of nf-core workflows\n\nDocumentation\n\nnf-core workflows have extensive documentation covering installation, usage, and description of output files to ensure that you won’t be left in the dark.\n\nStable Releases\n\nnf-core workflows use GitHub releases to tag stable versions of the code and software, making workflow runs totally reproducible.\n\nPackaged software\n\nPipeline dependencies are automatically downloaded and handled using Docker, Singularity, Conda, or other software management tools. There is no need for any software installations.\n\nPortable and reproducible\n\nnf-core workflows follow best practices to ensure maximum portability and reproducibility. The large community makes the workflows exceptionally well-tested and easy to execute.\n\nCloud-ready\n\nnf-core workflows are tested on AWS" + }, + { + "objectID": "workshops/5.1_nf_core_template.html#nf-core-tools", + "href": "workshops/5.1_nf_core_template.html#nf-core-tools", + "title": "Nextflow Development - Developing Modularised Workflows", + "section": "5.1 Nf-core tools", + "text": "5.1 Nf-core tools\nnf-core-tools is a python package with helper tools for the nf-core community.\nThese helper tools can be used for both building and running nf-core workflows.\nToday we will be focusing on the developer commands to build a workflow using nf-core templates and structures.\nTake a look at what is within with nf-core-tools suite\nnf-core -h\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\n\n \n Usage: nf-core [OPTIONS] COMMAND [ARGS]... \n \n nf-core/tools provides a set of helper tools for use with nf-core Nextflow pipelines. \n It is designed for both end-users running pipelines and also developers creating new pipelines. \n \n╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮\n│ --version Show the version and exit. │\n│ --verbose -v Print verbose output to the console. │\n│ --hide-progress Don't show progress bars. │\n│ --log-file -l <filename> Save a verbose log to a file. │\n│ --help -h Show this message and exit. │\n╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n╭─ Commands for users ─────────────────────────────────────────────────────────────────────────────╮\n│ list List available nf-core pipelines with local info. │\n│ launch Launch a pipeline using a web GUI or command line prompts. │\n│ create-params-file Build a parameter file for a pipeline. │\n│ download Download a pipeline, nf-core/configs and pipeline singularity images. │\n│ licences List software licences for a given workflow (DSL1 only). │\n│ tui Open Textual TUI. │\n╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n╭─ Commands for developers ────────────────────────────────────────────────────────────────────────╮\n│ create Create a new pipeline using the nf-core template. │\n│ lint Check pipeline code against nf-core guidelines. │\n│ modules Commands to manage Nextflow DSL2 modules (tool wrappers). │\n│ subworkflows Commands to manage Nextflow DSL2 subworkflows (tool wrappers). │\n│ schema Suite of tools for developers to manage pipeline schema. │\n│ create-logo Generate a logo with the nf-core logo template. │\n│ bump-version Update nf-core pipeline version number. │\n│ sync Sync a pipeline TEMPLATE branch with the nf-core template. │\n╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\nToday we will be predominately focusing on most of the tools for developers." + }, + { + "objectID": "workshops/5.1_nf_core_template.html#nf-core-pipeline", + "href": "workshops/5.1_nf_core_template.html#nf-core-pipeline", + "title": "Nextflow Development - Developing Modularised Workflows", + "section": "5.2 Nf-core Pipeline", + "text": "5.2 Nf-core Pipeline\nLet’s review the structure of the nf-core/rnaseq pipeline.\nAlmost all of the structure provided here is from the nf-core templates. As we briefly covered last week in Developing Modularised Workflows, it is good practice to separate your workflow from subworkflows and modules. As this allows you to modularise your workflows and reuse modules.\nNf-core assists in enforcing this structure with the subfolders:\n\nworkflows - contains the main workflow\nsubworkflows - contains subworkflows either as written by the nf-core community or self-written\nmodules - contains modules either as written by the nf-core community or self-written\n\nIn our Introduction to Nextflow and running nf-core workflows workshop in Customising & running nf-core pipelines, we briefly touched on configuration files in the conf/ folder and nextflow.config.\nToday we will be working on files in these locations and expanding our use of the nf-core template to include:\n\nfiles in the assets folder\nnextflow_schema.json\n\n\n\n5.2.1 nf-core create\nThe create subcommand makes a new pipeline using the nf-core base template. With a given pipeline name, description and author, it makes a starter pipeline which follows nf-core best practices.\nAfter creating the files, the command initialises the folder as a git repository and makes an initial commit. This first “vanilla” commit which is identical to the output from the templating tool is important, as it allows us to keep your pipeline in sync with the base template in the future. See the nf-core syncing docs for more information.\nLet’s set up the nf-core template for today’s workshop:\nnf-core create\nAs we progress through the interactive prompts, we will use the following values below: \nRemember to swap out the Author name with your own!\nThe creates a pipeline called myrnaseq in the directory pmcc-myrnaseq (<prefix>-<name>) with mmyeung as the author. If selected exclude the following:\n\ngithub: removed all files required for GitHub hosting of the pipeline. Specifically, the .github folder and .gitignore file.\nci: removes the GitHub continuous integration tests from the pipeline. Specifically, the .github/workflows/ folder.\ngithub_badges: removes GitHub badges from the README.md file.\nigenomes: removes pipeline options related to iGenomes. Including the conf/igenomes.config file and all references to it.\nnf_core_configs: excludes nf_core/configs repository options, which make multiple config profiles for various institutional clusters available.\n\nTo run the pipeline creation silently (i.e. without any prompts) with the nf-core template, you can use the --plain option.\n\n\n\n\n\n\nAuthor name\n\n\n\nTypically, we would use your github username as the value here, this allows an extra layer of traceability.\n\n\n\n\n\n\n\n\nCustomised pipeline prefix\n\n\n\nRemember we are currently only making the most of the nf-core templates and not contributing back to nf-core. As such, we should not use the nf-core prefix to our pipeline.\n\n\n\n\n\n\n\n\nSkipped templates\n\n\n\nNote that the highlighted values under Skip template areas? are the sections that will be skipped. As this is a test pipeline we are skipping the set up of github CI and badges\n\n\nAs we have requested GitHub hosting, on completion of the command, you will note there are suggested github commands included in the output. Use these commands to push the commits from your computer. You can then continue to edit, commit and push normally as you build your pipeline.\n\n\n\nnf-core template\nLet’s see what has been minimally provided by nf-core create\nll pmcc-myrnaseq/\ntotal 47\ndrwxrwxr-x 2 myeung myeung 4096 Jun 11 15:00 assets\n-rw-rw-r-- 1 myeung myeung 372 Jun 11 15:00 CHANGELOG.md\n-rw-rw-r-- 1 myeung myeung 2729 Jun 11 15:00 CITATIONS.md\ndrwxrwxr-x 2 myeung myeung 4096 Jun 11 15:00 conf\ndrwxrwxr-x 3 myeung myeung 4096 Jun 11 15:00 docs\n-rw-rw-r-- 1 myeung myeung 1060 Jun 11 15:00 LICENSE\n-rw-rw-r-- 1 myeung myeung 3108 Jun 11 15:00 main.nf\ndrwxrwxr-x 3 myeung myeung 4096 Jun 11 15:00 modules\n-rw-rw-r-- 1 myeung myeung 1561 Jun 11 15:00 modules.json\n-rw-rw-r-- 1 myeung myeung 9982 Jun 11 15:00 nextflow.config\n-rw-rw-r-- 1 myeung myeung 16657 Jun 11 15:00 nextflow_schema.json\n-rw-rw-r-- 1 myeung myeung 3843 Jun 11 15:00 README.md\ndrwxrwxr-x 4 myeung myeung 4096 Jun 11 15:00 subworkflows\n-rw-rw-r-- 1 myeung myeung 165 Jun 11 15:00 tower.yml\ndrwxrwxr-x 2 myeung myeung 4096 Jun 11 15:00 workflows\nAs you take look through the files created you will see many comments through the files starting with // TODO nf-core. These are pointers from nf-core towards areas of the pipeline that you may be intersted in changing.\nThey are also the “key word” used by the nf-core lint.\n\nAlternative setups for nf-core create\nAside from the interactive setup we have just completed for nf-core create, there are two alternative methods.\n\nProvide the option using the optional flags from nf-core create\nProvide a template.yaml via the --template-yaml option\n\n\n\n\n\n\n\nChallenge\n\n\n\nCreate a second pipeline template using the optional flags with the name “myworkflow”, provide a description, author name and set the version to “0.0.1”\nWhat options are still you still prompted for?\n\n\n\n\n\n\n\n\nSolution\n\n\n\n\n\nRun the following:\nnf-core create --name myworkflow --description \"my workflow test\" --author \"@mmyeung\" --version \"0.0.1\"\nNote that you are still prompted for any additional customisations such as the pipeline prefix and steps to skip\n\n\n\n\n\n\n\n\n\nAdvanced Challange\n\n\n\nCreate another pipeline template using a yaml file called mytemplate.yaml\nHint: the key values in the yaml should be name, description, author, prefix and skip\nSet the pipeline to skip ci, igenomes and nf_core_configs\n\n\n\n\n\n\n\n\nSolution\n\n\n\n\n\nRun the following:\nvim mytemplate.yaml\nValues in mytemplate.yaml\nname: coolpipe\ndescription: A cool pipeline\nauthor: me\nprefix: myorg\nskip:\n - ci\n - igenomes\n - nf_core_configs\nnf-core create --template-yaml mytemplate.yaml" + }, + { + "objectID": "workshops/5.1_nf_core_template.html#test-profile", + "href": "workshops/5.1_nf_core_template.html#test-profile", + "title": "Nextflow Development - Developing Modularised Workflows", + "section": "5.3 Test Profile", + "text": "5.3 Test Profile\nnf-core tries to encourage software engineering concepts such as minimal test sets, this can be set up using the conf/test.config and conf/test_full.config\nFor the duration of this workshop we will be making use of the conf/test.config, to test our pipeline.\nLet’s take a look at what is currently in the conf/test.config.\ncat pmcc-myrnaseq/conf/test.config\n/*\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n Nextflow config file for running minimal tests\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n Defines input files and everything required to run a fast and simple pipeline test.\n\n Use as follows:\n nextflow run pmcc/myrnaseq -profile test,<docker/singularity> --outdir <OUTDIR>\n\n----------------------------------------------------------------------------------------\n*/\n\nparams {\n config_profile_name = 'Test profile'\n config_profile_description = 'Minimal test dataset to check pipeline function'\n\n // Limit resources so that this can run on GitHub Actions\n max_cpus = 2\n max_memory = '6.GB'\n max_time = '6.h'\n\n // Input data\n // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets\n // TODO nf-core: Give any required params for the test so that command line flags are not needed\n input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv'\n\n // Genome references\n genome = 'R64-1-1'\n}\nFrom this, we can see that this config uses the params scope to define:\n\nMaximal values for resources\nDirects the input parameter to a sample sheet hosted in the nf-core/testdata github\nSets the genome to “R64-1-1”\n\n\n\n\n\n\n\nHow does setting the parameter genome set all the genome references?\n\n\n\nThis is possible due to us using the igenomes configs from nf-core.\nYou can see in the conf/igenomes.config how nested within each genome definition are paths to various reference files.\nTo find out more about the igenomes project here\n\n\nFor the duration of this workshop we are going to use the data from nf-training that was cloned in the first workshop. We are also going to update our test.config to contain the igenomes_base parameter, as we have a local cache on the cluster.\ninput = \"/home/Shared/For_NF_Workshop/training/nf-training/data/ggal/samplesheet.csv\"\noutdir = \"/scratch/users/${USER}/myrnaseqtest\"\n\n// genome references\ngenome = \"GRCh38\"\nigenomes_base = \"/data/janis/nextflow/references/genomes/ngi-igenomes\"\nAlso, we will need to change the value, custom_config_base to null, in nextflow.config\ncustom_config_base = null\nLet’s quickly check that our pipeline runs with the test profile.\ncd ..\nnextflow run ./pmcc-myrnaseq -profile test,singularity\n\n\n\n\n\n\nWhat’s the difference between the test.config and the test_full.config\n\n\n\nTypically the test.config contains the minimal test example, while the test_full.config contains at least one full sized example data." + }, + { + "objectID": "workshops/5.1_nf_core_template.html#nf-core-modules", + "href": "workshops/5.1_nf_core_template.html#nf-core-modules", + "title": "Nextflow Development - Developing Modularised Workflows", + "section": "5.4 Nf-core modules", + "text": "5.4 Nf-core modules\nYou can find all the nf-core modules that have been accepted and peer-tested by the community in nf-core modules.\nor with\nnf-core modules list remote\nyou can check which modules are installed localling in your pipeline by running nf-core modules list local, within the pipeline folder.\ncd pmcc-myrnaseq\n\nnf-core modules list local\n\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\n\nINFO Repository type: pipeline\nINFO Modules installed in '.':\n┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓\n┃ Module Name ┃ Repository ┃ Version SHA ┃ Message ┃ Date ┃\n┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩\n│ fastqc │ nf-core/modules │ 285a505 │ Fix FastQC memory allocation (#5432) │ 2024-04-05 │\n│ multiqc │ nf-core/modules │ b7ebe95 │ Update MQC container (#5006) │ 2024-02-29 │\n└─────────────┴─────────────────┴─────────────┴──────────────────────────────────────┴────────────┘\n\n\n\n\n\n\nOverall Challenge\n\n\n\nWe are going to replicate sections of the workflow from last week.\nFASTQC -> Trimgalore -> FASTQC -> MULTIQC\n\n\n\n5.3.1 Installing nf-core modules\nThe general format for installing modules is as below.\nnf-core modules install <tool>/<subcommand>\n\n\n\n\n\n\nTip\n\n\n\nNote that if you search for the modules on the nf-core modules website, you can find the install command at the top of the tool\n\n\n\n\n\n\n\n\nTip\n\n\n\nRemember to run the install commands from within the nf-core pipeline folder (in this case the pmcc-myrnaseq folder)\nIf you are not in an nf-core folder you will see the following error\n\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\n\nWARNING 'repository_type' not defined in .nf-core.yml\n? Is this repository an nf-core pipeline or a fork of nf-core/modules? (Use arrow keys)\n » Pipeline\n nf-core/modules\n\n\n\n\n\n\n\n\nChallenge\n\n\n\nInstall the following nf-core modules\n\ntrimgalore\nsalmon quant\nfastqc\n\nWhat happens when we try to install the fastqc module?\n\n\n\n\n\n\n\n\nSolution\n\n\n\n\n\nUnfortunately, nf-core does not allow the installation of multiple modules in one line therefore we mush provide the commands separately for each module.\nnf-core modules install trimgalore\nnf-core modules install salmon/quant\nnf-core modules install fastqc\nNote that from above, when we checked which modules have been installed locally in our pipeline, fastqc was already installed. As such, we see the following output warning us that fastqc is installed and we can either force the reinstallation or we can update the module\n\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\nINFO Module 'fastqc' is already installed.\nINFO To update 'fastqc' run 'nf-core modules update fastqc'. To force reinstallation use '--force'. \n\n\n\n\n\n\n\n\n\nAdvanced Challenge\n\n\n\nCan you think of a way to streamline the installation of modules?\n\n\nfollowing the installation what files changed, check with\ngit status\nOn branch master\nChanges not staged for commit:\n (use \"git add <file>...\" to update what will be committed)\n (use \"git restore <file>...\" to discard changes in working directory)\n modified: modules.json\n\nUntracked files:\n (use \"git add <file>...\" to include in what will be committed)\n modules/nf-core/salmon/\n modules/nf-core/trimgalore/\n\nno changes added to commit (use \"git add\" and/or \"git commit -a\")\nmodules.json is a running record of the modules installed and should be included in your pipeline. Note: you can find the github SHA for the exact “version” of the module installed.\nThis insulates your pipeline from when a module is deleted.\nrm -r modules/nf-core/salmon/quant\n\nnf-core modules list local\n\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\n\nINFO Repository type: pipeline\nINFO Reinstalling modules found in 'modules.json' but missing from directory: 'modules/nf-core/salmon/quant'\nINFO Modules installed in '.':\n┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓\n┃ Module Name ┃ Repository ┃ Version SHA ┃ Message ┃ Date ┃\n┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩\n│ fastqc │ nf-core/modules │ 285a505 │ Fix FastQC memory allocation (#5432) │ 2024-04-05 │\n│ multiqc │ nf-core/modules │ b7ebe95 │ Update MQC container (#5006) │ 2024-02-29 │\n│ salmon/quant │ nf-core/modules │ cb6b2b9 │ fix stubs salmon (#5517) │ 2024-04-24 │\n│ trimgalore │ nf-core/modules │ a984184 │ run nf-core lint on trimgalore (#5129) │ 2024-03-15 │\n└──────────────┴─────────────────┴─────────────┴────────────────────────────────────────┴────────────┘\n\n\n\n\n\n\nAdvanced Challenge\n\n\n\nHow would you look up previous versions of the module?\n\n\n\n\n\n\n\n\nCaution\n\n\n\n\n\nThere are a few ways to approach this.\n\nYou could hop onto github and search throught the git history for the main.nf of the particular module, to identify the git SHA and provide it to the --sha flag.\nYou could run the install command with the --prompt flag, as seen below\n\n\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\n\nINFO Module 'fastqc' is already installed.\n? Module fastqc is already installed.\nDo you want to force the reinstallation? Yes\n? Select 'fastqc' commit: (Use arrow keys)\n Fix FastQC memory allocation (#5432) 285a50500f9e02578d90b3ce6382ea3c30216acd (installed version)\n Update FASTQC to use unique names for snapshots (#4825) f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c\n CHORES: update fasqc tests with new data organisation (#4760) c9488585ce7bd35ccd2a30faa2371454c8112fb9\n fix fastqc tests n snap (#4669) 617777a807a1770f73deb38c80004bac06807eef\n Update version strings (#4556) 65ad3e0b9a4099592e1102e92e10455dc661cf53\n Remove pytest-workflow tests for modules covered by nf-test (#4521) 3e8b0c1144ccf60b7848efbdc2be285ff20b49ee\n Add conda environment names (#4327) 3f5420aa22e00bd030a2556dfdffc9e164ec0ec5\n Fix conda declaration (#4252) 8fc1d24c710ebe1d5de0f2447ec9439fd3d9d66a\n Move conda environment to yml (#4079) 516189e968feb4ebdd9921806988b4c12b4ac2dc\n authors => maintainers (#4173) cfd937a668919d948f6fcbf4218e79de50c2f36f\n » older commits\n\n\n\n\n\n5.3.2 Updating nf-core modules\nAbove we got and error message for fastq because the module was already installed. As listed in the output, one of the suggested solutions is that we might be looking to update the module\nnf-core modules update fastqc\nAfter running the command you will find that you are prompted for whether you wish to view the differences between the current installation and the update.\n\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\n\n? Do you want to view diffs of the proposed changes? (Use arrow keys)\n » No previews, just update everything\n Preview diff in terminal, choose whether to update files\n Just write diffs to a patch file\nFor the sake of this exercise, we are going to roll fastqc back by one commit.\nIf you select the 2nd option Preview diff in terminal, choose whether to update files\nnf-core modules update fastqc -p\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\n\n? Do you want to view diffs of the proposed changes? Preview diff in terminal, choose whether to update files\n? Select 'fastqc' commit: (Use arrow keys)\n Fix FastQC memory allocation (#5432) 285a50500f9e02578d90b3ce6382ea3c30216acd (installed version)\n » Update FASTQC to use unique names for snapshots (#4825) f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c\n CHORES: update fasqc tests with new data organisation (#4760) c9488585ce7bd35ccd2a30faa2371454c8112fb9\n fix fastqc tests n snap (#4669) 617777a807a1770f73deb38c80004bac06807eef\n Update version strings (#4556) 65ad3e0b9a4099592e1102e92e10455dc661cf53\n Remove pytest-workflow tests for modules covered by nf-test (#4521) 3e8b0c1144ccf60b7848efbdc2be285ff20b49ee\n Add conda environment names (#4327) 3f5420aa22e00bd030a2556dfdffc9e164ec0ec5\n Fix conda declaration (#4252) 8fc1d24c710ebe1d5de0f2447ec9439fd3d9d66a\n Move conda environment to yml (#4079) 516189e968feb4ebdd9921806988b4c12b4ac2dc\n authors => maintainers (#4173) cfd937a668919d948f6fcbf4218e79de50c2f36f\n older commits\n? Select 'fastqc' commit: Update FASTQC to use unique names for snapshots (#4825) f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c\nINFO Changes in module 'nf-core/fastqc' between (285a50500f9e02578d90b3ce6382ea3c30216acd) and (f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c)\nINFO Changes in 'fastqc/main.nf':\n --- modules/nf-core/fastqc/main.nf\n +++ modules/nf-core/fastqc/main.nf\n @@ -25,11 +25,6 @@\n def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, \"${prefix}.${reads.extension}\" ]] : reads.withIndex().collect { entry, index -> [ entry, \"${prefix}_${index + 1}.${entry.extension}\" ] }\n def rename_to = old_new_pairs*.join(' ').join(' ')\n def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ')\n -\n - def memory_in_mb = MemoryUnit.of(\"${task.memory}\").toUnit('MB')\n - // FastQC memory value allowed range (100 - 10000)\n - def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb)\n -\n \"\"\"\n printf \"%s %s\\\\n\" $rename_to | while read old_name new_name; do\n [ -f \"\\${new_name}\" ] || ln -s \\$old_name \\$new_name\n @@ -38,7 +33,6 @@\n fastqc \\\\\n $args \\\\\n --threads $task.cpus \\\\\n - --memory $fastqc_memory \\\\\n $renamed_files\n\n cat <<-END_VERSIONS > versions.yml\nINFO 'modules/nf-core/fastqc/meta.yml' is unchanged\nINFO 'modules/nf-core/fastqc/environment.yml' is unchanged\nINFO 'modules/nf-core/fastqc/tests/main.nf.test.snap' is unchanged\nINFO 'modules/nf-core/fastqc/tests/tags.yml' is unchanged\nINFO 'modules/nf-core/fastqc/tests/main.nf.test' is unchanged\n? Update module 'fastqc'? No\nINFO Updates complete ✨ \n\n\n5.3.3 Removing nf-core modules\nAs mentioned above, if you decide that you don’t need a module anymore, you can’t just remove the folder with rm -r.\nFor nf-core to no longer register the module is to be distributed with your pipeline you need to use:\nnf-core modules remove\nAs an exercise, we are going to install the samtools/sort module\nnf-core modules install samtools/sort\nQuickly view the modules.json or use nf-core modules list local to view the changes from installing the module.\nNow remove the samtools/sort module\nnf-core modules remove samtools/sort\n\n\n\n\n\n\nOverall Challenge\n\n\n\nNow add the include module statements to the our workflows/myrnaseq.nf\n\n\n\n\n\n\n\n\nCaution\n\n\n\n\n\ninclude { FASTQC as FASTQC_one } from '../modules/nf-core/fastq/main' \ninclude { FASTQC as FASTQC_two } from '../modules/nf-core/fastq/main' \n\ninclude { TRIMGALORE } from '../modules/nf-core/trimgalore/main'\n\n\n\n\n\n5.3.4 Writing modules with nf-core template\nFor this section we are going to refer to the nf-core guidelines for modules.\nWhile these are the full guidelines for contributing back to nf-core, there are still some general components that are good practice even if you are NOT planning to contribute.\n\n\n\n\n\n\nSummary of guidelines\n\n\n\n\nAll required and optional input files must be included in the input as a path variable\nThe command should run without any additional argument, any required flag values should be included as an input val variable\ntask.ext.args must be provided as a variable\nWhere possible all input and output files should be compressed (i.e. fastq.gz and .bam)\nA versions.yml file is output\nNaming conventions include using all lowercase without puntuation and follows the convention of software/tool (i.e. bwa/mem)\nAll outputs must include an emit definition\n\n\n\nWe are going to write up our own samtools/view module.\nnf-core modules create \n\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\n\nINFO Repository type: pipeline\nINFO Press enter to use default values (shown in brackets) or type your own responses. ctrl+click underlined text to open links.\nName of tool/subtool: samtools/view\nINFO Using Bioconda package: 'bioconda::samtools=1.20'\nINFO Could not find a Docker/Singularity container (Unexpected response code `500` for https://api.biocontainers.pro/ga4gh/trs/v2/tools/samtools/versions/samtools-1.20) ## Cluster\nGitHub Username: (@author): @mmyeung\nINFO Provide an appropriate resource label for the process, taken from the nf-core pipeline template.\n For example: process_single, process_low, process_medium, process_high, process_long\n? Process resource label: process_low\nINFO Where applicable all sample-specific information e.g. 'id', 'single_end', 'read_group' MUST be provided as an input via a Groovy Map called\n 'meta'. This information may not be required in some instances, for example indexing reference genome files.\nWill the module require a meta map of sample information? [y/n] (y): y\nINFO Created component template: 'samtools/view'\nINFO Created following files:\n modules/local/samtools/view.nf\nAs we progressed through the interactive prompt, you will have noticed that nf-core always attempts to locate the corresponding bioconda package and singularity/Docker container.\n\n\n\n\n\n\nWhat happens when there is no bioconda package or container?\n\n\n\n\n\nnf-core modules create --author @mmyeung --label process_single --meta testscript\nThe command will indicate that the there is no bioconda package with the software name, and prompt you for a package name you might wish to use.\nINFO Repository type: pipeline\nINFO Press enter to use default values (shown in brackets) or type your own responses. ctrl+click underlined text to open links.\nWARNING Could not find Conda dependency using the Anaconda API: 'testscript'\nDo you want to enter a different Bioconda package name? [y/n]: n\nWARNING Could not find Conda dependency using the Anaconda API: 'testscript'\n Building module without tool software and meta, you will need to enter this information manually.\nINFO Created component template: 'testscript'\nINFO Created following files:\n modules/local/testscript.nf \nwithin the module .nf script you will note that the definitions for the conda and container are incomplete for the tool.\n conda \"${moduleDir}/environment.yml\"\n container \"${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?\n 'https://depot.galaxyproject.org/singularity/YOUR-TOOL-HERE':\n 'biocontainers/YOUR-TOOL-HERE' }\"\nnf-core has a large cache of containers here. Though you can also provide a simple path to docker hub.\n container \"mmyeung/trccustomunix:0.0.1\"\n\n\n\nThe resource labels, are those as defined in conf/base.config\n\n\n\n\n\n\nChallenge\n\n\n\nWrite up the inputs, outputs and script for samtools/view.\nAssume that all the inputs will be .bam and the outputs will also be .bam.\nFor reference look at the documentation for samtools/view\nAre there optional flags that take file inputs? What options need to set to ensure that the command runs without error?\n\n\n\n\n\n\n\n\nCaution\n\n\n\n\n\nprocess SAMTOOLS_VIEW {\n tag \"$meta.id\"\n label 'process_low'\n\n conda \"${moduleDir}/environment.yml\"\n container \"${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?\n 'https://depot.galaxyproject.org/singularity/samtools:1.20--h50ea8bc_0' :\n 'biocontainers/samtools:1.20--h50ea8bc_0' }\"\n\n input:\n tuple val(meta), path(input), path(index)\n tuple val(meta2), path(fasta)\n path bed\n path qname\n\n output:\n tuple val(meta), path(\"*.bam\"), emit: bam\n path \"versions.yml\", emit: versions\n\n when:\n task.ext.when == null || task.ext.when\n\n script:\n def args = task.ext.args ?: ''\n def args2 = task.ext.args2 ?: ''\n def prefix = task.ext.prefix ?: \"${meta.id}\"\n def reference = fasta ? \"--reference ${fasta}\" : \"\"\n def readnames = qname ? \"--qname-file ${qname}\": \"\"\n def regions = bed ? \"-L ${bed}\": \"\"\n if (\"$input\" == \"${prefix}.${file_type}\") error \"Input and output names are the same, use \\\"task.ext.prefix\\\" to disambiguate!\"\n \"\"\"\n samtools \\\\\n view \\\\\n -hb \\\\\n --threads ${task.cpus-1} \\\\\n ${reference} \\\\\n ${readnames} \\\\\n ${regions} \\\\\n $args \\\\\n -o ${prefix}.bam \\\\\n $input \\\\\n $args2\n\n cat <<-END_VERSIONS > versions.yml\n \"${task.process}\":\n samtools: \\$(echo \\$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\\$//')\n END_VERSIONS\n \"\"\"\n\n stub:\n def args = task.ext.args ?: ''\n def prefix = task.ext.prefix ?: \"${meta.id}\"\n def file_type = args.contains(\"--output-fmt sam\") ? \"sam\" :\n args.contains(\"--output-fmt bam\") ? \"bam\" :\n args.contains(\"--output-fmt cram\") ? \"cram\" :\n input.getExtension()\n if (\"$input\" == \"${prefix}.${file_type}\") error \"Input and output names are the same, use \\\"task.ext.prefix\\\" to disambiguate!\"\n\n def index = args.contains(\"--write-index\") ? \"touch ${prefix}.csi\" : \"\"\n\n \"\"\"\n touch ${prefix}.${file_type}\n ${index}\n\n cat <<-END_VERSIONS > versions.yml\n \"${task.process}\":\n samtools: \\$(echo \\$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\\$//')\n END_VERSIONS\n \"\"\"\n\n\n\nSimilar to nf-core create you can minimise a the number of prompts by using optional flags.\n\n\n\n\n\n\nOverall Challenge\n\n\n\nWrite up the short workflow as discussed above\nFASTQC -> trimgalore -> FASTQC -> MULTIQC" + }, + { + "objectID": "workshops/5.1_nf_core_template.html#nf-core-subworkflow", + "href": "workshops/5.1_nf_core_template.html#nf-core-subworkflow", + "title": "Nextflow Development - Developing Modularised Workflows", + "section": "5.4 Nf-core subworkflow", + "text": "5.4 Nf-core subworkflow\nnf-core subworkflows\nor with\nnf-core subworkflows list remote\n\n5.4.1 Installing nf-core subworkflows\nSubworkflows can be updated/removed like modules\n\n\n\n\n\n\nChallenge\n\n\n\nInstall the subworkflow fastq_subsample_fq_salmon into the workflow\n\n\n\n\n\n\n\n\nCaution\n\n\n\n\n\nnf-core subworkflows install fastq_subsample_fq_salmon\n\n\n\n\n\n5.4.2 Writing subworkflows with nf-core template\n\n\n\n\n\n\nChallenge\n\n\n\nWrite up the QC_WF subworkflow from last week." + }, + { + "objectID": "workshops/5.1_nf_core_template.html#nf-core-schema-and-input-validation", + "href": "workshops/5.1_nf_core_template.html#nf-core-schema-and-input-validation", + "title": "Nextflow Development - Developing Modularised Workflows", + "section": "5.5 Nf-core schema and input validation", + "text": "5.5 Nf-core schema and input validation\nRelies on plugins written by nf-core community\nIn particular nf-validation\nnextflow_schmea.json is for pipeline parameters\nnf-core schema build\n\n ,--./,-.\n ___ __ __ __ ___ /,-._.--~\\\n |\\ | |__ __ / ` / \\ |__) |__ } {\n | \\| | \\__, \\__/ | \\ |___ \\`-._,-`-,\n `._,._,'\n\n nf-core/tools version 2.14.1 - https://nf-co.re\n\n\nINFO [✓] Default parameters match schema validation\nINFO [✓] Pipeline schema looks valid (found 32 params)\nINFO Writing schema with 32 params: 'nextflow_schema.json'\n🚀 Launch web builder for customisation and editing? [y/n]: y\nINFO Opening URL: https://nf-co.re/pipeline_schema_builder?id=1718112529_0841fa08f86f\nINFO Waiting for form to be completed in the browser. Remember to click Finished when you're done.\n⢿ Use ctrl+c to stop waiting and force exit.\nRecommend writing in web browser\njson format details additional reading\n\n\n\n\n\n\nChallenge\n\n\n\nWe are going add the input parameter for the transcript.fa\nThen install salmon/index and write up quant_wf subworkflow from last week.git\n\n\n\n5.5.2 Nf-core inputs\nnested in this schema is the input or samplesheet schema. unfortunately there isn’t a nice interface to help you write this schema yet.\n\nmeta: Allows you to predesignate the “key” with in the “meta”\nrequired: value must be included\ndependency: value is dependant on other value existing in samplesheet (i.e. fastq_2 must imply there is a fastq_1)\n\n\n\n5.6 Nf-core tools for launching\ncreate-params-file\n\n\n5.7 Nf-core for pipeline management\nbump-version ==> good software management to note down versions" + }, + { + "objectID": "workshops/5.1_nf_core_template.html#contributing-to-nf-core", + "href": "workshops/5.1_nf_core_template.html#contributing-to-nf-core", + "title": "Nextflow Development - Developing Modularised Workflows", + "section": "Contributing to nf-core", + "text": "Contributing to nf-core\nFull pipelines Please see the nf-core documentation for a full walkthrough of how to create a new nf-core workflow.\n\nThis workshop is adapted from Fundamentals Training, Advanced Training, Developer Tutorials, Nextflow Patterns materials from Nextflow, nf-core nf-core tools documentation and nf-validation" }, { "objectID": "workshops/3.1_creating_a_workflow.html", @@ -69,6 +125,20 @@ "section": "Creating an RNAseq Workflow", "text": "Creating an RNAseq Workflow\n\n\n\n\n\n\nObjectives\n\n\n\n\nDevelop a Nextflow workflow\nRead data of different types into a Nextflow workflow\nOutput Nextflow process results to a predefined directory\n\n\n\n\n4.1.1. Define Workflow Parameters\nLet’s create a Nextflow script rnaseq.nf for a RNA-seq workflow. The code begins with a shebang, which declares Nextflow as the interpreter.\n#!/usr/bin/env nextflow\nOne way to define the workflow parameters is inside the Nextflow script.\nparams.reads = \"/.../training/nf-training/data/ggal/*_{1,2}.fq\"\nparams.transcriptome_file = \"/.../training/nf-training/data/ggal/transcriptome.fa\"\nparams.multiqc = \"/.../training/nf-training/multiqc\"\n\nprintln \"reads: $params.reads\"\nWorkflow parameters can be defined and accessed inside the Nextflow script by prepending the prefix params to a variable name, separated by a dot character, eg. params.reads.\nDifferent data types can be assigned as a parameter in Nextflow. The reads parameter is defined as multiple .fq files. The transcriptome_file parameter is defined as one file, /.../training/nf-training/data/ggal/transcriptome.fa. The multiqc parameter is defined as a directory, /.../training/nf-training/data/ggal/multiqc.\nThe Groovy println command is then used to print the contents of the reads parameter, which is access with the $ character.\nRun the script:\n>>> nextflow run rnaseq.nf\nN E X T F L O W ~ version 23.04.1\nLaunching `rnaseq.nf` [astonishing_raman] DSL2 - revision: 8c9adc1772\nreads: /.../training/nf-training/data/ggal/*_{1,2}.fq\n\n\n\n4.1.2. Create a transcriptome index file\nCommands or scripts can be executed inside a process.\nprocess INDEX {\n input:\n path transcriptome\n\n output:\n path \"salmon_idx\"\n\n script:\n \"\"\"\n salmon index --threads $task.cpus -t $transcriptome -i salmon_idx\n \"\"\"\n}\nThe INDEX process takes an input path, and assigns that input as the variable transcriptome. The path type qualifier will allow Nextflow to stage the files in the process execution directory, where they can be accessed by the script via the defined variable name, ie. transcriptome. The code between the three double-quotes of the script block will be executed, and accesses the input transcriptome variable using $. The output is a path, with a filename salmon_idx. The output path can also be defined using wildcards, eg. path \"*_idx\".\nNote that the name of the input file is not used and is only referenced to by the input variable name. This feature allows pipeline tasks to be self-contained and decoupled from the execution environment. As best practice, avoid referencing files that are not defined in the process script.\nTo execute the INDEX process, a workflow scope will need to be added.\nworkflow {\n index_ch = INDEX(params.transcriptome_file)\n}\nHere, the params.transcriptome_file parameter we defined earlier in the Nextflow script is used as an input into the INDEX process. The output of the process is assigned to the index_ch channel.\nRun the Nextflow script:\n>>> nextflow run rnaseq.nf\n\nERROR ~ Error executing process > 'INDEX'\n\nCaused by:\n Process `INDEX` terminated with an error exit status (127)\n\nCommand executed:\n\n salmon index --threads 1 -t transcriptome.fa -i salmon_index\n\nCommand exit status:\n 127\n\nCommand output:\n (empty)\n\nCommand error:\n .command.sh: line 2: salmon: command not found\n\nWork dir:\n /.../work/85/495a21afcaaf5f94780aff6b2a964c\n\nTip: you can try to figure out what's wrong by changing to the process work dir and showing the script file named `.command.sh`\n\n -- Check '.nextflow.log' file for details\nWhen a process execution exits with a non-zero exit status, the workflow will be stopped. Nextflow will output the cause of the error, the command that caused the error, the exit status, the standard output (if available), the comand standard error, and the work directory where the process was executed.\nLet’s first look inside the process execution directory:\n>>> ls -a /.../work/85/495a21afcaaf5f94780aff6b2a964c \n\n. .command.begin .command.log .command.run .exitcode\n.. .command.err .command.out .command.sh transcriptome.fa\nWe can see that the input file transcriptome.fa has been staged inside this process execution directory by being symbolically linked. This allows it to be accessed by the script.\nInside the .command.err script, we can see that the salmon command was not found, resulting in the termination of the Nextflow workflow.\nSingularity containers can be used to execute the process within an environment that contains the package of interest. Create a config file nextflow.config containing the following:\nsingularity {\n enabled = true\n autoMounts = true\n cacheDir = \"/config/binaries/singularity/containers_devel/nextflow\"\n}\nThe container process directive can be used to specify the required container:\nprocess INDEX {\n container \"/config/binaries/singularity/containers_devel/nextflow/depot.galaxyproject.org-singularity-salmon-1.10.1--h7e5ed60_0.img\"\n\n input:\n path transcriptome\n\n output:\n path \"salmon_idx\"\n\n script:\n \"\"\"\n salmon index --threads $task.cpus -t $transcriptome -i salmon_idx\n \"\"\"\n}\nRun the Nextflow script:\n>>> nextflow run rnaseq.nf\nN E X T F L O W ~ version 23.04.1\nLaunching `rnaseq.nf` [distraught_goldwasser] DSL2 - revision: bdebf34e16\nexecutor > local (1)\n[37/7ef8f0] process > INDEX [100%] 1 of 1 ✔\nThe newly created nextflow.config files does not need to be specified in the nextflow run command. This file is automatically searched for and used by Nextflow.\nAn alternative to singularity containers is the use of a module. Since the script block is executed as a Bash script, it can contain any command or script normally executed on the command line. If there is a module present in the host environment, it can be loaded as part of the process script.\nprocess INDEX {\n input:\n path transcriptome\n\n output:\n path \"salmon_idx\"\n\n script:\n \"\"\"\n module purge\n module load salmon/1.3.0\n\n salmon index --threads $task.cpus -t $transcriptome -i salmon_idx\n \"\"\"\n}\nRun the Nextflow script:\n>>> nextflow run rnaseq.nf\nN E X T F L O W ~ version 23.04.1\nLaunching `rnaseq.nf` [reverent_liskov] DSL2 - revision: b74c22049d\nexecutor > local (1)\n[ba/3c12ab] process > INDEX [100%] 1 of 1 ✔\n\n\n\n4.1.3. Collect Read Files By Pairs\nPreviously, we have defined the reads parameter to be the following:\nparams.reads = \"/.../training/nf-training/data/ggal/*_{1,2}.fq\"\nChallenge: Convert the reads parameter into a tuple channel called reads_ch, where the first element is a unique grouping key, and the second element is the paired .fq files. Then, view the contents of reads_ch\n\n\n\n\n\n\nAnswer\n\n\n\n\n\nreads_ch = Channel.fromFilePairs(\"$params.reads\")\nreads_ch.view()\nThe fromFilePairs channel factory will automatically group input files into a tuple with a unique grouping key. The view() channel operator can be used to view the contents of the channel.\n>>> nextflow run rnaseq.nf\n\n[gut, [/.../training/nf-training/data/ggal/gut_1.fq, /.../training/nf-training/data/ggal/gut_2.fq]]\n[liver, [/.../training/nf-training/data/ggal/liver_1.fq, /.../training/nf-training/data/ggal/liver_2.fq]]\n[lung, [/.../training/nf-training/data/ggal/lung_1.fq, /.../training/nf-training/data/ggal/lung_2.fq]]\n\n\n\n\n\n4.1.4. Perform Expression Quantification\nLet’s add a new process QUANTIFICATION that uses both the indexed transcriptome file and the .fq file pairs to execute the salmon quant command.\nprocess QUANTIFICATION {\n input:\n path salmon_index\n tuple val(sample_id), path(reads)\n\n output:\n path \"$sample_id\"\n\n script:\n \"\"\"\n salmon quant --threads $task.cpus --libType=U \\\n -i $salmon_index -1 ${reads[0]} -2 ${reads[1]} -o $sample_id\n \"\"\"\n}\nThe QUANTIFICATION process takes two inputs, the first is the path to the salmon_index created from the INDEX process. The second input is set to match the output of fromFilePairs – a tuple where the first element is a value (ie. grouping key), and the second element is a list of paths to the .fq reads.\nIn the script block, the salmon quant command saves the output of the tool as $sample_id. This output is emitted by the QUANTIFICATION process, using $ to access the Nextflow variable.\nChallenge:\nSet the following as the execution container for QUANTIFICATION:\n/config/binaries/singularity/containers_devel/nextflow/depot.galaxyproject.org-singularity-salmon-1.10.1--h7e5ed60_0.img\nAssign index_ch and reads_ch as the inputs to this process, and emit the process outputs as quant_ch. View the contents of quant_ch\n\n\n\n\n\n\nAnswer\n\n\n\n\n\nTo assign a container to a process, the container directive can be used.\nprocess QUANTIFICATION {\n container \"/config/binaries/singularity/containers_devel/nextflow/depot.galaxyproject.org-singularity-salmon-1.10.1--h7e5ed60_0.img\"\n\n input:\n path salmon_index\n tuple val(sample_id), path(reads)\n\n output:\n path \"$sample_id\"\n\n script:\n \"\"\"\n salmon quant --threads $task.cpus --libType=U \\\n -i $salmon_index -1 ${reads[0]} -2 ${reads[1]} -o $sample_id\n \"\"\"\n}\nTo run the QUANTIFICATION process and emit the outputs as quant_ch, the following can be added to the end of the workflow block:\nquant_ch = QUANTIFICATION(index_ch, reads_ch)\nquant_ch.view()\nThe script can now be run:\n>>> nextflow run rnaseq.nf \nN E X T F L O W ~ version 23.04.1\nLaunching `rnaseq.nf` [elated_cray] DSL2 - revision: abe41f4f69\nexecutor > local (4)\n[e5/e75095] process > INDEX [100%] 1 of 1 ✔\n[4c/68a000] process > QUANTIFICATION (1) [100%] 3 of 3 ✔\n/.../work/b1/d861d26d4d36864a17d2cec8d67c80/liver\n/.../work/b4/a6545471c1f949b2723d43a9cce05f/lung\n/.../work/4c/68a000f7c6503e8ae1fe4d0d3c93d8/gut\nIn the Nextflow output, we can see that the QUANTIFICATION process has been ran three times, since the reads_ch consists of three elements. Nextflow will automatically run the QUANTIFICATION process on each of the elements in the input channel, creating separate process execution work directories for each execution.\n\n\n\n\n\n4.1.5. Quality Control\nNow, let’s implement a FASTQC quality control process for the input fastq reads.\nChallenge:\nCreate a process called FASTQC that takes reads_ch as an input, and declares the process input to be a tuple matching the structure of reads_ch, where the first element is assigned the variable sample_id, and the second variable is assigned the variable reads. This FASTQC process will first create an output directory fastqc_${sample_id}_logs, then perform fastqc on the input reads and save the results in the newly created directory fastqc_${sample_id}_logs:\nmkdir fastqc_${sample_id}_logs\nfastqc -o fastqc_${sample_id}_logs -f fastq -q ${reads}\nTake fastqc_${sample_id}_logs as the output of the process, and assign it to the channel fastqc_ch. Finally, specify the process container to be the following:\n/config/binaries/singularity/containers_devel/nextflow/depot.galaxyproject.org-singularity-fastqc-0.12.1--hdfd78af_0.img\n\n\n\n\n\n\nAnswer\n\n\n\n\n\nThe process FASTQC is created in rnaseq.nf. Since the input channel is a tuple, the process input declaration is a tuple containing elements that match the structure of the incoming channel. The first element of the tuple is assigned the variable sample_id, and the second element of the tuple is assigned the variable reads. The relevant container is specified using the container process directive.\nprocess FASTQC {\n container \"/config/binaries/singularity/containers_devel/nextflow/depot.galaxyproject.org-singularity-fastqc-0.12.1--hdfd78af_0.img\"\n\n input:\n tuple val(sample_id), path(reads)\n\n output:\n path \"fastqc_${sample_id}_logs\"\n\n script:\n \"\"\"\n mkdir fastqc_${sample_id}_logs\n fastqc -o fastqc_${sample_id}_logs -f fastq -q ${reads}\n \"\"\"\n}\nIn the workflow scope, the following can be added:\nfastqc_ch = FASTQC(reads_ch)\nThe FASTQC process is called, taking reads_ch as an input. The output of the process is assigned to be fastqc_ch.\n>>> nextflow run rnaseq.nf\nN E X T F L O W ~ version 23.04.1\nLaunching `rnaseq.nf` [sad_jennings] DSL2 - revision: cfae7ccc0e\nexecutor > local (7)\n[b5/6bece3] process > INDEX [100%] 1 of 1 ✔\n[32/46f20b] process > QUANTIFICATION (3) [100%] 3 of 3 ✔\n[44/27aa8d] process > FASTQC (2) [100%] 3 of 3 ✔\nIn the Nextflow output, we can see that the FASTQC has been ran three times as expected, since the reads_ch consists of three elements.\n\n\n\n\n\n4.1.6. MultiQC Report\nSo far, the generated outputs have all been saved inside the Nextflow work directory. For the FASTQC process, the specified output directory is only created inside the process execution directory. To save results to a specified folder, the publishDir process directive can be used.\nLet’s create a new MULTIQC process in our workflow that takes the outputs from the QUANTIFICATION and FASTQC processes to create a final report using the multiqc tool, and publish the process outputs to a directory outside of the process execution directory.\nprocess MULTIQC {\n publishDir params.outdir, mode:'copy'\n container \"/config/binaries/singularity/containers_devel/nextflow/depot.galaxyproject.org-singularity-multiqc-1.21--pyhdfd78af_0.img\"\n\n input:\n path quantification\n path fastqc\n\n output:\n path \"*.html\"\n\n script:\n \"\"\"\n multiqc . --filename $quantification\n \"\"\"\n}\nIn the MULTIQC process, the multiqc command is performed on both quantification and fastqc inputs, and publishes the report to a directory defined by the outdir parameter. Only files that match the declaration in the output block are published, not all the outputs of a process. By default, files are published to the target folder creating a symbolic link to the file produced in the process execution directory. This behavior can be modified using the mode option, eg. copy, which copies the file from the process execution directory to the specified output directory.\nAdd the following to the end of workflow scope:\nmultiqc_ch = MULTIQC(quant_ch, fastqc_ch)\nRun the pipeline, specifying an output directory using the outdir parameter:\nnextflow run rnaseq.nf --outdir \"results\"\nA results directory containing the output multiqc reports will be created outside of the process execution directory.\n>>> ls results\ngut.html liver.html lung.html\n\n\n\n\n\n\n\nKey points\n\n\n\n\nCommands or scripts can be executed inside a process\nEnvironments can be defined using the container process directive\nThe input declaration for a process must match the structure of the channel that is being passed into that process\n\n\n\n\nThis workshop is adapted from Fundamentals Training, Advanced Training, Developer Tutorials, and Nextflow Patterns materials from Nextflow and nf-core\n^*Draft for Future Sessions" }, + { + "objectID": "workshops/1.1_intro_nextflow.html", + "href": "workshops/1.1_intro_nextflow.html", + "title": "Introduction to Nextflow", + "section": "", + "text": "Objectives\n\n\n\n\nLearn about the benefits of a workflow manager.\nLearn Nextflow terminology.\nLearn basic commands and options to run a Nextflow workflow" + }, + { + "objectID": "workshops/1.1_intro_nextflow.html#footnotes", + "href": "workshops/1.1_intro_nextflow.html#footnotes", + "title": "Introduction to Nextflow", + "section": "Footnotes", + "text": "Footnotes\n\n\nhttps://www.lexico.com/definition/workflow↩︎" + }, { "objectID": "workshops/4.1_draft_future_sess.html", "href": "workshops/4.1_draft_future_sess.html", diff --git a/sessions/1_intro_run_nf.html b/sessions/1_intro_run_nf.html index 5a02e24..c27ea35 100644 --- a/sessions/1_intro_run_nf.html +++ b/sessions/1_intro_run_nf.html @@ -136,6 +136,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/sessions/2_nf_dev_intro.html b/sessions/2_nf_dev_intro.html index 89320b3..cebf6c2 100644 --- a/sessions/2_nf_dev_intro.html +++ b/sessions/2_nf_dev_intro.html @@ -136,6 +136,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • @@ -262,7 +266,7 @@

    Workshop schedule

    5th Jun 2024 -Working with nf-core Templates +Working with nf-core Templates Introduction to developing nextflow workflow with nf-core templates 12th Jun 2024 diff --git a/sitemap.xml b/sitemap.xml index 9a03f0c..eb83333 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,50 +2,54 @@ https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/sessions/2_nf_dev_intro.html - 2024-06-05T01:14:15.516Z + 2024-06-12T01:27:30.337Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/index.html - 2024-06-05T01:14:14.739Z + 2024-06-12T01:27:29.555Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/2.3_tips_and_tricks.html - 2024-06-05T01:14:13.126Z + 2024-06-12T01:27:27.940Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/1.2_intro_nf_core.html - 2024-06-05T01:14:12.280Z + 2024-06-12T01:27:27.088Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/2.2_troubleshooting.html - 2024-06-05T01:14:10.690Z + 2024-06-12T01:27:25.519Z - https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/1.1_intro_nextflow.html - 2024-06-05T01:14:09.608Z + https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/5.1_nf_core_template.html + 2024-06-12T01:27:24.444Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/3.1_creating_a_workflow.html - 2024-06-05T01:14:08.992Z + 2024-06-12T01:27:22.488Z + + + https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/1.1_intro_nextflow.html + 2024-06-12T01:27:23.094Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/4.1_draft_future_sess.html - 2024-06-05T01:14:09.996Z + 2024-06-12T01:27:24.838Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/4.1_modules.html - 2024-06-05T01:14:11.525Z + 2024-06-12T01:27:26.330Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/00_setup.html - 2024-06-05T01:14:12.669Z + 2024-06-12T01:27:27.480Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/workshops/2.1_customise_and_run.html - 2024-06-05T01:14:14.390Z + 2024-06-12T01:27:29.196Z https://PMCC-BioinformaticsCore.github.io/nextflow-intro-workshop/sessions/1_intro_run_nf.html - 2024-06-05T01:14:15.120Z + 2024-06-12T01:27:29.939Z diff --git a/workshops/00_setup.html b/workshops/00_setup.html index 2b6545c..e6b951e 100644 --- a/workshops/00_setup.html +++ b/workshops/00_setup.html @@ -170,6 +170,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/workshops/1.1_intro_nextflow.html b/workshops/1.1_intro_nextflow.html index 47044d3..38ab512 100644 --- a/workshops/1.1_intro_nextflow.html +++ b/workshops/1.1_intro_nextflow.html @@ -170,6 +170,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/workshops/1.2_intro_nf_core.html b/workshops/1.2_intro_nf_core.html index 6ad7aed..c5e41ed 100644 --- a/workshops/1.2_intro_nf_core.html +++ b/workshops/1.2_intro_nf_core.html @@ -170,6 +170,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/workshops/2.1_customise_and_run.html b/workshops/2.1_customise_and_run.html index 8f54609..9abd893 100644 --- a/workshops/2.1_customise_and_run.html +++ b/workshops/2.1_customise_and_run.html @@ -170,6 +170,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/workshops/2.2_troubleshooting.html b/workshops/2.2_troubleshooting.html index 03b617c..803c4f7 100644 --- a/workshops/2.2_troubleshooting.html +++ b/workshops/2.2_troubleshooting.html @@ -170,6 +170,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/workshops/2.3_tips_and_tricks.html b/workshops/2.3_tips_and_tricks.html index d229d06..c1240ae 100644 --- a/workshops/2.3_tips_and_tricks.html +++ b/workshops/2.3_tips_and_tricks.html @@ -170,6 +170,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/workshops/3.1_creating_a_workflow.html b/workshops/3.1_creating_a_workflow.html index d81c526..b8f89f9 100644 --- a/workshops/3.1_creating_a_workflow.html +++ b/workshops/3.1_creating_a_workflow.html @@ -170,6 +170,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/workshops/4.1_draft_future_sess.html b/workshops/4.1_draft_future_sess.html index 16dbc84..aa88555 100644 --- a/workshops/4.1_draft_future_sess.html +++ b/workshops/4.1_draft_future_sess.html @@ -170,6 +170,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/workshops/4.1_modules.html b/workshops/4.1_modules.html index 2eccb3e..a6d8355 100644 --- a/workshops/4.1_modules.html +++ b/workshops/4.1_modules.html @@ -170,6 +170,10 @@
  • Modularisation +
  • +
  • + + Nf-core Template
  • diff --git a/workshops/5.1_nf_core_template.html b/workshops/5.1_nf_core_template.html new file mode 100644 index 0000000..dd0f2fc --- /dev/null +++ b/workshops/5.1_nf_core_template.html @@ -0,0 +1,1559 @@ + + + + + + + + + +Peter Mac Nextflow Workshop - Nextflow Development - Developing Modularised Workflows + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    + +
    + + + + +
    + +
    +
    +

    Nextflow Development - Developing Modularised Workflows

    +
    + + + +
    + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +Objectives +
    +
    +
    +
      +
    • Develop a basic Nextflow workflow with nf-core templates
    • +
    • Test and set up profiles for a Nextflow workflow
    • +
    • Create conditional processes, and conditional scripts within a processs
    • +
    • Read data of different types into a Nextflow workflow
    • +
    +
    +
    +
    +

    Environment Setup

    +

    Set up an interactive shell to run our Nextflow workflow:

    +
    srun --pty -p prod_short --mem 8GB --mincpus 2 -t 0-2:00 bash
    +

    Load the required modules to run Nextflow:

    +
    module load nextflow/23.04.1
    +module load singularity/3.7.3
    +

    Set the singularity cache environment variable:

    +
    export NXF_SINGULARITY_CACHEDIR=/config/binaries/singularity/containers_devel/nextflow
    +

    Singularity images downloaded by workflow executions will now be stored in this directory.

    +

    You may want to include these, or other environmental variables, in your .bashrc file (or alternate) that is loaded when you log in so you don’t need to export variables every session. A complete list of environment variables can be found here.

    +

    Set up a python virtual environment with nf-core/tools installed:

    +
    module load python/3.11.2
    +python -m venv /scratch/users/${USER}/nfcorevenv
    +
    +source /scratch/users/${USER}/nfcorevenv/bin/activate
    +
    +pip install nf-core==2.14.1
    +
    +
    +

    5. Nf-core

    +

    nf-core is a community effort to collect a curated set of analysis workflows built using Nextflow.

    +

    nf-core provides a standardized set of best practices, guidelines, and templates for building and sharing bioinformatics workflows. These workflows are designed to be modular, scalable, and portable, allowing researchers to easily adapt and execute them using their own data and compute resources.

    +

    The community is a diverse group of bioinformaticians, developers, and researchers from around the world who collaborate on developing and maintaining a growing collection of high-quality workflows. These workflows cover a range of applications, including transcriptomics, proteomics, and metagenomics.

    +

    One of the key benefits of nf-core is that it promotes open development, testing, and peer review, ensuring that the workflows are robust, well-documented, and validated against real-world datasets. This helps to increase the reliability and reproducibility of bioinformatics analyses and ultimately enables researchers to accelerate their scientific discoveries.

    +

    nf-core is published in Nature Biotechnology: Nat Biotechnol 38, 276–278 (2020). Nature Biotechnology

    +

    Key Features of nf-core workflows

    +
      +
    • Documentation +
        +
      • nf-core workflows have extensive documentation covering installation, usage, and description of output files to ensure that you won’t be left in the dark.
      • +
    • +
    • Stable Releases +
        +
      • nf-core workflows use GitHub releases to tag stable versions of the code and software, making workflow runs totally reproducible.
      • +
    • +
    • Packaged software +
        +
      • Pipeline dependencies are automatically downloaded and handled using Docker, Singularity, Conda, or other software management tools. There is no need for any software installations.
      • +
    • +
    • Portable and reproducible +
        +
      • nf-core workflows follow best practices to ensure maximum portability and reproducibility. The large community makes the workflows exceptionally well-tested and easy to execute.
      • +
    • +
    • Cloud-ready +
        +
      • nf-core workflows are tested on AWS
      • +
    • +
    +
    +
    +

    5.1 Nf-core tools

    +

    nf-core-tools is a python package with helper tools for the nf-core community.

    +

    These helper tools can be used for both building and running nf-core workflows.

    +

    Today we will be focusing on the developer commands to build a workflow using nf-core templates and structures.

    +

    Take a look at what is within with nf-core-tools suite

    +
    nf-core -h
    +
                                              ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +
    +                                                                                                    
    + Usage: nf-core [OPTIONS] COMMAND [ARGS]...                                                         
    +                                                                                                    
    + nf-core/tools provides a set of helper tools for use with nf-core Nextflow pipelines.              
    + It is designed for both end-users running pipelines and also developers creating new pipelines.    
    +                                                                                                    
    +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
    +│ --version                        Show the version and exit.                                      │
    +│ --verbose        -v              Print verbose output to the console.                            │
    +│ --hide-progress                  Don't show progress bars.                                       │
    +│ --log-file       -l  <filename>  Save a verbose log to a file.                                   │
    +│ --help           -h              Show this message and exit.                                     │
    +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
    +╭─ Commands for users ─────────────────────────────────────────────────────────────────────────────╮
    +│ list                  List available nf-core pipelines with local info.                          │
    +│ launch                Launch a pipeline using a web GUI or command line prompts.                 │
    +│ create-params-file    Build a parameter file for a pipeline.                                     │
    +│ download              Download a pipeline, nf-core/configs and pipeline singularity images.      │
    +│ licences              List software licences for a given workflow (DSL1 only).                   │
    +│ tui                   Open Textual TUI.                                                          │
    +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
    +╭─ Commands for developers ────────────────────────────────────────────────────────────────────────╮
    +│ create            Create a new pipeline using the nf-core template.                              │
    +│ lint              Check pipeline code against nf-core guidelines.                                │
    +│ modules           Commands to manage Nextflow DSL2 modules (tool wrappers).                      │
    +│ subworkflows      Commands to manage Nextflow DSL2 subworkflows (tool wrappers).                 │
    +│ schema            Suite of tools for developers to manage pipeline schema.                       │
    +│ create-logo       Generate a logo with the nf-core logo template.                                │
    +│ bump-version      Update nf-core pipeline version number.                                        │
    +│ sync              Sync a pipeline TEMPLATE branch with the nf-core template.                     │
    +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
    +

    Today we will be predominately focusing on most of the tools for developers.

    +
    +
    +

    5.2 Nf-core Pipeline

    +

    Let’s review the structure of the nf-core/rnaseq pipeline.

    +

    Almost all of the structure provided here is from the nf-core templates. As we briefly covered last week in Developing Modularised Workflows, it is good practice to separate your workflow from subworkflows and modules. As this allows you to modularise your workflows and reuse modules.

    +

    Nf-core assists in enforcing this structure with the subfolders:

    +
      +
    • workflows - contains the main workflow
    • +
    • subworkflows - contains subworkflows either as written by the nf-core community or self-written
    • +
    • modules - contains modules either as written by the nf-core community or self-written
    • +
    +

    In our Introduction to Nextflow and running nf-core workflows workshop in Customising & running nf-core pipelines, we briefly touched on configuration files in the conf/ folder and nextflow.config.

    +

    Today we will be working on files in these locations and expanding our use of the nf-core template to include:

    +
      +
    • files in the assets folder
    • +
    • nextflow_schema.json
    • +
    • +
    +
    +

    5.2.1 nf-core create

    +

    The create subcommand makes a new pipeline using the nf-core base template. With a given pipeline name, description and author, it makes a starter pipeline which follows nf-core best practices.

    +

    After creating the files, the command initialises the folder as a git repository and makes an initial commit. This first “vanilla” commit which is identical to the output from the templating tool is important, as it allows us to keep your pipeline in sync with the base template in the future. See the nf-core syncing docs for more information.

    +

    Let’s set up the nf-core template for today’s workshop:

    +
    nf-core create
    +

    As we progress through the interactive prompts, we will use the following values below:

    +

    Remember to swap out the Author name with your own!

    +

    The creates a pipeline called myrnaseq in the directory pmcc-myrnaseq (<prefix>-<name>) with mmyeung as the author. If selected exclude the following:

    +
      +
    • github: removed all files required for GitHub hosting of the pipeline. Specifically, the .github folder and .gitignore file.
    • +
    • ci: removes the GitHub continuous integration tests from the pipeline. Specifically, the .github/workflows/ folder.
    • +
    • github_badges: removes GitHub badges from the README.md file.
    • +
    • igenomes: removes pipeline options related to iGenomes. Including the conf/igenomes.config file and all references to it.
    • +
    • nf_core_configs: excludes nf_core/configs repository options, which make multiple config profiles for various institutional clusters available.
    • +
    +

    To run the pipeline creation silently (i.e. without any prompts) with the nf-core template, you can use the --plain option.

    +
    +
    +
    + +
    +
    +Author name +
    +
    +
    +

    Typically, we would use your github username as the value here, this allows an extra layer of traceability.

    +
    +
    +
    +
    +
    + +
    +
    +Customised pipeline prefix +
    +
    +
    +

    Remember we are currently only making the most of the nf-core templates and not contributing back to nf-core. As such, we should not use the nf-core prefix to our pipeline.

    +
    +
    +
    +
    +
    + +
    +
    +Skipped templates +
    +
    +
    +

    Note that the highlighted values under Skip template areas? are the sections that will be skipped. As this is a test pipeline we are skipping the set up of github CI and badges

    +
    +
    +

    As we have requested GitHub hosting, on completion of the command, you will note there are suggested github commands included in the output. Use these commands to push the commits from your computer. You can then continue to edit, commit and push normally as you build your pipeline.

    +

    +
    +
    +

    nf-core template

    +

    Let’s see what has been minimally provided by nf-core create

    +
    ll pmcc-myrnaseq/
    +
    total 47
    +drwxrwxr-x 2 myeung myeung  4096 Jun 11 15:00 assets
    +-rw-rw-r-- 1 myeung myeung   372 Jun 11 15:00 CHANGELOG.md
    +-rw-rw-r-- 1 myeung myeung  2729 Jun 11 15:00 CITATIONS.md
    +drwxrwxr-x 2 myeung myeung  4096 Jun 11 15:00 conf
    +drwxrwxr-x 3 myeung myeung  4096 Jun 11 15:00 docs
    +-rw-rw-r-- 1 myeung myeung  1060 Jun 11 15:00 LICENSE
    +-rw-rw-r-- 1 myeung myeung  3108 Jun 11 15:00 main.nf
    +drwxrwxr-x 3 myeung myeung  4096 Jun 11 15:00 modules
    +-rw-rw-r-- 1 myeung myeung  1561 Jun 11 15:00 modules.json
    +-rw-rw-r-- 1 myeung myeung  9982 Jun 11 15:00 nextflow.config
    +-rw-rw-r-- 1 myeung myeung 16657 Jun 11 15:00 nextflow_schema.json
    +-rw-rw-r-- 1 myeung myeung  3843 Jun 11 15:00 README.md
    +drwxrwxr-x 4 myeung myeung  4096 Jun 11 15:00 subworkflows
    +-rw-rw-r-- 1 myeung myeung   165 Jun 11 15:00 tower.yml
    +drwxrwxr-x 2 myeung myeung  4096 Jun 11 15:00 workflows
    +

    As you take look through the files created you will see many comments through the files starting with // TODO nf-core. These are pointers from nf-core towards areas of the pipeline that you may be intersted in changing.

    +

    They are also the “key word” used by the nf-core lint.

    +
    +

    Alternative setups for nf-core create

    +

    Aside from the interactive setup we have just completed for nf-core create, there are two alternative methods.

    +
      +
    1. Provide the option using the optional flags from nf-core create
    2. +
    3. Provide a template.yaml via the --template-yaml option
    4. +
    +
    +
    +
    + +
    +
    +Challenge +
    +
    +
    +

    Create a second pipeline template using the optional flags with the name “myworkflow”, provide a description, author name and set the version to “0.0.1”

    +

    What options are still you still prompted for?

    +
    +
    +
    + +
    +
    +

    Run the following:

    +
    nf-core create --name myworkflow --description "my workflow test" --author "@mmyeung" --version "0.0.1"
    +

    Note that you are still prompted for any additional customisations such as the pipeline prefix and steps to skip

    +
    +
    +
    +
    +
    +
    + +
    +
    +Advanced Challange +
    +
    +
    +

    Create another pipeline template using a yaml file called mytemplate.yaml

    +

    Hint: the key values in the yaml should be name, description, author, prefix and skip

    +

    Set the pipeline to skip ci, igenomes and nf_core_configs

    +
    +
    +
    + +
    +
    +

    Run the following:

    +
    vim mytemplate.yaml
    +

    Values in mytemplate.yaml

    +
    name: coolpipe
    +description: A cool pipeline
    +author: me
    +prefix: myorg
    +skip:
    +  - ci
    +  - igenomes
    +  - nf_core_configs
    +
    nf-core create --template-yaml mytemplate.yaml
    +
    +
    +
    +
    +
    +
    +
    +

    5.3 Test Profile

    +

    nf-core tries to encourage software engineering concepts such as minimal test sets, this can be set up using the conf/test.config and conf/test_full.config

    +

    For the duration of this workshop we will be making use of the conf/test.config, to test our pipeline.

    +

    Let’s take a look at what is currently in the conf/test.config.

    +
    cat pmcc-myrnaseq/conf/test.config
    +
    /*
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    +    Nextflow config file for running minimal tests
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    +    Defines input files and everything required to run a fast and simple pipeline test.
    +
    +    Use as follows:
    +        nextflow run pmcc/myrnaseq -profile test,<docker/singularity> --outdir <OUTDIR>
    +
    +----------------------------------------------------------------------------------------
    +*/
    +
    +params {
    +    config_profile_name        = 'Test profile'
    +    config_profile_description = 'Minimal test dataset to check pipeline function'
    +
    +    // Limit resources so that this can run on GitHub Actions
    +    max_cpus   = 2
    +    max_memory = '6.GB'
    +    max_time   = '6.h'
    +
    +    // Input data
    +    // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets
    +    // TODO nf-core: Give any required params for the test so that command line flags are not needed
    +    input  = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv'
    +
    +    // Genome references
    +    genome = 'R64-1-1'
    +}
    +

    From this, we can see that this config uses the params scope to define:

    +
      +
    • Maximal values for resources
    • +
    • Directs the input parameter to a sample sheet hosted in the nf-core/testdata github
    • +
    • Sets the genome to “R64-1-1”
    • +
    +
    +
    +
    + +
    +
    +How does setting the parameter genome set all the genome references? +
    +
    +
    +

    This is possible due to us using the igenomes configs from nf-core.

    +

    You can see in the conf/igenomes.config how nested within each genome definition are paths to various reference files.

    +

    To find out more about the igenomes project here

    +
    +
    +

    For the duration of this workshop we are going to use the data from nf-training that was cloned in the first workshop. We are also going to update our test.config to contain the igenomes_base parameter, as we have a local cache on the cluster.

    +
    input = "/home/Shared/For_NF_Workshop/training/nf-training/data/ggal/samplesheet.csv"
    +outdir = "/scratch/users/${USER}/myrnaseqtest"
    +
    +// genome references
    +genome = "GRCh38"
    +igenomes_base = "/data/janis/nextflow/references/genomes/ngi-igenomes"
    +

    Also, we will need to change the value, custom_config_base to null, in nextflow.config

    +
    custom_config_base         = null
    +

    Let’s quickly check that our pipeline runs with the test profile.

    +
    cd ..
    +nextflow run ./pmcc-myrnaseq -profile test,singularity
    +
    +
    +
    + +
    +
    +What’s the difference between the test.config and the test_full.config +
    +
    +
    +

    Typically the test.config contains the minimal test example, while the test_full.config contains at least one full sized example data.

    +
    +
    +
    +
    +

    5.4 Nf-core modules

    +

    You can find all the nf-core modules that have been accepted and peer-tested by the community in nf-core modules.

    +

    or with

    +
    nf-core modules list remote
    +

    you can check which modules are installed localling in your pipeline by running nf-core modules list local, within the pipeline folder.

    +
    cd pmcc-myrnaseq
    +
    +nf-core modules list local
    +
    
    +                                          ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +
    +INFO     Repository type: pipeline
    +INFO     Modules installed in '.':
    +┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
    +┃ Module Name ┃ Repository      ┃ Version SHA ┃ Message                              ┃ Date       ┃
    +┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
    +│ fastqc      │ nf-core/modules │ 285a505     │ Fix FastQC memory allocation (#5432) │ 2024-04-05 │
    +│ multiqc     │ nf-core/modules │ b7ebe95     │ Update MQC container (#5006)         │ 2024-02-29 │
    +└─────────────┴─────────────────┴─────────────┴──────────────────────────────────────┴────────────┘
    +
    +
    +
    + +
    +
    +Overall Challenge +
    +
    +
    +

    We are going to replicate sections of the workflow from last week.

    +

    FASTQC -> Trimgalore -> FASTQC -> MULTIQC

    +
    +
    +
    +

    5.3.1 Installing nf-core modules

    +

    The general format for installing modules is as below.

    +
    nf-core modules install <tool>/<subcommand>
    +
    +
    +
    + +
    +
    +Tip +
    +
    +
    +

    Note that if you search for the modules on the nf-core modules website, you can find the install command at the top of the tool

    +
    +
    +
    +
    +
    + +
    +
    +Tip +
    +
    +
    +

    Remember to run the install commands from within the nf-core pipeline folder (in this case the pmcc-myrnaseq folder)

    +

    If you are not in an nf-core folder you will see the following error

    +
    
    +                                          ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +
    +WARNING  'repository_type' not defined in .nf-core.yml
    +? Is this repository an nf-core pipeline or a fork of nf-core/modules? (Use arrow keys)
    + » Pipeline
    +   nf-core/modules
    +
    +
    +
    +
    +
    + +
    +
    +Challenge +
    +
    +
    +

    Install the following nf-core modules

    +
      +
    • trimgalore
    • +
    • salmon quant
    • +
    • fastqc
    • +
    +

    What happens when we try to install the fastqc module?

    +
    +
    +
    + +
    +
    +

    Unfortunately, nf-core does not allow the installation of multiple modules in one line therefore we mush provide the commands separately for each module.

    +
    nf-core modules install trimgalore
    +nf-core modules install salmon/quant
    +nf-core modules install fastqc
    +

    Note that from above, when we checked which modules have been installed locally in our pipeline, fastqc was already installed. As such, we see the following output warning us that fastqc is installed and we can either force the reinstallation or we can update the module

    +
    
    +                                          ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +INFO     Module 'fastqc' is already installed.
    +INFO     To update 'fastqc' run 'nf-core modules update fastqc'. To force reinstallation use '--force'. 
    +
    +
    +
    +
    +
    +
    + +
    +
    +Advanced Challenge +
    +
    +
    +

    Can you think of a way to streamline the installation of modules?

    +
    +
    +

    following the installation what files changed, check with

    +
    git status
    +
    On branch master
    +Changes not staged for commit:
    +  (use "git add <file>..." to update what will be committed)
    +  (use "git restore <file>..." to discard changes in working directory)
    +        modified:   modules.json
    +
    +Untracked files:
    +  (use "git add <file>..." to include in what will be committed)
    +        modules/nf-core/salmon/
    +        modules/nf-core/trimgalore/
    +
    +no changes added to commit (use "git add" and/or "git commit -a")
    +

    modules.json is a running record of the modules installed and should be included in your pipeline. Note: you can find the github SHA for the exact “version” of the module installed.

    +

    This insulates your pipeline from when a module is deleted.

    +
    rm -r modules/nf-core/salmon/quant
    +
    +nf-core modules list local
    +
    
    +                                          ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +
    +INFO     Repository type: pipeline
    +INFO     Reinstalling modules found in 'modules.json' but missing from directory: 'modules/nf-core/salmon/quant'
    +INFO     Modules installed in '.':
    +┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
    +┃ Module Name  ┃ Repository      ┃ Version SHA ┃ Message                                ┃ Date       ┃
    +┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
    +│ fastqc       │ nf-core/modules │ 285a505     │ Fix FastQC memory allocation (#5432)   │ 2024-04-05 │
    +│ multiqc      │ nf-core/modules │ b7ebe95     │ Update MQC container (#5006)           │ 2024-02-29 │
    +│ salmon/quant │ nf-core/modules │ cb6b2b9     │ fix stubs salmon (#5517)               │ 2024-04-24 │
    +│ trimgalore   │ nf-core/modules │ a984184     │ run nf-core lint on trimgalore (#5129) │ 2024-03-15 │
    +└──────────────┴─────────────────┴─────────────┴────────────────────────────────────────┴────────────┘
    +
    +
    +
    + +
    +
    +Advanced Challenge +
    +
    +
    +

    How would you look up previous versions of the module?

    +
    +
    +
    + +
    +
    +

    There are a few ways to approach this.

    +
      +
    1. You could hop onto github and search throught the git history for the main.nf of the particular module, to identify the git SHA and provide it to the --sha flag.
    2. +
    3. You could run the install command with the --prompt flag, as seen below
    4. +
    +
    
    +                                          ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +
    +INFO     Module 'fastqc' is already installed.
    +? Module fastqc is already installed.
    +Do you want to force the reinstallation? Yes
    +? Select 'fastqc' commit: (Use arrow keys)
    +   Fix FastQC memory allocation (#5432) 285a50500f9e02578d90b3ce6382ea3c30216acd (installed version)
    +   Update FASTQC to use unique names for snapshots (#4825) f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c
    +   CHORES: update fasqc tests with new data organisation (#4760) c9488585ce7bd35ccd2a30faa2371454c8112fb9
    +   fix fastqc tests n snap (#4669) 617777a807a1770f73deb38c80004bac06807eef
    +   Update version strings (#4556) 65ad3e0b9a4099592e1102e92e10455dc661cf53
    +   Remove pytest-workflow tests for modules covered by nf-test (#4521) 3e8b0c1144ccf60b7848efbdc2be285ff20b49ee
    +   Add conda environment names (#4327) 3f5420aa22e00bd030a2556dfdffc9e164ec0ec5
    +   Fix conda declaration (#4252) 8fc1d24c710ebe1d5de0f2447ec9439fd3d9d66a
    +   Move conda environment to yml (#4079) 516189e968feb4ebdd9921806988b4c12b4ac2dc
    +   authors => maintainers (#4173) cfd937a668919d948f6fcbf4218e79de50c2f36f
    + » older commits
    +
    +
    +
    +
    +
    +

    5.3.2 Updating nf-core modules

    +

    Above we got and error message for fastq because the module was already installed. As listed in the output, one of the suggested solutions is that we might be looking to update the module

    +
    nf-core modules update fastqc
    +

    After running the command you will find that you are prompted for whether you wish to view the differences between the current installation and the update.

    +
    
    +                                          ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +
    +? Do you want to view diffs of the proposed changes? (Use arrow keys)
    + » No previews, just update everything
    +   Preview diff in terminal, choose whether to update files
    +   Just write diffs to a patch file
    +

    For the sake of this exercise, we are going to roll fastqc back by one commit.

    +

    If you select the 2nd option Preview diff in terminal, choose whether to update files

    +
    nf-core modules update fastqc -p
    +
                                              ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +
    +? Do you want to view diffs of the proposed changes? Preview diff in terminal, choose whether to update files
    +? Select 'fastqc' commit: (Use arrow keys)
    +   Fix FastQC memory allocation (#5432) 285a50500f9e02578d90b3ce6382ea3c30216acd (installed version)
    + » Update FASTQC to use unique names for snapshots (#4825) f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c
    +   CHORES: update fasqc tests with new data organisation (#4760) c9488585ce7bd35ccd2a30faa2371454c8112fb9
    +   fix fastqc tests n snap (#4669) 617777a807a1770f73deb38c80004bac06807eef
    +   Update version strings (#4556) 65ad3e0b9a4099592e1102e92e10455dc661cf53
    +   Remove pytest-workflow tests for modules covered by nf-test (#4521) 3e8b0c1144ccf60b7848efbdc2be285ff20b49ee
    +   Add conda environment names (#4327) 3f5420aa22e00bd030a2556dfdffc9e164ec0ec5
    +   Fix conda declaration (#4252) 8fc1d24c710ebe1d5de0f2447ec9439fd3d9d66a
    +   Move conda environment to yml (#4079) 516189e968feb4ebdd9921806988b4c12b4ac2dc
    +   authors => maintainers (#4173) cfd937a668919d948f6fcbf4218e79de50c2f36f
    +   older commits
    +
    ? Select 'fastqc' commit: Update FASTQC to use unique names for snapshots (#4825) f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c
    +INFO     Changes in module 'nf-core/fastqc' between (285a50500f9e02578d90b3ce6382ea3c30216acd) and (f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c)
    +INFO     Changes in 'fastqc/main.nf':
    + --- modules/nf-core/fastqc/main.nf
    + +++ modules/nf-core/fastqc/main.nf
    + @@ -25,11 +25,6 @@
    +      def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] }
    +      def rename_to = old_new_pairs*.join(' ').join(' ')
    +      def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ')
    + -
    + -    def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB')
    + -    // FastQC memory value allowed range (100 - 10000)
    + -    def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb)
    + -
    +      """
    +      printf "%s %s\\n" $rename_to | while read old_name new_name; do
    +          [ -f "\${new_name}" ] || ln -s \$old_name \$new_name
    + @@ -38,7 +33,6 @@
    +      fastqc \\
    +          $args \\
    +          --threads $task.cpus \\
    + -        --memory $fastqc_memory \\
    +          $renamed_files
    +
    +      cat <<-END_VERSIONS > versions.yml
    +INFO     'modules/nf-core/fastqc/meta.yml' is unchanged
    +INFO     'modules/nf-core/fastqc/environment.yml' is unchanged
    +INFO     'modules/nf-core/fastqc/tests/main.nf.test.snap' is unchanged
    +INFO     'modules/nf-core/fastqc/tests/tags.yml' is unchanged
    +INFO     'modules/nf-core/fastqc/tests/main.nf.test' is unchanged
    +? Update module 'fastqc'? No
    +INFO     Updates complete ✨   
    +
    +
    +

    5.3.3 Removing nf-core modules

    +

    As mentioned above, if you decide that you don’t need a module anymore, you can’t just remove the folder with rm -r.

    +

    For nf-core to no longer register the module is to be distributed with your pipeline you need to use:

    +
    nf-core modules remove
    +

    As an exercise, we are going to install the samtools/sort module

    +
    nf-core modules install samtools/sort
    +

    Quickly view the modules.json or use nf-core modules list local to view the changes from installing the module.

    +

    Now remove the samtools/sort module

    +
    nf-core modules remove samtools/sort
    +
    +
    +
    + +
    +
    +Overall Challenge +
    +
    +
    +

    Now add the include module statements to the our workflows/myrnaseq.nf

    +
    +
    +
    + +
    +
    +
    include { FASTQC as FASTQC_one } from '../modules/nf-core/fastq/main' 
    +include { FASTQC as FASTQC_two } from '../modules/nf-core/fastq/main' 
    +
    +include { TRIMGALORE } from '../modules/nf-core/trimgalore/main'
    +
    +
    +
    +
    +
    +

    5.3.4 Writing modules with nf-core template

    +

    For this section we are going to refer to the nf-core guidelines for modules.

    +

    While these are the full guidelines for contributing back to nf-core, there are still some general components that are good practice even if you are NOT planning to contribute.

    +
    +
    +
    + +
    +
    +Summary of guidelines +
    +
    +
    +
      +
    1. All required and optional input files must be included in the input as a path variable
    2. +
    3. The command should run without any additional argument, any required flag values should be included as an input val variable
    4. +
    5. task.ext.args must be provided as a variable
    6. +
    7. Where possible all input and output files should be compressed (i.e. fastq.gz and .bam)
    8. +
    9. A versions.yml file is output
    10. +
    11. Naming conventions include using all lowercase without puntuation and follows the convention of software/tool (i.e. bwa/mem)
    12. +
    13. All outputs must include an emit definition
    14. +
    +
    +
    +

    We are going to write up our own samtools/view module.

    +
    nf-core modules create 
    +
    
    +                                          ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +
    +INFO     Repository type: pipeline
    +INFO     Press enter to use default values (shown in brackets) or type your own responses. ctrl+click underlined text to open links.
    +Name of tool/subtool: samtools/view
    +INFO     Using Bioconda package: 'bioconda::samtools=1.20'
    +INFO     Could not find a Docker/Singularity container (Unexpected response code `500` for https://api.biocontainers.pro/ga4gh/trs/v2/tools/samtools/versions/samtools-1.20) ## Cluster
    +GitHub Username: (@author): @mmyeung
    +INFO     Provide an appropriate resource label for the process, taken from the nf-core pipeline template.
    +         For example: process_single, process_low, process_medium, process_high, process_long
    +? Process resource label: process_low
    +INFO     Where applicable all sample-specific information e.g. 'id', 'single_end', 'read_group' MUST be provided as an input via a Groovy Map called
    +         'meta'. This information may not be required in some instances, for example indexing reference genome files.
    +Will the module require a meta map of sample information? [y/n] (y): y
    +INFO     Created component template: 'samtools/view'
    +INFO     Created following files:
    +           modules/local/samtools/view.nf
    +

    As we progressed through the interactive prompt, you will have noticed that nf-core always attempts to locate the corresponding bioconda package and singularity/Docker container.

    +
    + +
    +
    +
    nf-core modules create --author @mmyeung --label process_single --meta testscript
    +

    The command will indicate that the there is no bioconda package with the software name, and prompt you for a package name you might wish to use.

    +
    INFO     Repository type: pipeline
    +INFO     Press enter to use default values (shown in brackets) or type your own responses. ctrl+click underlined text to open links.
    +WARNING  Could not find Conda dependency using the Anaconda API: 'testscript'
    +Do you want to enter a different Bioconda package name? [y/n]: n
    +WARNING  Could not find Conda dependency using the Anaconda API: 'testscript'
    +         Building module without tool software and meta, you will need to enter this information manually.
    +INFO     Created component template: 'testscript'
    +INFO     Created following files:
    +           modules/local/testscript.nf      
    +

    within the module .nf script you will note that the definitions for the conda and container are incomplete for the tool.

    +
        conda "${moduleDir}/environment.yml"
    +    container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?
    +        'https://depot.galaxyproject.org/singularity/YOUR-TOOL-HERE':
    +        'biocontainers/YOUR-TOOL-HERE' }"
    +

    nf-core has a large cache of containers here. Though you can also provide a simple path to docker hub.

    +
        container "mmyeung/trccustomunix:0.0.1"
    +
    +
    +
    +

    The resource labels, are those as defined in conf/base.config

    +
    +
    +
    + +
    +
    +Challenge +
    +
    +
    +

    Write up the inputs, outputs and script for samtools/view.

    +

    Assume that all the inputs will be .bam and the outputs will also be .bam.

    +

    For reference look at the documentation for samtools/view

    +

    Are there optional flags that take file inputs? What options need to set to ensure that the command runs without error?

    +
    +
    +
    + +
    +
    +
    process SAMTOOLS_VIEW {
    +    tag "$meta.id"
    +    label 'process_low'
    +
    +    conda "${moduleDir}/environment.yml"
    +    container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ?
    +        'https://depot.galaxyproject.org/singularity/samtools:1.20--h50ea8bc_0' :
    +        'biocontainers/samtools:1.20--h50ea8bc_0' }"
    +
    +    input:
    +    tuple val(meta), path(input), path(index)
    +    tuple val(meta2), path(fasta)
    +    path bed
    +    path qname
    +
    +    output:
    +    tuple val(meta), path("*.bam"),  emit: bam
    +    path  "versions.yml",            emit: versions
    +
    +    when:
    +    task.ext.when == null || task.ext.when
    +
    +    script:
    +    def args = task.ext.args ?: ''
    +    def args2 = task.ext.args2 ?: ''
    +    def prefix = task.ext.prefix ?: "${meta.id}"
    +    def reference = fasta ? "--reference ${fasta}" : ""
    +    def readnames = qname ? "--qname-file ${qname}": ""
    +    def regions = bed ? "-L ${bed}": ""
    +    if ("$input" == "${prefix}.${file_type}") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!"
    +    """
    +    samtools \\
    +        view \\
    +        -hb \\
    +        --threads ${task.cpus-1} \\
    +        ${reference} \\
    +        ${readnames} \\
    +        ${regions} \\
    +        $args \\
    +        -o ${prefix}.bam \\
    +        $input \\
    +        $args2
    +
    +    cat <<-END_VERSIONS > versions.yml
    +    "${task.process}":
    +        samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//')
    +    END_VERSIONS
    +    """
    +
    +    stub:
    +    def args = task.ext.args ?: ''
    +    def prefix = task.ext.prefix ?: "${meta.id}"
    +    def file_type = args.contains("--output-fmt sam") ? "sam" :
    +                    args.contains("--output-fmt bam") ? "bam" :
    +                    args.contains("--output-fmt cram") ? "cram" :
    +                    input.getExtension()
    +    if ("$input" == "${prefix}.${file_type}") error "Input and output names are the same, use \"task.ext.prefix\" to disambiguate!"
    +
    +    def index = args.contains("--write-index") ? "touch ${prefix}.csi" : ""
    +
    +    """
    +    touch ${prefix}.${file_type}
    +    ${index}
    +
    +    cat <<-END_VERSIONS > versions.yml
    +    "${task.process}":
    +        samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//')
    +    END_VERSIONS
    +    """
    +
    +
    +
    +

    Similar to nf-core create you can minimise a the number of prompts by using optional flags.

    +
    +
    +
    + +
    +
    +Overall Challenge +
    +
    +
    +

    Write up the short workflow as discussed above

    +

    FASTQC -> trimgalore -> FASTQC -> MULTIQC

    +
    +
    +
    +
    +
    +

    5.4 Nf-core subworkflow

    +

    nf-core subworkflows

    +

    or with

    +
    nf-core subworkflows list remote
    +
    +

    5.4.1 Installing nf-core subworkflows

    +

    Subworkflows can be updated/removed like modules

    +
    +
    +
    + +
    +
    +Challenge +
    +
    +
    +

    Install the subworkflow fastq_subsample_fq_salmon into the workflow

    +
    +
    +
    + +
    +
    +
    nf-core subworkflows install fastq_subsample_fq_salmon
    +
    +
    +
    +
    +
    +

    5.4.2 Writing subworkflows with nf-core template

    +
    +
    +
    + +
    +
    +Challenge +
    +
    +
    +

    Write up the QC_WF subworkflow from last week.

    +
    +
    +
    +
    +
    +

    5.5 Nf-core schema and input validation

    +

    Relies on plugins written by nf-core community

    +

    In particular nf-validation

    +

    nextflow_schmea.json is for pipeline parameters

    +
    nf-core schema build
    +
    
    +                                          ,--./,-.
    +          ___     __   __   __   ___     /,-._.--~\
    +    |\ | |__  __ /  ` /  \ |__) |__         }  {
    +    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
    +                                          `._,._,'
    +
    +    nf-core/tools version 2.14.1 - https://nf-co.re
    +
    +
    +INFO     [✓] Default parameters match schema validation
    +INFO     [✓] Pipeline schema looks valid (found 32 params)
    +INFO     Writing schema with 32 params: 'nextflow_schema.json'
    +🚀  Launch web builder for customisation and editing? [y/n]: y
    +INFO     Opening URL: https://nf-co.re/pipeline_schema_builder?id=1718112529_0841fa08f86f
    +INFO     Waiting for form to be completed in the browser. Remember to click Finished when you're done.
    +⢿ Use ctrl+c to stop waiting and force exit.
    +

    Recommend writing in web browser

    +

    json format details additional reading

    +
    +
    +
    + +
    +
    +Challenge +
    +
    +
    +

    We are going add the input parameter for the transcript.fa

    +

    Then install salmon/index and write up quant_wf subworkflow from last week.git

    +
    +
    +
    +

    5.5.2 Nf-core inputs

    +

    nested in this schema is the input or samplesheet schema. unfortunately there isn’t a nice interface to help you write this schema yet.

    +
      +
    • meta: Allows you to predesignate the “key” with in the “meta”

    • +
    • required: value must be included

    • +
    • dependency: value is dependant on other value existing in samplesheet (i.e. fastq_2 must imply there is a fastq_1)

    • +
    +
    +
    +

    5.6 Nf-core tools for launching

    +

    create-params-file

    +
    +
    +

    5.7 Nf-core for pipeline management

    +

    bump-version ==> good software management to note down versions

    +
    +
    +
    +

    Contributing to nf-core

    +

    Full pipelines Please see the nf-core documentation for a full walkthrough of how to create a new nf-core workflow.

    +
    +

    This workshop is adapted from Fundamentals Training, Advanced Training, Developer Tutorials, Nextflow Patterns materials from Nextflow, nf-core nf-core tools documentation and nf-validation

    + + +
    + +
    + +
    + + + + \ No newline at end of file diff --git a/workshops/media/5.2.1_nf_core_create_github.png b/workshops/media/5.2.1_nf_core_create_github.png new file mode 100644 index 0000000000000000000000000000000000000000..a0cbec6793772941819692e8460ab8e6b7aeea18 GIT binary patch literal 31252 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 literal 0 HcmV?d00001 diff --git a/workshops/media/5.2.1_nf_core_create_interactive.png b/workshops/media/5.2.1_nf_core_create_interactive.png new file mode 100644 index 0000000000000000000000000000000000000000..bdb9760c9686bc98e1865ffe255662ae67d5cab7 GIT binary patch literal 22233 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 literal 0 HcmV?d00001