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: 6 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ commands:
make allchecks
python -m pytest -n2

- run:
name: Build cython example LWT interface code and run
command: |
cd python/lwt_interface/cython_example
make

- run:
name: Generate coverage
command: |
Expand Down
13 changes: 13 additions & 0 deletions python/lwt_interface/cython_example/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
all: compile run

compile:
pip install -e . --use-pep517

run:
PYTHONPATH=../.. python -c "import example; example.main()"

clean:
rm -rf build/
rm -rf tskit_cython_example.egg-info/
rm -f example.c
rm -f *.so
64 changes: 64 additions & 0 deletions python/lwt_interface/cython_example/_lwtc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* MIT License
*
* Copyright (c) 2019-2020 Tskit Developers
* Copyright (c) 2015-2018 University of Oxford
*
* 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.
*/
// Turn off clang-formatting for this file as turning off formatting
// for specific bits will make it more confusing.
// clang-format off

#define PY_SSIZE_T_CLEAN
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include <Python.h>
#include <structmember.h>
#include <numpy/arrayobject.h>

#include "kastore.h"
#include "tskit.h"

#include "tskit_lwt_interface.h"

static PyMethodDef lwt_methods[] = {
{ NULL, NULL, 0, NULL } /* sentinel */
};

static struct PyModuleDef lwt_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "_lwt",
.m_doc = "tskit LightweightTableCollection",
.m_size = -1,
.m_methods = lwt_methods };

PyMODINIT_FUNC
PyInit__lwtc(void)
{
PyObject *module = PyModule_Create(&lwt_module);
if (module == NULL) {
return NULL;
}
import_array();
if (register_lwt_class(module) != 0) {
return NULL;
}
return module;
}
63 changes: 63 additions & 0 deletions python/lwt_interface/cython_example/example.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from libc.stdint cimport uint32_t
import _lwtc
import tskit

cdef extern from "tskit.h" nogil:
ctypedef uint32_t tsk_flags_t
ctypedef struct tsk_table_collection_t:
pass
ctypedef struct tsk_treeseq_t:
pass
int tsk_treeseq_init(tsk_treeseq_t *self, const tsk_table_collection_t *tables, tsk_flags_t options)
int tsk_treeseq_free(tsk_treeseq_t *self)
int tsk_table_collection_build_index(tsk_table_collection_t *self, tsk_flags_t options)
ctypedef struct tsk_tree_t:
pass
int tsk_tree_init(tsk_tree_t *self, const tsk_treeseq_t *ts, tsk_flags_t options)
int tsk_tree_first(tsk_tree_t *self)
int tsk_tree_next(tsk_tree_t *self)
int tsk_tree_last(tsk_tree_t *self)
int tsk_tree_prev(tsk_tree_t *self)
int tsk_tree_get_num_roots(tsk_tree_t *self)
int tsk_tree_free(tsk_tree_t *self)
const char *tsk_strerror(int err)

cdef extern:
ctypedef class _lwtc.LightweightTableCollection [object LightweightTableCollection]:
cdef tsk_table_collection_t *tables

def check_tsk_error(val):
if val < 0:
raise RuntimeError(tsk_strerror(val))

def iterate_trees(pyts: tskit.TreeSequence):
lwtc = LightweightTableCollection()
lwtc.fromdict(pyts.dump_tables().asdict())
cdef tsk_treeseq_t ts
err = tsk_treeseq_init(&ts, lwtc.tables, 0)
check_tsk_error(err)
cdef tsk_tree_t tree
ret = tsk_tree_init(&tree, &ts, 0)
check_tsk_error(ret)

print("Iterate forwards")
cdef int tree_iter = tsk_tree_first(&tree)
while tree_iter == 1:
print("\ttree has %d roots" % (tsk_tree_get_num_roots(&tree)))
tree_iter = tsk_tree_next(&tree)
check_tsk_error(tree_iter)

print("Iterate backwards")
tree_iter = tsk_tree_last(&tree)
while tree_iter == 1:
print("\ttree has %d roots" % (tsk_tree_get_num_roots(&tree)))
tree_iter = tsk_tree_prev(&tree)
check_tsk_error(tree_iter)

tsk_tree_free(&tree)
tsk_treeseq_free(&ts)

def main():
import msprime as msp # (msprime could be compiled against a different version of tskit)
ts = msp.simulate(sample_size=5, length=100, recombination_rate=.01)
iterate_trees(ts)
13 changes: 13 additions & 0 deletions python/lwt_interface/cython_example/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[build-system]
requires = ["setuptools>=64", "wheel", "Cython", "numpy"]
build-backend = "setuptools.build_meta"

[project]
name = "tskit_cython_example"
version = "0.0.1"
description = "Cython example for tskit"
authors = [{name = "tskit developers"}]
dependencies = ["numpy", "Cython"]

[tool.setuptools]
packages = []
40 changes: 40 additions & 0 deletions python/lwt_interface/cython_example/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import glob
import os

import numpy as np
from Cython.Build import cythonize
from setuptools import setup
from setuptools.extension import Extension

TSKIT_BASE = os.path.join(os.path.dirname(__file__), "..", "..", "..")
TSKIT_C_PATH = os.path.join(TSKIT_BASE, "c")
TSKIT_PY_PATH = os.path.join(TSKIT_BASE, "python/lwt_interface")
KASTORE_PATH = os.path.join(TSKIT_BASE, "c", "subprojects", "kastore")
include_dirs = [TSKIT_C_PATH, TSKIT_PY_PATH, KASTORE_PATH, np.get_include()]

tskit_sourcefiles = list(glob.glob(os.path.join(TSKIT_C_PATH, "tskit", "*.c"))) + [
os.path.join(KASTORE_PATH, "kastore.c")
]

extensions = [
Extension(
"_lwtc",
["_lwtc.c"] + tskit_sourcefiles,
language="c",
include_dirs=include_dirs,
),
Extension(
"example",
["example.pyx"] + tskit_sourcefiles,
language="c",
include_dirs=include_dirs,
),
]

extensions = cythonize(extensions, language_level=3)

setup(
name="tskit_cython_example",
version="0.0.1",
ext_modules=extensions,
)
Loading