From e5e011cdde4bb4650390587f9c51b5ad3e6ee25f Mon Sep 17 00:00:00 2001 From: SophiaPerzan-DG Date: Tue, 6 Oct 2026 11:49:30 -0400 Subject: [PATCH 1/2] fix: IntervalData write fails with single-length Interval-like objects --- genome_kit/interval_data.py | 2 +- tests/test_interval_data.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/genome_kit/interval_data.py b/genome_kit/interval_data.py index 607415ae..5dddc9c4 100644 --- a/genome_kit/interval_data.py +++ b/genome_kit/interval_data.py @@ -435,7 +435,7 @@ def _concat_pieces(self, intervals: list[Interval]): """Fetch and concatenate the data slices for ``intervals`` (in order) along the aligned axis. """ - pieces = [self._get_interval_like(iv).data for iv in intervals] + pieces = [self._get_interval_like(iv)._data for iv in intervals] return pieces[0] if len(pieces) == 1 else np.concatenate(pieces, axis=self._axis) # The forms a value assigned via an interval-like key may take. See diff --git a/tests/test_interval_data.py b/tests/test_interval_data.py index 41aec87c..c10bba51 100644 --- a/tests/test_interval_data.py +++ b/tests/test_interval_data.py @@ -155,6 +155,36 @@ def test_set_dis(self): interval_data[0] = -interval_data[0] np.testing.assert_equal(-data[0], interval_data[0]) + def test_data_read_only_does_not_affect_backing_array(self): + position = Interval('chr1', '+', 100, 100, self.genome) + interval = position.expand(0, 3) + data = np.arange(0, 30).reshape(3, 10) + interval_data = IntervalData(interval, data) + + view = interval_data.data + self.assertFalse(view.flags.writeable) + with self.assertRaises(ValueError): + view[0, 0] = 1 + + self.assertTrue(data.flags.writeable) + interval_data[0] = -interval_data[0] + np.testing.assert_equal(-np.arange(0, 10), interval_data[0]) + + def test_set_after_single_piece_concat(self): + base = Interval('chr1', '+', 100, 106, self.genome) + piece = Interval('chr1', '+', 101, 103, self.genome) + keys = { + 'list': [piece], + 'dis': DisjointIntervalSequence.from_intervals([piece]), + } + for name, key in keys.items(): + with self.subTest(name): + interval_data = IntervalData(base, np.zeros((6, 4), dtype=int)) + sub = interval_data[key] + sub[0] = 1 + np.testing.assert_equal(np.ones(4), sub[0]) + np.testing.assert_equal(np.ones(4), interval_data[1]) + class TestIntervalDataSliceIndex(unittest.TestCase): rank = 3 From 96dd15677b872329cc5e3094dcb93e258c7aaf14 Mon Sep 17 00:00:00 2001 From: SophiaPerzan-DG Date: Mon, 19 Oct 2026 12:35:21 -0400 Subject: [PATCH 2/2] chore: update data property typing --- genome_kit/interval_data.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/genome_kit/interval_data.py b/genome_kit/interval_data.py index 5dddc9c4..6ab5e439 100644 --- a/genome_kit/interval_data.py +++ b/genome_kit/interval_data.py @@ -161,8 +161,8 @@ def interval(self) -> IntervalLike: return self._interval @property - def data(self): - """Return the backing data array.""" + def data(self) -> np.ndarray: + """Return the backing data array as read-only.""" if isinstance(self._data, np.ndarray): read_only_view = self._data.view() read_only_view.flags.writeable = False