Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: true
matrix:
python-version: ["3.9", "3.13"]
python-version: ["3.11", "3.14"]
os: [ubuntu-22.04] #, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand All @@ -34,7 +34,7 @@ jobs:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
with:
python-version: "3.13"
python-version: "3.14"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand All @@ -47,7 +47,7 @@ jobs:
- name: Run mypy
run: poetry run mypy sentieon_cli --exclude scripts
- name: Run flake8
run: poetry run flake8 . --extend-ignore E231,E221, --exclude .github/scripts/license_message.py,sentieon_cli/scripts/gvcf_combine.py,sentieon_cli/scripts/vcf_mod.py,sentieon_cli/scripts/hybrid_anno.py,sentieon_cli/scripts/hybrid_select.py,sentieon_cli/archive.py,sentieon_cli/scripts/trimalt.py,playground,tests # false+ from python 3.12
run: poetry run flake8 .
- name: Run the automated tests
run: poetry run pytest -v
- name: Run doct tests
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ jobs:
fail-fast: true
max-parallel: 1
matrix:
python-version: ["3.9", "3.13"]
sentieon-version: ["202503.01"]
python-version: ["3.11", "3.14"]
sentieon-version: ["202503.02"]
os: [ubuntu-22.04] #, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand Down Expand Up @@ -97,8 +97,8 @@ jobs:
fail-fast: true
max-parallel: 1
matrix:
python-version: ["3.9", "3.13"]
sentieon-version: ["202503.01"]
python-version: ["3.11", "3.14"]
sentieon-version: ["202503.02"]
os: [ubuntu-22.04] #, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand Down Expand Up @@ -219,8 +219,8 @@ jobs:
fail-fast: true
max-parallel: 1
matrix:
python-version: ["3.9", "3.13"]
sentieon-version: ["202503.01"]
python-version: ["3.11", "3.14"]
sentieon-version: ["202503.02"]
os: [ubuntu-22.04] #, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.13"
python-version: "3.14"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand All @@ -29,4 +29,4 @@ jobs:
poetry build -f sdist
gh release upload ${{github.event.release.tag_name}} dist/*.tar.gz
env:
GITHUB_TOKEN: ${{ github.TOKEN }}
GITHUB_TOKEN: ${{ github.TOKEN }}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ A command-line interface for the Sentieon software

Download the latest tar.gz file from the GitHub release page, https://github.com/sentieon/sentieon-cli/releases/ and install the package with pip:
```sh
curl -LO https://github.com/Sentieon/sentieon-cli/releases/download/v1.5.2/sentieon_cli-1.5.2.tar.gz
pip install sentieon_cli-1.5.2.tar.gz
curl -LO https://github.com/Sentieon/sentieon-cli/releases/download/v1.6.0/sentieon_cli-1.6.0.tar.gz
pip install sentieon_cli-1.6.0.tar.gz
```

## Installation with Poetry
Expand Down
870 changes: 655 additions & 215 deletions poetry.lock

Large diffs are not rendered by default.

35 changes: 30 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@

[project]
name = "sentieon_cli"
version = "1.5.2"
version = "1.6.0"
description = "entry point for sentieon command-line tools"
authors = [
{name = "Don Freed", email = "don.freed@sentieon.com"},
{name = "Brent", email = "bpederse@gmail.com"},
]
readme = "README.md"
requires-python = ">= 3.8"
requires-python = ">= 3.11"

classifiers = [
"Development Status :: 5 - Production/Stable",
Expand All @@ -18,9 +18,10 @@ classifiers = [
include = ["LICENSE"]

dependencies = [
"colorlog (>=6.7.0,<7.0.0)",
"importlib-resources (>=5.0,<6.0)",
"packaging (>=23.2,<26.0)",
"packaging (>=23.2)",
"mappy (>=2.30,<3.0)",
"scipy (>=1.17.1,<2.0.0)",
"levenshtein (>=0.27.3,<0.28.0)",
]

[project.scripts]
Expand All @@ -32,17 +33,41 @@ ignore_missing_imports = true
[tool.black]
line-length = 79

[tool.flake8]
max-line-length = 79
extend-ignore = ["E231", "E221"]
exclude = [
".github/scripts/license_message.py",
"sentieon_cli/scripts/combine_cnv.py",
"sentieon_cli/scripts/gvcf_combine.py",
"sentieon_cli/scripts/vcf_mod.py",
"sentieon_cli/scripts/hybrid_anno.py",
"sentieon_cli/scripts/hybrid_select.py",
"sentieon_cli/scripts/indel2cnv.py",
"sentieon_cli/scripts/trimalt.py",
"sentieon_cli/archive.py",
"playground",
"tests",
]

[tool.poetry.group.dev.dependencies]
pytest = "^7.0.0"
pytest-asyncio = ">=0.21.0"
black = "*"
flake8 = "*"
Flake8-pyproject = "*"
mypy = "*"

[tool.poetry.group.test.dependencies]
pytest = "^7.0.0"
pytest-asyncio = ">=0.21.0"
black = "*"
mypy = "*"

[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "strict"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
2 changes: 1 addition & 1 deletion sentieon_cli/base_pangenome.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import pathlib
from typing import List, Optional

from importlib_resources import files
from importlib.resources import files

from . import command_strings as cmds
from .job import Job
Expand Down
3 changes: 2 additions & 1 deletion sentieon_cli/command_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ def cmd_pyexec_vcf_mod_haploid_patch(
"""
merge dnascope and dnascope-hp variants
"""
assert tech.upper() in ("HIFI", "ONT")
if tech.upper() not in ("HIFI", "ONT"):
raise ValueError(f"Unsupported tech '{tech}', must be 'HIFI' or 'ONT'")

cmd = f"sentieon pyexec {kwargs['vcf_mod_py']} -t {cores} "
cmd += "haploid_patch "
Expand Down
11 changes: 7 additions & 4 deletions sentieon_cli/dag.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ def add_job(self, job: Job, dependencies: Optional[Set[Job]] = None):
"""Add a job to the DAG"""
if dependencies:
for dependency in dependencies:
assert (
dependency in self.waiting_jobs
or dependency in self.ready_jobs
)
if (
dependency not in self.waiting_jobs
and dependency not in self.ready_jobs
):
raise ValueError(
f"Dependency '{dependency}' is not in the DAG"
)

if isinstance(dependencies, set) and len(dependencies) > 0:
self.waiting_jobs[job] = dependencies.copy()
Expand Down
35 changes: 25 additions & 10 deletions sentieon_cli/dnascope.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import packaging.version

from importlib_resources import files
from importlib.resources import files

from . import command_strings as cmds
from .dag import DAG
Expand Down Expand Up @@ -49,7 +49,6 @@
total_memory,
)


ALN_MIN_VERSIONS = {
"sentieon driver": packaging.version.Version("202308"),
"samtools": packaging.version.Version("1.16"),
Expand Down Expand Up @@ -256,7 +255,9 @@ def __init__(self) -> None:
self.no_split_alignment = False

def validate(self) -> None:
assert self.output_vcf
if not self.output_vcf:
self.logger.error("output_vcf is required")
sys.exit(2)

# uniquify pipeline attributes
self.sr_r1_fastq = self.r1_fastq
Expand Down Expand Up @@ -458,8 +459,12 @@ def build_dag(self) -> DAG:

def sr_align_inputs(self) -> Tuple[List[pathlib.Path], Set[Job], Job]:
"""Align input BAM/CRAM/uBAM/uCRAM files with bwa"""
assert self.reference
assert self.model_bundle
if not self.reference:
self.logger.error("reference is required")
sys.exit(2)
if not self.model_bundle:
self.logger.error("model_bundle is required")
sys.exit(2)

if not self.skip_version_check:
for cmd, min_version in ALN_MIN_VERSIONS.items():
Expand Down Expand Up @@ -526,8 +531,12 @@ def sr_align_fastq(
self,
) -> Tuple[List[pathlib.Path], Set[Job], Optional[Job]]:
"""Align fastq files to the reference genome using bwa"""
assert self.reference
assert self.model_bundle
if not self.reference:
self.logger.error("reference is required")
sys.exit(2)
if not self.model_bundle:
self.logger.error("model_bundle is required")
sys.exit(2)

res: List[pathlib.Path] = []
jobs: Set[Job] = set()
Expand Down Expand Up @@ -625,7 +634,9 @@ def dedup_and_metrics(
Optional[Job],
]:
"""Perform dedup and metrics collection"""
assert self.output_vcf
if not self.output_vcf:
self.logger.error("output_vcf is required")
sys.exit(2)
suffix = "bam" if self.bam_format else "cram"

# Create the metrics directory
Expand Down Expand Up @@ -790,8 +801,12 @@ def sr_call_variants(
deduped: List[pathlib.Path],
) -> Tuple[Job, Job, Job, Optional[Job], Optional[Job], Optional[Job]]:
"""Call SNVs, indels, and SVs using DNAscope"""
assert self.model_bundle
assert self.output_vcf
if not self.model_bundle:
self.logger.error("model_bundle is required")
sys.exit(2)
if not self.output_vcf:
self.logger.error("output_vcf is required")
sys.exit(2)

if not self.skip_version_check:
for cmd, min_version in VARIANTS_MIN_VERSIONS.items():
Expand Down
27 changes: 19 additions & 8 deletions sentieon_cli/dnascope_hybrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import packaging.version

from importlib_resources import files
from importlib.resources import files

from .logging import get_logger
from .archive import ar_load
Expand Down Expand Up @@ -47,7 +47,6 @@
)
from .transfer import build_transfer_jobs


logger = get_logger(__name__)


Expand Down Expand Up @@ -520,9 +519,15 @@ def build_dag(self) -> DAG:
self.logger.info("Building the DAG")
dag = DAG()

assert self.output_vcf
assert self.reference
assert self.model_bundle
if not self.output_vcf:
self.logger.error("output_vcf is required")
sys.exit(2)
if not self.reference:
self.logger.error("reference is required")
sys.exit(2)
if not self.model_bundle:
self.logger.error("model_bundle is required")
sys.exit(2)

rg_info = RgInfo(
self.lr_aln_readgroups,
Expand Down Expand Up @@ -712,9 +717,15 @@ def call_variants(
"""
Call SNVs and indels using the DNAscope hybrid pipeline
"""
assert self.output_vcf
assert self.reference
assert self.model_bundle
if not self.output_vcf:
self.logger.error("output_vcf is required")
sys.exit(2)
if not self.reference:
self.logger.error("reference is required")
sys.exit(2)
if not self.model_bundle:
self.logger.error("model_bundle is required")
sys.exit(2)

ref_fai = pathlib.Path(str(self.reference) + ".fai")

Expand Down
Loading
Loading