diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 6866f649..bbf83e63 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -16,11 +16,15 @@ Contributions to the code are even more welcome ;) If you'd like to write some code for nf-core/phaseimpute, the standard workflow is as follows: +1. Check that there isn't already an issue about your idea in the [nf-core/phaseimpute issues](https://github.com/nf-core/phaseimpute/issues) to avoid duplicating work. If there isn't one already, please create one so that others know you're working on this 1. Check that there isn't already an issue about your idea in the [nf-core/phaseimpute issues](https://github.com/nf-core/phaseimpute/issues) to avoid duplicating work. If there isn't one already, please create one so that others know you're working on this 2. [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [nf-core/phaseimpute repository](https://github.com/nf-core/phaseimpute) to your GitHub account 3. Make the necessary changes / additions within your forked repository following [Pipeline conventions](#pipeline-contribution-conventions) 4. Use `nf-core schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). 5. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged +3. Make the necessary changes / additions within your forked repository following [Pipeline conventions](#pipeline-contribution-conventions) +4. Use `nf-core schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). +5. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged If you're not used to this workflow with git, you can start with some [docs from GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests) or even their [excellent `git` resources](https://try.github.io/). @@ -37,6 +41,7 @@ Typically, pull-requests are only fully reviewed when these tests are passing, t There are typically two types of tests that run: +### Lint tests ### Lint tests `nf-core` has a [set of guidelines](https://nf-co.re/developers/guidelines) which all pipelines must adhere to. @@ -44,6 +49,7 @@ To enforce these and ensure that all pipelines stay in sync, we have developed a If any failures or warnings are encountered, please follow the listed URL for more documentation. +### Pipeline tests ### Pipeline tests Each `nf-core` pipeline should be set up with a minimal set of test-data. @@ -53,6 +59,7 @@ These tests are run both with the latest available version of `Nextflow` and als ## Patch +:warning: Only in the unlikely and regretful event of a release happening with a bug. :warning: Only in the unlikely and regretful event of a release happening with a bug. - On your own fork, make a new branch `patch` based on `upstream/master`. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index b1e6b755..a48df31d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,5 @@ +Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. + +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/phaseimpute/tree/master/.github/CONTRIBUTING.md) +--> + ## PR checklist +- [ ] This comment contains a description of changes (with reason). - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/phaseimpute/tree/master/.github/CONTRIBUTING.md) diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 1619a8f9..2ab2e90f 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -4,13 +4,18 @@ name: nf-core branch protection on: pull_request_target: branches: [master] + pull_request_target: + branches: [master] jobs: test: + runs-on: ubuntu-latest runs-on: ubuntu-latest steps: + # PRs to the nf-core repo master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches # PRs to the nf-core repo master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches - name: Check PRs + if: github.repository == 'nf-core/phaseimpute' if: github.repository == 'nf-core/phaseimpute' run: | { [[ ${{github.event.pull_request.head.repo.full_name }} == nf-core/phaseimpute ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ecc6d0cb..eff088eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,12 +11,30 @@ on: env: NXF_ANSI_LOG: false +concurrency: + group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true +# This workflow runs the pipeline with the minimal test dataset to check that it completes without any syntax errors +on: + push: + branches: + - dev + pull_request: + release: + types: [published] + +env: + NXF_ANSI_LOG: false + concurrency: group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" cancel-in-progress: true jobs: test: + name: Run pipeline with test data + # Only run on push if this is the nf-core dev branch (merged PRs) + if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/phaseimpute') }}" name: Run pipeline with test data # Only run on push if this is the nf-core dev branch (merged PRs) if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/phaseimpute') }}" @@ -26,6 +44,9 @@ jobs: NXF_VER: - "23.04.0" - "latest-everything" + NXF_VER: + - "23.04.0" + - "latest-everything" steps: - name: Check out pipeline code uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 @@ -39,8 +60,12 @@ jobs: uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - name: Run pipeline with test data + # TODO nf-core: You can customise CI pipeline run tests as required + # For example: adding multiple test runs with different parameters + # Remember that you can parallelise this by using strategy.matrix # TODO nf-core: You can customise CI pipeline run tests as required # For example: adding multiple test runs with different parameters # Remember that you can parallelise this by using strategy.matrix run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results + nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 073e1876..cdd1c57d 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -2,10 +2,14 @@ name: nf-core linting # This workflow is triggered on pushes and PRs to the repository. # It runs the `nf-core lint` and markdown lint tests to ensure # that the code meets the nf-core guidelines. +# It runs the `nf-core lint` and markdown lint tests to ensure +# that the code meets the nf-core guidelines. on: push: branches: - dev + branches: + - dev pull_request: release: types: [published] @@ -47,6 +51,7 @@ jobs: python -m pip install --upgrade pip pip install nf-core + - name: Run nf-core lint env: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} diff --git a/.gitignore b/.gitignore index 5124c9ac..32ce547c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ results/ testing/ testing* *.pyc +*.code-workspace \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index c089ec78..cc78c4fb 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -45,8 +45,10 @@ Questions, concerns, or ideas on what we can include? Contact members of the Saf ## Our Responsibilities Members of the Safety Team (the Safety Officers) are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behaviour. +The safety officer is responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behaviour. The Safety Team, in consultation with the nf-core core team, have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this CoC, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. +The safety officer in consultation with the nf-core core team have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. Members of the core team or the Safety Team who violate the CoC will be required to recuse themselves pending investigation. They will not have access to any reports of the violations and will be subject to the same actions as others in violation of the CoC. diff --git a/README.md b/README.md index edf0acd8..c7ad0d44 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,13 @@ workflows use the "tube map" design for that. See https://nf-co.re/docs/contributing/design_guidelines#examples for examples. --> -1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) -2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) +### Main steps of the pipeline +The **phaseimpute** pipeline is constituted of 5 main steps: + +| Metro map | Modes | +|-----------|-------------| +| metromap | - **Pre-processing**: Phasing, QC, variant filtering, variant annotation of the reference panel
- **Phase**: Phasing of the target dataset on the reference panel
- **Simulate**: Simulation of the target dataset from high quality target data
- **Concordance**: Concordance between the target dataset and a truth dataset
- **Post-processing**: Variant filtering based on their imputation quality | ## Usage > [!NOTE] @@ -72,6 +76,19 @@ nextflow run nf-core/phaseimpute \ For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/phaseimpute/usage) and the [parameter documentation](https://nf-co.re/phaseimpute/parameters). +## Description of the different mode of the pipeline + +Here is a short description of the different mode of the pipeline. +For more information please refer to the [documentation](https://nf-core.github.io/phaseimpute/usage/). + +| Mode | Flow chart | Description | +|-------------------|-----------------------------------------------------------------|----------------------------------------------------------------------------------------| +| **Preprocessing** | phase_metro | The preprocessing mode is responsible to the preparation of the multiple input file that will be used by the phasing process.
The main processes are :
- **Haplotypes phasing** of the reference panel using [**Shapeit5**](https://odelaneau.github.io/shapeit5/).
- **Filter** the reference panel to select only the necessary variants.
- **Chunking the reference panel** in a subset of region for all the chromosomes.
- **Extract** the positions where to perform the imputation.| +| **Phasing** | phase_metro | The phasing mode is the core mode of this pipeline.
It is constituted of 3 main steps:
- **Phasing**: Phasing of the target dataset on the reference panel using either:
  - [**Glimpse1**](https://odelaneau.github.io/GLIMPSE/glimpse1/index.html)
  It's come with the necessety to compute the genotype likelihoods of the target dataset.
  This step is done using [BCFTOOLS_mpileup](https://samtools.github.io/bcftools/bcftools.html#mpileup)
  - [**Glimpse2**](https://odelaneau.github.io/GLIMPSE/glimpse2/index.html) For this step the reference panel is transformed to binary chunks.
  - [**Stitch**](https://github.com/rwdavies/stitch)
  - [**Quilt**](https://github.com/rwdavies/QUILT)
- **Ligation**: all the different chunks are merged together.
- **Sampling** (optional) | +| **Simulate** | simulate_metro | The simulation mode is used to create artificial low informative genetic information from high density data. This allow to compare the imputed result to a *truth* and therefore evaluate the quality of the imputation.
For the moment it is possible to simulate:
- Low-pass data by **downsample** BAM or CRAM using [SAMTOOLS_view -s]() at different depth
- Genotype data by **SNP selecting** the position used by a designated SNP chip.
The simulation mode will also compute the **Genotype likelihoods** of the high density data. | +| **Concordance** | concordance_metro | This mode compare two vcf together to compute a summary of the differences between them.
To do so it use either:
- [**Glimpse1**](https://odelaneau.github.io/GLIMPSE/glimpse1/index.html) concordance process.
- [**Glimpse2**](https://odelaneau.github.io/GLIMPSE/glimpse2/index.html) concordance process
- Or convert the two vcf fill to `.zarr` using [**Scikit allele**](https://scikit-allel.readthedocs.io/en/stable/) and [**anndata**](https://anndata.readthedocs.io/en/latest/) before comparing the SNPs. | +| **Postprocessing**| postprocessing_metro | This final process unable to loop the whole pipeline for increasing the performance of the imputation. To do so it filter out the best imputed position and rerun the analysis using this positions. | + ## Pipeline output To see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/phaseimpute/results) tab on the nf-core website pipeline page. @@ -90,8 +107,10 @@ We thank the following people for their extensive assistance in the development If you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md). +For further information or help, don't hesitate to get in touch on the [Slack `#phaseimpute` channel](https://nfcore.slack.com/channels/phaseimpute) (you can join with [this invite](https://nf-co.re/join/slack)). For further information or help, don't hesitate to get in touch on the [Slack `#phaseimpute` channel](https://nfcore.slack.com/channels/phaseimpute) (you can join with [this invite](https://nf-co.re/join/slack)). +## Citations ## Citations diff --git a/assets/chr_rename.txt b/assets/chr_rename.txt new file mode 100644 index 00000000..a85016b6 --- /dev/null +++ b/assets/chr_rename.txt @@ -0,0 +1,39 @@ +chr1 1 +chr2 2 +chr3 3 +chr4 4 +chr5 5 +chr6 6 +chr7 7 +chr8 8 +chr9 9 +chr10 10 +chr11 11 +chr12 12 +chr13 13 +chr14 14 +chr15 15 +chr16 16 +chr17 17 +chr18 18 +chr19 19 +chr20 20 +chr21 21 +chr22 22 +chr23 23 +chr24 24 +chr25 25 +chr26 26 +chr27 27 +chr28 28 +chr29 29 +chr30 30 +chr31 31 +chr32 32 +chr33 33 +chr34 34 +chr35 35 +chr36 36 +chr37 37 +chr38 38 +chr39 X diff --git a/assets/regionsheet.csv b/assets/regionsheet.csv new file mode 100644 index 00000000..030c9ba1 --- /dev/null +++ b/assets/regionsheet.csv @@ -0,0 +1,2 @@ +chr,start,end +20,20000000,2200000 diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 5f653ab7..441a688f 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,3 @@ -sample,fastq_1,fastq_2 -SAMPLE_PAIRED_END,/path/to/fastq/files/AEG588A1_S1_L002_R1_001.fastq.gz,/path/to/fastq/files/AEG588A1_S1_L002_R2_001.fastq.gz -SAMPLE_SINGLE_END,/path/to/fastq/files/AEG588A4_S4_L003_R1_001.fastq.gz, +sample,BAM,BAI +1_BAM_1X,/path/to/.bam,/path/to/.bai +1_BAM_SNP,/path/to/.bam,/path/to/.bai diff --git a/assets/schema_input.json b/assets/schema_input.json index 6a7e788c..ce442280 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema", "$id": "https://raw.githubusercontent.com/nf-core/phaseimpute/master/assets/schema_input.json", - "title": "nf-core/phaseimpute pipeline - params.input schema", + "title": "nf-core/phaseimpute pipeline - params.input", "description": "Schema for the file provided with params.input", "type": "array", "items": { @@ -13,21 +13,17 @@ "errorMessage": "Sample name must be provided and cannot contain spaces", "meta": ["id"] }, - "fastq_1": { + "BAM": { "type": "string", - "format": "file-path", - "exists": true, - "pattern": "^\\S+\\.f(ast)?q\\.gz$", - "errorMessage": "FastQ file for reads 1 must be provided, cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" + "pattern": "^\\S+\\.bam$", + "errorMessage": "BAM file must be provided, cannot contain spaces and must have extension '.bam'" }, - "fastq_2": { + "BAI": { + "errorMessage": "BAI file must be provided, cannot contain spaces and must have extension '.bai'", "type": "string", - "format": "file-path", - "exists": true, - "pattern": "^\\S+\\.f(ast)?q\\.gz$", - "errorMessage": "FastQ file for reads 2 cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" + "pattern": "^\\S+\\.bai$" } }, - "required": ["sample", "fastq_1"] + "required": ["sample", "BAM", "BAI"] } } diff --git a/assets/schema_input_region.json b/assets/schema_input_region.json new file mode 100644 index 00000000..6c871b1a --- /dev/null +++ b/assets/schema_input_region.json @@ -0,0 +1,35 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "https://raw.githubusercontent.com/nf-core/phaseimpute/master/assets/schema_input.json", + "title": "nf-core/phaseimpute pipeline - params.input_region schema", + "description": "Schema for the file provided with params.input_region", + "type": "array", + "items": { + "type": "object", + "properties": { + "chr": { + "anyOf": [ + { + "type": "string", + "pattern": "^\\S+$" + }, + { + "type": "integer", + "pattern": "^\\d+$" + } + ] + }, + "start": { + "type": "integer", + "pattern": "^\\d+$", + "errorMessage": "Region start name must be provided, cannot contain spaces and must be numeric" + }, + "end": { + "type": "integer", + "pattern": "^\\d+$", + "errorMessage": "Region end name must be provided, cannot contain spaces and must be numeric" + } + }, + "required": ["chr", "start", "end"] + } +} diff --git a/conf/modules.config b/conf/modules.config index e3ea8fa6..f30dbfa6 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,10 +18,6 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] - withName: FASTQC { - ext.args = '--quiet' - } - withName: CUSTOM_DUMPSOFTWAREVERSIONS { publishDir = [ path: { "${params.outdir}/pipeline_info" }, @@ -39,4 +35,116 @@ process { ] } + // Simulate workflow + withName: VIEW_REGION { + ext.args = [ + ].join(' ') + ext.prefix = { "${meta.id}_R${meta.region}" } + } + withName: VIEW_DEPTH { + ext.args = [ + ].join(' ') + ext.prefix = { "${meta.id}_D${meta.depth}" } + } + + // Panel preparation workflow + withName: VIEW_VCF_REGION { + ext.args = [ + "-Oz", + "--no-version" + ].join(' ') + ext.prefix = { "${meta.id}_${meta.region}" } + } + + withName: BCFTOOLS_ANNOTATE { + ext.args = [ + "-Oz", + "--no-version" + ].join(' ') + ext.prefix = { "${meta.id}_chrDel_${meta.region}" } + } + + withName: VIEW_VCF_SNPS { + ext.args = [ + "-m 2", + "-M 2", + "-v snps", + "--no-version" + ].join(' ') + ext.prefix = { "${meta.id}_SPNS" } + } + withName: BCFTOOLS_NORM{ + ext.args = [ + "-m", + "-any", + "--no-version" + ].join(' ') + ext.prefix = { "${meta.id}_norm" } + } + withName: VIEW_VCF_SITES { + ext.args = [ + "-G", + "-m 2", + "-M 2", + "-v snps", + "--no-version" + ].join(' ') + ext.prefix = { "${meta.id}_SITES" } + } + withName: BCFTOOLS_QUERY { + ext.args = [ + "-f'%CHROM\t%POS\t%REF,%ALT\n'", + ].join(' ') + ext.prefix = { "${meta.id}_SITES_TSV" } + } + withName: TABIX_TABIX { + ext.args = [ + "-s1", + "-b2", + "-e2" + ].join(' ') + ext.prefix = { "${meta.id}_SITES_TSV" } + } + withName: BEDTOOLS_MAKEWINDOWS { + ext.args = [ + '-w 60000', + '-s 40000' + ].join(' ') + ext.prefix = { "${meta.id}_chunks" } + } + withName: BCFTOOLS_MPILEUP { + ext.args = [ + "-I", + "-E", + "-a 'FORMAT/DP'" + ].join(' ') + ext.args2 = [ + "-Aim", + "-C alleles" + ].join(' ') + } + + withName: GLIMPSE_PHASE { + ext.args = [ + "--impute-reference-only-variants" + ].join(' ') + ext.prefix = { "${meta.id}" } + ext.suffix = "bcf" + } + withName: GLIMPSE_CHUNK { + ext.args = [ + "--window-size 200000", + "--buffer-size 20000" + ].join(' ') + ext.prefix = { "${meta.id}" } + } + withName: GLIMPSE_LIGATE { + ext.prefix = { "${meta.id}_D${meta.depth}_P${meta.panel}" } + } + withName: GLIMPSE_CONCORDANCE { + ext.prefix = { "${meta.id}_D${meta.depth}_P${meta.panel}_R${meta.region}" } + } + withName: ADD_COLUMNS { + ext.prefix = { "${meta.id}_D${meta.depth}_P${meta.panel}_R${meta.region}_SNP" } + } } diff --git a/conf/test_full.config b/conf/test_full.config index 90d800db..cb2a0fae 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,8 +17,21 @@ params { // Input data for full size test // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = 'https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_full_illumina_amplicon.csv' // Genome references - genome = 'R64-1-1' + map = "/groups/dog/llenezet/test-datasets/data/genetic_maps.b38/chr21.b38.gmap.gz" + genome = "GRCh38" + fasta = "/groups/dog/llenezet/script/phaseimpute/data/genome.fa" + + // Resources increase incompatible with Github Action + max_cpus = 12 + max_memory = '50.GB' + max_time = '6.h' + + // Input data + input = "tests/csv/sample_sim.csv" + panel = "tests/csv/panel.csv" + input_region_string = "all" + outdir = "results/test_full" + step = "simulate" } diff --git a/conf/test_panelprep.config b/conf/test_panelprep.config new file mode 100644 index 00000000..32a78c5a --- /dev/null +++ b/conf/test_panelprep.config @@ -0,0 +1,33 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 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 nf-core/phaseimpute -profile test_panelprep, --outdir + +---------------------------------------------------------------------------------------- +*/ + +params { + config_profile_name = 'Test Panel preparation mode' + 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 + input = "tests/csv/panel.csv" + input_region_file = "tests/csv/regionsheet.csv" + outdir = "results/test_panelprep" + genome = "GRCh38" + + map = "/groups/dog/llenezet/test-datasets/data/genetic_maps.b38/chr21.b38.gmap.gz" + fasta = "/groups/dog/llenezet/test-datasets/data/reference_genome/hs38DH.chr21.fa" + + step = "panelprep" + tools = ["glimpse2", "glimpse1"] +} diff --git a/conf/test_sim.config b/conf/test_sim.config new file mode 100644 index 00000000..b8312420 --- /dev/null +++ b/conf/test_sim.config @@ -0,0 +1,33 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 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 nf-core/phaseimpute -profile test_sim, --outdir + +---------------------------------------------------------------------------------------- +*/ + +params { + config_profile_name = 'Test simulation mode' + 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 + input = "tests/csv/sample_sim.csv" + input_region_file = "tests/csv/regionsheet.csv" + depth = [1, 2] + outdir = "results/test_sim" + genome = "GRCh38" + + map = "/groups/dog/llenezet/test-datasets/data/genetic_maps.b38/chr21.b38.gmap.gz" + fasta = "/groups/dog/llenezet/test-datasets/data/reference_genome/hs38DH.chr21.fa" + + step = "simulate" +} diff --git a/docs/NfCore_library.xml b/docs/NfCore_library.xml new file mode 100644 index 00000000..21989d75 --- /dev/null +++ b/docs/NfCore_library.xml @@ -0,0 +1,163 @@ +[ + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"group\" vertex=\"1\" connectable=\"0\" parent=\"1\"><mxGeometry y=\"15\" width=\"20\" height=\"45\" as=\"geometry\"/></mxCell><mxCell id=\"3\" value=\"\" style=\"ellipse;whiteSpace=wrap;html=1;aspect=fixed;rounded=1;rotation=0;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry width=\"20\" height=\"20\" relative=\"1\" as=\"geometry\"><mxPoint y=\"-15\" as=\"offset\"/></mxGeometry></mxCell><mxCell id=\"4\" value=\"\" style=\"ellipse;whiteSpace=wrap;html=1;aspect=fixed;rounded=1;rotation=0;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry y=\"5\" width=\"20\" height=\"20\" as=\"geometry\"/></mxCell><mxCell id=\"5\" style=\"edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;strokeWidth=2;endArrow=none;endFill=0;\" edge=\"1\" parent=\"2\" source=\"3\" target=\"4\"><mxGeometry relative=\"1\" as=\"geometry\"/></mxCell><mxCell id=\"6\" style=\"edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;strokeWidth=2;\" edge=\"1\" parent=\"2\" source=\"3\" target=\"4\"><mxGeometry relative=\"1\" as=\"geometry\"/></mxCell><mxCell id=\"7\" value=\"\" style=\"ellipse;whiteSpace=wrap;html=1;aspect=fixed;rounded=1;rotation=0;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry y=\"25\" width=\"20\" height=\"20\" as=\"geometry\"/></mxCell><mxCell id=\"8\" style=\"edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;strokeWidth=2;endArrow=none;endFill=0;\" edge=\"1\" parent=\"2\" source=\"4\" target=\"7\"><mxGeometry relative=\"1\" as=\"geometry\"/></mxCell><mxCell id=\"9\" style=\"edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;strokeWidth=2;endArrow=none;endFill=0;\" edge=\"1\" parent=\"2\" source=\"4\" target=\"7\"><mxGeometry relative=\"1\" as=\"geometry\"/></mxCell><mxCell id=\"10\" value=\"\" style=\"rounded=0;whiteSpace=wrap;html=1;strokeColor=#FFFFFF;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"5\" width=\"10\" height=\"30\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 20, + "h": 60, + "aspect": "fixed", + "title": "triple_circle" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"group\" vertex=\"1\" connectable=\"0\" parent=\"1\"><mxGeometry width=\"20\" height=\"40\" as=\"geometry\"/></mxCell><mxCell id=\"3\" value=\"\" style=\"ellipse;whiteSpace=wrap;html=1;aspect=fixed;rounded=1;rotation=0;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry width=\"20\" height=\"20\" as=\"geometry\"/></mxCell><mxCell id=\"4\" value=\"\" style=\"ellipse;whiteSpace=wrap;html=1;aspect=fixed;rounded=1;rotation=0;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry y=\"20\" width=\"20\" height=\"20\" as=\"geometry\"/></mxCell><mxCell id=\"5\" style=\"edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;strokeWidth=2;endArrow=none;endFill=0;\" edge=\"1\" parent=\"2\" source=\"3\" target=\"4\"><mxGeometry relative=\"1\" as=\"geometry\"/></mxCell><mxCell id=\"6\" style=\"edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;strokeWidth=2;\" edge=\"1\" parent=\"2\" source=\"3\" target=\"4\"><mxGeometry relative=\"1\" as=\"geometry\"/></mxCell><mxCell id=\"7\" value=\"\" style=\"rounded=0;whiteSpace=wrap;html=1;strokeColor=#FFFFFF;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"5\" y=\"15\" width=\"10\" height=\"10\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 20, + "h": 40, + "aspect": "fixed", + "title": "double_circle" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"ellipse;whiteSpace=wrap;html=1;aspect=fixed;rounded=1;rotation=0;strokeWidth=2;\" vertex=\"1\" parent=\"1\"><mxGeometry width=\"20\" height=\"20\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 20, + "h": 20, + "aspect": "fixed", + "title": "single_circle" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;\" vertex=\"1\" parent=\"1\"><mxGeometry width=\"20\" height=\"60\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 20, + "h": 60, + "aspect": "fixed", + "title": "triple_square" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;\" vertex=\"1\" parent=\"1\"><mxGeometry width=\"20\" height=\"40\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 20, + "h": 40, + "aspect": "fixed", + "title": "double_square" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;\" vertex=\"1\" parent=\"1\"><mxGeometry width=\"20\" height=\"20\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 20, + "h": 20, + "aspect": "fixed", + "title": "single_square" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;arcSize=50;\" vertex=\"1\" parent=\"1\"><mxGeometry width=\"20\" height=\"60\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 20, + "h": 60, + "aspect": "fixed", + "title": "triple_round" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;arcSize=50;\" vertex=\"1\" parent=\"1\"><mxGeometry width=\"20\" height=\"40\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 20, + "h": 40, + "aspect": "fixed", + "title": "double_round" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"group\" vertex=\"1\" connectable=\"0\" parent=\"1\"><mxGeometry width=\"90\" height=\"100\" as=\"geometry\"/></mxCell><mxCell id=\"3\" value=\"\" style=\"shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;rounded=1;size=20;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"5\" width=\"80\" height=\"100\" as=\"geometry\"/></mxCell><mxCell id=\"4\" value=\"&lt;font data-font-src=&quot;https://fonts.googleapis.com/css?family=Maven+Pro&quot; face=&quot;Maven Pro&quot; color=&quot;#ffffff&quot;&gt;&lt;b&gt;&lt;font style=&quot;font-size: 20px;&quot;&gt;Fastq&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;fillColor=#000000;\" vertex=\"1\" parent=\"2\"><mxGeometry y=\"40\" width=\"90\" height=\"40\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 90, + "h": 100, + "aspect": "fixed", + "title": "single_file" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"group\" vertex=\"1\" connectable=\"0\" parent=\"1\"><mxGeometry width=\"95\" height=\"105\" as=\"geometry\"/></mxCell><mxCell id=\"3\" value=\"\" style=\"shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;rounded=1;size=20;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"5\" width=\"80\" height=\"100\" as=\"geometry\"/></mxCell><mxCell id=\"4\" value=\"&lt;font data-font-src=&quot;https://fonts.googleapis.com/css?family=Maven+Pro&quot; face=&quot;Maven Pro&quot; color=&quot;#ffffff&quot;&gt;&lt;b&gt;&lt;font style=&quot;font-size: 20px;&quot;&gt;Fastq&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;fillColor=#000000;\" vertex=\"1\" parent=\"2\"><mxGeometry y=\"40\" width=\"90\" height=\"40\" as=\"geometry\"/></mxCell><mxCell id=\"5\" value=\"\" style=\"shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;rounded=1;size=20;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"10\" y=\"5\" width=\"80\" height=\"100\" as=\"geometry\"/></mxCell><mxCell id=\"6\" value=\"&lt;font data-font-src=&quot;https://fonts.googleapis.com/css?family=Maven+Pro&quot; face=&quot;Maven Pro&quot; color=&quot;#ffffff&quot;&gt;&lt;b&gt;&lt;font style=&quot;font-size: 20px;&quot;&gt;Fastq&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;fillColor=#000000;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"5\" y=\"45\" width=\"90\" height=\"40\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 95, + "h": 105, + "aspect": "fixed", + "title": "double_file" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"group\" vertex=\"1\" connectable=\"0\" parent=\"1\"><mxGeometry width=\"100\" height=\"110\" as=\"geometry\"/></mxCell><mxCell id=\"3\" value=\"\" style=\"shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;rounded=1;size=20;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"5\" width=\"80\" height=\"100\" as=\"geometry\"/></mxCell><mxCell id=\"4\" value=\"&lt;font data-font-src=&quot;https://fonts.googleapis.com/css?family=Maven+Pro&quot; face=&quot;Maven Pro&quot; color=&quot;#ffffff&quot;&gt;&lt;b&gt;&lt;font style=&quot;font-size: 20px;&quot;&gt;Fastq&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;fillColor=#000000;\" vertex=\"1\" parent=\"2\"><mxGeometry y=\"40\" width=\"90\" height=\"40\" as=\"geometry\"/></mxCell><mxCell id=\"5\" value=\"\" style=\"shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;rounded=1;size=20;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"10\" y=\"5\" width=\"80\" height=\"100\" as=\"geometry\"/></mxCell><mxCell id=\"6\" value=\"&lt;font data-font-src=&quot;https://fonts.googleapis.com/css?family=Maven+Pro&quot; face=&quot;Maven Pro&quot; color=&quot;#ffffff&quot;&gt;&lt;b&gt;&lt;font style=&quot;font-size: 20px;&quot;&gt;Fastq&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;fillColor=#000000;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"5\" y=\"45\" width=\"90\" height=\"40\" as=\"geometry\"/></mxCell><mxCell id=\"7\" value=\"\" style=\"shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;rounded=1;size=20;strokeWidth=2;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"15\" y=\"10\" width=\"80\" height=\"100\" as=\"geometry\"/></mxCell><mxCell id=\"8\" value=\"&lt;font data-font-src=&quot;https://fonts.googleapis.com/css?family=Maven+Pro&quot; face=&quot;Maven Pro&quot; color=&quot;#ffffff&quot;&gt;&lt;b&gt;&lt;font style=&quot;font-size: 20px;&quot;&gt;Fastq&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;strokeWidth=2;fillColor=#000000;\" vertex=\"1\" parent=\"2\"><mxGeometry x=\"10\" y=\"50\" width=\"90\" height=\"40\" as=\"geometry\"/></mxCell></root></mxGraphModel>", + "w": 100, + "h": 110, + "aspect": "fixed", + "title": "triple_file" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint as=\"sourcePoint\"/><mxPoint x=\"40\" as=\"targetPoint\"/></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 0.5714285714285714, + "aspect": "fixed", + "title": "line_0_bk" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;strokeColor=#7EB2DD;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint as=\"sourcePoint\"/><mxPoint x=\"40\" as=\"targetPoint\"/></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 0.5714285714285714, + "aspect": "fixed", + "title": "line_0_bl" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;strokeColor=#24B064;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint as=\"sourcePoint\"/><mxPoint x=\"40\" as=\"targetPoint\"/></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 0.5714285714285714, + "aspect": "fixed", + "title": "line_0_gr" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;strokeColor=#FF9914;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint as=\"sourcePoint\"/><mxPoint x=\"40\" as=\"targetPoint\"/></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 0.5714285714285714, + "aspect": "fixed", + "title": "line_0_or" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint as=\"sourcePoint\"/><mxPoint x=\"40\" y=\"40\" as=\"targetPoint\"/><Array as=\"points\"><mxPoint x=\"20\"/><mxPoint x=\"40\" y=\"20\"/></Array></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 40, + "aspect": "fixed", + "title": "line_90_WS" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint y=\"40\" as=\"sourcePoint\"/><mxPoint x=\"40\" as=\"targetPoint\"/><Array as=\"points\"><mxPoint x=\"20\" y=\"40\"/><mxPoint x=\"40\" y=\"20\"/></Array></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 40, + "aspect": "fixed", + "title": "line_90_WN" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint x=\"40\" y=\"40\" as=\"sourcePoint\"/><mxPoint as=\"targetPoint\"/><Array as=\"points\"><mxPoint x=\"20\" y=\"40\"/><mxPoint y=\"20\"/></Array></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 40, + "aspect": "fixed", + "title": "line_90_EN" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint x=\"40\" as=\"sourcePoint\"/><mxPoint y=\"40\" as=\"targetPoint\"/><Array as=\"points\"><mxPoint x=\"20\"/><mxPoint y=\"20\"/></Array></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 40, + "aspect": "fixed", + "title": "line_90_ES" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint as=\"sourcePoint\"/><mxPoint x=\"40\" y=\"20\" as=\"targetPoint\"/><Array as=\"points\"><mxPoint x=\"20\"/></Array></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 20, + "aspect": "fixed", + "title": "line_45_WS" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint y=\"20\" as=\"sourcePoint\"/><mxPoint x=\"40\" as=\"targetPoint\"/><Array as=\"points\"><mxPoint x=\"20\" y=\"20\"/></Array></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 20, + "aspect": "fixed", + "title": "line_45_WN" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint x=\"40\" y=\"20\" as=\"sourcePoint\"/><mxPoint as=\"targetPoint\"/><Array as=\"points\"><mxPoint x=\"20\" y=\"20\"/></Array></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 20, + "aspect": "fixed", + "title": "line_45_EN" + }, + { + "xml": "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"\" style=\"endArrow=none;html=1;rounded=1;strokeWidth=2;\" edge=\"1\" parent=\"1\"><mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\"><mxPoint x=\"40\" as=\"sourcePoint\"/><mxPoint y=\"20\" as=\"targetPoint\"/><Array as=\"points\"><mxPoint x=\"20\"/></Array></mxGeometry></mxCell></root></mxGraphModel>", + "w": 40, + "h": 20, + "aspect": "fixed", + "title": "line_45_ES" + } +] \ No newline at end of file diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 00000000..4a956863 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,49 @@ +# Development + +To contribute to this pipeline you will need to install the development environment: +This is possible only on linux or MacOs machine as Nextflow only work on these platform. + +```bash +conda env create -f environment.yml +conda activate nf-core-phaseimpute-1.0dev +``` + +## Add new module + +```bash +nf-core modules install +``` + +## Open questions + +How to use different schema ? +- Use nf-validation +For the moment use different input / step. +In the futur, if/else logic will be added in the yml nf-core schema. + +What's the use of dumpcustomsoftware ? +Will be deleted + +How to add to multiQC ? +Take exemple on Sarek. +All report file are in a dedicated channel. + +How to add nf-test ? +Add in `tests` folder and run with tag. +Add tags.yml + +How to run stub tests ? +Use nf-test + +How to run the tests ? +nf-test option tag + +What's the use of the template branch ? +TEMPLATE branch have the skeleton for all common part of the pipeline. +Will be asked to be merged to dev from time to time. + +When is it necessary to merge to master / main ? +First release, create a false PR to first commit that will be checked by whole community + 2 reviewers approval. + +What should be the Github action ? +All GA come from the TEMPLATE branch. diff --git a/docs/images/Logo.svg b/docs/images/Logo.svg new file mode 100644 index 00000000..9330090c --- /dev/null +++ b/docs/images/Logo.svg @@ -0,0 +1,208 @@ + + + + diff --git a/docs/images/metro/.$MetroMap.xml.bkp b/docs/images/metro/.$MetroMap.xml.bkp new file mode 100644 index 00000000..8f6dbcf9 --- /dev/null +++ b/docs/images/metro/.$MetroMap.xml.bkp @@ -0,0 +1,4844 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/metro/Concordance.png b/docs/images/metro/Concordance.png new file mode 100644 index 00000000..056c787e Binary files /dev/null and b/docs/images/metro/Concordance.png differ diff --git a/docs/images/metro/MetroMap.png b/docs/images/metro/MetroMap.png new file mode 100644 index 00000000..8c401e53 Binary files /dev/null and b/docs/images/metro/MetroMap.png differ diff --git a/docs/images/metro/MetroMap.xml b/docs/images/metro/MetroMap.xml new file mode 100644 index 00000000..f3e6e736 --- /dev/null +++ b/docs/images/metro/MetroMap.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/docs/images/metro/Phase.png b/docs/images/metro/Phase.png new file mode 100644 index 00000000..d920dfbf Binary files /dev/null and b/docs/images/metro/Phase.png differ diff --git a/docs/images/metro/PostProcessing.png b/docs/images/metro/PostProcessing.png new file mode 100644 index 00000000..2780766b Binary files /dev/null and b/docs/images/metro/PostProcessing.png differ diff --git a/docs/images/metro/PreProcessing.png b/docs/images/metro/PreProcessing.png new file mode 100644 index 00000000..c0964be4 Binary files /dev/null and b/docs/images/metro/PreProcessing.png differ diff --git a/docs/images/metro/Simulate.png b/docs/images/metro/Simulate.png new file mode 100644 index 00000000..a6d2f0eb Binary files /dev/null and b/docs/images/metro/Simulate.png differ diff --git a/docs/images/metro/txt2image.md b/docs/images/metro/txt2image.md new file mode 100644 index 00000000..abfe7cd7 --- /dev/null +++ b/docs/images/metro/txt2image.md @@ -0,0 +1,21 @@ +# Install desktop app + +Got to `https://github.com/jgraph/drawio-desktop/releases/` and download the latest version for your OS. + +To install it on wsl + +```bash +sudo apt install /mnt/c/Users/llenezet/Dowlnoads/drawio-amd64-21.6.8.deb +``` + +To use drawio + +```bash +drawio --version +drawio docs/images/metro/MetroMap.xml --export --format png --page-index 0 --output docs/images/metro/MetroMap.png --scale 3 +drawio docs/images/metro/MetroMap.xml --export --format png --layers 0 --page-index 1 --output docs/images/metro/PostProcessing.png --scale 3 +drawio docs/images/metro/MetroMap.xml --export --format png --layers 1 --page-index 1 --output docs/images/metro/Concordance.png --scale 3 +drawio docs/images/metro/MetroMap.xml --export --format png --layers 2 --page-index 1 --output docs/images/metro/Simulate.png --scale 3 +drawio docs/images/metro/MetroMap.xml --export --format png --layers 3 --page-index 1 --output docs/images/metro/Phase.png --scale 3 +drawio docs/images/metro/MetroMap.xml --export --format png --layers 4 --page-index 1 --output docs/images/metro/PreProcessing.png --scale 3 +``` diff --git a/docs/output.md b/docs/output.md index d7417cae..3b82d32d 100644 --- a/docs/output.md +++ b/docs/output.md @@ -2,14 +2,19 @@ ## Introduction +## Introduction + This document describes the output produced by the pipeline. Most of the plots are taken from the MultiQC report, which summarises results at the end of the pipeline. The directories listed below will be created in the results directory after the pipeline has finished. All paths are relative to the top-level results directory. +The directories listed below will be created in the results directory after the pipeline has finished. All paths are relative to the top-level results directory. + ## Pipeline overview +The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: - [FastQC](#fastqc) - Raw read QC @@ -51,6 +56,7 @@ The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They m +[MultiQC](http://multiqc.info) is a visualization tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in the report data directory. [MultiQC](http://multiqc.info) is a visualization tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in the report data directory. Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQC. The pipeline has special steps which also allow the software versions to be reported in the MultiQC output for future traceability. For more information about how to use MultiQC reports, see . diff --git a/docs/usage.md b/docs/usage.md index f419339a..20f92f3d 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -2,14 +2,21 @@ ## :warning: Please read this documentation on the nf-core website: [https://nf-co.re/phaseimpute/usage](https://nf-co.re/phaseimpute/usage) +> _Documentation of pipeline parameters is generated automatically from the pipeline schema and can no longer be found in markdown files._ +## :warning: Please read this documentation on the nf-core website: [https://nf-co.re/phaseimpute/usage](https://nf-co.re/phaseimpute/usage) + > _Documentation of pipeline parameters is generated automatically from the pipeline schema and can no longer be found in markdown files._ ## Introduction +## Samplesheet input + + ## Samplesheet input +You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row as shown in the examples below. You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row as shown in the examples below. ```bash @@ -58,6 +65,7 @@ The typical command for running the pipeline is as follows: ```bash nextflow run nf-core/phaseimpute --input ./samplesheet.csv --outdir ./results --genome GRCh37 -profile docker +nextflow run nf-core/phaseimpute --input ./samplesheet.csv --outdir ./results --genome GRCh37 -profile docker ``` This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. @@ -68,6 +76,9 @@ Note that the pipeline will create the following files in your working directory work # Directory containing the nextflow working files # Finished results in specified location (defined with --outdir) .nextflow_log # Log file from Nextflow +work # Directory containing the nextflow working files + # Finished results in specified location (defined with --outdir) +.nextflow_log # Log file from Nextflow # Other nextflow hidden files, eg. history of pipeline runs and old logs. ``` @@ -106,8 +117,10 @@ nextflow pull nf-core/phaseimpute ### Reproducibility +It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. +First, go to the [nf-core/phaseimpute releases page](https://github.com/nf-core/phaseimpute/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. First, go to the [nf-core/phaseimpute releases page](https://github.com/nf-core/phaseimpute/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. @@ -128,6 +141,7 @@ These options are part of Nextflow and use a _single_ hyphen (pipeline parameter Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. +Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Apptainer, Conda) - see below. Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Apptainer, Conda) - see below. :::info @@ -141,6 +155,25 @@ They are loaded in sequence, so later profiles can overwrite earlier profiles. If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer enviroment. +- `test` + - A profile with a complete configuration for automated testing + - Includes links to test data so needs no other parameters +- `docker` + - A generic configuration profile to be used with [Docker](https://docker.com/) +- `singularity` + - A generic configuration profile to be used with [Singularity](https://sylabs.io/docs/) +- `podman` + - A generic configuration profile to be used with [Podman](https://podman.io/) +- `shifter` + - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) +- `charliecloud` + - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) +- `apptainer` + - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) +- `conda` + - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter, Charliecloud, or Apptainer. +If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer enviroment. + - `test` - A profile with a complete configuration for automated testing - Includes links to test data so needs no other parameters @@ -161,6 +194,7 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof ### `-resume` +Specify this when restarting a pipeline. Nextflow will use cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. For input to be considered the same, not only the names must be identical but the files' contents as well. For more info about this parameter, see [this blog post](https://www.nextflow.io/blog/2019/demystifying-nextflow-resume.html). Specify this when restarting a pipeline. Nextflow will use cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. For input to be considered the same, not only the names must be identical but the files' contents as well. For more info about this parameter, see [this blog post](https://www.nextflow.io/blog/2019/demystifying-nextflow-resume.html). You can also supply a run name to resume a specific run: `-resume [run-name]`. Use the `nextflow log` command to show previous run names. @@ -216,9 +250,62 @@ Some HPC setups also allow you to run nextflow within a cluster job submitted yo ## Nextflow memory requirements +In some cases, the Nextflow Java virtual machines can start to request a large amount of memory. +We recommend adding the following line to your environment to limit this (typically in `~/.bashrc` or `~./bash_profile`): +Specify the path to a specific config file (this is a core Nextflow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information. + +## Custom configuration + +### Resource requests + +Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher requests (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. + +To change the resource requests, please see the [max resources](https://nf-co.re/docs/usage/configuration#max-resources) and [tuning workflow resources](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources) section of the nf-core website. + +### Custom Containers + +In some cases you may wish to change which container or conda environment a step of the pipeline uses for a particular tool. By default nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However in some cases the pipeline specified version maybe out of date. + +To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/usage/configuration#updating-tool-versions) section of the nf-core website. + +### Custom Tool Arguments + +A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. + +To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/usage/configuration#customising-tool-arguments) section of the nf-core website. + +### nf-core/configs + +In most cases, you will only need to create a custom config as a one-off but if you and others within your organisation are likely to be running nf-core pipelines regularly and need to use the same settings regularly it may be a good idea to request that your custom config file is uploaded to the `nf-core/configs` git repository. Before you do this please can you test that the config file works with your pipeline of choice using the `-c` parameter. You can then create a pull request to the `nf-core/configs` repository with the addition of your config file, associated documentation file (see examples in [`nf-core/configs/docs`](https://github.com/nf-core/configs/tree/master/docs)), and amending [`nfcore_custom.config`](https://github.com/nf-core/configs/blob/master/nfcore_custom.config) to include your custom profile. + +See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for more information about creating your own configuration files. + +If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). + +## Azure Resource Requests + +To be used with the `azurebatch` profile by specifying the `-profile azurebatch`. +We recommend providing a compute `params.vm_type` of `Standard_D16_v3` VMs by default but these options can be changed if required. + +Note that the choice of VM size depends on your quota and the overall workload during the analysis. +For a thorough list, please refer the [Azure Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes). + +## Running in the background + +Nextflow handles job submissions and supervises the running jobs. The Nextflow process must run until the pipeline is finished. + +The Nextflow `-bg` flag launches Nextflow in the background, detached from your terminal so that the workflow does not stop if you log out of your session. The logs are saved to a file. + +Alternatively, you can use `screen` / `tmux` or similar tool to create a detached session which you can log back into at a later time. +Some HPC setups also allow you to run nextflow within a cluster job submitted your job scheduler (from where it submits more jobs). + +## Nextflow memory requirements + In some cases, the Nextflow Java virtual machines can start to request a large amount of memory. We recommend adding the following line to your environment to limit this (typically in `~/.bashrc` or `~./bash_profile`): ```bash NXF_OPTS='-Xms1g -Xmx4g' ``` +NXF_OPTS='-Xms1g -Xmx4g' +``` diff --git a/lib/NfcoreTemplate.groovy b/lib/NfcoreTemplate.groovy new file mode 100644 index 00000000..408951ae --- /dev/null +++ b/lib/NfcoreTemplate.groovy @@ -0,0 +1,336 @@ +// +// This file holds several functions used within the nf-core pipeline template. +// + +import org.yaml.snakeyaml.Yaml + +class NfcoreTemplate { + + // + // Check AWS Batch related parameters have been specified correctly + // + public static void awsBatch(workflow, params) { + if (workflow.profile.contains('awsbatch')) { + // Check params.awsqueue and params.awsregion have been set if running on AWSBatch + assert (params.awsqueue && params.awsregion) : "Specify correct --awsqueue and --awsregion parameters on AWSBatch!" + // Check outdir paths to be S3 buckets if running on AWSBatch + assert params.outdir.startsWith('s3:') : "Outdir not on S3 - specify S3 Bucket to run on AWSBatch!" + } + } + + // + // Warn if a -profile or Nextflow config has not been provided to run the pipeline + // + public static void checkConfigProvided(workflow, log) { + if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { + log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + + " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + + " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + + " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + + "Please refer to the quick start section and usage docs for the pipeline.\n " + } + } + + // + // Generate version string + // + public static String version(workflow) { + String version_string = "" + + if (workflow.manifest.version) { + def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' + version_string += "${prefix_v}${workflow.manifest.version}" + } + + if (workflow.commitId) { + def git_shortsha = workflow.commitId.substring(0, 7) + version_string += "-g${git_shortsha}" + } + + return version_string + } + + // + // Construct and send completion email + // + public static void email(workflow, params, summary_params, projectDir, log, multiqc_report=[]) { + + // Set up the e-mail variables + def subject = "[$workflow.manifest.name] Successful: $workflow.runName" + if (!workflow.success) { + subject = "[$workflow.manifest.name] FAILED: $workflow.runName" + } + + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['Date Started'] = workflow.start + misc_fields['Date Completed'] = workflow.complete + misc_fields['Pipeline script file path'] = workflow.scriptFile + misc_fields['Pipeline script hash ID'] = workflow.scriptId + if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository + if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId + if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision + misc_fields['Nextflow Version'] = workflow.nextflow.version + misc_fields['Nextflow Build'] = workflow.nextflow.build + misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp + + def email_fields = [:] + email_fields['version'] = NfcoreTemplate.version(workflow) + email_fields['runName'] = workflow.runName + email_fields['success'] = workflow.success + email_fields['dateComplete'] = workflow.complete + email_fields['duration'] = workflow.duration + email_fields['exitStatus'] = workflow.exitStatus + email_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + email_fields['errorReport'] = (workflow.errorReport ?: 'None') + email_fields['commandLine'] = workflow.commandLine + email_fields['projectDir'] = workflow.projectDir + email_fields['summary'] = summary << misc_fields + + // On success try attach the multiqc report + def mqc_report = null + try { + if (workflow.success) { + mqc_report = multiqc_report.getVal() + if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { + if (mqc_report.size() > 1) { + log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" + } + mqc_report = mqc_report[0] + } + } + } catch (all) { + if (multiqc_report) { + log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" + } + } + + // Check if we are only sending emails on failure + def email_address = params.email + if (!params.email && params.email_on_fail && !workflow.success) { + email_address = params.email_on_fail + } + + // Render the TXT template + def engine = new groovy.text.GStringTemplateEngine() + def tf = new File("$projectDir/assets/email_template.txt") + def txt_template = engine.createTemplate(tf).make(email_fields) + def email_txt = txt_template.toString() + + // Render the HTML template + def hf = new File("$projectDir/assets/email_template.html") + def html_template = engine.createTemplate(hf).make(email_fields) + def email_html = html_template.toString() + + // Render the sendmail template + def max_multiqc_email_size = (params.containsKey('max_multiqc_email_size') ? params.max_multiqc_email_size : 0) as nextflow.util.MemoryUnit + def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "$projectDir", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] + def sf = new File("$projectDir/assets/sendmail_template.txt") + def sendmail_template = engine.createTemplate(sf).make(smail_fields) + def sendmail_html = sendmail_template.toString() + + // Send the HTML e-mail + Map colors = logColours(params.monochrome_logs) + if (email_address) { + try { + if (params.plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } + // Try to send HTML e-mail using sendmail + [ 'sendmail', '-t' ].execute() << sendmail_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" + } catch (all) { + // Catch failures and try with plaintext + def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] + if ( mqc_report.size() <= max_multiqc_email_size.toBytes() ) { + mail_cmd += [ '-A', mqc_report ] + } + mail_cmd.execute() << email_html + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" + } + } + + // Write summary e-mail HTML to a file + def output_d = new File("${params.outdir}/pipeline_info/") + if (!output_d.exists()) { + output_d.mkdirs() + } + def output_hf = new File(output_d, "pipeline_report.html") + output_hf.withWriter { w -> w << email_html } + def output_tf = new File(output_d, "pipeline_report.txt") + output_tf.withWriter { w -> w << email_txt } + } + + // + // Construct and send a notification to a web server as JSON + // e.g. Microsoft Teams and Slack + // + public static void IM_notification(workflow, params, summary_params, projectDir, log) { + def hook_url = params.hook_url + + def summary = [:] + for (group in summary_params.keySet()) { + summary << summary_params[group] + } + + def misc_fields = [:] + misc_fields['start'] = workflow.start + misc_fields['complete'] = workflow.complete + misc_fields['scriptfile'] = workflow.scriptFile + misc_fields['scriptid'] = workflow.scriptId + if (workflow.repository) misc_fields['repository'] = workflow.repository + if (workflow.commitId) misc_fields['commitid'] = workflow.commitId + if (workflow.revision) misc_fields['revision'] = workflow.revision + misc_fields['nxf_version'] = workflow.nextflow.version + misc_fields['nxf_build'] = workflow.nextflow.build + misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp + + def msg_fields = [:] + msg_fields['version'] = NfcoreTemplate.version(workflow) + msg_fields['runName'] = workflow.runName + msg_fields['success'] = workflow.success + msg_fields['dateComplete'] = workflow.complete + msg_fields['duration'] = workflow.duration + msg_fields['exitStatus'] = workflow.exitStatus + msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') + msg_fields['errorReport'] = (workflow.errorReport ?: 'None') + msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "") + msg_fields['projectDir'] = workflow.projectDir + msg_fields['summary'] = summary << misc_fields + + // Render the JSON template + def engine = new groovy.text.GStringTemplateEngine() + // Different JSON depending on the service provider + // Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format + def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json" + def hf = new File("$projectDir/assets/${json_path}") + def json_template = engine.createTemplate(hf).make(msg_fields) + def json_message = json_template.toString() + + // POST + def post = new URL(hook_url).openConnection(); + post.setRequestMethod("POST") + post.setDoOutput(true) + post.setRequestProperty("Content-Type", "application/json") + post.getOutputStream().write(json_message.getBytes("UTF-8")); + def postRC = post.getResponseCode(); + if (! postRC.equals(200)) { + log.warn(post.getErrorStream().getText()); + } + } + + // + // Print pipeline summary on completion + // + public static void summary(workflow, params, log) { + Map colors = logColours(params.monochrome_logs) + if (workflow.success) { + if (workflow.stats.ignoredCount == 0) { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + } + } else { + log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" + } + } + + // + // ANSII Colours used for terminal logging + // + public static Map logColours(Boolean monochrome_logs) { + Map colorcodes = [:] + + // Reset / Meta + colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" + colorcodes['bold'] = monochrome_logs ? '' : "\033[1m" + colorcodes['dim'] = monochrome_logs ? '' : "\033[2m" + colorcodes['underlined'] = monochrome_logs ? '' : "\033[4m" + colorcodes['blink'] = monochrome_logs ? '' : "\033[5m" + colorcodes['reverse'] = monochrome_logs ? '' : "\033[7m" + colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" + + // Regular Colors + colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" + colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" + colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" + colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" + colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" + colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" + colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" + colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" + + // Bold + colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" + colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" + colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" + colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" + colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" + colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" + colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" + colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" + + // Underline + colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" + colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" + colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" + colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" + colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" + colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" + colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" + colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" + + // High Intensity + colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" + colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" + colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" + colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" + colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" + colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" + colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" + colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" + + // Bold High Intensity + colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" + colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" + colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" + colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" + colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" + colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" + colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" + colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" + + return colorcodes + } + + // + // Does what is says on the tin + // + public static String dashedLine(monochrome_logs) { + Map colors = logColours(monochrome_logs) + return "-${colors.dim}----------------------------------------------------${colors.reset}-" + } + + // + // nf-core logo + // + public static String logo(workflow, monochrome_logs) { + Map colors = logColours(monochrome_logs) + String workflow_version = NfcoreTemplate.version(workflow) + String.format( + """\n + ${dashedLine(monochrome_logs)} + ${colors.green},--.${colors.black}/${colors.green},-.${colors.reset} + ${colors.blue} ___ __ __ __ ___ ${colors.green}/,-._.--~\'${colors.reset} + ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} + ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} + ${colors.green}`._,._,\'${colors.reset} + ${colors.purple} ${workflow.manifest.name} ${workflow_version}${colors.reset} + ${dashedLine(monochrome_logs)} + """.stripIndent() + ) + } +} diff --git a/lib/Utils.groovy b/lib/Utils.groovy new file mode 100644 index 00000000..8d030f4e --- /dev/null +++ b/lib/Utils.groovy @@ -0,0 +1,47 @@ +// +// This file holds several Groovy functions that could be useful for any Nextflow pipeline +// + +import org.yaml.snakeyaml.Yaml + +class Utils { + + // + // When running with -profile conda, warn if channels have not been set-up appropriately + // + public static void checkCondaChannels(log) { + Yaml parser = new Yaml() + def channels = [] + try { + def config = parser.load("conda config --show channels".execute().text) + channels = config.channels + } catch(NullPointerException | IOException e) { + log.warn "Could not verify conda channel configuration." + return + } + + // Check that all channels are present + // This channel list is ordered by required channel priority. + def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean + + // Check that they are in the right order + def channel_priority_violation = false + def n = required_channels_in_order.size() + for (int i = 0; i < n - 1; i++) { + channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) + } + + if (channels_missing | channel_priority_violation) { + log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " There is a problem with your Conda configuration!\n\n" + + " You will need to set-up the conda-forge and bioconda channels correctly.\n" + + " Please refer to https://bioconda.github.io/\n" + + " The observed channel order is \n" + + " ${channels}\n" + + " but the following channel order is required:\n" + + " ${required_channels_in_order}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + } + } +} diff --git a/lib/WorkflowMain.groovy b/lib/WorkflowMain.groovy new file mode 100644 index 00000000..8a6e7105 --- /dev/null +++ b/lib/WorkflowMain.groovy @@ -0,0 +1,63 @@ +// +// This file holds several functions specific to the main.nf workflow in the nf-core/phaseimpute pipeline +// + +import nextflow.Nextflow + +class WorkflowMain { + + // + // Citation string for pipeline + // + public static String citation(workflow) { + return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + + // TODO nf-core: Add Zenodo DOI for pipeline after first release + //"* The pipeline\n" + + //" https://doi.org/10.5281/zenodo.XXXXXXX\n\n" + + "* The nf-core framework\n" + + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + + "* Software dependencies\n" + + " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" + } + + + // + // Validate parameters and print summary to screen + // + public static void initialise(workflow, params, log) { + + // Print workflow version and exit on --version + if (params.version) { + String workflow_version = NfcoreTemplate.version(workflow) + log.info "${workflow.manifest.name} ${workflow_version}" + System.exit(0) + } + + // Check that a -profile or Nextflow config has been provided to run the pipeline + NfcoreTemplate.checkConfigProvided(workflow, log) + + // Check that conda channels are set-up correctly + if (workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + Utils.checkCondaChannels(log) + } + + // Check AWS batch settings + NfcoreTemplate.awsBatch(workflow, params) + + // Check input has been provided + if (!params.input) { + Nextflow.error("Please provide an input samplesheet to the pipeline e.g. '--input samplesheet.csv'") + } + } + // + // Get attribute from genome config file e.g. fasta + // + public static Object getGenomeAttribute(params, attribute) { + if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { + if (params.genomes[ params.genome ].containsKey(attribute)) { + return params.genomes[ params.genome ][ attribute ] + } + } + return null + } +} diff --git a/lib/WorkflowPhaseimpute.groovy b/lib/WorkflowPhaseimpute.groovy new file mode 100644 index 00000000..982c0c86 --- /dev/null +++ b/lib/WorkflowPhaseimpute.groovy @@ -0,0 +1,122 @@ +// +// This file holds several functions specific to the workflow/phaseimpute.nf in the nf-core/phaseimpute pipeline +// + +import nextflow.Nextflow +import groovy.text.SimpleTemplateEngine + +class WorkflowPhaseimpute { + + // + // Check and validate parameters + // + public static void initialise(params, log) { + + genomeExistsError(params, log) + + + if (!params.fasta) { + Nextflow.error "Genome fasta file not specified with e.g. '--fasta genome.fa' or via a detectable config file." + } + } + + // + // Get workflow summary for MultiQC + // + public static String paramsSummaryMultiqc(workflow, summary) { + String summary_section = '' + for (group in summary.keySet()) { + def group_params = summary.get(group) // This gets the parameters of that particular group + if (group_params) { + summary_section += "

$group

\n" + summary_section += "
\n" + for (param in group_params.keySet()) { + summary_section += "
$param
${group_params.get(param) ?: 'N/A'}
\n" + } + summary_section += "
\n" + } + } + + String yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" + yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" + yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" + yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" + yaml_file_text += "plot_type: 'html'\n" + yaml_file_text += "data: |\n" + yaml_file_text += "${summary_section}" + return yaml_file_text + } + + // + // Generate methods description for MultiQC + // + + public static String toolCitationText(params) { + + // TODO Optionally add in-text citation tools to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "Tool (Foo et al. 2023)" : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def citation_text = [ + "Tools used in the workflow included:", + "FastQC (Andrews 2010),", + "MultiQC (Ewels et al. 2016)", + "." + ].join(' ').trim() + + return citation_text + } + + public static String toolBibliographyText(params) { + + // TODO Optionally add bibliographic entries to this list. + // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "
  • Author (2023) Pub name, Journal, DOI
  • " : "", + // Uncomment function in methodsDescriptionText to render in MultiQC report + def reference_text = [ + "
  • Andrews S, (2010) FastQC, URL: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/).
  • ", + "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics , 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " + ].join(' ').trim() + + return reference_text + } + + public static String methodsDescriptionText(run_workflow, mqc_methods_yaml, params) { + // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file + def meta = [:] + meta.workflow = run_workflow.toMap() + meta["manifest_map"] = run_workflow.manifest.toMap() + + // Pipeline DOI + meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" + meta["nodoi_text"] = meta.manifest_map.doi ? "": "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " + + // Tool references + meta["tool_citations"] = "" + meta["tool_bibliography"] = "" + + // TODO Only uncomment below if logic in toolCitationText/toolBibliographyText has been filled! + //meta["tool_citations"] = toolCitationText(params).replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") + //meta["tool_bibliography"] = toolBibliographyText(params) + + + def methods_text = mqc_methods_yaml.text + + def engine = new SimpleTemplateEngine() + def description_html = engine.createTemplate(methods_text).make(meta) + + return description_html + } + + // + // Exit pipeline if incorrect --genome key provided + // + private static void genomeExistsError(params, log) { + if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { + def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + + " Currently, the available genome keys are:\n" + + " ${params.genomes.keySet().join(", ")}\n" + + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + Nextflow.error(error_string) + } + } +} diff --git a/lib/nfcore_external_java_deps.jar b/lib/nfcore_external_java_deps.jar new file mode 100644 index 00000000..805c8bb5 Binary files /dev/null and b/lib/nfcore_external_java_deps.jar differ diff --git a/main.nf b/main.nf index fdb2b251..97671036 100644 --- a/main.nf +++ b/main.nf @@ -1,5 +1,11 @@ #!/usr/bin/env nextflow /* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + nf-core/phaseimpute +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Github : https://github.com/nf-core/phaseimpute + Website: https://nf-co.re/phaseimpute + Slack : https://nfcore.slack.com/channels/phaseimpute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ nf-core/phaseimpute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/modules.json b/modules.json index da1b3812..8e361457 100644 --- a/modules.json +++ b/modules.json @@ -5,20 +5,151 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { + "bcftools/annotate": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": ["modules"] + }, + "bcftools/index": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": [ + "multiple_impute_glimpse2", + "modules", + "vcf_impute_glimpse", + "vcf_phase_shapeit5" + ] + }, + "bcftools/norm": { + "branch": "master", + "git_sha": "0435e4eebc94e53721c194b2d5d06f455a79e407", + "installed_by": ["modules"] + }, + "bcftools/query": { + "branch": "master", + "git_sha": "b5cc8edd887e27c51a48387e34549d4405d9769f", + "installed_by": ["modules"] + }, + "bcftools/view": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": ["modules"] + }, + "bedtools/makewindows": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": ["vcf_phase_shapeit5"] + }, + "custom/dumpsoftwareversions": { + "branch": "master", + "git_sha": "05c280924b6c768d484c7c443dad5e605c4ff4b4", + "installed_by": ["modules"] + }, "fastqc": { "branch": "master", - "git_sha": "f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c", + "git_sha": "9a4517e720bc812e95b56d23d15a1653b6db4f53", "installed_by": ["modules"] }, + "glimpse/chunk": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": ["vcf_impute_glimpse", "modules"] + }, + "glimpse/ligate": { + "branch": "master", + "git_sha": "36cfa4c2a7e538832c50f40cb16d159e84cd3305", + "installed_by": ["vcf_impute_glimpse"] + }, + "glimpse/phase": { + "branch": "master", + "git_sha": "36cfa4c2a7e538832c50f40cb16d159e84cd3305", + "installed_by": ["vcf_impute_glimpse"] + }, + "glimpse2/chunk": { + "branch": "master", + "git_sha": "36cfa4c2a7e538832c50f40cb16d159e84cd3305", + "installed_by": ["multiple_impute_glimpse2"] + }, + "glimpse2/ligate": { + "branch": "master", + "git_sha": "36cfa4c2a7e538832c50f40cb16d159e84cd3305", + "installed_by": ["multiple_impute_glimpse2"] + }, + "glimpse2/phase": { + "branch": "master", + "git_sha": "36cfa4c2a7e538832c50f40cb16d159e84cd3305", + "installed_by": ["multiple_impute_glimpse2"] + }, + "glimpse2/splitreference": { + "branch": "master", + "git_sha": "36cfa4c2a7e538832c50f40cb16d159e84cd3305", + "installed_by": ["multiple_impute_glimpse2"] + }, "multiqc": { "branch": "master", "git_sha": "b7ebe95761cd389603f9cc0e0dc384c0f663815a", "installed_by": ["modules"] + }, + "samtools/coverage": { + "branch": "master", + "git_sha": "2fe9363ae3b3ab1c79f43dae9b1a4074694c57d6", + "installed_by": ["modules"] + }, + "samtools/faidx": { + "branch": "master", + "git_sha": "fd742419940e01ba1c5ecb172c3e32ec840662fe", + "installed_by": ["modules"] + }, + "samtools/index": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": ["modules"] + }, + "samtools/view": { + "branch": "master", + "git_sha": "3ffae3598260a99e8db3207dead9f73f87f90d1f", + "installed_by": ["modules"], + "patch": "modules/nf-core/samtools/view/samtools-view.diff" + }, + "shapeit5/ligate": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": ["vcf_phase_shapeit5"] + }, + "shapeit5/phasecommon": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": ["vcf_phase_shapeit5"] + }, + "tabix/bgzip": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": ["modules"] + }, + "tabix/tabix": { + "branch": "master", + "git_sha": "911696ea0b62df80e900ef244d7867d177971f73", + "installed_by": ["modules"] } } }, "subworkflows": { "nf-core": { + "multiple_impute_glimpse2": { + "branch": "master", + "git_sha": "dedc0e31087f3306101c38835d051bf49789445a", + "installed_by": ["subworkflows"] + }, + "vcf_impute_glimpse": { + "branch": "master", + "git_sha": "74d79f1853c9ff2961e6061aad3c68d728d5c20d", + "installed_by": ["subworkflows"] + }, + "vcf_phase_shapeit5": { + "branch": "master", + "git_sha": "dedc0e31087f3306101c38835d051bf49789445a", + "installed_by": ["subworkflows"] + }, "utils_nextflow_pipeline": { "branch": "master", "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", diff --git a/modules/nf-core/bcftools/annotate/main.nf b/modules/nf-core/bcftools/annotate/main.nf new file mode 100644 index 00000000..222f07d7 --- /dev/null +++ b/modules/nf-core/bcftools/annotate/main.nf @@ -0,0 +1,65 @@ +process BCFTOOLS_ANNOTATE { + tag "$meta.id" + label 'process_low' + + conda "bioconda::bcftools=1.17" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bcftools:1.17--haef29d1_0': + 'biocontainers/bcftools:1.17--haef29d1_0' }" + + input: + tuple val(meta), path(input), path(index), path(annotations), path(annotations_index), path(header_lines) + + output: + tuple val(meta), path("*.{vcf,vcf.gz,bcf,bcf.gz}"), emit: vcf + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def header_file = header_lines ? "--header-lines ${header_lines}" : '' + def annotations_file = annotations ? "--annotations ${annotations}" : '' + def rename_chr_cmd = rename_chr ? "--rename-chrs ${rename_chr}" : '' + def extension = args.contains("--output-type b") || args.contains("-Ob") ? "bcf.gz" : + args.contains("--output-type u") || args.contains("-Ou") ? "bcf" : + args.contains("--output-type z") || args.contains("-Oz") ? "vcf.gz" : + args.contains("--output-type v") || args.contains("-Ov") ? "vcf" : + "vcf" + if ("$input" == "${prefix}.${extension}") error "Input and output names are the same, set prefix in module configuration to disambiguate!" + """ + bcftools \\ + annotate \\ + $args \\ + $annotations_file \\ + $header_file \\ + $rename_chr_cmd \\ + --output ${prefix}.${extension} \\ + --threads $task.cpus \\ + $input + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$( bcftools --version |& sed '1!d; s/^.*bcftools //' ) + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def extension = args.contains("--output-type b") || args.contains("-Ob") ? "bcf.gz" : + args.contains("--output-type u") || args.contains("-Ou") ? "bcf" : + args.contains("--output-type z") || args.contains("-Oz") ? "vcf.gz" : + args.contains("--output-type v") || args.contains("-Ov") ? "vcf" : + "vcf" + """ + touch ${prefix}.${extension} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$( bcftools --version |& sed '1!d; s/^.*bcftools //' ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/bcftools/annotate/meta.yml b/modules/nf-core/bcftools/annotate/meta.yml new file mode 100644 index 00000000..60f053ea --- /dev/null +++ b/modules/nf-core/bcftools/annotate/meta.yml @@ -0,0 +1,56 @@ +name: bcftools_annotate +description: Add or remove annotations. +keywords: + - bcftools + - annotate + - vcf + - remove + - add +tools: + - annotate: + description: Add or remove annotations. + homepage: http://samtools.github.io/bcftools/bcftools.html + documentation: https://samtools.github.io/bcftools/bcftools.html#annotate + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input: + type: file + description: Query VCF or BCF file, can be either uncompressed or compressed + - index: + type: file + description: Index of the query VCF or BCF file + - annotations: + type: file + description: Bgzip-compressed file with annotations + - annotations_index: + type: file + description: Index of the annotations file + - header_lines: + type: file + description: Contains lines to append to the output VCF header + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - vcf: + type: file + description: Compressed annotated VCF file + pattern: "*{vcf,vcf.gz,bcf,bcf.gz}" + +authors: + - "@projectoriented" + - "@ramprasadn" diff --git a/modules/nf-core/bcftools/index/main.nf b/modules/nf-core/bcftools/index/main.nf new file mode 100644 index 00000000..43360aab --- /dev/null +++ b/modules/nf-core/bcftools/index/main.nf @@ -0,0 +1,37 @@ +process BCFTOOLS_INDEX { + tag "$meta.id" + label 'process_low' + + conda "bioconda::bcftools=1.17" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bcftools:1.17--haef29d1_0': + 'biocontainers/bcftools:1.17--haef29d1_0' }" + + input: + tuple val(meta), path(vcf) + + output: + tuple val(meta), path("*.csi"), optional:true, emit: csi + tuple val(meta), path("*.tbi"), optional:true, emit: tbi + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + + """ + bcftools \\ + index \\ + $args \\ + --threads $task.cpus \\ + $vcf + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$(bcftools --version 2>&1 | head -n1 | sed 's/^.*bcftools //; s/ .*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/bcftools/index/meta.yml b/modules/nf-core/bcftools/index/meta.yml new file mode 100644 index 00000000..b883fa5f --- /dev/null +++ b/modules/nf-core/bcftools/index/meta.yml @@ -0,0 +1,49 @@ +name: bcftools_index +description: Index VCF tools +keywords: + - vcf + - index + - bcftools + - csi + - tbi +tools: + - bcftools: + description: BCFtools is a set of utilities that manipulate variant calls in the Variant Call Format (VCF) and its binary counterpart BCF. All commands work transparently with both VCFs and BCFs, both uncompressed and BGZF-compressed. Most commands accept VCF, bgzipped VCF and BCF with filetype detected automatically even when streaming from a pipe. Indexed VCF and BCF will work in all situations. Un-indexed VCF and BCF and streams will work in most, but not all situations. + homepage: https://samtools.github.io/bcftools/ + documentation: https://samtools.github.io/bcftools/howtos/index.html + tool_dev_url: https://github.com/samtools/bcftools + doi: "10.1093/gigascience/giab008" + licence: ["MIT", "GPL-3.0-or-later"] + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - VCF: + type: file + description: VCF file (optionally GZIPPED) + pattern: "*.{vcf,vcf.gz}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - version: + type: file + description: File containing software version + pattern: "versions.yml" + - csi: + type: file + description: Default VCF file index file + pattern: "*.csi" + - tbi: + type: file + description: Alternative VCF file index file for larger files (activated with -t parameter) + pattern: "*.tbi" + +authors: + - "@jfy133" diff --git a/modules/nf-core/bcftools/norm/main.nf b/modules/nf-core/bcftools/norm/main.nf new file mode 100644 index 00000000..608f20a1 --- /dev/null +++ b/modules/nf-core/bcftools/norm/main.nf @@ -0,0 +1,60 @@ +process BCFTOOLS_NORM { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::bcftools=1.17" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bcftools:1.17--haef29d1_0': + 'biocontainers/bcftools:1.17--haef29d1_0' }" + + input: + tuple val(meta), path(vcf), path(tbi) + tuple val(meta2), path(fasta) + + output: + tuple val(meta), path("*.{vcf,vcf.gz,bcf,bcf.gz}") , emit: vcf + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '--output-type z' + def prefix = task.ext.prefix ?: "${meta.id}" + def extension = args.contains("--output-type b") || args.contains("-Ob") ? "bcf.gz" : + args.contains("--output-type u") || args.contains("-Ou") ? "bcf" : + args.contains("--output-type z") || args.contains("-Oz") ? "vcf.gz" : + args.contains("--output-type v") || args.contains("-Ov") ? "vcf" : + "vcf.gz" + + """ + bcftools norm \\ + --fasta-ref ${fasta} \\ + --output ${prefix}.${extension}\\ + $args \\ + --threads $task.cpus \\ + ${vcf} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$(bcftools --version 2>&1 | head -n1 | sed 's/^.*bcftools //; s/ .*\$//') + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '--output-type z' + def prefix = task.ext.prefix ?: "${meta.id}" + def extension = args.contains("--output-type b") || args.contains("-Ob") ? "bcf.gz" : + args.contains("--output-type u") || args.contains("-Ou") ? "bcf" : + args.contains("--output-type z") || args.contains("-Oz") ? "vcf.gz" : + args.contains("--output-type v") || args.contains("-Ov") ? "vcf" : + "vcf.gz" + """ + touch ${prefix}.${extension} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$(bcftools --version 2>&1 | head -n1 | sed 's/^.*bcftools //; s/ .*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/bcftools/norm/meta.yml b/modules/nf-core/bcftools/norm/meta.yml new file mode 100644 index 00000000..33ebea36 --- /dev/null +++ b/modules/nf-core/bcftools/norm/meta.yml @@ -0,0 +1,58 @@ +name: bcftools_norm +description: Normalize VCF file +keywords: + - normalize + - norm + - variant calling + - VCF +tools: + - norm: + description: | + Normalize VCF files. + homepage: http://samtools.github.io/bcftools/bcftools.html + documentation: http://www.htslib.org/doc/bcftools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - vcf: + type: file + description: | + The vcf file to be normalized + e.g. 'file1.vcf' + pattern: "*.{vcf,vcf.gz}" + - tbi: + type: file + description: | + An optional index of the VCF file (for when the VCF is compressed) + pattern: "*.vcf.gz.tbi" + - meta2: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'genome' ] + - fasta: + type: file + description: FASTA reference file + pattern: "*.{fasta,fa}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - vcf: + type: file + description: One of uncompressed VCF (.vcf), compressed VCF (.vcf.gz), compressed BCF (.bcf.gz) or uncompressed BCF (.bcf) normalized output file + pattern: "*.{vcf,vcf.gz,bcf,bcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@abhi18av" + - "@ramprasadn" diff --git a/modules/nf-core/bcftools/query/main.nf b/modules/nf-core/bcftools/query/main.nf new file mode 100644 index 00000000..bff3654c --- /dev/null +++ b/modules/nf-core/bcftools/query/main.nf @@ -0,0 +1,56 @@ +process BCFTOOLS_QUERY { + tag "$meta.id" + label 'process_single' + + conda "bioconda::bcftools=1.17" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bcftools:1.17--haef29d1_0': + 'biocontainers/bcftools:1.17--haef29d1_0' }" + + input: + tuple val(meta), path(vcf), path(tbi) + path regions + path targets + path samples + + output: + tuple val(meta), path("*.${suffix}"), emit: output + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + suffix = task.ext.suffix ?: "txt" + def regions_file = regions ? "--regions-file ${regions}" : "" + def targets_file = targets ? "--targets-file ${targets}" : "" + def samples_file = samples ? "--samples-file ${samples}" : "" + """ + bcftools query \\ + $regions_file \\ + $targets_file \\ + $samples_file \\ + $args \\ + $vcf \\ + > ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$(bcftools --version 2>&1 | head -n1 | sed 's/^.*bcftools //; s/ .*\$//') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + suffix = task.ext.suffix ?: "txt" + """ + touch ${prefix}.${suffix} \\ + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$(bcftools --version 2>&1 | head -n1 | sed 's/^.*bcftools //; s/ .*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/bcftools/query/meta.yml b/modules/nf-core/bcftools/query/meta.yml new file mode 100644 index 00000000..67302ced --- /dev/null +++ b/modules/nf-core/bcftools/query/meta.yml @@ -0,0 +1,60 @@ +name: bcftools_query +description: Extracts fields from VCF or BCF files and outputs them in user-defined format. +keywords: + - query + - variant calling + - bcftools + - VCF +tools: + - query: + description: | + Extracts fields from VCF or BCF files and outputs them in user-defined format. + homepage: http://samtools.github.io/bcftools/bcftools.html + documentation: http://www.htslib.org/doc/bcftools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - vcf: + type: file + description: | + The vcf file to be qeuried. + pattern: "*.{vcf.gz, vcf}" + - tbi: + type: file + description: | + The tab index for the VCF file to be inspected. + pattern: "*.tbi" + - regions: + type: file + description: | + Optionally, restrict the operation to regions listed in this file. + - targets: + type: file + description: | + Optionally, restrict the operation to regions listed in this file (doesn't rely upon index files) + - samples: + type: file + description: | + Optional, file of sample names to be included or excluded. + e.g. 'file.tsv' +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - output: + type: file + description: BCFTools query output file + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@abhi18av" + - "@drpatelh" diff --git a/modules/nf-core/bcftools/view/main.nf b/modules/nf-core/bcftools/view/main.nf new file mode 100644 index 00000000..86f807d3 --- /dev/null +++ b/modules/nf-core/bcftools/view/main.nf @@ -0,0 +1,55 @@ +process BCFTOOLS_VIEW { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::bcftools=1.17" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bcftools:1.17--haef29d1_0': + 'biocontainers/bcftools:1.17--haef29d1_0' }" + + input: + tuple val(meta), path(vcf), path(index) + path(regions) + path(targets) + path(samples) + + output: + tuple val(meta), path("*.gz") , emit: vcf + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def regions_file = regions ? "--regions-file ${regions}" : "" + def targets_file = targets ? "--targets-file ${targets}" : "" + def samples_file = samples ? "--samples-file ${samples}" : "" + """ + bcftools view \\ + --output ${prefix}.vcf.gz \\ + ${regions_file} \\ + ${targets_file} \\ + ${samples_file} \\ + $args \\ + --threads $task.cpus \\ + ${vcf} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$(bcftools --version 2>&1 | head -n1 | sed 's/^.*bcftools //; s/ .*\$//') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.vcf.gz + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bcftools: \$(bcftools --version 2>&1 | head -n1 | sed 's/^.*bcftools //; s/ .*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/bcftools/view/meta.yml b/modules/nf-core/bcftools/view/meta.yml new file mode 100644 index 00000000..326fd1fa --- /dev/null +++ b/modules/nf-core/bcftools/view/meta.yml @@ -0,0 +1,63 @@ +name: bcftools_view +description: View, subset and filter VCF or BCF files by position and filtering expression. Convert between VCF and BCF +keywords: + - variant calling + - view + - bcftools + - VCF + +tools: + - view: + description: | + View, subset and filter VCF or BCF files by position and filtering expression. Convert between VCF and BCF + homepage: http://samtools.github.io/bcftools/bcftools.html + documentation: http://www.htslib.org/doc/bcftools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - vcf: + type: file + description: | + The vcf file to be inspected. + e.g. 'file.vcf' + - index: + type: file + description: | + The tab index for the VCF file to be inspected. + e.g. 'file.tbi' + - regions: + type: file + description: | + Optionally, restrict the operation to regions listed in this file. + e.g. 'file.vcf' + - targets: + type: file + description: | + Optionally, restrict the operation to regions listed in this file (doesn't rely upon index files) + e.g. 'file.vcf' + - samples: + type: file + description: | + Optional, file of sample names to be included or excluded. + e.g. 'file.tsv' +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - vcf: + type: file + description: VCF normalized output file + pattern: "*.{vcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@abhi18av" diff --git a/modules/nf-core/bedtools/makewindows/main.nf b/modules/nf-core/bedtools/makewindows/main.nf new file mode 100644 index 00000000..96dcff15 --- /dev/null +++ b/modules/nf-core/bedtools/makewindows/main.nf @@ -0,0 +1,49 @@ +process BEDTOOLS_MAKEWINDOWS { + tag "$meta.id" + label 'process_single' + + conda "bioconda::bedtools=2.30.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/bedtools:2.30.0--h7d7f7ad_1' : + 'biocontainers/bedtools:2.30.0--h7d7f7ad_1' }" + + input: + tuple val(meta), path(regions) + + output: + tuple val(meta), path("*.bed"), emit: bed + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def arg_input = regions.extension in ["bed", "tab"] ? "-b ${regions}" : "-g ${regions}" + if ("${regions}" == "${prefix}.bed") error "Input and output names are the same, set prefix in module configuration to disambiguate!" + """ + bedtools \\ + makewindows \\ + ${arg_input} \\ + ${args} \\ + > ${prefix}.bed + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bedtools: \$(bedtools --version | sed -e "s/bedtools v//g") + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + if ("${regions}" == "${prefix}.bed") error "Input and output names are the same, set prefix in module configuration to disambiguate!" + """ + touch ${prefix}.bed + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + bedtools: \$(bedtools --version | sed -e "s/bedtools v//g") + END_VERSIONS + """ +} diff --git a/modules/nf-core/bedtools/makewindows/meta.yml b/modules/nf-core/bedtools/makewindows/meta.yml new file mode 100644 index 00000000..f543da69 --- /dev/null +++ b/modules/nf-core/bedtools/makewindows/meta.yml @@ -0,0 +1,41 @@ +name: bedtools_makewindows +description: Makes adjacent or sliding windows across a genome or BED file. +keywords: + - bed + - windows + - fai + - chunking +tools: + - bedtools: + description: A set of tools for genomic analysis tasks, specifically enabling genome arithmetic (merge, count, complement) on various file types. + homepage: https://bedtools.readthedocs.io + documentation: https://bedtools.readthedocs.io/en/latest/content/tools/makewindows.html + doi: "10.1093/bioinformatics/btq033" + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - regions: + type: file + description: BED file OR Genome details file () + pattern: "*.{bed,tab,fai}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - bed: + type: file + description: BED file containing the windows + pattern: "*.bed" +authors: + - "@kevbrick" + - "@nvnieuwk" diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf new file mode 100644 index 00000000..c9d014b1 --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -0,0 +1,24 @@ +process CUSTOM_DUMPSOFTWAREVERSIONS { + label 'process_single' + + // Requires `pyyaml` which does not have a dedicated container but is in the MultiQC container + conda "bioconda::multiqc=1.15" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/multiqc:1.15--pyhdfd78af_0' : + 'biocontainers/multiqc:1.15--pyhdfd78af_0' }" + + input: + path versions + + output: + path "software_versions.yml" , emit: yml + path "software_versions_mqc.yml", emit: mqc_yml + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + template 'dumpsoftwareversions.py' +} diff --git a/modules/nf-core/custom/dumpsoftwareversions/meta.yml b/modules/nf-core/custom/dumpsoftwareversions/meta.yml new file mode 100644 index 00000000..c32657de --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/meta.yml @@ -0,0 +1,36 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/yaml-schema.json +name: custom_dumpsoftwareversions +description: Custom module used to dump software versions within the nf-core pipeline template +keywords: + - custom + - dump + - version +tools: + - custom: + description: Custom module used to dump software versions within the nf-core pipeline template + homepage: https://github.com/nf-core/tools + documentation: https://github.com/nf-core/tools + licence: ["MIT"] +input: + - versions: + type: file + description: YML file containing software versions + pattern: "*.yml" + +output: + - yml: + type: file + description: Standard YML file containing software versions + pattern: "software_versions.yml" + - mqc_yml: + type: file + description: MultiQC custom content YML file containing software versions + pattern: "software_versions_mqc.yml" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@drpatelh" + - "@grst" diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py new file mode 100644 index 00000000..e55b8d43 --- /dev/null +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python + + +"""Provide functions to merge multiple versions.yml files.""" + + +import platform +from textwrap import dedent + +import yaml + + +def _make_versions_html(versions): + """Generate a tabular HTML output of all versions for MultiQC.""" + html = [ + dedent( + """\\ + + + + + + + + + + """ + ) + ] + for process, tmp_versions in sorted(versions.items()): + html.append("") + for i, (tool, version) in enumerate(sorted(tmp_versions.items())): + html.append( + dedent( + f"""\\ + + + + + + """ + ) + ) + html.append("") + html.append("
    Process Name Software Version
    {process if (i == 0) else ''}{tool}{version}
    ") + return "\\n".join(html) + + +def main(): + """Load all version files and generate merged output.""" + versions_this_module = {} + versions_this_module["${task.process}"] = { + "python": platform.python_version(), + "yaml": yaml.__version__, + } + + with open("$versions") as f: + versions_by_process = yaml.load(f, Loader=yaml.BaseLoader) | versions_this_module + + # aggregate versions by the module name (derived from fully-qualified process name) + versions_by_module = {} + for process, process_versions in versions_by_process.items(): + module = process.split(":")[-1] + try: + if versions_by_module[module] != process_versions: + raise AssertionError( + "We assume that software versions are the same between all modules. " + "If you see this error-message it means you discovered an edge-case " + "and should open an issue in nf-core/tools. " + ) + except KeyError: + versions_by_module[module] = process_versions + + versions_by_module["Workflow"] = { + "Nextflow": "$workflow.nextflow.version", + "$workflow.manifest.name": "$workflow.manifest.version", + } + + versions_mqc = { + "id": "software_versions", + "section_name": "${workflow.manifest.name} Software Versions", + "section_href": "https://github.com/${workflow.manifest.name}", + "plot_type": "html", + "description": "are collected at run time from the software output.", + "data": _make_versions_html(versions_by_module), + } + + with open("software_versions.yml", "w") as f: + yaml.dump(versions_by_module, f, default_flow_style=False) + with open("software_versions_mqc.yml", "w") as f: + yaml.dump(versions_mqc, f, default_flow_style=False) + + with open("versions.yml", "w") as f: + yaml.dump(versions_this_module, f, default_flow_style=False) + + +if __name__ == "__main__": + main() diff --git a/modules/nf-core/glimpse/chunk/main.nf b/modules/nf-core/glimpse/chunk/main.nf new file mode 100644 index 00000000..f2ffed2f --- /dev/null +++ b/modules/nf-core/glimpse/chunk/main.nf @@ -0,0 +1,37 @@ +process GLIMPSE_CHUNK { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::glimpse-bio=1.1.1" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/glimpse-bio:1.1.1--h2ce4488_2': + 'biocontainers/glimpse-bio:1.1.1--hce55b13_1' }" + + input: + tuple val(meta), path(input), path(input_index), val(region) + + output: + tuple val(meta), path("*.txt"), emit: chunk_chr + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: "" + + """ + GLIMPSE_chunk \\ + $args \\ + --input $input \\ + --region $region \\ + --thread $task.cpus \\ + --output ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse: "\$(GLIMPSE_phase --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]')" + END_VERSIONS + """ +} diff --git a/modules/nf-core/glimpse/chunk/meta.yml b/modules/nf-core/glimpse/chunk/meta.yml new file mode 100644 index 00000000..9ac840a6 --- /dev/null +++ b/modules/nf-core/glimpse/chunk/meta.yml @@ -0,0 +1,53 @@ +name: "glimpse_chunk" +description: Defines chunks where to run imputation +keywords: + - chunk + - imputation + - low coverage +tools: + - "glimpse": + description: "GLIMPSE is a phasing and imputation method for large-scale low-coverage sequencing studies." + homepage: "https://odelaneau.github.io/GLIMPSE" + documentation: "https://odelaneau.github.io/GLIMPSE/commands.html" + tool_dev_url: "https://github.com/odelaneau/GLIMPSE" + doi: "10.1038/s41588-020-00756-0" + licence: "['MIT']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - input: + type: file + description: | + Target dataset in VCF/BCF format defined at all variable positions. + The file could possibly be without GT field (for efficiency reasons a file containing only the positions is recommended). + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + + - region: + type: string + description: | + Target region, usually a full chromosome (e.g. chr20:1000000-2000000 or chr20). + For chrX, please treat PAR and non-PAR regions as different choromosome in order to avoid mixing ploidy. +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - txt: + type: file + description: Tab delimited output txt file containing buffer and imputation regions. + pattern: "*.{txt}" + +authors: + - "@louislenezet" diff --git a/modules/nf-core/glimpse/ligate/main.nf b/modules/nf-core/glimpse/ligate/main.nf new file mode 100644 index 00000000..f9775bbf --- /dev/null +++ b/modules/nf-core/glimpse/ligate/main.nf @@ -0,0 +1,51 @@ +process GLIMPSE_LIGATE { + tag "$meta.id" + label 'process_low' + + conda "bioconda::glimpse-bio=1.1.1" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/glimpse-bio:1.1.1--hce55b13_1': + 'biocontainers/glimpse-bio:1.1.1--hce55b13_1' }" + + input: + tuple val(meta), path(input_list), path(input_index) + + output: + tuple val(meta), path("*.{vcf,bcf,vcf.gz,bcf.gz}"), emit: merged_variants + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def suffix = task.ext.suffix ?: "vcf.gz" + """ + printf "%s\\n" $input_list | tr -d '[],' > all_files.txt + + GLIMPSE_ligate \\ + $args \\ + --input all_files.txt \\ + --thread $task.cpus \\ + --output ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse: "\$(GLIMPSE_ligate --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]')" + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + def suffix = task.ext.suffix ?: "vcf.gz" + def args = task.ext.args ?: "" + """ + touch ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse: "\$(GLIMPSE_ligate --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]')" + END_VERSIONS + """ +} diff --git a/modules/nf-core/glimpse/ligate/meta.yml b/modules/nf-core/glimpse/ligate/meta.yml new file mode 100644 index 00000000..9a2a8daa --- /dev/null +++ b/modules/nf-core/glimpse/ligate/meta.yml @@ -0,0 +1,54 @@ +name: "glimpse_ligate" +description: Concatenates imputation chunks in a single VCF/BCF file ligating phased information. +keywords: + - ligate + - low-coverage + - glimpse + - imputation +tools: + - "glimpse": + description: "GLIMPSE is a phasing and imputation method for large-scale low-coverage sequencing studies." + homepage: "https://odelaneau.github.io/GLIMPSE" + documentation: "https://odelaneau.github.io/GLIMPSE/commands.html" + tool_dev_url: "https://github.com/odelaneau/GLIMPSE" + doi: "10.1038/s41588-020-00756-0" + licence: "['MIT']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - input_list: + type: file + description: VCF/BCF file containing genotype probabilities (GP field). + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + + - input_index: + type: file + description: Index file of the input VCF/BCF file containing genotype likelihoods. + pattern: "*.{vcf.gz.csi,bcf.gz.csi}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - merged_variants: + type: file + description: | + Output VCF/BCF file for the merged regions. + Phased information (HS field) is updated accordingly for the full region. + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + +authors: + - "@louislenezet" diff --git a/modules/nf-core/glimpse/phase/main.nf b/modules/nf-core/glimpse/phase/main.nf new file mode 100644 index 00000000..e2c73ea2 --- /dev/null +++ b/modules/nf-core/glimpse/phase/main.nf @@ -0,0 +1,58 @@ +process GLIMPSE_PHASE { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::glimpse-bio=1.1.1" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/glimpse-bio:1.1.1--h2ce4488_2': + 'biocontainers/glimpse-bio:1.1.1--hce55b13_1' }" + + input: + tuple val(meta) , path(input), path(input_index), path(samples_file), val(input_region), val(output_region), path(reference), path(reference_index), path(map) + + output: + tuple val(meta), path("*.{vcf,bcf,vcf.gz,bcf.gz}"), emit: phased_variant + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}_${input_region.replace(":","_")}" + def suffix = task.ext.suffix ?: "vcf.gz" + + def map_command = map ? "--map $map" :"" + def samples_file_command = samples_file ? "--samples-file $samples_file" :"" + + """ + GLIMPSE_phase \\ + $args \\ + --input $input \\ + --reference $reference \\ + $map_command \\ + $samples_file_command \\ + --input-region $input_region \\ + --output-region $output_region \\ + --thread $task.cpus \\ + --output ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse: "\$(GLIMPSE_phase --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]')" + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}_${input_region.replace(":","_")}" + def suffix = task.ext.suffix ?: "vcf.gz" + """ + touch ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse: "\$(GLIMPSE_phase --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]')" + END_VERSIONS + """ +} diff --git a/modules/nf-core/glimpse/phase/meta.yml b/modules/nf-core/glimpse/phase/meta.yml new file mode 100644 index 00000000..47da4de6 --- /dev/null +++ b/modules/nf-core/glimpse/phase/meta.yml @@ -0,0 +1,90 @@ +name: "glimpse_phase" +description: main GLIMPSE algorithm, performs phasing and imputation refining genotype likelihoods +keywords: + - phase + - imputation + - low-coverage + - glimpse + +tools: + - "glimpse": + description: "GLIMPSE is a phasing and imputation method for large-scale low-coverage sequencing studies." + homepage: "https://odelaneau.github.io/GLIMPSE" + documentation: "https://odelaneau.github.io/GLIMPSE/commands.html" + tool_dev_url: "https://github.com/odelaneau/GLIMPSE" + doi: "10.1038/s41588-020-00756-0" + licence: "['MIT']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - input: + type: file + description: Input VCF/BCF file containing genotype likelihoods. + pattern: "*.{vcf.gz,bcf.gz}" + + - input_index: + type: file + description: Index file of the input VCF/BCF file containing genotype likelihoods. + pattern: "*.{vcf.gz.csi,bcf.gz.csi}" + + - samples_file: + type: file + description: | + File with sample names and ploidy information. + One sample per line with a mandatory second column indicating ploidy (1 or 2). + Sample names that are not present are assumed to have ploidy 2 (diploids). + GLIMPSE does NOT handle the use of sex (M/F) instead of ploidy. + pattern: "*.{txt,tsv}" + + - input_region: + type: string + description: Target region used for imputation, including left and right buffers (e.g. chr20:1000000-2000000). + pattern: "chrXX:leftBufferPosition-rightBufferPosition" + + - output_region: + type: string + description: Target imputed region, excluding left and right buffers (e.g. chr20:1000000-2000000). + pattern: "chrXX:leftBufferPosition-rightBufferPosition" + + - reference: + type: file + description: Reference panel of haplotypes in VCF/BCF format. + pattern: "*.{vcf.gz,bcf.gz}" + + - reference_index: + type: file + description: Index file of the Reference panel file. + pattern: "*.{vcf.gz.csi,bcf.gz.csi}" + + - map: + type: file + description: File containing the genetic map. + pattern: "*.gmap" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - phased_variants: + type: file + description: | + Output VCF/BCF file containing genotype probabilities (GP field), + imputed dosages (DS field), best guess genotypes (GT field), + sampled haplotypes in the last (max 16) main iterations (HS field) and info-score. + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + +authors: + - "@louislenezet" diff --git a/modules/nf-core/glimpse2/chunk/main.nf b/modules/nf-core/glimpse2/chunk/main.nf new file mode 100644 index 00000000..2e848d8c --- /dev/null +++ b/modules/nf-core/glimpse2/chunk/main.nf @@ -0,0 +1,63 @@ +process GLIMPSE2_CHUNK { + tag "$meta.id" + label 'process_low' + + beforeScript """ + if cat /proc/cpuinfo | grep avx2 -q + then + echo "Feature AVX2 present on host" + else + echo "Feature AVX2 not present on host" + exit 1 + fi + """ + conda "bioconda::glimpse-bio=2.0.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/glimpse-bio:2.0.0--hf340a29_0': + 'biocontainers/glimpse-bio:2.0.0--hf340a29_0' }" + + input: + tuple val(meta) , path(input), path(input_index), val(region) + tuple val(meta2), path(map) + val(model) + + output: + tuple val(meta), path("*.txt"), emit: chunk_chr + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: "" + def map_cmd = map ? "--map ${map}":"" + + """ + GLIMPSE2_chunk \\ + $args \\ + $map_cmd \\ + --${model} \\ + --input $input \\ + --region $region \\ + --threads $task.cpus \\ + --output ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse2: "\$(GLIMPSE2_chunk --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -1)" + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: "" + """ + touch ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse2: "\$(GLIMPSE2_chunk --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -1)" + END_VERSIONS + """ +} diff --git a/modules/nf-core/glimpse2/chunk/meta.yml b/modules/nf-core/glimpse2/chunk/meta.yml new file mode 100644 index 00000000..fb8ae97f --- /dev/null +++ b/modules/nf-core/glimpse2/chunk/meta.yml @@ -0,0 +1,77 @@ +name: "glimpse2_chunk" +description: Defines chunks where to run imputation +keywords: + - chunk + - low-coverage + - imputation + - glimpse +tools: + - "glimpse2": + description: "GLIMPSE2 is a phasing and imputation method for large-scale low-coverage sequencing studies." + homepage: "https://odelaneau.github.io/GLIMPSE" + documentation: "https://odelaneau.github.io/GLIMPSE/commands.html" + tool_dev_url: "https://github.com/odelaneau/GLIMPSE" + doi: "10.1038/s41588-020-00756-0" + licence: "['MIT']" + +requirements: + - AVX2 + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - input: + type: file + description: | + Target dataset in VCF/BCF format defined at all variable positions. + The file could possibly be without GT field (for efficiency reasons a file containing only the positions is recommended). + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + + - input_index: + type: file + description: Index file of the input VCF/BCF file containing genotype likelihoods. + pattern: "*.{vcf.gz.csi,bcf.gz.csi}" + + - region: + type: string + description: | + Target region, usually a full chromosome (e.g. chr20:1000000-2000000 or chr20). + For chrX, please treat PAR and non-PAR regions as different choromosome in order to avoid mixing ploidy. + + - map: + type: file + description: File containing the genetic map. + pattern: "*.gmap" + + - model: + type: string + description: | + Algorithm model to use: + "recursive": Recursive algorithm + "sequential": Sequential algorithm (Recommended) + "uniform-number-variants": Experimental. Uniform the number of variants in the sequential algorithm + pattern: "{recursive,sequential,uniform-number-variants}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - txt: + type: file + description: Tab delimited output txt file containing buffer and imputation regions. + pattern: "*.{txt}" + +authors: + - "@louislenezet" diff --git a/modules/nf-core/glimpse2/ligate/main.nf b/modules/nf-core/glimpse2/ligate/main.nf new file mode 100644 index 00000000..97de22e1 --- /dev/null +++ b/modules/nf-core/glimpse2/ligate/main.nf @@ -0,0 +1,51 @@ +process GLIMPSE2_LIGATE { + tag "$meta.id" + label 'process_low' + + conda "bioconda::glimpse-bio=2.0.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/glimpse-bio:2.0.0--hf340a29_0': + 'biocontainers/glimpse-bio:2.0.0--hf340a29_0' }" + + input: + tuple val(meta), path(input_list), path(input_index) + + output: + tuple val(meta), path("*.{vcf,bcf,vcf.gz,bcf.gz}"), emit: merged_variants + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def suffix = task.ext.suffix ?: "vcf.gz" + """ + printf "%s\\n" $input_list | tr -d '[],' > all_files.txt + + GLIMPSE2_ligate \\ + $args \\ + --input all_files.txt \\ + --thread $task.cpus \\ + --output ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse2: "\$(GLIMPSE2_ligate --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -1)" + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def suffix = task.ext.suffix ?: "vcf.gz" + """ + touch ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse2: "\$(GLIMPSE2_ligate --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -1)" + END_VERSIONS + """ +} diff --git a/modules/nf-core/glimpse2/ligate/meta.yml b/modules/nf-core/glimpse2/ligate/meta.yml new file mode 100644 index 00000000..59400719 --- /dev/null +++ b/modules/nf-core/glimpse2/ligate/meta.yml @@ -0,0 +1,54 @@ +name: "glimpse2_ligate" +description: | + Ligatation of multiple phased BCF/VCF files into a single whole chromosome file. + GLIMPSE2 is run in chunks that are ligated into chromosome-wide files maintaining the phasing. +keywords: + - ligate + - low-coverage + - glimpse + - imputation +tools: + - "glimpse2": + description: "GLIMPSE2 is a phasing and imputation method for large-scale low-coverage sequencing studies." + homepage: "https://odelaneau.github.io/GLIMPSE" + documentation: "https://odelaneau.github.io/GLIMPSE/commands.html" + tool_dev_url: "https://github.com/odelaneau/GLIMPSE" + doi: "10.1038/s41588-020-00756-0" + licence: "['MIT']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - input_list: + type: file + description: VCF/BCF file containing genotype probabilities (GP field). + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + + - input_index: + type: file + description: Index file of the input VCF/BCF file containing genotype likelihoods. + pattern: "*.{csi,tbi}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - merged_variants: + type: file + description: Output ligated (phased) file in VCF/BCF format. + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + +authors: + - "@louislenezet" diff --git a/modules/nf-core/glimpse2/phase/main.nf b/modules/nf-core/glimpse2/phase/main.nf new file mode 100644 index 00000000..8ab9eb9b --- /dev/null +++ b/modules/nf-core/glimpse2/phase/main.nf @@ -0,0 +1,86 @@ +process GLIMPSE2_PHASE { + tag "$meta.id" + label 'process_medium' + + beforeScript """ + if cat /proc/cpuinfo | grep avx2 -q + then + echo "Feature AVX2 present on host" + else + echo "Feature AVX2 not present on host" + exit 1 + fi + """ + + conda "bioconda::glimpse-bio=2.0.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/glimpse-bio:2.0.0--hf340a29_0': + 'biocontainers/glimpse-bio:2.0.0--hf340a29_0' }" + + input: + tuple val(meta) , path(input), path(input_index), path(samples_file), val(input_region), val(output_region), path(reference), path(reference_index), path(map) + tuple val(meta2), path(fasta_reference), path(fasta_reference_index) + + output: + tuple val(meta), path("*.{vcf,bcf,bgen}"), emit: phased_variant + tuple val(meta), path("*.txt.gz") , emit: stats_coverage, optional: true + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def region = input_region ? "${output_region.replace(":","_")}" : "${reference}" + def args = task.ext.args ?: "" + def prefix = task.ext.prefix ?: "${meta.id}_${region}" + def suffix = task.ext.suffix ?: "bcf" + + def map_command = map ? "--map $map" : "" + def samples_file_command = samples_file ? "--samples-file $samples_file" : "" + def fasta_command = fasta_reference ? "--fasta $fasta_reference" : "" + def input_region_cmd = input_region ? "--input-region $input_region" : "" + def output_region_cmd = output_region ? "--output-region $output_region": "" + + def input_bam = input.any { it.extension in ["cram","bam"]} + + """ + if $input_bam + then + ls -1 | grep '\\.cram\$\\|\\.bam\$' > all_bam.txt + input_command="--bam-list all_bam.txt" + else + input_command="--input-gl $input" + fi + + GLIMPSE2_phase \\ + $args \\ + \$input_command \\ + --reference $reference \\ + $map_command \\ + $fasta_command \\ + $samples_file_command \\ + $input_region_cmd \\ + $output_region_cmd \\ + --thread $task.cpus \\ + --output ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse2: "\$(GLIMPSE2_phase --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -1)" + END_VERSIONS + """ + + stub: + def region = input_region ? "${output_region.replace(":","_")}" : "${reference}" + def args = task.ext.args ?: "" + def prefix = task.ext.prefix ?: "${meta.id}_${region}" + def suffix = task.ext.suffix ?: "bcf" + """ + touch ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse2: "\$(GLIMPSE2_phase --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -1)" + END_VERSIONS + """ +} diff --git a/modules/nf-core/glimpse2/phase/meta.yml b/modules/nf-core/glimpse2/phase/meta.yml new file mode 100644 index 00000000..5e5e88cb --- /dev/null +++ b/modules/nf-core/glimpse2/phase/meta.yml @@ -0,0 +1,114 @@ +name: "glimpse2_phase" +description: Tool for imputation and phasing from vcf file or directly from bam files. +keywords: + - phasing + - low-coverage + - imputation + - glimpse +tools: + - "glimpse2": + description: "GLIMPSE2 is a phasing and imputation method for large-scale low-coverage sequencing studies." + homepage: "https://odelaneau.github.io/GLIMPSE" + documentation: "https://odelaneau.github.io/GLIMPSE/commands.html" + tool_dev_url: "https://github.com/odelaneau/GLIMPSE" + doi: "10.1038/s41588-020-00756-0" + licence: "['MIT']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - input: + type: file + description: | + Either multiple BAM/CRAM files containing low-coverage sequencing reads or one VCF/BCF file containing the genotype likelihoods. + When using BAM/CRAM the name of the file is used as samples name. + pattern: "*.{bam,cram,vcf,vcf.gz,bcf,bcf.gz}" + + - input_index: + type: file + description: Index file of the input BAM/CRAM/VCF/BCF file. + pattern: "*.{bam.bai,cram.crai,vcf.gz.csi,bcf.gz.csi}" + + - samples_file: + type: file + description: | + File with sample names and ploidy information. + One sample per line with a mandatory second column indicating ploidy (1 or 2). + Sample names that are not present are assumed to have ploidy 2 (diploids). + GLIMPSE does NOT handle the use of sex (M/F) instead of ploidy. + pattern: "*.{txt,tsv}" + + - input_region: + type: string + description: | + Target region used for imputation, including left and right buffers (e.g. chr20:1000000-2000000). + Optional if reference panel is in bin format. + pattern: "chrXX:leftBufferPosition-rightBufferPosition" + + - output_region: + type: string + description: | + Target imputed region, excluding left and right buffers (e.g. chr20:1000000-2000000). + Optional if reference panel is in bin format. + pattern: "chrXX:leftBufferPosition-rightBufferPosition" + + - reference: + type: file + description: Reference panel of haplotypes in VCF/BCF format. + pattern: "*.{vcf.gz,bcf.gz}" + + - reference_index: + type: file + description: Index file of the Reference panel file. + pattern: "*.{vcf.gz.csi,bcf.gz.csi}" + + - map: + type: file + description: | + File containing the genetic map. + Optional if reference panel is in bin format. + pattern: "*.gmap" + + - fasta_reference: + type: file + description: | + Faidx-indexed reference sequence file in the appropriate genome build. + Necessary for CRAM files. + pattern: "*.fasta" + + - fasta_reference_index: + type: file + description: | + Faidx index of the reference sequence file in the appropriate genome build. + Necessary for CRAM files. + pattern: "*.fai" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - phased_variants: + type: file + description: | + Output VCF/BCF file containing genotype probabilities (GP field), imputed dosages (DS field), best guess genotypes (GT field), sampled haplotypes in the last (max 16) main iterations (HS field) and info-score. + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + + - stats_coverage: + type: file + description: Optional coverage statistic file created when BAM/CRAM files are used as inputs. + pattern: "*.txt.gz" + +authors: + - "@LouisLeNezet" diff --git a/modules/nf-core/glimpse2/splitreference/main.nf b/modules/nf-core/glimpse2/splitreference/main.nf new file mode 100644 index 00000000..a35d3020 --- /dev/null +++ b/modules/nf-core/glimpse2/splitreference/main.nf @@ -0,0 +1,64 @@ +process GLIMPSE2_SPLITREFERENCE { + tag "$meta.id" + label 'process_low' + + beforeScript """ + if cat /proc/cpuinfo | grep avx2 -q + then + echo "Feature AVX2 present" + else + echo "Feature AVX2 not present on node" + exit 1 + fi + """ + + conda "bioconda::glimpse-bio=2.0.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/glimpse-bio:2.0.0--hf340a29_0': + 'biocontainers/glimpse-bio:2.0.0--hf340a29_0' }" + + input: + tuple val(meta) , path(reference), path(reference_index), val(input_region), val(output_region) + tuple val(meta2), path(map) + + + output: + tuple val(meta), path("*.bin"), emit: bin_ref + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}_${output_region.replace(":","_")}" + def map_command = map ? "--map $map" : "" + + """ + GLIMPSE2_split_reference \\ + $args \\ + --reference $reference \\ + $map_command \\ + --input-region $input_region \\ + --output-region $output_region \\ + --thread $task.cpus \\ + --output ${prefix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse2: "\$(GLIMPSE2_split_reference --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -1)" + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}_${output_region.replace(":","_")}" + """ + touch ${prefix}.bin + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + glimpse2: "\$(GLIMPSE2_split_reference --help | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -1)" + END_VERSIONS + """ +} diff --git a/modules/nf-core/glimpse2/splitreference/meta.yml b/modules/nf-core/glimpse2/splitreference/meta.yml new file mode 100644 index 00000000..3a36b9ad --- /dev/null +++ b/modules/nf-core/glimpse2/splitreference/meta.yml @@ -0,0 +1,65 @@ +name: "glimpse2_splitreference" +description: Tool to create a binary reference panel for quick reading time. +keywords: + - split + - reference + - phasing +tools: + - "glimpse2": + description: "GLIMPSE2 is a phasing and imputation method for large-scale low-coverage sequencing studies." + homepage: "https://odelaneau.github.io/GLIMPSE" + documentation: "https://odelaneau.github.io/GLIMPSE/commands.html" + tool_dev_url: "https://github.com/odelaneau/GLIMPSE" + doi: "10.1038/s41588-020-00756-0" + licence: "['MIT']" +requirements: + - AVX2 +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - reference: + type: file + description: Reference panel of haplotypes in VCF/BCF format. + pattern: "*.{vcf.gz,bcf.gz}" + + - reference_index: + type: file + description: Index file of the Reference panel file. + pattern: "*.{vcf.gz.csi,bcf.gz.csi}" + + - input_region: + type: string + description: Target region used for imputation, including left and right buffers (e.g. chr20:1000000-2000000). + pattern: "chrXX:leftBufferPosition-rightBufferPosition" + + - output_region: + type: string + description: Target imputed region, excluding left and right buffers (e.g. chr20:1000000-2000000). + pattern: "chrXX:leftBufferPosition-rightBufferPosition" + + - map: + type: file + description: File containing the genetic map. + pattern: "*.gmap" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - bin_ref: + type: file + description: binary reference panel + pattern: "*.bin" + +authors: + - "@LouisLeNezet" diff --git a/modules/nf-core/samtools/coverage/main.nf b/modules/nf-core/samtools/coverage/main.nf new file mode 100644 index 00000000..02046525 --- /dev/null +++ b/modules/nf-core/samtools/coverage/main.nf @@ -0,0 +1,50 @@ +process SAMTOOLS_COVERAGE { + tag "$meta.id" + label 'process_single' + + conda "bioconda::samtools=1.17" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : + 'biocontainers/samtools:1.17--h00cdaf9_0' }" + + input: + tuple val(meta), path(input), path(input_index), val(region) + + output: + tuple val(meta), path("*.txt"), emit: coverage + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def region_cmd = region ? "--region ${region}" : '' + + """ + samtools \\ + coverage \\ + $args \\ + $region_cmd \\ + -o ${prefix}.txt \\ + $input + + 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}" + """ + touch ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//' ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/coverage/meta.yml b/modules/nf-core/samtools/coverage/meta.yml new file mode 100644 index 00000000..9becd3ea --- /dev/null +++ b/modules/nf-core/samtools/coverage/meta.yml @@ -0,0 +1,49 @@ +name: "samtools_coverage" +description: produces a histogram or table of coverage per chromosome +keywords: + - depth + - samtools + - bam +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input: + type: file + description: BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + - input_index: + type: file + description: BAM/CRAM index file + pattern: "*.{bai,crai}" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + - coverage: + type: file + description: Tabulated text containing the coverage at each position or region or an ASCII-art histogram (with --histogram). + pattern: "*.txt" + +authors: + - "@LouisLeNezet" diff --git a/modules/nf-core/samtools/faidx/main.nf b/modules/nf-core/samtools/faidx/main.nf new file mode 100644 index 00000000..59ed3088 --- /dev/null +++ b/modules/nf-core/samtools/faidx/main.nf @@ -0,0 +1,50 @@ +process SAMTOOLS_FAIDX { + tag "$fasta" + label 'process_single' + + conda "bioconda::samtools=1.17" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : + 'biocontainers/samtools:1.17--h00cdaf9_0' }" + + input: + tuple val(meta), path(fasta) + tuple val(meta2), path(fai) + + output: + tuple val(meta), path ("*.{fa,fasta}") , emit: fa , optional: true + tuple val(meta), path ("*.fai") , emit: fai, optional: true + tuple val(meta), path ("*.gzi") , emit: gzi, optional: true + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + samtools \\ + faidx \\ + $fasta \\ + $args + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + def match = (task.ext.args =~ /-o(?:utput)?\s(.*)\s?/).findAll() + def fastacmd = match[0] ? "touch ${match[0][1]}" : '' + """ + ${fastacmd} + touch ${fasta}.fai + + cat <<-END_VERSIONS > versions.yml + + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/faidx/meta.yml b/modules/nf-core/samtools/faidx/meta.yml new file mode 100644 index 00000000..957b25e5 --- /dev/null +++ b/modules/nf-core/samtools/faidx/meta.yml @@ -0,0 +1,57 @@ +name: samtools_faidx +description: Index FASTA file +keywords: + - index + - fasta + - faidx +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'test' ] + - fasta: + type: file + description: FASTA file + pattern: "*.{fa,fasta}" + - meta2: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'test' ] + - fai: + type: file + description: FASTA index file + pattern: "*.{fai}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fai: + type: file + description: FASTA index file + pattern: "*.{fai}" + - gzi: + type: file + description: Optional gzip index file for compressed inputs + pattern: "*.gzi" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@ewels" + - "@phue" diff --git a/modules/nf-core/samtools/index/main.nf b/modules/nf-core/samtools/index/main.nf new file mode 100644 index 00000000..0b20aa4b --- /dev/null +++ b/modules/nf-core/samtools/index/main.nf @@ -0,0 +1,48 @@ +process SAMTOOLS_INDEX { + tag "$meta.id" + label 'process_low' + + conda "bioconda::samtools=1.17" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : + 'biocontainers/samtools:1.17--h00cdaf9_0' }" + + input: + tuple val(meta), path(input) + + output: + tuple val(meta), path("*.bai") , optional:true, emit: bai + tuple val(meta), path("*.csi") , optional:true, emit: csi + tuple val(meta), path("*.crai"), optional:true, emit: crai + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + samtools \\ + index \\ + -@ ${task.cpus-1} \\ + $args \\ + $input + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + """ + touch ${input}.bai + touch ${input}.crai + touch ${input}.csi + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/index/meta.yml b/modules/nf-core/samtools/index/meta.yml new file mode 100644 index 00000000..8bd2fa6f --- /dev/null +++ b/modules/nf-core/samtools/index/meta.yml @@ -0,0 +1,53 @@ +name: samtools_index +description: Index SAM/BAM/CRAM file +keywords: + - index + - bam + - sam + - cram +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bai: + type: file + description: BAM/CRAM/SAM index file + pattern: "*.{bai,crai,sai}" + - crai: + type: file + description: BAM/CRAM/SAM index file + pattern: "*.{bai,crai,sai}" + - csi: + type: file + description: CSI index file + pattern: "*.{csi}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@ewels" + - "@maxulysse" diff --git a/modules/nf-core/samtools/view/main.nf b/modules/nf-core/samtools/view/main.nf new file mode 100644 index 00000000..be5a9676 --- /dev/null +++ b/modules/nf-core/samtools/view/main.nf @@ -0,0 +1,69 @@ +process SAMTOOLS_VIEW { + tag "$meta.id" + label 'process_low' + + conda "bioconda::samtools=1.17" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/samtools:1.17--h00cdaf9_0' : + 'biocontainers/samtools:1.17--h00cdaf9_0' }" + + input: + tuple val(meta), path(input), path(index), path(fasta), val(region), val(subsample) + path qname + + output: + tuple val(meta), path("*.bam"), emit: bam, optional: true + tuple val(meta), path("*.cram"), emit: cram, optional: true + tuple val(meta), path("*.sam"), emit: sam, optional: true + tuple val(meta), path("*.bai"), emit: bai, optional: true + tuple val(meta), path("*.csi"), emit: csi, optional: true + tuple val(meta), path("*.crai"), emit: crai, optional: true + 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 region_cmd = region ? "${region}" : "" + def subsample_cmd = subsample ? "--subsample ${subsample}" : "" + 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!" + """ + samtools \\ + view \\ + --threads ${task.cpus-1} \\ + ${reference} \\ + ${readnames} \\ + $args \\ + ${subsample_cmd} \\ + -o ${prefix}.${file_type} \\ + $input \\ + $args2 \\ + ${region_cmd} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.bam + touch ${prefix}.cram + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + samtools: \$(echo \$(samtools --version 2>&1) | sed 's/^.*samtools //; s/Using.*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/samtools/view/meta.yml b/modules/nf-core/samtools/view/meta.yml new file mode 100644 index 00000000..3b05450b --- /dev/null +++ b/modules/nf-core/samtools/view/meta.yml @@ -0,0 +1,84 @@ +name: samtools_view +description: filter/convert SAM/BAM/CRAM file +keywords: + - view + - bam + - sam + - cram +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input: + type: file + description: BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + - index: + type: file + description: BAM.BAI/BAM.CSI/CRAM.CRAI file (optional) + pattern: "*.{.bai,.csi,.crai}" + - meta2: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'test' ] + - fasta: + type: file + description: Reference file the CRAM was created with (optional) + pattern: "*.{fasta,fa}" + - qname: + type: file + description: Optional file with read names to output only select alignments + pattern: "*.{txt,list}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: optional filtered/converted BAM file + pattern: "*.{bam}" + - cram: + type: file + description: optional filtered/converted CRAM file + pattern: "*.{cram}" + - sam: + type: file + description: optional filtered/converted SAM file + pattern: "*.{sam}" + # bai, csi, and crai are created with `--write-index` + - bai: + type: file + description: optional BAM file index + pattern: "*.{bai}" + - csi: + type: file + description: optional tabix BAM file index + pattern: "*.{csi}" + - crai: + type: file + description: optional CRAM file index + pattern: "*.{crai}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@joseespinosa" + - "@FriederikeHanssen" + - "@priyanka-surana" diff --git a/modules/nf-core/samtools/view/samtools-view.diff b/modules/nf-core/samtools/view/samtools-view.diff new file mode 100644 index 00000000..0d94a071 --- /dev/null +++ b/modules/nf-core/samtools/view/samtools-view.diff @@ -0,0 +1,42 @@ +Changes in module 'nf-core/samtools/view' +--- modules/nf-core/samtools/view/main.nf ++++ modules/nf-core/samtools/view/main.nf +@@ -8,8 +8,7 @@ + 'biocontainers/samtools:1.17--h00cdaf9_0' }" + + input: +- tuple val(meta), path(input), path(index) +- tuple val(meta2), path(fasta) ++ tuple val(meta), path(input), path(index), path(fasta), val(region), val(depth) + path qname + + output: +@@ -25,11 +24,13 @@ + task.ext.when == null || task.ext.when + + script: +- def args = task.ext.args ?: '' +- def args2 = task.ext.args2 ?: '' ++ 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 reference = fasta ? "--reference ${fasta}" : "" ++ def readnames = qname ? "--qname-file ${qname}": "" ++ def region_cmd = region ? "-r ${region}" : "" ++ def depth_cmd = depth ? "-s ${depth}" : "" + def file_type = args.contains("--output-fmt sam") ? "sam" : + args.contains("--output-fmt bam") ? "bam" : + args.contains("--output-fmt cram") ? "cram" : +@@ -42,6 +43,8 @@ + ${reference} \\ + ${readnames} \\ + $args \\ ++ ${region_cmd} \\ ++ ${depth_cmd} \\ + -o ${prefix}.${file_type} \\ + $input \\ + $args2 + +************************************************************ diff --git a/modules/nf-core/shapeit5/ligate/main.nf b/modules/nf-core/shapeit5/ligate/main.nf new file mode 100644 index 00000000..79898758 --- /dev/null +++ b/modules/nf-core/shapeit5/ligate/main.nf @@ -0,0 +1,38 @@ +process SHAPEIT5_LIGATE { + tag "$meta.id" + label 'process_low' + + conda "bioconda::shapeit5=1.0.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/shapeit5:1.0.0--h0c8ee15_0': + 'biocontainers/shapeit5:1.0.0--h0c8ee15_0'}" + + input: + tuple val(meta), path(input_list), path (input_list_index) + + output: + tuple val(meta), path("*.{vcf,bcf,vcf.gz,bcf.gz}"), emit: merged_variants + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def suffix = task.ext.suffix ?: "vcf.gz" + """ + printf "%s\\n" $input_list | tr -d '[],' > all_files.txt + + SHAPEIT5_ligate \\ + $args \\ + --input all_files.txt \\ + --thread $task.cpus \\ + --output ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + shapeit5: "\$(SHAPEIT5_ligate | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -n 1)" + END_VERSIONS + """ +} diff --git a/modules/nf-core/shapeit5/ligate/meta.yml b/modules/nf-core/shapeit5/ligate/meta.yml new file mode 100644 index 00000000..bbc8e57e --- /dev/null +++ b/modules/nf-core/shapeit5/ligate/meta.yml @@ -0,0 +1,57 @@ +name: "shapeit5_ligate" +description: | + Ligate multiple phased BCF/VCF files into a single whole chromosome file. + Typically run to ligate multiple chunks of phased common variants. +keywords: + - ligate + - haplotype + - shapeit +tools: + - "shapeit5": + description: "Fast and accurate method for estimation of haplotypes (phasing)" + homepage: "https://odelaneau.github.io/shapeit5/" + documentation: "https://odelaneau.github.io/shapeit5/docs/documentation" + tool_dev_url: "https://github.com/odelaneau/shapeit5" + doi: "10.1101/2022.10.19.512867 " + licence: "['MIT']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - input_list: + type: file + description: | + VCF/BCF files containing genotype probabilities (GP field). + The files should be ordered by genomic position. + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + + - input_list_index: + type: file + description: VCF/BCF files index. + pattern: "*.csi" + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + + - merged_variants: + type: file + description: | + Output VCF/BCF file for the merged regions. + Phased information (HS field) is updated accordingly for the full region. + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + +authors: + - "@louislenezet" diff --git a/modules/nf-core/shapeit5/phasecommon/main.nf b/modules/nf-core/shapeit5/phasecommon/main.nf new file mode 100644 index 00000000..f63ed334 --- /dev/null +++ b/modules/nf-core/shapeit5/phasecommon/main.nf @@ -0,0 +1,52 @@ +process SHAPEIT5_PHASECOMMON { + tag "$meta.id" + label 'process_medium' + + conda "bioconda::shapeit5=1.0.0" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/shapeit5:1.0.0--h0c8ee15_0': + 'biocontainers/shapeit5:1.0.0--h0c8ee15_0'}" + + input: + tuple val(meta) , path(input), path(input_index), path(pedigree), val(region) + tuple val(meta2), path(reference), path(reference_index) + tuple val(meta3), path(scaffold), path(scaffold_index) + tuple val(meta4), path(map) + + output: + tuple val(meta), path("*.{vcf,bcf,vcf.gz,bcf.gz}"), emit: phased_variant + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + + def prefix = task.ext.prefix ?: "${meta.id}" + def suffix = task.ext.suffix ?: "vcf.gz" + if ("$input" == "${prefix}.${suffix}") error "Input and output names are the same, set prefix in module configuration to disambiguate!" + + def map_command = map ? "--map $map" : "" + def reference_command = reference ? "--reference $reference" : "" + def scaffold_command = scaffold ? "--scaffold $scaffold" : "" + def pedigree_command = pedigree ? "--pedigree $pedigree" : "" + + """ + SHAPEIT5_phase_common \\ + $args \\ + --input $input \\ + $map_command \\ + $reference_command \\ + $scaffold_command \\ + $pedigree_command \\ + --region $region \\ + --thread $task.cpus \\ + --output ${prefix}.${suffix} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + shapeit5: "\$(SHAPEIT5_phase_common | sed -nr '/Version/p' | grep -o -E '([0-9]+.){1,2}[0-9]' | head -1)" + END_VERSIONS + """ +} diff --git a/modules/nf-core/shapeit5/phasecommon/meta.yml b/modules/nf-core/shapeit5/phasecommon/meta.yml new file mode 100644 index 00000000..0cb5ab08 --- /dev/null +++ b/modules/nf-core/shapeit5/phasecommon/meta.yml @@ -0,0 +1,78 @@ +name: "shapeit5_phasecommon" +description: Tool to phase common sites, typically SNP array data, or the first step of WES/WGS data. +keywords: + - phasing + - haplotype + - shapeit +tools: + - "shapeit5": + description: "Fast and accurate method for estimation of haplotypes (phasing)" + homepage: "https://odelaneau.github.io/shapeit5/" + documentation: "https://odelaneau.github.io/shapeit5/docs/documentation" + tool_dev_url: "https://github.com/odelaneau/shapeit5" + doi: "10.1101/2022.10.19.512867 " + licence: "['MIT']" + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input: + type: file + description: | + Target dataset in VCF/BCF format defined at all variable positions. + The file could possibly be without GT field (for efficiency reasons a file containing only the positions is recommended). + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + - input_index: + type: file + description: Index file of the input VCF/BCF file containing genotype likelihoods. + pattern: "*.{vcf.gz.csi,bcf.gz.csi}" + - pedigree: + type: file + description: | + Pedigree information in the following format: offspring father mother. + pattern: "*.{txt, tsv}" + - region: + type: string + description: | + Target region, usually a full chromosome (e.g. chr20:1000000-2000000 or chr20). + For chrX, please treat PAR and non-PAR regions as different choromosome in order to avoid mixing ploidy. + pattern: "chrXX:leftBufferPosition-rightBufferPosition" + - reference: + type: file + description: Reference panel of haplotypes in VCF/BCF format. + pattern: "*.{vcf.gz,bcf.gz}" + - reference_index: + type: file + description: Index file of the Reference panel file. + pattern: "*.{vcf.gz.csi,bcf.gz.csi}" + - scaffold: + type: file + description: Scaffold of haplotypes in VCF/BCF format. + pattern: "*.{vcf.gz,bcf.gz}" + - scaffold_index: + type: file + description: Index file of the scaffold file. + pattern: "*.{vcf.gz.csi,bcf.gz.csi}" + - map: + type: file + description: File containing the genetic map. + pattern: "*.gmap" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - phased_variants: + type: file + description: Phased haplotypes in VCF/BCF format. + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@LouisLeNezet" diff --git a/modules/nf-core/tabix/bgzip/main.nf b/modules/nf-core/tabix/bgzip/main.nf new file mode 100644 index 00000000..8c47d9e2 --- /dev/null +++ b/modules/nf-core/tabix/bgzip/main.nf @@ -0,0 +1,54 @@ +process TABIX_BGZIP { + tag "$meta.id" + label 'process_single' + + conda "bioconda::tabix=1.11" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/tabix:1.11--hdfd78af_0' : + 'biocontainers/tabix:1.11--hdfd78af_0' }" + + input: + tuple val(meta), path(input) + + output: + tuple val(meta), path("${output}") , emit: output + tuple val(meta), path("${output}.gzi"), emit: gzi, optional: true + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + in_bgzip = ["gz", "bgz", "bgzf"].contains(input.getExtension()) + extension = in_bgzip ? input.getBaseName().tokenize(".")[-1] : input.getExtension() + output = in_bgzip ? "${prefix}.${extension}" : "${prefix}.${extension}.gz" + command = in_bgzip ? '-d' : '' + // Name the index according to $prefix, unless a name has been requested + if ((args.matches("(^| )-i\\b") || args.matches("(^| )--index(\$| )")) && !args.matches("(^| )-I\\b") && !args.matches("(^| )--index-name\\b")) { + args = args + " -I ${output}.gzi" + } + """ + bgzip $command -c $args -@${task.cpus} $input > ${output} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + tabix: \$(echo \$(tabix -h 2>&1) | sed 's/^.*Version: //; s/ .*\$//') + END_VERSIONS + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + in_bgzip = ["gz", "bgz", "bgzf"].contains(input.getExtension()) + output = in_bgzip ? input.getBaseName() : "${prefix}.${input.getExtension()}.gz" + + """ + touch ${output} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + tabix: \$(echo \$(tabix -h 2>&1) | sed 's/^.*Version: //; s/ .*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/tabix/bgzip/meta.yml b/modules/nf-core/tabix/bgzip/meta.yml new file mode 100644 index 00000000..c3ea2107 --- /dev/null +++ b/modules/nf-core/tabix/bgzip/meta.yml @@ -0,0 +1,47 @@ +name: tabix_bgzip +description: Compresses/decompresses files +keywords: + - compress + - decompress + - bgzip + - tabix +tools: + - bgzip: + description: | + Bgzip compresses or decompresses files in a similar manner to, and compatible with, gzip. + homepage: https://www.htslib.org/doc/tabix.html + documentation: http://www.htslib.org/doc/bgzip.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input: + type: file + description: file to compress or to decompress +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - output: + type: file + description: Output compressed/decompressed file + pattern: "*." + - gzi: + type: file + description: Optional gzip index file for compressed inputs + pattern: "*.gzi" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@joseespinosa" + - "@drpatelh" + - "@maxulysse" + - "@nvnieuwk" diff --git a/modules/nf-core/tabix/tabix/main.nf b/modules/nf-core/tabix/tabix/main.nf new file mode 100644 index 00000000..5bf332ef --- /dev/null +++ b/modules/nf-core/tabix/tabix/main.nf @@ -0,0 +1,42 @@ +process TABIX_TABIX { + tag "$meta.id" + label 'process_single' + + conda "bioconda::tabix=1.11" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/tabix:1.11--hdfd78af_0' : + 'biocontainers/tabix:1.11--hdfd78af_0' }" + + input: + tuple val(meta), path(tab) + + output: + tuple val(meta), path("*.tbi"), optional:true, emit: tbi + tuple val(meta), path("*.csi"), optional:true, emit: csi + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + tabix $args $tab + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + tabix: \$(echo \$(tabix -h 2>&1) | sed 's/^.*Version: //; s/ .*\$//') + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${tab}.tbi + cat <<-END_VERSIONS > versions.yml + + "${task.process}": + tabix: \$(echo \$(tabix -h 2>&1) | sed 's/^.*Version: //; s/ .*\$//') + END_VERSIONS + """ +} diff --git a/modules/nf-core/tabix/tabix/meta.yml b/modules/nf-core/tabix/tabix/meta.yml new file mode 100644 index 00000000..fcc6e524 --- /dev/null +++ b/modules/nf-core/tabix/tabix/meta.yml @@ -0,0 +1,45 @@ +name: tabix_tabix +description: create tabix index from a sorted bgzip tab-delimited genome file +keywords: + - index + - tabix + - vcf +tools: + - tabix: + description: Generic indexer for TAB-delimited genome position files. + homepage: https://www.htslib.org/doc/tabix.html + documentation: https://www.htslib.org/doc/tabix.1.html + doi: 10.1093/bioinformatics/btq671 + licence: ["MIT"] +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - tab: + type: file + description: TAB-delimited genome position file compressed with bgzip + pattern: "*.{bed.gz,gff.gz,sam.gz,vcf.gz}" +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - tbi: + type: file + description: tabix index file + pattern: "*.{tbi}" + - csi: + type: file + description: coordinate sorted index file + pattern: "*.{csi}" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@joseespinosa" + - "@drpatelh" + - "@maxulysse" diff --git a/nextflow.config b/nextflow.config index 399795d8..e72be4a1 100644 --- a/nextflow.config +++ b/nextflow.config @@ -8,21 +8,30 @@ // Global default params, used in configs params { + + // step + step = 'all' + input_region_string = null + input_region_file = "assets/regionsheet.csv" - // TODO nf-core: Specify your pipeline's command line flags // Input options input = null // References genome = null igenomes_base = 's3://ngi-igenomes/igenomes/' igenomes_ignore = false - fasta = null// MultiQC options + fasta = null + // MultiQC options multiqc_config = null multiqc_title = null multiqc_logo = null max_multiqc_email_size = '25.MB' multiqc_methods_description = null + // Simulate + depth = [1, 2] + genotype = null + // Boilerplate options outdir = null publish_dir_mode = 'copy' @@ -60,13 +69,26 @@ params { // Load base.config by default for all pipelines includeConfig 'conf/base.config' +// Load base.config by default for all pipelines +includeConfig 'conf/igenomes.config' + // Load nf-core custom profiles from different Institutions try { includeConfig "${params.custom_config_base}/nfcore_custom.config" + includeConfig "${params.custom_config_base}/nfcore_custom.config" } catch (Exception e) { System.err.println("WARNING: Could not load nf-core/config profiles: ${params.custom_config_base}/nfcore_custom.config") } +// Load nf-core/phaseimpute custom profiles from different institutions. +// Warning: Uncomment only if a pipeline-specific instititutional config already exists on nf-core/configs! +// try { +// includeConfig "${params.custom_config_base}/pipeline/phaseimpute.config" +// } catch (Exception e) { +// System.err.println("WARNING: Could not load nf-core/config/phaseimpute profiles: ${params.custom_config_base}/pipeline/phaseimpute.config") +// } + + // Load nf-core/phaseimpute custom profiles from different institutions. // Warning: Uncomment only if a pipeline-specific institutional config already exists on nf-core/configs! // try { diff --git a/nextflow_schema.json b/nextflow_schema.json index bfb9e9ae..c3dec469 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -5,12 +5,49 @@ "description": "Phasing and imputation pipeline", "type": "object", "definitions": { + "simulate": { + "title": "Simulate", + "type": "object", + "description": "Argument for the simulation mode", + "default": "", + "properties": { + "depth": { + "type": "array", + "default": [0.2, 0.5, 1], + "fa_icon": "fas fa-list-ol" + }, + "genotype": { + "type": "string", + "pattern": "^\\S+\\.(csv|tsv|txt)$", + "format": "file-path", + "mimetype": "text/csv" + } + } + }, + "panelprep": { + "title": "Panel preparation", + "type": "object", + "description": "Argument for the preparation of the reference panel", + "default": "", + "properties": { + "panel": { + "type": "string", + "fa_icon": "far fa-file-code", + "pattern": "^\\S+\\.(vcf|bcf)(\\.gz)?$", + "format": "file-path" + }, + "to_phase": { + "type": "boolean", + "pattern": "true|false" + } + } + }, "input_output_options": { "title": "Input/output options", "type": "object", "fa_icon": "fas fa-terminal", "description": "Define where the pipeline should find input data and save output data.", - "required": ["input", "outdir"], + "required": ["outdir"], "properties": { "input": { "type": "string", @@ -40,6 +77,12 @@ "type": "string", "description": "MultiQC report title. Printed as page header, used for filename if not otherwise specified.", "fa_icon": "fas fa-file-signature" + }, + "step": { + "type": "string", + "description": "Step to run.", + "fa_icon": "fas fa-step-forward", + "enum": ["simulate", "panelprep", "impute", "validate"] } } }, @@ -270,6 +313,9 @@ } }, "allOf": [ + { + "$ref": "#/definitions/simulate" + }, { "$ref": "#/definitions/input_output_options" }, diff --git a/subworkflows/local/bam_downsample.nf b/subworkflows/local/bam_downsample.nf new file mode 100644 index 00000000..bcc95a87 --- /dev/null +++ b/subworkflows/local/bam_downsample.nf @@ -0,0 +1,83 @@ +include { SAMTOOLS_COVERAGE } from '../../modules/nf-core/samtools/coverage/main.nf' +include { SAMTOOLS_INDEX as INDEX } from '../../modules/nf-core/samtools/index/main.nf' +include { SAMTOOLS_VIEW as VIEW_REGION } from '../../modules/nf-core/samtools/view/main.nf' +include { SAMTOOLS_VIEW as VIEW_DEPTH } from '../../modules/nf-core/samtools/view/main.nf' + +workflow BAM_DOWNSAMPLELE { + + take: + ch_bam // channel: [ [id, ref], bam, bai ] + ch_depth // channel: [ val(depth) ] + ch_fasta // channel: [ fasta ] + main: + + ch_versions = Channel.empty() + + // Add fasta and region to bam channel + ch_input_region = ch_bam + .combine(ch_fasta) + .combine(ch_region) + .map{ metaI, bam, index, fasta, metaR, region -> + [ metaI + metaR, bam, index, fasta, region ] + } + .combine(Channel.of([[]])) // depth parameter + + // Extract region of interest + VIEW_REGION(ch_input_region, []) + ch_versions = ch_versions.mix(VIEW_REGION.out.versions.first()) + + // Index region of interest + INDEX1 (VIEW_REGION.out.bam) + ch_versions = ch_versions.mix(INDEX1.out.versions.first()) + + // Add region to channel + ch_coverage = ch_bam + .map{ metaIR, bam, index -> + [ metaIR, bam, index, metaIR["region"] ] + } + + // Get coverage of the region + SAMTOOLS_COVERAGE ( ch_coverage ) // meta, bam, bai, region + ch_versions = ch_versions.mix(SAMTOOLS_COVERAGE.out.versions.first()) + + // Compute mean depth of the region + ch_mean_depth = SAMTOOLS_COVERAGE.out.coverage.view() + .splitCsv(header: true, sep:'\t') + .map{ metaIR, row -> + [ metaIR,"${row.meandepth}" as Float ] + } + + // Compute downsampling factor + ch_depth_factor = ch_mean_depth + .combine(ch_depth) + .map{ metaIR, mean, depth -> + [ metaIR, metaIR + ["depth":depth], depth as Float / mean ] + } + + // Add all necessary channel for downsampling + ch_input_downsample = ch_coverage + .combine(ch_fasta) + .combine(ch_depth_factor) + .map{ metaIR, bam, index, region, fasta, metaIRD, depth -> + [ metaIRD, bam, index, fasta, region, depth ] + } + + // Downsample + VIEW_DEPTH(ch_input_downsample, []) + ch_versions = ch_versions.mix(VIEW_DEPTH.out.versions.first()) + + // Index result + INDEX2(VIEW_DEPTH.out.bam) + ch_versions = ch_versions.mix(INDEX2.out.versions.first()) + + // Aggregate bam and index + ch_bam_region = VIEW_REGION.out.bam + .combine(INDEX1.out.bai) + ch_bam_emul = VIEW_DEPTH.out.bam + .combine(INDEX2.out.bai) + + emit: + bam_region = ch_bam_region // channel: [ metaIR, bam, bai ] + bam_emul = ch_bam_emul // channel: [ metaIRD, bam, bai ] + versions = ch_versions // channel: [ versions.yml ] +} diff --git a/subworkflows/local/bam_region.nf b/subworkflows/local/bam_region.nf new file mode 100644 index 00000000..52940088 --- /dev/null +++ b/subworkflows/local/bam_region.nf @@ -0,0 +1,37 @@ +include { SAMTOOLS_INDEX as INDEX1 } from '../../modules/nf-core/samtools/index/main.nf' +include { SAMTOOLS_VIEW as VIEW_REGION } from '../../modules/nf-core/samtools/view/main.nf' + +workflow BAM_REGION { + + take: + ch_bam // channel: [ [id, ref], bam, bai ] + ch_region // channel: [ [ref, region], val(chr:start-end) ] + ch_fasta // channel: [ fasta ] + main: + + ch_versions = Channel.empty() + + // Add fasta and region to bam channel + ch_input_region = ch_bam + .combine(ch_fasta) + .combine(ch_region) + .map{ meta, bam, index, fasta, metaR, region -> + [meta + metaR, bam, index, fasta, region] + } + .combine(Channel.of([[]])) // depth parameter + + // Extract region of interest + VIEW_REGION(ch_input_region, []) + ch_versions = ch_versions.mix(VIEW_REGION.out.versions.first()) + + // Index region of interest + INDEX1 (VIEW_REGION.out.bam) + ch_versions = ch_versions.mix(INDEX1.out.versions.first()) + + ch_bam_region = VIEW_REGION.bam + .combine(INDEX1.out.bai, by: 0) + + emit: + bam_region = ch_bam_region // channel: [ metaIR, bam, index ] + versions = ch_versions // channel: [ versions.yml ] +} \ No newline at end of file diff --git a/subworkflows/local/compute_gl.nf b/subworkflows/local/compute_gl.nf new file mode 100644 index 00000000..81ca597d --- /dev/null +++ b/subworkflows/local/compute_gl.nf @@ -0,0 +1,38 @@ +include { BCFTOOLS_MPILEUP } from '../../modules/nf-core/bcftools/mpileup/main.nf' +include { BCFTOOLS_INDEX } from '../../modules/nf-core/bcftools/index/main.nf' + + +workflow COMPUTE_GL { + + take: + ch_input // channel: [ [id, ref], bam, bai ] + ch_region // channel: [ [ref, region], fasta, val(region)] + ch_sites // channel: [ [id, region], sites, index] + ch_tsv // channel: [ [id, region], tsv, index] + + main: + + ch_versions = Channel.empty() + + ch_panel = ch_sites + .combine(ch_tsv, by:0) + ch_mpileup = ch_input + .map{ meta, bam, index -> [meta.subMap(["ref","region"]), meta, bam, index]} + .combine(ch_region, by:0) + .combine(ch_panel.map{metaIpRR,sites,tsv -> + [metaIpRR.subMap(["ref","region"]), metaIpRR, sites, tsv]}, + by:0) + .map{metaRR, metaIRR, bam, bindex, fasta, region, metaIpRR, sites, tsv -> + [metaIRR + ["panel": metaIpRR.panel], bam, fasta, sites, tsv]} + + BCFTOOLS_MPILEUP(ch_mpileup,[]) + ch_versions = ch_versions.mix(BCFTOOLS_MPILEUP.out.versions.first()) + + ch_output = BCFTOOLS_MPILEUP.out.vcf + combine(BCFTOOLS_MPILEUP.out.tbi, by:0) + + emit: + vcf = ch_output + stats = BCFTOOLS_MPILEUP.out.stats + versions = ch_versions // channel: [ versions.yml ] +} \ No newline at end of file diff --git a/subworkflows/local/get_panel.nf b/subworkflows/local/get_panel.nf new file mode 100644 index 00000000..06068a49 --- /dev/null +++ b/subworkflows/local/get_panel.nf @@ -0,0 +1,94 @@ +include { BCFTOOLS_VIEW as VIEW_VCF_SNPS } from '../../modules/nf-core/bcftools/view/main.nf' +include { BCFTOOLS_VIEW as VIEW_VCF_SITES } from '../../modules/nf-core/bcftools/view/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX1 } from '../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX3 } from '../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX4 } from '../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX5 } from '../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_NORM } from '../../modules/nf-core/bcftools/norm/main.nf' +include { BCFTOOLS_QUERY } from '../../modules/nf-core/bcftools/query/main.nf' +include { TABIX_BGZIP } from '../../modules/nf-core/tabix/bgzip/main' +include { TABIX_TABIX } from '../../modules/nf-core/tabix/tabix/main' +include { VCF_PHASE_SHAPEIT5 } from '../../subworkflows/nf-core/vcf_phase_shapeit5/main' + + +workflow GET_PANEL { + take: + ch_vcf // channel: [ [id, ref], vcf, index ] + ch_region // channel: [ [ref, region], val(region) ] + ch_fasta // channel: [ fasta ] + file_chr_rename // file rename + + main: + + ch_versions = Channel.empty() + + // Normalise the panel + ch_norm = ch_vcf + .combine(ch_fasta) + + BCFTOOLS_NORM(ch_norm) + ch_versions = ch_versions.mix(BCFTOOLS_NORM.out.versions.first()) + + // Extract only the SNP + VIEW_VCF_SNPS(BCFTOOLS_NORM.out.vcf + .combine(Channel.of([[],[]])), [], [], []) + ch_versions = ch_versions.mix(VIEW_VCF_SNPS.out.versions.first()) + + VCF_INDEX3(VIEW_VCF_SNPS.out.vcf) + ch_versions = ch_versions.mix(VCF_INDEX3.out.versions.first()) + + ch_panel_norm = VIEW_VCF_SNPS.out.vcf + .combine(VCF_INDEX3, by:0) + + // Extract sites positions + vcf_region = VIEW_VCF_SNPS.out.vcf + .combine(VCF_INDEX3.out.csi, by:0) + VIEW_VCF_SITES( vcf_region + .combine(Channel.of([[]])), + [], [], []) + ch_versions = ch_versions.mix(VIEW_VCF_SITES.out.versions.first()) + + VCF_INDEX4(VIEW_VCF_SITES.out.vcf) + ch_versions = ch_versions.mix(VCF_INDEX4.out.versions.first()) + + ch_panel_sites = VIEW_VCF_SITES.out.vcf + .combine(VCF_INDEX4, by:0) + + // Convert to TSV + BCFTOOLS_QUERY(VIEW_VCF_SITES.out.vcf + .combine(VCF_INDEX4.out.csi, by:0), + [], [], []) + ch_versions = ch_versions.mix(BCFTOOLS_QUERY.out.versions.first()) + + TABIX_BGZIP(BCFTOOLS_QUERY.out.txt) + ch_versions = ch_versions.mix(TABIX_BGZIP.out.versions.first()) + + TABIX_TABIX(TABIX_BGZIP.out.output) + ch_versions = ch_versions.mix(TABIX_TABIX.out.versions.first()) + + ch_panel_tsv = TABIX_BGZIP.out.output + .combine(TABIX_TABIX.out.tbi, by: 0) + + // Phase panel + if (params.phase_panel == true) { + VCF_PHASE_SHAPEIT5(vcf_region + .map { meta, vcf, csi -> [meta, vcf, csi, [], meta.region] }, + Channel.of([[],[],[]]).collect(), + Channel.of([[],[],[]]).collect(), + Channel.of([[],[]]).collect()) + ch_versions = ch_versions.mix(VCF_PHASE_SHAPEIT5.out.versions.first()) + ch_panel_phased = VCF_PHASE_SHAPEIT5.out.variants_phased + .combine(VCF_PHASE_SHAPEIT5.out.variants_index, by: 0) + } else { + ch_panel_phased = VIEW_VCF_SNPS.out.vcf + .combine(VCF_INDEX3.out.csi, by: 0) + } + + emit: + panel_norm = ch_panel_norm // channel: [ meta, vcf, index ] + panel_sites = ch_panel_sites // channel: [ meta, bcf, index ] + panel_tsv = ch_panel_tsv // channel: [ meta, tsv, index ] + panel_phased = ch_panel_phased // channel: [ meta, vcf, index ] + + versions = ch_versions // channel: [ versions.yml ] +} diff --git a/subworkflows/local/vcf_chr_rename.nf b/subworkflows/local/vcf_chr_rename.nf new file mode 100644 index 00000000..806deedd --- /dev/null +++ b/subworkflows/local/vcf_chr_rename.nf @@ -0,0 +1,27 @@ +include { BCFTOOLS_ANNOTATE } from '../../modules/nf-core/bcftools/annotate/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX } from '../../modules/nf-core/bcftools/index/main.nf' + +workflow VCF_CHR_RENAME { + take: + ch_vcf // channel: [ [id, ref], vcf, csi ] + file_chr_rename // file + + main: + + ch_versions = Channel.empty() + + // Rename the chromosome without prefix + BCFTOOLS_ANNOTATE(ch_vcf + .combine(Channel.of([[],[], []])), + file_chr_rename) + + VCF_INDEX(BCFTOOLS_ANNOTATE.out.vcf) + ch_versions = ch_versions.mix(VCF_INDEX.out.versions.first()) + + ch_vcf_rename = BCFTOOLS_ANNOTATE.out.vcf + .combine(VCF_INDEX.out.csi) + + emit: + vcf_rename = ch_vcf_rename // [ meta, vcf, csi ] + versions = ch_versions // channel: [ versions.yml ] +} \ No newline at end of file diff --git a/subworkflows/local/vcf_region.nf b/subworkflows/local/vcf_region.nf new file mode 100644 index 00000000..7a9c10a6 --- /dev/null +++ b/subworkflows/local/vcf_region.nf @@ -0,0 +1,35 @@ +include { BCFTOOLS_VIEW as VIEW_VCF_REGION } from '../../modules/nf-core/bcftools/view/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX } from '../../modules/nf-core/bcftools/index/main.nf' + + +workflow VCF_REGION { + take: + ch_vcf // channel: [ [id], vcf ] + ch_region // channel: [ [region], val(region) ] + ch_fasta // channel: [ fasta ] + + main: + + ch_versions = Channel.empty() + + // Filter the region of interest of the panel file + ch_input_region = ch_vcf + .combine(ch_fasta) + .combine(ch_region) + .map{ metaI, vcf, index, fasta, metaR, region -> + [metaI + metaR, vcf, index, region+",chr"+region]} + + VIEW_VCF_REGION(ch_input_region, [], [], []) + ch_versions = ch_versions.mix(VIEW_VCF_REGION.out.versions.first()) + + VCF_INDEX(VIEW_VCF_REGION.out.vcf) + ch_versions = ch_versions.mix(VCF_INDEX.out.versions.first()) + + ch_vcf_region = VIEW_VCF_REGION.out.vcf + .combine(VCF_INDEX.out.csi) + + emit: + vcf_region = ch_vcf_region // channel: [ metaIR, vcf, index ] + versions = ch_versions // channel: [ versions.yml ] + +} \ No newline at end of file diff --git a/subworkflows/nf-core/multiple_impute_glimpse2/main.nf b/subworkflows/nf-core/multiple_impute_glimpse2/main.nf new file mode 100644 index 00000000..b300f771 --- /dev/null +++ b/subworkflows/nf-core/multiple_impute_glimpse2/main.nf @@ -0,0 +1,73 @@ +include { GLIMPSE2_CHUNK } from '../../../modules/nf-core/glimpse2/chunk/main' +include { GLIMPSE2_SPLITREFERENCE } from '../../../modules/nf-core/glimpse2/splitreference/main' +include { GLIMPSE2_PHASE } from '../../../modules/nf-core/glimpse2/phase/main' +include { GLIMPSE2_LIGATE } from '../../../modules/nf-core/glimpse2/ligate/main' +include { BCFTOOLS_INDEX as INDEX_PHASE } from '../../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_INDEX as INDEX_LIGATE } from '../../../modules/nf-core/bcftools/index/main.nf' + +workflow MULTIPLE_IMPUTE_GLIMPSE2 { + + take: + ch_input // channel (mandatory): [ meta, vcf, csi, infos ] + ch_ref // channel (mandatory): [ meta, vcf, csi, region ] + ch_map // channel (optional): [ meta, map ] + ch_fasta // channel (optional): [ meta, fasta, index ] + chunk_model // string: model used to chunk the reference panel + + main: + + ch_versions = Channel.empty() + + // Chunk reference panel + GLIMPSE2_CHUNK ( ch_ref, ch_map, chunk_model ) + ch_versions = ch_versions.mix( GLIMPSE2_CHUNK.out.versions.first() ) + + chunk_output = GLIMPSE2_CHUNK.out.chunk_chr + .splitCsv(header: ['ID', 'Chr', 'RegionBuf', 'RegionCnk', 'WindowCm', + 'WindowMb', 'NbTotVariants', 'NbComVariants'], + sep: "\t", skip: 0) + .map { meta, it -> [meta, it["RegionBuf"], it["RegionCnk"]]} + + // Split reference panel in bin files + split_input = ch_ref.map{ meta, ref, index, region -> [meta, ref, index]} + .combine(chunk_output, by: 0) + + GLIMPSE2_SPLITREFERENCE( split_input, ch_map ) + ch_versions = ch_versions.mix( GLIMPSE2_SPLITREFERENCE.out.versions.first() ) + + phase_input = ch_input.combine( GLIMPSE2_SPLITREFERENCE.out.bin_ref ) + .map{ input_meta, input_file, input_index, input_infos, + panel_meta, panel_bin -> + [input_meta, input_file, input_index, input_infos, + [], [], panel_bin, [], []] + }/* Remove unnecessary meta maps + add null index as we use a bin file, + add null value for input and output region as we use a bin file */ + + // Phase input files for each reference bin files + indexing + GLIMPSE2_PHASE ( phase_input, ch_fasta ) // [meta, vcf, index, sample_infos, regionin, regionout, regionindex, ref, ref_index, map], [ meta, fasta, index ] + ch_versions = ch_versions.mix( GLIMPSE2_PHASE.out.versions.first() ) + + INDEX_PHASE ( GLIMPSE2_PHASE.out.phased_variant ) + ch_versions = ch_versions.mix( INDEX_PHASE.out.versions.first() ) + + // Ligate all phased files in one and index it + ligate_input = GLIMPSE2_PHASE.out.phased_variant + .groupTuple() + .combine( INDEX_PHASE.out.csi + .groupTuple() + .collect(), by: 0 ) + + GLIMPSE2_LIGATE ( ligate_input ) + ch_versions = ch_versions.mix( GLIMPSE2_LIGATE.out.versions.first() ) + + INDEX_LIGATE ( GLIMPSE2_LIGATE.out.merged_variants ) + ch_versions = ch_versions.mix( INDEX_LIGATE.out.versions.first() ) + + emit: + chunk_chr = GLIMPSE2_CHUNK.out.chunk_chr // channel: [ val(meta), txt ] + merged_variants = GLIMPSE2_LIGATE.out.merged_variants // channel: [ val(meta), bcf ] + merged_variants_index = INDEX_LIGATE.out.csi // channel: [ val(meta), csi ] + + versions = ch_versions // channel: [ versions.yml ] +} diff --git a/subworkflows/nf-core/multiple_impute_glimpse2/meta.yml b/subworkflows/nf-core/multiple_impute_glimpse2/meta.yml new file mode 100644 index 00000000..46a418bc --- /dev/null +++ b/subworkflows/nf-core/multiple_impute_glimpse2/meta.yml @@ -0,0 +1,72 @@ +name: "multiple_impute_glimpse2" +description: Impute VCF/BCF files, but also CRAM and BAM files with Glimpse2 +keywords: + - glimpse + - chunk + - phase + - ligate + - split_reference + +components: + - glimpse2/chunk + - glimpse2/phase + - glimpse2/ligate + - glimpse2/splitreference + - bcftools/index + +input: + - ch_input: + type: file + description: | + Target dataset in CRAM, BAM or VCF/BCF format. + Index file of the input file. + File with sample names and ploidy information. + Structure: [ meta, file, index, txt ] + + - ch_ref: + type: file + description: | + Reference panel of haplotypes in VCF/BCF format. + Index file of the Reference panel file. + Target region, usually a full chromosome (e.g. chr20:1000000-2000000 or chr20). + The file could possibly be without GT field (for efficiency reasons a file containing only the positions is recommended). + Structure: [ meta, vcf, csi, region ] + + - ch_map: + type: file + description: | + File containing the genetic map. + Structure: [ meta, gmap ] + + - ch_fasta: + type: file + description: | + Reference genome in fasta format. + Reference genome index in fai format + Structure: [ meta, fasta, fai ] + +output: + - chunk_chr: + type: file + description: | + Tab delimited output txt file containing buffer and imputation regions. + Structure: [meta, txt] + + - merged_variants: + type: file + description: | + Output VCF/BCF file for the merged regions. + Phased information (HS field) is updated accordingly for the full region. + Structure: [ val(meta), bcf ] + + - merged_variants_index: + type: file + description: Index file of the ligated phased variants files. + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@LouisLeNezet" diff --git a/subworkflows/nf-core/vcf_impute_glimpse/main.nf b/subworkflows/nf-core/vcf_impute_glimpse/main.nf new file mode 100644 index 00000000..5fe26551 --- /dev/null +++ b/subworkflows/nf-core/vcf_impute_glimpse/main.nf @@ -0,0 +1,59 @@ +include { GLIMPSE_CHUNK } from '../../../modules/nf-core/glimpse/chunk/main' +include { GLIMPSE_PHASE } from '../../../modules/nf-core/glimpse/phase/main' +include { GLIMPSE_LIGATE } from '../../../modules/nf-core/glimpse/ligate/main' +include { BCFTOOLS_INDEX as INDEX_PHASE } from '../../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_INDEX as INDEX_LIGATE } from '../../../modules/nf-core/bcftools/index/main.nf' + +workflow VCF_IMPUTE_GLIMPSE { + + take: + ch_input // channel (mandatory): [ meta, vcf, csi, sample, region, ref, ref_index, map ] + + main: + + ch_versions = Channel.empty() + + input_chunk = ch_input.map{ + meta, vcf, csi, sample, region, ref, ref_index, map -> + [ meta, vcf, csi, region] + } + + GLIMPSE_CHUNK ( input_chunk ) + ch_versions = ch_versions.mix( GLIMPSE_CHUNK.out.versions ) + + chunk_output = GLIMPSE_CHUNK.out.chunk_chr + .splitCsv(header: ['ID', 'Chr', 'RegionIn', 'RegionOut', 'Size1', 'Size2'], sep: "\t", skip: 0) + .map { meta, it -> [meta, it["RegionIn"], it["RegionOut"]]} + + phase_input = ch_input.map{ meta, vcf, csi, sample, region, ref, ref_index, map -> [meta, vcf, csi, sample, ref, ref_index, map]} + .combine(chunk_output, by: 0) + .map{meta, vcf, csi, sample, ref, ref_index, map, regionin, regionout -> + [meta, vcf, csi, sample, regionin, regionout, ref, ref_index, map]} + + GLIMPSE_PHASE ( phase_input ) // [meta, vcf, index, sample_infos, regionin, regionout, ref, ref_index, map] + ch_versions = ch_versions.mix(GLIMPSE_PHASE.out.versions ) + + INDEX_PHASE ( GLIMPSE_PHASE.out.phased_variant ) + ch_versions = ch_versions.mix( INDEX_PHASE.out.versions ) + + // Ligate all phased files in one and index it + ligate_input = GLIMPSE_PHASE.out.phased_variant + .groupTuple( by: 0 ) + .combine( INDEX_PHASE.out.csi + .groupTuple( by: 0 ), + by: 0 + ) + + GLIMPSE_LIGATE ( ligate_input ) + ch_versions = ch_versions.mix(GLIMPSE_LIGATE.out.versions ) + + INDEX_LIGATE ( GLIMPSE_LIGATE.out.merged_variants ) + ch_versions = ch_versions.mix( INDEX_LIGATE.out.versions ) + + emit: + chunk_chr = GLIMPSE_CHUNK.out.chunk_chr // channel: [ val(meta), txt ] + merged_variants = GLIMPSE_LIGATE.out.merged_variants // channel: [ val(meta), bcf ] + merged_variants_index = INDEX_LIGATE.out.csi // channel: [ val(meta), csi ] + + versions = ch_versions // channel: [ versions.yml ] +} diff --git a/subworkflows/nf-core/vcf_impute_glimpse/meta.yml b/subworkflows/nf-core/vcf_impute_glimpse/meta.yml new file mode 100644 index 00000000..598b6888 --- /dev/null +++ b/subworkflows/nf-core/vcf_impute_glimpse/meta.yml @@ -0,0 +1,58 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "vcf_impute_glimpse" +description: Impute VCF/BCF files with Glimpse +keywords: + - glimpse + - chunk + - phase + - ligate + +components: + - glimpse/chunk + - glimpse/phase + - glimpse/ligate + - bcftools/index + +input: + - ch_input: + type: file + description: | + Target dataset in VCF/BCF format defined at all variable positions. + Index file of the input VCF/BCF file containing genotype likelihoods. + File with sample names and ploidy information. + Target region, usually a full chromosome (e.g. chr20:1000000-2000000 or chr20). + Reference panel of haplotypes in VCF/BCF format. + Index file of the Reference panel file. + File containing the genetic map. + The file could possibly be without GT field (for efficiency reasons a file containing only the positions is recommended). + Structure: [ meta, vcf, csi, txt, region, ref_vcf, ref_csi, gmap ] + +output: + - chunk_chr: + type: file + description: | + Tab delimited output txt file containing buffer and imputation regions. + Structure: [meta, txt] + + - phased_variants: + type: file + description: | + Output VCF/BCF file containing genotype probabilities (GP field), + imputed dosages (DS field), best guess genotypes (GT field), + sampled haplotypes in the last (max 16) main iterations (HS field) and info-score. + Structure: [ val(meta), bcf ] + + - merged_variants: + type: file + description: | + Output VCF/BCF file for the merged regions. + Phased information (HS field) is updated accordingly for the full region. + Structure: [ val(meta), bcf ] + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + +authors: + - "@LouisLeNezet" diff --git a/subworkflows/nf-core/vcf_phase_shapeit5/main.nf b/subworkflows/nf-core/vcf_phase_shapeit5/main.nf new file mode 100644 index 00000000..0ddebcb3 --- /dev/null +++ b/subworkflows/nf-core/vcf_phase_shapeit5/main.nf @@ -0,0 +1,97 @@ +include { BEDTOOLS_MAKEWINDOWS } from '../../../modules/nf-core/bedtools/makewindows/main.nf' +include { SHAPEIT5_PHASECOMMON } from '../../../modules/nf-core/shapeit5/phasecommon/main' +include { SHAPEIT5_LIGATE } from '../../../modules/nf-core/shapeit5/ligate/main' +include { BCFTOOLS_INDEX as VCF_INDEX1 } from '../../../modules/nf-core/bcftools/index/main.nf' +include { BCFTOOLS_INDEX as VCF_INDEX2 } from '../../../modules/nf-core/bcftools/index/main.nf' + +workflow VCF_PHASE_SHAPEIT5 { + + take: + ch_vcf // channel (mandatory): [ val(meta), path(vcf), path(csi), path(pedigree), val(region) ] + ch_ref // channel (optional) : [ val(meta), path(ref), path(csi) ] + ch_scaffold // channel (optional) : [ val(meta), path(scaffold), path(csi) ] + ch_map // channel (optional) : [ val(meta), path(map)] + + main: + + ch_versions = Channel.empty() + + // It is needed to generate a file containing the region to phase in a Chr \tab Start \tab End format + // The meta map needing to be conserved the following steps a required + + // Keep the meta map and the region in two separated channel but keed id field to link them back + ch_region = ch_vcf + .multiMap { meta, vcf, csi, pedigree, region -> + metadata: [ meta.id, meta] + region : [ meta.id, region] + } + + // Create the File in bed format and use the meta id for the file name + ch_merged_region = ch_region.region + .collectFile { metaid, region -> ["${metaid}.bed", region.replace(":","\t").replace("-","\t")] } + .map { file -> [file.baseName, file] } + + // Link back the meta map with the file + ch_region_file = ch_region.metadata + .join(ch_merged_region, failOnMismatch:true, failOnDuplicate:true) + .map { mid, meta, region_file -> [meta, region_file]} + + BEDTOOLS_MAKEWINDOWS(ch_region_file) + ch_versions = ch_versions.mix(BEDTOOLS_MAKEWINDOWS.out.versions.first()) + + ch_chunk_output = BEDTOOLS_MAKEWINDOWS.out.bed + .splitCsv(header: ['Chr', 'Start', 'End'], sep: "\t", skip: 0) + .map { meta, it -> [meta, it["Chr"]+":"+it["Start"]+"-"+it["End"]]} + + // Count the number of chunks + ch_chunks_number = BEDTOOLS_MAKEWINDOWS.out.bed + .map { meta, bed -> [meta, bed.countLines().intValue()]} + + ch_phase_input = ch_vcf + .map { meta, vcf, index, pedigree, region -> + [meta, vcf, index, pedigree] } + .combine(ch_chunk_output, by:0) + .map { meta, vcf, index, pedigree, chunk -> + [meta + [id: "${meta.id}_${chunk.replace(":","-")}"], // The meta.id field need to be modified to be unique for each chunk + vcf, index, pedigree, chunk]} + + SHAPEIT5_PHASECOMMON ( ch_phase_input, + ch_ref, + ch_scaffold, + ch_map ) + ch_versions = ch_versions.mix(SHAPEIT5_PHASECOMMON.out.versions.first()) + + VCF_INDEX1(SHAPEIT5_PHASECOMMON.out.phased_variant) + ch_versions = ch_versions.mix(VCF_INDEX1.out.versions.first()) + + ch_ligate_input = SHAPEIT5_PHASECOMMON.out.phased_variant + .join(VCF_INDEX1.out.csi, failOnMismatch:true, failOnDuplicate:true) + .view() + .map{ meta, vcf, csi -> + newmeta = meta + [id: meta.id.split("_")[0..-2].join("_")] + [newmeta, vcf, csi]}.view() + .combine(ch_chunks_number, by:0) + .map{meta, vcf, csi, chunks_num -> + [groupKey(meta, chunks_num), vcf, csi]} + .groupTuple() + .map{ meta, vcf, csi -> + [ meta, + vcf.sort { a, b -> + def aStart = a.getName().split('-')[-2].toInteger() + def bStart = b.getName().split('-')[-2].toInteger() + aStart <=> bStart}, + csi]} + + SHAPEIT5_LIGATE(ch_ligate_input) + ch_versions = ch_versions.mix(SHAPEIT5_LIGATE.out.versions.first()) + + VCF_INDEX2(SHAPEIT5_LIGATE.out.merged_variants) + ch_versions = ch_versions.mix(VCF_INDEX2.out.versions.first()) + + emit: + bed = BEDTOOLS_MAKEWINDOWS.out.bed // channel: [ val(meta), bed ] + variants_phased = SHAPEIT5_LIGATE.out.merged_variants // channel: [ val(meta), vcf ] + variants_index = VCF_INDEX2.out.csi // channel: [ val(meta), csi ] + versions = ch_versions // channel: [ versions.yml ] +} + diff --git a/subworkflows/nf-core/vcf_phase_shapeit5/meta.yml b/subworkflows/nf-core/vcf_phase_shapeit5/meta.yml new file mode 100644 index 00000000..686f2d92 --- /dev/null +++ b/subworkflows/nf-core/vcf_phase_shapeit5/meta.yml @@ -0,0 +1,72 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "vcf_phase_shapeit5" +description: Phase vcf panel with Shapeit5 tools +keywords: + - chunk + - phase + - ligate + - index + - vcf + +components: + - bedtools/makewindows + - shapeit5/phasecommon + - shapeit5/ligate + - bcftools/index + +input: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - ch_vcf: + type: file + description: | + Target dataset in VCF/BCF format defined at all variable positions. + Index file of the input VCF/BCF file containing genotype likelihoods. + Pedigree information in the following format: offspring father mother. + Target region, usually a full chromosome (e.g. chr20:1000000-2000000 or chr20). + The file could possibly be without GT field (for efficiency reasons a file containing only the positions is recommended). + Structure: [ val(meta), path(vcf), path(csi), path(pedigree), val(region) ] + - ch_ref: + type: file + description: | + Reference panel of haplotypes in VCF/BCF format. + Index file of the Reference panel file. + Structure: [ val(meta), path(ref), path(csi) ] + - ch_scaffold: + type: file + description: | + Scaffold of haplotypes in VCF/BCF format. + Index file of the Scaffold of haplotypes file. + Structure: [ val(meta), path(scaffold), path(csi) ] + - ch_map: + type: file + description: File containing the genetic map. + Structure: [val(meta), path(map)] + +output: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - bed: + type: file + description: BED file containing the windows + pattern: "*.bed" + - variants_phased: + type: file + description: Phased haplotypes in VCF/BCF format. + pattern: "*.{vcf,bcf,vcf.gz,bcf.gz}" + - variants_index: + type: file + description: CSI bcftools index + pattern: "*.csi" + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@LouisLeNezet" diff --git a/tests/csv/panel.csv b/tests/csv/panel.csv new file mode 100644 index 00000000..763ed1e8 --- /dev/null +++ b/tests/csv/panel.csv @@ -0,0 +1,3 @@ +panel,vcf,index,legend,to_phase +1000GP,"/groups/dog/llenezet/test-datasets/data/panel/21/panel_2020-08-05_chr21.phased.vcf.gz","/groups/dog/llenezet/test-datasets/data/panel/21/panel_2020-08-05_chr21.phased.vcf.gz.tbi",,FALSE +1000GP_RePhase,"/groups/dog/llenezet/test-datasets/data/panel/21/panel_2020-08-05_chr21.phased.vcf.gz","/groups/dog/llenezet/test-datasets/data/panel/21/panel_2020-08-05_chr21.phased.vcf.gz.tbi",,TRUE \ No newline at end of file diff --git a/tests/csv/regionsheet.csv b/tests/csv/regionsheet.csv new file mode 100644 index 00000000..543b24f1 --- /dev/null +++ b/tests/csv/regionsheet.csv @@ -0,0 +1,2 @@ +chr,start,end +chr1,0,1 \ No newline at end of file diff --git a/tests/csv/sample_sim.csv b/tests/csv/sample_sim.csv new file mode 100644 index 00000000..718e1383 --- /dev/null +++ b/tests/csv/sample_sim.csv @@ -0,0 +1,2 @@ +sample,BAM,BAI +NA12878,/groups/dog/llenezet/test-datasets/data/NA12878/21/NA12878.chr21.s.bam,/groups/dog/llenezet/test-datasets/data/NA12878/21/NA12878.chr21.s.bam.bai \ No newline at end of file diff --git a/tests/test_default.yml b/tests/test_default.yml new file mode 100644 index 00000000..d7994f56 --- /dev/null +++ b/tests/test_default.yml @@ -0,0 +1,7 @@ +- name: Run default pipeline + command: nextflow run main.nf -profile test --outdir results --genome GRCh37 + tags: + - default + files: + - path: results/csv/markduplicates.csv + md5sum: 0d6120bb99e92f6810343270711ca53e diff --git a/workflows/phaseimpute.nf b/workflows/phaseimpute.nf index 195669c1..c7835ac0 100644 --- a/workflows/phaseimpute.nf +++ b/workflows/phaseimpute.nf @@ -4,12 +4,36 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { FASTQC } from '../modules/nf-core/fastqc/main' -include { MULTIQC } from '../modules/nf-core/multiqc/main' +// +// MODULE: Installed directly from nf-core/modules +// +include { MULTIQC } from '../modules/nf-core/multiqc/main' include { paramsSummaryMap } from 'plugin/nf-validation' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_phaseimpute_pipeline' +include { SAMTOOLS_FAIDX } from '../modules/nf-core/samtools/faidx/main' +include { BAM_REGION } from '../subworkflows/local/bam_region' + +// +// SUBWORKFLOW: Consisting of a mix of local and nf-core/modules +// + +include { BAM_DOWNSAMPLE } from '../subworkflows/local/bam_downsample.nf' +include { COMPUTE_GL as GL_TRUTH } from '../subworkflows/local/compute_gl.nf' +include { COMPUTE_GL as GL_INPUT } from '../subworkflows/local/compute_gl.nf' + + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + INITIALIZE PARAMETERS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ +// +// Initialize file channels based on params, defined in the params.genomes[params.genome] scope +// +map = params.map ? Channel.fromPath(params.map).collect() : Channel.empty() + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -27,14 +51,120 @@ workflow PHASEIMPUTE { ch_versions = Channel.empty() ch_multiqc_files = Channel.empty() + /// Create single fasta channel + ch_fasta = Channel.of([[genome: params.genome]]) + .combine(Channel.fromPath(params.fasta).collect()) + + // Gather regions to use and create the meta map + if (params.input_region_string == "all") { + SAMTOOLS_FAIDX(ch_fasta, [[],[]]) + ch_multiqc_files = ch_multiqc_files.mix(SAMTOOLS_FAIDX.out.zip.collect{it[1]}) + ch_versions = ch_versions.mix(SAMTOOLS_FAIDX.out.versions.first()) + ch_region = SAMTOOLS_FAIDX.out.fai + .splitCsv(header: ["chr", "size", "offset", "lidebase", "linewidth", "qualoffset"], sep: "\t") + .map{ meta, row -> [meta + ["chr": row.chr], row.chr + ":0-" + row.size]} + .map{ metaC, region -> [metaC + ["region": region], region]} + } else { + ch_region = Channel.fromSamplesheet("input_region_file") + .map{ chr, start, end -> [["chr": chr], chr + ":" + start + "-" + end]} + .map{ metaC, region -> [metaC + ["region": region], region]} + } + + // Create map channel + if (params.map) { + ch_map = Channel.of([["map": params.map], params.map]).collect() + } else { + ch_map = Channel.of([[],[]]) + } + // - // MODULE: Run FastQC + // Simulate data if asked // - FASTQC ( - ch_samplesheet - ) - ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}) - ch_versions = ch_versions.mix(FASTQC.out.versions.first()) + if (params.step == 'simulate') { + // + // Read in samplesheet, validate and stage input_simulate files + // + ch_sim_input = Channel.fromSamplesheet("input") + + // Output channel of simulate process + ch_sim_output = Channel.empty() + + // Split the bam into the region specified + ch_bam_region = BAM_REGION(ch_input_sim, ch_region, fasta) + + // Initialize channel to impute + ch_bam_to_impute = Channel.empty() + + if (params.depth) { + // Create channel from depth parameter + ch_depth = Channel.fromList(params.depth) + + // Downsample input to desired depth + BAM_DOWNSAMPLE(ch_sim_input, ch_region, ch_depth, ch_fasta) + ch_versions = ch_versions.mix(BAM_DOWNSAMPLE.out.versions.first()) + + ch_sim_output = ch_sim_output.mix(BAM_DOWNSAMPLE.out.bam_emul) + } + + if (params.genotype) { + // Create channel from samplesheet giving the chips snp position + ch_chip_snp = Channel.fromSamplesheet("input_chip_snp") + BAM_TO_GENOTYPE(ch_sim_input, ch_region, ch_chip_snp, ch_fasta) + ch_sim_output = ch_sim_output.mix(BAM_TO_GENOTYPE.out.bam_emul) + } + } + + // + // Prepare panel + // + if (params.step == 'panelprep') { + ch_panel = Channel.fromSamplesheet("input") + + // Remove if necessary "chr" + if (params.panel_rename = true) { + ch_panel = VCF_CHR_RENAME(ch_panel, "./assets/chr_rename.txt") + } + + GET_PANEL(ch_panel) + ch_versions = ch_versions.mix(GET_PANEL.out.versions.first()) + + // Register all panel preparation to csv + } + + if (params.step.contains("impute")) { + // Read from panel preparation csv + + // Output channel of input process + ch_impute_output = Channel.empty() + + if (params.tools.contains("glimpse1")){ + print("Impute with Glimpse1") + // Glimpse1 subworkflow + GL_INPUT( + ch_sim_output, + REGION_CHECK.out.region, + GET_PANEL.out.panel_sites, + GET_PANEL.out.panel_tsv + ) + impute_input = GL_EMUL.out.vcf + | combine(Channel.of([[]])) + | map{meta, vcf, index, sample -> [meta, vcf, index, sample, meta.region]} + + VCF_IMPUTE_GLIMPSE(impute_input, + GET_PANEL.out.panel_phased, + ch_map) + + ch_impute_output = ch_impute_output.mix(VCF_IMPUTE_GLIMPSE.out.) + } + if (params.tools.contains("glimpse2")){ + print("Impute with Glimpse2") + // Glimpse2 subworkflow + } + if (params.tools.contains("quilt")){ + print("Impute with quilt") + // Quilt subworkflow + } + } // // Collate and save software versions