1# emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*-
2# vi: set ft=python sts=4 ts=4 sw=4 et:
3### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
4#
5#   See COPYING file distributed along with the NiBabel package for the
6#   copyright and license terms.
7#
8### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
9""" Define supported image classes and names """
10
11from .analyze import AnalyzeImage
12from .brikhead import AFNIImage
13from .cifti2 import Cifti2Image
14from .freesurfer import MGHImage
15from .gifti import GiftiImage
16from .minc1 import Minc1Image
17from .minc2 import Minc2Image
18from .nifti1 import Nifti1Pair, Nifti1Image
19from .nifti2 import Nifti2Pair, Nifti2Image
20from .parrec import PARRECImage
21from .spm99analyze import Spm99AnalyzeImage
22from .spm2analyze import Spm2AnalyzeImage
23from .volumeutils import Recoder
24from .deprecated import deprecate_with_version
25
26from .optpkg import optional_package
27_, have_scipy, _ = optional_package('scipy')
28
29
30# Ordered by the load/save priority.
31all_image_classes = [Nifti1Pair, Nifti1Image, Nifti2Pair,
32                     Cifti2Image, Nifti2Image,  # Cifti2 before Nifti2
33                     Spm2AnalyzeImage, Spm99AnalyzeImage, AnalyzeImage,
34                     Minc1Image, Minc2Image, MGHImage,
35                     PARRECImage, GiftiImage, AFNIImage]
36
37
38# DEPRECATED: mapping of names to classes and class functionality
39class ClassMapDict(dict):
40
41    @deprecate_with_version('class_map is deprecated.',
42                            '2.1', '4.0')
43    def __getitem__(self, *args, **kwargs):
44        return super(ClassMapDict, self).__getitem__(*args, **kwargs)
45
46
47class_map = ClassMapDict(
48    analyze={'class': AnalyzeImage,  # Image class
49             'ext': '.img',  # characteristic image extension
50             'has_affine': False,  # class can store an affine
51             'makeable': True,  # empty image can be easily made in memory
52             'rw': True},  # image can be written
53    spm99analyze={'class': Spm99AnalyzeImage,
54                  'ext': '.img',
55                  'has_affine': True,
56                  'makeable': True,
57                  'rw': have_scipy},
58    spm2analyze={'class': Spm2AnalyzeImage,
59                 'ext': '.img',
60                 'has_affine': True,
61                 'makeable': True,
62                 'rw': have_scipy},
63    nifti_pair={'class': Nifti1Pair,
64                'ext': '.img',
65                'has_affine': True,
66                'makeable': True,
67                'rw': True},
68    nifti_single={'class': Nifti1Image,
69                  'ext': '.nii',
70                  'has_affine': True,
71                  'makeable': True,
72                  'rw': True},
73    minc={'class': Minc1Image,
74          'ext': '.mnc',
75          'has_affine': True,
76          'makeable': True,
77          'rw': False},
78    mgh={'class': MGHImage,
79         'ext': '.mgh',
80         'has_affine': True,
81         'makeable': True,
82         'rw': True},
83    mgz={'class': MGHImage,
84         'ext': '.mgz',
85         'has_affine': True,
86         'makeable': True,
87         'rw': True},
88    par={'class': PARRECImage,
89         'ext': '.par',
90         'has_affine': True,
91         'makeable': False,
92         'rw': False},
93    afni={'class': AFNIImage,
94          'ext': '.brik',
95          'has_affine': True,
96          'makeable': False,
97          'rw': False})
98
99
100class ExtMapRecoder(Recoder):
101
102    @deprecate_with_version('ext_map is deprecated.',
103                            '2.1', '4.0')
104    def __getitem__(self, *args, **kwargs):
105        return super(ExtMapRecoder, self).__getitem__(*args, **kwargs)
106
107
108# mapping of extensions to default image class names
109ext_map = ExtMapRecoder((
110    ('nifti_single', '.nii'),
111    ('nifti_pair', '.img', '.hdr'),
112    ('minc', '.mnc'),
113    ('mgh', '.mgh'),
114    ('mgz', '.mgz'),
115    ('par', '.par'),
116    ('brik', '.brik')
117))
118
119# Image classes known to require spatial axes to be first in index ordering.
120# When adding an image class, consider whether the new class should be listed
121# here.
122KNOWN_SPATIAL_FIRST = (Nifti1Pair, Nifti1Image, Nifti2Pair, Nifti2Image,
123                       Spm2AnalyzeImage, Spm99AnalyzeImage, AnalyzeImage,
124                       MGHImage, PARRECImage, AFNIImage)
125
126
127def spatial_axes_first(img):
128    """ True if spatial image axes for `img` always preceed other axes
129
130    Parameters
131    ----------
132    img : object
133        Image object implementing at least ``shape`` attribute.
134
135    Returns
136    -------
137    spatial_axes_first : bool
138        True if image only has spatial axes (number of axes < 4) or image type
139        known to have spatial axes preceeding other axes.
140    """
141    if len(img.shape) < 4:
142        return True
143    return type(img) in KNOWN_SPATIAL_FIRST
144