Skip to content

Commit

Permalink
Possible fix for linspace chunks exceeding step_max
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanconn committed Nov 6, 2024
1 parent 5dcb3e7 commit 8f4e313
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
10 changes: 9 additions & 1 deletion cxotime/cxotime.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def linspace(
num : int | None
Number of time bins.
step_max : u.Quantity (timelike)
Maximum time interval step.. Should be positive nonzero.
Maximum time interval step. Should be positive nonzero.
Returns
-------
Expand All @@ -225,6 +225,14 @@ def linspace(

times = np.linspace(start, stop, num + 1)

if step_max is not None:
# confirm that all the time deltas are less than or equal to step_max
deltas_lt = [t <= step_max for t in np.diff(times)]
if np.any(deltas_lt):
# increase num and try again
num += 1
times = np.linspace(start, stop, num + 1)

return times

@classmethod
Expand Down
53 changes: 52 additions & 1 deletion cxotime/tests/test_cxotime_linspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ def run_linspace_step_test(start, stop, dt_max, expected_len, expected_values):
dt_max, abs(CxoTime(stop) - CxoTime(start))
)

# Confirm that all the intervals are the same duration
# Confirm that all the intervals are the basically the same duration
interval1 = result[1] - result[0]
assert all(np.isclose((result[1:] - result[:-1]).sec, interval1.sec))

# And that they are all less than or equal to dt_max
assert all((result[1:] - result[:-1]) <= dt_max)

# Confirm that the time range is covered
assert result[0] == start
assert result[-1] == stop
Expand All @@ -28,6 +31,54 @@ def run_linspace_step_test(start, stop, dt_max, expected_len, expected_values):
assert np.allclose(CxoTime(result).secs, CxoTime(expected_values).secs)


def test_linspace_step_bug():
"""Test that the steps are equal to or less than the maximum step for one case
described in https://github.com/sot/cxotime/issues/45 . For this case, the
maximum step is 1 minute and the range is 30 minutes. One would expect 30
intervals, but due to tiny numeric issues with np.linspace, we need an extra
interval to avoid having any intervals just over the step_max."""
run_linspace_step_test(
"2023:001:00:00:01.000",
"2023:001:00:30:01.000",
1 * u.min,
32,
[
"2023:001:00:00:01.000",
"2023:001:00:00:59.065",
"2023:001:00:01:57.129",
"2023:001:00:02:55.194",
"2023:001:00:03:53.258",
"2023:001:00:04:51.323",
"2023:001:00:05:49.387",
"2023:001:00:06:47.452",
"2023:001:00:07:45.516",
"2023:001:00:08:43.581",
"2023:001:00:09:41.645",
"2023:001:00:10:39.710",
"2023:001:00:11:37.774",
"2023:001:00:12:35.839",
"2023:001:00:13:33.903",
"2023:001:00:14:31.968",
"2023:001:00:15:30.032",
"2023:001:00:16:28.097",
"2023:001:00:17:26.161",
"2023:001:00:18:24.226",
"2023:001:00:19:22.290",
"2023:001:00:20:20.355",
"2023:001:00:21:18.419",
"2023:001:00:22:16.484",
"2023:001:00:23:14.548",
"2023:001:00:24:12.613",
"2023:001:00:25:10.677",
"2023:001:00:26:08.742",
"2023:001:00:27:06.806",
"2023:001:00:28:04.871",
"2023:001:00:29:02.935",
"2023:001:00:30:01.000",
],
)


def test_linspace_step_with_zero_range():
"""Test that the result is correct when start==stop."""
run_linspace_step_test(
Expand Down

0 comments on commit 8f4e313

Please sign in to comment.