In bioinformatics and computational biology, the vast and growing amount of data necessitates methods and tools that can process and analyze data in parallel. This demand gave birth to the scatter-gather approach, an essential pattern in creating pipelines that offers efficient data handling and parallel processing capabilities. In this tutorial, we will demonstrate how to create a CWL pipeline utilizing the scatter-gather approach. To this purpose, we will use two widely known tools: fastp and multiqc. Given the functionalities of both fastp and multiqc, their combination in a scatter-gather pipeline is incredibly useful. Individual datasets can be scattered across resources for parallel preprocessing with fastp. Subsequently, the outputs from each of these parallel tasks can be gathered and fed into multiqc, generating a consolidated quality report. This workflow not only accelerates the preprocessing of large datasets but also offers an aggregated perspective on data quality, ensuring that subsequent analyses are built upon a robust foundation.
Creating the tools
First, we create the two tools: fastp and multiqc. For this, we need the corresponding Docker images and CWL tool definitions. Please, look up this part of our help sites to learn more how to import a tool into ICA. In a nutshell, once the CWL tool definition is pasted into the editor, the other tabs for editing the tool will be populated. To complete the tool, the user needs to select the corresponding Docker image and to provide a tool version (could be any string).
For this demo, we will use the publicly available Docker images: quay.io/biocontainers/fastp:0.20.0--hdbcaa40_0 for fastp and docker.io/ewels/multiqc:v1.15 for multiqc. In this tutorial one can find how to import publicly available Docker images into ICA.
Furthermore, we will use the following CWL tool definitions:
#!/usr/bin/env cwl-runnercwlVersion:cwl:v1.0class:CommandLineToollabel:MultiQCdoc:MultiQC is a tool to create a single report with interactive plots for multiplebioinformatics analyses across many samples.inputs:files:type: - type:arrayitems:File - 'null'doc:Files containing the result of quality analysis.inputBinding:position:2directories:type: - type:arrayitems:Directory - 'null'doc:Directories containing the result of quality analysis.inputBinding:position:3report_name:type:stringdoc:Name of output report, without path but with full file name (e.g. report.html).default:multiqc_report.htmlinputBinding:position:1prefix:-noutputs:report:type:FileoutputBinding:glob: - '*.html'baseCommand:- multiqc
Pipeline
Once the tools are created, we will create the pipeline itself using these two tools at Projects > your_project > Flow > Pipelines > CWL > Graphical:
On the Definition tab, go to the tool repository and drag and drop the two tools which you just created on the pipeline editor.
Connect the JSON output of fastp to multiqc input by hovering over the middle of the round, blue connector of the output until the icon changes to a hand and then drag the connection to the first input of multiqc. You can use the magnification symbols to make it easier to connect these tools.
Above the diagram, drag and drop two input FASTQ files and an output HTML file on to the pipeline editor and connect the blue markers to match the diagram below.
Relevant aspects of the pipeline:
Both inputs are multivalue (as can be seen on the screenshot)
Ensure that the step fastp has scattering configured: it scatters on both inputs using the scatter method 'dotproduct'. This means that as many instances of this step will be executed as there are pairs of FASTQ files. To indicate that this step is executed multiple times, the icons of both inputs have doubled borders.
Important remark
Both input arrays (Read1 and Read2) must be matched. Currently an automatic sorting of input arrays is not supported yet. One has to take care of matching the input arrays. There are two ways to achieve this (besides the manual specification in the GUI):
invoke this pipeline in CLI using Bash functionality to sort the arrays
add a tool to the pipeline which will intake array of all FASTQ files, spread them on R1 and R2 suffixes, and sort them.
We will describe the second way in more detail. The tool will be based on public python Docker docker.io/python:3.10 and have the following definition. In this tool we are providing the Python script spread_script.py via Dirent feature.
#!/usr/bin/env cwl-runnercwlVersion:v1.0class:CommandLineToolrequirements:- class:InlineJavascriptRequirement- class:InitialWorkDirRequirementlisting: - entry:"import argparse\nimport os\nimport json\n\n# Create argument parser\n\ parser = argparse.ArgumentParser()\nparser.add_argument(\"-i\", \"--inputFiles\"\ , type=str, required=True, help=\"Input files\")\n\n# Parse the arguments\n\ args = parser.parse_args()\n\n# Split the inputFiles string into a list of file\ \ paths\ninput_files = args.inputFiles.split(',')\n\n# Sort the input files\ \ by the base filename\ninput_files = sorted(input_files, key=lambda x: os.path.basename(x))\n\ \n\n# Separate the files into left and right arrays, preserving the order\n\ left_files = [file for file in input_files if '_R1_' in os.path.basename(file)]\n\ right_files = [file for file in input_files if '_R2_' in os.path.basename(file)]\n\ \n# Print the left files for debugging\nprint(\"Left files:\", left_files)\n\ \n# Print the left files for debugging\nprint(\"Right files:\", right_files)\n\ \n# Ensure left and right files are matched\nassert len(left_files) == len(right_files),\ \ \"Mismatch in number of left and right files\"\n\n \n# Write the left files\ \ to a JSON file\nwith open('left_files.json', 'w') as outfile:\n left_files_objects\ \ = [{\"class\": \"File\", \"path\": file} for file in left_files]\n json.dump(left_files_objects,\ \ outfile)\n\n# Write the right files to a JSON file\nwith open('right_files.json',\ \ 'w') as outfile:\n right_files_objects = [{\"class\": \"File\", \"path\"\ : file} for file in right_files]\n json.dump(right_files_objects, outfile)\n\ \n"entryname:spread_script.pywritable:falselabel:spread_itemsinputs:inputFiles:type:type:arrayitems:FileinputBinding:separate:falseprefix:-iitemSeparator:','outputs:leftFiles:type:type:arrayitems:FileoutputBinding:glob: - left_files.jsonloadContents:trueoutputEval:$(JSON.parse(self[0].contents))rightFiles:type:type:arrayitems:FileoutputBinding:glob: - right_files.jsonloadContents:trueoutputEval:$(JSON.parse(self[0].contents))baseCommand:- python3- spread_script.py
Now this tool can added to the pipeline before fastp step.