@@ -93,46 +93,46 @@ class Cifti2HeaderError(Exception):
9393# "Standard CIFTI Mapping Combinations" within CIFTI-2 spec
9494# https://www.nitrc.org/forum/attachment.php?attachid=341&group_id=454&forum_id=1955
9595CIFTI_CODES = Recoder ((
96- ('dconn' , 'NIFTI_INTENT_CONNECTIVITY_DENSE' , (
96+ ('. dconn.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE' , (
9797 'CIFTI_INDEX_TYPE_BRAIN_MODELS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
9898 )),
99- ('dtseries' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES' , (
99+ ('. dtseries.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES' , (
100100 'CIFTI_INDEX_TYPE_SERIES' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
101101 )),
102- ('pconn' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED' , (
102+ ('. pconn.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED' , (
103103 'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_PARCELS' ,
104104 )),
105- ('ptseries' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SERIES' , (
105+ ('. ptseries.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SERIES' , (
106106 'CIFTI_INDEX_TYPE_SERIES' , 'CIFTI_INDEX_TYPE_PARCELS' ,
107107 )),
108- ('dscalar' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SCALARS' , (
108+ ('. dscalar.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SCALARS' , (
109109 'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
110110 )),
111- ('dlabel' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_LABELS' , (
111+ ('. dlabel.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_LABELS' , (
112112 'CIFTI_INDEX_TYPE_LABELS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
113113 )),
114- ('pscalar' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SCALAR' , (
114+ ('. pscalar.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_SCALAR' , (
115115 'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_PARCELS' ,
116116 )),
117- ('pdconn' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_DENSE' , (
117+ ('. pdconn.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_DENSE' , (
118118 'CIFTI_INDEX_TYPE_BRAIN_MODELS' , 'CIFTI_INDEX_TYPE_PARCELS' ,
119119 )),
120- ('dpconn' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_PARCELLATED' , (
120+ ('. dpconn.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_PARCELLATED' , (
121121 'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
122122 )),
123- ('pconnseries' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SERIES' , (
123+ ('. pconnseries.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SERIES' , (
124124 'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_SERIES' ,
125125 )),
126- ('pconnscalar' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SCALAR' , (
126+ ('. pconnscalar.nii ' , 'NIFTI_INTENT_CONNECTIVITY_PARCELLATED_PARCELLATED_SCALAR' , (
127127 'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_PARCELS' , 'CIFTI_INDEX_TYPE_SCALARS' ,
128128 )),
129- ('dfan' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES' , (
129+ ('. dfan.nii ' , 'NIFTI_INTENT_CONNECTIVITY_DENSE_SERIES' , (
130130 'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
131131 )),
132- ('dfibersamp' , 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN' , (
132+ ('. dfibersamp.nii ' , 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN' , (
133133 'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
134134 )),
135- ('dfansamp' , 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN' , (
135+ ('. dfansamp.nii ' , 'NIFTI_INTENT_CONNECTIVITY_UNKNOWN' , (
136136 'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_SCALARS' , 'CIFTI_INDEX_TYPE_BRAIN_MODELS' ,
137137 )),
138138), fields = ('extension' , 'niistring' , 'map_types' ))
@@ -1564,40 +1564,39 @@ def to_filename(self, filename, validate=True):
15641564 Parameters
15651565 ----------
15661566 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.
15711570 """
15721571 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
15921574
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+ )
15931590
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 )
16011600
16021601
16031602load = Cifti2Image .from_filename
0 commit comments