pax_global_header00006660000000000000000000000064140321040720014503gustar00rootroot0000000000000052 comment=9e228d47dd4561fdf63326513090a7b1cf0478f2 pyspoa-0.0.8/000077500000000000000000000000001403210407200130235ustar00rootroot00000000000000pyspoa-0.0.8/.github/000077500000000000000000000000001403210407200143635ustar00rootroot00000000000000pyspoa-0.0.8/.github/workflows/000077500000000000000000000000001403210407200164205ustar00rootroot00000000000000pyspoa-0.0.8/.github/workflows/build-wheels.sh000077500000000000000000000006171403210407200213470ustar00rootroot00000000000000#!/bin/bash set -e -x for PYBIN in /opt/python/cp3[6789]*/bin; do rm -rf venv3 "${PYBIN}/python3" -m venv venv3 source venv3/bin/activate python3 -m pip install cmake==3.18.4 python3 -m pip install -r requirements.txt make test "${PYBIN}/python3" setup.py bdist_wheel make clean deactivate done for wheel in dist/*.whl; do auditwheel repair "${wheel}" done pyspoa-0.0.8/.github/workflows/publish.yml000066400000000000000000000021151403210407200206100ustar00rootroot00000000000000name: publish-pyspao on: push: tags: - 'v*' jobs: linux-wheels: runs-on: ubuntu-latest container: quay.io/pypa/manylinux2010_x86_64 steps: - uses: actions/checkout@v1 - name: Build wheels run: | git submodule update --init --recursive bash .github/workflows/build-wheels.sh - uses: actions/upload-artifact@v1 with: name: linux-wheels path: wheelhouse/ osx-wheels: runs-on: macos-latest strategy: matrix: python-version: [3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Build wheels run: | git submodule update --init --recursive python3 -m venv venv3 source venv3/bin/activate python3 -m pip install -r requirements.txt make test python3 setup.py bdist_wheel - uses: actions/upload-artifact@v1 with: name: osx-${{ matrix.python-version }}-wheel path: dist/ pyspoa-0.0.8/.github/workflows/test.yml000066400000000000000000000024551403210407200201300ustar00rootroot00000000000000name: test-pyspoa on: [push] jobs: test: strategy: matrix: os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: python-version: '3.9' - name: Test ${{ matrix.os }} binding run: | git submodule update --init --recursive python3 -m venv venv3 source venv3/bin/activate python3 -m pip install -r requirements.txt make test linux-wheels: runs-on: ubuntu-latest container: quay.io/pypa/manylinux2010_x86_64 steps: - uses: actions/checkout@v1 - name: Build wheels run: | git submodule update --init --recursive bash .github/workflows/build-wheels.sh osx-wheels: runs-on: macos-latest strategy: matrix: python-version: [3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Build wheels run: | git submodule update --init --recursive python3 -m venv venv3 source venv3/bin/activate python3 -m pip install -r requirements.txt make test python3 setup.py bdist_wheel pyspoa-0.0.8/.gitignore000066400000000000000000000000671403210407200150160ustar00rootroot00000000000000.eggs/ dist/ build/ *~ *.so *-info/ tmp/ pyspoa/ venv*/pyspoa-0.0.8/.gitmodules000066400000000000000000000001101403210407200151700ustar00rootroot00000000000000[submodule "src"] path = src url = https://github.com/rvaser/spoa.git pyspoa-0.0.8/LICENSE000066400000000000000000000021031403210407200140240ustar00rootroot00000000000000MIT License Copyright (c) 2020 Oxford Nanopore Technologies, Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyspoa-0.0.8/MANIFEST.in000066400000000000000000000000311403210407200145530ustar00rootroot00000000000000recursive-include src/ * pyspoa-0.0.8/Makefile000066400000000000000000000002121403210407200144560ustar00rootroot00000000000000build: python3 setup.py develop test: build python3 tests/test_pyspoa.py clean: rm -rf src/build build tmp *~ python setup.py clean pyspoa-0.0.8/README.md000066400000000000000000000031771403210407200143120ustar00rootroot00000000000000# pyspoa ![test-pyspoa](https://github.com/nanoporetech/pyspoa/workflows/test-pyspoa/badge.svg) [![PyPI version](https://badge.fury.io/py/pyspoa.svg)](https://badge.fury.io/py/pyspoa) Python bindings to [spoa](https://github.com/rvaser/spoa). ## Installation ```bash $ pip install pyspoa ``` ## Usage ```python >>> from spoa import poa >>> >>> consensus, msa = poa(['AACTTATA', 'AACTTATG', 'AACTATA']) >>> consensus 'AACTTATA' >>> msa ['AACTTATA-', 'AACTTAT-G', 'AAC-TATA-'] >>> print(os.linesep.join(msa)) AACTTATA- AACTTAT-G AAC-TATA- ``` ## Developer Quick Start ```bash $ git clone --recursive https://github.com/nanoporetech/pyspoa.git $ cd pyspoa $ python3 -m venv pyspoa $ source pyspoa/bin/activate (pyspoa) $ pip install -r requirements.txt (pyspoa) $ make build ``` ### Licence and Copyright (c) 2019 Oxford Nanopore Technologies Ltd. pyspoa is distributed under the terms of the MIT License. If a copy of the License was not distributed with this file, You can obtain one at https://github.com/nanoporetech/pyspoa ### Research Release Research releases are provided as technology demonstrators to provide early access to features or stimulate Community development of tools. Support for this software will be minimal and is only provided directly by the developers. Feature requests, improvements, and discussions are welcome and can be implemented by forking and pull requests. However much as we would like to rectify every issue and piece of feedback users may have, the developers may have limited resource for support of this software. Research releases may be unstable and subject to rapid iteration by Oxford Nanopore Technologies. pyspoa-0.0.8/pyspoa.cpp000066400000000000000000000020031403210407200150350ustar00rootroot00000000000000#include "spoa.hpp" #include #include using namespace pybind11::literals; // for _a in pybind def auto poa(std::vector sequences, int algorithm, bool genmsa, int m, int n, int g, int e, int q, int c) -> pybind11::tuple { auto alignment_engine = spoa::AlignmentEngine::Create( static_cast(algorithm), m, n, g, e, q, c ); spoa::Graph graph{}; for (const auto& it: sequences) { auto alignment = alignment_engine->Align(it, graph); graph.AddAlignment(alignment, it); } auto consensus = graph.GenerateConsensus(); std::vector msa; if (genmsa) msa = graph.GenerateMultipleSequenceAlignment(); return pybind11::make_tuple(consensus, msa); } PYBIND11_MODULE(spoa, m) { m.def( "poa", &poa, "", "sequences"_a, "algorithm"_a=0, "genmsa"_a=true, "m"_a=5, "n"_a=-4, "g"_a=-8, "e"_a=-6, "q"_a=-10, "c"_a=-4 ); m.attr("__version__") = VERSION_INFO; } pyspoa-0.0.8/requirements.txt000066400000000000000000000001041403210407200163020ustar00rootroot00000000000000wheel>=0.34.1 pybind11>=2.4 auditwheel>=3.1.0 scikit-build==0.11.1 pyspoa-0.0.8/setup.py000066400000000000000000000077621403210407200145510ustar00rootroot00000000000000import os import sys import setuptools from shutil import rmtree from subprocess import run from setuptools import setup, Extension from setuptools.command.build_ext import build_ext from setuptools.command.install import install class get_pybind_include(object): """ Helper class to determine the pybind11 include path The purpose of this class is to postpone importing pybind11 until it is actually installed, so that the ``get_include()`` method can be invoked. """ def __init__(self, user=False): self.user = user def __str__(self): import pybind11 return pybind11.get_include(self.user) def has_flag(compiler, flagname): """ Return a boolean indicating whether a flag name is supported on the specified compiler. """ import tempfile with tempfile.NamedTemporaryFile('w', suffix='.cpp') as f: f.write('int main (int argc, char **argv) { return 0; }') try: compiler.compile([f.name], extra_postargs=[flagname]) except setuptools.distutils.errors.CompileError: return False return True def cpp_flag(compiler): """ Return the -std=c++[11/14/17] compiler flag. The newer version is prefered over c++11 (when it is available). """ flags = ['-std=c++14', '-std=c++11'] for flag in flags: if has_flag(compiler, flag): return flag raise RuntimeError('Unsupported compiler -- at least C++11 support is needed!') class BuildExt(build_ext): """ A custom build extension for adding compiler-specific options. """ c_opts = { 'msvc': ['/EHsc'], 'unix': [], } l_opts = { 'msvc': [], 'unix': [], } if sys.platform == 'darwin': darwin_opts = ['-stdlib=libc++', '-mmacosx-version-min=10.7'] c_opts['unix'] += darwin_opts l_opts['unix'] += darwin_opts def build_extensions(self): ct = self.compiler.compiler_type opts = self.c_opts.get(ct, []) link_opts = self.l_opts.get(ct, []) if ct == 'unix': opts.append('-DVERSION_INFO="%s"' % self.distribution.get_version()) opts.append(cpp_flag(self.compiler)) if has_flag(self.compiler, '-fvisibility=hidden'): opts.append('-fvisibility=hidden') elif ct == 'msvc': opts.append('/DVERSION_INFO=\\"%s\\"' % self.distribution.get_version()) for ext in self.extensions: ext.extra_compile_args = opts ext.extra_link_args = link_opts build_ext.build_extensions(self) ext_modules = [ Extension( 'spoa', ['pyspoa.cpp'], include_dirs=[ 'src/include/spoa', 'src/vendor/cereal/include', get_pybind_include(), get_pybind_include(user=True), ], language='c++', extra_objects=[ 'src/build/lib/libspoa.a' ], ), ] with open('README.md', encoding='utf-8') as f: long_description = f.read() class build_spoa(install): def run(self): bdir = "src/build" rmtree(bdir, ignore_errors=True) os.makedirs(bdir) run([ "cmake", "-D", "spoa_optimize_for_portability=ON", "-D", "CMAKE_BUILD_TYPE=Release", "-D", "CMAKE_CXX_FLAGS='-I ../vendor/cereal/include/ -fPIC '", "..", ], cwd=bdir) run("make", cwd=bdir) install.run(self) setup( name='pyspoa', version='0.0.8', author='Oxford Nanoporetech Technologies, Ltd.', author_email='support@nanoporetech.com', url='https://github.com/nanoporetech/pyspoa', description='Python bindings to spoa', long_description=long_description, long_description_content_type='text/markdown', ext_modules=ext_modules, install_requires=['pybind11>=2.4', 'cmake==3.18.4'], setup_requires=['pybind11>=2.4', 'cmake==3.18.4'], cmdclass={ 'build_ext': BuildExt, 'develop': build_spoa, 'install': build_spoa, }, zip_safe=False, ) pyspoa-0.0.8/src/000077500000000000000000000000001403210407200136125ustar00rootroot00000000000000pyspoa-0.0.8/tests/000077500000000000000000000000001403210407200141655ustar00rootroot00000000000000pyspoa-0.0.8/tests/test_pyspoa.py000066400000000000000000000011771403210407200171170ustar00rootroot00000000000000#!/usr/env/bin python3 from spoa import poa from unittest import TestCase, main class Tests(TestCase): def test_bindings(self): """ simple poa to check bindings""" consensus, msa = poa(['AACTTATA', 'AACTTATG', 'AACTATA']) self.assertEqual(consensus, 'AACTTATA') self.assertEqual(len(msa), 3) def test_bindings_no_msa(self): """ simple poa to check bindings with msa generation""" consensus, msa = poa(['AACTTATA', 'AACTTATG', 'AACTATA'], genmsa=False) self.assertEqual(consensus, 'AACTTATA') self.assertEqual(len(msa), 0) if __name__ == '__main__': main()