Compare commits
5 Commits
0.11.0
...
62ce1c9b2f
Author | SHA1 | Date | |
---|---|---|---|
62ce1c9b2f | |||
7384895578 | |||
5a03c7e8d8 | |||
ddf9cde175 | |||
2e8cdd8da9 |
17
README.md
17
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`.
|
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
|
## Features
|
||||||
|
|
||||||
Briefly, this library can:
|
Briefly, this library can:
|
||||||
@@ -22,4 +23,16 @@ Then, it's as easy as running `pip install autobigs-engine` in any terminal that
|
|||||||
|
|
||||||
### CLI usage
|
### 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.
|
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"
|
requires-python = ">=3.12"
|
||||||
description = "A library to rapidly fetch fetch MLST profiles given sequences for various diseases."
|
description = "A library to rapidly fetch fetch MLST profiles given sequences for various diseases."
|
||||||
|
license = {text = "GPL-3.0-or-later"}
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Homepage = "https://github.com/RealYHD/autoBIGS.engine"
|
Homepage = "https://github.com/Syph-and-VPD-Lab/autoBIGS.engine"
|
||||||
Source = "https://github.com/RealYHD/autoBIGS.engine"
|
Source = "https://github.com/Syph-and-VPD-Lab/autoBIGS.engine"
|
||||||
Issues = "https://github.com/RealYHD/autoBIGS.engine/issues"
|
Issues = "https://github.com/Syph-and-VPD-Lab/autoBIGS.engine/issues"
|
||||||
|
|
||||||
[tool.setuptools_scm]
|
[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 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:
|
async for named_strings in query_named_string_groups:
|
||||||
|
names: list[str] = list()
|
||||||
|
sequences: list[str] = list()
|
||||||
for named_string in named_strings:
|
for named_string in named_strings:
|
||||||
try:
|
names.append(named_string.name)
|
||||||
yield NamedMLSTProfile(named_string.name, (await self.profile_string([named_string.sequence])))
|
sequences.append(named_string.sequence)
|
||||||
except NoBIGSdbMatchesException as e:
|
try:
|
||||||
if stop_on_fail:
|
yield NamedMLSTProfile("-".join(names), (await self.profile_string(sequences)))
|
||||||
raise e
|
except NoBIGSdbMatchesException as e:
|
||||||
yield NamedMLSTProfile(named_string.name, None)
|
if stop_on_fail:
|
||||||
|
raise e
|
||||||
|
yield NamedMLSTProfile("-".join(names), None)
|
||||||
|
|
||||||
async def close(self):
|
async def close(self):
|
||||||
await self._http_client.close()
|
await self._http_client.close()
|
||||||
|
@@ -3,7 +3,7 @@ import csv
|
|||||||
from os import PathLike
|
from os import PathLike
|
||||||
from typing import AsyncIterable, Collection, Mapping, Sequence, Union
|
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]]:
|
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
|
result[locus] = tuple(result[locus]) # type: ignore
|
||||||
return dict(result)
|
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()
|
failed = list()
|
||||||
with open(handle, "w", newline='') as filehandle:
|
with open(handle, "w", newline='') as filehandle:
|
||||||
header = None
|
header = None
|
||||||
writer: Union[csv.DictWriter, None] = 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:
|
if mlst_profile is None:
|
||||||
failed.append(name)
|
failed.append(name)
|
||||||
continue
|
continue
|
||||||
|
@@ -3,7 +3,7 @@ from typing import AsyncIterable, Iterable
|
|||||||
import pytest
|
import pytest
|
||||||
from autobigs.engine.structures.alignment import AlignmentStats
|
from autobigs.engine.structures.alignment import AlignmentStats
|
||||||
from autobigs.engine.writing import alleles_to_text_map, write_mlst_profiles_as_csv
|
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
|
import tempfile
|
||||||
from csv import reader
|
from csv import reader
|
||||||
from os import path
|
from os import path
|
||||||
@@ -11,20 +11,20 @@ from os import path
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def dummy_alphabet_mlst_profile():
|
def dummy_alphabet_mlst_profile():
|
||||||
return MLSTProfile((
|
return NamedMLSTProfile("name", MLSTProfile((
|
||||||
Allele("A", "1", None),
|
Allele("A", "1", None),
|
||||||
Allele("D", "1", None),
|
Allele("D", "1", None),
|
||||||
Allele("B", "1", None),
|
Allele("B", "1", None),
|
||||||
Allele("C", "1", None),
|
Allele("C", "1", None),
|
||||||
Allele("C", "2", AlignmentStats(90, 10, 0, 90))
|
Allele("C", "2", AlignmentStats(90, 10, 0, 90))
|
||||||
), "mysterious", "very mysterious")
|
), "mysterious", "very mysterious"))
|
||||||
|
|
||||||
async def iterable_to_asynciterable(iterable: Iterable):
|
async def iterable_to_asynciterable(iterable: Iterable):
|
||||||
for iterated in iterable:
|
for iterated in iterable:
|
||||||
yield iterated
|
yield iterated
|
||||||
|
|
||||||
async def test_column_order_is_same_as_expected_file(dummy_alphabet_mlst_profile: MLSTProfile):
|
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:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
output_path = path.join(temp_dir, "out.csv")
|
output_path = path.join(temp_dir, "out.csv")
|
||||||
await write_mlst_profiles_as_csv(iterable_to_asynciterable(dummy_profiles), output_path)
|
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:]
|
target_columns = lines[4:]
|
||||||
assert target_columns == sorted(target_columns)
|
assert target_columns == sorted(target_columns)
|
||||||
|
|
||||||
async def test_alleles_to_text_map_mapping_is_correct(dummy_alphabet_mlst_profile: MLSTProfile):
|
async def test_alleles_to_text_map_mapping_is_correct(dummy_alphabet_mlst_profile: NamedMLSTProfile):
|
||||||
mapping = alleles_to_text_map(dummy_alphabet_mlst_profile.alleles)
|
mapping = alleles_to_text_map(dummy_alphabet_mlst_profile.mlst_profile.alleles) # type: ignore
|
||||||
expected_mapping = {
|
expected_mapping = {
|
||||||
"A": "1",
|
"A": "1",
|
||||||
"B": "1",
|
"B": "1",
|
||||||
@@ -44,4 +44,4 @@ async def test_alleles_to_text_map_mapping_is_correct(dummy_alphabet_mlst_profil
|
|||||||
}
|
}
|
||||||
for allele_name, allele_ids in mapping.items():
|
for allele_name, allele_ids in mapping.items():
|
||||||
assert allele_name in expected_mapping
|
assert allele_name in expected_mapping
|
||||||
assert allele_ids == expected_mapping[allele_name]
|
assert allele_ids == expected_mapping[allele_name]
|
||||||
|
Reference in New Issue
Block a user