Compare commits
6 Commits
0.10.0
...
62ce1c9b2f
Author | SHA1 | Date | |
---|---|---|---|
62ce1c9b2f | |||
7384895578 | |||
5a03c7e8d8 | |||
ddf9cde175 | |||
2e8cdd8da9 | |||
d0318536b2 |
15
README.md
15
README.md
@@ -1,7 +1,8 @@
|
||||
# autoBIGS.Engine
|
||||
# autoBIGS.engine
|
||||
|
||||
A python library implementing common BIGSdb MLST schemes and databases accesses for the purpose of typing sequences automatically. Implementation follows the RESTful API outlined by the official [BIGSdb documentation](https://bigsdb.readthedocs.io/en/latest/rest.html) up to `V1.50.0`.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
Briefly, this library can:
|
||||
@@ -23,3 +24,15 @@ Then, it's as easy as running `pip install autobigs-engine` in any terminal that
|
||||
### CLI usage
|
||||
|
||||
This is a independent python library and thus does not have any form of direct user interface. One way of using it could be to create your own Python script that makes calls to this libraries functions. Alternatively, you may use `autobigs-cli`, a `Python` package that implements a CLI for calling this library.
|
||||
|
||||
## Versioning
|
||||
|
||||
the autoBIGS project follows [semantic versioning](https://semver.org/) where the three numbers may be interpreted as MAJOR.MINOR.PATCH.
|
||||
|
||||
Note regarding major version 0 ([spec item 4](https://semver.org/#spec-item-4)), the following adaptation of semantic versioning definition is as follows:
|
||||
|
||||
1. Given x.Y.z, Y is only incremented when a backwards incompatible change is made.
|
||||
|
||||
2. Given x.y.Z, Z is only incremented when a backwards compatible change is made.
|
||||
|
||||
Versions of autoBIGS items with a major version number of 0 will introduce numerous changes and patches. As such, changes between such versions should be considered highly variable.
|
@@ -13,11 +13,12 @@ dependencies = [
|
||||
]
|
||||
requires-python = ">=3.12"
|
||||
description = "A library to rapidly fetch fetch MLST profiles given sequences for various diseases."
|
||||
license = {text = "GPL-3.0-or-later"}
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/RealYHD/autoBIGS.engine"
|
||||
Source = "https://github.com/RealYHD/autoBIGS.engine"
|
||||
Issues = "https://github.com/RealYHD/autoBIGS.engine/issues"
|
||||
Homepage = "https://github.com/Syph-and-VPD-Lab/autoBIGS.engine"
|
||||
Source = "https://github.com/Syph-and-VPD-Lab/autoBIGS.engine"
|
||||
Issues = "https://github.com/Syph-and-VPD-Lab/autoBIGS.engine/issues"
|
||||
|
||||
[tool.setuptools_scm]
|
||||
|
||||
|
@@ -124,13 +124,17 @@ class RemoteBIGSdbMLSTProfiler(BIGSdbMLSTProfiler):
|
||||
|
||||
async def profile_multiple_strings(self, query_named_string_groups: AsyncIterable[Iterable[NamedString]], stop_on_fail: bool = False) -> AsyncGenerator[NamedMLSTProfile, Any]:
|
||||
async for named_strings in query_named_string_groups:
|
||||
names: list[str] = list()
|
||||
sequences: list[str] = list()
|
||||
for named_string in named_strings:
|
||||
names.append(named_string.name)
|
||||
sequences.append(named_string.sequence)
|
||||
try:
|
||||
yield NamedMLSTProfile(named_string.name, (await self.profile_string([named_string.sequence])))
|
||||
yield NamedMLSTProfile("-".join(names), (await self.profile_string(sequences)))
|
||||
except NoBIGSdbMatchesException as e:
|
||||
if stop_on_fail:
|
||||
raise e
|
||||
yield NamedMLSTProfile(named_string.name, None)
|
||||
yield NamedMLSTProfile("-".join(names), None)
|
||||
|
||||
async def close(self):
|
||||
await self._http_client.close()
|
||||
|
@@ -5,12 +5,13 @@ from Bio import SeqIO
|
||||
|
||||
from autobigs.engine.structures.genomics import NamedString
|
||||
|
||||
async def read_fasta(handle: Union[str, TextIOWrapper]) -> AsyncGenerator[NamedString, Any]:
|
||||
async def read_fasta(handle: Union[str, TextIOWrapper]) -> Iterable[NamedString]:
|
||||
fasta_sequences = asyncio.to_thread(SeqIO.parse, handle=handle, format="fasta")
|
||||
results = []
|
||||
for fasta_sequence in await fasta_sequences:
|
||||
yield NamedString(fasta_sequence.id, str(fasta_sequence.seq))
|
||||
results.append(NamedString(fasta_sequence.id, str(fasta_sequence.seq)))
|
||||
return results
|
||||
|
||||
async def read_multiple_fastas(handles: Iterable[Union[str, TextIOWrapper]]) -> AsyncGenerator[NamedString, Any]:
|
||||
async def read_multiple_fastas(handles: Iterable[Union[str, TextIOWrapper]]) -> AsyncGenerator[Iterable[NamedString], Any]:
|
||||
for handle in handles:
|
||||
async for named_seq in read_fasta(handle):
|
||||
yield named_seq
|
||||
yield await read_fasta(handle)
|
@@ -3,7 +3,7 @@ import csv
|
||||
from os import PathLike
|
||||
from typing import AsyncIterable, Collection, Mapping, Sequence, Union
|
||||
|
||||
from autobigs.engine.structures.mlst import Allele, MLSTProfile
|
||||
from autobigs.engine.structures.mlst import Allele, MLSTProfile, NamedMLSTProfile
|
||||
|
||||
|
||||
def alleles_to_text_map(alleles: Collection[Allele]) -> Mapping[str, Union[Sequence[str], str]]:
|
||||
@@ -17,12 +17,14 @@ def alleles_to_text_map(alleles: Collection[Allele]) -> Mapping[str, Union[Seque
|
||||
result[locus] = tuple(result[locus]) # type: ignore
|
||||
return dict(result)
|
||||
|
||||
async def write_mlst_profiles_as_csv(mlst_profiles_iterable: AsyncIterable[tuple[str, Union[MLSTProfile, None]]], handle: Union[str, bytes, PathLike[str], PathLike[bytes]]) -> Sequence[str]:
|
||||
async def write_mlst_profiles_as_csv(mlst_profiles_iterable: AsyncIterable[NamedMLSTProfile], handle: Union[str, bytes, PathLike[str], PathLike[bytes]]) -> Sequence[str]:
|
||||
failed = list()
|
||||
with open(handle, "w", newline='') as filehandle:
|
||||
header = None
|
||||
writer: Union[csv.DictWriter, None] = None
|
||||
async for name, mlst_profile in mlst_profiles_iterable:
|
||||
async for named_mlst_profile in mlst_profiles_iterable:
|
||||
name = named_mlst_profile.name
|
||||
mlst_profile = named_mlst_profile.mlst_profile
|
||||
if mlst_profile is None:
|
||||
failed.append(name)
|
||||
continue
|
||||
|
@@ -2,6 +2,6 @@ from autobigs.engine.reading import read_fasta
|
||||
|
||||
|
||||
async def test_fasta_reader_not_none():
|
||||
named_strings = read_fasta("tests/resources/tohama_I_bpertussis.fasta")
|
||||
async for named_string in named_strings:
|
||||
named_strings = await read_fasta("tests/resources/tohama_I_bpertussis.fasta")
|
||||
for named_string in named_strings:
|
||||
assert named_string.name == "BX470248.1"
|
||||
|
@@ -3,7 +3,7 @@ from typing import AsyncIterable, Iterable
|
||||
import pytest
|
||||
from autobigs.engine.structures.alignment import AlignmentStats
|
||||
from autobigs.engine.writing import alleles_to_text_map, write_mlst_profiles_as_csv
|
||||
from autobigs.engine.structures.mlst import Allele, MLSTProfile
|
||||
from autobigs.engine.structures.mlst import Allele, MLSTProfile, NamedMLSTProfile
|
||||
import tempfile
|
||||
from csv import reader
|
||||
from os import path
|
||||
@@ -11,20 +11,20 @@ from os import path
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_alphabet_mlst_profile():
|
||||
return MLSTProfile((
|
||||
return NamedMLSTProfile("name", MLSTProfile((
|
||||
Allele("A", "1", None),
|
||||
Allele("D", "1", None),
|
||||
Allele("B", "1", None),
|
||||
Allele("C", "1", None),
|
||||
Allele("C", "2", AlignmentStats(90, 10, 0, 90))
|
||||
), "mysterious", "very mysterious")
|
||||
), "mysterious", "very mysterious"))
|
||||
|
||||
async def iterable_to_asynciterable(iterable: Iterable):
|
||||
for iterated in iterable:
|
||||
yield iterated
|
||||
|
||||
async def test_column_order_is_same_as_expected_file(dummy_alphabet_mlst_profile: MLSTProfile):
|
||||
dummy_profiles = [("test_1", dummy_alphabet_mlst_profile)]
|
||||
dummy_profiles = [dummy_alphabet_mlst_profile]
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
output_path = path.join(temp_dir, "out.csv")
|
||||
await write_mlst_profiles_as_csv(iterable_to_asynciterable(dummy_profiles), output_path)
|
||||
@@ -34,8 +34,8 @@ async def test_column_order_is_same_as_expected_file(dummy_alphabet_mlst_profile
|
||||
target_columns = lines[4:]
|
||||
assert target_columns == sorted(target_columns)
|
||||
|
||||
async def test_alleles_to_text_map_mapping_is_correct(dummy_alphabet_mlst_profile: MLSTProfile):
|
||||
mapping = alleles_to_text_map(dummy_alphabet_mlst_profile.alleles)
|
||||
async def test_alleles_to_text_map_mapping_is_correct(dummy_alphabet_mlst_profile: NamedMLSTProfile):
|
||||
mapping = alleles_to_text_map(dummy_alphabet_mlst_profile.mlst_profile.alleles) # type: ignore
|
||||
expected_mapping = {
|
||||
"A": "1",
|
||||
"B": "1",
|
||||
|
Reference in New Issue
Block a user