Skip to content

ENH: Add dtype argument to Cifti2Image #1111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 3, 2022

Conversation

effigies
Copy link
Member

To bring into line with other Analyze-like formats.

Given that the subject that brought us here was inappropriate use of image dtypes, I am also constraining the dtypes to those listed in the standard:

The datatype field in the NIfTI header can be any of float, double, and signed or unsigned int8,
int16, int32, or int64, with bitpix set correspondingly, per the NIfTI standard. Composite
datatypes, such as complex or RGB, and bitwise storage are not supported in CIFTI. Multiple
scalar maps, or separate files, can be used instead of composite datatypes.

I also dropped float128, which is not specifically restricted, but nor is it specifically permitted. Seems unlikely to be a good idea.

@effigies
Copy link
Member Author

Tests forthcoming.

@codecov
Copy link

codecov bot commented May 26, 2022

Codecov Report

Merging #1111 (7933fae) into master (4bd0027) will increase coverage by 0.01%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master    #1111      +/-   ##
==========================================
+ Coverage   92.26%   92.28%   +0.01%     
==========================================
  Files         100      100              
  Lines       12269    12285      +16     
  Branches     2399     2402       +3     
==========================================
+ Hits        11320    11337      +17     
  Misses        624      624              
+ Partials      325      324       -1     
Impacted Files Coverage Δ
nibabel/analyze.py 98.58% <100.00%> (+0.03%) ⬆️
nibabel/cifti2/cifti2.py 96.85% <100.00%> (+0.20%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4bd0027...7933fae. Read the comment docs.

@effigies effigies force-pushed the enh/cifti_dtype_arg branch 2 times, most recently from c2dbd89 to 70579bc Compare May 27, 2022 20:42
@effigies effigies force-pushed the enh/cifti_dtype_arg branch from 70579bc to 7933fae Compare May 27, 2022 20:51
Copy link
Member Author

@effigies effigies left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple notes for a reviewer.

@@ -103,6 +123,10 @@ def _underscore(string):
return re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', string).lower()


class LimitedNifti2Header(Nifti2Header):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly there's a better name. _Cifti2AsNiftiHeader exists to do some validation during parsing, but isn't the type of nifti_header.

class _Cifti2AsNiftiHeader(Nifti2Header):
""" Class for Cifti2 header extension """
@classmethod
def _valid_intent_code(klass, intent_code):
""" Return True if `intent_code` matches our class `klass`
"""
return intent_code >= 3000 and intent_code < 3100
@classmethod
def may_contain_header(klass, binaryblock):
if not super(_Cifti2AsNiftiHeader, klass).may_contain_header(binaryblock):
return False
hdr = klass(binaryblock=binaryblock[:klass.sizeof_hdr])
return klass._valid_intent_code(hdr.get_intent('code')[0])
@staticmethod
def _chk_qfac(hdr, fix=False):
# Allow qfac of 0 without complaint for CIFTI-2
rep = Report(HeaderDataError)
if hdr['pixdim'][0] in (-1, 0, 1):
return hdr, rep
rep.problem_level = 20
rep.problem_msg = 'pixdim[0] (qfac) should be 1 (default) or 0 or -1'
if fix:
hdr['pixdim'][0] = 1
rep.fix_msg = 'setting qfac to 1'
return hdr, rep
@staticmethod
def _chk_pixdims(hdr, fix=False):
rep = Report(HeaderDataError)
pixdims = hdr['pixdim']
spat_dims = pixdims[1:4]
if not np.any(spat_dims < 0):
return hdr, rep
rep.problem_level = 35
rep.problem_msg = 'pixdim[1,2,3] should be zero or positive'
if fix:
hdr['pixdim'][1:4] = np.abs(spat_dims)
rep.fix_msg = 'setting to abs of pixdim values'
return hdr, rep

@@ -674,7 +716,12 @@ def header_maker(self):
return self.image_maker.header_class()


class TestAnalyzeAPI(ImageHeaderAPI):
class TestSpatialImageAPI(ImageHeaderAPI):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This subclass/superclass swap occurs because not all spatial images have dtype overriding.

@effigies
Copy link
Member Author

effigies commented Jun 3, 2022

If anybody wants to review, please let me know by end of day (5pm UTC-4). Otherwise I'll merge and aim to release 4.0.0rc0 on Monday.

@effigies effigies merged commit a7e1e0e into nipy:master Jun 3, 2022
@effigies effigies deleted the enh/cifti_dtype_arg branch June 3, 2022 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant