Skip to content

tst: explicitly set intent codes to allow proper loading #604

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 8 commits into from
Mar 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions nibabel/cifti2/cifti2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,9 @@ def to_file_map(self, file_map=None):
header = self._nifti_header
extension = Cifti2Extension(content=self.header.to_xml())
header.extensions.append(extension)
# if intent code is not set, default to unknown CIFTI
if header.get_intent()[0] == 'none':
header.set_intent('NIFTI_INTENT_CONNECTIVITY_UNKNOWN')
data = reshape_dataobj(self.dataobj,
(1, 1, 1, 1) + self.dataobj.shape)
# If qform not set, reset pixdim values so Nifti2 does not complain
Expand Down
24 changes: 12 additions & 12 deletions nibabel/cifti2/parse_cifti2.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,27 +52,27 @@ def _mangle(self, value):
# The codes below appear on the CIFTI-2 standard
# http://www.nitrc.org/plugins/mwiki/index.php/cifti:ConnectivityMatrixFileFormats
# https://www.nitrc.org/forum/attachment.php?attachid=341&group_id=454&forum_id=1955
(3000, 'dense fiber/fan samples', (), 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN'),
(3001, 'dense connectivity', (), 'NIFTI_INTENT_CONNECTIVITY_DENSE'),
(3002, 'dense data series/fiber fans', (),
(3000, 'ConnUnknown', (), 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN'),
(3001, 'ConnDense', (), 'NIFTI_INTENT_CONNECTIVITY_DENSE'),
(3002, 'ConnDenseSeries', (),
'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES'),
(3003, 'parcellated connectivity', (),
(3003, 'ConnParcels', (),
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED'),
(3004, 'parcellated data series', (),
(3004, 'ConnParcelSries', (),
"NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SERIES"),
(3006, 'dense scalar', (),
(3006, 'ConnDenseScalar', (),
'NIFTI_INTENT_CONNECTIVITY_DENSE_SCALARS'),
(3007, 'dense label', (),
(3007, 'ConnDenseLabel', (),
'NIFTI_INTENT_CONNECTIVITY_DENSE_LABELS'),
(3008, 'parcellated scalar', (),
(3008, 'ConnParcelScalr', (),
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SCALAR'),
(3009, 'parcellated dense connectivity', (),
(3009, 'ConnParcelDense', (),
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_DENSE'),
(3010, 'dense parcellated connectivity', (),
(3010, 'ConnDenseParcel', (),
'NIFTI_INTENT_CONNECTIVITY_DENSE_PARCELLATED'),
(3011, 'parcellated connectivity series', (),
(3011, 'ConnPPSr', (),
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SERIES'),
(3012, 'parcellated connectivity scalar', (),
(3012, 'ConnPPSc', (),
'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SCALAR')))


Expand Down
51 changes: 45 additions & 6 deletions nibabel/cifti2/tests/test_new_cifti2.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"""
import numpy as np

import nibabel as nib
from nibabel import cifti2 as ci
from nibabel.tmpdirs import InTemporaryDirectory

Expand Down Expand Up @@ -212,10 +213,14 @@ def test_dtseries():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(13, 9)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES')

with InTemporaryDirectory():
ci.save(img, 'test.dtseries.nii')
img2 = ci.load('test.dtseries.nii')
img2 = nib.load('test.dtseries.nii')
assert_equal(img2.nifti_header.get_intent()[0],
'ConnDenseSeries')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
check_series_map(img2.header.matrix.get_index_map(0))
check_geometry_map(img2.header.matrix.get_index_map(1))
Expand All @@ -231,10 +236,13 @@ def test_dscalar():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(2, 9)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE_SCALARS')

with InTemporaryDirectory():
ci.save(img, 'test.dscalar.nii')
img2 = ci.load('test.dscalar.nii')
img2 = nib.load('test.dscalar.nii')
assert_equal(img2.nifti_header.get_intent()[0], 'ConnDenseScalar')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
check_scalar_map(img2.header.matrix.get_index_map(0))
check_geometry_map(img2.header.matrix.get_index_map(1))
Expand All @@ -250,10 +258,13 @@ def test_dlabel():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(2, 9)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE_LABELS')

with InTemporaryDirectory():
ci.save(img, 'test.dlabel.nii')
img2 = ci.load('test.dlabel.nii')
img2 = nib.load('test.dlabel.nii')
assert_equal(img2.nifti_header.get_intent()[0], 'ConnDenseLabel')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
check_label_map(img2.header.matrix.get_index_map(0))
check_geometry_map(img2.header.matrix.get_index_map(1))
Expand All @@ -267,10 +278,13 @@ def test_dconn():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(9, 9)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE')

with InTemporaryDirectory():
ci.save(img, 'test.dconn.nii')
img2 = ci.load('test.dconn.nii')
img2 = nib.load('test.dconn.nii')
assert_equal(img2.nifti_header.get_intent()[0], 'ConnDense')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
assert_equal(img2.header.matrix.get_index_map(0),
img2.header.matrix.get_index_map(1))
Expand All @@ -287,10 +301,13 @@ def test_ptseries():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(13, 3)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SERIES')

with InTemporaryDirectory():
ci.save(img, 'test.ptseries.nii')
img2 = ci.load('test.ptseries.nii')
img2 = nib.load('test.ptseries.nii')
assert_equal(img2.nifti_header.get_intent()[0], 'ConnParcelSries')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
check_series_map(img2.header.matrix.get_index_map(0))
check_parcel_map(img2.header.matrix.get_index_map(1))
Expand All @@ -306,10 +323,13 @@ def test_pscalar():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(2, 3)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SCALAR')

with InTemporaryDirectory():
ci.save(img, 'test.pscalar.nii')
img2 = ci.load('test.pscalar.nii')
img2 = nib.load('test.pscalar.nii')
assert_equal(img2.nifti_header.get_intent()[0], 'ConnParcelScalr')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
check_scalar_map(img2.header.matrix.get_index_map(0))
check_parcel_map(img2.header.matrix.get_index_map(1))
Expand All @@ -325,10 +345,13 @@ def test_pdconn():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(2, 3)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_DENSE')

with InTemporaryDirectory():
ci.save(img, 'test.pdconn.nii')
img2 = ci.load('test.pdconn.nii')
assert_equal(img2.nifti_header.get_intent()[0], 'ConnParcelDense')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
check_geometry_map(img2.header.matrix.get_index_map(0))
check_parcel_map(img2.header.matrix.get_index_map(1))
Expand All @@ -344,10 +367,13 @@ def test_dpconn():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(2, 3)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_DENSE_PARCELLATED')

with InTemporaryDirectory():
ci.save(img, 'test.dpconn.nii')
img2 = ci.load('test.dpconn.nii')
assert_equal(img2.nifti_header.get_intent()[0], 'ConnDenseParcel')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
check_parcel_map(img2.header.matrix.get_index_map(0))
check_geometry_map(img2.header.matrix.get_index_map(1))
Expand All @@ -367,6 +393,8 @@ def test_plabel():
with InTemporaryDirectory():
ci.save(img, 'test.plabel.nii')
img2 = ci.load('test.plabel.nii')
Copy link
Member Author

Choose a reason for hiding this comment

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

is this a valid CIFTI type? I cannot find *plabel.nii in the specifications
https://www.nitrc.org/forum/attachment.php?attachid=341&group_id=454&forum_id=1955

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

If we will raise an exception upon saving, we have some options

  • remove the plabel test
  • alter ci.save's signature to include a new parameter, force=False, that can be switched on to allow saving without intent codes

WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

how about skipping the plabel test for now till we find the INTENT code. i would rather not have a parameter.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link

@coalsont coalsont Mar 6, 2018

Choose a reason for hiding this comment

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

plabel is not in the cifti-2 spec. We didn't see it being useful at the time, so it was not in the draft. We later found that the information needed to reorder parcellated files to group certain parcels together in matrix display could be stored as a parcels by labels file, and decided to use that extention, matching the previous pattern of extension naming.

Per the "unknown" special cifti intent (main cifti-2 document, top of page 13, middle of paragraph), it is in fact valid to make such a file, and its extension is technically open to be anything that ends in ".<something>.nii". Feel free to write a test that loads and/or saves a cifti mapping combination that is not in the spec, this is an expected use case.

assert_equal(img.nifti_header.get_intent()[0], 'ConnUnknown')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
check_label_map(img2.header.matrix.get_index_map(0))
check_parcel_map(img2.header.matrix.get_index_map(1))
Expand All @@ -380,10 +408,13 @@ def test_pconn():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(3, 3)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED')

with InTemporaryDirectory():
ci.save(img, 'test.pconn.nii')
img2 = ci.load('test.pconn.nii')
assert_equal(img.nifti_header.get_intent()[0], 'ConnParcels')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
assert_equal(img2.header.matrix.get_index_map(0),
img2.header.matrix.get_index_map(1))
Expand All @@ -401,10 +432,14 @@ def test_pconnseries():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(3, 3, 13)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_'
'PARCELLATED_SERIES')

with InTemporaryDirectory():
ci.save(img, 'test.pconnseries.nii')
img2 = ci.load('test.pconnseries.nii')
assert_equal(img.nifti_header.get_intent()[0], 'ConnPPSr')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
assert_equal(img2.header.matrix.get_index_map(0),
img2.header.matrix.get_index_map(1))
Expand All @@ -423,10 +458,14 @@ def test_pconnscalar():
hdr = ci.Cifti2Header(matrix)
data = np.random.randn(3, 3, 13)
img = ci.Cifti2Image(data, hdr)
img.nifti_header.set_intent('NIFTI_INTENT_CONNECTIVITY_PARCELLATED_'
'PARCELLATED_SCALAR')

with InTemporaryDirectory():
ci.save(img, 'test.pconnscalar.nii')
img2 = ci.load('test.pconnscalar.nii')
assert_equal(img.nifti_header.get_intent()[0], 'ConnPPSc')
assert_true(isinstance(img2, ci.Cifti2Image))
assert_true((img2.get_data() == data).all())
assert_equal(img2.header.matrix.get_index_map(0),
img2.header.matrix.get_index_map(1))
Expand Down