Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-nibabel for openSUSE:Factory checked in at 2026-02-23 16:12:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-nibabel (Old) and /work/SRC/openSUSE:Factory/.python-nibabel.new.1977 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-nibabel" Mon Feb 23 16:12:52 2026 rev:16 rq:1334428 version:5.3.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-nibabel/python-nibabel.changes 2025-07-31 17:50:10.970082146 +0200 +++ /work/SRC/openSUSE:Factory/.python-nibabel.new.1977/python-nibabel.changes 2026-02-23 16:14:49.418959945 +0100 @@ -1,0 +2,9 @@ +Mon Feb 23 09:17:45 UTC 2026 - Dirk Müller <[email protected]> + +- update to 5.3.3: + * Fix frame order for single-frame DICOM files (pr/1387) + (Brendan Moloney, reviewed by CM) + * Replace :class:`dict` literal with :class:`set` in test. + (pr/1382) (CM) + +------------------------------------------------------------------- Old: ---- nibabel-5.3.2.tar.gz New: ---- nibabel-5.3.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-nibabel.spec ++++++ --- /var/tmp/diff_new_pack.POL8bV/_old 2026-02-23 16:14:49.918980561 +0100 +++ /var/tmp/diff_new_pack.POL8bV/_new 2026-02-23 16:14:49.922980726 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-nibabel # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %define binaries nib-conform nib-convert nib-dicomfs nib-diff nib-ls nib-nifti-dx nib-roi nib-stats nib-tck2trk nib-trk2tck parrec2nii Name: python-nibabel -Version: 5.3.2 +Version: 5.3.3 Release: 0 Summary: Tool to access multiple neuroimaging data formats License: MIT ++++++ nibabel-5.3.2.tar.gz -> nibabel-5.3.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nibabel-5.3.2/Changelog new/nibabel-5.3.3/Changelog --- old/nibabel-5.3.2/Changelog 2020-02-02 01:00:00.000000000 +0100 +++ new/nibabel-5.3.3/Changelog 2020-02-02 01:00:00.000000000 +0100 @@ -25,6 +25,17 @@ References like "pr/298" refer to github pull request numbers. +5.3.3 (Friday 5 December 2025) +============================== + +Bug-fix release in the 5.3.x series. + +Bug fixes +--------- +* Fix frame order for single-frame DICOM files (pr/1387) (Brendan Moloney, reviewed by CM) +* Replace :class:`dict` literal with :class:`set` in test. (pr/1382) (CM) + + 5.3.2 (Wednesday 23 October 2024) ================================= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nibabel-5.3.2/PKG-INFO new/nibabel-5.3.3/PKG-INFO --- old/nibabel-5.3.2/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 +++ new/nibabel-5.3.3/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ -Metadata-Version: 2.3 +Metadata-Version: 2.4 Name: nibabel -Version: 5.3.2 +Version: 5.3.3 Summary: Access a multitude of neuroimaging data formats Project-URL: Homepage, https://nipy.org/nibabel Project-URL: Development, https://github.com/nipy/nibabel diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nibabel-5.3.2/doc/source/_long_description.inc new/nibabel-5.3.3/doc/source/_long_description.inc --- old/nibabel-5.3.2/doc/source/_long_description.inc 1970-01-01 01:00:00.000000000 +0100 +++ new/nibabel-5.3.3/doc/source/_long_description.inc 2020-02-02 01:00:00.000000000 +0100 @@ -0,0 +1,97 @@ + +Read and write access to common neuroimaging file formats, including: +ANALYZE_ (plain, SPM99, SPM2 and later), GIFTI_, NIfTI1_, NIfTI2_, `CIFTI-2`_, +MINC1_, MINC2_, `AFNI BRIK/HEAD`_, ECAT_ and Philips PAR/REC. +In addition, NiBabel also supports FreeSurfer_'s MGH_, geometry, annotation and +morphometry files, and provides some limited support for DICOM_. + +NiBabel's API gives full or selective access to header information (metadata), +and image data is made available via NumPy arrays. For more information, see +NiBabel's `documentation site`_ and `API reference`_. + +.. _API reference: https://nipy.org/nibabel/api.html +.. _AFNI BRIK/HEAD: https://afni.nimh.nih.gov/pub/dist/src/README.attributes +.. _ANALYZE: http://www.grahamwideman.com/gw/brain/analyze/formatdoc.htm +.. _CIFTI-2: https://www.nitrc.org/projects/cifti/ +.. _DICOM: http://medical.nema.org/ +.. _documentation site: http://nipy.org/nibabel +.. _ECAT: http://xmedcon.sourceforge.net/Docs/Ecat +.. _Freesurfer: https://surfer.nmr.mgh.harvard.edu +.. _GIFTI: https://www.nitrc.org/projects/gifti +.. _MGH: https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/MghFormat +.. _MINC1: + https://en.wikibooks.org/wiki/MINC/Reference/MINC1_File_Format_Reference +.. _MINC2: + https://en.wikibooks.org/wiki/MINC/Reference/MINC2.0_File_Format_Reference +.. _NIfTI1: http://nifti.nimh.nih.gov/nifti-1/ +.. _NIfTI2: http://nifti.nimh.nih.gov/nifti-2/ + +Installation +============ + +To install NiBabel's `current release`_ with ``pip``, run:: + + pip install nibabel + +To install the latest development version, run:: + + pip install git+https://github.com/nipy/nibabel + +When working on NiBabel itself, it may be useful to install in "editable" mode:: + + git clone https://github.com/nipy/nibabel.git + pip install -e ./nibabel + +For more information on previous releases, see the `release archive`_ or +`development changelog`_. + +.. _current release: https://pypi.python.org/pypi/NiBabel +.. _release archive: https://github.com/nipy/NiBabel/releases +.. _development changelog: https://nipy.org/nibabel/changelog.html + +Testing +======= + +During development, we recommend using tox_ to run nibabel tests:: + + git clone https://github.com/nipy/nibabel.git + cd nibabel + tox + +To test an installed version of nibabel, install the test dependencies +and run pytest_:: + + pip install nibabel[test] + pytest --pyargs nibabel + +For more information, consult the `developer guidelines`_. + +.. _tox: https://tox.wiki +.. _pytest: https://docs.pytest.org +.. _developer guidelines: https://nipy.org/nibabel/devel/devguide.html + +Mailing List +============ + +Please send any questions or suggestions to the `neuroimaging mailing list +<https://mail.python.org/mailman/listinfo/neuroimaging>`_. + +License +======= + +NiBabel is licensed under the terms of the `MIT license +<https://github.com/nipy/nibabel/blob/master/COPYING#nibabel>`__. +Some code included with NiBabel is licensed under the `BSD license`_. +For more information, please see the COPYING_ file. + +.. _BSD license: https://opensource.org/licenses/BSD-3-Clause +.. _COPYING: https://github.com/nipy/nibabel/blob/master/COPYING + +Citation +======== + +NiBabel releases have a Zenodo_ `Digital Object Identifier`_ (DOI) badge at +the top of the release notes. Click on the badge for more information. + +.. _Digital Object Identifier: https://en.wikipedia.org/wiki/Digital_object_identifier +.. _zenodo: https://zenodo.org diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nibabel-5.3.2/nibabel/_version.py new/nibabel-5.3.3/nibabel/_version.py --- old/nibabel-5.3.2/nibabel/_version.py 2020-02-02 01:00:00.000000000 +0100 +++ new/nibabel-5.3.3/nibabel/_version.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,4 @@ # file generated by setuptools_scm # don't change, don't track in version control -__version__ = version = '5.3.2' -__version_tuple__ = version_tuple = (5, 3, 2) +__version__ = version = '5.3.3' +__version_tuple__ = version_tuple = (5, 3, 3) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nibabel-5.3.2/nibabel/nicom/dicomwrappers.py new/nibabel-5.3.3/nibabel/nicom/dicomwrappers.py --- old/nibabel-5.3.2/nibabel/nicom/dicomwrappers.py 2020-02-02 01:00:00.000000000 +0100 +++ new/nibabel-5.3.3/nibabel/nicom/dicomwrappers.py 2020-02-02 01:00:00.000000000 +0100 @@ -532,8 +532,8 @@ class FrameFilter: """Base class for defining how to filter out (ignore) frames from a multiframe file - It is guaranteed that the `applies` method will on a dataset before the `keep` method - is called on any of the frames inside. + It is guaranteed that the `applies` method will called on a dataset before the `keep` + method is called on any of the frames inside. """ def applies(self, dcm_wrp) -> bool: @@ -549,7 +549,7 @@ """Filter out all but one `StackID`""" def __init__(self, keep_id=None): - self._keep_id = keep_id + self._keep_id = str(keep_id) if keep_id is not None else None def applies(self, dcm_wrp) -> bool: first_fcs = dcm_wrp.frames[0].get('FrameContentSequence', (None,))[0] @@ -562,10 +562,16 @@ self._selected = self._keep_id if len(stack_ids) > 1: if self._keep_id is None: + try: + sids = [int(x) for x in stack_ids] + except: + self._selected = dcm_wrp.frames[0].FrameContentSequence[0].StackID + else: + self._selected = str(min(sids)) warnings.warn( - 'A multi-stack file was passed without an explicit filter, just using lowest StackID' + 'A multi-stack file was passed without an explicit filter, ' + f'using StackID = {self._selected}' ) - self._selected = min(stack_ids) return True return False @@ -707,6 +713,7 @@ @cached_property def frame_order(self): + """The ordering of frames to make nD array""" if self._frame_indices is None: _ = self.image_shape return np.lexsort(self._frame_indices.T) @@ -742,14 +749,20 @@ rows, cols = self.get('Rows'), self.get('Columns') if None in (rows, cols): raise WrapperError('Rows and/or Columns are empty.') - # Check number of frames, initialize array of frame indices + # Check number of frames and handle single frame files n_frames = len(self.frames) + if n_frames == 1: + self._frame_indices = np.array([[0]], dtype=np.int64) + return (rows, cols) + # Initialize array of frame indices try: frame_indices = np.array( [frame.FrameContentSequence[0].DimensionIndexValues for frame in self.frames] ) except AttributeError: raise WrapperError("Can't find frame 'DimensionIndexValues'") + if len(frame_indices.shape) == 1: + frame_indices = frame_indices.reshape(frame_indices.shape + (1,)) # Determine the shape and which indices to use shape = [rows, cols] curr_parts = n_frames diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nibabel-5.3.2/nibabel/nicom/tests/test_dicomwrappers.py new/nibabel-5.3.3/nibabel/nicom/tests/test_dicomwrappers.py --- old/nibabel-5.3.2/nibabel/nicom/tests/test_dicomwrappers.py 2020-02-02 01:00:00.000000000 +0100 +++ new/nibabel-5.3.3/nibabel/nicom/tests/test_dicomwrappers.py 2020-02-02 01:00:00.000000000 +0100 @@ -427,13 +427,6 @@ generate ipp values so slice location is negatively correlated with slice index """ - class PrintBase: - def __repr__(self): - attr_strs = [ - f'{attr}={getattr(self, attr)}' for attr in dir(self) if attr[0].isupper() - ] - return f"{self.__class__.__name__}({', '.join(attr_strs)})" - class DimIdxSeqElem(pydicom.Dataset): def __init__(self, dip=(0, 0), fgp=None): super().__init__() @@ -444,8 +437,8 @@ class FrmContSeqElem(pydicom.Dataset): def __init__(self, div, sid): super().__init__() - self.DimensionIndexValues = div - self.StackID = sid + self.DimensionIndexValues = list(div) + self.StackID = str(sid) class PlnPosSeqElem(pydicom.Dataset): def __init__(self, ipp): @@ -545,17 +538,28 @@ with pytest.raises(didw.WrapperError): dw.image_shape fake_mf.Rows = 32 - # No frame data raises WrapperError + # Single frame doesn't need dimension index values + assert dw.image_shape == (32, 64) + assert len(dw.frame_order) == 1 + assert dw.frame_order[0] == 0 + # Multiple frames do require dimension index values + fake_mf.PerFrameFunctionalGroupsSequence = [pydicom.Dataset(), pydicom.Dataset()] with pytest.raises(didw.WrapperError): - dw.image_shape + MFW(fake_mf).image_shape # check 2D shape with StackID index is 0 div_seq = ((1, 1),) fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0)) - assert MFW(fake_mf).image_shape == (32, 64) + dw = MFW(fake_mf) + assert dw.image_shape == (32, 64) + assert len(dw.frame_order) == 1 + assert dw.frame_order[0] == 0 # Check 2D shape with extraneous extra indices div_seq = ((1, 1, 2),) fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0)) - assert MFW(fake_mf).image_shape == (32, 64) + dw = MFW(fake_mf) + assert dw.image_shape == (32, 64) + assert len(dw.frame_order) == 1 + assert dw.frame_order[0] == 0 # Check 2D plus time div_seq = ((1, 1, 1), (1, 1, 2), (1, 1, 3)) fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0)) @@ -569,7 +573,7 @@ fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0)) with pytest.warns( UserWarning, - match='A multi-stack file was passed without an explicit filter, just using lowest StackID', + match='A multi-stack file was passed without an explicit filter,', ): assert MFW(fake_mf).image_shape == (32, 64, 3) # No warning if we expclitly select that StackID to keep @@ -581,7 +585,7 @@ fake_mf.update(fake_shape_dependents(div_seq, sid_seq=sid_seq)) with pytest.warns( UserWarning, - match='A multi-stack file was passed without an explicit filter, just using lowest StackID', + match='A multi-stack file was passed without an explicit filter,', ): assert MFW(fake_mf).image_shape == (32, 64, 3) # No warning if we expclitly select that StackID to keep @@ -590,6 +594,17 @@ # Check for error when explicitly requested StackID is missing with pytest.raises(didw.WrapperError): MFW(fake_mf, frame_filters=(didw.FilterMultiStack(3),)) + # StackID can be a string + div_seq = ((1,), (2,), (3,), (4,)) + sid_seq = ('a', 'a', 'a', 'b') + fake_mf.update(fake_shape_dependents(div_seq, sid_seq=sid_seq)) + with pytest.warns( + UserWarning, + match='A multi-stack file was passed without an explicit filter,', + ): + assert MFW(fake_mf).image_shape == (32, 64, 3) + assert MFW(fake_mf, frame_filters=(didw.FilterMultiStack('a'),)).image_shape == (32, 64, 3) + assert MFW(fake_mf, frame_filters=(didw.FilterMultiStack('b'),)).image_shape == (32, 64) # Make some fake frame data for 4D when StackID index is 0 div_seq = ((1, 1, 1), (1, 2, 1), (1, 1, 2), (1, 2, 2), (1, 1, 3), (1, 2, 3)) fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0)) @@ -599,7 +614,7 @@ fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0)) with pytest.warns( UserWarning, - match='A multi-stack file was passed without an explicit filter, just using lowest StackID', + match='A multi-stack file was passed without an explicit filter,', ): with pytest.raises(didw.WrapperError): MFW(fake_mf).image_shape @@ -638,7 +653,7 @@ fake_mf.update(fake_shape_dependents(div_seq, sid_seq=sid_seq)) with pytest.warns( UserWarning, - match='A multi-stack file was passed without an explicit filter, just using lowest StackID', + match='A multi-stack file was passed without an explicit filter,', ): with pytest.raises(didw.WrapperError): MFW(fake_mf).image_shape @@ -651,7 +666,7 @@ fake_mf.update(fake_shape_dependents(div_seq, sid_dim=1)) with pytest.warns( UserWarning, - match='A multi-stack file was passed without an explicit filter, just using lowest StackID', + match='A multi-stack file was passed without an explicit filter,', ): assert MFW(fake_mf).image_shape == (32, 64, 3) # Make some fake frame data for 4D when StackID index is 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nibabel-5.3.2/nibabel/tests/test_api_validators.py new/nibabel-5.3.3/nibabel/tests/test_api_validators.py --- old/nibabel-5.3.2/nibabel/tests/test_api_validators.py 2020-02-02 01:00:00.000000000 +0100 +++ new/nibabel-5.3.3/nibabel/tests/test_api_validators.py 2020-02-02 01:00:00.000000000 +0100 @@ -99,7 +99,7 @@ We check this in the module teardown function """ - run_tests = {} + run_tests = set() def obj_params(self): yield 1, 2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nibabel-5.3.2/tox.ini new/nibabel-5.3.3/tox.ini --- old/nibabel-5.3.2/tox.ini 2020-02-02 01:00:00.000000000 +0100 +++ new/nibabel-5.3.3/tox.ini 2020-02-02 01:00:00.000000000 +0100 @@ -70,8 +70,6 @@ NO_COLOR CLICOLOR CLICOLOR_FORCE -set_env = - py313: PYTHON_GIL=0 extras = test deps = # General minimum dependencies: pin based on API usage
