4242
4343
4444@attrs .define (slots = True )
45- class PET (BaseDataset [np .ndarray | None ]):
45+ class PET (BaseDataset [np .ndarray ]):
4646 """Data representation structure for PET data."""
4747
4848 midframe : np .ndarray = attrs .field (default = None , repr = _data_repr , eq = attrs .cmp_using (eq = _cmp ))
@@ -52,13 +52,13 @@ class PET(BaseDataset[np.ndarray | None]):
5252 uptake : np .ndarray = attrs .field (default = None , repr = _data_repr , eq = attrs .cmp_using (eq = _cmp ))
5353 """A (N,) numpy array specifying the uptake value of each sample or frame."""
5454
55- def _getextra (self , idx : int | slice | tuple | np .ndarray ) -> tuple [np .ndarray | None ]:
56- return (self .midframe [idx ] if self . midframe is not None else None ,)
55+ def _getextra (self , idx : int | slice | tuple | np .ndarray ) -> tuple [np .ndarray ]:
56+ return (self .midframe [idx ],)
5757
5858 # For the sake of the docstring
5959 def __getitem__ (
6060 self , idx : int | slice | tuple | np .ndarray
61- ) -> tuple [np .ndarray , np .ndarray | None , np .ndarray | None ]:
61+ ) -> tuple [np .ndarray , np .ndarray | None , np .ndarray ]:
6262 """
6363 Returns volume(s) and corresponding affine(s) and timing(s) through fancy indexing.
6464
@@ -75,7 +75,7 @@ def __getitem__(
7575 otherwise it may have shape ``(X, Y, Z, k)``.
7676 motion_affine : :obj:`~numpy.ndarray` or ``None``
7777 The corresponding per-volume motion affine(s) or ``None`` if identity transform(s).
78- time : :obj:`float` or ``None` `
78+ time : :obj:`~numpy.ndarray `
7979 The frame time corresponding to the index(es).
8080
8181 """
@@ -105,18 +105,17 @@ def lofo_split(self, index):
105105 with h5py .File (self ._filepath , "r" ) as in_file :
106106 root = in_file ["/0" ]
107107 pet_frame = np .asanyarray (root ["dataobj" ][..., index ])
108- if self .midframe is not None :
109- timing_frame = np .asanyarray (root ["midframe" ][..., index ])
108+ timing_frame = np .asanyarray (root ["midframe" ][..., index ])
110109
111110 # Mask to exclude the selected frame
112111 mask = np .ones (self .dataobj .shape [- 1 ], dtype = bool )
113112 mask [index ] = False
114113
115114 train_data = self .dataobj [..., mask ]
116- train_timings = self .midframe [mask ] if self . midframe is not None else None
115+ train_timings = self .midframe [mask ]
117116
118117 test_data = pet_frame
119- test_timing = timing_frame if self . midframe is not None else None
118+ test_timing = timing_frame
120119
121120 return (train_data , train_timings ), (test_data , test_timing )
122121
@@ -144,7 +143,7 @@ def set_transform(self, index: int, affine: np.ndarray, order: int = 3) -> None:
144143
145144 # update transform
146145 if self .motion_affines is None :
147- self .motion_affines = [None ] * len (self )
146+ self .motion_affines = np . asarray ( [None ] * len (self ) )
148147
149148 self .motion_affines [index ] = xform
150149
@@ -174,12 +173,6 @@ def to_filename(
174173 compression_opts = compression_opts ,
175174 )
176175
177- def to_nifti (self , filename , * _ ):
178- """Write a NIfTI 1.0 file to disk."""
179- nii = nb .Nifti1Image (self .dataobj , self .affine , None )
180- nii .header .set_xyzt_units ("mm" )
181- nii .to_filename (filename )
182-
183176 @classmethod
184177 def from_filename (cls , filename : Path | str ) -> Self :
185178 """Read an HDF5 file from disk."""
@@ -225,9 +218,9 @@ def load(
225218
226219def from_nii (
227220 filename : Path | str ,
221+ frame_time : np .ndarray | list [float ],
228222 brainmask_file : Path | str | None = None ,
229223 motion_file : Path | str | None = None ,
230- frame_time : np .ndarray | list [float ] | None = None ,
231224 frame_duration : np .ndarray | list [float ] | None = None ,
232225) -> PET :
233226 """
@@ -237,14 +230,13 @@ def from_nii(
237230 ----------
238231 filename : :obj:`os.pathlike`
239232 The NIfTI file.
233+ frame_time : :obj:`numpy.ndarray` or :obj:`list` of :obj:`float`
234+ The start times of each frame relative to the beginning of the acquisition.
240235 brainmask_file : :obj:`os.pathlike`, optional
241236 A brainmask NIfTI file. If provided, will be loaded and
242237 stored in the returned dataset.
243238 motion_file : :obj:`os.pathlike`, optional
244239 A file containing head motion affine matrices (linear).
245- frame_time : :obj:`numpy.ndarray` or :obj:`list` of :obj:`float`, optional
246- The start times of each frame relative to the beginning of the acquisition.
247- If ``None``, an error is raised (since BIDS requires ``FrameTimesStart``).
248240 frame_duration : :obj:`numpy.ndarray` or :obj:`list` of :obj:`float`, optional
249241 The duration of each frame.
250242 If ``None``, it is derived by the difference of consecutive frame times,
@@ -261,8 +253,6 @@ def from_nii(
261253 If ``frame_time`` is not provided (BIDS requires it).
262254
263255 """
264- if frame_time is None :
265- raise RuntimeError ("frame_time must be provided" )
266256 if motion_file :
267257 raise NotImplementedError
268258
@@ -277,17 +267,14 @@ def from_nii(
277267
278268 pet_obj .uptake = _compute_uptake_statistic (data , stat_func = np .sum )
279269
280- # If the user supplied new values, set them
281- if frame_time is not None :
282- # Convert to a float32 numpy array and zero out the earliest time
283- frame_time_arr = np .array (frame_time , dtype = np .float32 )
284- frame_time_arr -= frame_time_arr [0 ]
285- pet_obj .midframe = frame_time_arr
270+ # Convert to a float32 numpy array and zero out the earliest time
271+ frame_time_arr = np .array (frame_time , dtype = np .float32 )
272+ frame_time_arr -= frame_time_arr [0 ]
273+ pet_obj .midframe = frame_time_arr
286274
287275 # If the user doesn't provide frame_duration, we derive it:
288276 if frame_duration is None :
289- if pet_obj .midframe is not None :
290- durations = _compute_frame_duration (pet_obj .midframe )
277+ durations = _compute_frame_duration (pet_obj .midframe )
291278 else :
292279 durations = np .array (frame_duration , dtype = np .float32 )
293280
0 commit comments