Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add time_units enumeration #1832

Merged
merged 1 commit into from Oct 22, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion c/tests/test_tables.c
Expand Up @@ -454,7 +454,7 @@ test_table_collection_time_units(void)
tsk_table_collection_free(&tc2);
ret = tsk_table_collection_init(&tc1, 0);
CU_ASSERT_EQUAL_FATAL(ret, 0);
CU_ASSERT_EQUAL_FATAL(ret, strncmp(tc1.time_units, TSK_DEFAULT_TIME_UNITS, 7));
CU_ASSERT_EQUAL_FATAL(ret, strncmp(tc1.time_units, TSK_TIME_UNITS_UNKNOWN, 7));
tc1.sequence_length = 1.0;
ret = tsk_table_collection_dump(&tc1, _tmp_file_name, 0);
CU_ASSERT_EQUAL_FATAL(ret, 0);
Expand Down
2 changes: 1 addition & 1 deletion c/tskit/core.h
Expand Up @@ -87,7 +87,7 @@ __tsk_nan_f(void)
}
#define TSK_UNKNOWN_TIME __tsk_nan_f()

#define TSK_DEFAULT_TIME_UNITS "unknown"
#define TSK_TIME_UNITS_UNKNOWN "unknown"
#define TSK_TIME_UNITS_UNCALIBRATED "uncalibrated"

/**
Expand Down
2 changes: 1 addition & 1 deletion c/tskit/tables.c
Expand Up @@ -9789,7 +9789,7 @@ tsk_table_collection_init(tsk_table_collection_t *self, tsk_flags_t options)

/* Set default time_units value */
ret = tsk_table_collection_set_time_units(
self, TSK_DEFAULT_TIME_UNITS, strlen(TSK_DEFAULT_TIME_UNITS));
self, TSK_TIME_UNITS_UNKNOWN, strlen(TSK_TIME_UNITS_UNKNOWN));
if (ret != 0) {
goto out;
}
Expand Down
2 changes: 1 addition & 1 deletion python/CHANGELOG.rst
Expand Up @@ -56,7 +56,7 @@

- Add ``time_units`` to ``TreeSequence`` to describe the units of the time dimension of the
tree sequence. This is then used to generate an error if ``time_units`` is ``uncalibrated`` when
using the branch lengths in statistics. (:user:`benjeffery`, :issue:`1644`, :pr:`1760`)
using the branch lengths in statistics. (:user:`benjeffery`, :issue:`1644`, :pr:`1760`, :pr:`1832`)

- Add the ``virtual_root`` property to the Tree class (:user:`jeromekelleher`, :pr:`1704`).

Expand Down
4 changes: 4 additions & 0 deletions python/_tskitmodule.c
Expand Up @@ -11915,5 +11915,9 @@ PyInit__tskit(void)
PyModule_AddIntConstant(module, "FORWARD", TSK_DIR_FORWARD);
PyModule_AddIntConstant(module, "REVERSE", TSK_DIR_REVERSE);

PyModule_AddStringConstant(module, "TIME_UNITS_UNKNOWN", TSK_TIME_UNITS_UNKNOWN);
PyModule_AddStringConstant(
module, "TIME_UNITS_UNCALIBRATED", TSK_TIME_UNITS_UNCALIBRATED);

return module;
}
4 changes: 2 additions & 2 deletions python/lwt_interface/dict_encoding_testlib.py
Expand Up @@ -211,7 +211,7 @@ def test_missing_time_units(self, tables):
lwt = lwt_module.LightweightTableCollection()
lwt.fromdict(d)
tables = tskit.TableCollection.fromdict(lwt.asdict())
assert tables.time_units == "unknown"
assert tables.time_units == tskit.TIME_UNITS_UNKNOWN

def test_missing_metadata(self, tables):
assert tables.metadata != b""
Expand Down Expand Up @@ -603,7 +603,7 @@ def test_top_level_time_units(self, tables):
lwt.fromdict(d)
out = lwt.asdict()
tables = tskit.TableCollection.fromdict(out)
assert tables.time_units == "unknown"
assert tables.time_units == tskit.TIME_UNITS_UNKNOWN
# Missing is tested in TestMissingData above
d = tables.asdict()
# None should give default value
Expand Down
4 changes: 3 additions & 1 deletion python/tests/test_highlevel.py
Expand Up @@ -2402,14 +2402,16 @@ def test_tree_sequence_metadata(self):
def test_tree_sequence_time_units(self):
tc = tskit.TableCollection(1)
ts = tc.tree_sequence()
assert ts.time_units == "unknown"
assert ts.time_units == tskit.TIME_UNITS_UNKNOWN
tc.time_units = "something else"
ts = tc.tree_sequence()
assert ts.time_units == "something else"
with pytest.raises(AttributeError):
del ts.time_units
with pytest.raises(AttributeError):
ts.time_units = "readonly"
assert tskit.TIME_UNITS_UNKNOWN == "unknown"
assert tskit.TIME_UNITS_UNCALIBRATED == "uncalibrated"

def test_table_metadata_schemas(self):
ts = msprime.simulate(5)
Expand Down
9 changes: 7 additions & 2 deletions python/tests/test_lowlevel.py
Expand Up @@ -234,7 +234,7 @@ def test_set_time_units_errors(self):

def test_set_time_units(self):
tables = _tskit.TableCollection(1)
assert tables.time_units == "unknown"
assert tables.time_units == tskit.TIME_UNITS_UNKNOWN
for value in ["foo", "", "💩", "null char \0 in string"]:
tables.time_units = value
assert tables.time_units == value
Expand Down Expand Up @@ -1309,7 +1309,7 @@ def test_time_units(self):
tables.build_index()
ts = _tskit.TreeSequence()
ts.load_tables(tables)
assert ts.get_time_units() == "unknown"
assert ts.get_time_units() == tskit.TIME_UNITS_UNKNOWN
for value in ["foo", "", "💩", "null char \0 in string"]:
tables.time_units = value
ts = _tskit.TreeSequence()
Expand Down Expand Up @@ -3254,3 +3254,8 @@ def test_uninitialised():
method = getattr(uninitialised, method_name)
with pytest.raises((SystemError, ValueError)):
method()


def test_constants():
assert _tskit.TIME_UNITS_UNKNOWN == "unknown"
assert _tskit.TIME_UNITS_UNCALIBRATED == "uncalibrated"
2 changes: 1 addition & 1 deletion python/tests/test_tables.py
Expand Up @@ -4078,7 +4078,7 @@ def test_set_metadata(self):

def test_set_time_units(self):
tc = tskit.TableCollection(1)
assert tc.time_units == "unknown"
assert tc.time_units == tskit.TIME_UNITS_UNKNOWN

ex1 = "years"
ex2 = "generations"
Expand Down
4 changes: 2 additions & 2 deletions python/tests/test_tree_stats.py
Expand Up @@ -6084,7 +6084,7 @@ class TestTimeUncalibratedErrors:
def test_uncalibrated_time_allele_frequency_spectrum(self, ts_fixture):
ts_fixture.allele_frequency_spectrum(mode="branch")
tables = ts_fixture.dump_tables()
tables.time_units = "uncalibrated"
tables.time_units = tskit.TIME_UNITS_UNCALIBRATED
ts_uncalibrated = tables.tree_sequence()
ts_uncalibrated.allele_frequency_spectrum(mode="site")
with pytest.raises(
Expand All @@ -6100,7 +6100,7 @@ def test_uncalibrated_time_general_stat(self, ts_fixture):
W, lambda x: x * (x < ts_fixture.num_samples), W.shape[1], mode="branch"
)
tables = ts_fixture.dump_tables()
tables.time_units = "uncalibrated"
tables.time_units = tskit.TIME_UNITS_UNCALIBRATED
ts_uncalibrated = tables.tree_sequence()
ts_uncalibrated.general_stat(
W, lambda x: x * (x < ts_uncalibrated.num_samples), W.shape[1], mode="site"
Expand Down
6 changes: 6 additions & 0 deletions python/tskit/__init__.py
Expand Up @@ -50,6 +50,12 @@
#: NAN value, you cannot use `==` to test for it. Use :func:`is_unknown_time` instead.
UNKNOWN_TIME = _tskit.UNKNOWN_TIME

#: Default value of ts.time_units
TIME_UNITS_UNKNOWN = _tskit.TIME_UNITS_UNKNOWN

#: ts.time_units value when dimension is uncalibrated
TIME_UNITS_UNCALIBRATED = _tskit.TIME_UNITS_UNCALIBRATED

#: Options for printing to strings and HTML, modify with tskit.set_print_options.
_print_options = {"max_lines": 40}

Expand Down
3 changes: 2 additions & 1 deletion python/tskit/drawing.py
Expand Up @@ -38,6 +38,7 @@
import numpy as np
import svgwrite

import tskit
import tskit.util as util
from _tskit import NODE_IS_SAMPLE
from _tskit import NULL
Expand Down Expand Up @@ -551,7 +552,7 @@ def __init__(
y_label = "Node time"
else:
y_label = "Time"
if ts.time_units != "unknown":
if ts.time_units != tskit.TIME_UNITS_UNKNOWN:
y_label += f" ({ts.time_units})"
self.x_label = x_label
self.y_label = y_label
Expand Down
3 changes: 2 additions & 1 deletion python/tskit/trees.py
Expand Up @@ -41,6 +41,7 @@
import numpy as np

import _tskit
import tskit
import tskit.combinatorics as combinatorics
import tskit.drawing as drawing
import tskit.exceptions as exceptions
Expand Down Expand Up @@ -3153,7 +3154,7 @@ def parse_mutations(
if len(tokens) >= 3:
site = int(tokens[site_index])
node = int(tokens[node_index])
if time_index is None or tokens[time_index] == "unknown":
if time_index is None or tokens[time_index] == tskit.TIME_UNITS_UNKNOWN:
time = UNKNOWN_TIME
else:
time = float(tokens[time_index])
Expand Down