diff --git a/.config.yaml b/.config.yaml index 56bd6ad..c63a4b9 100644 --- a/.config.yaml +++ b/.config.yaml @@ -9,13 +9,29 @@ mykrobe: rasusa: params: "-c 150 -g 4411532 -s 88" +decom_DB: + url: "ftp://ftp-private.ebi.ac.uk/tbpore/0.1.0/decontamination_db/tbpore.remove_contam.fa.gz.map-ont.mmi.gz" + minimap2: - params: "-a -L --sam-hit-only --secondary=no -x map-ont" + map_to_decom_DB: + params: "-aL2 -x map-ont" + map: + params: "-a -L --sam-hit-only --secondary=no -x map-ont" samtools: + sort_decom_DB: + params: "" + index_decom_DB: + params: "" sort: params: "" +filter_contamination: + params: "--verbose --ignore-secondary" + +extract_decontaminated_nanopore_reads: + params: "grep" + bcftools: mpileup: params: "-x -I -Q 13 -a 'INFO/SCR,FORMAT/SP,INFO/ADR,INFO/ADF' -h100 -M10000" diff --git a/.gitignore b/.gitignore index 34f94bf..633579c 100644 --- a/.gitignore +++ b/.gitignore @@ -147,3 +147,4 @@ tmp/ /sample_example/ /tbpore_out/ /tests/helpers/logs/ +/pipelines/snakemake/.snakemake/ diff --git a/README.md b/README.md index 4e68191..a6b28c5 100644 --- a/README.md +++ b/README.md @@ -31,15 +31,15 @@ cd tbpore conda env create -f environment.yaml && conda activate tbpore # install dependencies just install # install tbpore just check # checks installation is fine -# if you want to run tbpore on an example isolate +# if you want to run tbpore on an example isolate (will require you to download the decontamination DB index) scripts/run_sample_example.sh ``` # Performance -Benchmarked on 109 TB Madagascar ONT samples with 1 thread: -* Runtime: `1361`s avg (`550`s SD), max `2294`s, min `102`s (s = seconds); -* RAM: `1266`MB avg (`394`MB SD), max `1914` MB, min `527` MB (MB = Megabytes); +Benchmarked on 91 TB Madagascar ONT samples with 1 thread: +* Runtime: `2255`s avg, `3805`s max (s = seconds); +* RAM: `12.4`GB avg, `13.1`GB max (GB = Gigabytes); # Usage diff --git a/data/decontamination_db/remove_contam.tsv.gz b/data/decontamination_db/remove_contam.tsv.gz new file mode 100644 index 0000000..98ec30d Binary files /dev/null and b/data/decontamination_db/remove_contam.tsv.gz differ diff --git a/environment.yaml b/environment.yaml index c830ad6..e352b98 100644 --- a/environment.yaml +++ b/environment.yaml @@ -16,4 +16,5 @@ dependencies: - rasusa - samtools=1.13 - bcftools=1.13 - - minimap2=2.24 + - minimap2=2.22 + - seqkit=2.0.0 diff --git a/external_scripts/filter_contamination.py b/external_scripts/filter_contamination.py new file mode 100644 index 0000000..964898d --- /dev/null +++ b/external_scripts/filter_contamination.py @@ -0,0 +1,182 @@ +import logging +from enum import Enum +from pathlib import Path +from typing import Set + +import click +import pandas as pd +import pysam + +IS_CONTAM_COL = "is_contaminant" + + +class RequiredIf(click.Option): + def __init__(self, *args, **kwargs): + self.required_if = kwargs.pop("required_if") + assert self.required_if, "'required_if' parameter required" + kwargs["help"] = ( + kwargs.get("help", "") + + " NOTE: This argument is mutually inclusive with %s" % self.required_if + ).strip() + super(RequiredIf, self).__init__(*args, **kwargs) + + def handle_parse_result(self, ctx, opts, args): + we_are_present = self.name in opts + other_present = self.required_if in opts + + if not other_present: + if we_are_present: + raise click.UsageError( + "Illegal usage: `%s` is mutually inclusive with `%s`" + % (self.name, self.required_if) + ) + + return super(RequiredIf, self).handle_parse_result(ctx, opts, args) + + +class Classification(Enum): + Contaminant = "contaminant" + Unmaped = "unmapped" + Keep = "keep" + Other = "other" + + +class Classifier: + def __init__(self, metadata_file: str): + self.metadata = pd.read_table( + metadata_file, + header=None, + names=["organism", IS_CONTAM_COL, "accession"], + index_col="accession", + dtype={IS_CONTAM_COL: "bool"}, + ) + + def classify(self, record: pysam.AlignedSegment) -> Classification: + if record.is_unmapped: + return Classification.Unmaped + + ref_id = record.reference_name + is_contam: bool = self.metadata.at[ref_id, IS_CONTAM_COL] + if is_contam: + return Classification.Contaminant + + return Classification.Keep + + +@click.command() +@click.help_option("--help", "-h") +@click.option( + "-i", + "--samfile", + help="{B,CR,S}AM file of reads mapped to decontamination database.", + type=click.Path(exists=True, dir_okay=False), + required=True, +) +@click.option( + "-m", + "--metadata", + help=( + "TSV file containing information about each reference in the database. Column " + "1 is the category, column 2 is whether the reference is contamination, column " + "3 is the accession ID for the reference." + ), + type=click.Path(exists=True, dir_okay=False), + required=True, +) +@click.option( + "-o", + "--outdir", + type=click.Path(dir_okay=True, writable=True), + help=( + "Directory to write the output files to. The files written will be named " + "unmapped.reads, contaminant.reads, and keep.reads" + ), + default=".", + show_default=True, +) +@click.option( + "--ignore-secondary/--include-secondary", + help="Ignore organism assignments for secondary alignments?", + default=True, + show_default=True, +) +@click.option("-v", "--verbose", help="Turns on debug-level logging.", is_flag=True) +def main( + samfile: str, + metadata: str, + outdir: str, + ignore_secondary: bool, + verbose: bool, +): + """This scripts classifies records in an alignment to a contamination database, with + the help of a metadata file mapping reference names to whether they are + contamination or not. It produces three files with a read identifier for each line: + - unmapped reads + - contaminated reads + - reads to keep + """ + log_level = logging.DEBUG if verbose else logging.INFO + logging.basicConfig( + format="%(asctime)s [%(levelname)s]: %(message)s", level=log_level + ) + outdir = Path(outdir) + outdir.mkdir(exist_ok=True) + + classifier = Classifier(metadata) + all_read_ids: Set[str] = set() + unmapped_reads: Set[str] = set() + contaminant_reads: Set[str] = set() + keep_reads: Set[str] = set() + + logging.info("Classifying records in alignment file...") + with pysam.AlignmentFile(samfile) as bam: + for record in bam: + read_id = record.query_name + if read_id is None: + logging.warning(f"Got a record with no query name\n{str(record)}") + continue + + all_read_ids.add(read_id) + if record.is_secondary and ignore_secondary: + logging.debug(f"{read_id} has secondary alignment. Skipping...") + continue + + classification = classifier.classify(record) + if classification is Classification.Unmaped: + unmapped_reads.add(read_id) + elif classification is Classification.Keep: + keep_reads.add(read_id) + elif classification.Contaminant: + contaminant_reads.add(read_id) + else: + raise NotImplementedError( + f"Don't know how to handle classification: {classification}" + ) + + # if any read in the pair is a "keeper" remove it from contaminants + contaminant_reads -= keep_reads + # reads are only unmapped if both are unmapped + unmapped_reads -= keep_reads.union(contaminant_reads) + + assert all_read_ids == keep_reads.union(unmapped_reads, contaminant_reads) + + logging.info(f"{len(keep_reads)} reads are to be kept") + logging.info(f"{len(contaminant_reads)} reads are contaminants") + logging.info(f"{len(unmapped_reads)} reads are unmapped") + logging.info("Writing output files...") + + keep_file = outdir / "keep.reads" + keep_file.write_text("\n".join(keep_reads)) + logging.info(f"Read identifiers to keep written to {keep_file}") + + contaminant_file = outdir / "contaminant.reads" + contaminant_file.write_text("\n".join(contaminant_reads)) + logging.info(f"Contaminant read identifiers written to {contaminant_file}") + + unmapped_file = outdir / "unmapped.reads" + unmapped_file.write_text("\n".join(unmapped_reads)) + logging.info(f"Unmapped read identifiers written to {unmapped_file}") + + +if __name__ == "__main__": + main() diff --git a/justfile b/justfile index 51f6634..9187c38 100644 --- a/justfile +++ b/justfile @@ -16,7 +16,7 @@ check-fmt: # lint code with flake8 lint: - poetry run flake8 . --extend-exclude=".venv/" + poetry run flake8 . --extend-exclude=".venv/,pipelines/snakemake" # install latest version with poetry install: @@ -25,7 +25,7 @@ install: # run all tests test opts="": - poetry run pytest {{opts}} tests/ + poetry run pytest -vv {{opts}} tests/ # run tests with coverage report coverage: diff --git a/pipelines/snakemake/Snakefile b/pipelines/snakemake/Snakefile new file mode 100644 index 0000000..19ea87e --- /dev/null +++ b/pipelines/snakemake/Snakefile @@ -0,0 +1,77 @@ +import glob + +configfile: "config.yaml" + +rule all: + input: + f"{config['output_dir']}/consensus_comparison.out", + f"{config['output_dir']}/bcfs_comparison.out", + f"{config['output_dir']}/mykrobe_comparison.out", + f"{config['output_dir']}/mykrobe_comparison.simple.out", + +def get_input(wildcards): + reads = glob.glob(f"{config['base_reads_dir']}/{wildcards.sample}.nanopore.fq.gz") + assert len(reads) == 1 + return reads + +rule run_tbpore: + input: + get_input + output: + directory(f"{config['output_dir']}/{{sample}}") + threads: 1 + resources: + mem_mb=lambda wildcards, attempt: 20000 * attempt + log: + "logs/run_tbpore_{sample}.log" + shell: + "tbpore --no-cleanup -o {output} {input}" + + +rule compare_h2h_and_tbpore_consensus: + input: + all_tbpore_outputs = expand(f"{config['output_dir']}/{{sample}}", sample=config['samples']) + output: + consensus_comparison = f"{config['output_dir']}/consensus_comparison.out" + params: + tbpore_output = config['output_dir'], + h2h_consensus_glob_pattern = config['h2h_consensus_glob_pattern'], + threads: 1 + resources: + mem_mb=lambda wildcards, attempt: 1000 * attempt + log: + "logs/compare_h2h_and_tbpore_consensus.log" + script: "scripts/compare_H2H_and_tbpore_consensus.py" + + +rule compare_h2h_and_tbpore_bcfs: + input: + all_tbpore_outputs = expand(f"{config['output_dir']}/{{sample}}", sample=config['samples']) + output: + bcfs_comparison = f"{config['output_dir']}/bcfs_comparison.out" + params: + tbpore_output = config['output_dir'], + h2h_bcf_glob_pattern = config['h2h_bcf_glob_pattern'], + threads: 1 + resources: + mem_mb=lambda wildcards, attempt: 1000 * attempt + log: + "logs/compare_h2h_and_tbpore_bcfs.log" + script: "scripts/compare_H2H_and_tbpore_bcfs.py" + + +rule compare_h2h_and_tbpore_mykrobe: + input: + all_tbpore_outputs = expand(f"{config['output_dir']}/{{sample}}", sample=config['samples']) + output: + mykrobe_comparison = f"{config['output_dir']}/mykrobe_comparison.out", + mykrobe_comparison_simple = f"{config['output_dir']}/mykrobe_comparison.simple.out" + params: + tbpore_output = config['output_dir'], + h2h_mykrobe_glob_pattern = config['h2h_mykrobe_glob_pattern'], + threads: 1 + resources: + mem_mb=lambda wildcards, attempt: 1000 * attempt + log: + "logs/compare_h2h_and_tbpore_mykrobe.log" + script: "scripts/compare_H2H_and_tbpore_mykrobe.py" diff --git a/pipelines/snakemake/config.yaml b/pipelines/snakemake/config.yaml new file mode 100644 index 0000000..7d46dcd --- /dev/null +++ b/pipelines/snakemake/config.yaml @@ -0,0 +1,6 @@ +base_reads_dir: "/hps/nobackup/iqbal/mbhall/tech_wars/data/madagascar/nanopore/raw_data/*/guppy_v5.0.16" +samples: ["mada_1-19", "mada_1-8", "mada_1-6", "mada_103", "mada_1-1", "mada_130", "mada_132", "mada_128", "mada_2-1", "mada_1-51", "mada_1-20", "mada_2-31", "mada_109", "mada_112", "mada_1-5", "mada_107", "mada_1-40", "mada_111", "mada_1-14", "mada_1-46", "mada_136", "mada_1-54", "mada_1-25", "mada_118", "mada_129", "mada_1-18", "mada_151", "mada_134", "mada_1-3", "mada_1-44", "mada_1-15", "mada_1-47", "mada_2-53", "mada_1-16", "mada_1-2", "mada_154", "mada_104", "mada_115", "mada_126", "mada_1-33", "mada_102", "mada_127", "mada_125", "mada_1-43", "mada_137", "mada_117", "mada_131", "mada_2-46", "mada_1-17", "mada_124", "mada_121", "mada_141", "mada_2-42", "mada_1-28", "mada_152", "mada_1-48", "mada_2-34", "mada_123", "mada_106", "mada_140", "mada_1-30", "mada_1-50", "mada_139", "mada_1-41", "mada_2-25", "mada_105", "mada_144", "mada_1-32", "mada_1-22", "mada_1-11", "mada_1-10", "mada_110", "mada_120", "mada_113", "mada_1-38", "mada_122", "mada_1-7", "mada_116", "mada_142", "mada_133", "mada_148", "mada_1-13", "mada_1-53", "mada_135", "mada_1-12", "mada_2-50", "mada_1-21", "mada_1-39", "mada_1-36", "mada_143", "mada_150"] +h2h_consensus_glob_pattern: "/hps/nobackup/iqbal/mbhall/tech_wars/analysis/baseline_variants/consensus/bcftools/madagascar/*.consensus.fa" +h2h_mykrobe_glob_pattern: "/hps/nobackup/iqbal/mbhall/tech_wars/analysis/resistance_prediction/results/mykrobe/predict/nanopore/madagascar/*/*.mykrobe.json" +h2h_bcf_glob_pattern: "/hps/nobackup/iqbal/mbhall/tech_wars/analysis/baseline_variants/nanopore/filtered_snps/madagascar/*.snps.filtered.bcf" +output_dir: "output" diff --git a/pipelines/snakemake/scripts/compare_H2H_and_tbpore_bcfs.py b/pipelines/snakemake/scripts/compare_H2H_and_tbpore_bcfs.py new file mode 100644 index 0000000..6311fb5 --- /dev/null +++ b/pipelines/snakemake/scripts/compare_H2H_and_tbpore_bcfs.py @@ -0,0 +1,55 @@ +from glob import glob +from pathlib import Path + +from cyvcf2 import VCF + + +def get_samples(glob_pattern): + bcf_files = (Path(file).resolve() for file in glob(glob_pattern)) + return {file.name.replace(".snps.filtered.bcf", ""): file for file in bcf_files} + + +def get_var_with_no_qual(variant): + variant = str(variant) + split_variant = variant.split("\t") + split_variant_with_no_qual = split_variant[:5] + split_variant[6:] + return "\t".join(split_variant_with_no_qual) + + +def compare(h2h_bcf_glob_pattern, tbpore_glob_pattern, output): + h2h_samples = get_samples(h2h_bcf_glob_pattern) + tbpore_samples = get_samples(tbpore_glob_pattern) + common_samples = set(h2h_samples.keys()).intersection(set(tbpore_samples.keys())) + + with open(output, "w") as output_fh: + for sample in common_samples: + h2h_bcf = VCF(h2h_samples[sample]) + tbpore_bcf = VCF(tbpore_samples[sample]) + nb_of_different_variants = 0 + for h2h_variant, tbpore_variant in zip(h2h_bcf, tbpore_bcf): + h2h_variant_with_no_qual = get_var_with_no_qual(h2h_variant) + tbpore_variant_with_no_qual = get_var_with_no_qual(tbpore_variant) + variants_are_different = ( + h2h_variant_with_no_qual != tbpore_variant_with_no_qual + ) + if variants_are_different: + print( + f"Different VCF records in sample {sample}:\n{h2h_variant}{tbpore_variant}", + file=output_fh, + ) + nb_of_different_variants += 1 + print( + f"Sample {sample}: {nb_of_different_variants} different variants", + file=output_fh, + ) + + +def __main__(): + compare( + h2h_bcf_glob_pattern=snakemake.params.h2h_bcf_glob_pattern, + tbpore_glob_pattern=f"{snakemake.params.tbpore_output}/*/*.snps.filtered.bcf", + output=snakemake.output.bcfs_comparison, + ) + + +__main__() diff --git a/pipelines/snakemake/scripts/compare_H2H_and_tbpore_consensus.py b/pipelines/snakemake/scripts/compare_H2H_and_tbpore_consensus.py new file mode 100644 index 0000000..d33c0d4 --- /dev/null +++ b/pipelines/snakemake/scripts/compare_H2H_and_tbpore_consensus.py @@ -0,0 +1,34 @@ +import subprocess +from glob import glob +from pathlib import Path + + +def get_samples(glob_pattern): + consensus_files = (Path(file).resolve() for file in glob(glob_pattern)) + return {file.name.replace(".consensus.fa", ""): file for file in consensus_files} + + +def compare(h2h_consensus_glob_pattern, tbpore_glob_pattern, output): + h2h_samples = get_samples(h2h_consensus_glob_pattern) + tbpore_samples = get_samples(tbpore_glob_pattern) + common_samples = set(h2h_samples.keys()).intersection(set(tbpore_samples.keys())) + + for sample in common_samples: + h2h_consensus = h2h_samples[sample] + tbpore_consensus = tbpore_samples[sample] + subprocess.check_call( + f"diff -qs {h2h_consensus} {tbpore_consensus} >> {output}", shell=True + ) + + +def __main__(): + with open(snakemake.output.consensus_comparison, "w"): + pass + compare( + h2h_consensus_glob_pattern=snakemake.params.h2h_consensus_glob_pattern, + tbpore_glob_pattern=f"{snakemake.params.tbpore_output}/*/*.consensus.fa", + output=snakemake.output.consensus_comparison, + ) + + +__main__() diff --git a/pipelines/snakemake/scripts/compare_H2H_and_tbpore_mykrobe.py b/pipelines/snakemake/scripts/compare_H2H_and_tbpore_mykrobe.py new file mode 100644 index 0000000..f6711f2 --- /dev/null +++ b/pipelines/snakemake/scripts/compare_H2H_and_tbpore_mykrobe.py @@ -0,0 +1,56 @@ +import json +from glob import glob +from pathlib import Path + +import dictdiffer + + +def get_samples(glob_pattern): + mykrobe_files = (Path(file).resolve() for file in glob(glob_pattern)) + return {file.name.replace(".mykrobe.json", ""): file for file in mykrobe_files} + + +def cleanup_susceptiblity_dict(dict): + for drug in dict: + if "called_by" in dict[drug]: + del dict[drug]["called_by"] + for drug in dict: + assert "called_by" not in dict[drug] + + +def compare(h2h_mykrobe_glob_pattern, tbpore_glob_pattern, output_fh, output_simple_fh): + h2h_samples = get_samples(h2h_mykrobe_glob_pattern) + tbpore_samples = get_samples(tbpore_glob_pattern) + common_samples = set(h2h_samples.keys()).intersection(set(tbpore_samples.keys())) + for sample in common_samples: + h2h_mykrobe = h2h_samples[sample] + tbpore_mykrobe = tbpore_samples[sample] + + with open(h2h_mykrobe) as h2h_mykrobe_fh, open( + tbpore_mykrobe + ) as tbpore_mykrobe_fh: + h2h_mykrobe_json = json.load(h2h_mykrobe_fh) + tbpore_mykrobe_json = json.load(tbpore_mykrobe_fh) + + print(f"Diffing mykrobe jsons for {sample}", file=output_fh) + h2h_susceptibility = h2h_mykrobe_json[sample]["susceptibility"] + tbpore_susceptibility = tbpore_mykrobe_json[sample]["susceptibility"] + for diff in list(dictdiffer.diff(h2h_susceptibility, tbpore_susceptibility)): + print(diff, file=output_fh) + + print(f"Diffing mykrobe jsons for {sample}", file=output_simple_fh) + cleanup_susceptiblity_dict(h2h_susceptibility) + cleanup_susceptiblity_dict(tbpore_susceptibility) + for diff in list(dictdiffer.diff(h2h_susceptibility, tbpore_susceptibility)): + print(diff, file=output_simple_fh) + + +with open(snakemake.output.mykrobe_comparison, "w") as output_fh, open( + snakemake.output.mykrobe_comparison_simple, "w" +) as output_simple_fh: + compare( + h2h_mykrobe_glob_pattern=snakemake.params.h2h_mykrobe_glob_pattern, + tbpore_glob_pattern=f"{snakemake.params.tbpore_output}/*/*.mykrobe.json", + output_fh=output_fh, + output_simple_fh=output_simple_fh, + ) diff --git a/pipelines/snakemake/scripts/compare_kept_reads.py b/pipelines/snakemake/scripts/compare_kept_reads.py new file mode 100644 index 0000000..bcd3f3d --- /dev/null +++ b/pipelines/snakemake/scripts/compare_kept_reads.py @@ -0,0 +1,121 @@ +import subprocess +from pathlib import Path + +# configs +samples = [ + "mada_1-19", + "mada_1-8", + "mada_1-6", + "mada_103", + "mada_1-1", + "mada_130", + "mada_132", + "mada_128", + "mada_2-1", + "mada_1-51", + "mada_1-20", + "mada_2-31", + "mada_109", + "mada_112", + "mada_1-5", + "mada_107", + "mada_1-40", + "mada_111", + "mada_1-14", + "mada_1-46", + "mada_136", + "mada_1-54", + "mada_1-25", + "mada_118", + "mada_129", + "mada_1-18", + "mada_151", + "mada_134", + "mada_1-3", + "mada_1-44", + "mada_1-15", + "mada_1-47", + "mada_2-53", + "mada_1-16", + "mada_1-2", + "mada_154", + "mada_104", + "mada_115", + "mada_126", + "mada_1-33", + "mada_102", + "mada_127", + "mada_125", + "mada_1-43", + "mada_137", + "mada_117", + "mada_131", + "mada_2-46", + "mada_1-17", + "mada_124", + "mada_121", + "mada_141", + "mada_2-42", + "mada_1-28", + "mada_152", + "mada_1-48", + "mada_2-34", + "mada_123", + "mada_106", + "mada_140", + "mada_1-30", + "mada_1-50", + "mada_139", + "mada_1-41", + "mada_2-25", + "mada_105", + "mada_144", + "mada_1-32", + "mada_1-22", + "mada_1-11", + "mada_1-10", + "mada_110", + "mada_120", + "mada_113", + "mada_1-38", + "mada_122", + "mada_1-7", + "mada_116", + "mada_142", + "mada_133", + "mada_148", + "mada_1-13", + "mada_1-53", + "mada_135", + "mada_1-12", + "mada_2-50", + "mada_1-21", + "mada_1-39", + "mada_1-36", + "mada_143", + "mada_150", +] +H2H_path = Path( + "/hps/nobackup/iqbal/mbhall/tech_wars/data/QC/filtered/madagascar/nanopore" +) +tbpore_path = Path( + "/hps/nobackup/iqbal/leandro/tbpore2/tbpore/pipelines/snakemake/output_human_decon" +) + +sample_to_nb_of_diffs = {} +for sample in samples: + h2h_keep_reads = H2H_path / sample / "keep.reads" + tbpore_keep_reads = ( + tbpore_path / sample / ".tbpore" / f"{sample}.decontaminated.filter/keep.reads" + ) + diff_out = subprocess.check_output( + f'/bin/bash -c "diff --suppress-common-lines -y <(sort {h2h_keep_reads}) <(sort {tbpore_keep_reads}) | wc -l"', + shell=True, + ) + nb_of_diffs = int(diff_out.strip()) + sample_to_nb_of_diffs[sample] = nb_of_diffs + +print("Differences:") +for sample, nb_of_diffs in sample_to_nb_of_diffs.items(): + print(f"{sample} {nb_of_diffs}") +print(f"Total {sum(sample_to_nb_of_diffs.values())}") diff --git a/pipelines/snakemake/submit_lsf.sh b/pipelines/snakemake/submit_lsf.sh new file mode 100755 index 0000000..db6ade6 --- /dev/null +++ b/pipelines/snakemake/submit_lsf.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -eux + +MEMORY=4000 +PROFILE="lsf" +LOG_DIR=logs/ +JOB_NAME="snakemake_master_process."$(date --iso-8601='minutes') + +mkdir -p $LOG_DIR + +bsub -R "select[mem>$MEMORY] rusage[mem=$MEMORY] span[hosts=1]" \ + -M "$MEMORY" \ + -o "$LOG_DIR"/"$JOB_NAME".o \ + -e "$LOG_DIR"/"$JOB_NAME".e \ + -J "$JOB_NAME" \ + snakemake --profile "$PROFILE" "$@" + +exit 0 diff --git a/poetry.lock b/poetry.lock index 6f58534..c7c962a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,11 @@ +[[package]] +name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "atomicwrites" version = "1.4.0" @@ -42,9 +50,28 @@ d = ["aiohttp (>=3.7.4)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +[[package]] +name = "certifi" +version = "2021.10.8" +description = "Python package for providing Mozilla's CA Bundle." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "charset-normalizer" +version = "2.0.12" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "dev" +optional = false +python-versions = ">=3.5.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + [[package]] name = "click" -version = "8.1.2" +version = "8.1.3" description = "Composable command line interface toolkit" category = "main" optional = false @@ -75,6 +102,26 @@ humanfriendly = ">=9.1" [package.extras] cron = ["capturer (>=2.4)"] +[[package]] +name = "configargparse" +version = "1.5.3" +description = "A drop-in replacement for argparse that allows options to also be set via config files and/or environment variables." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +test = ["mock", "pyyaml", "pytest"] +yaml = ["pyyaml"] + +[[package]] +name = "connection-pool" +version = "0.0.3" +description = "thread safe connection pool" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "coverage" version = "6.3.2" @@ -102,6 +149,63 @@ click = "*" coloredlogs = "*" numpy = "*" +[[package]] +name = "datrie" +version = "0.8.2" +description = "Super-fast, efficiently stored Trie for Python." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "dictdiffer" +version = "0.9.0" +description = "Dictdiffer is a library that helps you to diff and patch dictionaries." +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +all = ["Sphinx (>=3)", "sphinx-rtd-theme (>=0.2)", "check-manifest (>=0.42)", "mock (>=1.3.0)", "pytest-cov (>=2.10.1)", "pytest-isort (>=1.2.0)", "sphinx (>=3)", "tox (>=3.7.0)", "numpy (>=1.13.0)", "numpy (>=1.15.0)", "numpy (>=1.18.0)", "pytest (==5.4.3)", "pytest-pycodestyle (>=2)", "pytest-pydocstyle (>=2)", "pytest (>=6)", "pytest-pycodestyle (>=2.2.0)", "pytest-pydocstyle (>=2.2.0)", "numpy (>=1.20.0)"] +docs = ["Sphinx (>=3)", "sphinx-rtd-theme (>=0.2)"] +numpy = ["numpy (>=1.13.0)", "numpy (>=1.15.0)", "numpy (>=1.18.0)", "numpy (>=1.20.0)"] +tests = ["check-manifest (>=0.42)", "mock (>=1.3.0)", "pytest-cov (>=2.10.1)", "pytest-isort (>=1.2.0)", "sphinx (>=3)", "tox (>=3.7.0)", "pytest (==5.4.3)", "pytest-pycodestyle (>=2)", "pytest-pydocstyle (>=2)", "pytest (>=6)", "pytest-pycodestyle (>=2.2.0)", "pytest-pydocstyle (>=2.2.0)"] + +[[package]] +name = "docutils" +version = "0.18.1" +description = "Docutils -- Python Documentation Utilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "dpath" +version = "2.0.6" +description = "Filesystem-like pathing and searching for dictionaries" +category = "dev" +optional = false +python-versions = ">=3" + +[[package]] +name = "fastjsonschema" +version = "2.15.3" +description = "Fastest Python implementation of JSON schema" +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +devel = ["colorama", "jsonschema", "json-spec", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] + [[package]] name = "flake8" version = "4.0.1" @@ -115,6 +219,28 @@ mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.8.0,<2.9.0" pyflakes = ">=2.4.0,<2.5.0" +[[package]] +name = "gitdb" +version = "4.0.9" +description = "Git Object Database" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.27" +description = "GitPython is a python library used to interact with Git repositories" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +gitdb = ">=4.0.1,<5" + [[package]] name = "humanfriendly" version = "10.0" @@ -126,6 +252,29 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.dependencies] pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "dev" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "importlib-resources" +version = "5.7.1" +description = "Read resources from Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] + [[package]] name = "iniconfig" version = "1.1.1" @@ -148,6 +297,52 @@ requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsonschema" +version = "4.5.1" +description = "An implementation of JSON Schema validation for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +attrs = ">=17.4.0" +importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format_nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jupyter-core" +version = "4.10.0" +description = "Jupyter core package. A base package on which Jupyter projects rely." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +pywin32 = {version = ">=1.0", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = "*" + +[package.extras] +test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] + [[package]] name = "loguru" version = "0.5.3" @@ -163,6 +358,14 @@ win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] dev = ["codecov (>=2.0.15)", "colorama (>=0.3.4)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "tox-travis (>=0.12)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "Sphinx (>=2.2.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "black (>=19.10b0)", "isort (>=5.1.1)"] +[[package]] +name = "markupsafe" +version = "2.1.1" +description = "Safely add untrusted strings to HTML/XML markup." +category = "dev" +optional = false +python-versions = ">=3.7" + [[package]] name = "mccabe" version = "0.6.1" @@ -179,6 +382,23 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "nbformat" +version = "5.4.0" +description = "The Jupyter Notebook format" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +fastjsonschema = "*" +jsonschema = ">=2.6" +jupyter-core = "*" +traitlets = ">=5.1" + +[package.extras] +test = ["check-manifest", "testpath", "pytest", "pre-commit"] + [[package]] name = "numpy" version = "1.22.3" @@ -198,6 +418,27 @@ python-versions = ">=3.6" [package.dependencies] pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +[[package]] +name = "pandas" +version = "1.4.2" +description = "Powerful data structures for data analysis, time series, and statistics" +category = "main" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +numpy = [ + {version = ">=1.18.5", markers = "platform_machine != \"aarch64\" and platform_machine != \"arm64\" and python_version < \"3.10\""}, + {version = ">=1.19.2", markers = "platform_machine == \"aarch64\" and python_version < \"3.10\""}, + {version = ">=1.20.0", markers = "platform_machine == \"arm64\" and python_version < \"3.10\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, +] +python-dateutil = ">=2.8.1" +pytz = ">=2020.1" + +[package.extras] +test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] + [[package]] name = "pathspec" version = "0.9.0" @@ -206,6 +447,14 @@ category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +[[package]] +name = "plac" +version = "1.3.5" +description = "The smartest command line arguments parser in the world" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "platformdirs" version = "2.5.2" @@ -230,6 +479,25 @@ python-versions = ">=3.6" dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "psutil" +version = "5.9.0" +description = "Cross-platform lib for process and system monitoring in Python." +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.extras] +test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"] + +[[package]] +name = "pulp" +version = "2.6.0" +description = "PuLP is an LP modeler written in python. PuLP can generate MPS or LP files and call GLPK, COIN CLP/CBC, CPLEX, and GUROBI to solve linear problems." +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "py" version = "1.11.0" @@ -256,7 +524,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pyparsing" -version = "3.0.8" +version = "3.0.9" description = "pyparsing module - Classes and methods to define and execute parsing grammars" category = "dev" optional = false @@ -273,6 +541,22 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "pyrsistent" +version = "0.18.1" +description = "Persistent/Functional/Immutable data structures" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "pysam" +version = "0.19.0" +description = "pysam" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "pytest" version = "6.2.5" @@ -309,6 +593,33 @@ pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2022.1" +description = "World timezone definitions, modern and historical" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "pywin32" +version = "304" +description = "Python for Window Extensions" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "pyyaml" version = "6.0" @@ -317,6 +628,136 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "ratelimiter" +version = "1.2.0.post0" +description = "Simple python rate limiting object" +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +test = ["pytest (>=3.0)", "pytest-asyncio"] + +[[package]] +name = "requests" +version = "2.27.1" +description = "Python HTTP for Humans." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} +idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] + +[[package]] +name = "retry" +version = "0.9.2" +description = "Easy to use retry decorator." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +decorator = ">=3.4.2" +py = ">=1.4.26,<2.0.0" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "smart-open" +version = "6.0.0" +description = "Utils for streaming large files (S3, HDFS, GCS, Azure Blob Storage, gzip, bz2...)" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" + +[package.extras] +all = ["boto3", "google-cloud-storage (>=1.31.0)", "azure-storage-blob", "azure-common", "azure-core", "requests"] +azure = ["azure-storage-blob", "azure-common", "azure-core"] +gcs = ["google-cloud-storage (>=1.31.0)"] +http = ["requests"] +s3 = ["boto3"] +test = ["boto3", "google-cloud-storage (>=1.31.0)", "azure-storage-blob", "azure-common", "azure-core", "requests", "moto", "pathlib2", "responses", "paramiko", "pytest", "pytest-rerunfailures"] +webhdfs = ["requests"] + +[[package]] +name = "smmap" +version = "5.0.0" +description = "A pure Python implementation of a sliding window memory map manager" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "snakemake" +version = "7.6.2" +description = "Snakemake is a workflow management system that aims to reduce the complexity of creating workflows by providing a fast and comfortable execution environment, together with a clean and modern specification language in python style. Snakemake workflows are essentially Python scripts extended by declarative code to define rules. Rules describe how to create output files from input files." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +appdirs = "*" +configargparse = "*" +connection_pool = ">=0.0.3" +datrie = "*" +docutils = "*" +gitpython = "*" +jinja2 = ">=3.0,<4.0" +jsonschema = "*" +nbformat = "*" +psutil = "*" +pulp = ">=2.0" +pyyaml = "*" +ratelimiter = "*" +requests = "*" +retry = "*" +smart_open = ">=3.0" +stopit = "*" +tabulate = "*" +toposort = "*" +wrapt = "*" +yte = ">=1.0,<2.0" + +[package.extras] +google-cloud = ["oauth2client", "google-crc32c", "google-api-python-client", "google-cloud-storage"] +messaging = ["slacker"] +pep = ["peppy", "eido"] +reports = ["jinja2", "pygments"] + +[[package]] +name = "stopit" +version = "1.1.2" +description = "Timeout control decorator and context managers, raise any exception in another thread" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "tabulate" +version = "0.8.9" +description = "Pretty-print tabular data" +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +widechars = ["wcwidth"] + [[package]] name = "toml" version = "0.10.2" @@ -333,6 +774,25 @@ category = "dev" optional = false python-versions = ">=3.7" +[[package]] +name = "toposort" +version = "1.7" +description = "\"Implements a topological sort algorithm.\"" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "traitlets" +version = "5.2.0" +description = "Traitlets Python configuration system" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +test = ["pytest", "pre-commit"] + [[package]] name = "typing-extensions" version = "4.2.0" @@ -341,6 +801,19 @@ category = "dev" optional = false python-versions = ">=3.7" +[[package]] +name = "urllib3" +version = "1.26.9" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" + +[package.extras] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + [[package]] name = "win32-setctime" version = "1.1.0" @@ -352,12 +825,49 @@ python-versions = ">=3.5" [package.extras] dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"] +[[package]] +name = "wrapt" +version = "1.14.1" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[[package]] +name = "yte" +version = "1.4.0" +description = "A YAML template engine with Python expressions" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +dpath = ">=2.0,<3.0" +plac = ">=1.3.4,<2.0.0" +pyyaml = ">=6.0,<7.0" + +[[package]] +name = "zipp" +version = "3.8.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] + [metadata] lock-version = "1.1" python-versions = ">=3.8,<4.0" -content-hash = "266fb54d90592c1a0da968cea036d4004f98e933e77ad27a06681caa5a4e2a81" +content-hash = "24a96e4337f16fe4943d244dae158fb4ffa7dec9bd09e443dea763a231a258f8" [metadata.files] +appdirs = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -391,9 +901,17 @@ black = [ {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"}, {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, ] +certifi = [ + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, + {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, +] click = [ - {file = "click-8.1.2-py3-none-any.whl", hash = "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e"}, - {file = "click-8.1.2.tar.gz", hash = "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"}, + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -403,6 +921,13 @@ coloredlogs = [ {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, ] +configargparse = [ + {file = "ConfigArgParse-1.5.3-py3-none-any.whl", hash = "sha256:18f6535a2db9f6e02bd5626cc7455eac3e96b9ab3d969d366f9aafd5c5c00fe7"}, + {file = "ConfigArgParse-1.5.3.tar.gz", hash = "sha256:1b0b3cbf664ab59dada57123c81eff3d9737e0d11d8cf79e3d6eb10823f1739f"}, +] +connection-pool = [ + {file = "connection_pool-0.0.3.tar.gz", hash = "sha256:bf429e7aef65921c69b4ed48f3d48d3eac1383b05d2df91884705842d974d0dc"}, +] coverage = [ {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"}, {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"}, @@ -460,14 +985,77 @@ cyvcf2 = [ {file = "cyvcf2-0.30.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75a769ad18b09223a83d15edd32de58db8a81c21f044b8e2b4422ec34b0ac4c2"}, {file = "cyvcf2-0.30.15.tar.gz", hash = "sha256:8ed8b42f8518e107b471bbec02ef21478cae49f48207f348f8457dafd35c43da"}, ] +datrie = [ + {file = "datrie-0.8.2-cp27-cp27m-macosx_10_7_x86_64.whl", hash = "sha256:53969643e2794c37f024d5edaa42d5e6e2627d9937ddcc18d99128e9df700e4c"}, + {file = "datrie-0.8.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:6c9b333035312b79e6e9a10356d033e3d29aadbae6365007f706c854b3a94674"}, + {file = "datrie-0.8.2-cp27-cp27m-win32.whl", hash = "sha256:c783e2c1e28964b2b045a951eb9606833a188c4bd4a780da68d22f557e03e429"}, + {file = "datrie-0.8.2-cp27-cp27m-win_amd64.whl", hash = "sha256:f826e843138698501cbf1a21233f724b851b1e475fad532b638ac5904e115f10"}, + {file = "datrie-0.8.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bf5c956c0a9a9d0f07e3c8923746279171096de18a8a51685e22d9817f8755a6"}, + {file = "datrie-0.8.2-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:2de594d84a2f43a09ddc15316a8afd48aae0fdc456f9279d0940aa59c473d9d5"}, + {file = "datrie-0.8.2-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:651c63325056347b86c5de7ffeea8529230a5787c61ee6dcabc5b6c644bd3252"}, + {file = "datrie-0.8.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:0e3b76676abbae2368cce6bf605bb0ba7cfd11f2c420b96d67959f353d5d423f"}, + {file = "datrie-0.8.2-cp35-cp35m-win32.whl", hash = "sha256:3a3e360a765cc95410898dc222f8585ea1b1bba0538a1af4d8630a5bc3ad6ee7"}, + {file = "datrie-0.8.2-cp35-cp35m-win_amd64.whl", hash = "sha256:fa9f39ac88dc6286672b9dd286fe459646da48133c877a927af24803eaea441e"}, + {file = "datrie-0.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b6fd6c7c149b410a87d46072c1c98f6e87ec557802e1d0e09db7b858746e8550"}, + {file = "datrie-0.8.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:327d9c17efaebc66d1956dca047b76fdd0e5b989d63cb55b9038ec09d8769089"}, + {file = "datrie-0.8.2-cp36-cp36m-win32.whl", hash = "sha256:ee7cd8470a982356e104e62148f2dbe2d3e17545cafaa3ada29f2548984f1e89"}, + {file = "datrie-0.8.2-cp36-cp36m-win_amd64.whl", hash = "sha256:31e316ba305cdd7b8a42f8e4af5a0a15a628aee270d2f392c41329a709eeda6d"}, + {file = "datrie-0.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe04704eb41b8440ca61416d3670ca6ddeea847d19731cf121889bac2962d07"}, + {file = "datrie-0.8.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d704ee4fdc03f02d7dacc4d92052dbd490dba551509fccfd8ee52c9039d4ad"}, + {file = "datrie-0.8.2-cp37-cp37m-win32.whl", hash = "sha256:25e9e07ecfceaef78d23bde8d7278e4d6f63e1e3dc5ac00ccb4bec3062f0a8e0"}, + {file = "datrie-0.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:bf9f34f7c63797219b32713b561c4f94e777ff6c22beecfcd6bdf6b6c25b8518"}, + {file = "datrie-0.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e0582435a4adef1a2fce53aeedb656bf769b0f113b524f98be51d3e3d40720cb"}, + {file = "datrie-0.8.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b2d80fa687173cb8f8bae224ef00d1ad6bda8f8597bbb1a63f85182c7d91aeb3"}, + {file = "datrie-0.8.2-cp38-cp38-win32.whl", hash = "sha256:67603594f5db5c0029b1cf86a08e89cde015fe64cf0c4ae4e539c61114396729"}, + {file = "datrie-0.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:f61cf2726f04c08828bfb4e7af698b0b16bdf2777c3993d042f2898b8e118f21"}, + {file = "datrie-0.8.2-pp273-pypy_73-win32.whl", hash = "sha256:b07bd5fdfc3399a6dab86d6e35c72b1dbd598e80c97509c7c7518ab8774d3fda"}, + {file = "datrie-0.8.2-pp373-pypy36_pp73-win32.whl", hash = "sha256:89ff3d41df4f899387aa07b4b066f5da36e3a10b67b8aeae631c950502ff4503"}, + {file = "datrie-0.8.2.tar.gz", hash = "sha256:525b08f638d5cf6115df6ccd818e5a01298cd230b2dac91c8ff2e6499d18765d"}, +] +decorator = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] +dictdiffer = [ + {file = "dictdiffer-0.9.0-py2.py3-none-any.whl", hash = "sha256:442bfc693cfcadaf46674575d2eba1c53b42f5e404218ca2c2ff549f2df56595"}, + {file = "dictdiffer-0.9.0.tar.gz", hash = "sha256:17bacf5fbfe613ccf1b6d512bd766e6b21fb798822a133aa86098b8ac9997578"}, +] +docutils = [ + {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, + {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, +] +dpath = [ + {file = "dpath-2.0.6-py3-none-any.whl", hash = "sha256:8c439bb1c3b3222427e9b8812701cd99a0ef3415ddbb7c03a2379f6989a03965"}, + {file = "dpath-2.0.6.tar.gz", hash = "sha256:5a1ddae52233fbc8ef81b15fb85073a81126bb43698d3f3a1b6aaf561a46cdc0"}, +] +fastjsonschema = [ + {file = "fastjsonschema-2.15.3-py3-none-any.whl", hash = "sha256:ddb0b1d8243e6e3abb822bd14e447a89f4ab7439342912d590444831fa00b6a0"}, + {file = "fastjsonschema-2.15.3.tar.gz", hash = "sha256:0a572f0836962d844c1fc435e200b2e4f4677e4e6611a2e3bdd01ba697c275ec"}, +] flake8 = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, ] +gitdb = [ + {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, + {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, +] +gitpython = [ + {file = "GitPython-3.1.27-py3-none-any.whl", hash = "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d"}, + {file = "GitPython-3.1.27.tar.gz", hash = "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704"}, +] humanfriendly = [ {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, ] +idna = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +importlib-resources = [ + {file = "importlib_resources-5.7.1-py3-none-any.whl", hash = "sha256:e447dc01619b1e951286f3929be820029d48c75eb25d265c28b92a16548212b8"}, + {file = "importlib_resources-5.7.1.tar.gz", hash = "sha256:b6062987dfc51f0fcb809187cffbd60f35df7acb4589091f154214af6d0d49d3"}, +] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, @@ -476,10 +1064,64 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] +jinja2 = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] +jsonschema = [ + {file = "jsonschema-4.5.1-py3-none-any.whl", hash = "sha256:71b5e39324422543546572954ce71c67728922c104902cb7ce252e522235b33f"}, + {file = "jsonschema-4.5.1.tar.gz", hash = "sha256:7c6d882619340c3347a1bf7315e147e6d3dae439033ae6383d6acb908c101dfc"}, +] +jupyter-core = [ + {file = "jupyter_core-4.10.0-py3-none-any.whl", hash = "sha256:e7f5212177af7ab34179690140f188aa9bf3d322d8155ed972cbded19f55b6f3"}, + {file = "jupyter_core-4.10.0.tar.gz", hash = "sha256:a6de44b16b7b31d7271130c71a6792c4040f077011961138afed5e5e73181aec"}, +] loguru = [ {file = "loguru-0.5.3-py3-none-any.whl", hash = "sha256:f8087ac396b5ee5f67c963b495d615ebbceac2796379599820e324419d53667c"}, {file = "loguru-0.5.3.tar.gz", hash = "sha256:b28e72ac7a98be3d28ad28570299a393dfcd32e5e3f6a353dec94675767b6319"}, ] +markupsafe = [ + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, + {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, +] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, @@ -488,6 +1130,10 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] +nbformat = [ + {file = "nbformat-5.4.0-py3-none-any.whl", hash = "sha256:0d6072aaec95dddc39735c144ee8bbc6589c383fb462e4058abc855348152dad"}, + {file = "nbformat-5.4.0.tar.gz", hash = "sha256:44ba5ca6acb80c5d5a500f1e5b83ede8cbe364d5a495c4c8cf60aaf1ba656501"}, +] numpy = [ {file = "numpy-1.22.3-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:92bfa69cfbdf7dfc3040978ad09a48091143cffb778ec3b03fa170c494118d75"}, {file = "numpy-1.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8251ed96f38b47b4295b1ae51631de7ffa8260b5b087808ef09a39a9d66c97ab"}, @@ -514,10 +1160,37 @@ packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] +pandas = [ + {file = "pandas-1.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be67c782c4f1b1f24c2f16a157e12c2693fd510f8df18e3287c77f33d124ed07"}, + {file = "pandas-1.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5a206afa84ed20e07603f50d22b5f0db3fb556486d8c2462d8bc364831a4b417"}, + {file = "pandas-1.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0010771bd9223f7afe5f051eb47c4a49534345dfa144f2f5470b27189a4dd3b5"}, + {file = "pandas-1.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3228198333dd13c90b6434ddf61aa6d57deaca98cf7b654f4ad68a2db84f8cfe"}, + {file = "pandas-1.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b79af3a69e5175c6fa7b4e046b21a646c8b74e92c6581a9d825687d92071b51"}, + {file = "pandas-1.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:5586cc95692564b441f4747c47c8a9746792e87b40a4680a2feb7794defb1ce3"}, + {file = "pandas-1.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:061609334a8182ab500a90fe66d46f6f387de62d3a9cb9aa7e62e3146c712167"}, + {file = "pandas-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b8134651258bce418cb79c71adeff0a44090c98d955f6953168ba16cc285d9f7"}, + {file = "pandas-1.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df82739e00bb6daf4bba4479a40f38c718b598a84654cbd8bb498fd6b0aa8c16"}, + {file = "pandas-1.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:385c52e85aaa8ea6a4c600a9b2821181a51f8be0aee3af6f2dcb41dafc4fc1d0"}, + {file = "pandas-1.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:295872bf1a09758aba199992c3ecde455f01caf32266d50abc1a073e828a7b9d"}, + {file = "pandas-1.4.2-cp38-cp38-win32.whl", hash = "sha256:95c1e422ced0199cf4a34385ff124b69412c4bc912011ce895582bee620dfcaa"}, + {file = "pandas-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:5c54ea4ef3823108cd4ec7fb27ccba4c3a775e0f83e39c5e17f5094cb17748bc"}, + {file = "pandas-1.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c072c7f06b9242c855ed8021ff970c0e8f8b10b35e2640c657d2a541c5950f59"}, + {file = "pandas-1.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f549097993744ff8c41b5e8f2f0d3cbfaabe89b4ae32c8c08ead6cc535b80139"}, + {file = "pandas-1.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ff08a14ef21d94cdf18eef7c569d66f2e24e0bc89350bcd7d243dd804e3b5eb2"}, + {file = "pandas-1.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c5bf555b6b0075294b73965adaafb39cf71c312e38c5935c93d78f41c19828a"}, + {file = "pandas-1.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51649ef604a945f781105a6d2ecf88db7da0f4868ac5d45c51cb66081c4d9c73"}, + {file = "pandas-1.4.2-cp39-cp39-win32.whl", hash = "sha256:d0d4f13e4be7ce89d7057a786023c461dd9370040bdb5efa0a7fe76b556867a0"}, + {file = "pandas-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:09d8be7dd9e1c4c98224c4dfe8abd60d145d934e9fc1f5f411266308ae683e6a"}, + {file = "pandas-1.4.2.tar.gz", hash = "sha256:92bc1fc585f1463ca827b45535957815b7deb218c549b7c18402c322c7549a12"}, +] pathspec = [ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] +plac = [ + {file = "plac-1.3.5-py2.py3-none-any.whl", hash = "sha256:a8933d21a40fe2cec177a2f96217425a4e889d275aa3e25ecf9a9640ab16d416"}, + {file = "plac-1.3.5.tar.gz", hash = "sha256:38bdd864d0450fb748193aa817b9c458a8f5319fbf97b2261151cfc0a5812090"}, +] platformdirs = [ {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, @@ -526,6 +1199,44 @@ pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] +psutil = [ + {file = "psutil-5.9.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:55ce319452e3d139e25d6c3f85a1acf12d1607ddedea5e35fb47a552c051161b"}, + {file = "psutil-5.9.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:7336292a13a80eb93c21f36bde4328aa748a04b68c13d01dfddd67fc13fd0618"}, + {file = "psutil-5.9.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:cb8d10461c1ceee0c25a64f2dd54872b70b89c26419e147a05a10b753ad36ec2"}, + {file = "psutil-5.9.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:7641300de73e4909e5d148e90cc3142fb890079e1525a840cf0dfd39195239fd"}, + {file = "psutil-5.9.0-cp27-none-win32.whl", hash = "sha256:ea42d747c5f71b5ccaa6897b216a7dadb9f52c72a0fe2b872ef7d3e1eacf3ba3"}, + {file = "psutil-5.9.0-cp27-none-win_amd64.whl", hash = "sha256:ef216cc9feb60634bda2f341a9559ac594e2eeaadd0ba187a4c2eb5b5d40b91c"}, + {file = "psutil-5.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90a58b9fcae2dbfe4ba852b57bd4a1dded6b990a33d6428c7614b7d48eccb492"}, + {file = "psutil-5.9.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff0d41f8b3e9ebb6b6110057e40019a432e96aae2008951121ba4e56040b84f3"}, + {file = "psutil-5.9.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:742c34fff804f34f62659279ed5c5b723bb0195e9d7bd9907591de9f8f6558e2"}, + {file = "psutil-5.9.0-cp310-cp310-win32.whl", hash = "sha256:8293942e4ce0c5689821f65ce6522ce4786d02af57f13c0195b40e1edb1db61d"}, + {file = "psutil-5.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:9b51917c1af3fa35a3f2dabd7ba96a2a4f19df3dec911da73875e1edaf22a40b"}, + {file = "psutil-5.9.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e9805fed4f2a81de98ae5fe38b75a74c6e6ad2df8a5c479594c7629a1fe35f56"}, + {file = "psutil-5.9.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c51f1af02334e4b516ec221ee26b8fdf105032418ca5a5ab9737e8c87dafe203"}, + {file = "psutil-5.9.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32acf55cb9a8cbfb29167cd005951df81b567099295291bcfd1027365b36591d"}, + {file = "psutil-5.9.0-cp36-cp36m-win32.whl", hash = "sha256:e5c783d0b1ad6ca8a5d3e7b680468c9c926b804be83a3a8e95141b05c39c9f64"}, + {file = "psutil-5.9.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d62a2796e08dd024b8179bd441cb714e0f81226c352c802fca0fd3f89eeacd94"}, + {file = "psutil-5.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3d00a664e31921009a84367266b35ba0aac04a2a6cad09c550a89041034d19a0"}, + {file = "psutil-5.9.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7779be4025c540d1d65a2de3f30caeacc49ae7a2152108adeaf42c7534a115ce"}, + {file = "psutil-5.9.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:072664401ae6e7c1bfb878c65d7282d4b4391f1bc9a56d5e03b5a490403271b5"}, + {file = "psutil-5.9.0-cp37-cp37m-win32.whl", hash = "sha256:df2c8bd48fb83a8408c8390b143c6a6fa10cb1a674ca664954de193fdcab36a9"}, + {file = "psutil-5.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1d7b433519b9a38192dfda962dd8f44446668c009833e1429a52424624f408b4"}, + {file = "psutil-5.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3400cae15bdb449d518545cbd5b649117de54e3596ded84aacabfbb3297ead2"}, + {file = "psutil-5.9.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2237f35c4bbae932ee98902a08050a27821f8f6dfa880a47195e5993af4702d"}, + {file = "psutil-5.9.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1070a9b287846a21a5d572d6dddd369517510b68710fca56b0e9e02fd24bed9a"}, + {file = "psutil-5.9.0-cp38-cp38-win32.whl", hash = "sha256:76cebf84aac1d6da5b63df11fe0d377b46b7b500d892284068bacccf12f20666"}, + {file = "psutil-5.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:3151a58f0fbd8942ba94f7c31c7e6b310d2989f4da74fcbf28b934374e9bf841"}, + {file = "psutil-5.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:539e429da49c5d27d5a58e3563886057f8fc3868a5547b4f1876d9c0f007bccf"}, + {file = "psutil-5.9.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58c7d923dc209225600aec73aa2c4ae8ea33b1ab31bc11ef8a5933b027476f07"}, + {file = "psutil-5.9.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3611e87eea393f779a35b192b46a164b1d01167c9d323dda9b1e527ea69d697d"}, + {file = "psutil-5.9.0-cp39-cp39-win32.whl", hash = "sha256:4e2fb92e3aeae3ec3b7b66c528981fd327fb93fd906a77215200404444ec1845"}, + {file = "psutil-5.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:7d190ee2eaef7831163f254dc58f6d2e2a22e27382b936aab51c835fc080c3d3"}, + {file = "psutil-5.9.0.tar.gz", hash = "sha256:869842dbd66bb80c3217158e629d6fceaecc3a3166d3d1faee515b05dd26ca25"}, +] +pulp = [ + {file = "PuLP-2.6.0-py3-none-any.whl", hash = "sha256:37ea19fde27c2a767989a40e945d7a44b8c9cf007bd433e2c0a73acbd5e92f0c"}, + {file = "PuLP-2.6.0.tar.gz", hash = "sha256:4b4f7e1e954453e1b233720be23aea2f10ff068a835ac10c090a93d8e2eb2e8d"}, +] py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, @@ -539,13 +1250,59 @@ pyflakes = [ {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, ] pyparsing = [ - {file = "pyparsing-3.0.8-py3-none-any.whl", hash = "sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"}, - {file = "pyparsing-3.0.8.tar.gz", hash = "sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954"}, + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, ] pyreadline3 = [ {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"}, {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, ] +pyrsistent = [ + {file = "pyrsistent-0.18.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1"}, + {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26"}, + {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e"}, + {file = "pyrsistent-0.18.1-cp310-cp310-win32.whl", hash = "sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6"}, + {file = "pyrsistent-0.18.1-cp310-cp310-win_amd64.whl", hash = "sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-win32.whl", hash = "sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-win_amd64.whl", hash = "sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286"}, + {file = "pyrsistent-0.18.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6"}, + {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec"}, + {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c"}, + {file = "pyrsistent-0.18.1-cp38-cp38-win32.whl", hash = "sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca"}, + {file = "pyrsistent-0.18.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a"}, + {file = "pyrsistent-0.18.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5"}, + {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045"}, + {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c"}, + {file = "pyrsistent-0.18.1-cp39-cp39-win32.whl", hash = "sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc"}, + {file = "pyrsistent-0.18.1-cp39-cp39-win_amd64.whl", hash = "sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07"}, + {file = "pyrsistent-0.18.1.tar.gz", hash = "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96"}, +] +pysam = [ + {file = "pysam-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:44de1a3af7c7eb5f404d6337f0c9c4ee88c34c2d2fee1a7896ccd8e7d2aa475a"}, + {file = "pysam-0.19.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0ceb07c6253598ec70fef6ac0c0f7ab0d299562c1a91e737adb07239afba22d6"}, + {file = "pysam-0.19.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2057f3b8cc20562fd010e7971e83ab78978f17975563a711c94bca583ce8a2d3"}, + {file = "pysam-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a1a9ee6cd6dfa50973dcb51cd2245ea7d4d64d4e962d60e5e1a088f7b790e3e"}, + {file = "pysam-0.19.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b831170ff810bfd1242dbce4ddf8e693e95e39a4332d5903d416233d3d1be50a"}, + {file = "pysam-0.19.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fa4a5d334986d0696522246820f295cbf6c18dc1b78798f800a2d57d56207789"}, + {file = "pysam-0.19.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ab58d7d9b140e2e8a4918fc00661aa901ba461d9bccd4b499102b0828f2d897e"}, + {file = "pysam-0.19.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1d964c29fedf55d2a5d095227d19d915c2e0e5e42b1e0bdf7fab30cd1d2a850"}, + {file = "pysam-0.19.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8c78f9b84f7fe69530eaccf5b7f08636b3419f0017b5050aa7013f1c59d3d654"}, + {file = "pysam-0.19.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ada92b376717ac4c9c9924a096af9186035115d29a113eaa997d1c020ce421b9"}, + {file = "pysam-0.19.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:80b8f5b929c7f660b6e1497790a13c61f386b310a31ca54ad6ba110674d11c55"}, + {file = "pysam-0.19.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30017bed8d002d41f83fa7e10569525c811a8e3860d73a880ee653ef29fd4fbc"}, + {file = "pysam-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5e2e465522ba2c34cb96c013a28f9c9db303f8ab1350b4c11cca73677f1e9594"}, + {file = "pysam-0.19.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2103b4b6d9b0cc0b4aaccf64e87a92bfdabb7dc92810cf84be35ffe78fafa002"}, + {file = "pysam-0.19.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eaf342b9c71ed83a63237df2000e3bc1f0236165d48fd7240c4c78b66f28d63b"}, + {file = "pysam-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc0021b154206edfbaa13515cb67523c76c576b7a670e72a793f2da4f03139f4"}, + {file = "pysam-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3101e0fcd2f6accbfa72a554a71baf83f1c096bb0f9045059b3ead35901ce128"}, + {file = "pysam-0.19.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5118dcabac574638df43739941f0ee20cc4e9197aee4a8f10f195542a13f18e3"}, + {file = "pysam-0.19.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4fe1f1fae0e559d3412625dc7d4d08b477e80211b3fe5b267ba341a84f78b8be"}, + {file = "pysam-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2911e3760dd2b709c686f075146787b8bda35629093352c28a7e52ac00ddaffc"}, + {file = "pysam-0.19.0.tar.gz", hash = "sha256:dcc052566f9509fd93b2a2664f094a13f016fd60cdd189e05fb4eafa0c89505b"}, +] pytest = [ {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, @@ -554,6 +1311,30 @@ pytest-cov = [ {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, ] +python-dateutil = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] +pytz = [ + {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, + {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, +] +pywin32 = [ + {file = "pywin32-304-cp310-cp310-win32.whl", hash = "sha256:3c7bacf5e24298c86314f03fa20e16558a4e4138fc34615d7de4070c23e65af3"}, + {file = "pywin32-304-cp310-cp310-win_amd64.whl", hash = "sha256:4f32145913a2447736dad62495199a8e280a77a0ca662daa2332acf849f0be48"}, + {file = "pywin32-304-cp310-cp310-win_arm64.whl", hash = "sha256:d3ee45adff48e0551d1aa60d2ec066fec006083b791f5c3527c40cd8aefac71f"}, + {file = "pywin32-304-cp311-cp311-win32.whl", hash = "sha256:30c53d6ce44c12a316a06c153ea74152d3b1342610f1b99d40ba2795e5af0269"}, + {file = "pywin32-304-cp311-cp311-win_amd64.whl", hash = "sha256:7ffa0c0fa4ae4077e8b8aa73800540ef8c24530057768c3ac57c609f99a14fd4"}, + {file = "pywin32-304-cp311-cp311-win_arm64.whl", hash = "sha256:cbbe34dad39bdbaa2889a424d28752f1b4971939b14b1bb48cbf0182a3bcfc43"}, + {file = "pywin32-304-cp36-cp36m-win32.whl", hash = "sha256:be253e7b14bc601718f014d2832e4c18a5b023cbe72db826da63df76b77507a1"}, + {file = "pywin32-304-cp36-cp36m-win_amd64.whl", hash = "sha256:de9827c23321dcf43d2f288f09f3b6d772fee11e809015bdae9e69fe13213988"}, + {file = "pywin32-304-cp37-cp37m-win32.whl", hash = "sha256:f64c0377cf01b61bd5e76c25e1480ca8ab3b73f0c4add50538d332afdf8f69c5"}, + {file = "pywin32-304-cp37-cp37m-win_amd64.whl", hash = "sha256:bb2ea2aa81e96eee6a6b79d87e1d1648d3f8b87f9a64499e0b92b30d141e76df"}, + {file = "pywin32-304-cp38-cp38-win32.whl", hash = "sha256:94037b5259701988954931333aafd39cf897e990852115656b014ce72e052e96"}, + {file = "pywin32-304-cp38-cp38-win_amd64.whl", hash = "sha256:ead865a2e179b30fb717831f73cf4373401fc62fbc3455a0889a7ddac848f83e"}, + {file = "pywin32-304-cp39-cp39-win32.whl", hash = "sha256:25746d841201fd9f96b648a248f731c1dec851c9a08b8e33da8b56148e4c65cc"}, + {file = "pywin32-304-cp39-cp39-win_amd64.whl", hash = "sha256:d24a3382f013b21aa24a5cfbfad5a2cd9926610c0affde3e8ab5b3d7dbcf4ac9"}, +] pyyaml = [ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, @@ -589,6 +1370,40 @@ pyyaml = [ {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, ] +ratelimiter = [ + {file = "ratelimiter-1.2.0.post0-py3-none-any.whl", hash = "sha256:a52be07bc0bb0b3674b4b304550f10c769bbb00fead3072e035904474259809f"}, + {file = "ratelimiter-1.2.0.post0.tar.gz", hash = "sha256:5c395dcabdbbde2e5178ef3f89b568a3066454a6ddc223b76473dac22f89b4f7"}, +] +requests = [ + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, +] +retry = [ + {file = "retry-0.9.2-py2.py3-none-any.whl", hash = "sha256:ccddf89761fa2c726ab29391837d4327f819ea14d244c232a1d24c67a2f98606"}, + {file = "retry-0.9.2.tar.gz", hash = "sha256:f8bfa8b99b69c4506d6f5bd3b0aabf77f98cdb17f3c9fc3f5ca820033336fba4"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +smart-open = [ + {file = "smart_open-6.0.0-py3-none-any.whl", hash = "sha256:94afbd5058a45d4fdc4f859ed158b46054cb5ca1c019d76f6f8a60495f662129"}, + {file = "smart_open-6.0.0.tar.gz", hash = "sha256:d60106b96f0bcaedf5f1cd46ff5524a1c3d02d5653425618bb0fa66e158d22b0"}, +] +smmap = [ + {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, + {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, +] +snakemake = [ + {file = "snakemake-7.6.2.tar.gz", hash = "sha256:80cb2d0ab0a2366010a1c0b288a90159cd640f942ae86e740021c15c9989f872"}, +] +stopit = [ + {file = "stopit-1.1.2.tar.gz", hash = "sha256:f7f39c583fd92027bd9d06127b259aee7a5b7945c1f1fa56263811e1e766996d"}, +] +tabulate = [ + {file = "tabulate-0.8.9-py3-none-any.whl", hash = "sha256:d7c013fe7abbc5e491394e10fa845f8f32fe54f8dc60c6622c6cf482d25d47e4"}, + {file = "tabulate-0.8.9.tar.gz", hash = "sha256:eb1d13f25760052e8931f2ef80aaf6045a6cceb47514db8beab24cded16f13a7"}, +] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, @@ -597,11 +1412,97 @@ tomli = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +toposort = [ + {file = "toposort-1.7-py2.py3-none-any.whl", hash = "sha256:8ed8e109e96ae30bf66da2d2155e4eb9989d9c5c743c837e37d9774a4eddd804"}, + {file = "toposort-1.7.tar.gz", hash = "sha256:ddc2182c42912a440511bd7ff5d3e6a1cabc3accbc674a3258c8c41cbfbb2125"}, +] +traitlets = [ + {file = "traitlets-5.2.0-py3-none-any.whl", hash = "sha256:9dd4025123fbe018a2092b2ad6984792f53ea3362c698f37473258b1fa97b0bc"}, + {file = "traitlets-5.2.0.tar.gz", hash = "sha256:60474f39bf1d39a11e0233090b99af3acee93bbc2281777e61dd8c87da8a0014"}, +] typing-extensions = [ {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, ] +urllib3 = [ + {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, + {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, +] win32-setctime = [ {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, ] +wrapt = [ + {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, + {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, + {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, + {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, + {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, + {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, + {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, + {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, + {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, + {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, + {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, + {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, + {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, + {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, + {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, + {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, + {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, + {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, + {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, + {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, + {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, + {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, + {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, + {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, + {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, + {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, + {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, + {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, + {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, + {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, + {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, + {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, + {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, + {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, + {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, +] +yte = [ + {file = "yte-1.4.0-py3-none-any.whl", hash = "sha256:1e7d03e72eec2d7c311dd363f66069d6ff53fd4fecd99714fb0753fc0f3ab36b"}, + {file = "yte-1.4.0.tar.gz", hash = "sha256:20802e64b851be75172456650cfbac6f18c4c81ba01ccaede44f9242bb6c4685"}, +] +zipp = [ + {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, + {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, +] diff --git a/pyproject.toml b/pyproject.toml index f0466d1..6943337 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,6 +18,8 @@ click = "^8.0.3" cyvcf2 = "^0.30" loguru = "^0.5.3" pyyaml = ">=6.0" +pandas = "^1.4.2" +pysam = "^0.19.0" [tool.poetry.dev-dependencies] black = ">=22.3.0" @@ -25,10 +27,12 @@ isort = "^5.10.1" flake8 = "^4.0.1" pytest = "^6.2.5" pytest-cov = "^3.0.0" +snakemake = "^7.6.2" +dictdiffer = "^0.9.0" [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.isort] -profile = "black" \ No newline at end of file +profile = "black" diff --git a/tbpore/constants.py b/tbpore/constants.py index 4b50370..62a5d31 100644 --- a/tbpore/constants.py +++ b/tbpore/constants.py @@ -4,6 +4,10 @@ repo_root = Path(__file__).parent.parent.resolve() H37RV_genome = repo_root / "data/H37RV_genome/h37rv.fa.gz" H37RV_mask = repo_root / "data/H37RV_genome/compass-mask.bed" +decontamination_db_index = ( + repo_root / "data/decontamination_db/tbpore.remove_contam.fa.gz.map-ont.mmi" +) +decontamination_db_metadata = repo_root / "data/decontamination_db/remove_contam.tsv.gz" cache_dir = repo_root / ".cache" config_file = repo_root / ".config.yaml" external_scripts_dir = repo_root / "external_scripts" diff --git a/tbpore/external_tools.py b/tbpore/external_tools.py index 7248dcb..be533fb 100644 --- a/tbpore/external_tools.py +++ b/tbpore/external_tools.py @@ -31,6 +31,7 @@ def _build_command(tool: str, input: str, output: str, params: str) -> List[str] def run(self) -> None: with open(self.out_log, "w") as stdout_fh, open(self.err_log, "w") as stderr_fh: + print(f"Command line: {self.command_as_str}", file=stderr_fh) logger.info(f"Started running {self.command_as_str} ...") self._run_core(self.command, stdout_fh=stdout_fh, stderr_fh=stderr_fh) logger.info(f"Done running {self.command_as_str}") diff --git a/tbpore/tbpore.py b/tbpore/tbpore.py index fdc10d8..1118e95 100644 --- a/tbpore/tbpore.py +++ b/tbpore/tbpore.py @@ -16,6 +16,8 @@ __version__, cache_dir, config_file, + decontamination_db_index, + decontamination_db_metadata, external_scripts_dir, ) from tbpore.cli import Mutex @@ -84,6 +86,18 @@ def setup_logging(verbose: bool, quiet: bool) -> None: logger.add(sys.stderr, level=log_lvl, format=log_fmt) +def ensure_decontamination_db_is_available( + config: Dict[Any, Any], ctx: click.Context +) -> None: + if not decontamination_db_index.exists(): + logger.error( + f"Decontamination DB index {decontamination_db_index} does not exist, " + f"please download it at {config['decom_DB']['url']} and put it at {decontamination_db_index} " + f"before running tbpore" + ) + ctx.exit(2) + + @click.command() @click.help_option("--help", "-h") @click.version_option(__version__, "--version", "-V") @@ -179,6 +193,8 @@ def main( config = load_config_file() + ensure_decontamination_db_is_available(config, ctx) + # create dirs for the run outdir.mkdir(exist_ok=True, parents=True) if tmp is None: @@ -200,32 +216,78 @@ def main( infile = tmp / f"{name}.fq.gz" concatenate_inputs_into_infile(inputs, infile, recursive, ctx) - report_all_mykrobe_calls_param = "-A" if report_all_mykrobe_calls else "" - mykrobe_output = f"{outdir}/{name}.mykrobe.json" - mykrobe = ExternalTool( - tool="mykrobe", - input=f"-i {infile}", - output=f"-o {mykrobe_output}", - params=f"predict {report_all_mykrobe_calls_param} --sample {name} -t {threads} --tmp {tmp} " - f"--skeleton_dir {cache_dir} {config['mykrobe']['predict']['params']}", + decontaminated_sam = str(tmp / f"{name}.decontaminated.sam") + map_decontamination_db = ExternalTool( + tool="minimap2", + input=f"{decontamination_db_index} {infile}", + output=f"-o {decontaminated_sam}", + params=f"{config['minimap2']['map_to_decom_DB']['params']} -t {threads}", + logdir=logdir, + ) + + sorted_decontaminated_bam = str(tmp / f"{name}.decontaminated.sorted.bam") + sort_decontaminated_sam = ExternalTool( + tool="samtools", + input=decontaminated_sam, + output=f"-o {sorted_decontaminated_bam}", + params=f"sort -@ {threads} {config['samtools']['sort_decom_DB']['params']}", + logdir=logdir, + ) + + index_sorted_decontaminated_bam = ExternalTool( + tool="samtools", + input=sorted_decontaminated_bam, + output="", + params=f"index -@ {threads} {config['samtools']['index_decom_DB']['params']}", + logdir=logdir, + ) + + filter_contamination_dir = tmp / f"{name}.decontaminated.filter" + filter_contamination_dir.mkdir(parents=True, exist_ok=True) + filter_contamination = ExternalTool( + tool=sys.executable, + input=f"-i {sorted_decontaminated_bam} -m {decontamination_db_metadata}", + output=f"-o {filter_contamination_dir}", + params=f"{external_scripts_dir/'filter_contamination.py'} {config['filter_contamination']['params']}", + logdir=logdir, + ) + + reads_to_keep = filter_contamination_dir / "keep.reads" + decontaminated_nanopore_reads = tmp / f"{name}.decontaminated.fastq.gz" + extract_decontaminated_nanopore_reads = ExternalTool( + tool="seqkit", + input=f"-f {reads_to_keep} {infile}", + output=f"-o {decontaminated_nanopore_reads}", + params=config["extract_decontaminated_nanopore_reads"]["params"], logdir=logdir, ) subsampled_reads = f"{tmp}/{name}.subsampled.fastq.gz" rasusa = ExternalTool( tool="rasusa", - input=f"-i {infile}", + input=f"-i {decontaminated_nanopore_reads}", output=f"-o {subsampled_reads}", params=config["rasusa"]["params"], logdir=logdir, ) + report_all_mykrobe_calls_param = "-A" if report_all_mykrobe_calls else "" + mykrobe_output = f"{outdir}/{name}.mykrobe.json" + mykrobe = ExternalTool( + tool="mykrobe", + input=f"-i {subsampled_reads}", + output=f"-o {mykrobe_output}", + params=f"predict {report_all_mykrobe_calls_param} --sample {name} -t {threads} --tmp {tmp} " + f"--skeleton_dir {cache_dir} {config['mykrobe']['predict']['params']}", + logdir=logdir, + ) + sam_file = f"{tmp}/{name}.subsampled.sam" minimap = ExternalTool( tool="minimap2", input=f"{H37RV_genome} {subsampled_reads}", output=f"-o {sam_file}", - params=f"-t {threads} {config['minimap2']['params']}", + params=f"-t {threads} {config['minimap2']['map']['params']}", logdir=logdir, ) @@ -256,7 +318,7 @@ def main( logdir=logdir, ) - filtered_snps_file = f"{outdir}/{name}.subsampled.snps.filtered.bcf" + filtered_snps_file = f"{outdir}/{name}.snps.filtered.bcf" filtering_options = " ".join( ( config["filter"]["params"], @@ -281,8 +343,13 @@ def main( ) tools_to_run = [ - mykrobe, + map_decontamination_db, + sort_decontaminated_sam, + index_sorted_decontaminated_bam, + filter_contamination, + extract_decontaminated_nanopore_reads, rasusa, + mykrobe, minimap, samtools_sort, bcftools_mpileup, diff --git a/tests/test_external_tools.py b/tests/test_external_tools.py index 2f77d89..15112da 100644 --- a/tests/test_external_tools.py +++ b/tests/test_external_tools.py @@ -78,11 +78,12 @@ def test___run(self): for file in logsdir.iterdir(): file.unlink() + python_script = str(repo_root / "tests/helpers/run_test.py") external_tool = ExternalTool( sys.executable, "input", "output", - str(repo_root / "tests/helpers/run_test.py"), + python_script, logsdir, ) @@ -96,4 +97,7 @@ def test___run(self): err_file = glob.glob(f"{logsdir}/*.err")[0] with open(err_file) as err_file_fh: lines = err_file_fh.readlines() - assert lines == ["err\n"] + assert lines == [ + "err\n", + f"Command line: {sys.executable} {python_script} output input\n", + ] diff --git a/tests/test_tbpore.py b/tests/test_tbpore.py index 4c3d23c..fad2355 100644 --- a/tests/test_tbpore.py +++ b/tests/test_tbpore.py @@ -13,11 +13,14 @@ H37RV_genome, H37RV_mask, cache_dir, + decontamination_db_index, + decontamination_db_metadata, external_scripts_dir, main, ) +@patch("tbpore.tbpore.ensure_decontamination_db_is_available") class TestExternalToolsExecution: @staticmethod def get_command_line_from_mock(mock, index): @@ -25,7 +28,7 @@ def get_command_line_from_mock(mock, index): @patch.object(ExternalTool, ExternalTool._run_core.__name__) def test_whole_execution___minimum_params___check_all_external_tools_are_called_correctly( - self, run_core_mock, tmp_path + self, run_core_mock, ensure_decontamination_db_is_available_mock, tmp_path ): runner = CliRunner() with runner.isolated_filesystem(temp_dir=tmp_path) as td: @@ -40,36 +43,74 @@ def test_whole_execution___minimum_params___check_all_external_tools_are_called_ assert result.exit_code == 0 # ensure all tools were called in the correct order and with the correct parameters - assert run_core_mock.call_count == 8 + assert run_core_mock.call_count == 13 - mykrobe_cl = self.get_command_line_from_mock(run_core_mock, 0) + map_decontamination_db_cl = self.get_command_line_from_mock( + run_core_mock, 0 + ) assert ( - mykrobe_cl - == f"mykrobe predict --sample in -t 1 --tmp {td}/{TMP_NAME} --skeleton_dir {cache_dir} -e 0.08 " - f"--ploidy haploid --format json --min_proportion_expected_depth 0.20 --species tb " - f"-m 2048MB -o {td}/in.mykrobe.json -i {td}/{TMP_NAME}/in.fq.gz" + map_decontamination_db_cl + == f"minimap2 -aL2 -x map-ont -t 1 -o {td}/{TMP_NAME}/in.decontaminated.sam {decontamination_db_index} {td}/{TMP_NAME}/in.fq.gz" + ) + + sort_decontaminated_sam_cl = self.get_command_line_from_mock( + run_core_mock, 1 + ) + assert ( + sort_decontaminated_sam_cl + == f"samtools sort -@ 1 -o {td}/{TMP_NAME}/in.decontaminated.sorted.bam {td}/{TMP_NAME}/in.decontaminated.sam" + ) + + index_sorted_decontaminated_bam_cl = self.get_command_line_from_mock( + run_core_mock, 2 + ) + assert ( + index_sorted_decontaminated_bam_cl + == f"samtools index -@ 1 {td}/{TMP_NAME}/in.decontaminated.sorted.bam" ) - rasusa_cl = self.get_command_line_from_mock(run_core_mock, 1) + filter_contamination_cl = self.get_command_line_from_mock(run_core_mock, 3) + assert ( + filter_contamination_cl + == f"{sys.executable} {external_scripts_dir}/filter_contamination.py --verbose --ignore-secondary -o {td}/{TMP_NAME}/in.decontaminated.filter -i {td}/{TMP_NAME}/in.decontaminated.sorted.bam -m {decontamination_db_metadata}" + ) + + extract_decontaminated_nanopore_reads_cl = self.get_command_line_from_mock( + run_core_mock, 4 + ) + assert ( + extract_decontaminated_nanopore_reads_cl + == f"seqkit grep -o {td}/{TMP_NAME}/in.decontaminated.fastq.gz -f {td}/{TMP_NAME}/in.decontaminated.filter/keep.reads {td}/{TMP_NAME}/in.fq.gz" + ) + + rasusa_cl = self.get_command_line_from_mock(run_core_mock, 5) assert ( rasusa_cl - == f"rasusa -c 150 -g 4411532 -s 88 -o {td}/{TMP_NAME}/in.subsampled.fastq.gz -i {td}/{TMP_NAME}/in.fq.gz" + == f"rasusa -c 150 -g 4411532 -s 88 -o {td}/{TMP_NAME}/in.subsampled.fastq.gz -i {td}/{TMP_NAME}/in.decontaminated.fastq.gz" ) - minimap2_cl = self.get_command_line_from_mock(run_core_mock, 2) + mykrobe_cl = self.get_command_line_from_mock(run_core_mock, 6) + assert ( + mykrobe_cl + == f"mykrobe predict --sample in -t 1 --tmp {td}/{TMP_NAME} --skeleton_dir {cache_dir} -e 0.08 " + f"--ploidy haploid --format json --min_proportion_expected_depth 0.20 --species tb " + f"-m 2048MB -o {td}/in.mykrobe.json -i {td}/{TMP_NAME}/in.subsampled.fastq.gz" + ) + + minimap2_cl = self.get_command_line_from_mock(run_core_mock, 7) assert ( minimap2_cl == f"minimap2 -t 1 -a -L --sam-hit-only --secondary=no -x map-ont -o {td}/{TMP_NAME}/in.subsampled.sam " f"{H37RV_genome} {td}/{TMP_NAME}/in.subsampled.fastq.gz" ) - samtools_sort_cl = self.get_command_line_from_mock(run_core_mock, 3) + samtools_sort_cl = self.get_command_line_from_mock(run_core_mock, 8) assert ( samtools_sort_cl == f"samtools sort -@ 1 -o {td}/{TMP_NAME}/in.subsampled.sorted.sam {td}/{TMP_NAME}/in.subsampled.sam" ) - bcftools_mpileup_cl = self.get_command_line_from_mock(run_core_mock, 4) + bcftools_mpileup_cl = self.get_command_line_from_mock(run_core_mock, 9) assert ( bcftools_mpileup_cl == f"bcftools mpileup -f {H37RV_genome} --threads 1 -x -I -Q 13 " @@ -77,32 +118,32 @@ def test_whole_execution___minimum_params___check_all_external_tools_are_called_ f"{td}/{TMP_NAME}/in.subsampled.sorted.sam" ) - bcftools_call_cl = self.get_command_line_from_mock(run_core_mock, 5) + bcftools_call_cl = self.get_command_line_from_mock(run_core_mock, 10) assert ( bcftools_call_cl == f"bcftools call --threads 1 --ploidy 1 -V indels -m -o {td}/{TMP_NAME}/in.subsampled.snps.vcf " f"{td}/{TMP_NAME}/in.subsampled.pileup.vcf" ) - filter_vcf_cl = self.get_command_line_from_mock(run_core_mock, 6) + filter_vcf_cl = self.get_command_line_from_mock(run_core_mock, 11) assert ( filter_vcf_cl == f"{sys.executable} {external_scripts_dir}/apply_filters.py -P --verbose --overwrite -d 0 -D 0 " f"-q 85 -s 1 -b 0 -m 0 -r 0 -V 1e-05 -G 0 -K 0.9 -M 0 -x 0.2 " - f"-o {td}/in.subsampled.snps.filtered.bcf -i {td}/{TMP_NAME}/in.subsampled.snps.vcf" + f"-o {td}/in.snps.filtered.bcf -i {td}/{TMP_NAME}/in.subsampled.snps.vcf" ) - generate_consensus_cl = self.get_command_line_from_mock(run_core_mock, 7) + generate_consensus_cl = self.get_command_line_from_mock(run_core_mock, 12) assert ( generate_consensus_cl == f"{sys.executable} {external_scripts_dir}/consensus.py --sample-id in --verbose --ignore all " - f"--het-default none -o {td}/in.consensus.fa -i {td}/in.subsampled.snps.filtered.bcf " + f"--het-default none -o {td}/in.consensus.fa -i {td}/in.snps.filtered.bcf " f"-f {H37RV_genome} -m {H37RV_mask}" ) @patch.object(ExternalTool, ExternalTool._run_core.__name__) def test_whole_execution___several_params_affecting_tools_command_lines___check_all_external_tools_are_called_correctly( - self, run_core_mock, tmp_path + self, run_core_mock, ensure_decontamination_db_is_available_mock, tmp_path ): runner = CliRunner() with runner.isolated_filesystem(temp_dir=tmp_path) as td: @@ -128,37 +169,75 @@ def test_whole_execution___several_params_affecting_tools_command_lines___check_ assert result.exit_code == 0 # ensure all tools were called in the correct order and with the correct parameters - assert run_core_mock.call_count == 8 + assert run_core_mock.call_count == 13 - mykrobe_cl = self.get_command_line_from_mock(run_core_mock, 0) + map_decontamination_db_cl = self.get_command_line_from_mock( + run_core_mock, 0 + ) assert ( - mykrobe_cl - == f"mykrobe predict -A --sample custom_name -t 8 --tmp {td}/custom_tmp --skeleton_dir {cache_dir} -e 0.08 " - f"--ploidy haploid --format json --min_proportion_expected_depth 0.20 --species tb " - f"-m 2048MB -o {td}/custom_name.mykrobe.json -i {td}/custom_tmp/custom_name.fq.gz" + map_decontamination_db_cl + == f"minimap2 -aL2 -x map-ont -t 8 -o {td}/custom_tmp/custom_name.decontaminated.sam {decontamination_db_index} {td}/custom_tmp/custom_name.fq.gz" + ) + + sort_decontaminated_sam_cl = self.get_command_line_from_mock( + run_core_mock, 1 + ) + assert ( + sort_decontaminated_sam_cl + == f"samtools sort -@ 8 -o {td}/custom_tmp/custom_name.decontaminated.sorted.bam {td}/custom_tmp/custom_name.decontaminated.sam" ) - rasusa_cl = self.get_command_line_from_mock(run_core_mock, 1) + index_sorted_decontaminated_bam_cl = self.get_command_line_from_mock( + run_core_mock, 2 + ) + assert ( + index_sorted_decontaminated_bam_cl + == f"samtools index -@ 8 {td}/custom_tmp/custom_name.decontaminated.sorted.bam" + ) + + filter_contamination_cl = self.get_command_line_from_mock(run_core_mock, 3) + assert ( + filter_contamination_cl + == f"{sys.executable} {external_scripts_dir}/filter_contamination.py --verbose --ignore-secondary -o {td}/custom_tmp/custom_name.decontaminated.filter -i {td}/custom_tmp/custom_name.decontaminated.sorted.bam -m {decontamination_db_metadata}" + ) + + extract_decontaminated_nanopore_reads_cl = self.get_command_line_from_mock( + run_core_mock, 4 + ) + assert ( + extract_decontaminated_nanopore_reads_cl + == f"seqkit grep -o {td}/custom_tmp/custom_name.decontaminated.fastq.gz -f {td}/custom_tmp/custom_name.decontaminated.filter/keep.reads {td}/custom_tmp/custom_name.fq.gz" + ) + + rasusa_cl = self.get_command_line_from_mock(run_core_mock, 5) assert ( rasusa_cl == f"rasusa -c 150 -g 4411532 -s 88 -o {td}/custom_tmp/custom_name.subsampled.fastq.gz " - f"-i {td}/custom_tmp/custom_name.fq.gz" + f"-i {td}/custom_tmp/custom_name.decontaminated.fastq.gz" ) - minimap2_cl = self.get_command_line_from_mock(run_core_mock, 2) + mykrobe_cl = self.get_command_line_from_mock(run_core_mock, 6) + assert ( + mykrobe_cl + == f"mykrobe predict -A --sample custom_name -t 8 --tmp {td}/custom_tmp --skeleton_dir {cache_dir} -e 0.08 " + f"--ploidy haploid --format json --min_proportion_expected_depth 0.20 --species tb " + f"-m 2048MB -o {td}/custom_name.mykrobe.json -i {td}/custom_tmp/custom_name.subsampled.fastq.gz" + ) + + minimap2_cl = self.get_command_line_from_mock(run_core_mock, 7) assert ( minimap2_cl == f"minimap2 -t 8 -a -L --sam-hit-only --secondary=no -x map-ont -o {td}/custom_tmp/custom_name.subsampled.sam " f"{H37RV_genome} {td}/custom_tmp/custom_name.subsampled.fastq.gz" ) - samtools_sort_cl = self.get_command_line_from_mock(run_core_mock, 3) + samtools_sort_cl = self.get_command_line_from_mock(run_core_mock, 8) assert ( samtools_sort_cl == f"samtools sort -@ 8 -o {td}/custom_tmp/custom_name.subsampled.sorted.sam {td}/custom_tmp/custom_name.subsampled.sam" ) - bcftools_mpileup_cl = self.get_command_line_from_mock(run_core_mock, 4) + bcftools_mpileup_cl = self.get_command_line_from_mock(run_core_mock, 9) assert ( bcftools_mpileup_cl == f"bcftools mpileup -f {H37RV_genome} --threads 8 -x -I -Q 13 " @@ -166,26 +245,26 @@ def test_whole_execution___several_params_affecting_tools_command_lines___check_ f"{td}/custom_tmp/custom_name.subsampled.sorted.sam" ) - bcftools_call_cl = self.get_command_line_from_mock(run_core_mock, 5) + bcftools_call_cl = self.get_command_line_from_mock(run_core_mock, 10) assert ( bcftools_call_cl == f"bcftools call --threads 8 --ploidy 1 -V indels -m -o {td}/custom_tmp/custom_name.subsampled.snps.vcf " f"{td}/custom_tmp/custom_name.subsampled.pileup.vcf" ) - filter_vcf_cl = self.get_command_line_from_mock(run_core_mock, 6) + filter_vcf_cl = self.get_command_line_from_mock(run_core_mock, 11) assert ( filter_vcf_cl == f"{sys.executable} {external_scripts_dir}/apply_filters.py -P --verbose --overwrite -d 0 -D 0 " f"-q 85 -s 1 -b 0 -m 0 -r 0 -V 1e-05 -G 0 -K 0.9 -M 0 -x 0.2 " - f"-o {td}/custom_name.subsampled.snps.filtered.bcf -i {td}/custom_tmp/custom_name.subsampled.snps.vcf" + f"-o {td}/custom_name.snps.filtered.bcf -i {td}/custom_tmp/custom_name.subsampled.snps.vcf" ) - generate_consensus_cl = self.get_command_line_from_mock(run_core_mock, 7) + generate_consensus_cl = self.get_command_line_from_mock(run_core_mock, 12) assert ( generate_consensus_cl == f"{sys.executable} {external_scripts_dir}/consensus.py --sample-id custom_name --verbose --ignore all " - f"--het-default none -o {td}/custom_name.consensus.fa -i {td}/custom_name.subsampled.snps.filtered.bcf " + f"--het-default none -o {td}/custom_name.consensus.fa -i {td}/custom_name.snps.filtered.bcf " f"-f {H37RV_genome} -m {H37RV_mask}" ) @@ -194,8 +273,8 @@ def test_whole_execution___several_params_affecting_tools_command_lines___check_ ExternalTool._run_core.__name__, side_effect=["", "", subprocess.CalledProcessError(1, "minimap2")], ) - def test_partial_execution___minimum_params___minimap2_fails___checks_fail_happens_and_previous_tools_called_correctly( - self, run_core_mock, tmp_path + def test_partial_execution___minimum_params___index_sorted_decontaminated_bam_fails___checks_fail_happens_and_previous_tools_called_correctly( + self, run_core_mock, ensure_decontamination_db_is_available_mock, tmp_path ): runner = CliRunner() with runner.isolated_filesystem(temp_dir=tmp_path) as td: @@ -213,33 +292,38 @@ def test_partial_execution___minimum_params___minimap2_fails___checks_fail_happe # check if tbpore indeed failed assert result.exit_code == 1 - minimap2_cl = self.get_command_line_from_mock(run_core_mock, 2) + index_sorted_decontaminated_bam_cl = self.get_command_line_from_mock( + run_core_mock, 2 + ) assert ( - b"Error calling " + minimap2_cl.encode("utf-8") + b" (return code 1)" + b"Error calling " + + index_sorted_decontaminated_bam_cl.encode("utf-8") + + b" (return code 1)" in result.stdout_bytes ) # check if all tools until minimap2 were called correctly assert run_core_mock.call_count == 3 - mykrobe_cl = self.get_command_line_from_mock(run_core_mock, 0) + map_decontamination_db_cl = self.get_command_line_from_mock( + run_core_mock, 0 + ) assert ( - mykrobe_cl - == f"mykrobe predict --sample in -t 1 --tmp {td}/{TMP_NAME} --skeleton_dir {cache_dir} -e 0.08 " - f"--ploidy haploid --format json --min_proportion_expected_depth 0.20 --species tb " - f"-m 2048MB -o {td}/in.mykrobe.json -i {td}/{TMP_NAME}/in.fq.gz" + map_decontamination_db_cl + == f"minimap2 -aL2 -x map-ont -t 1 -o {td}/{TMP_NAME}/in.decontaminated.sam {decontamination_db_index} {td}/{TMP_NAME}/in.fq.gz" ) - rasusa_cl = self.get_command_line_from_mock(run_core_mock, 1) + sort_decontaminated_sam_cl = self.get_command_line_from_mock( + run_core_mock, 1 + ) assert ( - rasusa_cl - == f"rasusa -c 150 -g 4411532 -s 88 -o {td}/{TMP_NAME}/in.subsampled.fastq.gz -i {td}/{TMP_NAME}/in.fq.gz" + sort_decontaminated_sam_cl + == f"samtools sort -@ 1 -o {td}/{TMP_NAME}/in.decontaminated.sorted.bam {td}/{TMP_NAME}/in.decontaminated.sam" ) assert ( - minimap2_cl - == f"minimap2 -t 1 -a -L --sam-hit-only --secondary=no -x map-ont -o {td}/{TMP_NAME}/in.subsampled.sam " - f"{H37RV_genome} {td}/{TMP_NAME}/in.subsampled.fastq.gz" + index_sorted_decontaminated_bam_cl + == f"samtools index -@ 1 {td}/{TMP_NAME}/in.decontaminated.sorted.bam" ) # check if tmp not removed @@ -248,8 +332,11 @@ def test_partial_execution___minimum_params___minimap2_fails___checks_fail_happe @patch.object(ExternalTool, ExternalTool._run_core.__name__) +@patch("tbpore.tbpore.ensure_decontamination_db_is_available") class TestCLICleanup: - def test_no_cleanup(self, run_core_mock, tmp_path): + def test_no_cleanup( + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path + ): sample = "sam" opts = ["--no-cleanup", "-S", sample] runner = CliRunner() @@ -266,7 +353,9 @@ def test_no_cleanup(self, run_core_mock, tmp_path): tbpore_tmp = td / TMP_NAME assert tbpore_tmp.exists() - def test_with_cleanup(self, run_core_mock, tmp_path): + def test_with_cleanup( + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path + ): sample = "sam" opts = ["--cleanup", "-S", sample] runner = CliRunner() @@ -285,15 +374,20 @@ def test_with_cleanup(self, run_core_mock, tmp_path): @patch.object(ExternalTool, ExternalTool._run_core.__name__) +@patch("tbpore.tbpore.ensure_decontamination_db_is_available") class TestInputConcatenation: - def test_no_input___fails(self, run_core_mock, tmp_path): + def test_no_input___fails( + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path + ): runner = CliRunner() with runner.isolated_filesystem(temp_dir=tmp_path): result = runner.invoke(main, []) assert result.exit_code == 2 assert b"No INPUT files given" in result.stdout_bytes - def test_single_file(self, run_core_mock, tmp_path): + def test_single_file( + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path + ): sample = "sam" opts = ["-D", "-S", sample] runner = CliRunner() @@ -314,7 +408,9 @@ def test_single_file(self, run_core_mock, tmp_path): actual = fp.read() assert actual == expected_fq - def test_single_gz_file(self, run_core_mock, tmp_path): + def test_single_gz_file( + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path + ): sample = "sam" opts = ["-D", "-S", sample] runner = CliRunner() @@ -335,7 +431,9 @@ def test_single_gz_file(self, run_core_mock, tmp_path): actual = fp.read() assert actual == expected_fq - def test_multiple_files(self, run_core_mock, tmp_path): + def test_multiple_files( + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path + ): sample = "sam" opts = ["-D", "-S", sample] runner = CliRunner() @@ -362,7 +460,9 @@ def test_multiple_files(self, run_core_mock, tmp_path): expected = expected_fq1 + expected_fq2 assert sorted(actual) == sorted(expected) - def test_input_is_empty_dir___error_out(self, run_core_mock, tmp_path): + def test_input_is_empty_dir___error_out( + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path + ): sample = "sam" opts = ["-D", "-S", sample] runner = CliRunner() @@ -377,7 +477,9 @@ def test_input_is_empty_dir___error_out(self, run_core_mock, tmp_path): in result.stdout_bytes ) - def test_input_is_dir(self, run_core_mock, tmp_path): + def test_input_is_dir( + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path + ): sample = "sam" opts = ["-D", "-S", sample] runner = CliRunner() @@ -404,7 +506,9 @@ def test_input_is_dir(self, run_core_mock, tmp_path): expected = expected_fq1 + expected_fq2 assert sorted(actual) == sorted(expected) - def test_input_is_dir_and_one_file_has_bad_suffix(self, run_core_mock, tmp_path): + def test_input_is_dir_and_one_file_has_bad_suffix( + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path + ): sample = "sam" opts = ["-D", "-S", sample] runner = CliRunner() @@ -432,7 +536,7 @@ def test_input_is_dir_and_one_file_has_bad_suffix(self, run_core_mock, tmp_path) assert sorted(actual) == sorted(expected) def test_input_is_dir_and_files_in_dir___ensure_duplication_does_not_happen( - self, run_core_mock, tmp_path + self, ensure_decontamination_db_is_available_mock, run_core_mock, tmp_path ): sample = "sam" opts = ["-D", "-S", sample]