diff --git a/python/CHANGELOG.rst b/python/CHANGELOG.rst index a6f5986e62..2fb1eb9459 100644 --- a/python/CHANGELOG.rst +++ b/python/CHANGELOG.rst @@ -19,6 +19,11 @@ and a window breakpoint falls within an internal missing interval. (:user:`nspope`, :pr:`3176`, :issue:`3175`) +**Breaking changes** + +- ``ltrim``, ``rtrim``, ``trim`` and ``shift`` raise an error if used on a tree sequence + containing a reference sequence (:user:`hyanwong`, :pr:`3210`, :issue:`2091`) + -------------------- [0.6.4] - 2025-05-21 -------------------- diff --git a/python/tests/test_topology.py b/python/tests/test_topology.py index b2eb4ea6a7..89d72d31fe 100644 --- a/python/tests/test_topology.py +++ b/python/tests/test_topology.py @@ -7074,6 +7074,18 @@ def test_failure_with_migrations(self): with pytest.raises(ValueError): ts.trim() + def test_reference_sequence(self): + # Test that we fail if there is a reference sequence + tables = tskit.TableCollection(3.0) + tables.reference_sequence.data = "ABC" + ts = tables.tree_sequence() + with pytest.raises(ValueError, match="reference sequence"): + ts.ltrim() + with pytest.raises(ValueError, match="reference sequence"): + ts.rtrim() + with pytest.raises(ValueError, match="reference sequence"): + ts.trim() + class TestShift: """ @@ -7140,6 +7152,14 @@ def test_bad_seq_len(self): ): ts.shift(1, sequence_length=1) + def test_reference_sequence(self): + # Test that we fail if there is a reference sequence + tables = tskit.TableCollection(3.0) + tables.reference_sequence.data = "ABC" + ts = tables.tree_sequence() + with pytest.raises(ValueError, match="reference sequence"): + ts.shift(1) + class TestConcatenate: def test_simple(self): diff --git a/python/tskit/tables.py b/python/tskit/tables.py index bc078164c0..0ba33061fe 100644 --- a/python/tskit/tables.py +++ b/python/tskit/tables.py @@ -3887,6 +3887,11 @@ def keep_intervals(self, intervals, simplify=True, record_provenance=True): ) def _check_trim_conditions(self): + if self.has_reference_sequence(): + raise ValueError( + "Cannot trim if there is a reference sequence. Please remove the " + "reference sequence by calling `.reference_sequence.clear()` first." + ) if self.migrations.num_rows > 0: if (np.min(self.migrations.left) < np.min(self.edges.left)) and ( np.max(self.migrations.right) > np.max(self.edges.right) @@ -4005,6 +4010,11 @@ def shift(self, value, *, sequence_length=None, record_provenance=True): :param sequence_length: The new sequence length of the tree sequence. If ``None`` (default) add `value` to the sequence length. """ + if self.has_reference_sequence(): + raise ValueError( + "Cannot shift if there is a reference sequence. Please remove the " + "reference sequence by calling `.reference_sequence.clear()` first." + ) self.drop_index() self.edges.left += value self.edges.right += value