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/build_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.8'
python-version: '3.13'
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
Expand All @@ -37,7 +37,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.8'
python-version: '3.13'
architecture: ${{ matrix.target }}
- name: Build wheels
uses: PyO3/maturin-action@v1
Expand All @@ -59,7 +59,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.8'
python-version: '3.13'
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/tests_and_lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.9]
python-version: [3.13]
lint-flags:
- "--run-only-fast-linters"
- "--run-only-pylint"
Expand All @@ -38,7 +38,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -61,7 +61,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ and other sequence alignment algorithms written in Rust with Python bindings via
<p><img width="800px" src="https://raw.githubusercontent.com/kensho-technologies/sequence_align/main/docs/images/sequence_align.png"></p>

## Installation
`sequence_align` is distributed via [PyPi](https://pypi.org/project/sequence_align) for Python 3.7+, making installation as simple as the following --
`sequence_align` is distributed via [PyPi](https://pypi.org/project/sequence_align) for Python 3.9 - 3.13, making installation as simple as the following --
no special setup required for cross-platform compatibility, Rust installation, etc.!

``` bash
Expand Down
12 changes: 5 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,24 @@ build-backend = "maturin"

[project]
name = "sequence_align"
version = "0.2.0"
version = "0.3.0"
description = "Efficient implementations of Needleman-Wunsch and other sequence alignment algorithms in Rust with Python bindings."
readme = "README.md"
requires-python = ">=3.7"
requires-python = ">=3.9,<3.14"
authors = [
{name = "Kensho Technologies LLC.", email = "sequence-align-maintainer@kensho.com"},
]
maintainers = [
{name = "Kensho Technologies LLC.", email = "sequence-align-maintainer@kensho.com"},
]
license-files.paths = [
"LICENSE", # Apache 2.0
]
license = {file = "LICENSE"} # Apache 2.0
classifiers = [
"Operating System :: OS Independent",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Rust",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Topic :: Scientific/Engineering :: Bio-Informatics",
Expand Down
18 changes: 9 additions & 9 deletions src/sequence_align/pairwise.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright 2023-present Kensho Technologies, LLC.
from typing import Dict, List, Sequence, Tuple
from typing import Sequence

from sequence_align import _sequence_align # type: ignore

Expand All @@ -12,13 +12,13 @@ def _entry2idx(
seq_b: Sequence[str],
gap: str,
allow_gap: bool = False,
) -> Tuple[Dict[int, str], List[int], List[int]]:
) -> tuple[dict[int, str], list[int], list[int]]:
symbols = set(seq_a).union(set(seq_b))
if not allow_gap and gap in symbols:
raise ValueError(f'Gap entry "{gap}" found in seq_a and/or seq_b; must not exist in either')

symbols_without_gap = symbols - {gap}
idx2symbol: Dict[int, str] = {
idx2symbol: dict[int, str] = {
_GAP_VAL: gap,
**{idx: symbol for idx, symbol in enumerate(sorted(symbols_without_gap))},
}
Expand All @@ -31,11 +31,11 @@ def _entry2idx(


def _idx2entry(
idx2symbol: Dict[int, str],
seq_a_indices_aligned: List[int],
seq_b_indices_aligned: List[int],
idx2symbol: dict[int, str],
seq_a_indices_aligned: list[int],
seq_b_indices_aligned: list[int],
gap: str,
) -> Tuple[List[str], List[str]]:
) -> tuple[list[str], list[str]]:
seq_a_aligned = [gap if idx == _GAP_VAL else idx2symbol[idx] for idx in seq_a_indices_aligned]
seq_b_aligned = [gap if idx == _GAP_VAL else idx2symbol[idx] for idx in seq_b_indices_aligned]
return (seq_a_aligned, seq_b_aligned)
Expand All @@ -48,7 +48,7 @@ def needleman_wunsch(
mismatch_score: float = -1.0,
indel_score: float = -1.0,
gap: str = "-",
) -> Tuple[List[str], List[str]]:
) -> tuple[list[str], list[str]]:
"""Compute an optimal global pairwise alignment using the Needleman-Wunsch algorithm.

Args:
Expand Down Expand Up @@ -106,7 +106,7 @@ def hirschberg(
mismatch_score: float = -1.0,
indel_score: float = -1.0,
gap: str = "-",
) -> Tuple[List[str], List[str]]:
) -> tuple[list[str], list[str]]:
"""Compute an optimal global pairwise alignment using the Hirschberg algorithm.

Args:
Expand Down
4 changes: 2 additions & 2 deletions tests/perf/test_hirschberg.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright 2023-present Kensho Technologies, LLC.
import time
from typing import Any, Dict
from typing import Any
import unittest

from sequence_align.pairwise import hirschberg
Expand All @@ -23,7 +23,7 @@

class TestHirschberg(unittest.TestCase):
# Needed for mypy to not complain
expected_perf: Dict[str, Any] = dict()
expected_perf: dict[str, Any] = dict()

@classmethod
def setUpClass(cls) -> None:
Expand Down
4 changes: 2 additions & 2 deletions tests/perf/test_needleman_wunsch.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright 2023-present Kensho Technologies, LLC.
import time
from typing import Any, Dict
from typing import Any
import unittest

from sequence_align.pairwise import needleman_wunsch
Expand All @@ -23,7 +23,7 @@

class TestNeedlemanWunsch(unittest.TestCase):
# Needed for mypy to not complain
expected_perf: Dict[str, Any] = dict()
expected_perf: dict[str, Any] = dict()

@classmethod
def setUpClass(cls) -> None:
Expand Down
8 changes: 4 additions & 4 deletions tests/perf/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import multiprocessing as mp
import os
import random
from typing import Any, Callable, Dict, List, Tuple
from typing import Any, Callable

import psutil
import yaml
Expand All @@ -20,7 +20,7 @@
MEM_CHECK_INTERVAL = 0.01 # seconds


def _create_perturbed_seq(seq_a: List[str]) -> List[str]:
def _create_perturbed_seq(seq_a: list[str]) -> list[str]:
random.seed(1234)

seq_b = list()
Expand Down Expand Up @@ -48,7 +48,7 @@ def _create_perturbed_seq(seq_a: List[str]) -> List[str]:
return seq_b


def create_seq_pair(seq_a_len: int) -> Tuple[List[str], List[str]]:
def create_seq_pair(seq_a_len: int) -> tuple[list[str], list[str]]:
"""Create a pair of sequences, where the second is a perturbed version of the first."""
seq_a = random.choices(CHARS, k=seq_a_len)
seq_b = _create_perturbed_seq(seq_a)
Expand All @@ -63,7 +63,7 @@ def get_expected_perf(key: str) -> Any:


def max_memory_usage(
func: Callable[..., Any], args: Tuple[Any, ...], kwargs: Dict[str, Any]
func: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any]
) -> int:
"""Run the given function in a separate process and return the maximum memory usage in MiB."""
max_mem = 0
Expand Down