@@ -93,46 +93,46 @@ class Cifti2HeaderError(Exception):
93
93
# "Standard CIFTI Mapping Combinations" within CIFTI-2 spec
94
94
# https://www.nitrc.org/forum/attachment.php?attachid=341&group_id=454&forum_id=1955
95
95
CIFTI_CODES = Recoder ((
96
- ('dconn' , 'NIFTI_INTENT_CONNECTIVITY_DENSE' , (
96
+ ('. dconn.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE' , (
97
97
'CIFTI_INDEX_TYPE_BRAIN_MODELS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
98
98
)),
99
- ('dtseries' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES' , (
99
+ ('. dtseries.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES' , (
100
100
'CIFTI_INDEX_TYPE_SERIES' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
101
101
)),
102
- ('pconn' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED' , (
102
+ ('. pconn.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED' , (
103
103
'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_PARCELS' ,
104
104
)),
105
- ('ptseries' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SERIES' , (
105
+ ('. ptseries.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SERIES' , (
106
106
'CIFTI_INDEX_TYPE_SERIES' , 'CIFTI_INDEX_TYPE_PARCELS' ,
107
107
)),
108
- ('dscalar' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SCALARS' , (
108
+ ('. dscalar.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SCALARS' , (
109
109
'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
110
110
)),
111
- ('dlabel' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_LABELS' , (
111
+ ('. dlabel.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_LABELS' , (
112
112
'CIFTI_INDEX_TYPE_LABELS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
113
113
)),
114
- ('pscalar' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SCALAR' , (
114
+ ('. pscalar.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SCALAR' , (
115
115
'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_PARCELS' ,
116
116
)),
117
- ('pdconn' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_DENSE' , (
117
+ ('. pdconn.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_DENSE' , (
118
118
'CIFTI_INDEX_TYPE_BRAIN_MODELS' , 'CIFTI_INDEX_TYPE_PARCELS' ,
119
119
)),
120
- ('dpconn' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_PARCELLATED' , (
120
+ ('. dpconn.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_PARCELLATED' , (
121
121
'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
122
122
)),
123
- ('pconnseries' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SERIES' , (
123
+ ('. pconnseries.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SERIES' , (
124
124
'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_SERIES' ,
125
125
)),
126
- ('pconnscalar' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SCALAR' , (
126
+ ('. pconnscalar.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SCALAR' , (
127
127
'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_SCALARS' ,
128
128
)),
129
- ('dfan' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES' , (
129
+ ('. dfan.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES' , (
130
130
'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
131
131
)),
132
- ('dfibersamp' , 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN' , (
132
+ ('. dfibersamp.nii ' , 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN' , (
133
133
'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
134
134
)),
135
- ('dfansamp' , 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN' , (
135
+ ('. dfansamp.nii ' , 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN' , (
136
136
'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
137
137
)),
138
138
), fields = ('extension' , 'niistring' , 'map_types' ))
@@ -1564,40 +1564,39 @@ def to_filename(self, filename, validate=True):
1564
1564
Parameters
1565
1565
----------
1566
1566
validate : boolean, optional
1567
- If ``True``, infer and validate CIFTI type based on filename suffix.
1568
- This includes the setting of the NIfTI intent code and checking the ``CIFTI2Matrix``
1569
- for the expected IndicesMaps attributes.
1570
- If validation fails, an error will be raised instead.
1567
+ If ``True``, infer and validate CIFTI type based on MatrixIndicesMap values.
1568
+ This includes the setting of the relevant intent code within the NIfTI header.
1569
+ If validation fails, a UserWarning is issued and saving continues.
1571
1570
"""
1572
1571
if validate :
1573
- ext = _extract_cifti_extension (filename )
1574
- try :
1575
- CIFTI_CODES .extension [ext ]
1576
- except KeyError as err :
1577
- raise KeyError (
1578
- f"Validation failed: No information for extension { ext } available"
1579
- ) from err
1580
- intent = CIFTI_CODES .niistring [ext ]
1581
- self ._nifti_header .set_intent (intent )
1582
- # validate matrix indices
1583
- for idx , mtype in enumerate (CIFTI_CODES .map_types [ext ]):
1584
- try :
1585
- assert self .header .matrix .get_index_map (idx ).indices_map_to_data_type == mtype
1586
- except Exception :
1587
- raise Cifti2HeaderError (
1588
- f"Validation failed: Cifti2Matrix index map { idx } does "
1589
- f"not match expected type { mtype } "
1590
- )
1591
- super ().to_filename (filename )
1572
+ # Determine CIFTI type via index maps
1573
+ from .parse_cifti2 import intent_codes
1592
1574
1575
+ matrix = self .header .matrix
1576
+ map_types = tuple (
1577
+ matrix .get_index_map (idx ).indices_map_to_data_type for idx
1578
+ in sorted (matrix .mapped_indices )
1579
+ )
1580
+ try :
1581
+ expected_intent = CIFTI_CODES .niistring [map_types ]
1582
+ expected_ext = CIFTI_CODES .extension [map_types ]
1583
+ except KeyError : # unknown
1584
+ expected_intent = "NIFTI_INTENT_CONNECTIVITY_UNKNOWN"
1585
+ expected_ext = None
1586
+ warn (
1587
+ "No information found for matrix containing the following index maps:"
1588
+ f"{ map_types } , defaulting to unknown."
1589
+ )
1593
1590
1594
- def _extract_cifti_extension (filename ):
1595
- """Parses output filename for common suffixes and fetches corresponding intent code"""
1596
- from pathlib import Path
1597
- _suf = Path (filename ).suffixes
1598
- # select second to last if possible (.<suffix>.nii)
1599
- ext = _suf [- 2 ] if len (_suf ) >= 2 else _suf [0 ]
1600
- return ext .lstrip ('.' )
1591
+ orig_intent = self ._nifti_header .get_intent ()[0 ]
1592
+ if expected_intent != intent_codes .niistring [orig_intent ]:
1593
+ warn (
1594
+ f"Expected NIfTI intent: { expected_intent } has been automatically set."
1595
+ )
1596
+ self ._nifti_header .set_intent (expected_intent )
1597
+ if expected_ext is not None and not filename .endswith (expected_ext ):
1598
+ warn (f"Filename does not end with expected extension: { expected_ext } " )
1599
+ super ().to_filename (filename )
1601
1600
1602
1601
1603
1602
load = Cifti2Image .from_filename
0 commit comments