Skip to content

Commit 3083011

Browse files
authored
Remove deprecated stub_frames parameter from ophys interfaces (#1676)
1 parent e430a67 commit 3083011

File tree

13 files changed

+210
-169
lines changed

13 files changed

+210
-169
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# v0.9.4 (Upcoming)
22

33
## Removals, Deprecations and Changes
4+
* Removed the deprecated `stub_frames` parameter from ophys interfaces (`BaseImagingExtractorInterface`, `BaseSegmentationExtractorInterface`, `BrukerTiffMultiPlaneConverter`, `BrukerTiffSinglePlaneConverter`, `MiniscopeConverter`, `Suite2pSegmentationInterface`, `MinianSegmentationInterface`, `MiniscopeImagingDataInterface`). Use `stub_samples` instead. [PR #1676](https://github.com/catalystneuro/neuroconv/pull/1676)
45
* Removed deprecated wrapper functions from `roiextractors_pending_deprecation.py` (March 2026 deadline): `add_imaging_plane_to_nwbfile`, `add_image_segmentation_to_nwbfile`, `add_photon_series_to_nwbfile`, `add_plane_segmentation_to_nwbfile`, `add_background_plane_segmentation_to_nwbfile`, `add_background_fluorescence_traces_to_nwbfile`, `add_summary_images_to_nwbfile`. [PR #1680](https://github.com/catalystneuro/neuroconv/pull/1680)
56
* Added `*args` positional argument deprecation to `add_imaging_to_nwbfile` to enforce keyword-only arguments. Will be enforced on or after September 2026. [PR #1680](https://github.com/catalystneuro/neuroconv/pull/1680)
67
* Added `*args` positional argument deprecation to `add_segmentation_to_nwbfile` to enforce keyword-only arguments. Will be enforced on or after September 2026. [PR #1687](https://github.com/catalystneuro/neuroconv/pull/1687)
@@ -15,6 +16,7 @@
1516
* Added dict-based metadata pipeline for imaging in `roiextractors.py`, supporting the new `MicroscopySeries`, `ImagingPlanes`, and `Devices` metadata format keyed by `metadata_key`. Old list-based functions are preserved (renamed with `_old_list_format` suffix) and dispatched automatically when `metadata_key` is not provided. [PR #1677](https://github.com/catalystneuro/neuroconv/pull/1677)
1617

1718
## Improvements
19+
* Added array-like protocol methods (`shape`, `ndim`, `__len__`, `__getitem__`) to all data chunk iterators (`SliceableDataChunkIterator`, `SpikeInterfaceRecordingDataChunkIterator`, `ImagingExtractorDataChunkIterator`, `VideoDataChunkIterator`). [PR #1673](https://github.com/catalystneuro/neuroconv/pull/1673)
1820
* Added tests for `OnePhotonSeries`, `processing/ophys` container, and non-iterative write to `TestAddImaging` (dict-based metadata pipeline). [PR #1685](https://github.com/catalystneuro/neuroconv/pull/1685)
1921
* Added column-first fast path for writing Units tables when the table is new (no append/merge). Uses `id.extend()` + `add_column()` instead of per-row `add_unit()` calls, reducing Python overhead for large sortings. [PR #1669](https://github.com/catalystneuro/neuroconv/pull/1669)
2022

src/neuroconv/datainterfaces/behavior/video/video_utils.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ def _get_scaled_buffer_shape(self, buffer_gb: float, chunk_shape: tuple) -> tupl
307307
assert all(np.array(chunk_shape) > 0), f"Some dimensions of chunk_shape ({chunk_shape}) are less than zero!"
308308

309309
sample_shape = self._sample_shape
310-
series_shape = self._get_maxshape()
310+
series_shape = self.shape
311311
dtype = self._get_dtype()
312312

313313
buffer_shape = get_image_series_buffer_shape(
@@ -320,11 +320,51 @@ def _get_scaled_buffer_shape(self, buffer_gb: float, chunk_shape: tuple) -> tupl
320320

321321
return buffer_shape
322322

323+
@property
324+
def shape(self):
325+
"""Return (num_frames, height, width, channels) for this video."""
326+
return (self._num_samples, *self._sample_shape)
327+
328+
@property
329+
def ndim(self):
330+
"""Return the number of dimensions (always 4: frames x height x width x channels)."""
331+
return len(self.shape)
332+
333+
def __len__(self):
334+
"""Return the number of frames in this video."""
335+
return self._num_samples
336+
337+
def __getitem__(self, selection):
338+
"""Enable array-like slicing with random frame access for video data.
339+
340+
Unlike _get_data (which reads frames sequentially from the current cursor
341+
position), this method seeks to the correct frame position first, reads the
342+
requested range, and applies spatial slicing on the result.
343+
344+
Note that this mutates the video capture position, so concurrent access
345+
from multiple threads is not safe.
346+
"""
347+
resolved = self._convert_index_to_slices(selection)
348+
349+
# Seek to the correct frame position before reading
350+
start_frame = resolved[0].start
351+
end_frame = resolved[0].stop
352+
self.video_capture_ob.current_frame = start_frame
353+
354+
num_frames = end_frame - start_frame
355+
frames = np.empty(shape=(num_frames, *self.shape[1:]), dtype=self._dtype)
356+
for frame_index in range(num_frames):
357+
frames[frame_index] = next(self.video_capture_ob)
358+
359+
# Apply spatial slicing (height, width, channels)
360+
spatial_selection = (slice(0, num_frames),) + resolved[1:]
361+
return frames[spatial_selection]
362+
323363
def _get_data(self, selection: tuple[slice]) -> np.ndarray:
324364
start_frame = selection[0].start
325365
end_frame = selection[0].stop
326366

327-
shape = (end_frame - start_frame, *self._maxshape[1:])
367+
shape = (end_frame - start_frame, *self.shape[1:])
328368
frames = np.empty(shape=shape, dtype=self._dtype)
329369
for frame_number in range(end_frame - start_frame):
330370
frames[frame_number] = next(self.video_capture_ob)
@@ -334,4 +374,4 @@ def _get_dtype(self) -> np.dtype:
334374
return self._dtype
335375

336376
def _get_maxshape(self) -> tuple[int, int, int, int]:
337-
return (self._num_samples, *self._sample_shape)
377+
return self.shape

src/neuroconv/datainterfaces/ophys/baseimagingextractorinterface.py

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ def add_to_nwbfile(
174174
photon_series_index: int = 0,
175175
parent_container: Literal["acquisition", "processing/ophys"] = "acquisition",
176176
stub_test: bool = False,
177-
stub_frames: int | None = None,
178177
always_write_timestamps: bool = False,
179178
iterator_type: str | None = "v2",
180179
iterator_options: dict | None = None,
@@ -198,9 +197,6 @@ def add_to_nwbfile(
198197
under the "processing/ophys" module, by default "acquisition".
199198
stub_test : bool, optional
200199
If True, only writes a small subset of frames for testing purposes, by default False.
201-
stub_frames : int, optional
202-
.. deprecated:: February 2026
203-
Use `stub_samples` instead.
204200
always_write_timestamps : bool, optional
205201
Whether to always write timestamps, by default False.
206202
iterator_type : {"v2", None}, default: "v2"
@@ -217,7 +213,7 @@ def add_to_nwbfile(
217213
via ``get_default_backend_configuration()`` and ``configure_backend()`` after calling
218214
this method. See the backend configuration documentation for details.
219215
stub_samples : int, default: 100
220-
The number of samples (frames) to use for testing. When provided, takes precedence over `stub_frames`.
216+
The number of samples (frames) to use for testing.
221217
"""
222218

223219
from ...tools.roiextractors import add_imaging_to_nwbfile
@@ -229,7 +225,6 @@ def add_to_nwbfile(
229225
"photon_series_index",
230226
"parent_container",
231227
"stub_test",
232-
"stub_frames",
233228
"always_write_timestamps",
234229
"iterator_type",
235230
"iterator_options",
@@ -256,30 +251,14 @@ def add_to_nwbfile(
256251
photon_series_index = positional_values.get("photon_series_index", photon_series_index)
257252
parent_container = positional_values.get("parent_container", parent_container)
258253
stub_test = positional_values.get("stub_test", stub_test)
259-
stub_frames = positional_values.get("stub_frames", stub_frames)
260254
always_write_timestamps = positional_values.get("always_write_timestamps", always_write_timestamps)
261255
iterator_type = positional_values.get("iterator_type", iterator_type)
262256
iterator_options = positional_values.get("iterator_options", iterator_options)
263257
stub_samples = positional_values.get("stub_samples", stub_samples)
264258

265-
# Handle deprecation of stub_frames in favor of stub_samples
266-
if stub_frames is not None and stub_samples != 100:
267-
raise ValueError("Cannot specify both 'stub_frames' and 'stub_samples'. Use 'stub_samples' only.")
268-
269-
if stub_frames is not None:
270-
warnings.warn(
271-
"The 'stub_frames' parameter is deprecated and will be removed on or after February 2026. "
272-
"Use 'stub_samples' instead.",
273-
FutureWarning,
274-
stacklevel=2,
275-
)
276-
effective_stub_samples = stub_frames
277-
else:
278-
effective_stub_samples = stub_samples
279-
280259
if stub_test:
281-
effective_stub_samples = min([effective_stub_samples, self.imaging_extractor.get_num_samples()])
282-
imaging_extractor = self.imaging_extractor.slice_samples(start_sample=0, end_sample=effective_stub_samples)
260+
stub_samples = min([stub_samples, self.imaging_extractor.get_num_samples()])
261+
imaging_extractor = self.imaging_extractor.slice_samples(start_sample=0, end_sample=stub_samples)
283262
else:
284263
imaging_extractor = self.imaging_extractor
285264

src/neuroconv/datainterfaces/ophys/basesegmentationextractorinterface.py

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ def add_to_nwbfile(
155155
metadata: dict | None = None,
156156
*args, # TODO: change to * (keyword only) on or after August 2026
157157
stub_test: bool = False,
158-
stub_frames: int | None = None,
159158
include_background_segmentation: bool = False,
160159
include_roi_centroids: bool = True,
161160
include_roi_acceptance: bool = True,
@@ -175,9 +174,6 @@ def add_to_nwbfile(
175174
metadata : dict, optional
176175
The metadata for the interface
177176
stub_test : bool, default: False
178-
stub_frames : int, optional
179-
.. deprecated:: February 2026
180-
Use `stub_samples` instead.
181177
include_background_segmentation : bool, default: False
182178
Whether to include the background plane segmentation and fluorescence traces in the NWB file. If False,
183179
neuropil traces are included in the main plane segmentation rather than the background plane segmentation.
@@ -210,7 +206,7 @@ def add_to_nwbfile(
210206
via ``get_default_backend_configuration()`` and ``configure_backend()`` after calling
211207
this method. See the backend configuration documentation for details.
212208
stub_samples : int, default: 100
213-
The number of samples (frames) to use for testing. When provided, takes precedence over `stub_frames`.
209+
The number of samples (frames) to use for testing.
214210
roi_ids_to_add : list of str or int, optional
215211
The ROI IDs to include in the NWB file. If ``None`` (default), all ROIs are included.
216212
Use this to filter out rejected or unwanted ROIs and reduce file size.
@@ -228,7 +224,6 @@ def add_to_nwbfile(
228224
if args:
229225
parameter_names = [
230226
"stub_test",
231-
"stub_frames",
232227
"include_background_segmentation",
233228
"include_roi_centroids",
234229
"include_roi_acceptance",
@@ -256,7 +251,6 @@ def add_to_nwbfile(
256251
stacklevel=2,
257252
)
258253
stub_test = positional_values.get("stub_test", stub_test)
259-
stub_frames = positional_values.get("stub_frames", stub_frames)
260254
include_background_segmentation = positional_values.get(
261255
"include_background_segmentation", include_background_segmentation
262256
)
@@ -268,31 +262,14 @@ def add_to_nwbfile(
268262
stub_samples = positional_values.get("stub_samples", stub_samples)
269263
roi_ids_to_add = positional_values.get("roi_ids_to_add", roi_ids_to_add)
270264

271-
# Handle deprecation of stub_frames in favor of stub_samples
272-
if stub_frames is not None and stub_samples != 100:
273-
raise ValueError("Cannot specify both 'stub_frames' and 'stub_samples'. Use 'stub_samples' only.")
274-
275-
if stub_frames is not None:
276-
warnings.warn(
277-
"The 'stub_frames' parameter is deprecated and will be removed on or after February 2026. "
278-
"Use 'stub_samples' instead.",
279-
FutureWarning,
280-
stacklevel=2,
281-
)
282-
effective_stub_samples = stub_frames
283-
else:
284-
effective_stub_samples = stub_samples
285-
286265
segmentation_extractor = self.segmentation_extractor
287266

288267
if roi_ids_to_add is not None:
289268
segmentation_extractor = segmentation_extractor.select_rois(roi_ids=roi_ids_to_add)
290269

291270
if stub_test:
292-
effective_stub_samples = min([effective_stub_samples, segmentation_extractor.get_num_samples()])
293-
segmentation_extractor = segmentation_extractor.slice_samples(
294-
start_sample=0, end_sample=effective_stub_samples
295-
)
271+
stub_samples = min([stub_samples, segmentation_extractor.get_num_samples()])
272+
segmentation_extractor = segmentation_extractor.slice_samples(start_sample=0, end_sample=stub_samples)
296273

297274
metadata = metadata or self.get_metadata()
298275

src/neuroconv/datainterfaces/ophys/brukertiff/brukertiffconverter.py

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import warnings
21
from typing import Literal
32

43
from pydantic import DirectoryPath, validate_call
@@ -88,7 +87,6 @@ def add_to_nwbfile(
8887
nwbfile: NWBFile,
8988
metadata,
9089
stub_test: bool = False,
91-
stub_frames: int | None = None,
9290
stub_samples: int = 100,
9391
):
9492
"""
@@ -102,34 +100,16 @@ def add_to_nwbfile(
102100
Metadata dictionary containing information to describe the data being added to the NWB file.
103101
stub_test : bool, optional
104102
If True, only a subset of the data (up to `stub_samples`) will be added for testing purposes. Default is False.
105-
stub_frames : int, optional
106-
.. deprecated:: February 2026
107-
Use `stub_samples` instead.
108103
stub_samples : int, default: 100
109-
The number of samples (frames) to use for testing. When provided, takes precedence over `stub_frames`.
104+
The number of samples (frames) to use for testing.
110105
"""
111-
# Handle deprecation of stub_frames in favor of stub_samples
112-
if stub_frames is not None and stub_samples != 100:
113-
raise ValueError("Cannot specify both 'stub_frames' and 'stub_samples'. Use 'stub_samples' only.")
114-
115-
if stub_frames is not None:
116-
warnings.warn(
117-
"The 'stub_frames' parameter is deprecated and will be removed on or after February 2026. "
118-
"Use 'stub_samples' instead.",
119-
FutureWarning,
120-
stacklevel=2,
121-
)
122-
effective_stub_samples = stub_frames
123-
else:
124-
effective_stub_samples = stub_samples
125-
126106
for photon_series_index, (interface_name, data_interface) in enumerate(self.data_interface_objects.items()):
127107
data_interface.add_to_nwbfile(
128108
nwbfile=nwbfile,
129109
metadata=metadata,
130110
photon_series_index=photon_series_index,
131111
stub_test=stub_test,
132-
stub_samples=effective_stub_samples,
112+
stub_samples=stub_samples,
133113
)
134114

135115

@@ -196,7 +176,6 @@ def add_to_nwbfile(
196176
nwbfile: NWBFile,
197177
metadata,
198178
stub_test: bool = False,
199-
stub_frames: int | None = None,
200179
stub_samples: int = 100,
201180
):
202181
"""
@@ -211,32 +190,14 @@ def add_to_nwbfile(
211190
stub_test : bool, optional
212191
If True, only a subset of the data (defined by `stub_samples`) will be added for testing purposes,
213192
by default False.
214-
stub_frames : int, optional
215-
.. deprecated:: February 2026
216-
Use `stub_samples` instead.
217193
stub_samples : int, default: 100
218-
The number of samples (frames) to use for testing. When provided, takes precedence over `stub_frames`.
194+
The number of samples (frames) to use for testing.
219195
"""
220-
# Handle deprecation of stub_frames in favor of stub_samples
221-
if stub_frames is not None and stub_samples != 100:
222-
raise ValueError("Cannot specify both 'stub_frames' and 'stub_samples'. Use 'stub_samples' only.")
223-
224-
if stub_frames is not None:
225-
warnings.warn(
226-
"The 'stub_frames' parameter is deprecated and will be removed on or after February 2026. "
227-
"Use 'stub_samples' instead.",
228-
FutureWarning,
229-
stacklevel=2,
230-
)
231-
effective_stub_samples = stub_frames
232-
else:
233-
effective_stub_samples = stub_samples
234-
235196
for photon_series_index, (interface_name, data_interface) in enumerate(self.data_interface_objects.items()):
236197
data_interface.add_to_nwbfile(
237198
nwbfile=nwbfile,
238199
metadata=metadata,
239200
photon_series_index=photon_series_index,
240201
stub_test=stub_test,
241-
stub_samples=effective_stub_samples,
202+
stub_samples=stub_samples,
242203
)

src/neuroconv/datainterfaces/ophys/minian/miniandatainterface.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def add_to_nwbfile(
133133
metadata: Optional[dict] = None,
134134
*args, # TODO: change to * (keyword only) on or after August 2026
135135
stub_test: bool = False,
136-
stub_frames: int = 100,
136+
stub_samples: int = 100,
137137
include_background_segmentation: bool = True,
138138
include_roi_centroids: bool = True,
139139
include_roi_acceptance: bool = False,
@@ -145,7 +145,7 @@ def add_to_nwbfile(
145145
if args:
146146
parameter_names = [
147147
"stub_test",
148-
"stub_frames",
148+
"stub_samples",
149149
"include_background_segmentation",
150150
"include_roi_centroids",
151151
"include_roi_acceptance",
@@ -172,7 +172,7 @@ def add_to_nwbfile(
172172
stacklevel=2,
173173
)
174174
stub_test = positional_values.get("stub_test", stub_test)
175-
stub_frames = positional_values.get("stub_frames", stub_frames)
175+
stub_samples = positional_values.get("stub_samples", stub_samples)
176176
include_background_segmentation = positional_values.get(
177177
"include_background_segmentation", include_background_segmentation
178178
)
@@ -186,7 +186,7 @@ def add_to_nwbfile(
186186
nwbfile=nwbfile,
187187
metadata=metadata,
188188
stub_test=stub_test,
189-
stub_frames=stub_frames,
189+
stub_samples=stub_samples,
190190
include_background_segmentation=include_background_segmentation,
191191
include_roi_centroids=include_roi_centroids,
192192
include_roi_acceptance=include_roi_acceptance,

0 commit comments

Comments
 (0)