nipy / nibabel

Python package to access a cacophony of neuro-imaging file formats
http://nipy.org/nibabel/
Other
649 stars 258 forks source link

ValueError: Irregular spacing not supported #1236

Closed petsuter closed 1 year ago

petsuter commented 1 year ago

Trying to load the file D4600.mnc from https://www.facebase.org/chaise/record/#1/isa:imaging_data/RID=5-4T44

>>> import nibabel
>>> nibabel_image = nibabel.load("D4600.mnc")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python\lib\site-packages\nibabel\loadsave.py", line 52, in load
    img = image_klass.from_filename(filename, **kwargs)
  File "C:\Python\lib\site-packages\nibabel\dataobj_images.py", line 488, in from_filename
    return klass.from_file_map(file_map, mmap=mmap,
  File "C:\Python\lib\site-packages\nibabel\minc2.py", line 165, in from_file_map
    minc_file = Minc2File(h5py.File(holder.filename, 'r'))
  File "C:\Python\lib\site-packages\nibabel\minc2.py", line 63, in __init__
    raise ValueError('Irregular spacing not supported')
ValueError: Irregular spacing not supported

In https://github.com/nipy/nibabel/issues/448 it was suggested to comment out that line. Then it works:

>>> import nibabel
>>> nibabel_image = nibabel.load("D4600.mnc")
>>> nibabel_image.get_fdata()
array([[[-0.01740957, -0.01740957, -0.01740957, ..., -0.01740957,
         -0.01740957, -0.01740957],
...
>>> from nibabel.minc2 import Minc2File
>>> import h5py
>>> f = Minc2File(h5py.File("D4600.mnc"))
>>> f._dim_names
['zspace', 'yspace', 'xspace']
>>> [d.spacing for d in f._dims]
[b'xspace', b'xspace', b'xspace']
>>> list(f._mincfile['minc-2.0']['dimensions']['xspace'].attrs.items())
[('alignment', b'centre'), ('comments', b'X increases from patient left to right'), ('direction_cosines', array([1., 0., 0.])), ('length', 642), ('spacetype', b'native____'), ('spacing', b'xspace'), ('start', -2.625), ('step', 0.035), ('units', b'mm'), ('varid', b'MINC standard variable'), ('vartype', b'dimension____'), ('version', b'MINC Version    1.0')]
>>> list(f._mincfile['minc-2.0']['dimensions']['zspace'].attrs.items())
[('alignment', b'centre'), ('comments', b'Z increases from patient inferior to superior'), ('direction_cosines', array([0., 0., 1.])), ('length', 979), ('spacetype', b'native____'), ('spacing', b'xspace'), ('start', -4.060000000000001), ('step', 0.035), ('units', b'mm'), ('varid', b'MINC standard variable'), ('vartype', b'dimension____'), ('version', b'MINC Version    1.0')]
>>> list(f._mincfile['minc-2.0']['dimensions']['yspace'].attrs.items())
[('alignment', b'centre'), ('comments', b'Y increases from patient posterior to anterior'), ('direction_cosines', array([0., 1., 0.])), ('length', 586), ('spacetype', b'native____'), ('spacing', b'xspace'), ('start', -2.415), ('step', 0.035), ('units', b'mm'), ('varid', b'MINC standard variable'), ('vartype', b'dimension____'), ('version', b'MINC Version    1.0')]

Are those files all invalid? Should the check be removed or ignorable somehow? Thanks.

effigies commented 1 year ago

We could probably avoid this check. Without knowing much about MINC, I'd say the simplest thing would be to make it a flag so the user can say "I know what I'm doing and things might break if I try to use this like other spatial images".

Do you know much about MINC? Looking at what you've got there, it seems like spacing == 'xspace' rather than regular__, but describes a regular spacing. Is that standard or non-standard?

petsuter commented 1 year ago

I heard of MINC the first time today. 😅

Right, that was my impression also.

The comment in the code points to https://en.wikibooks.org/wiki/MINC/SoftwareDevelopment/MINC2.0_File_Format_Reference#Dimension_variable_attributes which claims:

spacing - String having the value regular__ to indicate a regularly spaced grid or irregular to indicate irregular spacing of samples. If the value of this attribute is irregular, then the dimension variable must be a vector varying with the dimension of the same name. If this attribute is absent, a value of regular__ should be assumed. Can be used for both dimension and dimension width variables.

So maybe xspace is non-conforming, but maybe any value other than irregular should de-facto be treated as regular__?

effigies commented 1 year ago

So maybe xspace is non-conforming, but maybe any value other than irregular should de-facto be treated as regular__?

That seems reasonable to me. I think I would follow the logic:

if irregular:
    raise ValueError
if not missing and not regular:
    warn(f"Invalid spacing declaration; assuming regular")

Would you be interested in submitting a pull request?

petsuter commented 1 year ago

Sounds good. Please feel free to edit or redo the PR if I misunderstood or missed something. 👍