Commit a12aa135 authored by van den Berg's avatar van den Berg
Browse files

Merge branch 'master' into known-snps

parents 6e9e769d 7b73fae2
Pipeline #2749 failed with stages
in 44 seconds
# Hutspot
This is a multisample DNA variant calling pipeline based on Snakemake, bwa and the
GATK HaplotypeCaller.
GATK HaplotypeCaller.
## Features
* Any number of samples is supported
......@@ -16,7 +16,7 @@ GATK HaplotypeCaller.
* No unnecessary jobs
* Coverage metrics for any number of bed files.
* Fully containerized rules through singularity and biocontainers. Legacy
conda environments are available as well.
conda environments are no long available.
* Optionally sub-sample inputs when number of bases exceeds a user-defined
threshold.
......@@ -47,10 +47,9 @@ pip install -r requirements.txt
We highly recommend the user of the containerized rules through
[singularity](https://www.sylabs.io/singularity/).
This option does, however,
require you to install singularity on your system. As this usually requires
administrative privileges, singularity is not contained within our provided
conda environment file.
This option does require you to install singularity on your system. As this
usually requires administrative privileges, singularity is not contained
within our provided conda environment file.
If you want to use singularity, make sure you install version 3 or higher.
......@@ -79,15 +78,6 @@ Please see the installation instructions
to do that.
## GATK
For license reasons, conda and singularity cannot fully install the GATK. The JAR
must be registered by running `gatk-register` after the environment is
created, which conflicts with the automated environment/container creation.
For this reason, hutspot **requires** you to manually specify the path to
the GATK executable JAR via `--config GATK=/path/to/gatk.jar`.
## Operating system
Hutspot was tested on Ubuntu 16.04 only.
......@@ -143,7 +133,8 @@ The following configuration values are **required**:
| ------------- | ----------- |
| `REFERENCE` | Absolute path to fasta file |
| `SAMPLE_CONFIG` | Path to config file as described above |
| `GATK` | Path to GATK jar. **Must** be version 3.7 |
| `DBSNP` | Path to dbSNP VCF |
The following configuration options are **optional**:
......@@ -215,27 +206,12 @@ snakemake -s Snakefile \
--restart-times 2 \
--config SAMPLE_CONFIG=samples.json \
REFERENCE=/path/to/genome.fasta \
GATK=/path/to/GenomeAnalysisTK.jar \
KNOWN_SITES=/path/to/dbsnp.vcf.gz,/path/to/onekg.vcf,/path/to/hapmap.vcf \
DBSNP=/path/to/dbsnp.vcf.gz \
FASTQ_COUNT=/path/to/fastq-count \
BED=/path/to/interesting_region.bed
```
## Using conda instead of singularity
Legacy conda environments are also available for each and every rule.
Simply use `--use-conda` instead of `--use-singularity` to enable conda
environments.
As dependency conflicts can and do arise with conda, it is recommended to
combine this flag with `--conda-prefix`, such that you only have to
build the environments once.
The conda environments use the same versions of tools as the singularity
containers, bar one:
* `fastqc` uses version 0.11.5 on conda, but 0.11.7 on singularity.
# Graph
Below you can see the rulegraph of the pipeline. The main variant calling flow
......
......@@ -25,6 +25,7 @@ import json
from functools import partial
from os.path import join, basename
from pathlib import Path
import itertools
from pyfaidx import Fasta
......@@ -34,12 +35,12 @@ if REFERENCE is None:
if not Path(REFERENCE).exists():
raise FileNotFoundError("Reference file {0} "
"does not exist.".format(REFERENCE))
DBSNP = config.get("DBSNP")
if DBSNP is None:
raise ValueError("You must set --config DBSNP=<path>")
if not Path(DBSNP).exists():
raise FileNotFoundError("{0} does not exist".format(DBSNP))
GATK = config.get("GATK")
if GATK is None:
raise ValueError("You must set --config GATK=<path>")
if not Path(GATK).exists():
raise FileNotFoundError("{0} does not exist.".format(GATK))
# these are all optional
BED = config.get("BED", "") # comma-separated list of BED files
......@@ -49,15 +50,18 @@ FASTQ_COUNT = config.get("FASTQ_COUNT")
MAX_BASES = config.get("MAX_BASES", "")
# Make sure all files with known sites exist
known_sites = config.get("KNOWN_SITES").split(',')
known_sites = config.get("KNOWN_SITES","")
# Did we get multiple KNOWN SITES?
known_sites = known_sites.split(',')
for filename in known_sites:
if not Path(filename).exists():
raise FileNotFoundError("{0} does not exist".format(DBSNP))
raise FileNotFoundError("{0} does not exist".format(filename))
# Generate the input string for basrecalibration
known_sites_argument = ''
for argument, filename in zip(repeat('-knownSites'), known_sites):
known_sites_argument +=' {argument} {filename}'.format(argument, filename)
for argument, filename in zip(itertools.repeat('-knownSites'), known_sites):
known_sites_argument +=' {} {}'.format(argument, filename)
def fsrc_dir(*args):
"""Wrapper around snakemake's srcdir to work like os.path.join"""
......@@ -224,7 +228,6 @@ rule seqtk_r1:
max_bases=str(MAX_BASES)
output:
fastq=temp("{sample}/pre_process/{sample}.sampled_R1.fastq.gz")
conda: "envs/seqtk.yml"
singularity: "docker://quay.io/biocontainers/mulled-v2-13686261ac0aa5682c680670ff8cda7b09637943:d143450dec169186731bb4df6f045a3c9ee08eb6-0"
shell: "bash {input.seqtk} {input.stats} {input.fastq} {output.fastq} "
"{params.max_bases}"
......@@ -240,7 +243,6 @@ rule seqtk_r2:
max_bases =str(MAX_BASES)
output:
fastq = temp("{sample}/pre_process/{sample}.sampled_R2.fastq.gz")
conda: "envs/seqtk.yml"
singularity: "docker://quay.io/biocontainers/mulled-v2-13686261ac0aa5682c680670ff8cda7b09637943:d143450dec169186731bb4df6f045a3c9ee08eb6-0"
shell: "bash {input.seqtk} {input.stats} {input.fastq} {output.fastq} "
"{params.max_bases}"
......@@ -259,7 +261,6 @@ rule sickle:
r2 = temp("{sample}/pre_process/{sample}.trimmed_R2.fastq"),
s = "{sample}/pre_process/{sample}.trimmed_singles.fastq"
singularity: "docker://quay.io/biocontainers/sickle-trim:1.33--ha92aebf_4"
conda: "envs/sickle.yml"
shell: "sickle pe -f {input.r1} -r {input.r2} -t sanger -o {output.r1} "
"-p {output.r2} -s {output.s}"
......@@ -272,7 +273,6 @@ rule cutadapt:
r1 = temp("{sample}/pre_process/{sample}.cutadapt_R1.fastq"),
r2 = temp("{sample}/pre_process/{sample}.cutadapt_R2.fastq")
singularity: "docker://quay.io/biocontainers/cutadapt:1.14--py36_0"
conda: "envs/cutadapt.yml"
shell: "cutadapt -a AGATCGGAAGAG -A AGATCGGAAGAG -m 1 -o {output.r1} "
"{input.r1} -p {output.r2} {input.r2}"
......@@ -287,7 +287,6 @@ rule align:
rg = "@RG\\tID:{sample}_lib1\\tSM:{sample}\\tPL:ILLUMINA"
output: temp("{sample}/bams/{sample}.sorted.bam")
singularity: "docker://quay.io/biocontainers/mulled-v2-002f51ea92721407ef440b921fb5940f424be842:43ec6124f9f4f875515f9548733b8b4e5fed9aa6-0"
conda: "envs/bwa.yml"
shell: "bwa mem -t 8 -R '{params.rg}' {input.ref} {input.r1} {input.r2} "
"| picard -Xmx4G SortSam CREATE_INDEX=TRUE TMP_DIR={input.temp} "
"INPUT=/dev/stdin OUTPUT={output} SORT_ORDER=coordinate"
......@@ -302,7 +301,6 @@ rule markdup:
bai = "{sample}/bams/{sample}.markdup.bai",
metrics = "{sample}/bams/{sample}.markdup.metrics"
singularity: "docker://quay.io/biocontainers/picard:2.14--py36_0"
conda: "envs/picard.yml"
shell: "picard -Xmx4G MarkDuplicates CREATE_INDEX=TRUE TMP_DIR={input.tmp} "
"INPUT={input.bam} OUTPUT={output.bam} "
"METRICS_FILE={output.metrics} "
......@@ -321,18 +319,13 @@ rule baserecal:
"""Base recalibrated BAM files"""
input:
bam = "{sample}/bams/{sample}.markdup.bam",
gatk = GATK,
ref = REFERENCE,
dbsnp = DBSNP,
one1kg = ONETHOUSAND,
hapmap = HAPMAP
output:
grp = "{sample}/bams/{sample}.baserecal.grp"
params:
knownsites = known_sites_argument
singularity: "docker://quay.io/biocontainers/gatk:3.7--py36_1"
conda: "envs/gatk.yml"
shell: "java -XX:ParallelGCThreads=1 -jar {input.gatk} -T "
singularity: "docker://broadinstitute/gatk3:3.7-0"
shell: "java -XX:ParallelGCThreads=1 -jar /usr/GenomeAnalysisTK.jar -T "
"BaseRecalibrator -I {input.bam} -o {output.grp} -nct 8 "
"-R {input.ref} -cov ReadGroupCovariate -cov QualityScoreCovariate "
"-cov CycleCovariate -cov ContextCovariate {params.knownsites}"
......@@ -344,15 +337,13 @@ rule gvcf_scatter:
bqsr="{sample}/bams/{sample}.baserecal.grp",
dbsnp=DBSNP,
ref=REFERENCE,
gatk=GATK
params:
chunk="{chunk}"
output:
gvcf=temp("{sample}/vcf/{sample}.{chunk}.part.vcf.gz"),
gvcf_tbi=temp("{sample}/vcf/{sample}.{chunk}.part.vcf.gz.tbi")
singularity: "docker://quay.io/biocontainers/gatk:3.7--py36_1"
conda: "envs/gatk.yml"
shell: "java -jar -Xmx4G -XX:ParallelGCThreads=1 {input.gatk} "
singularity: "docker://broadinstitute/gatk3:3.7-0"
shell: "java -jar -Xmx4G -XX:ParallelGCThreads=1 /usr/GenomeAnalysisTK.jar "
"-T HaplotypeCaller -ERC GVCF -I "
"{input.bam} -R {input.ref} -D {input.dbsnp} "
"-L '{params.chunk}' -o '{output.gvcf}' "
......@@ -363,14 +354,14 @@ rule gvcf_scatter:
rule gvcf_chunkfile:
"""
Create simple text file with paths to chunks for GVCF.
This uses a run directive in stead of a shell directive because
the amount of chunks may be so large the shell would error out with
an "argument list too long" error.
an "argument list too long" error.
See https://unix.stackexchange.com/a/120842 for more info
This also means this rule lives outside of singularity/conda and is
executed in snakemake's own environment.
This also means this rule lives outside of singularity and is
executed in snakemake's own environment.
"""
params:
chunkfiles = expand("{{sample}}/vcf/{{sample}}.{chunk}.part.vcf.gz",
......@@ -391,7 +382,6 @@ rule gvcf_gather:
chunkfile = "{sample}/vcf/chunkfile.txt"
output:
gvcf = "{sample}/vcf/{sample}.g.vcf.gz"
conda: "envs/bcftools.yml"
singularity: "docker://quay.io/biocontainers/bcftools:1.9--ha228f0b_4"
shell: "bcftools concat -f {input.chunkfile} -n > {output.gvcf}"
......@@ -402,7 +392,6 @@ rule gvcf_gather_tbi:
gvcf = "{sample}/vcf/{sample}.g.vcf.gz"
output:
tbi = "{sample}/vcf/{sample}.g.vcf.gz.tbi"
conda: "envs/tabix.yml"
singularity: "docker://quay.io/biocontainers/tabix:0.2.6--ha92aebf_0"
shell: "tabix -pvcf {input.gvcf}"
......@@ -413,8 +402,7 @@ rule genotype_scatter:
gvcfs = expand("{sample}/vcf/{sample}.g.vcf.gz", sample=SAMPLES),
tbis = expand("{sample}/vcf/{sample}.g.vcf.gz.tbi",
sample=SAMPLES),
ref=REFERENCE,
gatk=GATK
ref=REFERENCE
params:
li=" -V ".join(expand("{sample}/vcf/{sample}.g.vcf.gz",
sample=SAMPLES)),
......@@ -422,9 +410,8 @@ rule genotype_scatter:
output:
vcf=temp("multisample/genotype.{chunk}.part.vcf.gz"),
vcf_tbi=temp("multisample/genotype.{chunk}.part.vcf.gz.tbi")
singularity: "docker://quay.io/biocontainers/gatk:3.7--py36_1"
conda: "envs/gatk.yml"
shell: "java -jar -Xmx15G -XX:ParallelGCThreads=1 {input.gatk} -T "
singularity: "docker://broadinstitute/gatk3:3.7-0"
shell: "java -jar -Xmx15G -XX:ParallelGCThreads=1 /usr/GenomeAnalysisTK.jar -T "
"GenotypeGVCFs -R {input.ref} "
"-V {params.li} -L '{params.chunk}' -o '{output.vcf}'"
......@@ -432,14 +419,14 @@ rule genotype_scatter:
rule genotype_chunkfile:
"""
Create simple text file with paths to chunks for genotyping
This uses a run directive in stead of a shell directive because
the amount of chunks may be so large the shell would error out with
an "argument list too long" error.
an "argument list too long" error.
See https://unix.stackexchange.com/a/120842 for more info
This also means this rule lives outside of singularity/conda and is
executed in snakemake's own environment.
This also means this rule lives outside of singularity and is
executed in snakemake's own environment.
"""
params:
vcfs = expand("multisample/genotype.{chunk}.part.vcf.gz",
......@@ -460,7 +447,6 @@ rule genotype_gather:
chunkfile = "multisample/chunkfile.txt"
output:
vcf = "multisample/genotyped.vcf.gz"
conda: "envs/bcftools.yml"
singularity: "docker://quay.io/biocontainers/bcftools:1.9--ha228f0b_4"
shell: "bcftools concat -f {input.chunkfile} -n > {output.vcf}"
......@@ -471,7 +457,6 @@ rule genotype_gather_tbi:
vcf = "multisample/genotyped.vcf.gz"
output:
tbi = "multisample/genotyped.vcf.gz.tbi"
conda: "envs/tabix.yml"
singularity: "docker://quay.io/biocontainers/tabix:0.2.6--ha92aebf_0"
shell: "tabix -pvcf {input.vcf}"
......@@ -481,15 +466,13 @@ rule split_vcf:
input:
vcf="multisample/genotyped.vcf.gz",
tbi = "multisample/genotyped.vcf.gz.tbi",
gatk=GATK,
ref=REFERENCE
params:
s="{sample}"
output:
splitted="{sample}/vcf/{sample}_single.vcf.gz"
singularity: "docker://quay.io/biocontainers/gatk:3.7--py36_1"
conda: "envs/gatk.yml"
shell: "java -Xmx15G -XX:ParallelGCThreads=1 -jar {input.gatk} "
singularity: "docker://broadinstitute/gatk3:3.7-0"
shell: "java -Xmx15G -XX:ParallelGCThreads=1 -jar /usr/GenomeAnalysisTK.jar "
"-T SelectVariants -sn {params.s} -env -R {input.ref} -V "
"{input.vcf} -o {output.splitted}"
......@@ -503,7 +486,6 @@ rule mapped_num:
output:
num="{sample}/bams/{sample}.mapped.num"
singularity: "docker://quay.io/biocontainers/samtools:1.6--he673b24_3"
conda: "envs/samtools.yml"
shell: "samtools view -F 4 {input.bam} | wc -l > {output.num}"
......@@ -514,7 +496,6 @@ rule mapped_basenum:
output:
num="{sample}/bams/{sample}.mapped.basenum"
singularity: "docker://quay.io/biocontainers/samtools:1.6--he673b24_3"
conda: "envs/samtools.yml"
shell: "samtools view -F 4 {input.bam} | cut -f10 | wc -c > {output.num}"
......@@ -525,7 +506,6 @@ rule unique_num:
output:
num="{sample}/bams/{sample}.unique.num"
singularity: "docker://quay.io/biocontainers/samtools:1.6--he673b24_3"
conda: "envs/samtools.yml"
shell: "samtools view -F 4 -F 1024 {input.bam} | wc -l > {output.num}"
......@@ -536,7 +516,6 @@ rule usable_basenum:
output:
num="{sample}/bams/{sample}.usable.basenum"
singularity: "docker://quay.io/biocontainers/samtools:1.6--he673b24_3"
conda: "envs/samtools.yml"
shell: "samtools view -F 4 -F 1024 {input.bam} | cut -f10 | wc -c > "
"{output.num}"
......@@ -546,7 +525,7 @@ rule usable_basenum:
rule fastqc_raw:
"""
Run fastqc on raw fastq files
NOTE: singularity version uses 0.11.7 in stead of 0.11.5 due to
NOTE: singularity version uses 0.11.7 in stead of 0.11.5 due to
perl missing in the container of 0.11.5
"""
input:
......@@ -557,15 +536,14 @@ rule fastqc_raw:
output:
aux="{sample}/pre_process/raw_fastqc/.done.txt"
singularity: "docker://quay.io/biocontainers/fastqc:0.11.7--4"
conda: "envs/fastqc.yml"
shell: "fastqc --nogroup -o {params.odir} {input.r1} {input.r2} "
"&& echo 'done' > {output.aux}"
rule fastqc_merged:
"""
Run fastqc on merged fastq files
NOTE: singularity version uses 0.11.7 in stead of 0.11.5 due to
Run fastqc on merged fastq files
NOTE: singularity version uses 0.11.7 in stead of 0.11.5 due to
perl missing in the container of 0.11.5
"""
input:
......@@ -578,7 +556,6 @@ rule fastqc_merged:
r1="{sample}/pre_process/merged_fastqc/{sample}.merged_R1_fastqc.zip",
r2="{sample}/pre_process/merged_fastqc/{sample}.merged_R2_fastqc.zip"
singularity: "docker://quay.io/biocontainers/fastqc:0.11.7--4"
conda: "envs/fastqc.yml"
shell: "bash {input.fq} {input.r1} {input.r2} "
"{output.r1} {output.r2} {params.odir}"
......@@ -586,8 +563,8 @@ rule fastqc_merged:
rule fastqc_postqc:
"""
Run fastqc on fastq files post pre-processing
NOTE: singularity version uses 0.11.7 in stead of 0.11.5 due to
perl missing in the container of 0.11.5
NOTE: singularity version uses 0.11.7 in stead of 0.11.5 due to
perl missing in the container of 0.11.5
"""
input:
r1="{sample}/pre_process/{sample}.cutadapt_R1.fastq",
......@@ -599,7 +576,6 @@ rule fastqc_postqc:
r1="{sample}/pre_process/postqc_fastqc/{sample}.cutadapt_R1_fastqc.zip",
r2="{sample}/pre_process/postqc_fastqc/{sample}.cutadapt_R2_fastqc.zip"
singularity: "docker://quay.io/biocontainers/fastqc:0.11.7--4"
conda: "envs/fastqc.yml"
shell: "bash {input.fq} {input.r1} {input.r2} "
"{output.r1} {output.r2} {params.odir}"
......@@ -614,7 +590,6 @@ rule fqcount_preqc:
output:
"{sample}/pre_process/{sample}.preqc_count.json"
singularity: "docker://quay.io/biocontainers/fastq-count:0.1.0--h14c3975_0"
conda: "envs/fastq-count.yml"
shell: "fastq-count {input.r1} {input.r2} > {output}"
......@@ -626,7 +601,6 @@ rule fqcount_postqc:
output:
"{sample}/pre_process/{sample}.postqc_count.json"
singularity: "docker://quay.io/biocontainers/fastq-count:0.1.0--h14c3975_0"
conda: "envs/fastq-count.yml"
shell: "fastq-count {input.r1} {input.r2} > {output}"
......@@ -640,7 +614,6 @@ rule fastqc_stats:
postqc_r2="{sample}/pre_process/postqc_fastqc/{sample}.cutadapt_R2_fastqc.zip",
sc=fqpy
singularity: "docker://python:3.6-slim"
conda: "envs/collectstats.yml"
output:
"{sample}/pre_process/fastq_stats.json"
shell: "python {input.sc} --preqc-r1 {input.preqc_r1} "
......@@ -663,7 +636,6 @@ rule covstats:
covj="{sample}/coverage/{bed}.covstats.json",
covp="{sample}/coverage/{bed}.covstats.png"
singularity: "docker://quay.io/biocontainers/mulled-v2-3251e6c49d800268f0bc575f28045ab4e69475a6:4ce073b219b6dabb79d154762a9b67728c357edb-0"
conda: "envs/covstat.yml"
shell: "bedtools coverage -sorted -g {input.genome} -a {input.bed} "
"-b {input.bam} -d | python {input.covpy} - --plot {output.covp} "
"--title 'Targets coverage' --subtitle '{params.subt}' "
......@@ -679,7 +651,6 @@ rule vtools_coverage:
output:
tsv="{sample}/coverage/{ref}.coverages.tsv"
singularity: "docker://quay.io/biocontainers/vtools:1.0.0--py37h3010b51_0"
conda: "envs/vcfstats.yml"
shell: "vtools-gcoverage -I {input.gvcf} -R {input.ref} > {output.tsv}"
......@@ -693,7 +664,6 @@ rule vcfstats:
output:
stats="multisample/vcfstats.json"
singularity: "docker://quay.io/biocontainers/vtools:1.0.0--py37h3010b51_0"
conda: "envs/vcfstats.yml"
shell: "vtools-stats -i {input.vcf} > {output.stats}"
......@@ -718,7 +688,6 @@ if len(BASE_BEDS) >= 1:
output:
"{sample}/{sample}.stats.json"
singularity: "docker://quay.io/biocontainers/vtools:1.0.0--py37h3010b51_0"
conda: "envs/collectstats.yml"
shell: "python {input.colpy} --sample-name {params.sample_name} "
"--pre-qc-fastq {input.preqc} --post-qc-fastq {input.postq} "
"--mapped-num {input.mnum} --mapped-basenum {input.mbnum} "
......@@ -743,7 +712,6 @@ else:
output:
"{sample}/{sample}.stats.json"
singularity: "docker://quay.io/biocontainers/vtools:1.0.0--py37h3010b51_0"
conda: "envs/collectstats.yml"
shell: "python {input.colpy} --sample-name {params.sample_name} "
"--pre-qc-fastq {input.preqc} --post-qc-fastq {input.postq} "
"--mapped-num {input.mnum} --mapped-basenum {input.mbnum} "
......@@ -760,7 +728,6 @@ rule merge_stats:
output:
stats="stats.json"
singularity: "docker://quay.io/biocontainers/vtools:1.0.0--py37h3010b51_0"
conda: "envs/collectstats.yml"
shell: "python {input.mpy} --vcfstats {input.vstat} {input.cols} "
"> {output.stats}"
......@@ -773,7 +740,6 @@ rule stats_tsv:
output:
stats="stats.tsv"
singularity: "docker://python:3.6-slim"
conda: "envs/collectstats.yml"
shell: "python {input.sc} -i {input.stats} > {output.stats}"
......@@ -790,5 +756,4 @@ rule multiqc:
output:
report="multiqc_report/multiqc_report.html"
singularity: "docker://quay.io/biocontainers/multiqc:1.5--py36_0"
conda: "envs/multiqc.yml"
shell: "multiqc -f -o {params.rdir} {params.odir} || touch {output.report}"
- name: test-integration-run
command: >-
bash -c '
snakemake --use-conda --conda-prefix ${CONDA_PREFIX} --jobs 100 -w 120
--cluster "sbatch --parsable"
--cluster-status "${PWD}/cluster/slurm-cluster-status/slurm-cluster-status.py"
snakemake
--use-singularity
--singularity-prefix /tmp/singularity
--jobs 10 -w 120
-r -p -s Snakefile
--config JAVA=$(which java)
REFERENCE=${FUNCTIONAL_REF} GATK=${GATK_JAR}
DBSNP=${FUNCTIONAL_DBSNP}
ONETHOUSAND=${FUNCTIONAL_ONETHOUSAND}
HAPMAP=${FUNCTIONAL_HAPMAP}
SAMPLE_CONFIG=${FUNCTIONAL_SAMPLE_CONFIG}'
--config
REFERENCE=tests/data/ref.fa
GATK=tests/GenomeAnalysisTK.jar
DBSNP=tests/data/database.vcf.gz
ONETHOUSAND=tests/data/database.vcf.gz
HAPMAP=tests/data/database.vcf.gz
SAMPLE_CONFIG=tests/data/sample_config.json
exit_code: 0
stderr:
contains:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment