From 9846352f80dc6d05430e163f2f8be0a3cd119c10 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Thu, 10 Feb 2022 22:18:03 -0500 Subject: [PATCH 1/2] ENH: Allow save-time passing of on-disk dtype to to_* methods --- nibabel/analyze.py | 11 +++++++++-- nibabel/filebasedimages.py | 15 +++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/nibabel/analyze.py b/nibabel/analyze.py index 3daaaf1175..4ef3708325 100644 --- a/nibabel/analyze.py +++ b/nibabel/analyze.py @@ -989,7 +989,7 @@ def _get_fileholders(file_map): """ return file_map['header'], file_map['image'] - def to_file_map(self, file_map=None): + def to_file_map(self, file_map=None, dtype=None): """ Write image to `file_map` or contained ``self.file_map`` Parameters @@ -997,15 +997,21 @@ def to_file_map(self, file_map=None): file_map : None or mapping, optional files mapping. If None (default) use object's ``file_map`` attribute instead + dtype : dtype-like, optional + The on-disk data type to coerce the data array. """ if file_map is None: file_map = self.file_map data = np.asanyarray(self.dataobj) self.update_header() hdr = self._header - out_dtype = self.get_data_dtype() # Store consumable values for later restore offset = hdr.get_data_offset() + data_dtype = hdr.get_data_dtype() + # Override dtype conditionally + if dtype is not None: + hdr.set_data_dtype(out_dtype) + out_dtype = hdr.get_data_dtype() # Scalars of slope, offset to get immutable values slope = hdr['scl_slope'].item() if hdr.has_data_slope else np.nan inter = hdr['scl_inter'].item() if hdr.has_data_intercept else np.nan @@ -1045,6 +1051,7 @@ def to_file_map(self, file_map=None): self.file_map = file_map # Restore any changed consumable values hdr.set_data_offset(offset) + hdr.set_data_dtype(data_dtype) if hdr.has_data_slope: hdr['scl_slope'] = slope if hdr.has_data_intercept: diff --git a/nibabel/filebasedimages.py b/nibabel/filebasedimages.py index 3fd5b5fc8f..2cfddb5644 100644 --- a/nibabel/filebasedimages.py +++ b/nibabel/filebasedimages.py @@ -299,7 +299,7 @@ def filespec_to_file_map(klass, filespec): file_map[key] = FileHolder(filename=fname) return file_map - def to_filename(self, filename): + def to_filename(self, filename, **kwargs): """ Write image to files implied by filename string Parameters @@ -308,15 +308,17 @@ def to_filename(self, filename): filename to which to save image. We will parse `filename` with ``filespec_to_file_map`` to work out names for image, header etc. + \*\*kwargs : keyword arguments + Keyword arguments to format-specific save Returns ------- None """ self.file_map = self.filespec_to_file_map(filename) - self.to_file_map() + self.to_file_map(**kwargs) - def to_file_map(self, file_map=None): + def to_file_map(self, file_map=None, **kwargs): raise NotImplementedError @classmethod @@ -552,13 +554,14 @@ def from_bytes(klass, bytestring): file_map = klass.make_file_map({'image': bio, 'header': bio}) return klass.from_file_map(file_map) - def to_bytes(self): + def to_bytes(self, **kwargs): """ Return a ``bytes`` object with the contents of the file that would be written if the image were saved. Parameters ---------- - None + \*\*kwargs : keyword arguments + Keyword arguments that may be passed to ``img.to_file_map()`` Returns ------- @@ -569,5 +572,5 @@ def to_bytes(self): raise NotImplementedError("to_bytes() is undefined for multi-file images") bio = io.BytesIO() file_map = self.make_file_map({'image': bio, 'header': bio}) - self.to_file_map(file_map) + self.to_file_map(file_map, **kwargs) return bio.getvalue() From 325b65866fa22962f8c90d342fab0ad9ef7841f8 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Thu, 10 Feb 2022 22:20:15 -0500 Subject: [PATCH 2/2] ENH: Allow nibabel.save() to accept kwargs to pass to img.to_filename() --- nibabel/loadsave.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nibabel/loadsave.py b/nibabel/loadsave.py index 1f736409dd..145d0f29c5 100644 --- a/nibabel/loadsave.py +++ b/nibabel/loadsave.py @@ -130,7 +130,7 @@ def guessed_image_type(filename): raise ImageFileError(f'Cannot work out file type of "{filename}"') -def save(img, filename): +def save(img, filename, **kwargs): """ Save an image to file adapting format to `filename` Parameters @@ -139,6 +139,8 @@ def save(img, filename): image to save filename : str or os.PathLike filename (often implying filenames) to which to save `img`. + \*\*kwargs : keyword arguments + Keyword arguments to format-specific save Returns ------- @@ -148,7 +150,7 @@ def save(img, filename): # Save the type as expected try: - img.to_filename(filename) + img.to_filename(filename, **kwargs) except ImageFileError: pass else: @@ -196,7 +198,7 @@ def save(img, filename): # Here, we either have a klass or a converted image. if converted is None: converted = klass.from_image(img) - converted.to_filename(filename) + converted.to_filename(filename, **kwargs) @deprecate_with_version('read_img_data deprecated. '