diff --git a/.gitattributes b/.gitattributes index 7a2dabc..4457c76 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,7 @@ *.config linguist-language=nextflow *.nf.test linguist-language=nextflow +*.bwt binary +*.pac binary +*.sa binary modules/nf-core/** linguist-generated subworkflows/nf-core/** linguist-generated diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml index 0cecea5..d9e053f 100644 --- a/.github/workflows/nf-test.yml +++ b/.github/workflows/nf-test.yml @@ -119,7 +119,7 @@ jobs: confirm-pass: needs: [nf-test] if: always() - runs-on: # use self-hosted runners + runs-on: # use self-hosted runners - runs-on=${{ github.run_id }}-confirm-pass - runner=2cpu-linux-x64 steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d06777a..646c359 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,14 @@ +exclude: | + (?x)^( + \.nf-test/| + results/| + work/| + tmp/| + \.codex$| + \.codex/| + assets/testdata/.*\.(amb|ann|bwt|pac|sa)$ + ) + repos: - repo: https://github.com/pre-commit/mirrors-prettier rev: "v3.1.0" diff --git a/README.md b/README.md index 4c41aaa..602f26c 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ TrESFlow is a Nextflow DSL2 pipeline for the preprocessing of TrES-seq data from ## Install Install your conda/mamba/micromamba env as follows (conda-forge & bioconda channels): + ```bash micromamba env create -n tres micromamba activate tres @@ -16,12 +17,14 @@ micromamba install screen samtools bwa-mem2 star fastqc multiqc trim-galore deep ``` Download the repo and cd in it: + ```bash git clone git@github.com:CSOgroup/TrESFlow.git cd TrESFlow ``` Install codon in your env: + ```bash ./scripts/install_codon_0.16.3.sh --prefix /path/to/env/prefix ``` @@ -110,6 +113,9 @@ RNA publishes: - `rna_split_fastqs/` - `rna_align/` - `TrES_Stats/` +- `qc/samtools/` +- `multiqc/` +- `tres_report/` - `pipeline_info/` DNA publishes: @@ -117,9 +123,15 @@ DNA publishes: - `dna_split_fastqs/` - `dna_align/` - `TrES_Stats/` +- `qc/samtools/` +- `multiqc/` +- `tres_report/` - `pipeline_info/` -`TrES_Stats/` includes RNA and DNA sequencing-efficiency UpSet PDF plots. Sankey plots, HTML reports, count tables, combined RNA+DNA reports, and sequencing-efficiency warning TSVs are not produced. Optional unavailable BAM-derived categories are skipped with warnings in the process log. +The pipeline also writes two end-of-run HTML reports: + +- `tres_report/tres_report.html`: compact TrESFlow-specific RNA/DNA mapping and barcode summary +- `multiqc/multiqc_report.html`: nf-core MultiQC aggregation of supported logs and QC files ## Runtime Contract @@ -162,7 +174,7 @@ Default local CPU budget: Work-directory cleanup is intentionally aggressive: `--cleanup_work true` uses Nextflow's successful-run cleanup to remove task work directories after outputs have been published and downstream tasks have completed. This substantially reduces retained `work/` storage, but cleaned tasks are not expected to be usable with `--resume`. Set `--cleanup_work false` when you need the previous resume-friendly behavior for debugging or iterative development. -DNA alignment no longer removes low-count cell barcodes during `ALIGN_DNA`. The aligned BAM still keeps proper-pair mapped, non-blacklisted reads; duplicate removal is represented later by `*_NoDup.bam`, and duplicate status appears in DNA sequencing-efficiency plots as `Unique +`. +DNA alignment no longer removes low-count cell barcodes during `ALIGN_DNA`. The aligned BAM still keeps proper-pair mapped, non-blacklisted reads; duplicate removal is represented later by `*_NoDup.bam`. Every run writes: @@ -171,6 +183,21 @@ Every run writes: - `${outdir}/pipeline_info/execution_trace.tsv` - `${outdir}/pipeline_info/flowchart.html` - `${outdir}/pipeline_info/runtime_contract.tsv` +- `${outdir}/tres_report/tres_report.html` with per-library main statistics, detailed QC tables, and CSV/Excel export buttons +- `${outdir}/tres_report/tres_report_metrics.json` +- `${outdir}/multiqc/multiqc_report.html` + +Runs with real BAM outputs also write nf-core samtools sidecar QC under: + +- `${outdir}/qc/samtools/*.flagstat` +- `${outdir}/qc/samtools/*.stats` +- `${outdir}/qc/samtools/*.idxstats` +- `${outdir}/qc/samtools/*.quickcheck.tsv` + +Raw FASTQ QC from nf-core FastQC is written under: + +- `${outdir}/qc/fastqc/*_fastqc.html` +- `${outdir}/qc/fastqc/*_fastqc.zip` The active runtime scripts live under [`scripts/core_runtime/`](scripts/core_runtime/). `upstream/source_scripts/` is kept only as provenance for the vendored core code. diff --git a/assets/test_realdata/ligation_barcode_whitelist.txt b/assets/test_realdata/ligation_barcode_whitelist.txt new file mode 100644 index 0000000..113a233 --- /dev/null +++ b/assets/test_realdata/ligation_barcode_whitelist.txt @@ -0,0 +1,48 @@ +ATCACGTT +CGATGTTT +TTAGGCAT +TGACCACT +ACAGTGGT +GCCAATGT +CAGATCTG +ACTTGATG +GATCAGCG +TAGCTTGT +GGCTACAG +CTTGTACT +TGGTTGTT +TCTCGGTT +TAAGCGTT +TCCGTCTT +TGTACCTT +TTCTGTGT +TCTGCTGT +TTGGAGGT +TCGAGCGT +TGATACGT +TGCATAGT +TTGACTCT +TGCGATCT +TTCCTGCT +TAGTGACT +TACAGGAT +TCCTCAAT +TGTGGTTG +TACTAGTC +TTCCATTG +TCGAAGTG +TAACGCTG +TTGGTATG +TGAACTGG +TACTTCGG +TCTCACGG +TCAGGAGG +TAAGTTCG +TCCAGTCG +TGTATGCG +TCATTGAG +TGGCTCAG +TATGCCAG +TCAGATTC +TAGTCTTG +TTCAGCTC diff --git a/bin/render_tres_report.py b/bin/render_tres_report.py new file mode 100644 index 0000000..96c27b1 --- /dev/null +++ b/bin/render_tres_report.py @@ -0,0 +1,963 @@ +#!/usr/bin/env python3 +"""Render a compact TrESFlow HTML QC report from pipeline artifacts.""" + +from __future__ import annotations + +import argparse +import html +import json +import re +from collections import defaultdict +from datetime import datetime, timezone +from pathlib import Path +from statistics import mean + + +def parse_number(value: str): + value = value.strip().replace(",", "") + if value in {"", "-nan", "nan", "NaN", "N/A"}: + return None + try: + if re.match(r"^-?\d+$", value): + return int(value) + return float(value) + except ValueError: + return None + + +def parse_percent(value: str): + value = value.strip() + if not value: + return None + if value.endswith("%"): + value = value[:-1] + parsed = parse_number(value) + return float(parsed) if parsed is not None else None + + +def pct_from_fraction(value): + if value is None: + return None + return float(value) * 100.0 + + +def fmt_int(value): + if value is None: + return "n/a" + try: + return f"{int(value):,}" + except (TypeError, ValueError): + return "n/a" + + +def fmt_pct(value): + if value is None: + return "n/a" + return f"{float(value):.1f}%" + + +def pct(numerator, denominator): + if numerator is None or denominator in {None, 0}: + return None + return float(numerator) / float(denominator) * 100.0 + + +def fmt_count_pct(count, denominator): + percent = pct(count, denominator) + if percent is None: + return "n/a" + return f"{fmt_pct(percent)} ({fmt_int(count)})" + + +def css_width(value): + if value is None: + return "0" + return str(max(0.0, min(100.0, float(value)))) + + +def read_tsv_stats(path: Path): + stats = {} + for line in path.read_text(errors="replace").splitlines(): + if not line.strip() or line.startswith("#"): + continue + parts = line.rstrip("\n").split("\t") + key = parts[0] + count = parse_number(parts[1]) if len(parts) > 1 else None + percent = parse_percent(parts[2]) if len(parts) > 2 else None + stats[key] = {"count": count, "percent": percent, "raw": parts} + return stats + + +def read_counts(path: Path): + total = 0 + observed = 0 + top = [] + for line in path.read_text(errors="replace").splitlines(): + if not line.strip() or line.startswith("#"): + continue + parts = line.rstrip("\n").split("\t") + if not parts: + continue + count = parse_number(parts[0]) + if count is not None: + total += int(count) + observed += 1 + if len(top) < 5: + top.append({"count": int(count), "value": parts[1] if len(parts) > 1 else ""}) + return {"total": total, "observed": observed, "top": top} + + +def read_csv_key_values(path: Path): + values = {} + for line in path.read_text(errors="replace").splitlines(): + if not line.strip() or "," not in line: + continue + key, value = line.split(",", 1) + values[key.strip()] = parse_number(value) + return values + + +def read_flagstat(path: Path): + metrics = {"file": path.name} + for line in path.read_text(errors="replace").splitlines(): + total = re.match(r"^(\d+) \+ \d+ in total", line) + primary = re.match(r"^(\d+) \+ \d+ primary$", line) + mapped = re.match(r"^(\d+) \+ \d+ mapped \(([^%]+)%", line) + primary_mapped = re.match(r"^(\d+) \+ \d+ primary mapped \(([^%]+)%", line) + paired = re.match(r"^(\d+) \+ \d+ paired in sequencing", line) + read1 = re.match(r"^(\d+) \+ \d+ read1", line) + read2 = re.match(r"^(\d+) \+ \d+ read2", line) + properly = re.match(r"^(\d+) \+ \d+ properly paired \(([^%]+)%", line) + duplicates = re.match(r"^(\d+) \+ \d+ duplicates", line) + if total: + metrics["total"] = int(total.group(1)) + elif primary: + metrics["primary"] = int(primary.group(1)) + elif mapped: + metrics["mapped"] = int(mapped.group(1)) + metrics["mapped_percent"] = float(mapped.group(2)) + elif primary_mapped: + metrics["primary_mapped"] = int(primary_mapped.group(1)) + metrics["primary_mapped_percent"] = float(primary_mapped.group(2)) + elif paired: + metrics["paired_in_sequencing"] = int(paired.group(1)) + elif read1: + metrics["read1"] = int(read1.group(1)) + elif read2: + metrics["read2"] = int(read2.group(1)) + elif properly: + metrics["properly_paired"] = int(properly.group(1)) + metrics["properly_paired_percent"] = float(properly.group(2)) + elif duplicates: + metrics["duplicates"] = int(duplicates.group(1)) + return metrics + + +def read_duplicate_metrics(path: Path): + header = None + for line in path.read_text(errors="replace").splitlines(): + if not line.strip() or line.startswith("#"): + continue + parts = line.rstrip("\n").split("\t") + if header is None: + if "PERCENT_DUPLICATION" not in parts: + continue + header = parts + continue + values = dict(zip(header, parts)) + percent_dup = parse_number(values.get("PERCENT_DUPLICATION", "")) + read_pairs = parse_number(values.get("READ_PAIRS_EXAMINED", "")) + read_pair_duplicates = parse_number(values.get("READ_PAIR_DUPLICATES", "")) + unpaired_reads = parse_number(values.get("UNPAIRED_READS_EXAMINED", "")) + unpaired_duplicates = parse_number(values.get("UNPAIRED_READ_DUPLICATES", "")) + return { + "file": path.name, + "library": values.get("LIBRARY"), + "percent_duplication": float(percent_dup) * 100.0 if percent_dup is not None else None, + "unique_percent": (1.0 - float(percent_dup)) * 100.0 if percent_dup is not None else None, + "read_pairs_examined": int(read_pairs) if read_pairs is not None else None, + "read_pair_duplicates": int(read_pair_duplicates) if read_pair_duplicates is not None else None, + "unpaired_reads_examined": int(unpaired_reads) if unpaired_reads is not None else None, + "unpaired_read_duplicates": int(unpaired_duplicates) if unpaired_duplicates is not None else None, + } + return {"file": path.name} + + +def strip_suffix(name: str, suffix: str) -> str: + return name[: -len(suffix)] if name.endswith(suffix) else name + + +def collect_inputs(input_dir: Path): + files = [p for p in input_dir.rglob("*") if p.is_file()] + samples = defaultdict(lambda: {"rna": {}, "dna": {}}) + rna_summaries = [] + star_logs = [] + flagstats = [] + duplicate_metrics = [] + samtools_stats = [] + + for path in files: + name = path.name + + if name.endswith(".rna_sample_barcode.stats.tsv"): + sample = strip_suffix(name, ".rna_sample_barcode.stats.tsv") + samples[sample]["sample_id"] = sample + samples[sample]["rna"]["sample_barcode"] = read_tsv_stats(path) + elif name.endswith(".sample_barcode.stats.tsv") and not name.endswith(".dna_sample_barcode.stats.tsv"): + sample = strip_suffix(name, ".sample_barcode.stats.tsv") + samples[sample]["sample_id"] = sample + samples[sample]["rna"]["sample_barcode"] = read_tsv_stats(path) + elif name.endswith(".dna_sample_barcode.stats.tsv"): + sample = strip_suffix(name, ".dna_sample_barcode.stats.tsv") + samples[sample]["sample_id"] = sample + samples[sample]["dna"]["sample_barcode"] = read_tsv_stats(path) + elif name.endswith(".dna_modality.stats.tsv"): + sample = strip_suffix(name, ".dna_modality.stats.tsv") + samples[sample]["sample_id"] = sample + samples[sample]["dna"]["modality_barcode"] = read_tsv_stats(path) + elif name.endswith(".rna_umi.counts.tsv"): + sample = strip_suffix(name, ".rna_umi.counts.tsv") + samples[sample]["sample_id"] = sample + samples[sample]["rna"]["umi_counts"] = read_counts(path) + elif name.endswith(".umi.counts.tsv"): + sample = strip_suffix(name, ".umi.counts.tsv") + samples[sample]["sample_id"] = sample + samples[sample]["rna"]["umi_counts"] = read_counts(path) + elif name.endswith(".rna_cell.stats_L1.tsv") or name.endswith(".rna_cell.stats_L2.tsv") or name.endswith(".rna_cell.stats_L3.tsv"): + sample = re.sub(r"\.rna_cell\.stats_L[123]\.tsv$", "", name) + samples[sample]["sample_id"] = sample + samples[sample]["rna"].setdefault("cell_barcode", []).append(read_tsv_stats(path)) + elif name.endswith(".cell.stats_L1.tsv") or name.endswith(".cell.stats_L2.tsv") or name.endswith(".cell.stats_L3.tsv"): + sample = re.sub(r"\.cell\.stats_L[123]\.tsv$", "", name) + samples[sample]["sample_id"] = sample + samples[sample]["rna"].setdefault("cell_barcode", []).append(read_tsv_stats(path)) + elif name.endswith(".dna_cell.stats_L1.tsv") or name.endswith(".dna_cell.stats_L2.tsv") or name.endswith(".dna_cell.stats_L3.tsv"): + sample = re.sub(r"\.dna_cell\.stats_L[123]\.tsv$", "", name) + samples[sample]["sample_id"] = sample + samples[sample]["dna"].setdefault("cell_barcode", []).append(read_tsv_stats(path)) + elif name == "Summary.csv": + split = path.parent.name.replace(".Solo.outGeneFull", "") + values = read_csv_key_values(path) + values["split_id"] = split + rna_summaries.append(values) + elif name.endswith(".Log.final.out"): + star_logs.append({"file": name}) + elif name.endswith(".flagstat"): + metrics = read_flagstat(path) + metrics["id"] = strip_suffix(name, ".flagstat") + flagstats.append(metrics) + elif name.endswith(".DuplicateMetrics.txt"): + duplicate_metrics.append(read_duplicate_metrics(path)) + elif name.endswith(".stats"): + samtools_stats.append({"file": name}) + + return { + "samples": dict(samples), + "rna_summaries": rna_summaries, + "star_logs": star_logs, + "flagstats": flagstats, + "duplicate_metrics": duplicate_metrics, + "samtools_stats": samtools_stats, + "input_file_count": len(files), + } + + +def weighted_rna_percent(records, key): + numerator = 0.0 + denominator = 0.0 + for record in records: + reads = record.get("Number of Reads") + value = record.get(key) + if reads is None or value is None: + continue + numerator += float(reads) * float(value) + denominator += float(reads) + if denominator == 0: + return None + return pct_from_fraction(numerator / denominator) + + +def average(values): + clean = [float(v) for v in values if v is not None] + return mean(clean) if clean else None + + +def weighted_dna_unique_percent(records): + duplicate_total = 0 + examined_total = 0 + for record in records: + read_pairs = record.get("read_pairs_examined") + read_pair_duplicates = record.get("read_pair_duplicates") + unpaired_reads = record.get("unpaired_reads_examined") or 0 + unpaired_duplicates = record.get("unpaired_read_duplicates") or 0 + if read_pairs is None or read_pair_duplicates is None: + continue + duplicate_total += int(read_pair_duplicates) + int(unpaired_duplicates) + examined_total += int(read_pairs) + int(unpaired_reads) + if examined_total: + return (1.0 - (duplicate_total / examined_total)) * 100.0 + return average([item.get("unique_percent") for item in records]) + + +def cell_barcode_percent(cell_stats): + if not cell_stats: + return None + candidates = [] + for stats in cell_stats: + if "reads_with_all_ligations" in stats: + candidates.append(stats["reads_with_all_ligations"]["percent"]) + elif "reads_with_ligation_all_segments" in stats: + candidates.append(stats["reads_with_ligation_all_segments"]["percent"]) + elif "reads_with_ligation" in stats: + candidates.append(stats["reads_with_ligation"]["percent"]) + elif "reads_with_L1" in stats: + candidates.append(stats["reads_with_L1"]["percent"]) + return average(candidates) + + +def sample_for_split(split_id: str, sample_ids): + matches = [sample_id for sample_id in sample_ids if split_id == sample_id or split_id.startswith(f"{sample_id}_")] + return max(matches, key=len) if matches else split_id.split("_", 1)[0] + + +def flagstat_read_units(record): + if record.get("read1") is not None: + return record.get("read1") + if record.get("paired_in_sequencing") is not None: + return int(record["paired_in_sequencing"] / 2) + return record.get("primary_mapped") or record.get("mapped") or record.get("total") + + +def split_from_flagstat_id(flagstat_id: str): + split_id = re.sub(r"^(rna|dna)\.", "", flagstat_id) + split_id = re.sub(r"\.(filtered_cells|aligned|markeddup|nodup)$", "", split_id) + return split_id + + +def add_sample_value(sample_metrics, sample_id, key, value): + if value is None: + return + sample_metrics[sample_id][key] = sample_metrics[sample_id].get(key, 0) + int(round(float(value))) + + +def rna_mapping_counts(records, sample_ids, key): + counts = defaultdict(int) + for record in records: + split_id = record.get("split_id") + reads = record.get("Number of Reads") + fraction = record.get(key) + if not split_id or reads is None or fraction is None: + continue + sample_id = sample_for_split(split_id, sample_ids) + counts[sample_id] += int(round(float(reads) * float(fraction))) + return counts + + +def flagstat_counts_by_sample(flagstats, sample_ids, modality, stage): + counts = defaultdict(dict) + needle = f".{stage}" + for record in flagstats: + flagstat_id = record.get("id", "") + if not flagstat_id.startswith(f"{modality}.") or needle not in flagstat_id: + continue + sample_id = sample_for_split(split_from_flagstat_id(flagstat_id), sample_ids) + add_sample_value(counts, sample_id, "reads", flagstat_read_units(record)) + return {sample_id: values.get("reads") for sample_id, values in counts.items()} + + +def build_metrics(collected, library_name="unknown library"): + samples = collected["samples"] + library_name = library_name or "unknown library" + sample_ids = sorted(samples) + rna_transcriptome_counts = rna_mapping_counts( + collected["rna_summaries"], + sample_ids, + "Reads Mapped to GeneFull: Unique GeneFull", + ) + rna_genome_counts = rna_mapping_counts( + collected["rna_summaries"], + sample_ids, + "Reads Mapped to Genome: Unique", + ) + rna_usable_counts = flagstat_counts_by_sample(collected["flagstats"], sample_ids, "rna", "filtered_cells") + dna_mapped_counts = flagstat_counts_by_sample(collected["flagstats"], sample_ids, "dna", "aligned") + dna_usable_counts = flagstat_counts_by_sample(collected["flagstats"], sample_ids, "dna", "nodup") + + sequencing_rows = [] + for sample_id in sorted(samples): + sample = samples[sample_id] + + rna = sample.get("rna", {}) + rna_sb = rna.get("sample_barcode", {}) + if rna_sb: + sequencing_rows.append( + { + "library_name": library_name, + "sample_id": sample_id, + "modality": "RNA", + "reads": rna_sb.get("reads", {}).get("count"), + "confidently_mapped": pct(rna_genome_counts.get(sample_id), rna_sb.get("reads", {}).get("count")), + "confidently_mapped_reads": rna_genome_counts.get(sample_id), + "valid_sample_barcodes": rna_sb.get("bc_reads", {}).get("percent"), + "valid_cell_barcodes": cell_barcode_percent(rna.get("cell_barcode", [])), + "valid_modality_barcodes": None, + "usable_reads": rna_usable_counts.get(sample_id), + } + ) + + dna = sample.get("dna", {}) + dna_sb = dna.get("sample_barcode", {}) + if dna_sb: + sequencing_rows.append( + { + "library_name": library_name, + "sample_id": sample_id, + "modality": "DNA", + "reads": dna_sb.get("reads", {}).get("count"), + "confidently_mapped": pct(dna_mapped_counts.get(sample_id), dna_sb.get("reads", {}).get("count")), + "confidently_mapped_reads": dna_mapped_counts.get(sample_id), + "valid_sample_barcodes": dna_sb.get("bc_reads", {}).get("percent"), + "valid_modality_barcodes": dna.get("modality_barcode", {}).get("bc_reads", {}).get("percent"), + "valid_cell_barcodes": cell_barcode_percent(dna.get("cell_barcode", [])), + "usable_reads": dna_usable_counts.get(sample_id), + } + ) + + rna_raw_reads = sum(row.get("reads") or 0 for row in sequencing_rows if row["modality"] == "RNA") + dna_raw_reads = sum(row.get("reads") or 0 for row in sequencing_rows if row["modality"] == "DNA") + rna_transcriptome_count = sum(rna_transcriptome_counts.values()) + rna_genome_count = sum(rna_genome_counts.values()) + dna_mapped_count = sum(dna_mapped_counts.values()) + dna_usable_count = sum(dna_usable_counts.values()) + + mapping_quality = { + "rna_confidently_mapped_to_transcriptome_reads": rna_transcriptome_count, + "rna_confidently_mapped_to_transcriptome_percent": pct(rna_transcriptome_count, rna_raw_reads), + "rna_confidently_mapped_to_genome_reads": rna_genome_count, + "rna_confidently_mapped_to_genome_percent": pct(rna_genome_count, rna_raw_reads), + "dna_confidently_mapped_reads": dna_mapped_count, + "dna_confidently_mapped_percent": pct(dna_mapped_count, dna_raw_reads), + "dna_unique_reads": dna_usable_count, + "dna_unique_reads_percent": pct(dna_usable_count, dna_raw_reads), + } + main_statistics = [ + { + "metric": "RNA confidently mapped to transcriptome", + "value": mapping_quality["rna_confidently_mapped_to_transcriptome_percent"], + "count": rna_transcriptome_count, + "denominator": rna_raw_reads, + "value_type": "percent", + "subtitle": "STARsolo GeneFull unique reads / raw RNA reads", + "modality": "RNA", + }, + { + "metric": "DNA unique reads", + "value": mapping_quality["dna_unique_reads_percent"], + "count": dna_usable_count, + "denominator": dna_raw_reads, + "value_type": "percent", + "subtitle": "Final NoDup BAM read pairs / raw DNA reads", + "modality": "DNA", + }, + ] + libraries = [ + { + "library_name": library_name, + "mapping_quality": mapping_quality, + "main_statistics": main_statistics, + "sequencing_quality": sequencing_rows, + } + ] + export_rows = build_export_rows(libraries) + + return { + "generated_at": datetime.now(timezone.utc).isoformat(), + "library_name": library_name, + "libraries": libraries, + "mapping_quality": mapping_quality, + "sequencing_quality": sequencing_rows, + "export_rows": export_rows, + "inputs": { + "file_count": collected["input_file_count"], + "rna_summary_count": len(collected["rna_summaries"]), + "flagstat_count": len(collected["flagstats"]), + "duplicate_metrics_count": len(collected["duplicate_metrics"]), + "samtools_stats_count": len(collected["samtools_stats"]), + }, + "raw": collected, + } + + +def export_value(value, value_type=None): + if value_type == "percent": + return fmt_pct(value) + if isinstance(value, int): + return str(value) + if isinstance(value, float): + return f"{value:.4g}" + if value is None: + return "n/a" + return str(value) + + +def build_export_rows(libraries): + rows = [] + for library in libraries: + library_name = library["library_name"] + for card in library["main_statistics"]: + rows.append( + { + "section": "Main statistics", + "library": library_name, + "modality": card["modality"], + "fastq_id": "", + "metric": card["metric"], + "value": export_value(card.get("value"), card.get("value_type")), + "absolute_reads": fmt_int(card.get("count")), + "raw_reads": fmt_int(card.get("denominator")), + "number_of_reads": "", + "confidently_mapped": "", + "valid_sample_barcodes": "", + "valid_cell_barcodes": "", + "valid_modality_barcodes": "", + "usable_reads": "", + "details": card["subtitle"], + } + ) + for row in library["sequencing_quality"]: + rows.append( + { + "section": "Sequencing quality", + "library": library_name, + "modality": row["modality"], + "fastq_id": row["sample_id"], + "metric": "sample-level sequencing QC", + "value": "", + "number_of_reads": fmt_int(row.get("reads")), + "confidently_mapped": fmt_count_pct(row.get("confidently_mapped_reads"), row.get("reads")), + "valid_sample_barcodes": fmt_pct(row.get("valid_sample_barcodes")), + "valid_modality_barcodes": fmt_pct(row.get("valid_modality_barcodes")) + if row["modality"] == "DNA" + else "n/a", + "valid_cell_barcodes": fmt_pct(row.get("valid_cell_barcodes")), + "usable_reads": fmt_int(row.get("usable_reads")), + "details": "", + } + ) + return rows + + +def metric_card(title, value, subtitle, modality=None): + modality_class = (modality or "").lower() + absolute_line = "" + if isinstance(value, dict): + count = value.get("count") + denominator = value.get("denominator") + value = value.get("percent") + absolute_line = f"
{fmt_int(count)} / {fmt_int(denominator)} raw reads
" + return f""" +
+
{html.escape(title)}
+
{fmt_pct(value)}
+ {absolute_line} +
+
{html.escape(subtitle)}
+
+ """ + + +def sequencing_table(rows): + row_html = [] + for row in rows: + modality_class = "rna" if row["modality"] == "RNA" else "dna" + row_html.append( + f""" + + {html.escape(row['modality'])} + {html.escape(row['sample_id'])} + {fmt_int(row.get('reads'))} + {fmt_pct(row.get('valid_sample_barcodes'))} + {fmt_pct(row.get('valid_modality_barcodes')) if row['modality'] == 'DNA' else 'n/a'} + {fmt_pct(row.get('valid_cell_barcodes'))} + {fmt_count_pct(row.get('confidently_mapped_reads'), row.get('reads'))} + {fmt_int(row.get('usable_reads'))} + + """ + ) + + return f""" + + + + + + + + + + + + + + + {''.join(row_html) if row_html else ''} + +
ModalityFastq IDNumber of readsValid sample barcodesValid modality barcodesValid cell barcodesConfidently mapped to genomeUsable reads
No sequencing-quality inputs were detected.
+ """ + + +def render_library(library): + cards = [] + for card in library["main_statistics"]: + cards.append( + metric_card( + card["metric"], + { + "percent": card.get("value"), + "count": card.get("count"), + "denominator": card.get("denominator"), + }, + card["subtitle"], + card.get("modality"), + ) + ) + + return f""" +
+
+
+

Mapping Quality

+
+
+ {''.join(cards)} +
+
+ +
+
+

Sequencing Quality

+
+ {sequencing_table(library['sequencing_quality'])} +
+
+ """ + + +def render_html(metrics): + libraries = metrics.get("libraries") or [] + library_label = metrics.get("library_name") or "unknown library" + export_rows_json = json.dumps(metrics.get("export_rows", []), ensure_ascii=False).replace(" + + + + + TrESFlow QC Report + + + +
+
+
+

TrESFlow QC Report {html.escape(library_label)}

+
Generated {html.escape(metrics['generated_at'])}
+
+
+ + +
+
+ + {''.join(render_library(library) for library in libraries) if libraries else '
No library metrics were detected.
'} +
+ + + + +""" + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--input-dir", required=True, type=Path) + parser.add_argument("--output-html", required=True, type=Path) + parser.add_argument("--output-json", required=True, type=Path) + parser.add_argument("--library-name", default="unknown library") + args = parser.parse_args() + + collected = collect_inputs(args.input_dir) + metrics = build_metrics(collected, args.library_name) + + args.output_json.write_text(json.dumps(metrics, indent=2, sort_keys=True), encoding="utf-8") + args.output_html.write_text(render_html(metrics), encoding="utf-8") + + +if __name__ == "__main__": + main() diff --git a/conf/base.config b/conf/base.config index b7ea605..098efc2 100644 --- a/conf/base.config +++ b/conf/base.config @@ -7,6 +7,11 @@ process { // Scheduler reservations stay moderate by default so independent samples, // groups, and marks can overlap under the local executor. + withLabel: process_single { + cpus = Math.max(1, Math.min((params.helper_cpus ?: 4) as int, params.max_cpus as int)) + memory = '4 GB' + time = '2h' + } withName: TAG_RNA_SAMPLE_BARCODE { cpus = Math.max(1, Math.min((params.tagging_cpus ?: 4) as int, params.max_cpus as int)) @@ -83,30 +88,71 @@ process { time = '12h' } + withName: FASTQC { + cpus = Math.max(1, Math.min((params.helper_cpus ?: 4) as int, params.max_cpus as int)) + memory = '4 GB' + time = '2h' + } + + withName: SAMTOOLS_IDXSTATS { + cpus = Math.max(1, Math.min((params.helper_cpus ?: 4) as int, params.max_cpus as int)) + memory = '2 GB' + time = '1h' + } + + withName: SAMTOOLS_QUICKCHECK { + cpus = 1 + memory = '1 GB' + time = '1h' + } + + withName: SAMTOOLS_QUICKCHECK_REPORT { + cpus = 1 + memory = '1 GB' + time = '30m' + } + // ALIGN_DNA passes this CPU value to bwa-mem2 and samtools inside the wrapper. withName: ALIGN_DNA { cpus = Math.max(1, Math.min((params.dna_align_cpus ?: 16) as int, params.max_cpus as int)) time = '12h' } - withName: MARK_DUPLICATES_DNA { + withName: GATK4_MARKDUPLICATES { cpus = 1 memory = '8 GB' time = '6h' } + withName: NORMALIZE_DNA_MARKDUPLICATES { + cpus = 1 + memory = '2 GB' + time = '1h' + } + withName: SPLIT_DUPLICATES_DNA { cpus = Math.max(1, Math.min((params.helper_cpus ?: 4) as int, params.max_cpus as int)) memory = '4 GB' time = '2h' } - withName: BAM_COVERAGE_DNA { + withName: CHECK_DNA_NODUP_BAM { + cpus = Math.max(1, Math.min((params.helper_cpus ?: 4) as int, params.max_cpus as int)) + memory = '2 GB' + time = '1h' + } + + withName: DEEPTOOLS_BAMCOVERAGE { cpus = Math.max(1, Math.min((params.coverage_cpus ?: 8) as int, params.max_cpus as int)) memory = '4 GB' time = '2h' } + withName: NORMALIZE_DNA_BAMCOVERAGE { + cpus = 1 + memory = '1 GB' + time = '30m' + } } timeline { diff --git a/conf/modules.config b/conf/modules.config index 20b79ff..ea01467 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -7,3 +7,59 @@ must not define a global `publishDir` without a target path. ---------------------------------------------------------------------------------------- */ + +process { + withName: FASTQC { + publishDir = [ + path : "${params.outdir ?: "${projectDir}/results"}/qc/fastqc", + mode : params.publish_dir_mode, + overwrite: true + ] + } + + withName: SAMTOOLS_FLAGSTAT { + publishDir = [ + path : "${params.outdir ?: "${projectDir}/results"}/qc/samtools", + mode : params.publish_dir_mode, + overwrite: true, + pattern : "*.flagstat" + ] + } + + withName: SAMTOOLS_STATS { + publishDir = [ + path : "${params.outdir ?: "${projectDir}/results"}/qc/samtools", + mode : params.publish_dir_mode, + overwrite: true, + pattern : "*.stats" + ] + } + + withName: SAMTOOLS_IDXSTATS { + publishDir = [ + path : "${params.outdir ?: "${projectDir}/results"}/qc/samtools", + mode : params.publish_dir_mode, + overwrite: true, + pattern : "*.idxstats" + ] + } + + withName: GATK4_MARKDUPLICATES { + ext.prefix = { "${meta.id}_MarkedDup.bam" } + ext.args = '--REMOVE_DUPLICATES false --BARCODE_TAG CB --CREATE_INDEX true --MAX_RECORDS_IN_RAM 10000000' + } + + withName: DEEPTOOLS_BAMCOVERAGE { + ext.prefix = { "${meta.id}_NoDup" } + ext.args = { "-bs 100 --extendReads --centerReads --effectiveGenomeSize ${meta.dna_effective_genome_size}" } + } + + withName: MULTIQC { + publishDir = [ + path : "${params.outdir ?: "${projectDir}/results"}/multiqc", + mode : params.publish_dir_mode, + overwrite: true + ] + ext.prefix = 'multiqc_report' + } +} diff --git a/conf/test.config b/conf/test.config index 0826d27..bb62fb6 100644 --- a/conf/test.config +++ b/conf/test.config @@ -81,18 +81,35 @@ process { cpus = 1 } - withName: MARK_DUPLICATES_DNA { + withName: SPLIT_DUPLICATES_DNA { ext.mock = true + cpus = 1 } - withName: SPLIT_DUPLICATES_DNA { + withName: CHECK_DNA_NODUP_BAM { ext.mock = true cpus = 1 + memory = '1 GB' } - withName: BAM_COVERAGE_DNA { - ext.mock = true + withName: DEEPTOOLS_BAMCOVERAGE { cpus = 1 + memory = '1 GB' } + withName: SAMTOOLS_FLAGSTAT { + ext.when = false + } + + withName: SAMTOOLS_STATS { + ext.when = false + } + + withName: SAMTOOLS_IDXSTATS { + ext.when = false + } + + withName: SAMTOOLS_QUICKCHECK { + ext.when = false + } } diff --git a/docs/architecture/implemented_pipeline.md b/docs/architecture/implemented_pipeline.md index 50c4c06..2e28a04 100644 --- a/docs/architecture/implemented_pipeline.md +++ b/docs/architecture/implemented_pipeline.md @@ -3,8 +3,8 @@ Core workflow only: - RNA through the repo-owned STARsolo, filtered-BAM, and coverage stages -- DNA through `BAM_COVERAGE_DNA` -- Shared sequencing-efficiency UpSet PDF reporting from tag-record and alignment channels +- DNA through repo-owned tagging/splitting/alignment, nf-core `gatk4/markduplicates`, repo-owned NoDup extraction, and nf-core `deeptools/bamcoverage` +- nf-core FastQC/samtools sidecar QC, nf-core MultiQC, and a TrESFlow-specific HTML report at the end of the run ```mermaid flowchart TD @@ -27,7 +27,6 @@ flowchart TD REF --> DNA2 REF --> DNA5 REF --> DNA8 - DERIVE --> REPORT DERIVE --> RNA0 DERIVE --> RNA4 DERIVE --> DNA0 @@ -54,12 +53,32 @@ flowchart TD DNA3[TRIM_DNA_FASTQS] DNA4[SPLIT_DNA_READS] DNA5[ALIGN_DNA] - DNA6[MARK_DUPLICATES_DNA] + DNA6[nf-core GATK4_MARKDUPLICATES\n+ TrESFlow filename normalization] DNA7[SPLIT_DUPLICATES_DNA] - DNA8[BAM_COVERAGE_DNA] + DNA8[CHECK_DNA_NODUP_BAM\n+ nf-core DEEPTOOLS_BAMCOVERAGE] DNA0 --> DNA1 --> DNA2 --> DNA3 --> DNA4 --> DNA5 --> DNA6 --> DNA7 --> DNA8 end + subgraph Reporting[Shared Reporting] + FASTQC[nf-core FASTQC] + SAMTOOLS[nf-core SAMTOOLS_FLAGSTAT/STATS/IDXSTATS/QUICKCHECK] + MULTIQC[nf-core MULTIQC] + TRESHTML[TRES_REPORT_HTML] + end + + RNA0 --> FASTQC + RNA7 --> SAMTOOLS + RNA6 --> MULTIQC + DNA0 --> FASTQC + DNA5 --> SAMTOOLS + DNA6 --> SAMTOOLS + DNA7 --> SAMTOOLS + FASTQC --> MULTIQC + SAMTOOLS --> MULTIQC + SAMTOOLS --> TRESHTML + RNA6 --> TRESHTML + RNA2 --> TRESHTML + DNA2 --> TRESHTML ``` Notes: @@ -67,5 +86,8 @@ Notes: - One hierarchical samplesheet can describe RNA-only, DNA-only, or combined runs. - `sb_group_map.tsv`, `dna_mo_map.tsv`, and DNA modality whitelist files are internal artifacts, not user inputs. - `TAG_DNA_CELL_BARCODE` uses DNA `i1` as the ligation source: single reads use starts `15,53,91`; dual reads use starts `41,79,117`. -- DNA alignment does not enforce a low-count cell-barcode threshold; the BAM-derived `CB>100 +` category in sequencing-efficiency plots shows that status. +- nf-core FastQC and samtools modules are sidecar QC readers only; they do not alter downstream TrESFlow outputs. +- nf-core `gatk4/markduplicates` replaces the previous local GATK invocation but preserves `--BARCODE_TAG CB`, `--REMOVE_DUPLICATES false`, index creation, and the historical TrESFlow output names via a normalization adapter. +- nf-core `deeptools/bamcoverage` replaces the previous direct `bamCoverage` call. A repo-owned precheck keeps the previous zero-mapped NoDup BAM behavior by publishing a warning artifact and skipping coverage when needed. +- `TRES_REPORT_HTML` renders `tres_report/tres_report.html` and `tres_report_metrics.json` from existing TrES stats, STARsolo summaries, samtools outputs, and GATK duplicate metrics. - The active core runtime lives under [`scripts/core_runtime/`](/mnt/dataFast/ahrmad/tresflowdir/TrESFlow/scripts/core_runtime). diff --git a/docs/output.md b/docs/output.md index ca85151..018907a 100644 --- a/docs/output.md +++ b/docs/output.md @@ -22,6 +22,10 @@ DNA-related outputs: Shared reporting outputs: - `pipeline_info/` +- `qc/fastqc/` +- `qc/samtools/` +- `multiqc/` +- `tres_report/` ## RNA outputs @@ -39,6 +43,7 @@ SAM read-group header TSVs are internal work files and are not published. STARsolo and filtered BAM outputs: - `_.Solo.outGeneFull/` +- `_.Log.final.out` - `_.filtered_cells.bam` - `_.stranded_*.bw` - `_.unstranded_*.bw` @@ -64,7 +69,7 @@ Duplicate-marked BAMs, final duplicate-filtered BAMs, and coverage tracks: - `___NoDup.bam.bai` - `___NoDup.bw` -`*_MarkedDup.bam` is retained so sequencing-efficiency reporting can count aligned DNA reads before duplicate removal. `*_NoDup.bam` remains the duplicate-filtered output used for downstream DNA coverage. +`*_MarkedDup.bam` is generated by nf-core `gatk4/markduplicates` with TrESFlow's barcode-aware duplicate settings and then normalized back to the historical TrESFlow filename contract. `*_NoDup.bam` remains the duplicate-filtered output used for downstream DNA coverage. `*_NoDup.bw` is generated via nf-core `deeptools/bamcoverage` after the pipeline confirms that the NoDup BAM has mapped reads. ## Tagging/count/stat outputs @@ -92,6 +97,58 @@ Tagging summaries are published with modality-specific names: Only published tag-record tables are gzipped. Uncompressed tag-record TSVs are internal work files. +## QC and HTML reports + +### `qc/fastqc/` + +nf-core `fastqc` writes raw FASTQ QC files: + +- `*_fastqc.html` +- `*_fastqc.zip` + +### `qc/samtools/` + +When real BAMs are produced, nf-core samtools sidecar modules write standardized BAM QC files: + +- `*.flagstat` +- `*.stats` +- `*.idxstats` +- `*.quickcheck.tsv` + +These modules read existing RNA filtered BAMs and DNA aligned / marked-duplicate / NoDup BAMs. They do not modify any downstream TrESFlow outputs. + +In `-profile test`, the samtools sidecars are disabled because the smoke profile intentionally uses lightweight mock BAM text files. + +### `multiqc/` + +nf-core `multiqc` writes: + +- `multiqc_report.html` +- `multiqc_report_data/` + +MultiQC aggregates supported logs and QC text files, including FastQC, STAR logs, samtools outputs, and GATK duplicate metrics when present. + +### `tres_report/` + +The TrESFlow-specific end-of-run report writes: + +- `tres_report.html` +- `tres_report_metrics.json` + +This custom report is separate from MultiQC. It summarizes TrES-specific RNA/DNA mapping and barcode metrics in a compact HTML page: + +- the samplesheet `library_name` in the report title and per-library section header +- per-library main-statistic cards for RNA mapping and DNA mapped/unique-read summaries +- a detailed per-library sequencing QC table for barcode, read-count, and UMI/no-UMI fields +- browser-side `Export CSV` and `Export Excel` buttons for the displayed report metrics +- RNA mapping to transcriptome and genome from STARsolo `Summary.csv` +- DNA mapped-read and unique-read metrics from samtools/GATK outputs when DNA BAM QC is present +- RNA/DNA sample-barcode and cell-barcode rates from TrES tagging stats +- RNA observed UMI count from UMI tagging counts +- DNA modality barcode rate from DNA modality tagging stats + +DNA has no UMI metric by design. + ## Pipeline information `pipeline_info/` contains execution metadata and the derived helper contract written from the YAML samplesheet. @@ -124,6 +181,6 @@ The pipeline does not keep intermediate tagging, uSAM, duplicate-split, or cover - published RNA FASTQs are the grouped split FASTQs under `rna_split_fastqs/` - published DNA FASTQs are the grouped and marked split FASTQs under `dna_split_fastqs/` - earlier tag, trim, RNA uSAM, STAR aligned BAM, tag-record, and non-published coverage side products are transient task outputs -- DNA duplicate-marked BAMs are published under `dna_align/` for sequencing-efficiency reporting +- DNA duplicate-marked BAMs are published under `dna_align/` as duplicate-aware alignment outputs By default, `--cleanup_work true` asks Nextflow to clean successful task work directories after the workflow finishes successfully. This preserves published outputs while reducing retained `work/` storage. Set `--cleanup_work false` to keep work directories for debugging or a more resume-friendly run. diff --git a/docs/usage.md b/docs/usage.md index 6a73b81..a1c1230 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -5,14 +5,22 @@ `TrESFlow` supports one public input contract: a single hierarchical YAML samplesheet passed with `--samplesheet`. There is no CSV input mode in this repository. -The pipeline runs two independent modality branches from that YAML, then builds sequencing-efficiency UpSet plots from the published tag-record and alignment channels: +The pipeline runs two independent modality branches from that YAML, then builds nf-core QC sidecar outputs, MultiQC, and a compact TrESFlow-specific HTML report from the published tag-record, STAR, samtools, and alignment channels: - `rna`: sample-barcode tagging, UMI tagging, cell-barcode tagging, trimming, split by SB groups, `FqToSAM`, STARsolo, filtered BAM, bigWigs - `dna`: sample-barcode tagging, modality tagging, cell-barcode tagging, trimming, split by SB groups and DNA marks, alignment, duplicate marking, NoDup BAM, bigWig -Sequencing-efficiency outputs are written to `TrES_Stats/` as UpSet PDFs only. Sankey plots, HTML reports, count tables, combined RNA+DNA reports, and sequencing-efficiency warning TSVs are not produced. Optional unavailable BAM-derived categories are skipped with warnings in the process log. +End-of-run reporting is written separately: -DNA alignment no longer filters out low-count cell barcodes during `ALIGN_DNA`. Low-count status is visualized in sequencing-efficiency plots as `CB>100 +`, using BAM-derived unique query-name read-pair support. +- `tres_report/tres_report.html`: TrESFlow-specific per-library RNA/DNA mapping and barcode summary with CSV/Excel export buttons +- `tres_report/tres_report_metrics.json`: machine-readable metrics used by the HTML report +- `multiqc/multiqc_report.html`: nf-core MultiQC aggregation of supported logs and QC files +- `qc/fastqc/*_fastqc.{html,zip}`: nf-core FastQC reports for raw FASTQs +- `qc/samtools/*.flagstat`, `*.stats`, `*.idxstats`, and `*.quickcheck.tsv`: nf-core samtools sidecar QC for real BAM outputs + +The samtools sidecars are disabled in `-profile test` because the smoke profile uses mock BAM text files rather than valid BAMs. + +DNA alignment no longer filters out low-count cell barcodes during `ALIGN_DNA`. Duplicate-aware DNA outputs are represented by the published `*_MarkedDup.bam` and `*_NoDup.bam` files. ## Quick Start @@ -90,7 +98,7 @@ samples: ### `runtime` -- `env_prefix`: environment prefix containing `python3`, `codon`, `trim_galore`, `STAR`, `samtools`, `bedGraphToBigWig`, `bwa-mem2`, `bamCoverage`, and `gatk` +- `env_prefix`: environment prefix containing `python3`, `codon`, `trim_galore`, `STAR`, `samtools`, `bedGraphToBigWig`, `bwa-mem2`, `bamCoverage`, `FastQC`, and `gatk` - `tmpdir`: optional explicit task temporary directory. If omitted, the pipeline uses `--outdir`. The pipeline creates it if missing and fails if it is not writable. ### `references` diff --git a/modules.json b/modules.json index 7b81505..ea0a167 100644 --- a/modules.json +++ b/modules.json @@ -1,5 +1,52 @@ { "name": "nf-core/tres", "homePage": "", - "repos": {} -} \ No newline at end of file + "repos": { + "https://github.com/nf-core/modules.git": { + "modules": { + "nf-core": { + "deeptools/bamcoverage": { + "branch": "master", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", + "installed_by": ["modules"] + }, + "fastqc": { + "branch": "master", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", + "installed_by": ["modules"] + }, + "gatk4/markduplicates": { + "branch": "master", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", + "installed_by": ["modules"] + }, + "multiqc": { + "branch": "master", + "git_sha": "98403d15b0e50edae1f3fec5eae5e24982f1fade", + "installed_by": ["modules"] + }, + "samtools/flagstat": { + "branch": "master", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", + "installed_by": ["modules"] + }, + "samtools/idxstats": { + "branch": "master", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", + "installed_by": ["modules"] + }, + "samtools/quickcheck": { + "branch": "master", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", + "installed_by": ["modules"] + }, + "samtools/stats": { + "branch": "master", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", + "installed_by": ["modules"] + } + } + } + } + } +} diff --git a/modules/local/check_dna_nodup_bam/main.nf b/modules/local/check_dna_nodup_bam/main.nf new file mode 100644 index 0000000..0a73226 --- /dev/null +++ b/modules/local/check_dna_nodup_bam/main.nf @@ -0,0 +1,89 @@ +/* + * Guard nf-core/deeptools/bamcoverage from empty DNA NoDup BAMs. + * + * deepTools can be noisy or unhelpful on BAMs with zero mapped reads. The old + * local BAM_COVERAGE_DNA module skipped those BAMs and wrote a warning artifact; + * this module preserves that behavior before routing non-empty BAMs to nf-core. + */ + +import RuntimeSupport + +process CHECK_DNA_NODUP_BAM { + tag "${splitName}" + label 'process_single' + + publishDir "${params.outdir ?: "${projectDir}/results"}/pipeline_info/warnings", mode: params.publish_dir_mode, overwrite: true, pattern: "*.zero_mapped_nodup_bam.tsv" + + input: + tuple val(splitName), val(meta), path(noDupBam, stageAs: "input_NoDup.bam"), path(noDupBai, stageAs: "input_NoDup.bam.bai"), val(effectiveGenomeSize) + + output: + tuple val(splitName), val(meta), path("*_NoDup.bam"), path("*_NoDup.bam.bai"), val(effectiveGenomeSize), optional: true, emit: ready + tuple val(splitName), val(meta), path("${splitName}.zero_mapped_nodup_bam.tsv"), optional: true, emit: warnings + path("versions.yml"), emit: versions + + script: + def mode = task.ext.mock ? 'mock' : 'real' + def runtimeExports = RuntimeSupport.shellExports(meta) + def sampleId = meta.id as String + def suffix = splitName.replaceFirst("^${sampleId}_", '') + def tokens = suffix.tokenize('_') + def groupName = tokens ? tokens[0] : '' + def markName = tokens.size() > 1 ? tokens[1..-1].join('_') : '' + + if( mode == 'mock' ) { + """ + ${runtimeExports} + + touch "${splitName}_NoDup.bam" "${splitName}_NoDup.bam.bai" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + component: "local" + END_VERSIONS + """ + } + else { + """ + ${runtimeExports} + + if [[ ! -x "\$SAMTOOLS_BIN" ]]; then + echo "Missing configured DNA runtime executable: \$SAMTOOLS_BIN" >&2 + exit 1 + fi + + mapped_reads="\$("\$SAMTOOLS_BIN" view --threads "${task.cpus}" -c -F 4 "${noDupBam}")" + if [[ "\${mapped_reads}" -eq 0 ]]; then + bam_path="\$(readlink -f "${noDupBam}")" + cat >&2 <<'EOF' +================================================================================ +WARNING: ZERO MAPPED READS IN DNA NoDup BAM +================================================================================ +EOF + echo "Sample: ${sampleId}" >&2 + echo "Group: ${groupName}" >&2 + echo "Mark: ${markName}" >&2 + echo "BAM: \${bam_path}" >&2 + echo "Mapped reads: \${mapped_reads}" >&2 + echo "Skipped nf-core/deeptools/bamcoverage for ${splitName}" >&2 + printf 'sample\tgroup\tmark\tbam\tmapped_reads\tskipped_output\n' > "${splitName}.zero_mapped_nodup_bam.tsv" + printf '%s\t%s\t%s\t%s\t%s\t%s\n' \\ + "${sampleId}" \\ + "${groupName}" \\ + "${markName}" \\ + "\${bam_path}" \\ + "\${mapped_reads}" \\ + "${splitName}_NoDup.bw" \\ + >> "${splitName}.zero_mapped_nodup_bam.tsv" + else + cp -L "${noDupBam}" "${splitName}_NoDup.bam" + cp -L "${noDupBai}" "${splitName}_NoDup.bam.bai" + fi + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + component: "local" + END_VERSIONS + """ + } +} diff --git a/modules/local/normalize_dna_bamcoverage/main.nf b/modules/local/normalize_dna_bamcoverage/main.nf new file mode 100644 index 0000000..b9c5956 --- /dev/null +++ b/modules/local/normalize_dna_bamcoverage/main.nf @@ -0,0 +1,30 @@ +/* + * Normalize nf-core/deeptools/bamcoverage bigWig naming back to TrESFlow's + * historical _NoDup.bw output contract. + */ + +process NORMALIZE_DNA_BAMCOVERAGE { + tag "${splitName}" + label 'process_single' + + publishDir "${params.outdir ?: "${projectDir}/results"}/dna_align", mode: params.publish_dir_mode, overwrite: true, pattern: "${splitName}_NoDup.bw" + + input: + tuple val(splitName), val(meta), path(bigwig) + + output: + tuple val(splitName), val(meta), path("${splitName}_NoDup.bw"), emit: bw + path("versions.yml"), emit: versions + + script: + """ + if [[ "\$(readlink -f "${bigwig}")" != "\$(readlink -f "${splitName}_NoDup.bw" 2>/dev/null || true)" ]]; then + cp -L "${bigwig}" "${splitName}_NoDup.bw" + fi + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + component: "local" + END_VERSIONS + """ +} diff --git a/modules/local/normalize_dna_markduplicates/main.nf b/modules/local/normalize_dna_markduplicates/main.nf new file mode 100644 index 0000000..29ea524 --- /dev/null +++ b/modules/local/normalize_dna_markduplicates/main.nf @@ -0,0 +1,41 @@ +/* + * Normalize nf-core/gatk4/markduplicates outputs back to the TrESFlow DNA + * filename contract used by downstream NoDup extraction and reporting. + */ + +process NORMALIZE_DNA_MARKDUPLICATES { + tag "${splitName}" + label 'process_single' + + publishDir "${params.outdir ?: "${projectDir}/results"}/dna_align", mode: params.publish_dir_mode, overwrite: true, pattern: "${splitName}_MarkedDup.bam*" + publishDir "${params.outdir ?: "${projectDir}/results"}/dna_align", mode: params.publish_dir_mode, overwrite: true, pattern: "${splitName}.DuplicateMetrics.txt" + + input: + tuple val(splitName), val(meta), path(markedDupBam), path(markedDupBai), path(markedDupMetrics) + + output: + tuple val(splitName), val(meta), path("${splitName}_MarkedDup.bam"), emit: bam + tuple val(splitName), val(meta), path("${splitName}_MarkedDup.bam.bai"), emit: bai + tuple val(splitName), val(meta), path("${splitName}.DuplicateMetrics.txt"), emit: metrics + path("versions.yml"), emit: versions + + script: + """ + copy_if_needed() { + src="\$1" + dest="\$2" + if [[ "\$(readlink -f "\${src}")" != "\$(readlink -f "\${dest}" 2>/dev/null || true)" ]]; then + cp -L "\${src}" "\${dest}" + fi + } + + copy_if_needed "${markedDupBam}" "${splitName}_MarkedDup.bam" + copy_if_needed "${markedDupBai}" "${splitName}_MarkedDup.bam.bai" + copy_if_needed "${markedDupMetrics}" "${splitName}.DuplicateMetrics.txt" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + component: "local" + END_VERSIONS + """ +} diff --git a/modules/local/rna_starsolo_align/main.nf b/modules/local/rna_starsolo_align/main.nf index 7e3b337..eedb4ed 100644 --- a/modules/local/rna_starsolo_align/main.nf +++ b/modules/local/rna_starsolo_align/main.nf @@ -19,13 +19,16 @@ process RNA_STARSOLO_ALIGN { label 'codon_wrapper' publishDir "${params.outdir ?: "${projectDir}/results"}/rna_align", mode: 'copy', overwrite: true, pattern: "${splitName}.Solo.outGeneFull" + publishDir "${params.outdir ?: "${projectDir}/results"}/rna_align", mode: 'copy', overwrite: true, pattern: "${splitName}.Log.final.out" input: tuple val(splitName), val(meta), path(usam), val(starIndexDir) output: tuple val(splitName), val(meta), path("${splitName}.Solo.outGeneFull"), emit: solo_dir + tuple val(splitName), val(meta), path("${splitName}.Solo.outGeneFull/Summary.csv"), emit: solo_summary tuple val(splitName), val(meta), path("${splitName}.Aligned.sortedByCoord.out.bam"), emit: aligned_bam + tuple val(splitName), val(meta), path("${splitName}.Log.final.out"), emit: star_log path("versions.yml"), emit: versions script: @@ -54,6 +57,53 @@ EOF EOF printf 'mock aligned bam for %s\n' "${splitName}" > "${splitName}.Aligned.sortedByCoord.out.bam" + cat > "${splitName}.Log.final.out" <<'EOF' + Started job on | mock + Started mapping on | mock + Finished on | mock + Mapping speed, Million of reads per hour | 1.00 + Number of input reads | 1000 + Average input read length | 100 + UNIQUE READS: + Uniquely mapped reads number | 900 + Uniquely mapped reads % | 90.00% + Average mapped length | 100.00 + Number of splices: Total | 0 + Number of splices: Annotated (sjdb) | 0 + Number of splices: GT/AG | 0 + Number of splices: GC/AG | 0 + Number of splices: AT/AC | 0 + Number of splices: Non-canonical | 0 + Mismatch rate per base, % | 0.10% + Deletion rate per base | 0.00% + Deletion average length | 0.00 + Insertion rate per base | 0.00% + Insertion average length | 0.00 + MULTI-MAPPING READS: + Number of reads mapped to multiple loci | 50 + % of reads mapped to multiple loci | 5.00% + Number of reads mapped to too many loci | 0 + % of reads mapped to too many loci | 0.00% + UNMAPPED READS: + Number of reads unmapped: too many mismatches | 0 + % of reads unmapped: too many mismatches | 0.00% + Number of reads unmapped: too short | 50 + % of reads unmapped: too short | 5.00% + Number of reads unmapped: other | 0 + % of reads unmapped: other | 0.00% + CHIMERIC READS: + Number of chimeric reads | 0 + % of chimeric reads | 0.00% +EOF + cat > "${splitName}.Solo.outGeneFull/Summary.csv" <<'EOF' +Number of Reads,1000 +Reads Mapped to Genome: Unique+Multiple,0.95 +Reads Mapped to Genome: Unique,0.90 +Reads Mapped to GeneFull: Unique+Multiple GeneFull,0.85 +Reads Mapped to GeneFull: Unique GeneFull,0.80 +Estimated Number of Cells,1 +UMIs in Cells,100 +EOF cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -76,7 +126,7 @@ EOF "${starIndexDir}" \\ "." \\ "${task.cpus}" - + cat <<-END_VERSIONS > versions.yml "${task.process}": component: "local" diff --git a/modules/local/samtools_quickcheck_report/main.nf b/modules/local/samtools_quickcheck_report/main.nf new file mode 100644 index 0000000..b2c2d33 --- /dev/null +++ b/modules/local/samtools_quickcheck_report/main.nf @@ -0,0 +1,34 @@ +/* + * Convert nf-core/samtools/quickcheck exit codes into a small report artifact. + */ + +process SAMTOOLS_QUICKCHECK_REPORT { + tag "${meta.id}" + label 'process_single' + + publishDir "${params.outdir ?: "${projectDir}/results"}/qc/samtools", mode: params.publish_dir_mode, overwrite: true, pattern: "*.quickcheck.tsv" + + input: + tuple val(meta), path(bam), val(exitCode) + + output: + tuple val(meta), path("*.quickcheck.tsv"), emit: report + path("versions.yml"), emit: versions + + script: + def prefix = meta.id + """ + printf 'id\tbam\texit_code\tstatus\n' > "${prefix}.quickcheck.tsv" + if [[ "${exitCode}" == "0" ]]; then + status="pass" + else + status="fail" + fi + printf '%s\t%s\t%s\t%s\n' "${prefix}" "${bam}" "${exitCode}" "\${status}" >> "${prefix}.quickcheck.tsv" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + component: "local" + END_VERSIONS + """ +} diff --git a/modules/local/tres_report_html/main.nf b/modules/local/tres_report_html/main.nf new file mode 100644 index 0000000..0c3e7dd --- /dev/null +++ b/modules/local/tres_report_html/main.nf @@ -0,0 +1,37 @@ +/* + * Module: TRES_REPORT_HTML + * + * Builds a compact TrESFlow-specific HTML report from existing pipeline QC + * artifacts. This is intentionally separate from MultiQC because TrESFlow has + * assay-specific RNA/DNA barcode and mapping semantics that should be explained + * in one stable end-of-run page. + */ + +process TRES_REPORT_HTML { + tag "${meta.id}" + label 'process_single' + + publishDir "${params.outdir ?: "${projectDir}/results"}/tres_report", mode: 'copy', overwrite: true, pattern: "tres_report*" + + input: + tuple val(meta), path(reportInputs, stageAs: "inputs/?/*") + + output: + tuple val(meta), path("tres_report.html"), emit: html + tuple val(meta), path("tres_report_metrics.json"), emit: metrics_json + path("versions.yml"), emit: versions + + script: + """ + python3 "${projectDir}/bin/render_tres_report.py" \\ + --input-dir inputs \\ + --output-html tres_report.html \\ + --output-json tres_report_metrics.json \\ + --library-name "${meta.library_name ?: 'unknown library'}" + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + component: "local" + END_VERSIONS + """ +} diff --git a/modules/nf-core/deeptools/bamcoverage/environment.yml b/modules/nf-core/deeptools/bamcoverage/environment.yml new file mode 100644 index 0000000..c2d2fb3 --- /dev/null +++ b/modules/nf-core/deeptools/bamcoverage/environment.yml @@ -0,0 +1,8 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::deeptools=3.5.6 + - bioconda::samtools=1.20 diff --git a/modules/nf-core/deeptools/bamcoverage/main.nf b/modules/nf-core/deeptools/bamcoverage/main.nf new file mode 100644 index 0000000..bae5860 --- /dev/null +++ b/modules/nf-core/deeptools/bamcoverage/main.nf @@ -0,0 +1,67 @@ +process DEEPTOOLS_BAMCOVERAGE { + tag "$meta.id" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/mulled-v2-eb9e7907c7a753917c1e4d7a64384c047429618a:28424fe3aec58d2b3e4e4390025d886207657d25-0': + 'quay.io/biocontainers/mulled-v2-eb9e7907c7a753917c1e4d7a64384c047429618a:28424fe3aec58d2b3e4e4390025d886207657d25-0' }" + + input: + tuple val(meta) , path(input) , path(input_index) + path(fasta) + path(fasta_fai) + tuple val(meta2), path(blacklist) + + output: + tuple val(meta), path("*.bigWig") , emit: bigwig , optional: true + tuple val(meta), path("*.bedgraph"), emit: bedgraph, optional: true + tuple val("${task.process}"), val('deeptools'), eval('bamCoverage --version | sed "s/bamCoverage //g"') , emit: versions_deeptools, topic: versions + tuple val("${task.process}"), val('samtools'), eval("samtools version | sed '1!d;s/.* //'") , emit: versions_samtools, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def blacklist_cmd = blacklist ? "--blackListFileName ${blacklist}" : "" + def extension = args.contains("--outFileFormat bedgraph") || args.contains("-of bedgraph") ? "bedgraph" : "bigWig" + + // cram_input is currently not working with deeptools + // therefore it's required to convert cram to bam first + def is_cram = input.Extension == "cram" ? true : false + def input_out = is_cram ? input.BaseName + ".bam" : "${input}" + def fai_reference = fasta_fai ? "--fai-reference ${fasta_fai}" : "" + + if (is_cram){ + """ + samtools view -T $fasta $input $fai_reference -@ $task.cpus -o $input_out + samtools index -b $input_out -@ $task.cpus + + bamCoverage \\ + --bam $input_out \\ + $args \\ + --numberOfProcessors ${task.cpus} \\ + --outFileName ${prefix}.${extension} \\ + $blacklist_cmd + """ + } + else { + """ + bamCoverage \\ + --bam $input_out \\ + $args \\ + --numberOfProcessors ${task.cpus} \\ + --outFileName ${prefix}.${extension} \\ + $blacklist_cmd + """ + } + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + def extension = args.contains("--outFileFormat bedgraph") || args.contains("-of bedgraph") ? "bedgraph" : "bigWig" + """ + touch ${prefix}.${extension} + """ +} diff --git a/modules/nf-core/deeptools/bamcoverage/meta.yml b/modules/nf-core/deeptools/bamcoverage/meta.yml new file mode 100644 index 0000000..e9039f1 --- /dev/null +++ b/modules/nf-core/deeptools/bamcoverage/meta.yml @@ -0,0 +1,129 @@ +name: deeptools_bamcoverage +description: This tool takes an alignment of reads or fragments as input (BAM + file) and generates a coverage track (bigWig or bedGraph) as output. +keywords: + - coverage + - depth + - track +tools: + - deeptools: + description: A set of user-friendly tools for normalization and + visualization of deep-sequencing data + homepage: https://deeptools.readthedocs.io/en/develop/content/tools/bamCoverage.html + documentation: https://deeptools.readthedocs.io/en/develop/content/tools/bamCoverage.html + tool_dev_url: https://github.com/deeptools/deepTools/ + doi: "10.1093/nar/gkw257" + licence: + - "GPL v3" + identifier: biotools:deeptools +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input: + type: file + description: BAM/CRAM file + pattern: "*.{bam,cram}" + ontologies: [] + - input_index: + type: file + description: BAM/CRAM index file + pattern: "*.{bai,crai}" + ontologies: [] + - fasta: + type: file + description: Reference file the CRAM file was created with (required with + CRAM input) + pattern: "*.{fasta,fa}" + ontologies: [] + - fasta_fai: + type: file + description: Index of the reference file (optional, but recommended) + pattern: "*.{fai}" + ontologies: [] + - - meta2: + type: map + description: | + Groovy Map containing blacklist metadata + e.g. [ id:'blacklist' ] + - blacklist: + type: file + description: BED/GTF file containing regions to exclude from analysis + pattern: "*.{bed,gtf}" + ontologies: + - edam: "http://edamontology.org/data_3002" + - edam: "http://edamontology.org/format_3003" + optional: true +output: + bigwig: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.bigWig": + type: file + description: BigWig file + pattern: "*.bigWig" + ontologies: [] + bedgraph: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.bedgraph": + type: file + description: Bedgraph file + pattern: "*.bedgraph" + ontologies: [] + versions_deeptools: + - - ${task.process}: + type: string + description: The name of the process + - deeptools: + type: string + description: The name of the tool + - bamCoverage --version | sed "s/bamCoverage //g": + type: eval + description: The expression to obtain the version of the tool + versions_samtools: + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - samtools version | sed '1!d;s/.* //': + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - deeptools: + type: string + description: The name of the tool + - bamCoverage --version | sed "s/bamCoverage //g": + type: eval + description: The expression to obtain the version of the tool + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - samtools version | sed '1!d;s/.* //': + type: eval + description: The expression to obtain the version of the tool +authors: + - "@FriederikeHanssen" + - "@SusiJo" + - "@JoseEspinosa" +maintainers: + - "@FriederikeHanssen" + - "@SusiJo" + - "@JoseEspinosa" diff --git a/modules/nf-core/deeptools/bamcoverage/tests/main.nf.test b/modules/nf-core/deeptools/bamcoverage/tests/main.nf.test new file mode 100644 index 0000000..2857e33 --- /dev/null +++ b/modules/nf-core/deeptools/bamcoverage/tests/main.nf.test @@ -0,0 +1,134 @@ +nextflow_process { + + name "Test Process DEEPTOOLS_BAMCOVERAGE" + script "../main.nf" + process "DEEPTOOLS_BAMCOVERAGE" + + tag "modules" + tag "modules_nfcore" + tag "deeptools" + tag "deeptools/bamcoverage" + + test("homo_sampiens - bam") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ] + input[1] = [] + input[2] = [] + input[3] = [ + [ id:'no_blacklist' ], + [] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.bigwig, + process.out.findAll { key, val -> key.startsWith('version') }) + .match() + } + ) + } + } + + test("homo_sampiens - cram - fasta - fai ") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + '/genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + file(params.modules_testdata_base_path + '/genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram.crai', checkIfExists: true) + ] + input[1] = [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) ] + input[2] = [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) ] + input[3] = [ + [ id:'no_blacklist' ], + [] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.bigwig, + process.out.findAll { key, val -> key.startsWith('version') }) + .match() + } + ) + } + } + + test("homo_sampiens - cram - fasta") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + '/genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true), + file(params.modules_testdata_base_path + '/genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram.crai', checkIfExists: true) + ] + input[1] = [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) ] + input[2] = [] + input[3] = [ + [ id:'no_blacklist' ], + [] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.bigwig, + process.out.findAll { key, val -> key.startsWith('version') }) + .match() + } + ) + } + } + + test("homo_sampiens - bam - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ] + input[1] = [] + input[2] = [] + input[3] = [ + [ id:'no_blacklist' ], + [] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/deeptools/bamcoverage/tests/main.nf.test.snap b/modules/nf-core/deeptools/bamcoverage/tests/main.nf.test.snap new file mode 100644 index 0000000..4644d85 --- /dev/null +++ b/modules/nf-core/deeptools/bamcoverage/tests/main.nf.test.snap @@ -0,0 +1,167 @@ +{ + "homo_sampiens - bam": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.bigWig:md5,95fe9383a9e6c02aea6b785cf074274f" + ] + ], + { + "versions_deeptools": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "deeptools", + "3.5.6" + ] + ], + "versions_samtools": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "samtools", + "1.20" + ] + ] + } + ], + "timestamp": "2026-02-17T08:59:23.67581", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "homo_sampiens - cram - fasta - fai ": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.bigWig:md5,95fe9383a9e6c02aea6b785cf074274f" + ] + ], + { + "versions_deeptools": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "deeptools", + "3.5.6" + ] + ], + "versions_samtools": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "samtools", + "1.20" + ] + ] + } + ], + "timestamp": "2026-02-17T08:59:31.818598", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "homo_sampiens - bam - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.bigWig:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + + ], + "2": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "deeptools", + "3.5.6" + ] + ], + "3": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "samtools", + "1.20" + ] + ], + "bedgraph": [ + + ], + "bigwig": [ + [ + { + "id": "test", + "single_end": false + }, + "test.bigWig:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_deeptools": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "deeptools", + "3.5.6" + ] + ], + "versions_samtools": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "samtools", + "1.20" + ] + ] + } + ], + "timestamp": "2026-02-17T08:59:45.595332", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "homo_sampiens - cram - fasta": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.bigWig:md5,95fe9383a9e6c02aea6b785cf074274f" + ] + ], + { + "versions_deeptools": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "deeptools", + "3.5.6" + ] + ], + "versions_samtools": [ + [ + "DEEPTOOLS_BAMCOVERAGE", + "samtools", + "1.20" + ] + ] + } + ], + "timestamp": "2026-02-17T08:59:38.037745", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt new file mode 100644 index 0000000..7770ccd --- /dev/null +++ b/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt @@ -0,0 +1,822 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-64: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 +md5: a9f577daf3de00bca7c3c76c0ecbd1de +depends: +- __glibc >=2.17,<3.0.a0 +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28948 +timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda +sha256: d88aa7ae766cf584e180996e92fef2aa7d8e0a0a5ab1d4d49c32390c1b5fff31 +md5: dcdc58c15961dbf17a0621312b01f5cb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: LGPL-2.1-or-later +license_family: GPL +size: 584660 +timestamp: 1768327524772 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 +md5: d2ffd7602c02f2b316fd921d39876885 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 260182 +timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda +sha256: 06525fa0c4e4f56e771a3b986d0fdf0f0fc5a3270830ee47e127a5105bde1b9a +md5: bb6c4808bfa69d6f7f6b07e5846ced37 +depends: +- __glibc >=2.17,<3.0.a0 +- fontconfig >=2.15.0,<3.0a0 +- fonts-conda-ecosystem +- icu >=78.1,<79.0a0 +- libexpat >=2.7.3,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libglib >=2.86.3,<3.0a0 +- libpng >=1.6.53,<1.7.0a0 +- libstdcxx >=14 +- libxcb >=1.17.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pixman >=0.46.4,<1.0a0 +- xorg-libice >=1.1.2,<2.0a0 +- xorg-libsm >=1.2.6,<2.0a0 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: LGPL-2.1-only or MPL-1.1 +size: 989514 +timestamp: 1766415934926 +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c +md5: c9f6a4b12229f7331f79c9a00dd6e240 +depends: +- font-ttf-dejavu-sans-mono +- fontconfig +- openjdk >=8.0.144 +- perl +license: GPL >=3 +size: 11664291 +timestamp: 1677946722445 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +sha256: aa4a44dba97151221100a637c7f4bde619567afade9c0265f8e1c8eed8d7bd8c +md5: 867127763fbe935bab59815b6e0b7b5c +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 270705 +timestamp: 1771382710863 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 +md5: fee5683a3f04bd15cbd8318b096a27ab +depends: +- fonts-conda-forge +license: BSD-3-Clause +license_family: BSD +size: 3667 +timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda +sha256: aac402a8298f0c0cc528664249170372ef6b37ac39fdc92b40601a6aed1e32ff +md5: 3bf7b9fd5a7136126e0234db4b87c8b6 +depends: +- libgcc-ng >=12 +license: MIT +license_family: MIT +size: 77248 +timestamp: 1712692454246 +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda +sha256: 25ba37da5c39697a77fce2c9a15e48cf0a84f1464ad2aafbe53d8357a9f6cc8c +md5: 2cd94587f3a401ae05e03a6caf09539d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: LGPL-2.0-or-later +license_family: LGPL +size: 99596 +timestamp: 1755102025473 +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda +sha256: 477f2c553f72165020d3c56740ba354be916c2f0b76fd9f535e83d698277d5ec +md5: 14470902326beee192e33719a2e8bb7f +depends: +- __glibc >=2.17,<3.0.a0 +- cairo >=1.18.4,<2.0a0 +- graphite2 >=1.3.14,<2.0a0 +- icu >=78.3,<79.0a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.2 +- libfreetype6 >=2.14.2 +- libgcc >=14 +- libglib >=2.86.4,<3.0a0 +- libstdcxx >=14 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 2384060 +timestamp: 1774276284520 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a +md5: c80d8a3b84358cb967fa81e7075fbc8a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12723451 +timestamp: 1773822285671 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda +sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 +md5: b38117a3c920364aff79f870c984b4a3 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: LGPL-2.1-or-later +size: 134088 +timestamp: 1754905959823 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda +sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 +md5: fb53fb07ce46a575c5d004bbc96032c2 +depends: +- __glibc >=2.17,<3.0.a0 +- keyutils >=1.6.3,<2.0a0 +- libedit >=3.1.20250104,<3.2.0a0 +- libedit >=3.1.20250104,<4.0a0 +- libgcc >=14 +- libstdcxx >=14 +- openssl >=3.5.5,<4.0a0 +license: MIT +license_family: MIT +size: 1386730 +timestamp: 1769769569681 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +sha256: 836ec4b895352110335b9fdcfa83a8dcdbe6c5fb7c06c4929130600caea91c0a +md5: 6f2e2c8f58160147c4d1c6f4c14cbac4 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 249959 +timestamp: 1768184673131 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +sha256: f84cb54782f7e9cea95e810ea8fef186e0652d0fa73d3009914fa2c1262594e1 +md5: a752488c68f2e7c456bcbd8f16eec275 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 261513 +timestamp: 1773113328888 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda +sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c +md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 +depends: +- __glibc >=2.17,<3.0.a0 +- krb5 >=1.22.2,<1.23.0a0 +- libgcc >=14 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +license: Apache-2.0 +license_family: Apache +size: 4518030 +timestamp: 1770902209173 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 +md5: 6c77a605a7a689d17d4819c0f8ac9a00 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 73490 +timestamp: 1761979956660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda +sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 +md5: c277e0a4d549b03ac1e9d6cbbe3d017b +depends: +- ncurses +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- ncurses >=6.5,<7.0a0 +license: BSD-2-Clause +license_family: BSD +size: 134676 +timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 +md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76798 +timestamp: 1771259418166 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 +md5: a360c33a5abe61c07959e449fa1453eb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 58592 +timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 +md5: e289f3d17880e44b633ba911d57a321b +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8049 +timestamp: 1774298163029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d +md5: fb16b4b69e3f1dcfe79d80db8fd0c55d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 384575 +timestamp: 1774298162622 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 +md5: 0aa00f03f9e39fb9876085dee11a85d4 +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1041788 +timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 +md5: d5e96b1ed75ca01906b3d2469b4ce493 +depends: +- libgcc 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27526 +timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda +sha256: a27e44168a1240b15659888ce0d9b938ed4bdb49e9ea68a7c1ff27bcea8b55ce +md5: bb26456332b07f68bf3b7622ed71c0da +depends: +- __glibc >=2.17,<3.0.a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- libiconv >=1.18,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pcre2 >=10.47,<10.48.0a0 +constrains: +- glib 2.86.4 *_1 +license: LGPL-2.1-or-later +size: 4398701 +timestamp: 1771863239578 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 +md5: 239c5e9546c38a1e884d69effcf4c882 +depends: +- __glibc >=2.17,<3.0.a0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 603262 +timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda +sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f +md5: 915f5995e94f60e9a4826e0b0920ee88 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: LGPL-2.1-only +size: 790176 +timestamp: 1754908768807 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32 +md5: 8397539e3a0bbd1695584fb4f927485a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 633710 +timestamp: 1762094827865 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb +md5: c7c83eecbb72d88b940c249af56c8b17 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 113207 +timestamp: 1768752626120 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +sha256: 36ade759122cdf0f16e2a2562a19746d96cf9c863ffaa812f2f5071ebbe9c03c +md5: 5f13ffc7d30ffec87864e678df9957b4 +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 317669 +timestamp: 1770691470744 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e +md5: 1b08cd684f34175e4514474793d44bcb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc 15.2.0 he0feb66_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5852330 +timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 +md5: cd5a90476766d53e901500df9215e927 +depends: +- __glibc >=2.17,<3.0.a0 +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 435273 +timestamp: 1762022005702 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee +md5: db409b7c1720428638e7c0d509d3e1b5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 40311 +timestamp: 1766271528534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b +md5: aea31d2e5b1091feca96fcfe945c3cf9 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 429011 +timestamp: 1752159441324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa +md5: 92ed62436b625154323d40d5f2f11dd7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 395888 +timestamp: 1727278577118 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda +sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c +md5: 5aa797f8787fe7a17d1b0821485b5adc +depends: +- libgcc-ng >=12 +license: LGPL-2.1-or-later +size: 100393 +timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 +md5: d87ff7921124eccd67248aa483c23fec +depends: +- __glibc >=2.17,<3.0.a0 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 63629 +timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 +md5: 47e340acb35de30501a76c7c799c41d7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 891641 +timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda +sha256: 3825a4c84676a8a5cc23b397a2911e4efa4a805daf2af764153bd904e142ec41 +md5: a41092b0177362dbe5eb2a18501e86c0 +depends: +- xorg-libx11 +- xorg-libxext +- xorg-libxi +- xorg-libxrender +- xorg-libxtst +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- xorg-libxrender >=0.9.12,<0.10.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- giflib >=5.2.2,<5.3.0a0 +- xorg-libxrandr >=1.5.5,<2.0a0 +- harfbuzz >=12.3.2 +- fontconfig >=2.17.1,<3.0a0 +- fonts-conda-ecosystem +- xorg-libxtst >=1.2.5,<2.0a0 +- xorg-libxi >=1.8.2,<2.0a0 +- lcms2 >=2.18,<3.0a0 +- alsa-lib >=1.2.15.3,<1.3.0a0 +- libpng >=1.6.55,<1.7.0a0 +- xorg-libxt >=1.3.1,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- xorg-libxext >=1.3.7,<2.0a0 +- xorg-libx11 >=1.8.13,<2.0a0 +- libcups >=2.3.3,<2.4.0a0 +license: GPL-2.0-or-later WITH Classpath-exception-2.0 +license_family: GPL +size: 122465031 +timestamp: 1771443671180 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c +md5: f61eb8cd60ff9057122a3d338b99c00f +depends: +- __glibc >=2.17,<3.0.a0 +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3164551 +timestamp: 1769555830639 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda +sha256: 5e6f7d161356fefd981948bea5139c5aa0436767751a6930cb1ca801ebb113ff +md5: 7a3bff861a6583f1889021facefc08b1 +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 1222481 +timestamp: 1763655398280 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda +build_number: 7 +sha256: 9ec32b6936b0e37bcb0ed34f22ec3116e75b3c0964f9f50ecea5f58734ed6ce9 +md5: f2cfec9406850991f4e3d960cc9e3321 +depends: +- libgcc-ng >=12 +- libxcrypt >=4.4.36 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 13344463 +timestamp: 1703310653947 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda +sha256: 43d37bc9ca3b257c5dd7bf76a8426addbdec381f6786ff441dc90b1a49143b6a +md5: c01af13bdc553d1a8fbfff6e8db075f0 +depends: +- libgcc >=14 +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +license: MIT +license_family: MIT +size: 450960 +timestamp: 1754665235234 +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d +md5: f2c23a77b25efcad57d377b34bd84941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 593603 +timestamp: 1769710381284 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 +md5: b3c17d95b5a10c6e64a21fa17573e70e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 8252 +timestamp: 1726802366959 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda +sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b +md5: fb901ff28063514abb6046c9ec2c4a45 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 58628 +timestamp: 1734227592886 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda +sha256: 277841c43a39f738927145930ff963c5ce4c4dacf66637a3d95d802a64173250 +md5: 1c74ff8c35dcadf952a16f752ca5aa49 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libuuid >=2.38.1,<3.0a0 +- xorg-libice >=1.1.2,<2.0a0 +license: MIT +license_family: MIT +size: 27590 +timestamp: 1741896361728 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda +sha256: 516d4060139dbb4de49a4dcdc6317a9353fb39ebd47789c14e6fe52de0deee42 +md5: 861fb6ccbc677bb9a9fb2468430b9c6a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libxcb >=1.17.0,<2.0a0 +license: MIT +license_family: MIT +size: 839652 +timestamp: 1770819209719 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b +md5: b2895afaf55bf96a8c8282a2e47a5de0 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 15321 +timestamp: 1762976464266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 +md5: 1dafce8548e38671bea82e3f5c6ce22f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 20591 +timestamp: 1762976546182 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda +sha256: 79c60fc6acfd3d713d6340d3b4e296836a0f8c51602327b32794625826bd052f +md5: 34e54f03dfea3e7a2dcf1453a85f1085 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 50326 +timestamp: 1769445253162 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda +sha256: 83c4c99d60b8784a611351220452a0a85b080668188dce5dfa394b723d7b64f4 +md5: ba231da7fccf9ea1e768caf5c7099b84 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 20071 +timestamp: 1759282564045 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda +sha256: 1a724b47d98d7880f26da40e45f01728e7638e6ec69f35a3e11f92acd05f9e7a +md5: 17dcc85db3c7886650b8908b183d6876 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxfixes >=6.0.1,<7.0a0 +license: MIT +license_family: MIT +size: 47179 +timestamp: 1727799254088 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda +sha256: 80ed047a5cb30632c3dc5804c7716131d767089f65877813d4ae855ee5c9d343 +md5: e192019153591938acf7322b6459d36e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: MIT +license_family: MIT +size: 30456 +timestamp: 1769445263457 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda +sha256: 044c7b3153c224c6cedd4484dd91b389d2d7fd9c776ad0f4a34f099b3389f4a1 +md5: 96d57aba173e878a2089d5638016dc5e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 33005 +timestamp: 1734229037766 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda +sha256: a8afba4a55b7b530eb5c8ad89737d60d60bc151a03fbef7a2182461256953f0e +md5: 279b0de5f6ba95457190a1c459a64e31 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libice >=1.1.1,<2.0a0 +- xorg-libsm >=1.2.4,<2.0a0 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 379686 +timestamp: 1731860547604 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda +sha256: 752fdaac5d58ed863bbf685bb6f98092fe1a488ea8ebb7ed7b606ccfce08637a +md5: 7bbe9a0cc0df0ac5f5a8ad6d6a11af2f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxi >=1.7.10,<2.0a0 +license: MIT +license_family: MIT +size: 32808 +timestamp: 1727964811275 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 +md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 +depends: +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 601375 +timestamp: 1764777111296 diff --git a/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt new file mode 100644 index 0000000..cdc434c --- /dev/null +++ b/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt @@ -0,0 +1,769 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-aarch64: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 +md5: 468fd3bb9e1f671d36c2cbc677e56f1d +depends: +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28926 +timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda +sha256: ea2233e2db9908c2e5f29d3ca420a546b4583253f4f70abb5494cdd676866d42 +md5: 4a98cbc4ade694520227402ff8880630 +depends: +- libgcc >=14 +license: LGPL-2.1-or-later +license_family: GPL +size: 615729 +timestamp: 1768327548407 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c +md5: 840d8fc0d7b3209be93080bc20e07f2d +depends: +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 192412 +timestamp: 1771350241232 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda +sha256: 675db823f3d6fb6bf747fab3b0170ba99b269a07cf6df1e49fff2f9972be9cd1 +md5: 043c13ed3a18396994be9b4fab6572ad +depends: +- fontconfig >=2.15.0,<3.0a0 +- fonts-conda-ecosystem +- icu >=78.1,<79.0a0 +- libexpat >=2.7.3,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libglib >=2.86.3,<3.0a0 +- libpng >=1.6.53,<1.7.0a0 +- libstdcxx >=14 +- libxcb >=1.17.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pixman >=0.46.4,<1.0a0 +- xorg-libice >=1.1.2,<2.0a0 +- xorg-libsm >=1.2.6,<2.0a0 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: LGPL-2.1-only or MPL-1.1 +size: 927045 +timestamp: 1766416003626 +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c +md5: c9f6a4b12229f7331f79c9a00dd6e240 +depends: +- font-ttf-dejavu-sans-mono +- fontconfig +- openjdk >=8.0.144 +- perl +license: GPL >=3 +size: 11664291 +timestamp: 1677946722445 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +sha256: 835aff8615dd8d8fff377679710ce81b8a2c47b6404e21a92fb349fda193a15c +md5: 0fed1ff55f4938a65907f3ecf62609db +depends: +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 279044 +timestamp: 1771382728182 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 +md5: fee5683a3f04bd15cbd8318b096a27ab +depends: +- fonts-conda-forge +license: BSD-3-Clause +license_family: BSD +size: 3667 +timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda +sha256: a79dc3bd54c4fb1f249942ee2d5b601a76ecf9614774a4cff9af49adfa458db2 +md5: 2f809afaf0ba1ea4135dce158169efac +depends: +- libgcc-ng >=12 +license: MIT +license_family: MIT +size: 82124 +timestamp: 1712692444545 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda +sha256: c9b1781fe329e0b77c5addd741e58600f50bef39321cae75eba72f2f381374b7 +md5: 4aa540e9541cc9d6581ab23ff2043f13 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: LGPL-2.0-or-later +license_family: LGPL +size: 102400 +timestamp: 1755102000043 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda +sha256: e22f485fddaaea3ff4b6cae98e0197b9dccd2ed2770337ad6ff38a92afe04e59 +md5: 05d65a2cf410adc331c9ea61f59f1013 +depends: +- cairo >=1.18.4,<2.0a0 +- graphite2 >=1.3.14,<2.0a0 +- icu >=78.3,<79.0a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.2 +- libfreetype6 >=2.14.2 +- libgcc >=14 +- libglib >=2.86.4,<3.0a0 +- libstdcxx >=14 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 2345732 +timestamp: 1774281448329 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +sha256: 49ba6aed2c6b482bb0ba41078057555d29764299bc947b990708617712ef6406 +md5: 546da38c2fa9efacf203e2ad3f987c59 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12837286 +timestamp: 1773822650615 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda +sha256: 5ce830ca274b67de11a7075430a72020c1fb7d486161a82839be15c2b84e9988 +md5: e7df0aab10b9cbb73ab2a467ebfaf8c7 +depends: +- libgcc >=13 +license: LGPL-2.1-or-later +size: 129048 +timestamp: 1754906002667 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda +sha256: b53999d888dda53c506b264e8c02b5f5c8e022c781eda0718f007339e6bc90ba +md5: d9ca108bd680ea86a963104b6b3e95ca +depends: +- keyutils >=1.6.3,<2.0a0 +- libedit >=3.1.20250104,<3.2.0a0 +- libedit >=3.1.20250104,<4.0a0 +- libgcc >=14 +- libstdcxx >=14 +- openssl >=3.5.5,<4.0a0 +license: MIT +license_family: MIT +size: 1517436 +timestamp: 1769773395215 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +sha256: 379ef5e91a587137391a6149755d0e929f1a007d2dcb211318ac670a46c8596f +md5: bb960f01525b5e001608afef9d47b79c +depends: +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 293039 +timestamp: 1768184778398 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +sha256: 8957fd460c1c132c8031f65fd5f56ec3807fd71b7cab2c5e2b0937b13404ab36 +md5: d13423b06447113a90b5b1366d4da171 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 240444 +timestamp: 1773114901155 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda +sha256: 41b04f995c9f63af8c4065a35931e46cbc2fdd6b9bf7e4c19f90d53cbb2bc8e5 +md5: 67828c963b17db7dc989fe5d509ef04a +depends: +- krb5 >=1.22.2,<1.23.0a0 +- libgcc >=14 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +license: Apache-2.0 +license_family: Apache +size: 4553739 +timestamp: 1770903929794 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 +md5: a9138815598fe6b91a1d6782ca657b0c +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 71117 +timestamp: 1761979776756 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda +sha256: c0b27546aa3a23d47919226b3a1635fccdb4f24b94e72e206a751b33f46fd8d6 +md5: fb640d776fc92b682a14e001980825b1 +depends: +- ncurses +- libgcc >=13 +- ncurses >=6.5,<7.0a0 +license: BSD-2-Clause +license_family: BSD +size: 148125 +timestamp: 1738479808948 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 +md5: 57f3b3da02a50a1be2a6fe847515417d +depends: +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76564 +timestamp: 1771259530958 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 +md5: 2f364feefb6a7c00423e80dcb12db62a +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 55952 +timestamp: 1769456078358 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a +md5: a229e22d4d8814a07702b0919d8e6701 +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8125 +timestamp: 1774301094057 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c +md5: b99ed99e42dafb27889483b3098cace7 +depends: +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 422941 +timestamp: 1774301093473 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +sha256: 43df385bedc1cab11993c4369e1f3b04b4ca5d0ea16cba6a0e7f18dbc129fcc9 +md5: 552567ea2b61e3a3035759b2fdb3f9a6 +depends: +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 622900 +timestamp: 1771378128706 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +sha256: 83bb0415f59634dccfa8335d4163d1f6db00a27b36666736f9842b650b92cf2f +md5: 4feebd0fbf61075a1a9c2e9b3936c257 +depends: +- libgcc 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27568 +timestamp: 1771378136019 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda +sha256: afc503dbd04a5bf2709aa9d8318a03a8c4edb389f661ff280c3494bfef4341ec +md5: 4ac4372fc4d7f20630a91314cdac8afd +depends: +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- libiconv >=1.18,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pcre2 >=10.47,<10.48.0a0 +constrains: +- glib 2.86.4 *_1 +license: LGPL-2.1-or-later +size: 4512186 +timestamp: 1771863220969 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +sha256: fc716f11a6a8525e27a5d332ef6a689210b0d2a4dd1133edc0f530659aa9faa6 +md5: 4faa39bf919939602e594253bd673958 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 588060 +timestamp: 1771378040807 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda +sha256: 1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9 +md5: 5a86bf847b9b926f3a4f203339748d78 +depends: +- libgcc >=14 +license: LGPL-2.1-only +size: 791226 +timestamp: 1754910975665 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +sha256: 84064c7c53a64291a585d7215fe95ec42df74203a5bf7615d33d49a3b0f08bb6 +md5: 5109d7f837a3dfdf5c60f60e311b041f +depends: +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 691818 +timestamp: 1762094728337 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +sha256: 843c46e20519651a3e357a8928352b16c5b94f4cd3d5481acc48be2e93e8f6a3 +md5: 96944e3c92386a12755b94619bae0b35 +depends: +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 125916 +timestamp: 1768754941722 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +sha256: c7378c6b79de4d571d00ad1caf0a4c19d43c9c94077a761abb6ead44d891f907 +md5: be4088903b94ea297975689b3c3aeb27 +depends: +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 340156 +timestamp: 1770691477245 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +sha256: 31fdb9ffafad106a213192d8319b9f810e05abca9c5436b60e507afb35a6bc40 +md5: f56573d05e3b735cb03efeb64a15f388 +depends: +- libgcc 15.2.0 h8acb6b2_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5541411 +timestamp: 1771378162499 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 +md5: 8c6fd84f9c87ac00636007c6131e457d +depends: +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 488407 +timestamp: 1762022048105 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 +md5: cf2861212053d05f27ec49c3784ff8bb +depends: +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 43453 +timestamp: 1766271546875 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 +md5: 24e92d0942c799db387f5c9d7b81f1af +depends: +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 359496 +timestamp: 1752160685488 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b +md5: cd14ee5cca2464a425b1dbfc24d90db2 +depends: +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 397493 +timestamp: 1727280745441 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda +sha256: 6b46c397644091b8a26a3048636d10b989b1bf266d4be5e9474bf763f828f41f +md5: b4df5d7d4b63579d081fd3a4cf99740e +depends: +- libgcc-ng >=12 +license: LGPL-2.1-or-later +size: 114269 +timestamp: 1702724369203 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f +md5: 502006882cf5461adced436e410046d1 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 69833 +timestamp: 1774072605429 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468 +md5: 182afabe009dc78d8b73100255ee6868 +depends: +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 926034 +timestamp: 1738196018799 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda +sha256: 6fd2c872b275fa5d42a61a4b6dc28a819cde29f9048adb547363597432e0720e +md5: 27fdd5d67e235c20d23b2d66406497d3 +depends: +- xorg-libx11 +- xorg-libxext +- xorg-libxi +- xorg-libxrender +- xorg-libxtst +- libstdcxx >=14 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +- xorg-libxtst >=1.2.5,<2.0a0 +- libpng >=1.6.55,<1.7.0a0 +- alsa-lib >=1.2.15.3,<1.3.0a0 +- xorg-libx11 >=1.8.13,<2.0a0 +- xorg-libxi >=1.8.2,<2.0a0 +- xorg-libxrandr >=1.5.5,<2.0a0 +- lcms2 >=2.18,<3.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +- libcups >=2.3.3,<2.4.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- harfbuzz >=12.3.2 +- xorg-libxext >=1.3.7,<2.0a0 +- giflib >=5.2.2,<5.3.0a0 +- xorg-libxt >=1.3.1,<2.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- fontconfig >=2.17.1,<3.0a0 +- fonts-conda-ecosystem +license: GPL-2.0-or-later WITH Classpath-exception-2.0 +license_family: GPL +size: 106988620 +timestamp: 1771443741031 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +sha256: 7f8048c0e75b2620254218d72b4ae7f14136f1981c5eb555ef61645a9344505f +md5: 25f5885f11e8b1f075bccf4a2da91c60 +depends: +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3692030 +timestamp: 1769557678657 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda +sha256: 04df2cee95feba440387f33f878e9f655521e69f4be33a0cd637f07d3d81f0f9 +md5: 1a30c42e32ca0ea216bd0bfe6f842f0b +depends: +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 1166552 +timestamp: 1763655534263 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda +build_number: 7 +sha256: d78296134263b5bf476cad838ded65451e7162db756f9997c5d06b08122572ed +md5: 17d019cb2a6c72073c344e98e40dfd61 +depends: +- libgcc-ng >=12 +- libxcrypt >=4.4.36 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 13338804 +timestamp: 1703310557094 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda +sha256: e6b0846a998f2263629cfeac7bca73565c35af13251969f45d385db537a514e4 +md5: 1587081d537bd4ae77d1c0635d465ba5 +depends: +- libgcc >=14 +- libstdcxx >=14 +- libgcc >=14 +license: MIT +license_family: MIT +size: 357913 +timestamp: 1754665583353 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 +md5: ab7288cc39545556d1bc5e71ab2df9a9 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 636733 +timestamp: 1769712412683 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba +md5: bb5a90c93e3bac3d5690acf76b4a6386 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 8342 +timestamp: 1726803319942 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda +sha256: a2ba1864403c7eb4194dacbfe2777acf3d596feae43aada8d1b478617ce45031 +md5: c8d8ec3e00cd0fd8a231789b91a7c5b7 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 60433 +timestamp: 1734229908988 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda +sha256: b86a819cd16f90c01d9d81892155126d01555a20dabd5f3091da59d6309afd0a +md5: 2d1409c50882819cb1af2de82e2b7208 +depends: +- libgcc >=13 +- libuuid >=2.38.1,<3.0a0 +- xorg-libice >=1.1.2,<2.0a0 +license: MIT +license_family: MIT +size: 28701 +timestamp: 1741897678254 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda +sha256: cf886160e2ff580d77f7eb8ec1a77c41c2c5b05343e329bc35f0ddf40b8d92ab +md5: 22dd10425ef181e80e130db50675d615 +depends: +- libgcc >=14 +- libxcb >=1.17.0,<2.0a0 +license: MIT +license_family: MIT +size: 869058 +timestamp: 1770819244991 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 +md5: 1c246e1105000c3660558459e2fd6d43 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 16317 +timestamp: 1762977521691 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1 +md5: bff06dcde4a707339d66d45d96ceb2e2 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 21039 +timestamp: 1762979038025 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda +sha256: db2188bc0d844d4e9747bac7f6c1d067e390bd769c5ad897c93f1df759dc5dba +md5: fb42b683034619915863d68dd9df03a3 +depends: +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 52409 +timestamp: 1769446753771 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda +sha256: 8cb9c88e25c57e47419e98f04f9ef3154ad96b9f858c88c570c7b91216a64d0e +md5: e8b4056544341daf1d415eaeae7a040c +depends: +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 20704 +timestamp: 1759284028146 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda +sha256: 7b587407ecb9ccd2bbaf0fb94c5dbdde4d015346df063e9502dc0ce2b682fb5e +md5: eeee3bdb31c6acde2b81ad1b8c287087 +depends: +- libgcc >=13 +- xorg-libx11 >=1.8.9,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxfixes >=6.0.1,<7.0a0 +license: MIT +license_family: MIT +size: 48197 +timestamp: 1727801059062 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda +sha256: 9f5196665a8d72f4f119c40dcc4bafeb0b540b102cc7b8b299c2abf599e7919f +md5: 1f64c613f0b8d67e9fb0e165d898fb6b +depends: +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: MIT +license_family: MIT +size: 31122 +timestamp: 1769445286951 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda +sha256: ffd77ee860c9635a28cfda46163dcfe9224dc6248c62404c544ae6b564a0be1f +md5: ae2c2dd0e2d38d249887727db2af960e +depends: +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 33649 +timestamp: 1734229123157 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda +sha256: 7c109792b60720809a580612aba7f8eb2a0bd425b9fc078748a9d6ffc97cbfa8 +md5: a9e4852c8e0b68ee783e7240030b696f +depends: +- libgcc >=13 +- xorg-libice >=1.1.1,<2.0a0 +- xorg-libsm >=1.2.4,<2.0a0 +- xorg-libx11 >=1.8.9,<2.0a0 +license: MIT +license_family: MIT +size: 384752 +timestamp: 1731860572314 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda +sha256: 6eaffce5a34fc0a16a21ddeaefb597e792a263b1b0c387c1ce46b0a967d558e1 +md5: c05698071b5c8e0da82a282085845860 +depends: +- libgcc >=13 +- xorg-libx11 >=1.8.9,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxi >=1.7.10,<2.0a0 +license: MIT +license_family: MIT +size: 33786 +timestamp: 1727964907993 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 +md5: c3655f82dcea2aa179b291e7099c1fcc +depends: +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 614429 +timestamp: 1764777145593 diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml new file mode 100644 index 0000000..f9f54ee --- /dev/null +++ b/modules/nf-core/fastqc/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::fastqc=0.12.1 diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf new file mode 100644 index 0000000..1085126 --- /dev/null +++ b/modules/nf-core/fastqc/main.nf @@ -0,0 +1,57 @@ +process FASTQC { + tag "${meta.id}" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' + : 'quay.io/biocontainers/fastqc:0.12.1--hdfd78af_0'}" + + input: + tuple val(meta), path(reads, stageAs: '?/*') + + output: + tuple val(meta), path("*.html"), emit: html + tuple val(meta), path("*.zip"), emit: zip + tuple val("${task.process}"), val('fastqc'), eval('fastqc --version | sed "/FastQC v/!d; s/.*v//"'), emit: versions_fastqc, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + // Make list of old name and new name pairs to use for renaming in the bash while loop + def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[reads, "${prefix}.${reads.extension}"]] : reads.withIndex().collect { entry, index -> [entry, "${prefix}_${index + 1}.${entry.extension}"] } + def rename_to = old_new_pairs*.join(' ').join(' ') + def renamed_files = old_new_pairs.collect { _old_name, new_name -> new_name }.join(' ') + + // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) + // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 + // Dividing the task.memory by task.cpus allows to stick to requested amount of RAM in the label + def memory_in_mb = task.memory + ? (task.memory.toUnit('MB') / task.cpus).intValue() + : null + // FastQC memory value allowed range (100 - 10000) + def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) + def fastqc_memory_arg = fastqc_memory ? "--memory ${fastqc_memory}" : '' + + """ + printf "%s %s\\n" ${rename_to} | while read old_name new_name; do + [ -f "\${new_name}" ] || ln -s \$old_name \$new_name + done + + fastqc \\ + ${args} \\ + --threads ${task.cpus} \\ + ${fastqc_memory_arg} \\ + ${renamed_files} + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.html + touch ${prefix}.zip + """ +} diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml new file mode 100644 index 0000000..2f6cfef --- /dev/null +++ b/modules/nf-core/fastqc/meta.yml @@ -0,0 +1,111 @@ +name: fastqc +description: Run FastQC on sequenced reads +keywords: + - quality control + - qc + - adapters + - fastq +tools: + - fastqc: + description: | + FastQC gives general quality metrics about your reads. + It provides information about the quality score distribution + across your reads, the per base sequence content (%A/C/G/T). + + You get information about adapter contamination and other + overrepresented sequences. + homepage: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/ + documentation: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/ + licence: ["GPL-2.0-only"] + identifier: biotools:fastqc +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - reads: + type: file + description: | + List of input FastQ files of size 1 and 2 for single-end and paired-end data, + respectively. + ontologies: [] +output: + html: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.html": + type: file + description: FastQC report + pattern: "*_{fastqc.html}" + ontologies: [] + zip: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.zip": + type: file + description: FastQC report archive + pattern: "*_{fastqc.zip}" + ontologies: [] + versions_fastqc: + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool + +topics: + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool +authors: + - "@drpatelh" + - "@grst" + - "@ewels" + - "@FelixKrueger" +maintainers: + - "@drpatelh" + - "@grst" + - "@ewels" + - "@FelixKrueger" +containers: + docker: + linux/arm64: + name: community.wave.seqera.io/library/fastqc:0.12.1--e455e32f745abe68 + build_id: bd-e455e32f745abe68_1 + scan_id: sc-f102f736465af88c_1 + linux/amd64: + name: community.wave.seqera.io/library/fastqc:0.12.1--5cb1a2fa2f18c7c2 + build_id: bd-5cb1a2fa2f18c7c2_1 + scan_id: sc-0c0466326b6b77d2_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--5c4bd442468d75dd + build_id: bd-5c4bd442468d75dd_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/f2/f20b021476d1d87658820f971ebecc1e8cdbde0f338eb0d9cea2b0a8fc54a54b/data + linux/arm64: + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--127a87fc06499035 + build_id: bd-127a87fc06499035_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/46/46daf2dad0169afd2ae047c3e50ed3776259f664bf07e5e06b045dc23449e994/data + conda: + linux/amd64: + lock_file: modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt + linux/arm64: + lock_file: modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test new file mode 100644 index 0000000..66c44da --- /dev/null +++ b/modules/nf-core/fastqc/tests/main.nf.test @@ -0,0 +1,309 @@ +nextflow_process { + + name "Test Process FASTQC" + script "../main.nf" + process "FASTQC" + + tag "modules" + tag "modules_nfcore" + tag "fastqc" + + test("sarscov2 single-end [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [ id: 'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. + // looks like this:
Mon 2 Oct 2023
test.gz
+ // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } + ) + } + } + + test("sarscov2 paired-end [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } + ) + } + } + + test("sarscov2 interleaved [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } + ) + } + } + + test("sarscov2 paired-end [bam]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } + ) + } + } + + test("sarscov2 multiple [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, + { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, + { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } + ) + } + } + + test("sarscov2 custom_prefix") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'mysample', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } + ) + } + } + + test("sarscov2 single-end [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id: 'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 paired-end [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 interleaved [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 paired-end [bam] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 multiple [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 custom_prefix - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id:'mysample', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap new file mode 100644 index 0000000..c8ee120 --- /dev/null +++ b/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -0,0 +1,476 @@ +{ + "sarscov2 custom_prefix": { + "content": [ + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:39:14.518503" + }, + "sarscov2 single-end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "html": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "zip": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:39:19.309008" + }, + "sarscov2 custom_prefix - stub": { + "content": [ + { + "0": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "html": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "zip": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:39:44.94888" + }, + "sarscov2 interleaved [fastq]": { + "content": [ + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:38:45.168496" + }, + "sarscov2 paired-end [bam]": { + "content": [ + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:38:53.268919" + }, + "sarscov2 multiple [fastq]": { + "content": [ + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:39:05.050305" + }, + "sarscov2 paired-end [fastq]": { + "content": [ + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:38:37.2373" + }, + "sarscov2 paired-end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:39:24.450398" + }, + "sarscov2 multiple [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:39:39.758762" + }, + "sarscov2 single-end [fastq]": { + "content": [ + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:38:29.555068" + }, + "sarscov2 interleaved [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:39:29.193136" + }, + "sarscov2 paired-end [bam] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.10.0" + }, + "timestamp": "2025-10-28T16:39:34.144919" + } +} \ No newline at end of file diff --git a/modules/nf-core/gatk4/markduplicates/environment.yml b/modules/nf-core/gatk4/markduplicates/environment.yml new file mode 100644 index 0000000..4a13c61 --- /dev/null +++ b/modules/nf-core/gatk4/markduplicates/environment.yml @@ -0,0 +1,15 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda + +dependencies: + # renovate: datasource=conda depName=bioconda/gatk4 + - bioconda::gatk4=4.6.2.0 + # renovate: datasource=conda depName=bioconda/gcnvkernel + - bioconda::gcnvkernel=0.9 + # do not update - later htslib versions not compatible with gcnvkernel + - bioconda::htslib=1.21 + # do not update - later samtools versions not compatible with gcnvkernel + - bioconda::samtools=1.21 diff --git a/modules/nf-core/gatk4/markduplicates/main.nf b/modules/nf-core/gatk4/markduplicates/main.nf new file mode 100644 index 0000000..6fd44ea --- /dev/null +++ b/modules/nf-core/gatk4/markduplicates/main.nf @@ -0,0 +1,75 @@ +process GATK4_MARKDUPLICATES { + tag "${meta.id}" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e3/e3d753d93f57969fe76b8628a8dfcd23ef44bccd08c4ced7089c1f94bf47c89f/data' + : 'community.wave.seqera.io/library/gatk4_gcnvkernel_htslib_samtools:d3becb6465454c35'}" + + input: + tuple val(meta), path(bam) + path fasta + path fasta_fai + + output: + tuple val(meta), path("*cram"), emit: cram, optional: true + tuple val(meta), path("*bam"), emit: bam, optional: true + tuple val(meta), path("*.crai"), emit: crai, optional: true + tuple val(meta), path("*.bai"), emit: bai, optional: true + tuple val(meta), path("*.metrics"), emit: metrics + tuple val("${task.process}"), val('gatk4'), eval("gatk --version | sed -n '/GATK.*v/s/.*v//p'"), topic: versions, emit: versions_gatk4 + tuple val("${task.process}"), val('samtools'), eval("samtools version | sed '1!d;s/.* //'"), topic: versions, emit: versions_samtools + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}.bam" + + // If the extension is CRAM, then change it to BAM + prefix_bam = prefix.tokenize('.')[-1] == 'cram' ? "${prefix.substring(0, prefix.lastIndexOf('.'))}.bam" : prefix + + def input_list = bam.collect { bam_ -> "--INPUT ${bam_}" }.join(' ') + def reference = fasta ? "--REFERENCE_SEQUENCE ${fasta}" : "" + + def avail_mem = 3072 + if (!task.memory) { + log.info('[GATK MarkDuplicates] Available memory not known - defaulting to 3GB. Specify process memory requirements to change this.') + } + else { + avail_mem = (task.memory.mega * 0.8).intValue() + } + + // Using samtools and not Markduplicates to compress to CRAM speeds up computation: + // https://medium.com/@acarroll.dna/looking-at-trade-offs-in-compression-levels-for-genomics-tools-eec2834e8b94 + """ + gatk --java-options "-Xmx${avail_mem}M -XX:-UsePerfData" \\ + MarkDuplicates \\ + ${input_list} \\ + --OUTPUT ${prefix_bam} \\ + --METRICS_FILE ${prefix}.metrics \\ + --TMP_DIR . \\ + ${reference} \\ + ${args} + + # If cram files are wished as output, the run samtools for conversion + if [[ ${prefix} == *.cram ]]; then + samtools view -Ch -T ${fasta} -o ${prefix} ${prefix_bam} + rm ${prefix_bam} + samtools index ${prefix} + fi + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}.bam" + prefix_no_suffix = task.ext.prefix ? prefix.tokenize('.')[0] : "${meta.id}" + """ + touch ${prefix_no_suffix}.bam + touch ${prefix_no_suffix}.cram + touch ${prefix_no_suffix}.cram.crai + touch ${prefix_no_suffix}.bai + touch ${prefix}.metrics + """ +} diff --git a/modules/nf-core/gatk4/markduplicates/meta.yml b/modules/nf-core/gatk4/markduplicates/meta.yml new file mode 100644 index 0000000..33dbc1a --- /dev/null +++ b/modules/nf-core/gatk4/markduplicates/meta.yml @@ -0,0 +1,149 @@ +name: gatk4_markduplicates +description: This tool locates and tags duplicate reads in a BAM or SAM file, + where duplicate reads are defined as originating from a single fragment of + DNA. +keywords: + - bam + - gatk4 + - markduplicates + - sort +tools: + - gatk4: + description: Developed in the Data Sciences Platform at the Broad Institute, + the toolkit offers a wide variety of tools with a primary focus on variant + discovery and genotyping. Its powerful processing engine and + high-performance computing features make it capable of taking on projects + of any size. + homepage: https://gatk.broadinstitute.org/hc/en-us + documentation: https://gatk.broadinstitute.org/hc/en-us/articles/360037052812-MarkDuplicates-Picard- + tool_dev_url: https://github.com/broadinstitute/gatk + doi: 10.1158/1538-7445.AM2017-3590 + licence: ["MIT"] + identifier: "" +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: Sorted BAM file + pattern: "*.{bam}" + ontologies: [] + - fasta: + type: file + description: Fasta file + pattern: "*.{fasta}" + ontologies: [] + - fasta_fai: + type: file + description: Fasta index file + pattern: "*.{fai}" + ontologies: [] +output: + cram: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*cram": + type: file + description: Marked duplicates CRAM file + pattern: "*.{cram}" + ontologies: [] + bam: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*bam": + type: file + description: Marked duplicates BAM file + pattern: "*.{bam}" + ontologies: [] + crai: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.crai": + type: file + description: CRAM index file + pattern: "*.{cram.crai}" + ontologies: [] + bai: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.bai": + type: file + description: BAM index file + pattern: "*.{bam.bai}" + ontologies: [] + metrics: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.metrics": + type: file + description: Duplicate metrics file generated by GATK + pattern: "*.{metrics.txt}" + ontologies: [] + versions_gatk4: + - - ${task.process}: + type: string + description: The name of the process + - gatk4: + type: string + description: The name of the tool + - gatk --version | sed -n '/GATK.*v/s/.*v//p': + type: eval + description: The expression to obtain the version of the tool + versions_samtools: + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - samtools version | sed '1!d;s/.* //': + type: eval + description: The expression to obtain the version of the tool + +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - gatk4: + type: string + description: The name of the tool + - gatk --version | sed -n '/GATK.*v/s/.*v//p': + type: eval + description: The expression to obtain the version of the tool + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - samtools version | sed '1!d;s/.* //': + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@ajodeh-juma" + - "@FriederikeHanssen" + - "@maxulysse" +maintainers: + - "@ajodeh-juma" + - "@FriederikeHanssen" + - "@maxulysse" diff --git a/modules/nf-core/gatk4/markduplicates/tests/bam.config b/modules/nf-core/gatk4/markduplicates/tests/bam.config new file mode 100644 index 0000000..0bbfbac --- /dev/null +++ b/modules/nf-core/gatk4/markduplicates/tests/bam.config @@ -0,0 +1,8 @@ +process { + + withName: GATK4_MARKDUPLICATES { + ext.args = '--CREATE_INDEX true' + ext.prefix = { "${meta.id}.bam" } + } + +} diff --git a/modules/nf-core/gatk4/markduplicates/tests/cram.config b/modules/nf-core/gatk4/markduplicates/tests/cram.config new file mode 100644 index 0000000..04a9b07 --- /dev/null +++ b/modules/nf-core/gatk4/markduplicates/tests/cram.config @@ -0,0 +1,8 @@ +process { + + withName: GATK4_MARKDUPLICATES { + ext.args = '--CREATE_INDEX true' + ext.prefix = { "${meta.id}.cram" } + } + +} diff --git a/modules/nf-core/gatk4/markduplicates/tests/main.nf.test b/modules/nf-core/gatk4/markduplicates/tests/main.nf.test new file mode 100644 index 0000000..bbf6639 --- /dev/null +++ b/modules/nf-core/gatk4/markduplicates/tests/main.nf.test @@ -0,0 +1,128 @@ +nextflow_process { + + name "Test Process GATK4_MARKDUPLICATES" + script "../main.nf" + process "GATK4_MARKDUPLICATES" + + tag "modules" + tag "modules_nfcore" + tag "gatk4" + tag "gatk4/markduplicates" + + test("sarscov2 - bam") { + config "./bam.config" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ] + input[1] = [] + input[2] = [] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot( + process.out.bam, + process.out.bai, + file(process.out.metrics[0][1]).name, + process.out.findAll { key, val -> key.startsWith("versions") } + ).match() } + ) + } + } + + test("homo_sapiens - multiple bam") { + config "./bam.config" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], + [ + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.sorted.bam', checkIfExists: true) + ] + ] + input[1] = [] + input[2] = [] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot( + process.out.bam, + process.out.bai, + file(process.out.metrics[0][1]).name, + process.out.findAll { key, val -> key.startsWith("versions") } + ).match() } + ) + } + } + + test("homo_sapiens - multiple cram") { + config "./cram.config" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.sorted.bam', checkIfExists: true) + ] + ] + input[1] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + input[2] = file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.fai', checkIfExists: true) + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot( + file(process.out.cram[0][1]).name, + file(process.out.crai[0][1]).name, + file(process.out.metrics[0][1]).name, + process.out.findAll { key, val -> key.startsWith("versions") } + ).match() } + ) + } + } + + test("stub") { + config "./bam.config" + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], + [] + ] + input[1] = [] + input[2] = [] + """ + } + } + + then { + assertAll( + { assert process.success } + ) + } + } +} diff --git a/modules/nf-core/gatk4/markduplicates/tests/main.nf.test.snap b/modules/nf-core/gatk4/markduplicates/tests/main.nf.test.snap new file mode 100644 index 0000000..0a49132 --- /dev/null +++ b/modules/nf-core/gatk4/markduplicates/tests/main.nf.test.snap @@ -0,0 +1,118 @@ +{ + "sarscov2 - bam": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.bam:md5,a9994ba43be93769a06d4814e95928cd" + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + "test.bai:md5,fd1c3cc02f4e223d32eedeed842b86c7" + ] + ], + "test.bam.metrics", + { + "versions_gatk4": [ + [ + "GATK4_MARKDUPLICATES", + "gatk4", + "4.6.2.0" + ] + ], + "versions_samtools": [ + [ + "GATK4_MARKDUPLICATES", + "samtools", + "1.21" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.3" + }, + "timestamp": "2026-02-05T16:39:06.851947547" + }, + "homo_sapiens - multiple bam": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.bam:md5,6fee419d69f55f53b5a0d0334a5f9615" + ] + ], + [ + [ + { + "id": "test", + "single_end": false + }, + "test.bai:md5,2b1603773979ad06f4dbcbaa90e93e8c" + ] + ], + "test.bam.metrics", + { + "versions_gatk4": [ + [ + "GATK4_MARKDUPLICATES", + "gatk4", + "4.6.2.0" + ] + ], + "versions_samtools": [ + [ + "GATK4_MARKDUPLICATES", + "samtools", + "1.21" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.3" + }, + "timestamp": "2026-02-05T16:39:14.928475242" + }, + "homo_sapiens - multiple cram": { + "content": [ + "test.cram", + "test.cram.crai", + "test.cram.metrics", + { + "versions_gatk4": [ + [ + "GATK4_MARKDUPLICATES", + "gatk4", + "4.6.2.0" + ] + ], + "versions_samtools": [ + [ + "GATK4_MARKDUPLICATES", + "samtools", + "1.21" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.3" + }, + "timestamp": "2026-02-05T16:39:23.543842929" + } +} \ No newline at end of file diff --git a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt new file mode 100644 index 0000000..2a91c22 --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt @@ -0,0 +1,1526 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-64: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.0-h27c8c51_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.6-py314h2b28147_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.2.0-py314h8ec4b1a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.41.0-py310h49dadd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.41.0-py310hcbd6021_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.4-py314h2e6c369_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.5-habeac84_100_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.5.9-py314h5bd0f2a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.1-hbc0de68_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 +md5: a9f577daf3de00bca7c3c76c0ecbd1de +depends: +- __glibc >=2.17,<3.0.a0 +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28948 +timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 +md5: aaa2a381ccc56eac91d63b6c1240312f +depends: +- cpython +- python-gil +license: MIT +license_family: MIT +size: 8191 +timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 +md5: 2934f256a8acfe48f6ebb4fce6cde29c +depends: +- python >=3.9 +- typing-extensions >=4.0.0 +license: MIT +license_family: MIT +size: 18074 +timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab +md5: c6b0543676ecb1fb2d7643941fe375f2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 64927 +timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda +noarch: generic +sha256: a1c97297e867776760489537bc5ae36fa83a154be30e3b79385a39ca4cb058fe +md5: 1133126d840e75287d83947be3fc3e71 +depends: +- python >=3.14 +license: BSD-3-Clause AND MIT AND EPL-2.0 +size: 7533 +timestamp: 1778594057496 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda +sha256: 3ad3500bff54a781c29f16ce1b288b36606e2189d0b0ef2f67036554f47f12b0 +md5: 8910d2c46f7e7b519129f486e0fe927a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- libbrotlicommon 1.2.0 hb03c661_1 +license: MIT +license_family: MIT +size: 367376 +timestamp: 1764017265553 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 +md5: d2ffd7602c02f2b316fd921d39876885 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 260182 +timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +sha256: 9812a303a1395e1dafbd92e5bc8a1ff6013bcbba0a09c7f03a8d23e43560aa9b +md5: 489b8e97e666c93f68fdb35c3c9b957f +depends: +- __unix +license: ISC +size: 129868 +timestamp: 1779289852439 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +sha256: 645655a3510e38e625da136595f3f16f2130c3263630cc3bc8f60f619ddbe490 +md5: 9fefff2f745ea1cc2ef15211a20c054a +depends: +- python >=3.10 +license: ISC +size: 134201 +timestamp: 1779285131141 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +sha256: 3f9483d62ce24ecd063f8a5a714448445dc8d9e201147c46699fc0033e824457 +md5: a9167b9571f3baa9d448faa2139d1089 +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 58872 +timestamp: 1775127203018 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +sha256: 99ab8ef815c4520cce3a7482c2513f377c14348206857661d84c76a55e030f97 +md5: 003767c47f1f0a474c4de268b57839c3 +depends: +- __unix +- python +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 104631 +timestamp: 1779108494556 +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 +md5: b866ff7007b934d564961066c8195983 +depends: +- humanfriendly >=9.1 +- python >=3.9 +license: MIT +license_family: MIT +size: 43758 +timestamp: 1733928076798 +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +sha256: 59c9e29800b483b390467f90e82b0da3a4fbf0612efe1c90813fca232780e160 +md5: 071cf7b0ce333c81718b054066c15102 +depends: +- networkx >=2.0 +- numpy +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 39326 +timestamp: 1735759976140 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +noarch: generic +sha256: 777882d2685f368417f31bbe1b28f73687fc6c8f6a5768bda20ffeefa6b07f5b +md5: a749029ce5d0632a913db19d17f944ab +depends: +- python >=3.14,<3.15.0a0 +- python_abi * *_cp314 +license: Python-2.0 +size: 50212 +timestamp: 1779236682725 +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_0.conda +sha256: 29a10599d56d93bd750914888ebe6822d47722070762b4647b34d12df9f4476e +md5: d0757fd84af06f065eba49d39af6c546 +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat 2.8.1 hecca717_0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 148238 +timestamp: 1779278694477 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.0-h27c8c51_0.conda +sha256: e798086d8a65d55dc4c51f5746705639c9a5f2eeb0b8fc50e6152cfc0d69a4e8 +md5: 06965b2f9854d0b15e0443ee81fe83dc +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat >=2.8.1,<3.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +- libgcc >=14 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 280882 +timestamp: 1779421631622 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 +md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 +depends: +- python >=3.10 +- hyperframe >=6.1,<7 +- hpack >=4.1,<5 +- python +license: MIT +license_family: MIT +size: 95967 +timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba +md5: 0a802cb9888dd14eeefc611f05c40b6e +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 30731 +timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d +md5: 7fe569c10905402ed47024fc481bb371 +depends: +- __unix +- python >=3.9 +license: MIT +license_family: MIT +size: 73563 +timestamp: 1733928021866 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +sha256: 6c4343b376d0b12a4c75ab992640970d36c933cad1fd924f6a1181fa91710e80 +md5: daddf757c3ecd6067b9af1df1f25d89e +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 67994 +timestamp: 1766267728652 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 +md5: 8e6923fc12f1fe8f8c4e5c9f343256ac +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 17397 +timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +sha256: 3d25f9f6f7ab3e1ce6429fc8c8aae0335cf446692e715068488536d220cc43de +md5: 1b9083b7f00609605d1483dbc6071a81 +depends: +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 62642 +timestamp: 1779294335905 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +sha256: 43e2a5497cad1598ff88a3e69f69bc88b7b8f141fa63c60eab5db296317318b8 +md5: ffc17e785d64e12fc311af9184221839 +depends: +- python >=3.10 +- zipp >=3.20 +- python +license: Apache-2.0 +size: 34766 +timestamp: 1779714582554 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b +md5: 04558c96691bed63104678757beb4f8d +depends: +- markupsafe >=2.0 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 120685 +timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 +md5: ada41c863af263cc4c5fcbaff7c3e4dc +depends: +- attrs >=22.2.0 +- jsonschema-specifications >=2023.3.6 +- python >=3.10 +- referencing >=0.28.4 +- rpds-py >=0.25.0 +- python +license: MIT +license_family: MIT +size: 82356 +timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 +md5: 439cd0f567d697b20a8f45cb70a1005a +depends: +- python >=3.10 +- referencing >=0.31.0 +- python +license: MIT +license_family: MIT +size: 19236 +timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2 +sha256: 7f243680ca03eba7457b7a48f93a9440ba8181a8eac20a3eb5ef165ab6c96664 +md5: b3723b235b0758abaae8c82ce4d80146 +depends: +- __glibc >=2.17,<3.0.a0 +- expat >=2.2.10,<3.0.0a0 +- fontconfig +- fonts-conda-forge +- libgcc-ng >=9.3.0 +- mathjax 2.7.* +- nspr >=4.29,<5.0a0 +- nss >=3.62,<4.0a0 +- sqlite >=3.34.0,<4.0a0 +license: MIT +license_family: MIT +size: 62099926 +timestamp: 1615199463039 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_0.conda +sha256: eb89c6c39f2f6a93db55723dbb2f6bba8c8e63e6312bf1abf13e6e9ff45849c8 +md5: f92f984b558e6e6204014b16d212b271 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.4.1,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 251086 +timestamp: 1778079286384 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda +sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c +md5: 18335a698559cdbcd86150a48bf54ba6 +depends: +- __glibc >=2.17,<3.0.a0 +- zstd >=1.5.7,<1.6.0a0 +constrains: +- binutils_impl_linux-64 2.45.1 +license: GPL-3.0-only +license_family: GPL +size: 728002 +timestamp: 1774197446916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +sha256: f84cb54782f7e9cea95e810ea8fef186e0652d0fa73d3009914fa2c1262594e1 +md5: a752488c68f2e7c456bcbd8f16eec275 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 261513 +timestamp: 1773113328888 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda +build_number: 7 +sha256: 081c850f99bc355821fac9c6e3727d40b3f8ce3beb50a5437cf03726b611ff39 +md5: 955b44e8b00b7f7ef4ce0130cef12394 +depends: +- libopenblas >=0.3.33,<0.3.34.0a0 +- libopenblas >=0.3.33,<1.0a0 +constrains: +- libcblas 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapack 3.11.0 7*_openblas +- liblapacke 3.11.0 7*_openblas +- mkl <2027 +license: BSD-3-Clause +license_family: BSD +size: 18716 +timestamp: 1778489854108 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda +build_number: 7 +sha256: 956ae0bb1ec8b0c3663d75b151aceb0521b54e513bf97f621a035f9c87037970 +md5: 0675639dc24cb0032f199e7ff68e4633 +depends: +- libblas 3.11.0 7_h4a7cf45_openblas +constrains: +- liblapacke 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapack 3.11.0 7*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18675 +timestamp: 1778489861559 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 +md5: 6c77a605a7a689d17d4819c0f8ac9a00 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 73490 +timestamp: 1761979956660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda +sha256: 363018b25fdb5534c79783d912bd4b685a3547f4fc5996357ad548899b0ee8e7 +md5: 93764a5ca80616e9c10106cdaec92f74 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- expat 2.8.1.* +license: MIT +license_family: MIT +size: 77294 +timestamp: 1779278686680 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 +md5: a360c33a5abe61c07959e449fa1453eb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 58592 +timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 +md5: e289f3d17880e44b633ba911d57a321b +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8049 +timestamp: 1774298163029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d +md5: fb16b4b69e3f1dcfe79d80db8fd0c55d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 384575 +timestamp: 1774298162622 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +sha256: 8e0a3b5e41272e5678499b5dfc4cddb673f9e935de01eb0767ce857001229f46 +md5: 57736f29cc2b0ec0b6c2952d3f101b6a +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_19 +- libgomp 15.2.0 he0feb66_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1041084 +timestamp: 1778269013026 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda +sha256: 9dcf54adfaa5e861123c2da4f2f0451a685464ea7e5a41ad91cf67b31d658d98 +md5: 331ee9b72b9dff570d56b1302c5ab37d +depends: +- libgcc 15.2.0 he0feb66_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27694 +timestamp: 1778269016987 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda +sha256: 561a42758ef25b9ce308c4e2cf56daee4f06138385a17e29a492cd928e00be6f +md5: 42bf7eca1a951735fa06c0e3c0d5c8e6 +depends: +- libgfortran5 15.2.0 h68bc16d_19 +constrains: +- libgfortran-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27655 +timestamp: 1778269042954 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda +sha256: 057978bb69fea29ed715a9b98adf71015c31baecc4aeb2bfc20d4fd5d83579d4 +md5: 85072b0ad177c966294f129b7c04a2d5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=15.2.0 +constrains: +- libgfortran 15.2.0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 2483673 +timestamp: 1778269025089 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +sha256: 5abe4ab9d93f6c9757d654f1969ae2267d4505315c1f2f8fe705fd60af084f1b +md5: faac990cb7aedc7f3a2224f2c9b0c26c +depends: +- __glibc >=2.17,<3.0.a0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 603817 +timestamp: 1778268942614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda +sha256: 10056646c28115b174de81a44e23e3a0a3b95b5347d2e6c45cc6d49d35294256 +md5: 6178c6f2fb254558238ef4e6c56fb782 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 633831 +timestamp: 1775962768273 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda +build_number: 7 +sha256: 96962084921f197c9ad13fb7f8b324f2351d50ff3d8d962148751ad532f54a01 +md5: 6569b4f273740e25dc0dc7e3232c2a6c +depends: +- libblas 3.11.0 7_h4a7cf45_openblas +constrains: +- liblapacke 3.11.0 7*_openblas +- libcblas 3.11.0 7*_openblas +- blas 2.307 openblas +license: BSD-3-Clause +license_family: BSD +size: 18694 +timestamp: 1778489869038 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda +sha256: ec30e52a3c1bf7d0425380a189d209a52baa03f22fb66dd3eb587acaa765bd6d +md5: b88d90cad08e6bc8ad540cb310a761fb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- xz 5.8.3.* +license: 0BSD +size: 113478 +timestamp: 1775825492909 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda +sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 +md5: 2c21e66f50753a083cbe6b80f38268fa +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-2-Clause +license_family: BSD +size: 92400 +timestamp: 1769482286018 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda +sha256: 3d9aa85648e5e18a6d66db98b8c4317cc426721ad7a220aa86330d1ccedc8903 +md5: 2d3278b721e40468295ca755c3b84070 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libgfortran +- libgfortran5 >=14.3.0 +constrains: +- openblas >=0.3.33,<0.3.34.0a0 +license: BSD-3-Clause +license_family: BSD +size: 5931919 +timestamp: 1776993658641 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda +sha256: 377cfe037f3eeb3b1bf3ad333f724a64d32f315ee1958581fc671891d63d3f89 +md5: eba48a68a1a2b9d3c0d9511548db85db +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: zlib-acknowledgement +size: 317729 +timestamp: 1776315175087 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda +sha256: 54cdcd3214313b62c2a8ee277e6f42150d9b748264c1b70d958bf735e420ef8d +md5: 7dc38adcbf71e6b38748e919e16e0dce +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: blessing +size: 954962 +timestamp: 1777986471789 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda +sha256: dff1058c76ec6b8759e41cefa2508162d00e4a5e6721aa68ec3fd10094e702dc +md5: 5794b3bdc38177caf969dabd3af08549 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc 15.2.0 he0feb66_19 +constrains: +- libstdcxx-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5852044 +timestamp: 1778269036376 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 +md5: cd5a90476766d53e901500df9215e927 +depends: +- __glibc >=2.17,<3.0.a0 +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 435273 +timestamp: 1762022005702 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda +sha256: 3f0edf1280e2f6684a986f821eaa3e123d2694a00b31b96ca0d4a4c12c129231 +md5: 7d0a66598195ef00b6efc55aefc7453b +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 40163 +timestamp: 1779118517630 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b +md5: aea31d2e5b1091feca96fcfe945c3cf9 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 429011 +timestamp: 1752159441324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa +md5: 92ed62436b625154323d40d5f2f11dd7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 395888 +timestamp: 1727278577118 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 +md5: d87ff7921124eccd67248aa483c23fec +depends: +- __glibc >=2.17,<3.0.a0 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 63629 +timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +sha256: 20e0892592a3e7c683e3d66df704a9425d731486a97c34fc56af4da1106b2b6b +md5: ba0a9221ce1063f31692c07370d062f3 +depends: +- importlib-metadata >=4.4 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 85893 +timestamp: 1770694658918 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +sha256: 0c4c35376fe920714390d46e4b8d31c876d65f18e1655899e0763ec25f2a902f +md5: 6d03368f2b2b0a5fb6839df53b2eb5e0 +depends: +- mdurl >=0.1,<1 +- python >=3.10 +license: MIT +license_family: MIT +size: 69017 +timestamp: 1778169663339 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda +sha256: c279be85b59a62d5c52f5dd9a4cd43ebd08933809a8416c22c3131595607d4cf +md5: 9a17c4307d23318476d7fbf0fedc0cde +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- jinja2 >=3.0.0 +license: BSD-3-Clause +license_family: BSD +size: 27424 +timestamp: 1772445227915 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2 +sha256: 02fef69bde69db264a12f21386612262f545b6e3e68d8f1ccec19f3eaae58edf +md5: 86e69bd82c2a2c6fd29f5ab7e02b3691 +license: Apache-2.0 +license_family: Apache +size: 22281629 +timestamp: 1662784498331 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 +md5: 592132998493b3ff25fd7479396e8351 +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 14465 +timestamp: 1733255681319 +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +sha256: e86033aa55a9e915e2d0957e770bdb81e3feb26a227d1adb17f9d6c528da6a71 +md5: cdb20309681ba3ce8f52c110e214d4f3 +depends: +- click +- coloredlogs +- humanize +- importlib-metadata +- jinja2 >=3.0.0 +- jsonschema +- markdown +- natsort +- numpy +- packaging +- pillow >=10.2.0 +- plotly >=5.18 +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 +- pyaml-env +- pydantic >=2.7.1 +- python >=3.9,!=3.14.1 +- python-dotenv +- python-kaleido 0.2.1 +- pyyaml >=4 +- requests +- rich >=10 +- rich-click +- spectra >=0.0.10 +- tiktoken +- tqdm +- typeguard >=4 +license: GPL-3.0-or-later +license_family: GPL3 +size: 4282188 +timestamp: 1779465338806 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +sha256: 70f43d62450927d51673eecd8823e14f5b3cfebdb43cda1d502eba97162bab42 +md5: 6687827c332121727ce383919e1ec8c2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 284323 +timestamp: 1778929680962 +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 +md5: e941e85e273121222580723010bd4fa2 +depends: +- python >=3.9 +- python +license: MIT +license_family: MIT +size: 39262 +timestamp: 1770905275632 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda +sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 +md5: fc21868a1a5aacc937e7a18747acb8a5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: X11 AND BSD-3-Clause +size: 918956 +timestamp: 1777422145199 +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 +md5: a2c1eeadae7a309daed9d62c96012a2b +depends: +- python >=3.11 +- python +constrains: +- numpy >=1.25 +- scipy >=1.11.2 +- matplotlib-base >=3.8 +- pandas >=2.0 +license: BSD-3-Clause +license_family: BSD +size: 1587439 +timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda +sha256: e3664264bd936c357523b55c71ed5a30263c6ba278d726a75b1eb112e6fb0b64 +md5: e235d5566c9cc8970eb2798dd4ecf62f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: MPL-2.0 +license_family: MOZILLA +size: 228588 +timestamp: 1762348634537 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda +sha256: 44dd98ffeac859d84a6dcba79a2096193a42fc10b29b28a5115687a680dd6aea +md5: 567fbeed956c200c1db5782a424e58ee +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libsqlite >=3.51.0,<4.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- nspr >=4.38,<5.0a0 +license: MPL-2.0 +license_family: MOZILLA +size: 2057773 +timestamp: 1763485556350 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.6-py314h2b28147_0.conda +sha256: bc61ae892973751a6b0e6ecea57ed6d7053224bddcb007165d6ceb1d7344ad47 +md5: f49b5f950379e0b97c35ca97682f7c6a +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- liblapack >=3.9.0,<4.0a0 +- python_abi 3.14.* *_cp314 +- libblas >=3.9.0,<4.0a0 +- libcblas >=3.9.0,<4.0a0 +constrains: +- numpy-base <0a0 +license: BSD-3-Clause +license_family: BSD +size: 8928909 +timestamp: 1779169198391 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda +sha256: 3900f9f2dbbf4129cf3ad6acf4e4b6f7101390b53843591c53b00f034343bc4d +md5: 11b3379b191f63139e29c0d19dee24cd +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.50,<1.7.0a0 +- libstdcxx >=14 +- libtiff >=4.7.1,<4.8.0a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-2-Clause +license_family: BSD +size: 355400 +timestamp: 1758489294972 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda +sha256: c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb +md5: da1b85b6a87e141f5140bb9924cecab0 +depends: +- __glibc >=2.17,<3.0.a0 +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3167099 +timestamp: 1775587756857 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 +md5: 4c06a92e74452cfa53623a81592e8934 +depends: +- python >=3.8 +- python +license: Apache-2.0 +license_family: APACHE +size: 91574 +timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.2.0-py314h8ec4b1a_0.conda +sha256: 123d8a7c16c88658b4f29e9f115a047598c941708dade74fbaff373a32dbec5e +md5: 76c4757c0ec9d11f969e8eb44899307b +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libtiff >=4.7.1,<4.8.0a0 +- openjpeg >=2.5.4,<3.0a0 +- libxcb >=1.17.0,<2.0a0 +- libwebp-base >=1.6.0,<2.0a0 +- zlib-ng >=2.3.3,<2.4.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- python_abi 3.14.* *_cp314 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +- lcms2 >=2.18,<3.0a0 +- tk >=8.6.13,<8.7.0a0 +license: HPND +size: 1082797 +timestamp: 1775060059882 +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 +md5: 3e9427ee186846052e81fadde8ebe96a +depends: +- narwhals >=1.15.1 +- packaging +- python >=3.10 +constrains: +- ipywidgets >=7.6 +license: MIT +license_family: MIT +size: 5251872 +timestamp: 1772628857717 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +sha256: 70fc56877c4a095ee658d61924d8019768fbae4a48437058d181fc94b0a7c4d8 +md5: 25a883fed9f1f3f21ff317a3e7c92ac4 +depends: +- polars-runtime-32 ==1.41.0 +- python >=3.10 +- python +constrains: +- numpy >=1.16.0 +- pyarrow >=7.0.0 +- fastexcel >=0.9 +- openpyxl >=3.0.0 +- xlsx2csv >=0.8.0 +- connectorx >=0.3.2 +- deltalake >=1.0.0 +- pyiceberg >=0.7.1 +- altair >=5.4.0 +- great_tables >=0.8.0 +- polars-runtime-32 ==1.41.0 +- polars-runtime-64 ==1.41.0 +- polars-runtime-compat ==1.41.0 +license: MIT +size: 539656 +timestamp: 1779630790562 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.41.0-py310h49dadd8_0.conda +noarch: python +sha256: e51ee3fe5259f2e115b2f78f8fbe3554e419c7c82b0c110878e12a5ff95ce3ab +md5: 7682765a1588e5ac887c99736d297c93 +depends: +- python +- __glibc >=2.17,<3.0.a0 +- libstdcxx >=14 +- libgcc >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +size: 42578921 +timestamp: 1779630790562 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.41.0-py310hcbd6021_0.conda +noarch: python +sha256: 29c3831c92394af11d9f7d04882dda9479ffbb76a3d36ba155d52159d67805fa +md5: cb0b620c9914a07a9022cb8b183ea9ee +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +size: 41864944 +timestamp: 1779630722548 +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d +md5: f2c23a77b25efcad57d377b34bd84941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 593603 +timestamp: 1769710381284 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 +md5: b3c17d95b5a10c6e64a21fa17573e70e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 8252 +timestamp: 1726802366959 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +sha256: 58994e0d2ea8584cb399546e6f6896d771995e6121d1a7b6a2c9948388358932 +md5: e17be1016bcc3516827b836cd3e4d9dc +depends: +- python >=3.9 +- pyyaml >=5.0,<=7.0 +license: MIT +license_family: MIT +size: 14645 +timestamp: 1736766960536 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +sha256: 69700e31165df070e9716315e042196aa92525dae5deb5107785847ab9f4189f +md5: 729843edafc0899b3348bd3f19525b9d +depends: +- typing-inspection >=0.4.2 +- typing_extensions >=4.14.1 +- python >=3.10 +- annotated-types >=0.6.0 +- pydantic-core ==2.46.4 +- python +license: MIT +license_family: MIT +size: 346511 +timestamp: 1778103405862 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.4-py314h2e6c369_0.conda +sha256: 802e216c39f1359aed60823b6e11d8ccd812b0ae1c81ae5ac1c81f99446409ab +md5: 0c96993dbeadf3a277cf757b9f1c9412 +depends: +- python +- typing-extensions >=4.6.0,!=4.7.0 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 1895020 +timestamp: 1778084229247 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 +md5: 16c18772b340887160c79a6acc022db0 +depends: +- python >=3.10 +license: BSD-2-Clause +license_family: BSD +size: 893031 +timestamp: 1774796815820 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 +md5: 461219d1a5bd61342293efa2c0c90eac +depends: +- __unix +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 21085 +timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.5-habeac84_100_cp314.conda +build_number: 100 +sha256: 55eed9bf2a3f6e90311276f0834737fe7c2d9ec3e5e2e557507858df4c7521e6 +md5: da92e59ff92f2d5ede4f612af20f583f +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- ld_impl_linux-64 >=2.36.1 +- libexpat >=2.8.0,<3.0a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- liblzma >=5.8.3,<6.0a0 +- libmpdec >=4.0.0,<5.0a0 +- libsqlite >=3.53.1,<4.0a0 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- openssl >=3.5.6,<4.0a0 +- python_abi 3.14.* *_cp314 +- readline >=8.3,<9.0a0 +- tk >=8.6.13,<8.7.0a0 +- tzdata +- zstd >=1.5.7,<1.6.0a0 +license: Python-2.0 +size: 36745188 +timestamp: 1779236923603 +python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 +md5: 130584ad9f3a513cdd71b1fdc1244e9c +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 27848 +timestamp: 1772388605021 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +sha256: 41dd7da285d71d519257fa7dacb1cae060d5ebfaa5f92cba5994899d2978e943 +md5: 41954747ba952ec4b01e16c2c9e8d8ff +depends: +- cpython 3.14.5.* +- python_abi * *_cp314 +license: Python-2.0 +size: 50212 +timestamp: 1779236703009 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 +md5: 310259a5b03ff02289d7705f39e2b1d2 +depends: +- kaleido-core 0.2.1.* +- python >=3.5 +license: MIT +license_family: MIT +size: 18320 +timestamp: 1615204747600 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +build_number: 8 +sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 +md5: 0539938c55b6b1a59b560e843ad864a4 +constrains: +- python 3.14.* *_cp314 +license: BSD-3-Clause +license_family: BSD +size: 6989 +timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda +sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d +md5: 2035f68f96be30dc60a5dfd7452c7941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- yaml >=0.2.5,<0.3.0a0 +license: MIT +license_family: MIT +size: 202391 +timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda +sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 +md5: d7d95fc8287ea7bf33e0e7116d2b95ec +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-3.0-only +license_family: GPL +size: 345073 +timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 +md5: 870293df500ca7e18bedefa5838a22ab +depends: +- attrs >=22.2.0 +- python >=3.10 +- rpds-py >=0.7.0 +- typing_extensions >=4.4.0 +- python +license: MIT +license_family: MIT +size: 51788 +timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.5.9-py314h5bd0f2a_0.conda +sha256: c7a4aca4977c15c82d053b06cbc676460974c1b25757cfeea8a9a2497ac911f8 +md5: 9dd235b6ac69a0198080dac39f9891aa +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +license: Apache-2.0 AND CNRI-Python +license_family: PSF +size: 413611 +timestamp: 1778374155646 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +sha256: 1715246b19c9f85ee022933b4845f2fc14ac9184981b7b7d9b728bec8e9588da +md5: 4a85203c1d80c1059086ae860836ffb9 +depends: +- python >=3.10 +- certifi >=2023.5.7 +- charset-normalizer >=2,<4 +- idna >=2.5,<4 +- urllib3 >=1.26,<3 +- python +constrains: +- chardet >=3.0.2,<8 +license: Apache-2.0 +license_family: APACHE +size: 68709 +timestamp: 1778851103479 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +sha256: 3d6ba2c0fcdac3196ba2f0615b4104e532525ffa1335b50a2878be5ff488814a +md5: 0242025a3c804966bf71aa04eee82f66 +depends: +- markdown-it-py >=2.2.0 +- pygments >=2.13.0,<3.0.0 +- python >=3.10 +- typing_extensions >=4.0.0,<5.0.0 +- python +license: MIT +license_family: MIT +size: 208577 +timestamp: 1775991661559 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 +md5: 0c20a8ebcddb24a45da89d5e917e6cb9 +depends: +- python >=3.10 +- rich >=12 +- click >=8 +- typing-extensions >=4 +- __unix +- python +license: MIT +license_family: MIT +size: 64356 +timestamp: 1769850479089 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda +sha256: e53b0cbf3b324eaa03ca1fe1a688fdf4ab42cea9c25270b0a7307d8aaaa4f446 +md5: c1c368b5437b0d1a68f372ccf01cb133 +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 376121 +timestamp: 1764543122774 +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +sha256: 7c65782d2511738e62c70462e89d65da4fa54d5a7e47c46667bcd27a59f81876 +md5: 472239e4eb7b5a84bb96b3ed7e3a596a +depends: +- colormath >=3.0.0 +- python >=3.9 +license: MIT +license_family: MIT +size: 22284 +timestamp: 1735770589188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.1-hbc0de68_0.conda +sha256: d167fa92781bcdcd3b9aaa6bb1cd50c5b108f6190c170098a118b5cf5df2f881 +md5: 8e0b8654ead18e50af552e54b5a08a61 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libsqlite 3.53.1 h0c1763c_0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- readline >=8.3,<9.0a0 +license: blessing +size: 205399 +timestamp: 1777986477546 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda +sha256: 7e395d67fd249d901beb1ae269057763c0d8c3ee5f7a348694bdb16d158a37d9 +md5: d705f9d8a1185a2b01cced191177a028 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- regex >=2022.1.18 +- requests >=2.26.0 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 939648 +timestamp: 1764028306357 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda +sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac +md5: cffd3bdd58090148f4cfcd831f4b26ab +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +constrains: +- xorg-libx11 >=1.8.12,<2.0a0 +license: TCL +license_family: BSD +size: 3301196 +timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 +md5: e5ce43272193b38c2e9037446c1d9206 +depends: +- python >=3.10 +- __unix +- python +license: MPL-2.0 and MIT +size: 94132 +timestamp: 1770153424136 +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +sha256: 59d7851d32fddb5b510272e6557aa982edeb927d349648dac27f5bf01d18bb26 +md5: 4460f039b7dedf15f7df086446ca75ae +depends: +- typing_extensions >=4.14.0 +- python >=3.10 +- importlib-metadata >=3.6 +- python +constrains: +- pytest >=7 +license: MIT +license_family: MIT +size: 38297 +timestamp: 1778779291237 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c +md5: edd329d7d3a4ab45dcf905899a7a6115 +depends: +- typing_extensions ==4.15.0 pyhcf101f3_0 +license: PSF-2.0 +license_family: PSF +size: 91383 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +sha256: 8b90d2f19f9458b8c58a55e1fcdc1d90c1603a847a47654d8a454549413ba60a +md5: 53f5409c5cfd6c5a66417d68e3f0a864 +depends: +- python >=3.10 +- typing_extensions >=4.12.0 +- python +license: MIT +license_family: MIT +size: 20935 +timestamp: 1777105465795 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 +md5: 0caa1af407ecff61170c9437a808404d +depends: +- python >=3.10 +- python +license: PSF-2.0 +license_family: PSF +size: 51692 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c +md5: ad659d0a2b3e47e38d829aa8cad2d610 +license: LicenseRef-Public-Domain +size: 119135 +timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 +md5: cbb88288f74dbe6ada1c6c7d0a97223e +depends: +- backports.zstd >=1.0.0 +- brotli-python >=1.2.0 +- h2 >=4,<5 +- pysocks >=1.5.6,<2.0,!=1.5.7 +- python >=3.10 +license: MIT +license_family: MIT +size: 103560 +timestamp: 1778188657149 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b +md5: b2895afaf55bf96a8c8282a2e47a5de0 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 15321 +timestamp: 1762976464266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 +md5: 1dafce8548e38671bea82e3f5c6ce22f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 20591 +timestamp: 1762976546182 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda +sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad +md5: a77f85f77be52ff59391544bfe73390a +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +license: MIT +license_family: MIT +size: 85189 +timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +sha256: 210bd31c22bb88f5e2a167df24c95bb5f152b2ada7502f9b8c49d1f5366db423 +md5: ba3dcdc8584155c97c648ae9c044b7a3 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 24190 +timestamp: 1779159948016 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda +sha256: ea4e50c465d70236408cb0bfe0115609fd14db1adcd8bd30d8918e0291f8a75f +md5: 2aadb0d17215603a82a2a6b0afd9a4cb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Zlib +license_family: Other +size: 122618 +timestamp: 1770167931827 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 +md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 +depends: +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 601375 +timestamp: 1764777111296 diff --git a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt new file mode 100644 index 0000000..3d5b93d --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt @@ -0,0 +1,1476 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-aarch64: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.18.0-hba86a56_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.19.1-h9d5b58d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-7_haddc8a3_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-7_hd72aa62_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-7_h88aeb00_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.33-pthreads_h9d3fd7e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.1-h022381a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.6-py314he1698a1_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.2.0-py314hac3e5ec_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.41.0-py310h32c7c23_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.41.0-py310hc0e61be_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.46.4-py314h451b6cc_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.5-hfd9ac0a_100_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.5.9-py314h51f160d_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.1-he8854b5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 +md5: 468fd3bb9e1f671d36c2cbc677e56f1d +depends: +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28926 +timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 +md5: aaa2a381ccc56eac91d63b6c1240312f +depends: +- cpython +- python-gil +license: MIT +license_family: MIT +size: 8191 +timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 +md5: 2934f256a8acfe48f6ebb4fce6cde29c +depends: +- python >=3.9 +- typing-extensions >=4.0.0 +license: MIT +license_family: MIT +size: 18074 +timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab +md5: c6b0543676ecb1fb2d7643941fe375f2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 64927 +timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda +noarch: generic +sha256: a1c97297e867776760489537bc5ae36fa83a154be30e3b79385a39ca4cb058fe +md5: 1133126d840e75287d83947be3fc3e71 +depends: +- python >=3.14 +license: BSD-3-Clause AND MIT AND EPL-2.0 +size: 7533 +timestamp: 1778594057496 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda +sha256: 5a5b0cdcd7ed89c6a8fb830924967f6314a2b71944bc1ebc2c105781ba97aa75 +md5: a1b5c571a0923a205d663d8678df4792 +depends: +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +constrains: +- libbrotlicommon 1.2.0 he30d5cf_1 +license: MIT +license_family: MIT +size: 373193 +timestamp: 1764017486851 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c +md5: 840d8fc0d7b3209be93080bc20e07f2d +depends: +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 192412 +timestamp: 1771350241232 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +sha256: 9812a303a1395e1dafbd92e5bc8a1ff6013bcbba0a09c7f03a8d23e43560aa9b +md5: 489b8e97e666c93f68fdb35c3c9b957f +depends: +- __unix +license: ISC +size: 129868 +timestamp: 1779289852439 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +sha256: 645655a3510e38e625da136595f3f16f2130c3263630cc3bc8f60f619ddbe490 +md5: 9fefff2f745ea1cc2ef15211a20c054a +depends: +- python >=3.10 +license: ISC +size: 134201 +timestamp: 1779285131141 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +sha256: 3f9483d62ce24ecd063f8a5a714448445dc8d9e201147c46699fc0033e824457 +md5: a9167b9571f3baa9d448faa2139d1089 +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 58872 +timestamp: 1775127203018 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +sha256: 99ab8ef815c4520cce3a7482c2513f377c14348206857661d84c76a55e030f97 +md5: 003767c47f1f0a474c4de268b57839c3 +depends: +- __unix +- python +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 104631 +timestamp: 1779108494556 +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 +md5: b866ff7007b934d564961066c8195983 +depends: +- humanfriendly >=9.1 +- python >=3.9 +license: MIT +license_family: MIT +size: 43758 +timestamp: 1733928076798 +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +sha256: 59c9e29800b483b390467f90e82b0da3a4fbf0612efe1c90813fca232780e160 +md5: 071cf7b0ce333c81718b054066c15102 +depends: +- networkx >=2.0 +- numpy +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 39326 +timestamp: 1735759976140 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +noarch: generic +sha256: 777882d2685f368417f31bbe1b28f73687fc6c8f6a5768bda20ffeefa6b07f5b +md5: a749029ce5d0632a913db19d17f944ab +depends: +- python >=3.14,<3.15.0a0 +- python_abi * *_cp314 +license: Python-2.0 +size: 50212 +timestamp: 1779236682725 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_0.conda +sha256: a9cd5eb1700e11cc39acc36630a2d72a4e317943bd7c5695cd8804419f04ff42 +md5: 89f0247b3cea528d8ad1a6664a313153 +depends: +- libexpat 2.8.1 hfae3067_0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 140114 +timestamp: 1779278679081 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.18.0-hba86a56_0.conda +sha256: 1805f4ab3d9e1734a5a17abccc2cb0fdade51d4d5f29bdc410600ea0115ec050 +md5: b660d59a9d0fb3297327418624acaec3 +depends: +- libexpat >=2.8.1,<3.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +- libgcc >=14 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 293348 +timestamp: 1779421661332 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 +md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 +depends: +- python >=3.10 +- hyperframe >=6.1,<7 +- hpack >=4.1,<5 +- python +license: MIT +license_family: MIT +size: 95967 +timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba +md5: 0a802cb9888dd14eeefc611f05c40b6e +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 30731 +timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d +md5: 7fe569c10905402ed47024fc481bb371 +depends: +- __unix +- python >=3.9 +license: MIT +license_family: MIT +size: 73563 +timestamp: 1733928021866 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +sha256: 6c4343b376d0b12a4c75ab992640970d36c933cad1fd924f6a1181fa91710e80 +md5: daddf757c3ecd6067b9af1df1f25d89e +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 67994 +timestamp: 1766267728652 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 +md5: 8e6923fc12f1fe8f8c4e5c9f343256ac +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 17397 +timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +sha256: 3d25f9f6f7ab3e1ce6429fc8c8aae0335cf446692e715068488536d220cc43de +md5: 1b9083b7f00609605d1483dbc6071a81 +depends: +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 62642 +timestamp: 1779294335905 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +sha256: 43e2a5497cad1598ff88a3e69f69bc88b7b8f141fa63c60eab5db296317318b8 +md5: ffc17e785d64e12fc311af9184221839 +depends: +- python >=3.10 +- zipp >=3.20 +- python +license: Apache-2.0 +size: 34766 +timestamp: 1779714582554 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b +md5: 04558c96691bed63104678757beb4f8d +depends: +- markupsafe >=2.0 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 120685 +timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 +md5: ada41c863af263cc4c5fcbaff7c3e4dc +depends: +- attrs >=22.2.0 +- jsonschema-specifications >=2023.3.6 +- python >=3.10 +- referencing >=0.28.4 +- rpds-py >=0.25.0 +- python +license: MIT +license_family: MIT +size: 82356 +timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 +md5: 439cd0f567d697b20a8f45cb70a1005a +depends: +- python >=3.10 +- referencing >=0.31.0 +- python +license: MIT +license_family: MIT +size: 19236 +timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2 +sha256: d3c7f4797566e6f983d16c2a87063a18e4b2d819a66230190a21584d70042755 +md5: 4f0d284f5d11e04277b552eb1c172c7f +depends: +- __glibc >=2.17,<3.0.a0 +- expat >=2.2.10,<3.0.0a0 +- fontconfig +- fonts-conda-forge +- libgcc-ng >=9.3.0 +- mathjax 2.7.* +- nspr >=4.29,<5.0a0 +- nss >=3.62,<4.0a0 +- sqlite >=3.34.0,<4.0a0 +license: MIT +license_family: MIT +size: 65750397 +timestamp: 1615199465742 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.19.1-h9d5b58d_0.conda +sha256: 1e5f68e4b36a0e1a278c6dc026bc3d7775518a15832cbc9d7fc1c0e4c47784b1 +md5: b1f8bee3c53a6d2c103fb4a1ae44f5c4 +depends: +- libgcc >=14 +- libjpeg-turbo >=3.1.4.1,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 296899 +timestamp: 1778079402392 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda +sha256: 7abd913d81a9bf00abb699e8987966baa2065f5132e37e815f92d90fc6bba530 +md5: a21644fc4a83da26452a718dc9468d5f +depends: +- zstd >=1.5.7,<1.6.0a0 +constrains: +- binutils_impl_linux-aarch64 2.45.1 +license: GPL-3.0-only +license_family: GPL +size: 875596 +timestamp: 1774197520746 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +sha256: 8957fd460c1c132c8031f65fd5f56ec3807fd71b7cab2c5e2b0937b13404ab36 +md5: d13423b06447113a90b5b1366d4da171 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 240444 +timestamp: 1773114901155 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-7_haddc8a3_openblas.conda +build_number: 7 +sha256: f27ba323c2f1e1731b5e880fe520f178f55047f25be94f77e649605b2343c066 +md5: e8d07b777f6ff1fab69665336561910b +depends: +- libopenblas >=0.3.33,<0.3.34.0a0 +- libopenblas >=0.3.33,<1.0a0 +constrains: +- liblapack 3.11.0 7*_openblas +- libcblas 3.11.0 7*_openblas +- mkl <2027 +- blas 2.307 openblas +- liblapacke 3.11.0 7*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18696 +timestamp: 1778489796402 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-7_hd72aa62_openblas.conda +build_number: 7 +sha256: c8f0192362966df0828419f042d6f94c079e5df00ad6bd05b5e84c12b42f8cc7 +md5: 90ac57b82c055faa9be25031864b7d8f +depends: +- libblas 3.11.0 7_haddc8a3_openblas +constrains: +- liblapack 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapacke 3.11.0 7*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18664 +timestamp: 1778489802790 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 +md5: a9138815598fe6b91a1d6782ca657b0c +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 71117 +timestamp: 1761979776756 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda +sha256: 1fc392b997c6ee2bd3226a7cd870d0edbcbb367e25f9f18dd4a7025fced6efc0 +md5: 513dd884361dfb8a554298ed69b58823 +depends: +- libgcc >=14 +constrains: +- expat 2.8.1.* +license: MIT +license_family: MIT +size: 77140 +timestamp: 1779278671302 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 +md5: 2f364feefb6a7c00423e80dcb12db62a +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 55952 +timestamp: 1769456078358 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a +md5: a229e22d4d8814a07702b0919d8e6701 +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8125 +timestamp: 1774301094057 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c +md5: b99ed99e42dafb27889483b3098cace7 +depends: +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 422941 +timestamp: 1774301093473 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda +sha256: 4592b096e553f67799ae70d4b6167eeda3ec74587d68c7aecbf4e7b1df136681 +md5: f35b3f52d0a2ec4ffe3c89ba135cdb9a +depends: +- _openmp_mutex >=4.5 +constrains: +- libgomp 15.2.0 h8acb6b2_19 +- libgcc-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 622462 +timestamp: 1778268755949 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda +sha256: 1137f93f477f56199ded24117430045a0c02cbe8b10031beac3b9ad2138539d3 +md5: 770cf892e5530f43e63cadc673e85653 +depends: +- libgcc 15.2.0 h8acb6b2_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27738 +timestamp: 1778268759211 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_19.conda +sha256: e5ad94be72634233510b33ba792a3339921bd468f0b8bc6961ea05eded251d9b +md5: c7a5b5decf969ead5ecada83654164cf +depends: +- libgfortran5 15.2.0 h1b7bec0_19 +constrains: +- libgfortran-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27728 +timestamp: 1778268784621 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_19.conda +sha256: af8e9bdcaa77f133a8ee4c1ef57ef564d9c45aa262abf9f5ef9b50eb99d96407 +md5: 779dbb494de6d3d6477cab52eb34285a +depends: +- libgcc >=15.2.0 +constrains: +- libgfortran 15.2.0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1487244 +timestamp: 1778268767295 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda +sha256: 2370ef0ffcbae5bede3c4bf136add4abc257245eb91f724c99bb4a43116c5a83 +md5: c5e8a379c4a2ec2aea4ba22758c001d9 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 587387 +timestamp: 1778268674393 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda +sha256: e97ec2af5f09f8f6ea8ecd550055c95ae80fae22015fcfadaa94eafe025c9ccc +md5: a85ba48648f6868016f2741fd9170250 +depends: +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 693143 +timestamp: 1775962625956 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-7_h88aeb00_openblas.conda +build_number: 7 +sha256: 20b38a0156200ac65f597bf0a93914c565435f2cc58b1042581854231a99ac35 +md5: 5899cbd743cc74fd655c1ed2af7120f3 +depends: +- libblas 3.11.0 7_haddc8a3_openblas +constrains: +- libcblas 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapacke 3.11.0 7*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18685 +timestamp: 1778489809140 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda +sha256: d61962b9cd54c3554361550203c64d5b65b71e3058a285b66e4b04b9769f0a5c +md5: 76298a9e6d71ee6e832a8d0d7373b261 +depends: +- libgcc >=14 +constrains: +- xz 5.8.3.* +license: 0BSD +size: 126102 +timestamp: 1775828008518 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda +sha256: 57c0dd12d506e84541c4e877898bd2a59cca141df493d34036f18b2751e0a453 +md5: 7b9813e885482e3ccb1fa212b86d7fd0 +depends: +- libgcc >=14 +license: BSD-2-Clause +license_family: BSD +size: 114056 +timestamp: 1769482343003 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.33-pthreads_h9d3fd7e_0.conda +sha256: b018ecfb05e75a8eea3f21f6b5c5c2a54b5178bdcf19e2e2df2735740214a8c8 +md5: 58a66cd95e9692f08abe89f55a6f3f12 +depends: +- libgcc >=14 +- libgfortran +- libgfortran5 >=14.3.0 +constrains: +- openblas >=0.3.33,<0.3.34.0a0 +license: BSD-3-Clause +license_family: BSD +size: 5121336 +timestamp: 1776993423004 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda +sha256: 483eaa53da40a6a3e558709d9f7b1ca388735364ae21a1ba58cf942514649c92 +md5: f51503ac45a4888bce71af9027a2ecc9 +depends: +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: zlib-acknowledgement +size: 341202 +timestamp: 1776315188425 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.1-h022381a_0.conda +sha256: ad03b7d8e4d08001f0df88ee7a56108bb35bae4795a42b9a04cc1abfa822bd07 +md5: 2ec1119217d8f0d086e9a62f3cb0e5ea +depends: +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: blessing +size: 955361 +timestamp: 1777986487553 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda +sha256: 1dadc45e599f510dd5f97141dddcdbb9844d9f1430c1f3a38075cf1c58f87b4e +md5: 543fbc8d71f2a0baf04cf88ce96cb8bb +depends: +- libgcc 15.2.0 h8acb6b2_19 +constrains: +- libstdcxx-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5546559 +timestamp: 1778268777463 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 +md5: 8c6fd84f9c87ac00636007c6131e457d +depends: +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 488407 +timestamp: 1762022048105 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda +sha256: 1628839b062e98b2192857d4da8496ac9ac6b0dbb77aa040c34efc9192c440ee +md5: 0f42f9fedd2a32d798de95a7f65c456f +depends: +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 43453 +timestamp: 1779118526838 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 +md5: 24e92d0942c799db387f5c9d7b81f1af +depends: +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 359496 +timestamp: 1752160685488 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b +md5: cd14ee5cca2464a425b1dbfc24d90db2 +depends: +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 397493 +timestamp: 1727280745441 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f +md5: 502006882cf5461adced436e410046d1 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 69833 +timestamp: 1774072605429 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +sha256: 20e0892592a3e7c683e3d66df704a9425d731486a97c34fc56af4da1106b2b6b +md5: ba0a9221ce1063f31692c07370d062f3 +depends: +- importlib-metadata >=4.4 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 85893 +timestamp: 1770694658918 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +sha256: 0c4c35376fe920714390d46e4b8d31c876d65f18e1655899e0763ec25f2a902f +md5: 6d03368f2b2b0a5fb6839df53b2eb5e0 +depends: +- mdurl >=0.1,<1 +- python >=3.10 +license: MIT +license_family: MIT +size: 69017 +timestamp: 1778169663339 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda +sha256: 383c188496d13a55658c06e61e7d4cdff2c9f9d5a0648769fca8250bece7e0ef +md5: e5de3c36dd548b35ff2a8aa49208dcb3 +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- jinja2 >=3.0.0 +license: BSD-3-Clause +license_family: BSD +size: 27913 +timestamp: 1772446407659 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2 +sha256: 8fd4c79d6eda3d4cba73783114305a53a154ada4d1e334d4e02cb3521429599b +md5: 7b08314a6867a9d5648a1c3265e9eb8e +license: Apache-2.0 +license_family: Apache +size: 22257008 +timestamp: 1662784555011 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 +md5: 592132998493b3ff25fd7479396e8351 +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 14465 +timestamp: 1733255681319 +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +sha256: e86033aa55a9e915e2d0957e770bdb81e3feb26a227d1adb17f9d6c528da6a71 +md5: cdb20309681ba3ce8f52c110e214d4f3 +depends: +- click +- coloredlogs +- humanize +- importlib-metadata +- jinja2 >=3.0.0 +- jsonschema +- markdown +- natsort +- numpy +- packaging +- pillow >=10.2.0 +- plotly >=5.18 +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 +- pyaml-env +- pydantic >=2.7.1 +- python >=3.9,!=3.14.1 +- python-dotenv +- python-kaleido 0.2.1 +- pyyaml >=4 +- requests +- rich >=10 +- rich-click +- spectra >=0.0.10 +- tiktoken +- tqdm +- typeguard >=4 +license: GPL-3.0-or-later +license_family: GPL3 +size: 4282188 +timestamp: 1779465338806 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +sha256: 70f43d62450927d51673eecd8823e14f5b3cfebdb43cda1d502eba97162bab42 +md5: 6687827c332121727ce383919e1ec8c2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 284323 +timestamp: 1778929680962 +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 +md5: e941e85e273121222580723010bd4fa2 +depends: +- python >=3.9 +- python +license: MIT +license_family: MIT +size: 39262 +timestamp: 1770905275632 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda +sha256: 369db85c5cd8d99dde364ce70725d76511d9c8199e5b820c740414091bf5bcca +md5: b2a43456aa56fe80c2477a5094899eff +depends: +- libgcc >=14 +license: X11 AND BSD-3-Clause +size: 960036 +timestamp: 1777422174534 +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 +md5: a2c1eeadae7a309daed9d62c96012a2b +depends: +- python >=3.11 +- python +constrains: +- numpy >=1.25 +- scipy >=1.11.2 +- matplotlib-base >=3.8 +- pandas >=2.0 +license: BSD-3-Clause +license_family: BSD +size: 1587439 +timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda +sha256: 78a06e89285fef242e272998b292c1e621e3ee3dd4fba62ec014e503c7ec118f +md5: 6dd4f07147774bf720075a210f8026b9 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: MPL-2.0 +license_family: MOZILLA +size: 235140 +timestamp: 1762350120355 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda +sha256: 48942696889367ffd448f8dccfc080fb7e130b9938a4a3b6b20ef8e6af856463 +md5: 4540f9570d12db2150f42ba036154552 +depends: +- libgcc >=14 +- libsqlite >=3.51.0,<4.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- nspr >=4.38,<5.0a0 +license: MPL-2.0 +license_family: MOZILLA +size: 2061869 +timestamp: 1763490303490 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.6-py314he1698a1_0.conda +sha256: 04af718b911f8a3a0095481c7e283aa081a175fe626eccbc2c5644bcb2aba9a1 +md5: 8b173772deea177b45d2a133b509b3f7 +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- python_abi 3.14.* *_cp314 +- libblas >=3.9.0,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- libcblas >=3.9.0,<4.0a0 +constrains: +- numpy-base <0a0 +license: BSD-3-Clause +license_family: BSD +size: 8002900 +timestamp: 1779169206742 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda +sha256: bd1bc8bdde5e6c5cbac42d462b939694e40b59be6d0698f668515908640c77b8 +md5: cea962410e327262346d48d01f05936c +depends: +- libgcc >=14 +- libpng >=1.6.50,<1.7.0a0 +- libstdcxx >=14 +- libtiff >=4.7.1,<4.8.0a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-2-Clause +license_family: BSD +size: 392636 +timestamp: 1758489353577 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda +sha256: 348cb74c1530ac241215d047ef65d134cf797af935c97a68655319362b7e6a01 +md5: 3b129669089e4d6a5c6871dbb4669b99 +depends: +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3706406 +timestamp: 1775589602258 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 +md5: 4c06a92e74452cfa53623a81592e8934 +depends: +- python >=3.8 +- python +license: Apache-2.0 +license_family: APACHE +size: 91574 +timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.2.0-py314hac3e5ec_0.conda +sha256: 96b26c2657275ffe84ab510edf0865e21999d791485d12794edd4a71b837beb6 +md5: 87d58d103b47c4a8567b3d7666647684 +depends: +- python +- libgcc >=14 +- python 3.14.* *_cp314 +- openjpeg >=2.5.4,<3.0a0 +- libxcb >=1.17.0,<2.0a0 +- libwebp-base >=1.6.0,<2.0a0 +- zlib-ng >=2.3.3,<2.4.0a0 +- python_abi 3.14.* *_cp314 +- lcms2 >=2.18,<3.0a0 +- tk >=8.6.13,<8.7.0a0 +- libtiff >=4.7.1,<4.8.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +license: HPND +size: 1062080 +timestamp: 1775060067775 +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 +md5: 3e9427ee186846052e81fadde8ebe96a +depends: +- narwhals >=1.15.1 +- packaging +- python >=3.10 +constrains: +- ipywidgets >=7.6 +license: MIT +license_family: MIT +size: 5251872 +timestamp: 1772628857717 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +sha256: 70fc56877c4a095ee658d61924d8019768fbae4a48437058d181fc94b0a7c4d8 +md5: 25a883fed9f1f3f21ff317a3e7c92ac4 +depends: +- polars-runtime-32 ==1.41.0 +- python >=3.10 +- python +constrains: +- numpy >=1.16.0 +- pyarrow >=7.0.0 +- fastexcel >=0.9 +- openpyxl >=3.0.0 +- xlsx2csv >=0.8.0 +- connectorx >=0.3.2 +- deltalake >=1.0.0 +- pyiceberg >=0.7.1 +- altair >=5.4.0 +- great_tables >=0.8.0 +- polars-runtime-32 ==1.41.0 +- polars-runtime-64 ==1.41.0 +- polars-runtime-compat ==1.41.0 +license: MIT +size: 539656 +timestamp: 1779630790562 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.41.0-py310h32c7c23_0.conda +noarch: python +sha256: d903b774ec09189e164207328aac157eee82fed8cc5c9ace46aeb5d1c15cb5b3 +md5: 8c08c506ed1ea8ce0ca37af5e918c58d +depends: +- python +- libgcc >=14 +- libstdcxx >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +size: 38704429 +timestamp: 1779630794932 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.41.0-py310hc0e61be_0.conda +noarch: python +sha256: 101696adff43a654146376c62ef9611bf7946b95fa46f604fe247d77eefc6267 +md5: 65b73e4260677ee5162bdbb252e28e06 +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +size: 38651498 +timestamp: 1779630714016 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 +md5: ab7288cc39545556d1bc5e71ab2df9a9 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 636733 +timestamp: 1769712412683 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba +md5: bb5a90c93e3bac3d5690acf76b4a6386 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 8342 +timestamp: 1726803319942 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +sha256: 58994e0d2ea8584cb399546e6f6896d771995e6121d1a7b6a2c9948388358932 +md5: e17be1016bcc3516827b836cd3e4d9dc +depends: +- python >=3.9 +- pyyaml >=5.0,<=7.0 +license: MIT +license_family: MIT +size: 14645 +timestamp: 1736766960536 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +sha256: 69700e31165df070e9716315e042196aa92525dae5deb5107785847ab9f4189f +md5: 729843edafc0899b3348bd3f19525b9d +depends: +- typing-inspection >=0.4.2 +- typing_extensions >=4.14.1 +- python >=3.10 +- annotated-types >=0.6.0 +- pydantic-core ==2.46.4 +- python +license: MIT +license_family: MIT +size: 346511 +timestamp: 1778103405862 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.46.4-py314h451b6cc_0.conda +sha256: 1a7c6b18e404c13c4d959888ecb48a9ed9de0e41be2872932b83a35278088df0 +md5: 9c3ace6aba6df14b943256095ac1281e +depends: +- python +- typing-extensions >=4.6.0,!=4.7.0 +- libgcc >=14 +- python 3.14.* *_cp314 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 1780773 +timestamp: 1778084251775 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 +md5: 16c18772b340887160c79a6acc022db0 +depends: +- python >=3.10 +license: BSD-2-Clause +license_family: BSD +size: 893031 +timestamp: 1774796815820 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 +md5: 461219d1a5bd61342293efa2c0c90eac +depends: +- __unix +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 21085 +timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.5-hfd9ac0a_100_cp314.conda +build_number: 100 +sha256: d37bad5447365346166c72950ea8f49689aa49cecc1b0623d00458427627b8df +md5: d956e09feb806f5974675ce92ad81d45 +depends: +- bzip2 >=1.0.8,<2.0a0 +- ld_impl_linux-aarch64 >=2.36.1 +- libexpat >=2.8.0,<3.0a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- liblzma >=5.8.3,<6.0a0 +- libmpdec >=4.0.0,<5.0a0 +- libsqlite >=3.53.1,<4.0a0 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- openssl >=3.5.6,<4.0a0 +- python_abi 3.14.* *_cp314 +- readline >=8.3,<9.0a0 +- tk >=8.6.13,<8.7.0a0 +- tzdata +- zstd >=1.5.7,<1.6.0a0 +license: Python-2.0 +size: 37510439 +timestamp: 1779236267040 +python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 +md5: 130584ad9f3a513cdd71b1fdc1244e9c +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 27848 +timestamp: 1772388605021 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +sha256: 41dd7da285d71d519257fa7dacb1cae060d5ebfaa5f92cba5994899d2978e943 +md5: 41954747ba952ec4b01e16c2c9e8d8ff +depends: +- cpython 3.14.5.* +- python_abi * *_cp314 +license: Python-2.0 +size: 50212 +timestamp: 1779236703009 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 +md5: 310259a5b03ff02289d7705f39e2b1d2 +depends: +- kaleido-core 0.2.1.* +- python >=3.5 +license: MIT +license_family: MIT +size: 18320 +timestamp: 1615204747600 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +build_number: 8 +sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 +md5: 0539938c55b6b1a59b560e843ad864a4 +constrains: +- python 3.14.* *_cp314 +license: BSD-3-Clause +license_family: BSD +size: 6989 +timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda +sha256: 496b5e65dfdd0aaaaa5de0dcaaf3bceea00fcb4398acf152f89e567c82ec1046 +md5: 9ae2c92975118058bd720e9ba2bb7c58 +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +- yaml >=0.2.5,<0.3.0a0 +license: MIT +license_family: MIT +size: 195678 +timestamp: 1770223441816 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda +sha256: fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216 +md5: 3d49cad61f829f4f0e0611547a9cda12 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-3.0-only +license_family: GPL +size: 357597 +timestamp: 1765815673644 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 +md5: 870293df500ca7e18bedefa5838a22ab +depends: +- attrs >=22.2.0 +- python >=3.10 +- rpds-py >=0.7.0 +- typing_extensions >=4.4.0 +- python +license: MIT +license_family: MIT +size: 51788 +timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.5.9-py314h51f160d_0.conda +sha256: 05ef55f09f31eabd0a205f6b065e13fc746675f41924620977692ef0ffe5aad8 +md5: 34ed7bc9febeca70f55b757ca09c354d +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +license: Apache-2.0 AND CNRI-Python +license_family: PSF +size: 409780 +timestamp: 1778374195988 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +sha256: 1715246b19c9f85ee022933b4845f2fc14ac9184981b7b7d9b728bec8e9588da +md5: 4a85203c1d80c1059086ae860836ffb9 +depends: +- python >=3.10 +- certifi >=2023.5.7 +- charset-normalizer >=2,<4 +- idna >=2.5,<4 +- urllib3 >=1.26,<3 +- python +constrains: +- chardet >=3.0.2,<8 +license: Apache-2.0 +license_family: APACHE +size: 68709 +timestamp: 1778851103479 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +sha256: 3d6ba2c0fcdac3196ba2f0615b4104e532525ffa1335b50a2878be5ff488814a +md5: 0242025a3c804966bf71aa04eee82f66 +depends: +- markdown-it-py >=2.2.0 +- pygments >=2.13.0,<3.0.0 +- python >=3.10 +- typing_extensions >=4.0.0,<5.0.0 +- python +license: MIT +license_family: MIT +size: 208577 +timestamp: 1775991661559 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 +md5: 0c20a8ebcddb24a45da89d5e917e6cb9 +depends: +- python >=3.10 +- rich >=12 +- click >=8 +- typing-extensions >=4 +- __unix +- python +license: MIT +license_family: MIT +size: 64356 +timestamp: 1769850479089 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda +sha256: a587240f16eac7c6a80f9585cef679cd1cb9a287b8dfcdd36dcef1f7e7db15dc +md5: e7f6ed9e60043bb5cbcc527764897f0d +depends: +- python +- libgcc >=14 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 376332 +timestamp: 1764543345455 +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +sha256: 7c65782d2511738e62c70462e89d65da4fa54d5a7e47c46667bcd27a59f81876 +md5: 472239e4eb7b5a84bb96b3ed7e3a596a +depends: +- colormath >=3.0.0 +- python >=3.9 +license: MIT +license_family: MIT +size: 22284 +timestamp: 1735770589188 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.1-he8854b5_0.conda +sha256: 27467e4bfb0681546f149718c33b806fec078185fbaa6a4d17d440bc8f56185c +md5: 46009bdca2315a99e0a3a7d0ba1af3b9 +depends: +- libgcc >=14 +- libsqlite 3.53.1 h022381a_0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- readline >=8.3,<9.0a0 +license: blessing +size: 209964 +timestamp: 1777986493350 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda +sha256: c1da41c79262b27efa168407cfecc47b20270e5fc071a8307f95a2c85fb94170 +md5: 55bf7b559202236157b14323b40f19e6 +depends: +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- regex >=2022.1.18 +- requests >=2.26.0 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 914402 +timestamp: 1764030357702 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda +sha256: e25c314b52764219f842b41aea2c98a059f06437392268f09b03561e4f6e5309 +md5: 7fc6affb9b01e567d2ef1d05b84aa6ed +depends: +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +constrains: +- xorg-libx11 >=1.8.12,<2.0a0 +license: TCL +license_family: BSD +size: 3368666 +timestamp: 1769464148928 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 +md5: e5ce43272193b38c2e9037446c1d9206 +depends: +- python >=3.10 +- __unix +- python +license: MPL-2.0 and MIT +size: 94132 +timestamp: 1770153424136 +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +sha256: 59d7851d32fddb5b510272e6557aa982edeb927d349648dac27f5bf01d18bb26 +md5: 4460f039b7dedf15f7df086446ca75ae +depends: +- typing_extensions >=4.14.0 +- python >=3.10 +- importlib-metadata >=3.6 +- python +constrains: +- pytest >=7 +license: MIT +license_family: MIT +size: 38297 +timestamp: 1778779291237 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c +md5: edd329d7d3a4ab45dcf905899a7a6115 +depends: +- typing_extensions ==4.15.0 pyhcf101f3_0 +license: PSF-2.0 +license_family: PSF +size: 91383 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +sha256: 8b90d2f19f9458b8c58a55e1fcdc1d90c1603a847a47654d8a454549413ba60a +md5: 53f5409c5cfd6c5a66417d68e3f0a864 +depends: +- python >=3.10 +- typing_extensions >=4.12.0 +- python +license: MIT +license_family: MIT +size: 20935 +timestamp: 1777105465795 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 +md5: 0caa1af407ecff61170c9437a808404d +depends: +- python >=3.10 +- python +license: PSF-2.0 +license_family: PSF +size: 51692 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c +md5: ad659d0a2b3e47e38d829aa8cad2d610 +license: LicenseRef-Public-Domain +size: 119135 +timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 +md5: cbb88288f74dbe6ada1c6c7d0a97223e +depends: +- backports.zstd >=1.0.0 +- brotli-python >=1.2.0 +- h2 >=4,<5 +- pysocks >=1.5.6,<2.0,!=1.5.7 +- python >=3.10 +license: MIT +license_family: MIT +size: 103560 +timestamp: 1778188657149 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 +md5: 1c246e1105000c3660558459e2fd6d43 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 16317 +timestamp: 1762977521691 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1 +md5: bff06dcde4a707339d66d45d96ceb2e2 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 21039 +timestamp: 1762979038025 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda +sha256: 66265e943f32ce02396ad214e27cb35f5b0490b3bd4f064446390f9d67fa5d88 +md5: 032d8030e4a24fe1f72c74423a46fb88 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 88088 +timestamp: 1753484092643 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +sha256: 210bd31c22bb88f5e2a167df24c95bb5f152b2ada7502f9b8c49d1f5366db423 +md5: ba3dcdc8584155c97c648ae9c044b7a3 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 24190 +timestamp: 1779159948016 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda +sha256: 638a3a41a4fbfed52d3c60c8ef5a3693b3f12a5b1a3f58fa29f5698d0a0702e2 +md5: f731af71c723065d91b4c01bb822641b +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Zlib +license_family: Other +size: 121046 +timestamp: 1770167944449 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 +md5: c3655f82dcea2aa179b291e7099c1fcc +depends: +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 614429 +timestamp: 1764777145593 diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml new file mode 100644 index 0000000..7a970e2 --- /dev/null +++ b/modules/nf-core/multiqc/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::multiqc=1.35 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf new file mode 100644 index 0000000..c4bc715 --- /dev/null +++ b/modules/nf-core/multiqc/main.nf @@ -0,0 +1,50 @@ +process MULTIQC { + tag "${meta.id}" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' + : 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc'}" + + input: + tuple val(meta), path(multiqc_files, stageAs: "?/*"), path(multiqc_config, stageAs: "?/*"), path(multiqc_logo), path(replace_names), path(sample_names) + + output: + tuple val(meta), path("*.html"), emit: report + tuple val(meta), path("*_data"), emit: data + tuple val(meta), path("*_plots"), emit: plots, optional: true + // MultiQC should not push its versions to the `versions` topic. Its input depends on the versions topic to be resolved thus outputting to the topic will let the pipeline hang forever + tuple val("${task.process}"), val('multiqc'), eval('multiqc --version | sed "s/.* //g"'), emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' + def config = multiqc_config ? multiqc_config instanceof List ? "--config ${multiqc_config.join(' --config ')}" : "--config ${multiqc_config}" : "" + def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' + def replace = replace_names ? "--replace-names ${replace_names}" : '' + def samples = sample_names ? "--sample-names ${sample_names}" : '' + """ + multiqc \\ + --force \\ + ${args} \\ + ${config} \\ + ${prefix} \\ + ${logo} \\ + ${replace} \\ + ${samples} \\ + . + """ + + stub: + """ + mkdir multiqc_data + touch multiqc_data/.stub + mkdir multiqc_plots + touch multiqc_plots/.stub + touch multiqc_report.html + """ +} diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml new file mode 100644 index 0000000..27ce18d --- /dev/null +++ b/modules/nf-core/multiqc/meta.yml @@ -0,0 +1,133 @@ +name: multiqc +description: Aggregate results from bioinformatics analyses across many samples + into a single report +keywords: + - QC + - bioinformatics tools + - Beautiful stand-alone HTML report +tools: + - multiqc: + description: | + MultiQC searches a given directory for analysis logs and compiles a HTML report. + It's a general use tool, perfect for summarising the output from numerous bioinformatics tools. + homepage: https://multiqc.info/ + documentation: https://multiqc.info/docs/ + licence: + - "GPL-3.0-or-later" + identifier: biotools:multiqc +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - multiqc_files: + type: file + description: | + List of reports / files recognised by MultiQC, for example the html and zip output of FastQC + ontologies: [] + - multiqc_config: + type: file + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + ontologies: + - edam: http://edamontology.org/format_3750 + - multiqc_logo: + type: file + description: Optional logo file for MultiQC + pattern: "*.{png}" + ontologies: [] + - replace_names: + type: file + description: | + Optional two-column sample renaming file. First column a set of + patterns, second column a set of corresponding replacements. Passed via + MultiQC's `--replace-names` option. + pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 + - sample_names: + type: file + description: | + Optional TSV file with headers, passed to the MultiQC --sample_names + argument. + pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 +output: + report: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*.html": + type: file + description: MultiQC report file + pattern: ".html" + ontologies: [] + data: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*_data": + type: directory + description: MultiQC data dir + pattern: "multiqc_data" + plots: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*_plots": + type: file + description: Plots created by MultiQC + pattern: "*_plots" + ontologies: [] + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - multiqc: + type: string + description: The tool name + - multiqc --version | sed "s/.* //g": + type: eval + description: The expression to obtain the version of the tool +authors: + - "@abhi18av" + - "@bunop" + - "@drpatelh" + - "@jfy133" +maintainers: + - "@abhi18av" + - "@bunop" + - "@drpatelh" + - "@jfy133" +containers: + conda: + linux/amd64: + lock_file: modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt + linux/arm64: + lock_file: modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt + docker: + linux/amd64: + name: community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc + build_id: bd-c17fb751507e9dfc_1 + scan_id: sc-3b1b3932f9846892_1 + linux/arm64: + name: community.wave.seqera.io/library/multiqc:1.35--5c84a5000a226ab5 + build_id: bd-5c84a5000a226ab5_1 + scan_id: sc-0d39df41e9737bbd_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2 + build_id: bd-c680f2aea25ccec2_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data + linux/arm64: + name: oras://community.wave.seqera.io/library/multiqc:1.35--c0468833d65b2f81 + build_id: bd-c0468833d65b2f81_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e4/e48aa28aebc881254a499b24c3e1ce77b8df1b85a5432699ed6f72eb17ac7fb5/data diff --git a/modules/nf-core/multiqc/tests/custom_prefix.config b/modules/nf-core/multiqc/tests/custom_prefix.config new file mode 100644 index 0000000..b30b135 --- /dev/null +++ b/modules/nf-core/multiqc/tests/custom_prefix.config @@ -0,0 +1,5 @@ +process { + withName: 'MULTIQC' { + ext.prefix = "custom_prefix" + } +} diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test new file mode 100644 index 0000000..4cbdb95 --- /dev/null +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -0,0 +1,211 @@ +nextflow_process { + + name "Test Process MULTIQC" + script "../main.nf" + process "MULTIQC" + + tag "modules" + tag "modules_nfcore" + tag "multiqc" + + config "./nextflow.config" + + test("sarscov2 single-end [fastqc]") { + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) + """ + } + } + + then { + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } + } + + test("sarscov2 single-end [fastqc] - custom prefix") { + config "./custom_prefix.config" + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) + """ + } + } + + then { + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } + } + + test("sarscov2 single-end [fastqc] [config]") { + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true), + [], + [], + [] + ]) + """ + } + } + + then { + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } + } + + test("sarscov2 single-end [fastqc] [multiple configs]") { + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [ + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true), + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true) + ], + [], + [], + [] + ]) + """ + } + } + + then { + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } + } + + test("sarscov2 single-end [fastqc] - stub") { + + options "-stub" + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot(sanitizeOutput(process.out)).match() } + ) + } + } +} diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap new file mode 100644 index 0000000..4489921 --- /dev/null +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -0,0 +1,422 @@ +{ + "sarscov2 single-end [fastqc] [multiple configs]": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.35" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:42.577775492", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "sarscov2 single-end [fastqc]": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_software_versions.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.35" + ] + ] + } + ], + "timestamp": "2026-03-17T16:21:17.072841555", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "sarscov2 single-end [fastqc] - stub": { + "content": [ + { + "data": [ + [ + { + "id": "FASTQC" + }, + [ + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "plots": [ + [ + { + "id": "FASTQC" + }, + [ + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "report": [ + [ + { + "id": "FASTQC" + }, + "multiqc_report.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.35" + ] + ] + } + ], + "timestamp": "2026-02-26T15:14:39.789193051", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "sarscov2 single-end [fastqc] [config]": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.35" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:30.372239611", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "sarscov2 single-end [fastqc] - custom prefix": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_software_versions.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "custom_prefix.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.35" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:18.189023981", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/multiqc/tests/nextflow.config b/modules/nf-core/multiqc/tests/nextflow.config new file mode 100644 index 0000000..374dfef --- /dev/null +++ b/modules/nf-core/multiqc/tests/nextflow.config @@ -0,0 +1,6 @@ +process { + withName: 'MULTIQC' { + ext.prefix = null + ext.args = '-p' + } +} diff --git a/modules/nf-core/samtools/flagstat/environment.yml b/modules/nf-core/samtools/flagstat/environment.yml new file mode 100644 index 0000000..946bb36 --- /dev/null +++ b/modules/nf-core/samtools/flagstat/environment.yml @@ -0,0 +1,10 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + # renovate: datasource=conda depName=bioconda/htslib + - bioconda::htslib=1.23.1 + # renovate: datasource=conda depName=bioconda/samtools + - bioconda::samtools=1.23.1 diff --git a/modules/nf-core/samtools/flagstat/main.nf b/modules/nf-core/samtools/flagstat/main.nf new file mode 100644 index 0000000..2d9588b --- /dev/null +++ b/modules/nf-core/samtools/flagstat/main.nf @@ -0,0 +1,47 @@ +process SAMTOOLS_FLAGSTAT { + tag "${meta.id}" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8c/8c5d2818c8b9f58e1fba77ce219fdaf32087ae53e857c4a496402978af26e78c/data' + : 'community.wave.seqera.io/library/htslib_samtools:1.23.1--5b6bb4ede7e612e5'}" + + input: + tuple val(meta), path(bam), path(bai) + + output: + tuple val(meta), path("*.flagstat"), emit: flagstat + tuple val("${task.process}"), val('samtools'), eval("samtools version | sed '1!d;s/.* //'"), emit: versions_samtools, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + samtools \\ + flagstat \\ + --threads ${task.cpus} \\ + ${bam} \\ + > ${prefix}.flagstat + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + cat <<-END_FLAGSTAT > ${prefix}.flagstat + 1000000 + 0 in total (QC-passed reads + QC-failed reads) + 0 + 0 secondary + 0 + 0 supplementary + 0 + 0 duplicates + 900000 + 0 mapped (90.00% : N/A) + 1000000 + 0 paired in sequencing + 500000 + 0 read1 + 500000 + 0 read2 + 800000 + 0 properly paired (80.00% : N/A) + 850000 + 0 with mate mapped to a different chr + 50000 + 0 with mate mapped to a different chr (mapQ>=5) + END_FLAGSTAT + """ +} diff --git a/modules/nf-core/samtools/flagstat/meta.yml b/modules/nf-core/samtools/flagstat/meta.yml new file mode 100644 index 0000000..f658acd --- /dev/null +++ b/modules/nf-core/samtools/flagstat/meta.yml @@ -0,0 +1,76 @@ +name: samtools_flagstat +description: Counts the number of alignments in a BAM/CRAM/SAM file for each + FLAG type +keywords: + - stats + - mapping + - counts + - bam + - sam + - cram +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: + - "MIT" + identifier: biotools:samtools +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + ontologies: [] + - bai: + type: file + description: Index for BAM/CRAM/SAM file + pattern: "*.{bai,crai,sai}" + ontologies: [] +output: + flagstat: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.flagstat": + type: file + description: File containing samtools flagstat output + pattern: "*.{flagstat}" + ontologies: [] + versions_samtools: + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - samtools version | sed '1!d;s/.* //': + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - samtools version | sed '1!d;s/.* //': + type: eval + description: The expression to obtain the version of the tool +authors: + - "@drpatelh" +maintainers: + - "@drpatelh" + - "@matthdsm" diff --git a/modules/nf-core/samtools/flagstat/tests/main.nf.test b/modules/nf-core/samtools/flagstat/tests/main.nf.test new file mode 100644 index 0000000..3b648a3 --- /dev/null +++ b/modules/nf-core/samtools/flagstat/tests/main.nf.test @@ -0,0 +1,56 @@ +nextflow_process { + + name "Test Process SAMTOOLS_FLAGSTAT" + script "../main.nf" + process "SAMTOOLS_FLAGSTAT" + tag "modules" + tag "modules_nfcore" + tag "samtools" + tag "samtools/flagstat" + + test("BAM") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("BAM - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/samtools/flagstat/tests/main.nf.test.snap b/modules/nf-core/samtools/flagstat/tests/main.nf.test.snap new file mode 100644 index 0000000..b110c47 --- /dev/null +++ b/modules/nf-core/samtools/flagstat/tests/main.nf.test.snap @@ -0,0 +1,88 @@ +{ + "BAM - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.flagstat:md5,67394650dbae96d1a4fcc70484822159" + ] + ], + "1": [ + [ + "SAMTOOLS_FLAGSTAT", + "samtools", + "1.23.1" + ] + ], + "flagstat": [ + [ + { + "id": "test", + "single_end": false + }, + "test.flagstat:md5,67394650dbae96d1a4fcc70484822159" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_FLAGSTAT", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T08:59:26.188788" + }, + "BAM": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.flagstat:md5,4f7ffd1e6a5e85524d443209ac97d783" + ] + ], + "1": [ + [ + "SAMTOOLS_FLAGSTAT", + "samtools", + "1.23.1" + ] + ], + "flagstat": [ + [ + { + "id": "test", + "single_end": false + }, + "test.flagstat:md5,4f7ffd1e6a5e85524d443209ac97d783" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_FLAGSTAT", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T08:59:20.212002" + } +} \ No newline at end of file diff --git a/modules/nf-core/samtools/idxstats/environment.yml b/modules/nf-core/samtools/idxstats/environment.yml new file mode 100644 index 0000000..946bb36 --- /dev/null +++ b/modules/nf-core/samtools/idxstats/environment.yml @@ -0,0 +1,10 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + # renovate: datasource=conda depName=bioconda/htslib + - bioconda::htslib=1.23.1 + # renovate: datasource=conda depName=bioconda/samtools + - bioconda::samtools=1.23.1 diff --git a/modules/nf-core/samtools/idxstats/main.nf b/modules/nf-core/samtools/idxstats/main.nf new file mode 100644 index 0000000..4d74768 --- /dev/null +++ b/modules/nf-core/samtools/idxstats/main.nf @@ -0,0 +1,38 @@ +process SAMTOOLS_IDXSTATS { + tag "${meta.id}" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8c/8c5d2818c8b9f58e1fba77ce219fdaf32087ae53e857c4a496402978af26e78c/data' + : 'community.wave.seqera.io/library/htslib_samtools:1.23.1--5b6bb4ede7e612e5'}" + + input: + tuple val(meta), path(bam), path(bai) + + output: + tuple val(meta), path("*.idxstats"), emit: idxstats + tuple val("${task.process}"), val('samtools'), eval("samtools version | sed '1!d;s/.* //'"), emit: versions_samtools, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def prefix = task.ext.prefix ?: "${meta.id}" + + """ + # Note: --threads value represents *additional* CPUs to allocate (total CPUs = 1 + --threads). + samtools \\ + idxstats \\ + --threads ${task.cpus - 1} \\ + ${bam} \\ + > ${prefix}.idxstats + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + + """ + touch ${prefix}.idxstats + """ +} diff --git a/modules/nf-core/samtools/idxstats/meta.yml b/modules/nf-core/samtools/idxstats/meta.yml new file mode 100644 index 0000000..0f9fb3d --- /dev/null +++ b/modules/nf-core/samtools/idxstats/meta.yml @@ -0,0 +1,76 @@ +name: samtools_idxstats +description: Reports alignment summary statistics for a BAM/CRAM/SAM file +keywords: + - stats + - mapping + - counts + - chromosome + - bam + - sam + - cram +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: + - "MIT" + identifier: biotools:samtools +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - bam: + type: file + description: BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + ontologies: [] + - bai: + type: file + description: Index for BAM/CRAM/SAM file + pattern: "*.{bai,crai,sai}" + ontologies: [] +output: + idxstats: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.idxstats": + type: file + description: File containing samtools idxstats output + pattern: "*.{idxstats}" + ontologies: [] + versions_samtools: + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - samtools version | sed '1!d;s/.* //': + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - samtools version | sed '1!d;s/.* //': + type: eval + description: The expression to obtain the version of the tool +authors: + - "@drpatelh" +maintainers: + - "@drpatelh" + - "@matthdsm" diff --git a/modules/nf-core/samtools/idxstats/tests/main.nf.test b/modules/nf-core/samtools/idxstats/tests/main.nf.test new file mode 100644 index 0000000..c990cd5 --- /dev/null +++ b/modules/nf-core/samtools/idxstats/tests/main.nf.test @@ -0,0 +1,59 @@ +nextflow_process { + + name "Test Process SAMTOOLS_IDXSTATS" + script "../main.nf" + process "SAMTOOLS_IDXSTATS" + tag "modules" + tag "modules_nfcore" + tag "samtools" + tag "samtools/idxstats" + + test("bam") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + process.out.idxstats, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } + ) + } + } + + test("bam - stub") { + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot( + process.out.idxstats, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } + ) + } + }} diff --git a/modules/nf-core/samtools/idxstats/tests/main.nf.test.snap b/modules/nf-core/samtools/idxstats/tests/main.nf.test.snap new file mode 100644 index 0000000..7bcde2f --- /dev/null +++ b/modules/nf-core/samtools/idxstats/tests/main.nf.test.snap @@ -0,0 +1,56 @@ +{ + "bam - stub": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.idxstats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + { + "versions_samtools": [ + [ + "SAMTOOLS_IDXSTATS", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T08:59:41.877526" + }, + "bam": { + "content": [ + [ + [ + { + "id": "test", + "single_end": false + }, + "test.idxstats:md5,df60a8c8d6621100d05178c93fb053a2" + ] + ], + { + "versions_samtools": [ + [ + "SAMTOOLS_IDXSTATS", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T08:59:34.725514" + } +} \ No newline at end of file diff --git a/modules/nf-core/samtools/quickcheck/environment.yml b/modules/nf-core/samtools/quickcheck/environment.yml new file mode 100644 index 0000000..310db6d --- /dev/null +++ b/modules/nf-core/samtools/quickcheck/environment.yml @@ -0,0 +1,8 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - "bioconda::samtools=1.23" + - "bioconda::htslib=1.23.1" diff --git a/modules/nf-core/samtools/quickcheck/main.nf b/modules/nf-core/samtools/quickcheck/main.nf new file mode 100644 index 0000000..0b877d6 --- /dev/null +++ b/modules/nf-core/samtools/quickcheck/main.nf @@ -0,0 +1,36 @@ +process SAMTOOLS_QUICKCHECK { + tag "${meta.id}" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8c/8c5d2818c8b9f58e1fba77ce219fdaf32087ae53e857c4a496402978af26e78c/data' + : 'community.wave.seqera.io/library/htslib_samtools:1.23.1--5b6bb4ede7e612e5'}" + + input: + tuple val(meta), path(bam) + + output: + tuple val(meta), path(bam), env("EXIT_CODE"), emit: bam + tuple val("${task.process}"), val('samtools'), eval("samtools version | sed '1!d;s/.* //'"), topic: versions, emit: versions_samtools + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + samtools quickcheck \\ + ${args} \\ + ${bam} || EXIT_CODE=\$? + + EXIT_CODE=\${EXIT_CODE:-0} + """ + + stub: + def args = task.ext.args ?: '' + """ + EXIT_CODE=0 + echo ${args} + """ +} diff --git a/modules/nf-core/samtools/quickcheck/meta.yml b/modules/nf-core/samtools/quickcheck/meta.yml new file mode 100644 index 0000000..64e44b6 --- /dev/null +++ b/modules/nf-core/samtools/quickcheck/meta.yml @@ -0,0 +1,76 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "samtools_quickcheck" +description: Quickly check that input files appear to be intact. Checks that beginning of the file contains a valid header (all formats) containing at least one target sequence and then seeks to the end of the file and checks that an end-of-file (EOF) is present and intact (BAM and CRAM only). Alignment records are not checked. The quickcheck module returns a non-zero EXIT_CODE if any input files don't have a valid header or are missing an EOF block. Otherwise EXIT_CODE is zero. +keywords: + - check + - quickcheck + - sam + - bam + - cram +tools: + - "samtools": + description: "Tools for dealing with SAM, BAM and CRAM files" + homepage: "https://www.htslib.org/" + documentation: "https://www.htslib.org/doc/samtools-quickcheck.html" + tool_dev_url: "https://github.com/samtools/" + doi: "10.1093/bioinformatics/btp352" + licence: ["MIT"] + identifier: biotools:samtools + +input: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - bam: + type: file + description: sequence_trace file + pattern: "*.{cram,sam,bam}" + ontologies: + - edam: http://edamontology.org/data_0924 # Sequence trace + - edam: http://edamontology.org/format_3462 # CRAM + - edam: http://edamontology.org/format_2573 # SAM + - edam: http://edamontology.org/format_2572 # BAM +output: + bam: + - - meta: + type: map + description: Groovy Map containing sample information. e.g. `[ id:'sample1' ]` + - bam: + type: file + description: sequence_trace file + pattern: "*.{cram,sam,bam}" + ontologies: + - edam: http://edamontology.org/data_0924 # Sequence trace + - edam: http://edamontology.org/format_3462 # CRAM + - edam: http://edamontology.org/format_2573 # SAM + - edam: http://edamontology.org/format_2572 # BAM + - EXIT_CODE: + type: string + description: Exit code (0 for success, non-zero otherwise) that is the result of the format check. + ontologies: [] + versions_samtools: + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - "samtools version | sed '1!d;s/.* //'": + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - samtools: + type: string + description: The name of the tool + - "samtools version | sed '1!d;s/.* //'": + type: eval + description: The expression to obtain the version of the tool +authors: + - "@Krannich479" +maintainers: + - "@Krannich479" + - "@matthdsm" diff --git a/modules/nf-core/samtools/quickcheck/tests/main.nf.test b/modules/nf-core/samtools/quickcheck/tests/main.nf.test new file mode 100644 index 0000000..a4a0748 --- /dev/null +++ b/modules/nf-core/samtools/quickcheck/tests/main.nf.test @@ -0,0 +1,207 @@ +// nf-core modules test samtools/quickcheck +nextflow_process { + + name "Test Process SAMTOOLS_QUICKCHECK" + script "../main.nf" + process "SAMTOOLS_QUICKCHECK" + + tag "modules" + tag "modules_nfcore" + tag "samtools" + tag "samtools/quickcheck" + + test(" bam - PE ") { + when { + process { + """ + input[0] = Channel.of([ + [ id:'test.paired_end.sorted' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.bam.collect{ it[2] } == ["0"] }, + { assert snapshot(process.out).match() } + ) + } + } + + test(" bam - SE ") { + when { + process { + """ + input[0] = [ + [ id:'test.single_end.sorted' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.single_end.sorted.bam', checkIfExists: true), + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.bam.collect{ it[2] } == ["0"] }, + { assert snapshot(process.out).match() } + ) + } + } + + test(" bam - PE - stub") { + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test.paired_end.sorted' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.bam.collect{ it[2] } == ["0"] }, + { assert snapshot(process.out).match() } + ) + } + } + + test(" cram - PE ") { + when { + process { + """ + input[0] = Channel.of([ + [ id:'test.paired_end.sorted' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.sorted.cram', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.bam.collect{ it[2] } == ["0"] }, + { assert snapshot(process.out).match() } + ) + } + } + + test(" sam - PE - No targets") { + /* SAM header misses targets of corresponding alignments */ + when { + process { + """ + input[0] = [ + [ id:'test.paired_end.sorted' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.invalid.sam', checkIfExists: true), + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.bam.collect{ it[2] } == ["8"] }, + { assert snapshot(process.out).match() } + ) + } + } + + test(" sam - PE - No targets - ignore targets / unaligned option") { + /* SAM header misses targets of corresponding alignments, but the '-u' parameter makes this tolerated as unaligned */ + config "./nextflow.config" + + when { + process { + """ + input[0] = [ + [ id:'test.paired_end.sorted' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.invalid.sam', checkIfExists: true), + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.bam.collect{ it[2] } == ["0"] }, + { assert snapshot(process.out).match() } + ) + } + } + + test(" bam - ?E - Bad EOF") { + when { + process { + """ + input[0] = [ + [ id:'1.quickcheck.badeof' ], + file('https://github.com/samtools/samtools/raw/refs/heads/develop/test/quickcheck/1.quickcheck.badeof.bam', checkIfExists: true), + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.bam.collect{ it[2] } == ["16"] }, + { assert snapshot(process.out).match() } + ) + } + } + + test(" bam - ?E - No targets") { + when { + process { + """ + input[0] = [ + [ id:'10.quickcheck.notargets' ], + file('https://github.com/samtools/samtools/raw/refs/heads/develop/test/quickcheck/10.quickcheck.notargets.bam', checkIfExists: true), + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.bam.collect{ it[2] } == ["8"] }, + { assert snapshot(process.out).match() } + ) + } + } + + test(" bam - ?E - Bad header") { + when { + process { + """ + input[0] = [ + [ id:'2.quickcheck.badheader' ], + file('https://github.com/samtools/samtools/raw/refs/heads/develop/test/quickcheck/2.quickcheck.badheader.bam', checkIfExists: true), + ] + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.bam.collect{ it[2] } == ["4"] }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/samtools/quickcheck/tests/main.nf.test.snap b/modules/nf-core/samtools/quickcheck/tests/main.nf.test.snap new file mode 100644 index 0000000..a048e5a --- /dev/null +++ b/modules/nf-core/samtools/quickcheck/tests/main.nf.test.snap @@ -0,0 +1,389 @@ +{ + " bam - PE - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.bam:md5,fb76969225f658c10e4cdf496b703a61", + "0" + ] + ], + "1": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ], + "bam": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.bam:md5,fb76969225f658c10e4cdf496b703a61", + "0" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:02:12.590185" + }, + " sam - PE - No targets": { + "content": [ + { + "0": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.invalid.sam:md5,c9307be2f9d47f648c1bb864b3e12542", + "8" + ] + ], + "1": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ], + "bam": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.invalid.sam:md5,c9307be2f9d47f648c1bb864b3e12542", + "8" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:02:23.072247" + }, + " bam - SE ": { + "content": [ + { + "0": [ + [ + { + "id": "test.single_end.sorted" + }, + "test.single_end.sorted.bam:md5,e29aca28f0d40c6637139fc008f3f2c9", + "0" + ] + ], + "1": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ], + "bam": [ + [ + { + "id": "test.single_end.sorted" + }, + "test.single_end.sorted.bam:md5,e29aca28f0d40c6637139fc008f3f2c9", + "0" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:02:05.559532" + }, + " cram - PE ": { + "content": [ + { + "0": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.cram:md5,e0146aa3a5a196e4cb5593f545e95c31", + "0" + ] + ], + "1": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ], + "bam": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.cram:md5,e0146aa3a5a196e4cb5593f545e95c31", + "0" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:02:17.843915" + }, + " bam - PE ": { + "content": [ + { + "0": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.bam:md5,fb76969225f658c10e4cdf496b703a61", + "0" + ] + ], + "1": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ], + "bam": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.bam:md5,fb76969225f658c10e4cdf496b703a61", + "0" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:01:59.948119" + }, + " bam - ?E - Bad EOF": { + "content": [ + { + "0": [ + [ + { + "id": "1.quickcheck.badeof" + }, + "1.quickcheck.badeof.bam:md5,e389fce53b839a9b65fd9b25bd448d8b", + "16" + ] + ], + "1": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ], + "bam": [ + [ + { + "id": "1.quickcheck.badeof" + }, + "1.quickcheck.badeof.bam:md5,e389fce53b839a9b65fd9b25bd448d8b", + "16" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:02:33.740526" + }, + " bam - ?E - No targets": { + "content": [ + { + "0": [ + [ + { + "id": "10.quickcheck.notargets" + }, + "10.quickcheck.notargets.bam:md5,89fc7ae65ec7e624d1ce1d4499d4b43a", + "8" + ] + ], + "1": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ], + "bam": [ + [ + { + "id": "10.quickcheck.notargets" + }, + "10.quickcheck.notargets.bam:md5,89fc7ae65ec7e624d1ce1d4499d4b43a", + "8" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:02:40.774367" + }, + " sam - PE - No targets - ignore targets / unaligned option": { + "content": [ + { + "0": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.invalid.sam:md5,c9307be2f9d47f648c1bb864b3e12542", + "0" + ] + ], + "1": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ], + "bam": [ + [ + { + "id": "test.paired_end.sorted" + }, + "test.paired_end.sorted.invalid.sam:md5,c9307be2f9d47f648c1bb864b3e12542", + "0" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:02:28.064753" + }, + " bam - ?E - Bad header": { + "content": [ + { + "0": [ + [ + { + "id": "2.quickcheck.badheader" + }, + "2.quickcheck.badheader.bam:md5,7c9300a04c23ee607dcc95e26f318932", + "4" + ] + ], + "1": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ], + "bam": [ + [ + { + "id": "2.quickcheck.badheader" + }, + "2.quickcheck.badheader.bam:md5,7c9300a04c23ee607dcc95e26f318932", + "4" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_QUICKCHECK", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:02:46.357687" + } +} \ No newline at end of file diff --git a/modules/nf-core/samtools/quickcheck/tests/nextflow.config b/modules/nf-core/samtools/quickcheck/tests/nextflow.config new file mode 100644 index 0000000..b6d217a --- /dev/null +++ b/modules/nf-core/samtools/quickcheck/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: SAMTOOLS_QUICKCHECK { + ext.args = '-u' + } +} diff --git a/modules/nf-core/samtools/stats/environment.yml b/modules/nf-core/samtools/stats/environment.yml new file mode 100644 index 0000000..946bb36 --- /dev/null +++ b/modules/nf-core/samtools/stats/environment.yml @@ -0,0 +1,10 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + # renovate: datasource=conda depName=bioconda/htslib + - bioconda::htslib=1.23.1 + # renovate: datasource=conda depName=bioconda/samtools + - bioconda::samtools=1.23.1 diff --git a/modules/nf-core/samtools/stats/main.nf b/modules/nf-core/samtools/stats/main.nf new file mode 100644 index 0000000..28457e6 --- /dev/null +++ b/modules/nf-core/samtools/stats/main.nf @@ -0,0 +1,40 @@ +process SAMTOOLS_STATS { + tag "${meta.id}" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8c/8c5d2818c8b9f58e1fba77ce219fdaf32087ae53e857c4a496402978af26e78c/data' + : 'community.wave.seqera.io/library/htslib_samtools:1.23.1--5b6bb4ede7e612e5'}" + + input: + tuple val(meta), path(input), path(input_index) + tuple val(meta2), path(fasta), path(fai) + + output: + tuple val(meta), path("*.stats"), emit: stats + tuple val("${task.process}"), val('samtools'), eval('samtools version | sed "1!d;s/.* //"'), emit: versions_samtools, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def reference = fasta ? "--reference ${fasta}" : "" + """ + samtools \\ + stats \\ + ${args} \\ + --threads ${task.cpus} \\ + ${reference} \\ + ${input} \\ + > ${prefix}.stats + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.stats + """ +} diff --git a/modules/nf-core/samtools/stats/meta.yml b/modules/nf-core/samtools/stats/meta.yml new file mode 100644 index 0000000..5fd7e76 --- /dev/null +++ b/modules/nf-core/samtools/stats/meta.yml @@ -0,0 +1,94 @@ +name: samtools_stats +description: Produces comprehensive statistics from SAM/BAM/CRAM file +keywords: + - statistics + - counts + - bam + - sam + - cram +tools: + - samtools: + description: | + SAMtools is a set of utilities for interacting with and post-processing + short DNA sequence read alignments in the SAM, BAM and CRAM formats, written by Heng Li. + These files are generated as output by short read aligners like BWA. + homepage: http://www.htslib.org/ + documentation: http://www.htslib.org/doc/samtools.html + doi: 10.1093/bioinformatics/btp352 + licence: ["MIT"] + identifier: biotools:samtools +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input: + type: file + description: BAM/CRAM file from alignment + pattern: "*.{bam,cram}" + ontologies: [] + - input_index: + type: file + description: BAI/CRAI file from alignment + pattern: "*.{bai,crai}" + ontologies: [] + - - meta2: + type: map + description: | + Groovy Map containing reference information + e.g. [ id:'genome' ] + - fasta: + type: file + description: Reference file the CRAM was created with (optional) + pattern: "*.{fasta,fa,fna}" + ontologies: [] + - fai: + type: file + description: FASTA ref index file + pattern: "*.{fasta,fa,fna}.fai" + ontologies: [] +output: + stats: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.stats": + type: file + description: File containing samtools stats output + pattern: "*.{stats}" + ontologies: [] + versions_samtools: + - - ${task.process}: + type: string + description: Name of the process + - samtools: + type: string + description: Name of the tool + - samtools version | sed "1!d;s/.* //": + type: eval + description: The expression to obtain the version of the tool + +topics: + versions: + - - ${task.process}: + type: string + description: Name of the process + - samtools: + type: string + description: Name of the tool + - samtools version | sed "1!d;s/.* //": + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@drpatelh" + - "@FriederikeHanssen" + - "@ramprasadn" +maintainers: + - "@drpatelh" + - "@FriederikeHanssen" + - "@ramprasadn" + - "@matthdsm" diff --git a/modules/nf-core/samtools/stats/tests/main.nf.test b/modules/nf-core/samtools/stats/tests/main.nf.test new file mode 100644 index 0000000..140adf3 --- /dev/null +++ b/modules/nf-core/samtools/stats/tests/main.nf.test @@ -0,0 +1,115 @@ +nextflow_process { + + name "Test Process SAMTOOLS_STATS" + script "../main.nf" + process "SAMTOOLS_STATS" + + tag "modules" + tag "modules_nfcore" + tag "samtools" + tag "samtools/stats" + + test("bam") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ]) + input[1] = [[],[],[]] + """ + } + } + + then { + assertAll( + {assert process.success}, + {assert snapshot(process.out).match()} + ) + } + } + + test("cram") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram.crai', checkIfExists: true) + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + {assert process.success}, + {assert snapshot(process.out).match()} + ) + } + } + + test("bam - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam.bai', checkIfExists: true) + ]) + input[1] = [[],[],[]] + """ + } + } + + then { + assertAll( + {assert process.success}, + {assert snapshot(process.out).match()} + ) + } + } + + test("cram - stub") { + + options "-stub" + + when { + process { + """ + input[0] = Channel.of([ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/cram/test.paired_end.recalibrated.sorted.cram.crai', checkIfExists: true) + ]) + input[1] = Channel.of([ + [ id:'genome' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll( + {assert process.success}, + {assert snapshot(process.out).match()} + ) + } + } +} diff --git a/modules/nf-core/samtools/stats/tests/main.nf.test.snap b/modules/nf-core/samtools/stats/tests/main.nf.test.snap new file mode 100644 index 0000000..975d44a --- /dev/null +++ b/modules/nf-core/samtools/stats/tests/main.nf.test.snap @@ -0,0 +1,174 @@ +{ + "cram": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,e4d6cf0e75cebd0bafa84141e0b6929b" + ] + ], + "1": [ + [ + "SAMTOOLS_STATS", + "samtools", + "1.23.1" + ] + ], + "stats": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,e4d6cf0e75cebd0bafa84141e0b6929b" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_STATS", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:05:39.987454" + }, + "bam - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + "SAMTOOLS_STATS", + "samtools", + "1.23.1" + ] + ], + "stats": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_STATS", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:05:47.495502" + }, + "cram - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + "SAMTOOLS_STATS", + "samtools", + "1.23.1" + ] + ], + "stats": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_STATS", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:05:56.38373" + }, + "bam": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,80f94eb0b68e213bdc8231109d3b43ad" + ] + ], + "1": [ + [ + "SAMTOOLS_STATS", + "samtools", + "1.23.1" + ] + ], + "stats": [ + [ + { + "id": "test", + "single_end": false + }, + "test.stats:md5,80f94eb0b68e213bdc8231109d3b43ad" + ] + ], + "versions_samtools": [ + [ + "SAMTOOLS_STATS", + "samtools", + "1.23.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-03-19T09:05:24.59441" + } +} \ No newline at end of file diff --git a/scripts/core_runtime/Split_ReadsV2.codon b/scripts/core_runtime/Split_ReadsV2.codon index aceb5c8..c430d1b 100755 --- a/scripts/core_runtime/Split_ReadsV2.codon +++ b/scripts/core_runtime/Split_ReadsV2.codon @@ -354,7 +354,7 @@ def gid_from_sb_raw(sample: str, sb_raw: str, sb_to_gid: Dict[str, int]) -> int: # defensive: if some inputs ever already have injected base removed if sb_raw in sb_to_gid: return sb_to_gid[sb_raw] - + key1 = normalize_sb_drop_first(sb_raw) if key1 in sb_to_gid: return sb_to_gid[key1] diff --git a/scripts/core_runtime/Tag.codon b/scripts/core_runtime/Tag.codon index 182b6b4..9e9dce0 100755 --- a/scripts/core_runtime/Tag.codon +++ b/scripts/core_runtime/Tag.codon @@ -29,7 +29,7 @@ def read_barcode_whitelist_from_file(bc_whitelist_filename: str): with open(bc_whitelist_filename, "r") as fh: [bc_whitelist.add(Kmer[BC_LEN](seq(bc_line.strip()))) for bc_line in fh] - + return bc_whitelist # Function to get the filename and extension @@ -42,7 +42,7 @@ def split_filename(filepath): else: name, ext1 = filename.rsplit('.', 1) return name, ext1 - + def tag_fastq( I2:str, R1:str, @@ -106,7 +106,7 @@ def tag_fastq( R1_tagged_outpath_fh = open(R1_tagged_outpath, 'w') R2_tagged_outpath = f"{out_folder}/{R2_fname}_{tag}.{R2_ext}" R2_tagged_outpath_fh = open(R2_tagged_outpath, 'w') - + # Initialize barcode and stats lists corr_bcs = List[str](capacity=500000000) # Store number of reads which have hamming distance of 0, 1, 2 or 3 from barcodes whitelist. @@ -114,7 +114,7 @@ def tag_fastq( n_reads = 0 sys.stdout.write(f"Tagging reads...\n") - + for recordI2,recordR1,recordR2 in zip(I2_gen,R1_gen, R2_gen): #assert recordI2.name == recordR1.name == recordR2.name, f"I2 ({I2}) & R1 ({R1}) & R2 ({R2}) read names don't match." @@ -132,12 +132,12 @@ def tag_fastq( bc_seq=bc_seq, bc_qual=bc_qual, max_hamming_dist=HD) - + if first_pass: R1comment = '' else: R1comment = '\t' + recordR1.comment - + ##Check if read comment is already a SAM tag #if (len(recordR1.comment) >= 3 and recordR1.comment[2] == ':' and recordR1.comment[0].isalpha() and recordR1.comment[1].isalnum()): # R1comment = '\t' + recordR1.comment @@ -159,14 +159,14 @@ def tag_fastq( if n_reads % 20000 == 0: sys.stdout.write(f"\r{n_reads} reads processed ...") sys.stdout.flush() - + sys.stdout.write("\r") sys.stdout.flush() sys.stdout.write(f"Finished processing {n_reads} reads...\n") - + BC_Counter = Counter(corr_bcs) n_nomatch = BC_Counter.pop('NoMatch') - + # Close the corrected read files R1_tagged_outpath_fh.close() R2_tagged_outpath_fh.close() @@ -177,7 +177,7 @@ def tag_fastq( reads_without_bc = n_reads - bc_reads # Calculate fraction of barcodes found in all reads. frac_bcs_found = bc_reads / n_reads - + # Store the stats stats_tsv = ( f"reads\t{n_reads}\t100.00%\n" + @@ -189,24 +189,24 @@ def tag_fastq( f"bc_reads_with_{i}_mismatches\t{bc_mismatches_stats[i]}\t" + f"{(bc_mismatches_stats[i] / n_reads * 100.0)}%\n" ) - + #Writing log files and sam header # write the stats to corrected_bc_stats_tsv_filename with open(out_folder + corrected_bc_stats_tsv_filename, 'w') as file: file.write(stats_tsv) - + # write the reads_per_barcode to reads_per_barcode_tsv_filename with open(out_folder + reads_per_barcode_tsv_filename, "w") as file: # Write item counts as tab-separated values for bc, read_count in BC_Counter.items(): file.write(f"{read_count}\t{bc}\n") file.write(f"{n_nomatch}\tNoMatch") - + # print the stats to the console sys.stdout.write(f'\n{stats_tsv}\n') return frac_bcs_found - + def main(): # Check that the correct number of arguments are passed @@ -224,7 +224,7 @@ def main(): out = sys.argv[7] first_pass_arg = sys.argv[8] rev_comp_arg = sys.argv[9] - + # Check that the max_mismatches is 0, 1, 2 or 3 if HD not in [0,1,2,3]: sys.stderr.write(f"\nExiting...\nMaximum Hamming Distance (HD) must be 0, 1, 2 or 3\n") @@ -233,7 +233,7 @@ def main(): # Ensure the path ends with a '/' if not out.endswith('/'): out = out + '/' - + xtraBC = '' if first_pass_arg=='first_pass': IS_IT_YOUR_FIRST_PASS=True @@ -258,7 +258,7 @@ def main(): bc_whitelist = read_barcode_whitelist_from_file(bc_whitelist_filename=bc_whitelist_filename) # Read FASTQ with Forward barcodes and write R1 R2 FASTQs tagging them in the read comment - # with a tag and a barcode that match the whitelist closely enough, + # with a tag and a barcode that match the whitelist closely enough, # Output stats frac_bcs_found = tag_fastq( @@ -273,7 +273,7 @@ def main(): reads_per_barcode_tsv_filename=f'Reads_Per_Barcode_{sample_name}_{tag_name}.tsv', out_folder=out, rev_comp=REV_COMP) - + sys.stdout.write(f"\n{frac_bcs_found * 100.00}% of the reads had a valid barcode.\n") if __name__ == "__main__": diff --git a/scripts/core_runtime/Tag_Lig3.codon b/scripts/core_runtime/Tag_Lig3.codon index 912c0b6..c4fc28f 100755 --- a/scripts/core_runtime/Tag_Lig3.codon +++ b/scripts/core_runtime/Tag_Lig3.codon @@ -81,7 +81,7 @@ def tag_fastq( corrected_bc_stats_tsv_filename = f'Barcode_Statistics_{sample}_{tag}.tsv' reads_per_barcode_tsv_filename = f'Reads_Per_Barcode_{sample}_{tag}.tsv' Tag_records_filename = f'Tag_Records_{sample}.tsv' - + # Initialize file readers/writers # Process barcode reader if I2.endswith('.gz'): @@ -112,7 +112,7 @@ def tag_fastq( # Handle Tag records output paths Tag_records_outpath = f"{out_folder}/{Tag_records_filename}" Tag_records_outpath_fh = open(Tag_records_outpath, 'w') - + # Initialize barcode and stats lists corr_bcs = List[str](capacity=500000000) # Store number of reads which have hamming distance of 0, 1, 2 or 3 from barcodes whitelist. @@ -136,14 +136,14 @@ def tag_fastq( else: # Forward bc_seq_l1, bc_qual_l1 = (recordI2.seq[l_bc_start_list[0]:l_bc_start_list[0]+BC_LEN], recordI2.qual[l_bc_start_list[0]:l_bc_start_list[0]+BC_LEN]) - + corrected_bc_l1 = correct_bc_by_qual_order_with_whitelist_or_correct_bc_with_Ns_with_whitelist( bc_whitelist=bc_whitelist, bc_length=BC_LEN, bc_seq=bc_seq_l1, bc_qual=bc_qual_l1, max_hamming_dist=HD) - + if corrected_bc_l1: bc_mismatches_stats_l1[corrected_bc_l1.hamming_dist] += 1 else: @@ -156,14 +156,14 @@ def tag_fastq( else: # Forward bc_seq_l2, bc_qual_l2 = (recordI2.seq[l_bc_start_list[1]:l_bc_start_list[1]+BC_LEN], recordI2.qual[l_bc_start_list[1]:l_bc_start_list[1]+BC_LEN]) - + corrected_bc_l2 = correct_bc_by_qual_order_with_whitelist_or_correct_bc_with_Ns_with_whitelist( bc_whitelist=bc_whitelist, bc_length=BC_LEN, bc_seq=bc_seq_l2, bc_qual=bc_qual_l2, max_hamming_dist=HD) - + if corrected_bc_l2: bc_mismatches_stats_l2[corrected_bc_l2.hamming_dist] += 1 else: @@ -177,14 +177,14 @@ def tag_fastq( else: # Forward bc_seq_l3, bc_qual_l3 = (recordI2.seq[l_bc_start_list[2]:l_bc_start_list[2]+BC_LEN], recordI2.qual[l_bc_start_list[2]:l_bc_start_list[2]+BC_LEN]) - + corrected_bc_l3 = correct_bc_by_qual_order_with_whitelist_or_correct_bc_with_Ns_with_whitelist( bc_whitelist=bc_whitelist, bc_length=BC_LEN, bc_seq=bc_seq_l3, bc_qual=bc_qual_l3, max_hamming_dist=HD) - + if n_reads == 1: assert recordI2.name == recordR1.name == recordR2.name, f"I2 ({I2}) & R1 ({R1}) & R2 ({R2}) read names don't match." @@ -192,16 +192,16 @@ def tag_fastq( bc_mismatches_stats_l3[corrected_bc_l3.hamming_dist] += 1 else: corrected_bc_l3 = (8,'NoMatch') - + sb_start = recordR1.comment.find("SB:Z:") sb_tag = recordR1.comment[sb_start+5:].split()[0] corrs = [sb_tag,corrected_bc_l1.corrected_bc,corrected_bc_l2.corrected_bc,corrected_bc_l3.corrected_bc] # Check for NoMatch and build the final_bc final_bc = 'NoMatch' if 'NoMatch' in corrs else ''.join(corrs) - + corr_bcs.append(final_bc) - + record_name_tagged = recordR1.name + f' {tag}:Z:{final_bc}' + f'\tRG:Z:{final_bc}' + f'\t{recordR1.comment}' R1_tagged_outpath_fh.write(f'@{record_name_tagged}\n{recordR1.read}\n+\n{recordR1.qual}\n') R2_tagged_outpath_fh.write(f'@{record_name_tagged}\n{recordR2.read}\n+\n{recordR2.qual}\n') @@ -220,7 +220,7 @@ def tag_fastq( sys.stdout.flush() sys.stdout.write(f"Preparing BCs lists...DONE\n") sys.stdout.flush() - + # Close the corrected read files R1_tagged_outpath_fh.close() R2_tagged_outpath_fh.close() @@ -238,7 +238,7 @@ def tag_fastq( frac_bcs_found = bc_reads / n_reads # Reads in barcode with less than required amount of reads reads_in_too_small_bc = bc_reads - n_passing_reads #in this case reads_in_too_small_bc are the reads with at least 1 valid ligation but not all 3 ligations - + # stats stats_tsv = ( f"reads\t{n_reads}\t100.00%\n" + @@ -254,9 +254,9 @@ def tag_fastq( f"reads_with_L{li}\t{bc_reads}\t" + f"{(bc_reads / n_reads * 100.0)}%\n" + f"reads_with_L{li}_with_all_ligations\t{n_passing_reads}\t" + f"{(n_passing_reads / bc_reads * 100.0)}%\n" + f"reads_with_L{li}_missing_other_ligation\t{reads_in_too_small_bc}\t" + f"{(reads_in_too_small_bc / bc_reads * 100.0)}%\n" - f"reads_with_all_ligations\t{n_passing_reads}\t" + f"{(n_passing_reads / n_reads * 100.0)}%\n" + f"reads_with_all_ligations\t{n_passing_reads}\t" + f"{(n_passing_reads / n_reads * 100.0)}%\n" ) - + #Writing log files and sam header # write the stats to corrected_bc_stats_tsv_filename with open(out_folder + f"{corrected_bc_stats_tsv_filename.rsplit('.', 1)[0]}_L{li}.{corrected_bc_stats_tsv_filename.rsplit('.', 1)[1]}", 'w') as file: @@ -273,7 +273,7 @@ def tag_fastq( sys.stdout.write(f'DONE\n') return frac_bcs_found - + def main(): START_LIST = [15,53,91] @@ -297,7 +297,7 @@ def main(): sys.stderr.write(f"\nExiting...\nExpected exactly three comma-separated ligation start positions, got: {sys.argv[8]}\n") sys.exit(1) START_LIST = [int(start_tokens[0]), int(start_tokens[1]), int(start_tokens[2])] - + # Check that the max_mismatches is 0, 1, 2 or 3 if HD not in [0,1,2,3]: sys.stderr.write(f"\nExiting...\nMaximum Hamming Distance (HD) must be 0, 1, 2 or 3\n") @@ -307,7 +307,7 @@ def main(): bc_whitelist = read_barcode_whitelist_from_file(bc_whitelist_filename=bc_whitelist_filename) # Read FASTQ with Forward barcodes and write R1 R2 FASTQs tagging them in the read comment - # with a tag and a barcode that match the whitelist closely enough, + # with a tag and a barcode that match the whitelist closely enough, # Output stats frac_bcs_found = tag_fastq( I2 = I2, @@ -319,7 +319,7 @@ def main(): sample=sample_name, out_folder=out+'/', rev_comp=False) - + sys.stdout.write(f"{frac_bcs_found * 100.00}% of the reads had a valid barcode.\n") if __name__ == "__main__": diff --git a/scripts/core_runtime/Tag_UMI.codon b/scripts/core_runtime/Tag_UMI.codon index 3b51bb3..362af24 100755 --- a/scripts/core_runtime/Tag_UMI.codon +++ b/scripts/core_runtime/Tag_UMI.codon @@ -80,13 +80,13 @@ def tag_fastq( R1_tagged_outpath_fh = open(R1_tagged_outpath, 'w') R2_tagged_outpath = f"{out_folder}/{R2_fname}_{tag}.{R2_ext}" R2_tagged_outpath_fh = open(R2_tagged_outpath, 'w') - + # Initialize barcode and stats lists corr_bcs = List[str](capacity=500000000) n_reads = 0 sys.stdout.write(f"Tagging reads with UMI...\n") - + for recordI2,recordR1,recordR2 in zip(I2_gen,R1_gen, R2_gen): #assert recordI2.name == recordR1.name == recordR2.name, f"I2 ({I2}) & R1 ({R1}) & R2 ({R2}) read names don't match." @@ -97,7 +97,7 @@ def tag_fastq( else: # Forward bc_seq, bc_qual = (recordI2.seq[BC_START:BC_START+BC_LEN], recordI2.qual[BC_START:BC_START+BC_LEN]) - + bc_seq = str(bc_seq) record_name_tagged = recordR1.name + f' {tag}:Z:{bc_seq}' + f'\t{recordR1.comment}' corr_bcs.append(bc_seq) @@ -109,25 +109,25 @@ def tag_fastq( if n_reads % 20000 == 0: sys.stdout.write(f"\r{n_reads} reads processed ...") sys.stdout.flush() - + sys.stdout.write("\r") sys.stdout.flush() sys.stdout.write(f"Finished processing {n_reads} reads...\n") - + BC_Counter = Counter(corr_bcs) - + # write the reads_per_barcode to reads_per_barcode_tsv_filename with open(out_folder + reads_per_barcode_tsv_filename, "w") as file: # Write item counts as tab-separated values for bc, read_count in BC_Counter.items(): file.write(f"{read_count}\t{bc}\n") - + # Close the corrected read files R1_tagged_outpath_fh.close() R2_tagged_outpath_fh.close() return 0 - + def main(): # Check that the correct number of arguments are passed @@ -148,7 +148,7 @@ def main(): out = out + '/' # Read FASTQ with Forward barcodes and write R1 R2 FASTQs tagging them in the read comment - # with a tag and a barcode that match the whitelist closely enough, + # with a tag and a barcode that match the whitelist closely enough, # Output stats tag_fastq( I2 = I2, @@ -158,7 +158,7 @@ def main(): reads_per_barcode_tsv_filename=f'Reads_Per_Barcode_{sample_name}_{tag_name}.tsv', out_folder=out, rev_comp=True) - + if __name__ == "__main__": main() diff --git a/scripts/core_runtime/utils.codon b/scripts/core_runtime/utils.codon index 5268544..a60b9b6 100755 --- a/scripts/core_runtime/utils.codon +++ b/scripts/core_runtime/utils.codon @@ -15,7 +15,7 @@ def get_qual_sorted_idx(qual): key=lambda x: x[1], algorithm="insertion", reverse=False - ) + ) ) ) @@ -201,7 +201,7 @@ def correct_bc_by_qual_order_with_whitelist_or_correct_bc_with_Ns_with_whitelist """ assert len(str(bc_seq)) == bc_length, "The barcodes are not the expected length..." - + if "N" in str(bc_seq): corrected_bc = correct_bc_with_Ns_with_whitelist( bc_whitelist, diff --git a/subworkflows/local/dna_core/main.nf b/subworkflows/local/dna_core/main.nf index 5eaed8e..fd164dc 100644 --- a/subworkflows/local/dna_core/main.nf +++ b/subworkflows/local/dna_core/main.nf @@ -26,9 +26,12 @@ include { TAG_DNA_CELL_BARCODE } from '../../../modules/local/tag_dna_cell_b include { TRIM_DNA_FASTQS } from '../../../modules/local/trim_dna_fastqs/main' include { SPLIT_DNA_READS } from '../../../modules/local/split_dna_reads/main' include { ALIGN_DNA } from '../../../modules/local/align_dna/main' -include { MARK_DUPLICATES_DNA } from '../../../modules/local/mark_duplicates_dna/main' +include { GATK4_MARKDUPLICATES } from '../../../modules/nf-core/gatk4/markduplicates/main' +include { NORMALIZE_DNA_MARKDUPLICATES } from '../../../modules/local/normalize_dna_markduplicates/main' include { SPLIT_DUPLICATES_DNA } from '../../../modules/local/split_duplicates_dna/main' -include { BAM_COVERAGE_DNA } from '../../../modules/local/bam_coverage_dna/main' +include { CHECK_DNA_NODUP_BAM } from '../../../modules/local/check_dna_nodup_bam/main' +include { DEEPTOOLS_BAMCOVERAGE } from '../../../modules/nf-core/deeptools/bamcoverage/main' +include { NORMALIZE_DNA_BAMCOVERAGE } from '../../../modules/local/normalize_dna_bamcoverage/main' def selectDnaIndexRead(final Map meta, final Object i1, final Object i2, final String fieldName) { return meta[fieldName] == 'i1' ? i1 : i2 @@ -42,6 +45,19 @@ def dnaLigationStartPositions(final Map meta) { return meta.dna_tagmentation == 'dual' ? '41,79,117' : '15,53,91' } +def nfcoreDnaMeta(final String splitName, final Map meta, final String stage) { + return meta + [ + id : splitName, + tres_sample_id : meta.id, + tres_split_name: splitName, + tres_stage : stage, + ] +} + +def restoreDnaMeta(final Map meta) { + return meta + [id: meta.tres_sample_id ?: meta.id] +} + workflow DNA_CORE { take: ch_dna_samples @@ -145,9 +161,32 @@ workflow DNA_CORE { // Finish the DNA core with alignment, duplicate marking, NoDup extraction, and coverage. ALIGN_DNA(ch_align_input) ch_versions = ch_versions.mix(ALIGN_DNA.out.versions) - MARK_DUPLICATES_DNA(ALIGN_DNA.out.bam) - ch_versions = ch_versions.mix(MARK_DUPLICATES_DNA.out.versions) - SPLIT_DUPLICATES_DNA(MARK_DUPLICATES_DNA.out.bam) + + ch_gatk_markduplicates_input = ALIGN_DNA.out.bam.map { splitName, meta, alignedBam -> + tuple(nfcoreDnaMeta(splitName, meta, 'markeddup'), alignedBam) + } + + GATK4_MARKDUPLICATES(ch_gatk_markduplicates_input, [], []) + ch_versions = ch_versions.mix(GATK4_MARKDUPLICATES.out.versions_gatk4) + ch_versions = ch_versions.mix(GATK4_MARKDUPLICATES.out.versions_samtools) + + ch_normalize_markduplicates_input = GATK4_MARKDUPLICATES.out.bam + .join(GATK4_MARKDUPLICATES.out.bai) + .join(GATK4_MARKDUPLICATES.out.metrics) + .map { nfMeta, markedDupBam, markedDupBai, markedDupMetrics -> + tuple( + nfMeta.tres_split_name as String, + restoreDnaMeta(nfMeta), + markedDupBam, + markedDupBai, + markedDupMetrics + ) + } + + NORMALIZE_DNA_MARKDUPLICATES(ch_normalize_markduplicates_input) + ch_versions = ch_versions.mix(NORMALIZE_DNA_MARKDUPLICATES.out.versions) + + SPLIT_DUPLICATES_DNA(NORMALIZE_DNA_MARKDUPLICATES.out.bam) ch_versions = ch_versions.mix(SPLIT_DUPLICATES_DNA.out.versions) ch_nodup_for_coverage = SPLIT_DUPLICATES_DNA.out.bam @@ -162,13 +201,44 @@ workflow DNA_CORE { ) } - BAM_COVERAGE_DNA(ch_nodup_for_coverage) - ch_versions = ch_versions.mix(BAM_COVERAGE_DNA.out.versions) + CHECK_DNA_NODUP_BAM(ch_nodup_for_coverage) + ch_versions = ch_versions.mix(CHECK_DNA_NODUP_BAM.out.versions) + + ch_deeptools_bamcoverage_input = CHECK_DNA_NODUP_BAM.out.ready.map { splitName, meta, noDupBam, noDupBai, effectiveGenomeSize -> + tuple(nfcoreDnaMeta(splitName, meta, 'nodup_coverage'), noDupBam, noDupBai) + } + + DEEPTOOLS_BAMCOVERAGE( + ch_deeptools_bamcoverage_input, + [], + [], + tuple([id: 'no_blacklist'], []) + ) + ch_versions = ch_versions.mix(DEEPTOOLS_BAMCOVERAGE.out.versions_deeptools) + ch_versions = ch_versions.mix(DEEPTOOLS_BAMCOVERAGE.out.versions_samtools) + + ch_normalize_bamcoverage_input = DEEPTOOLS_BAMCOVERAGE.out.bigwig.map { nfMeta, bigwig -> + tuple( + nfMeta.tres_split_name as String, + restoreDnaMeta(nfMeta), + bigwig + ) + } + + NORMALIZE_DNA_BAMCOVERAGE(ch_normalize_bamcoverage_input) + ch_versions = ch_versions.mix(NORMALIZE_DNA_BAMCOVERAGE.out.versions) ch_barcode_reports = TAG_DNA_SAMPLE_BARCODE.out.metrics .mix(TAG_DNA_MODALITY_BARCODE.out.metrics) .mix(TAG_DNA_CELL_BARCODE.out.metrics) + ch_barcode_report_files = TAG_DNA_SAMPLE_BARCODE.out.metrics + .flatMap { sampleId, counts, stats -> [counts, stats] } + .mix(TAG_DNA_MODALITY_BARCODE.out.metrics.flatMap { sampleId, counts, stats -> [counts, stats] }) + .mix(TAG_DNA_CELL_BARCODE.out.metrics.flatMap { sampleId, counts, tagRecords, statsL1, statsL2, statsL3 -> + [counts, statsL1, statsL2, statsL3] + }) + emit: tagged_fastqs = TAG_DNA_CELL_BARCODE.out.tagged trimmed_fastqs = TRIM_DNA_FASTQS.out.trimmed @@ -176,14 +246,15 @@ workflow DNA_CORE { rg_headers = SPLIT_DNA_READS.out.rg_headers aligned_bams = ALIGN_DNA.out.bam aligned_bais = ALIGN_DNA.out.bai - markeddup_bams = MARK_DUPLICATES_DNA.out.bam - markeddup_bais = MARK_DUPLICATES_DNA.out.bai - duplicate_metrics = MARK_DUPLICATES_DNA.out.metrics + markeddup_bams = NORMALIZE_DNA_MARKDUPLICATES.out.bam + markeddup_bais = NORMALIZE_DNA_MARKDUPLICATES.out.bai + duplicate_metrics = NORMALIZE_DNA_MARKDUPLICATES.out.metrics nodup_bams = SPLIT_DUPLICATES_DNA.out.bam nodup_bais = SPLIT_DUPLICATES_DNA.out.bai - coverage_bigwigs = BAM_COVERAGE_DNA.out.bw - coverage_warnings = BAM_COVERAGE_DNA.out.warnings + coverage_bigwigs = NORMALIZE_DNA_BAMCOVERAGE.out.bw + coverage_warnings = CHECK_DNA_NODUP_BAM.out.warnings barcode_reports = ch_barcode_reports + barcode_report_files = ch_barcode_report_files tres_tag_records = TAG_DNA_CELL_BARCODE.out.tres_tag_records versions = ch_versions } diff --git a/subworkflows/local/dna_core/meta.yml b/subworkflows/local/dna_core/meta.yml index cbebad9..336de97 100644 --- a/subworkflows/local/dna_core/meta.yml +++ b/subworkflows/local/dna_core/meta.yml @@ -14,9 +14,12 @@ components: - "trim/dna/fastqs" - "split/dna/reads" - "align/dna" - - "mark/duplicates/dna" + - "gatk4/markduplicates" + - "normalize/dna/markduplicates" - "split/duplicates/dna" - - "bam/coverage/dna" + - "check/dna/nodup/bam" + - "deeptools/bamcoverage" + - "normalize/dna/bamcoverage" input: - ch_dna_samples: type: tuple diff --git a/subworkflows/local/rna_core/main.nf b/subworkflows/local/rna_core/main.nf index 69b7d80..61dcd75 100644 --- a/subworkflows/local/rna_core/main.nf +++ b/subworkflows/local/rna_core/main.nf @@ -138,6 +138,13 @@ workflow RNA_CORE { .mix(TAG_RNA_UMI.out.metrics) .mix(TAG_RNA_CELL_BARCODE.out.metrics) + ch_barcode_report_files = TAG_RNA_SAMPLE_BARCODE.out.metrics + .flatMap { sampleId, counts, stats -> [counts, stats] } + .mix(TAG_RNA_UMI.out.metrics.flatMap { sampleId, counts -> [counts] }) + .mix(TAG_RNA_CELL_BARCODE.out.metrics.flatMap { sampleId, counts, tagRecords, statsL1, statsL2, statsL3 -> + [counts, statsL1, statsL2, statsL3] + }) + emit: tagged_fastqs = TAG_RNA_CELL_BARCODE.out.tagged trimmed_fastqs = TRIM_RNA_FASTQS.out.trimmed @@ -145,10 +152,13 @@ workflow RNA_CORE { rg_headers = SPLIT_RNA_READS.out.rg_headers usam_files = FQ_TO_SAM.out.usam aligned_solo_dirs = RNA_STARSOLO_ALIGN.out.solo_dir + aligned_solo_summaries = RNA_STARSOLO_ALIGN.out.solo_summary + aligned_star_logs = RNA_STARSOLO_ALIGN.out.star_log aligned_filtered_bams = RNA_FILTERED_BAM.out.filtered_bam aligned_stranded_bigwigs = RNA_COVERAGE.out.stranded_bw aligned_unstranded_bigwigs = RNA_COVERAGE.out.unstranded_bw barcode_reports = ch_barcode_reports + barcode_report_files = ch_barcode_report_files tres_tag_records = TAG_RNA_CELL_BARCODE.out.tres_tag_records versions = ch_versions } diff --git a/workflows/treseq.nf b/workflows/treseq.nf index 2a096c3..85f4032 100644 --- a/workflows/treseq.nf +++ b/workflows/treseq.nf @@ -20,6 +20,14 @@ import WorkflowSupport include { RNA_CORE } from '../subworkflows/local/rna_core' include { DNA_CORE } from '../subworkflows/local/dna_core' +include { TRES_REPORT_HTML } from '../modules/local/tres_report_html/main' +include { FASTQC } from '../modules/nf-core/fastqc/main' +include { SAMTOOLS_FLAGSTAT } from '../modules/nf-core/samtools/flagstat/main' +include { SAMTOOLS_STATS } from '../modules/nf-core/samtools/stats/main' +include { SAMTOOLS_IDXSTATS } from '../modules/nf-core/samtools/idxstats/main' +include { SAMTOOLS_QUICKCHECK } from '../modules/nf-core/samtools/quickcheck/main' +include { SAMTOOLS_QUICKCHECK_REPORT } from '../modules/local/samtools_quickcheck_report/main' +include { MULTIQC } from '../modules/nf-core/multiqc/main' def toRnaCoreInput(final Map row) { tuple( @@ -55,6 +63,26 @@ def samplesheetParseOptions() { ] } +def qcMeta(final Map meta, final String id, final String modality, final String stage, final String splitName) { + return meta + [ + id : id, + tres_modality : modality, + tres_qc_stage : stage, + tres_split_name : splitName, + ] +} + +def toFastqcInput(final Map row) { + final List reads = row.modality == 'dna' + ? [row.i1, row.i2, row.r1, row.r2] + : [row.i1, row.r1, row.r2] + + return tuple( + qcMeta(row, "${row.modality}.${row.id}.raw", row.modality as String, 'raw_fastq', row.id as String), + reads.findAll { it }.collect { file(it) } + ) +} + def validateCoreResourceContract(final List rnaRows, final List dnaRows, final int maxCpus) { if( maxCpus < 1 ) { error "Invalid --max_cpus '${maxCpus}'. Value must be >= 1" @@ -70,6 +98,7 @@ workflow TRESEQ { final List rnaRows = sampleRows.findAll { row -> row.modality == 'rna' } final List dnaRows = sampleRows.findAll { row -> row.modality == 'dna' } final int maxCpus = params.max_cpus as int + final String libraryName = sampleRows ? (sampleRows[0].library_name as String) : 'unknown library' validateCoreResourceContract(rnaRows, dnaRows, maxCpus) @@ -87,6 +116,91 @@ workflow TRESEQ { RNA_CORE(ch_rna_samples) DNA_CORE(ch_dna_samples) + Channel + .fromList(sampleRows) + .map { row -> toFastqcInput(row) } + .set { ch_raw_fastqs_for_fastqc } + + FASTQC(ch_raw_fastqs_for_fastqc) + + // nf-core sidecar QC modules. These do not alter the TrESFlow data path; + // they only read existing BAMs and emit standardized QC text files. + ch_rna_bams_for_qc = RNA_CORE.out.aligned_filtered_bams.map { splitName, meta, bam -> + tuple(qcMeta(meta, "rna.${splitName}.filtered_cells", 'rna', 'filtered_cells', splitName), bam, []) + } + + ch_dna_aligned_bams_for_qc = DNA_CORE.out.aligned_bams + .join(DNA_CORE.out.aligned_bais) + .map { splitName, metaFromBam, bam, metaFromBai, bai -> + tuple(qcMeta(metaFromBam, "dna.${splitName}.aligned", 'dna', 'aligned', splitName), bam, bai) + } + + ch_dna_markeddup_bams_for_qc = DNA_CORE.out.markeddup_bams + .join(DNA_CORE.out.markeddup_bais) + .map { splitName, metaFromBam, bam, metaFromBai, bai -> + tuple(qcMeta(metaFromBam, "dna.${splitName}.markeddup", 'dna', 'markeddup', splitName), bam, bai) + } + + ch_dna_nodup_bams_for_qc = DNA_CORE.out.nodup_bams + .join(DNA_CORE.out.nodup_bais) + .map { splitName, metaFromBam, bam, metaFromBai, bai -> + tuple(qcMeta(metaFromBam, "dna.${splitName}.nodup", 'dna', 'nodup', splitName), bam, bai) + } + + ch_bams_for_nfcore_qc = ch_rna_bams_for_qc + .mix(ch_dna_aligned_bams_for_qc) + .mix(ch_dna_markeddup_bams_for_qc) + .mix(ch_dna_nodup_bams_for_qc) + + ch_dna_indexed_bams_for_nfcore_qc = ch_dna_aligned_bams_for_qc + .mix(ch_dna_markeddup_bams_for_qc) + .mix(ch_dna_nodup_bams_for_qc) + + ch_bams_for_nfcore_quickcheck = ch_bams_for_nfcore_qc.map { meta, bam, bai -> + tuple(meta, bam) + } + + ch_samtools_stats_reference = Channel.value(tuple([id: 'no_reference'], [], [])) + + SAMTOOLS_FLAGSTAT(ch_bams_for_nfcore_qc) + SAMTOOLS_STATS(ch_bams_for_nfcore_qc, ch_samtools_stats_reference) + SAMTOOLS_IDXSTATS(ch_dna_indexed_bams_for_nfcore_qc) + SAMTOOLS_QUICKCHECK(ch_bams_for_nfcore_quickcheck) + SAMTOOLS_QUICKCHECK_REPORT(SAMTOOLS_QUICKCHECK.out.bam) + + ch_barcode_report_files = RNA_CORE.out.barcode_report_files + .mix(DNA_CORE.out.barcode_report_files) + + ch_report_source_files = ch_barcode_report_files + .mix(RNA_CORE.out.aligned_solo_summaries.map { splitName, meta, soloSummary -> soloSummary }) + .mix(RNA_CORE.out.aligned_star_logs.map { splitName, meta, starLog -> starLog }) + .mix(DNA_CORE.out.duplicate_metrics.map { splitName, meta, metrics -> metrics }) + .mix(FASTQC.out.zip.map { meta, zip -> zip }) + .mix(SAMTOOLS_FLAGSTAT.out.flagstat.map { meta, flagstat -> flagstat }) + .mix(SAMTOOLS_STATS.out.stats.map { meta, stats -> stats }) + .mix(SAMTOOLS_IDXSTATS.out.idxstats.map { meta, idxstats -> idxstats }) + .mix(SAMTOOLS_QUICKCHECK_REPORT.out.report.map { meta, report -> report }) + + ch_tres_report_input = ch_report_source_files + .collect() + .map { files -> tuple([id: 'tresflow', library_name: libraryName], files) } + + ch_multiqc_input = ch_report_source_files + .collect() + .map { files -> + tuple( + [id: 'tresflow'], + files, + file("${projectDir}/assets/multiqc_config.yml"), + [], + [], + [] + ) + } + + TRES_REPORT_HTML(ch_tres_report_input) + MULTIQC(ch_multiqc_input) + emit: tagged_fastqs = RNA_CORE.out.tagged_fastqs trimmed_fastqs = RNA_CORE.out.trimmed_fastqs @@ -94,6 +208,8 @@ workflow TRESEQ { rg_headers = RNA_CORE.out.rg_headers usam_files = RNA_CORE.out.usam_files aligned_solo_dirs = RNA_CORE.out.aligned_solo_dirs + aligned_solo_summaries = RNA_CORE.out.aligned_solo_summaries + aligned_star_logs = RNA_CORE.out.aligned_star_logs aligned_filtered_bams = RNA_CORE.out.aligned_filtered_bams aligned_stranded_bigwigs = RNA_CORE.out.aligned_stranded_bigwigs aligned_unstranded_bigwigs = RNA_CORE.out.aligned_unstranded_bigwigs @@ -112,4 +228,14 @@ workflow TRESEQ { dna_coverage_bigwigs = DNA_CORE.out.coverage_bigwigs dna_coverage_warnings = DNA_CORE.out.coverage_warnings dna_barcode_reports = DNA_CORE.out.barcode_reports + samtools_flagstat = SAMTOOLS_FLAGSTAT.out.flagstat + samtools_stats = SAMTOOLS_STATS.out.stats + samtools_idxstats = SAMTOOLS_IDXSTATS.out.idxstats + samtools_quickcheck = SAMTOOLS_QUICKCHECK_REPORT.out.report + fastqc_html = FASTQC.out.html + fastqc_zip = FASTQC.out.zip + multiqc_report = MULTIQC.out.report + multiqc_data = MULTIQC.out.data + tres_report_html = TRES_REPORT_HTML.out.html + tres_report_metrics_json = TRES_REPORT_HTML.out.metrics_json }