Skip to content

Commit 8e23c8c

Browse files
ojasvatsyayangithub-actionspollytur
authored
Standardize empty-query behavior across interpolators (sensorium-competition#145)
* Standardize empty-query behavior across interpolators * Fix duplicate warning and finalize dtype consistency --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Polina Turishcheva <49938348+pollytur@users.noreply.github.com>
1 parent 805e3a5 commit 8e23c8c

2 files changed

Lines changed: 39 additions & 17 deletions

File tree

experanto/interpolators.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,14 @@ def interpolate(
279279

280280
if len(valid_times) == 0:
281281
warnings.warn(
282-
"Sequence interpolation returns empty array, no valid times queried",
282+
"Interpolation returns empty array, no valid times queried.",
283283
UserWarning,
284284
stacklevel=2,
285285
)
286286
return (
287-
(np.empty((0, self._data.shape[1])), valid)
287+
(np.empty((0, self._data.shape[1]), dtype=self._data.dtype), valid)
288288
if return_valid
289-
else np.empty((0, self._data.shape[1]))
289+
else np.empty((0, self._data.shape[1]), dtype=self._data.dtype)
290290
)
291291

292292
idx_lower = np.floor((valid_times - self.start_time) / self.time_delta).astype(
@@ -345,6 +345,12 @@ def interpolate(
345345

346346
def close(self) -> None:
347347
super().close()
348+
349+
if hasattr(self, "_data") and isinstance(self._data, np.memmap):
350+
mmap_obj = getattr(self._data, "_mmap", None)
351+
if mmap_obj is not None:
352+
mmap_obj.close()
353+
348354
del self._data
349355

350356

@@ -406,14 +412,14 @@ def interpolate(
406412

407413
if len(valid_times) == 0:
408414
warnings.warn(
409-
"Sequence interpolation returns empty array, no valid times queried",
415+
"Interpolation returns empty array, no valid times queried.",
410416
UserWarning,
411417
stacklevel=2,
412418
)
413419
return (
414-
(np.empty((0, self._data.shape[1])), valid)
420+
(np.empty((0, self._data.shape[1]), dtype=self._data.dtype), valid)
415421
if return_valid
416-
else np.empty((0, self._data.shape[1]))
422+
else np.empty((0, self._data.shape[1]), dtype=self._data.dtype)
417423
)
418424

419425
idx_lower = np.floor(
@@ -469,7 +475,6 @@ def interpolate(
469475
np.copyto(interpolated, neuron_means, where=np.isnan(interpolated))
470476

471477
return (interpolated, valid) if return_valid else interpolated
472-
473478
else:
474479
raise NotImplementedError(
475480
"interpolation_mode should be linear or nearest_neighbor"
@@ -532,7 +537,7 @@ def __init__(
532537
self.end_time = self.timestamps[-1]
533538
self.valid_interval = TimeInterval(self.start_time, self.end_time)
534539
self.rescale = rescale
535-
self.cache_trials = cache_data # Store the cache preference
540+
self.cache_data = cache_data # Store the cache preference
536541
self.use_stimuli_names = use_stimuli_names
537542
self._parse_trials()
538543

@@ -627,9 +632,7 @@ def _parse_trials(self) -> None:
627632
else:
628633
data_file_name = self.root_folder / "data" / f"{key}.npy"
629634
self.trials.append(
630-
ScreenTrial.create(
631-
data_file_name, metadata, cache_data=self.cache_trials
632-
)
635+
ScreenTrial.create(data_file_name, metadata, cache_data=self.cache_data)
633636
)
634637

635638
def interpolate(
@@ -691,6 +694,20 @@ def rescale_frame(self, frame: np.ndarray) -> np.ndarray:
691694
np.float32
692695
)
693696

697+
def close(self) -> None:
698+
super().close()
699+
700+
if hasattr(self, "trials"):
701+
for trial in self.trials:
702+
if hasattr(trial, "_cached_data") and isinstance(
703+
trial._cached_data, np.memmap
704+
):
705+
mmap_obj = getattr(trial._cached_data, "_mmap", None)
706+
if mmap_obj is not None:
707+
mmap_obj.close()
708+
del trial._cached_data
709+
del self.trials
710+
694711

695712
class TimeIntervalInterpolator(Interpolator):
696713
"""Interpolator for labeled time intervals.
@@ -762,7 +779,7 @@ def interpolate(
762779

763780
if n_times == 0:
764781
warnings.warn(
765-
"TimeIntervalInterpolator returns an empty array, no valid times queried.",
782+
"Interpolation returns empty array, no valid times queried.",
766783
UserWarning,
767784
stacklevel=2,
768785
)
@@ -1092,10 +1109,15 @@ def interpolate(
10921109

10931110
# Handle edge case where no times are valid
10941111
if len(valid_times) == 0:
1112+
warnings.warn(
1113+
"Interpolation returns empty array, no valid times queried.",
1114+
UserWarning,
1115+
stacklevel=2,
1116+
)
10951117
return (
1096-
(np.empty((0, self.n_signals)), valid)
1118+
(np.empty((0, self.n_signals), dtype=np.float64), valid)
10971119
if return_valid
1098-
else np.empty((0, self.n_signals))
1120+
else np.empty((0, self.n_signals), dtype=np.float64)
10991121
)
11001122

11011123
# 2. Prepare boundaries

tests/test_sequence_interpolator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ def test_linear_interpolation_with_phase_shifts(
331331

332332

333333
@pytest.mark.filterwarnings(
334-
"ignore:Sequence interpolation returns empty array, no valid times queried:UserWarning"
334+
"ignore:Interpolation returns empty array, no valid times queried.:UserWarning"
335335
)
336336
@pytest.mark.parametrize("interpolation_mode", ["nearest_neighbor", "linear"])
337337
@pytest.mark.parametrize("end_time", [0.05, 1.0, 5.0, 12.0])
@@ -370,7 +370,7 @@ def test_interpolation_for_invalid_times(interpolation_mode, end_time, keep_nans
370370

371371

372372
@pytest.mark.filterwarnings(
373-
"ignore:Sequence interpolation returns empty array, no valid times queried:UserWarning"
373+
"ignore:Interpolation returns empty array, no valid times queried.:UserWarning"
374374
)
375375
@pytest.mark.parametrize("interpolation_mode", ["nearest_neighbor", "linear"])
376376
@pytest.mark.parametrize("end_time", [0.05, 1.0, 5.0, 12.0])
@@ -429,7 +429,7 @@ def test_interpolation_for_empty_times(interpolation_mode, phase_shifts):
429429

430430
with pytest.warns(
431431
UserWarning,
432-
match="Sequence interpolation returns empty array, no valid times queried",
432+
match="Interpolation returns empty array, no valid times queried.",
433433
):
434434
interp, valid = seq_interp.interpolate(
435435
times=np.array([]), return_valid=True

0 commit comments

Comments
 (0)