Skip to content

Commit 0eb2637

Browse files
Merge pull request #114 from jeromekelleher/py-0.1.4
Py 0.1.4
2 parents 0ccf1c9 + 8372f2c commit 0eb2637

File tree

7 files changed

+218
-7
lines changed

7 files changed

+218
-7
lines changed

docs/c-api.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,11 @@ ensure that it is a **released version**. Released versions are
163163
tagged on GitHub using the convention ``C_{VERSION}``. The code
164164
can either be downloaded from GitHub on the `releases page
165165
<https://github.com/tskit-dev/tskit/releases>`_ or checked out
166-
using git. For example, to check out the ``C_0.99.0`` release::
166+
using git. For example, to check out the ``C_0.99.1`` release::
167167

168168
$ git clone https://github.com/tskit-dev/tskit.git
169169
$ cd tskit
170-
$ git checkout C_0.99.0
170+
$ git checkout C_0.99.1
171171

172172
Git submodules may also be considered---see the
173173
`example <https://github.com/tskit-dev/tskit-build-examples/tree/master/meson>`_

python/CHANGELOG.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
--------------------
2+
[0.1.4] - 2019-02-01
3+
--------------------
4+
5+
Minor feature update. Using the C API 0.99.1.
6+
7+
**New features**
8+
9+
- Add interface for setting TableCollection.sequence_length:
10+
https://github.com/tskit-dev/tskit/issues/107
11+
- Add support for building and dropping TableCollection indexes:
12+
https://github.com/tskit-dev/tskit/issues/108
13+
14+
115
--------------------
216
[0.1.3] - 2019-01-14
317
--------------------

python/_tskitmodule.c

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5372,6 +5372,25 @@ TableCollection_get_sequence_length(TableCollection *self, void *closure)
53725372
return Py_BuildValue("f", self->tables->sequence_length);
53735373
}
53745374

5375+
static int
5376+
TableCollection_set_sequence_length(TableCollection *self, PyObject *value, void *closure)
5377+
{
5378+
int ret = -1;
5379+
5380+
if (value == NULL) {
5381+
PyErr_SetString(PyExc_TypeError, "Cannot delete the sequence_length attribute");
5382+
goto out;
5383+
}
5384+
if (! PyNumber_Check(value)) {
5385+
PyErr_SetString(PyExc_TypeError, "sequence_length must be a number");
5386+
goto out;
5387+
}
5388+
self->tables->sequence_length = PyFloat_AsDouble(value);
5389+
ret = 0;
5390+
out:
5391+
return ret;
5392+
}
5393+
53755394
static PyObject *
53765395
TableCollection_get_file_uuid(TableCollection *self, void *closure)
53775396
{
@@ -5499,6 +5518,45 @@ TableCollection_deduplicate_sites(TableCollection *self)
54995518
return ret;
55005519
}
55015520

5521+
static PyObject *
5522+
TableCollection_build_index(TableCollection *self)
5523+
{
5524+
int err;
5525+
PyObject *ret = NULL;
5526+
5527+
err = tsk_table_collection_build_index(self->tables, 0);
5528+
if (err != 0) {
5529+
handle_library_error(err);
5530+
goto out;
5531+
}
5532+
ret = Py_BuildValue("");
5533+
out:
5534+
return ret;
5535+
}
5536+
5537+
static PyObject *
5538+
TableCollection_drop_index(TableCollection *self)
5539+
{
5540+
int err;
5541+
PyObject *ret = NULL;
5542+
5543+
err = tsk_table_collection_drop_index(self->tables, 0);
5544+
if (err != 0) {
5545+
handle_library_error(err);
5546+
goto out;
5547+
}
5548+
ret = Py_BuildValue("");
5549+
out:
5550+
return ret;
5551+
}
5552+
5553+
static PyObject *
5554+
TableCollection_has_index(TableCollection *self)
5555+
{
5556+
bool has_index = tsk_table_collection_has_index(self->tables, 0);
5557+
return Py_BuildValue("i", (int) has_index);
5558+
}
5559+
55025560
/* Forward declaration */
55035561
static PyTypeObject TableCollectionType;
55045562

@@ -5525,24 +5583,31 @@ static PyGetSetDef TableCollection_getsetters[] = {
55255583
{"mutations", (getter) TableCollection_get_mutations, NULL, "The mutation table."},
55265584
{"populations", (getter) TableCollection_get_populations, NULL, "The population table."},
55275585
{"provenances", (getter) TableCollection_get_provenances, NULL, "The provenance table."},
5528-
{"sequence_length", (getter) TableCollection_get_sequence_length, NULL,
5529-
"The sequence length."},
5586+
{"sequence_length",
5587+
(getter) TableCollection_get_sequence_length,
5588+
(setter) TableCollection_set_sequence_length, "The sequence length."},
55305589
{"file_uuid", (getter) TableCollection_get_file_uuid, NULL,
55315590
"The UUID of the corresponding file."},
55325591
{NULL} /* Sentinel */
55335592
};
55345593

55355594
static PyMethodDef TableCollection_methods[] = {
55365595
{"simplify", (PyCFunction) TableCollection_simplify, METH_VARARGS|METH_KEYWORDS,
5537-
"Simplifies for a given sample subset." },
5596+
"Simplifies for a given sample subset." },
55385597
{"sort", (PyCFunction) TableCollection_sort, METH_VARARGS|METH_KEYWORDS,
5539-
"Sorts the tables to satisfy tree sequence requirements." },
5598+
"Sorts the tables to satisfy tree sequence requirements." },
55405599
{"equals", (PyCFunction) TableCollection_equals, METH_VARARGS,
5541-
"Returns True if the parameter table collection is equal to this one." },
5600+
"Returns True if the parameter table collection is equal to this one." },
55425601
{"compute_mutation_parents", (PyCFunction) TableCollection_compute_mutation_parents,
55435602
METH_NOARGS, "Computes the mutation parents for a the tables." },
55445603
{"deduplicate_sites", (PyCFunction) TableCollection_deduplicate_sites,
55455604
METH_NOARGS, "Removes sites with duplicate positions." },
5605+
{"build_index", (PyCFunction) TableCollection_build_index,
5606+
METH_NOARGS, "Builds an index on the table collection." },
5607+
{"drop_index", (PyCFunction) TableCollection_drop_index,
5608+
METH_NOARGS, "Drops indexes." },
5609+
{"has_index", (PyCFunction) TableCollection_has_index,
5610+
METH_NOARGS, "Returns True if the TableCollection is indexed." },
55465611
{NULL} /* Sentinel */
55475612
};
55485613

python/tests/test_lowlevel.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,21 @@ def test_reference_deletion(self):
156156
for table in tables:
157157
self.assertGreater(len(str(table)), 0)
158158

159+
def test_set_sequence_length_errors(self):
160+
tables = _tskit.TableCollection(1)
161+
with self.assertRaises(TypeError):
162+
del tables.sequence_length
163+
for bad_value in ["sdf", None, []]:
164+
with self.assertRaises(TypeError):
165+
tables.sequence_length = bad_value
166+
167+
def test_set_sequence_length(self):
168+
tables = _tskit.TableCollection(1)
169+
self.assertEqual(tables.sequence_length, 1)
170+
for value in [-1, 1e6, 1e-22, 1000, 2**32, -10000]:
171+
tables.sequence_length = value
172+
self.assertEqual(tables.sequence_length, value)
173+
159174

160175
class TestTreeSequence(LowLevelTestCase):
161176
"""

python/tests/test_tables.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,89 @@ def test_uuid_empty(self):
15361536
tables = tskit.TableCollection(sequence_length=1)
15371537
self.assertIsNone(tables.file_uuid, None)
15381538

1539+
def test_empty_indexes(self):
1540+
tables = tskit.TableCollection(sequence_length=1)
1541+
self.assertFalse(tables.has_index())
1542+
tables.build_index()
1543+
self.assertTrue(tables.has_index())
1544+
tables.drop_index()
1545+
self.assertFalse(tables.has_index())
1546+
1547+
def test_index_unsorted(self):
1548+
tables = tskit.TableCollection(sequence_length=1)
1549+
tables.nodes.add_row(flags=1, time=0)
1550+
tables.nodes.add_row(flags=1, time=0)
1551+
tables.nodes.add_row(flags=1, time=0)
1552+
tables.nodes.add_row(flags=0, time=1)
1553+
tables.nodes.add_row(flags=0, time=2)
1554+
tables.edges.add_row(0, 1, 3, 0)
1555+
tables.edges.add_row(0, 1, 3, 1)
1556+
tables.edges.add_row(0, 1, 4, 3)
1557+
tables.edges.add_row(0, 1, 4, 2)
1558+
1559+
self.assertFalse(tables.has_index())
1560+
with self.assertRaises(tskit.LibraryError):
1561+
tables.build_index()
1562+
self.assertFalse(tables.has_index())
1563+
tables.sort()
1564+
tables.build_index()
1565+
self.assertTrue(tables.has_index())
1566+
ts = tables.tree_sequence()
1567+
self.assertEqual(ts.tables, tables)
1568+
1569+
def test_index_from_ts(self):
1570+
ts = msprime.simulate(10, random_seed=1)
1571+
tables = ts.dump_tables()
1572+
self.assertTrue(tables.has_index())
1573+
tables.drop_index()
1574+
self.assertFalse(tables.has_index())
1575+
ts = tables.tree_sequence()
1576+
self.assertEqual(ts.tables, tables)
1577+
self.assertFalse(tables.has_index())
1578+
1579+
def test_set_sequence_length_errors(self):
1580+
tables = tskit.TableCollection(1)
1581+
with self.assertRaises(AttributeError):
1582+
del tables.sequence_length
1583+
for bad_value in ["asdf", None, []]:
1584+
with self.assertRaises(TypeError):
1585+
tables.sequence_length = bad_value
1586+
1587+
def test_set_sequence_length(self):
1588+
tables = tskit.TableCollection(1)
1589+
for value in [-1, 100, 2**32, 1e-6]:
1590+
tables.sequence_length = value
1591+
self.assertEqual(tables.sequence_length, value)
1592+
1593+
def test_bad_sequence_length(self):
1594+
tables = msprime.simulate(10, random_seed=1).dump_tables()
1595+
self.assertEqual(tables.sequence_length, 1)
1596+
for value in [-1, 0, -0.99, 0.9999]:
1597+
tables.sequence_length = value
1598+
with self.assertRaises(tskit.LibraryError):
1599+
tables.tree_sequence()
1600+
with self.assertRaises(tskit.LibraryError):
1601+
tables.sort()
1602+
with self.assertRaises(tskit.LibraryError):
1603+
tables.build_index()
1604+
with self.assertRaises(tskit.LibraryError):
1605+
tables.compute_mutation_parents()
1606+
with self.assertRaises(tskit.LibraryError):
1607+
tables.simplify()
1608+
self.assertEqual(tables.sequence_length, value)
1609+
1610+
def test_sequence_length_longer_than_edges(self):
1611+
tables = msprime.simulate(10, random_seed=1).dump_tables()
1612+
tables.sequence_length = 2
1613+
ts = tables.tree_sequence()
1614+
self.assertEqual(ts.sequence_length, 2)
1615+
self.assertEqual(ts.num_trees, 2)
1616+
trees = ts.trees()
1617+
tree = next(trees)
1618+
self.assertGreater(len(tree.parent_dict), 0)
1619+
tree = next(trees)
1620+
self.assertEqual(len(tree.parent_dict), 0)
1621+
15391622

15401623
class TestTableCollectionPickle(unittest.TestCase):
15411624
"""

python/tskit/__main__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from __future__ import print_function
2+
from __future__ import division
3+
4+
5+
def main():
6+
print("Not implemented yet; please be patient!!")
7+
8+
9+
if __name__ == "__main__":
10+
main()

python/tskit/tables.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,10 @@ def provenances(self):
15171517
def sequence_length(self):
15181518
return self.ll_tables.sequence_length
15191519

1520+
@sequence_length.setter
1521+
def sequence_length(self, sequence_length):
1522+
self.ll_tables.sequence_length = sequence_length
1523+
15201524
@property
15211525
def file_uuid(self):
15221526
return self.ll_tables.file_uuid
@@ -1751,6 +1755,26 @@ def deduplicate_sites(self):
17511755
self.ll_tables.deduplicate_sites()
17521756
# TODO add provenance
17531757

1758+
def has_index(self):
1759+
"""
1760+
Returns True if this TableCollection is indexed.
1761+
"""
1762+
return bool(self.ll_tables.has_index())
1763+
1764+
def build_index(self):
1765+
"""
1766+
Builds an index on this TableCollection. Any existing indexes are automatically
1767+
dropped.
1768+
"""
1769+
self.ll_tables.build_index()
1770+
1771+
def drop_index(self):
1772+
"""
1773+
Drops an indexes present on this table collection. If the table are not currently
1774+
indexed this method has no effect.
1775+
"""
1776+
self.ll_tables.drop_index()
1777+
17541778

17551779
# Pickle support. See copyreg registration for this function below.
17561780
def _table_collection_pickle(tables):

0 commit comments

Comments
 (0)