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
3 changes: 3 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## 0.2.7

### Bug Fixes
- Fix a regression introduced in 0.2.6 where `is_monotonic` was significantly degrading `.sel` performance.

### Documentation
- Achieved **100% docstring coverage** (excluding `__magic__` and private `_methods`) (@atrabattoni).
- Improved *User Guide* index (@atrabattoni).
Expand Down
11 changes: 11 additions & 0 deletions tests/coordinates/test_dense.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,14 @@ def test_from_block(self):
coord = DenseCoordinate.from_block(0, 5, 1, dim="x")
expected = DenseCoordinate([0, 1, 2, 3, 4], dim="x")
assert coord.equals(expected)

def test_is_monotonic_increasing(self):
assert DenseCoordinate([1, 2, 3]).is_monotonic_increasing()
assert not DenseCoordinate([1, 3, 2]).is_monotonic_increasing()
t0 = np.datetime64("2000-01-01T00:00:00")
times = np.array([t0, t0 + np.timedelta64(1, "s"), t0 + np.timedelta64(2, "s")])
assert DenseCoordinate(times).is_monotonic_increasing()
times_bad = np.array(
[t0, t0 + np.timedelta64(2, "s"), t0 + np.timedelta64(1, "s")]
)
assert not DenseCoordinate(times_bad).is_monotonic_increasing()
22 changes: 22 additions & 0 deletions tests/coordinates/test_interp.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,3 +444,25 @@ def test_get_split_indices_overlaps_with_tolerance(self):
result = coord.get_split_indices(kind="overlaps", tolerance=0.5)
assert isinstance(result, np.ndarray)
np.testing.assert_array_equal(result, [5], strict=True)

def test_is_monotonic_increasing_true(self):
coord = InterpCoordinate(
{"tie_indices": [0, 4, 5, 9], "tie_values": [0.0, 4.0, 5.0, 9.0]}
)
assert coord.is_monotonic_increasing() is True

def test_is_monotonic_increasing_false(self):
coord = InterpCoordinate(
{"tie_indices": [0, 4, 5, 9], "tie_values": [0.0, 4.0, 3.0, 7.0]}
)
assert coord.is_monotonic_increasing() is False

def test_is_monotonic_increasing_multi_segment(self):
# Three segments all strictly increasing — must not raise ValueError from bool()
coord = InterpCoordinate(
{
"tie_indices": [0, 4, 5, 9, 10, 14],
"tie_values": [0.0, 4.0, 5.0, 9.0, 10.0, 14.0],
}
)
assert coord.is_monotonic_increasing() is True
23 changes: 23 additions & 0 deletions tests/coordinates/test_sampled.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,3 +984,26 @@ def test_get_split_indices_overlaps_with_tolerance(self):
result = coord.get_split_indices(kind="overlaps", tolerance=1.0)
assert isinstance(result, np.ndarray)
np.testing.assert_array_equal(result, [5], strict=True)

def test_is_monotonic_increasing_true(self):
coord = SampledCoordinate(
{"tie_values": [0.0, 5.0], "tie_lengths": [5, 5], "sampling_interval": 1.0}
)
assert coord.is_monotonic_increasing() is True

def test_is_monotonic_increasing_false(self):
coord = SampledCoordinate(
{"tie_values": [0.0, 2.0], "tie_lengths": [5, 5], "sampling_interval": 1.0}
)
assert coord.is_monotonic_increasing() is False

def test_is_monotonic_increasing_multi_segment(self):
# Three segments all increasing — must not raise ValueError from bool()
coord = SampledCoordinate(
{
"tie_values": [0.0, 5.0, 11.0],
"tie_lengths": [5, 5, 5],
"sampling_interval": 1.0,
}
)
assert coord.is_monotonic_increasing() is True
4 changes: 4 additions & 0 deletions xdas/coordinates/interp.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ def get_sampling_interval(self, cast=True):
delta = delta / np.timedelta64(1, "s")
return delta

def is_monotonic_increasing(self):
"""Return ``True`` if no segment boundary exhibits a backward jump."""
return not self.get_split_indices("overlaps", tolerance=False).size

def equals(self, other):
"""Return ``True`` if *other* has identical tie points, dim, and dtype."""
return (
Expand Down
4 changes: 4 additions & 0 deletions xdas/coordinates/sampled.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@ def get_sampling_interval(self, cast=True):
delta = delta / np.timedelta64(1, "s")
return delta

def is_monotonic_increasing(self):
"""Return ``True`` if no segment starts below the end of the previous one."""
return not self.get_split_indices("overlaps", tolerance=False).size

def equals(self, other):
"""Return ``True`` if *other* has identical tie values, lengths, sampling interval, dim, and dtype."""
return (
Expand Down
Loading