Skip to content

Commit 0b8286d

Browse files
author
cindeem
committed
NF: added full datatypes, filetypes descriptions , documentation
1 parent 407a0e5 commit 0b8286d

File tree

2 files changed

+82
-20
lines changed

2 files changed

+82
-20
lines changed

nibabel/ecat.py

Lines changed: 78 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,35 @@
151151
('fill', np.uint16)]
152152
subhdr_dtype = np.dtype(subheader_dtd)
153153

154-
155-
154+
# Ecat Data Types
155+
_dtdefs = ( # code, name, equivalent dtype
156+
(1, 'ECAT7_BYTE', np.uint8),
157+
(2, 'ECAT7_VAXI2', np.int16),
158+
(3, 'ECAT7_VAXI4', np.float32),
159+
(4, 'ECAT7_VAXR4', np.float32),
160+
(5, 'ECAT7_IEEER4', np.float32),
161+
(6, 'ECAT7_SUNI2', np.uint16),
162+
(7, 'ECAT7_SUNI4', np.int32))
163+
data_type_codes = make_dt_codes(_dtdefs)
164+
165+
166+
# Matrix File Types
167+
ft_defs = ( # code, name
168+
(0, 'ECAT7_UNKNOWN'),
169+
(1, 'ECAT7_2DSCAN'),
170+
(2, 'ECAT7_IMAGE16'),
171+
(3, 'ECAT7_ATTEN'),
172+
(4, 'ECAT7_2DNORM'),
173+
(5, 'ECAT7_POLARMAP'),
174+
(6, 'ECAT7_VOLUME8'),
175+
(7, 'ECAT7_VOLUME16'),
176+
(8, 'ECAT7_PROJ'),
177+
(9, 'ECAT7_PROJ16'),
178+
(10, 'ECAT7_IMAGE8'),
179+
(11, 'ECAT7_3DSCAN'),
180+
(12, 'ECAT7_3DSCAN8'),
181+
(13, 'ECAT7_3DNORM'),
182+
(14, 'ECAT7_3DSCANFIT'))
156183

157184
class EcatHeader(object):
158185
"""Class for basic Ecat PET header
@@ -171,6 +198,7 @@ class EcatHeader(object):
171198
"""
172199

173200
_dtype = hdr_dtype
201+
_ft_defs = ft_defs
174202

175203
def __init__(self,
176204
fileobj=None,
@@ -317,6 +345,15 @@ def __setitem__(self, item, value):
317345
'''
318346
self._header_data[item] = value
319347

348+
def get_filetype(self):
349+
""" gets type of ECAT Matrix File from
350+
code stored in header"""
351+
ft_codes = dict(self._ft_defs)
352+
code = self._header_data['file_type'].item()
353+
if not ft_codes.has_key(code):
354+
raise KeyError('Ecat Filetype CODE %d not recognized'%code)
355+
return ft_codes[code]
356+
320357
def __iter__(self):
321358
return iter(self.keys())
322359

@@ -338,9 +375,10 @@ class EcatMlist(object):
338375
def __init__(self,fileobj, hdr):
339376
""" gets list of frames and subheaders in pet file
340377
341-
Parameteres
378+
Parameters
342379
-----------
343-
fileobj : ECAT file <filename>.v
380+
fileobj : ECAT file <filename>.v fileholder or file object
381+
with read, seek methods
344382
345383
Returns
346384
-------
@@ -389,15 +427,29 @@ def get_mlist(self, fileobj):
389427

390428
def get_frame_order(self):
391429
"""Returns the order of the frames in the file
430+
Useful as sometimes Frames are not stored in the file in
431+
chronological order, and can be used to extract frames
432+
in correct order
392433
393434
Returns
394435
-------
436+
id_dict: dict mapping frame number -> [mlist_row, mlist_id]
395437
396-
frame_dict: dict mapping mlist id -> frame number
397-
398-
id_dict: dict mapping frame number -> mlist id
438+
(where mlist id is value in the first column of the mlist matrix )
399439
400-
(where mlist id is in the first column of the mlist matrix )
440+
Examples
441+
--------
442+
>>> img = ecat.load('singleframe.v')
443+
>>> mlist = img._mlist
444+
>>> mlist.get_frame_order()
445+
{0: [0, 16842758.0]}
446+
>>> img2 = ecat.load('multiframe.v')
447+
>>> mlist2 = img2._mlist
448+
>>> mlist2.get_frame_order()
449+
{0: [0, 16842754.0],
450+
1: [1, 16842755.0],
451+
2: [2, 16842756.0],
452+
3: [3, 16842757.0]}
401453
"""
402454
mlist = self._mlist
403455
ind = mlist[:,0] > 0
@@ -412,14 +464,26 @@ def get_frame_order(self):
412464

413465
return id_dict
414466

415-
416-
417-
418467
class EcatSubHeader(object):
419-
"""parses the subheaders in the ecat (.v) file """
468+
420469
_subhdrdtype = subhdr_dtype
470+
_data_type_codes = data_type_codes
421471

422472
def __init__(self, hdr, mlist, fileobj):
473+
"""parses the subheaders in the ecat (.v) file
474+
there is one subheader for each frame in the ecat file
475+
476+
Parameters
477+
-----------
478+
hdr : EcatHeader
479+
480+
mlist : EcatMlist
481+
482+
fileobj : ECAT file <filename>.v fileholder or file object
483+
with read, seek methods
484+
485+
486+
"""
423487
self._header = hdr
424488
self.endianness = hdr.endianness
425489
self._mlist = mlist
@@ -511,13 +575,8 @@ def get_zooms(self,frame=0):
511575

512576

513577
def _get_data_dtype(self, frame):
514-
dt = self.subheaders[frame]['data_type']
515-
if dt == 5:
516-
return np.dtype('float')
517-
elif dt == 6:
518-
return np.dtype('ushort')
519-
else:
520-
return None
578+
dtcode = self.subheaders[frame]['data_type'].item()
579+
return self._data_type_codes.dtype[dtcode]
521580

522581
def _get_frame_offset(self, frame=0):
523582
mlist = self._mlist._mlist

nibabel/tests/test_ecat.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,12 @@ def test_empty(self):
4040
yield assert_true(hdr['ecat_calibration_factor'] == 1.0)
4141

4242
def test_dtype(self):
43+
#dtype not specified in header, only in subheaders
4344
hdr = self.header_class()
4445
yield assert_raises(NotImplementedError,
4546
hdr.get_data_dtype)
47+
def test_filetype(self):
48+
hdr = self.header_class()
4649

4750
def test_copy(self):
4851
hdr = self.header_class()
@@ -109,7 +112,7 @@ def test_subheader(self):
109112
np.array([ 2.20241979, 2.20241979, 3.125, 1.]))
110113
yield assert_equal(self.subhdr.get_zooms()[0], 2.20241978764534)
111114
yield assert_equal(self.subhdr.get_zooms()[2], 3.125)
112-
yield assert_equal(self.subhdr._get_data_dtype(0),np.dtype('ushort'))
115+
yield assert_equal(self.subhdr._get_data_dtype(0),np.uint16)
113116
yield assert_equal(self.subhdr._get_frame_offset(), 1536)
114117
dat = self.subhdr.raw_data_from_fileobj()
115118
yield assert_equal(dat.shape, self.subhdr.get_shape())

0 commit comments

Comments
 (0)