1
2
3
4
5
6
7
8
9 """Dataset that gets its samples from a NIfTI file"""
10
11 __docformat__ = 'restructuredtext'
12
13 from mvpa.base import externals
14 externals.exists('nifti', raiseException=True)
15
16 import numpy as N
17 from mvpa.misc.copy import deepcopy
18
19
20 oldname = __name__
21
22 __name__ = 'iaugf9zrkjsbdv89'
23 from nifti import NiftiImage
24
25 __name__ = oldname
26
27 from mvpa.datasets.base import Dataset
28 from mvpa.datasets.mapped import MappedDataset
29 from mvpa.datasets.event import EventDataset
30 from mvpa.mappers.base import CombinedMapper
31 from mvpa.mappers.metric import DescreteMetric, cartesianDistance
32 from mvpa.mappers.array import DenseArrayMapper
33 from mvpa.base import warning
34
35
37 """Load/access NIfTI data from files or instances.
38
39 :Parameter:
40 src: str | NiftiImage
41 Filename of a NIfTI image or a `NiftiImage` instance.
42
43 :Returns:
44 NiftiImage | None
45 If the source is not supported None is returned.
46 """
47 nifti = None
48
49
50 if isinstance(src, str):
51
52 try:
53 nifti = NiftiImage(src)
54 except RuntimeError, e:
55 warning("ERROR: NiftiDatasets: Cannot open NIfTI file %s" \
56 % src)
57 raise e
58 elif isinstance(src, NiftiImage):
59
60 nifti = src
61
62 return nifti
63
64
66 """Convenience function to extract the data array from a NiftiImage
67
68 This function will make use of advanced features of PyNIfTI to prevent
69 unnecessary copying if a sufficent version is available.
70 """
71 if externals.exists('nifti >= 0.20081017.1'):
72 return nim.data
73 else:
74 return nim.asarray()
75
76
78 """Dataset loading its samples from a NIfTI image or file.
79
80 Samples can be loaded from a NiftiImage instance or directly from a NIfTI
81 file. This class stores all relevant information from the NIfTI file header
82 and provides information about the metrics and neighborhood information of
83 all voxels.
84
85 Most importantly it allows to map data back into the original data space
86 and format via :meth:`~mvpa.datasets.nifti.NiftiDataset.map2Nifti`.
87
88 This class allows for convenient pre-selection of features by providing a
89 mask to the constructor. Only non-zero elements from this mask will be
90 considered as features.
91
92 NIfTI files are accessed via PyNIfTI. See
93 http://niftilib.sourceforge.net/pynifti/ for more information about
94 pynifti.
95 """
96
97
98 - def __init__(self, samples=None, mask=None, dsattr=None, **kwargs):
99 """
100 :Parameters:
101 samples: str | NiftiImage
102 Filename of a NIfTI image or a `NiftiImage` instance.
103 mask: str | NiftiImage
104 Filename of a NIfTI image or a `NiftiImage` instance.
105 """
106
107 if not dsattr is None and dsattr.has_key('mapper'):
108 MappedDataset.__init__(self,
109 samples=samples,
110 dsattr=dsattr,
111 **kwargs)
112 return
113
114
115
116
117
118
119
120 niftisamples = getNiftiFromAnySource(samples)
121 samples = niftisamples.data
122
123
124
125
126
127
128 dsattr = {'niftihdr': niftisamples.header}
129
130
131
132
133 niftimask = getNiftiFromAnySource(mask)
134 if not niftimask is None:
135 mask = getNiftiData(niftimask)
136
137
138
139
140
141
142
143 elementsize = [i for i in reversed(niftisamples.voxdim)]
144 mapper = DenseArrayMapper(mask=mask, shape=samples.shape[1:],
145 metric=DescreteMetric(elementsize=elementsize,
146 distance_function=cartesianDistance))
147
148 MappedDataset.__init__(self,
149 samples=samples,
150 mapper=mapper,
151 dsattr=dsattr,
152 **kwargs)
153
154
156 """Maps a data vector into the dataspace and wraps it with a
157 NiftiImage. The header data of this object is used to initialize
158 the new NiftiImage.
159
160 :Parameters:
161 data : ndarray or Dataset
162 The data to be wrapped into NiftiImage. If None (default), it
163 would wrap samples of the current dataset. If it is a Dataset
164 instance -- takes its samples for mapping
165 """
166 if data is None:
167 data = self.samples
168 elif isinstance(data, Dataset):
169
170 data = data.samples
171 dsarray = self.mapper.reverse(data)
172 return NiftiImage(dsarray, self.niftihdr)
173
174
175 niftihdr = property(fget=lambda self: self._dsattr['niftihdr'],
176 doc='Access to the NIfTI header dictionary.')
177
178
179
181 """Dataset with event-defined samples from a NIfTI timeseries image.
182
183 This is a convenience dataset to facilitate the analysis of event-related
184 fMRI datasets. Boxcar-shaped samples are automatically extracted from the
185 full timeseries using :class:`~mvpa.misc.support.Event` definition lists.
186 For each event all volumes covering that particular event in time
187 (including partial coverage) are used to form the corresponding sample.
188
189 The class supports the conversion of events defined in 'realtime' into the
190 descrete temporal space defined by the NIfTI image. Moreover, potentially
191 varying offsets between true event onset and timepoint of the first selected
192 volume can be stored as an additional feature in the dataset.
193
194 Additionally, the dataset supports masking. This is done similar to the
195 masking capabilities of :class:`~mvpa.datasets.nifti.NiftiDataset`. However,
196 the mask can either be of the same shape as a single NIfTI volume, or
197 can be of the same shape as the generated boxcar samples, i.e.
198 a samples consisting of three volumes with 24 slices and 64x64 inplane
199 resolution needs a mask with shape (3, 24, 64, 64). In the former case the
200 mask volume is automatically expanded to be identical in a volumes of the
201 boxcar.
202 """
203 - def __init__(self, samples=None, events=None, mask=None, evconv=False,
204 storeoffset=False, tr=None, **kwargs):
205 """
206 :Paramaters:
207 evconv: bool
208 Convert event definitions using `onset` and `duration` in some
209 temporal unit into #sample notation.
210 storeoffset: Bool
211 Whether to store temproal offset information when converting
212 Events into descrete time. Only considered when evconv == True.
213 tr: float
214 Temporal distance of two adjacent NIfTI volumes. This can be used
215 to override the corresponding value in the NIfTI header.
216 """
217
218 if events is None:
219 EventDataset.__init__(self, samples=samples, events=events,
220 mask=mask, **kwargs)
221 return
222
223 nifti = getNiftiFromAnySource(samples)
224
225 samples = nifti.data
226
227
228
229
230
231
232 dsattr = {'niftihdr': nifti.header}
233
234
235
236
237 elementsize = [i for i in reversed(nifti.voxdim)]
238
239
240
241 metric = DescreteMetric(elementsize=elementsize,
242 distance_function=cartesianDistance)
243
244
245 if evconv:
246
247 dt = nifti.rtime
248
249 if not tr is None:
250 dt = tr
251 if dt == 0:
252 raise ValueError, "'dt' cannot be zero when converting Events"
253
254 events = [ev.asDescreteTime(dt, storeoffset) for ev in events]
255 else:
256
257 events = deepcopy(events)
258
259
260
261 for ev in events:
262 oldonset = ev['onset']
263 oldduration = ev['duration']
264 ev['onset'] = int(ev['onset'])
265 ev['duration'] = int(ev['duration'])
266 if not oldonset == ev['onset'] \
267 or not oldduration == ev['duration']:
268 warning("Loosing information during automatic integer "
269 "conversion of EVs. Consider an explicit conversion"
270 " by setting `evconv` in ERNiftiDataset().")
271
272
273 if not mask is None:
274 mask_nim = getNiftiFromAnySource(mask)
275 if not mask_nim is None:
276 mask = getNiftiData(mask_nim)
277 else:
278 raise ValueError, "Cannot load mask from '%s'" % mask
279
280
281 EventDataset.__init__(self, samples=samples, events=events,
282 mask=mask, dametric=metric, dsattr=dsattr,
283 **kwargs)
284
285
287 """Maps a data vector into the dataspace and wraps it with a
288 NiftiImage. The header data of this object is used to initialize
289 the new NiftiImage.
290
291 .. note::
292 Only the features corresponding to voxels are mapped back -- not
293 any additional features passed via the Event definitions.
294
295 :Parameters:
296 data : ndarray or Dataset
297 The data to be wrapped into NiftiImage. If None (default), it
298 would wrap samples of the current dataset. If it is a Dataset
299 instance -- takes its samples for mapping
300 """
301 if data is None:
302 data = self.samples
303 elif isinstance(data, Dataset):
304
305 data = data.samples
306
307 mr = self.mapper.reverse(data)
308
309
310 if isinstance(self.mapper, CombinedMapper):
311
312 mr = mr[0]
313 else:
314 pass
315
316 return NiftiImage(mr, self.niftihdr)
317
318
319 niftihdr = property(fget=lambda self: self._dsattr['niftihdr'],
320 doc='Access to the NIfTI header dictionary.')
321