Skip to content

Commit 93a4bf5

Browse files
committed
RF: remove EcatMlist class, write mlist as int32
Remove EcatMlist class for simplicity, replace with functions on mlist array. The CTI code has the mlist as an int32 array, use int32s throughout, and hope.
1 parent ab6f30b commit 93a4bf5

File tree

2 files changed

+67
-115
lines changed

2 files changed

+67
-115
lines changed

nibabel/ecat.py

Lines changed: 28 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ def get_frame_order(mlist):
405405
>>> ecat_file = os.path.join(nibabel_dir,'tests','data','tinypet.v')
406406
>>> img = ecat.load(ecat_file)
407407
>>> mlist = img.get_mlist()
408-
>>> mlist.get_frame_order()
408+
>>> get_frame_order(mlist)
409409
{0: [0, 16842758]}
410410
"""
411411
ids = mlist[:, 0].copy()
@@ -449,7 +449,7 @@ def get_series_framenumbers(mlist):
449449
>>> ecat_file = os.path.join(nibabel_dir,'tests','data','tinypet.v')
450450
>>> img = ecat.load(ecat_file)
451451
>>> mlist = img.get_mlist()
452-
>>> mlist.get_series_framenumbers()
452+
>>> get_series_framenumbers(mlist)
453453
{0: 1}
454454
"""
455455
nframes = len(mlist)
@@ -502,46 +502,6 @@ def read_subheaders(fileobj, mlist, endianness):
502502
return subheaders
503503

504504

505-
class EcatMlist(object):
506-
# Can we do without this object, just using the functions?
507-
508-
def __init__(self,fileobj, hdr):
509-
""" gets list of frames and subheaders in pet file
510-
511-
Container for Ecat mlist
512-
513-
Data for mlist is numpy array shape (frames, 4)
514-
515-
Columns are:
516-
517-
* 0 - Matrix identifier.
518-
* 1 - subheader block number
519-
* 2 - Last block number of matrix data block.
520-
* 3 - Matrix status:
521-
* 1 - exists - rw
522-
* 2 - exists - ro
523-
* 3 - matrix deleted
524-
525-
A block above is 512 bytes in the image data file
526-
527-
Parameters
528-
-----------
529-
fileobj : file-like
530-
ECAT file <filename>.v fileholder or file object with read, seek
531-
methods
532-
"""
533-
self.hdr = hdr
534-
self._mlist = np.zeros((hdr['num_frames'], 4), dtype='uint32')
535-
mlist_data = read_mlist(fileobj, hdr.endianness)
536-
self._mlist[:len(mlist_data)] = mlist_data
537-
538-
def get_frame_order(self):
539-
return get_frame_order(self._mlist)
540-
541-
def get_series_framenumbers(self):
542-
return get_series_framenumbers(self._mlist)
543-
544-
545505
class EcatSubHeader(object):
546506

547507
_subhdrdtype = subhdr_dtype
@@ -554,17 +514,17 @@ def __init__(self, hdr, mlist, fileobj):
554514
Parameters
555515
-----------
556516
hdr : EcatHeader
557-
558-
mlist : EcatMlist
559-
517+
ECAT main header
518+
mlist : array shape (N, 4)
519+
Matrix list
560520
fileobj : ECAT file <filename>.v fileholder or file object
561521
with read, seek methods
562522
"""
563523
self._header = hdr
564524
self.endianness = hdr.endianness
565525
self._mlist = mlist
566526
self.fileobj = fileobj
567-
self.subheaders = read_subheaders(fileobj, mlist._mlist, hdr.endianness)
527+
self.subheaders = read_subheaders(fileobj, mlist, hdr.endianness)
568528

569529
def get_shape(self, frame=0):
570530
""" returns shape of given frame"""
@@ -576,11 +536,9 @@ def get_shape(self, frame=0):
576536

577537
def get_nframes(self):
578538
"""returns number of frames"""
579-
mlist = self._mlist
580-
framed = mlist.get_frame_order()
539+
framed = get_frame_order(self._mlist)
581540
return len(framed)
582541

583-
584542
def _check_affines(self):
585543
"""checks if all affines are equal across frames"""
586544
nframes = self.get_nframes()
@@ -625,9 +583,7 @@ def _get_data_dtype(self, frame):
625583
return self._data_type_codes.dtype[dtcode]
626584

627585
def _get_frame_offset(self, frame=0):
628-
mlist = self._mlist._mlist
629-
offset = (mlist[frame][1]) * BLOCK_SIZE
630-
return int(offset)
586+
return int(self._mlist[frame][1] * BLOCK_SIZE)
631587

632588
def _get_oriented_data(self, raw_data, orientation=None):
633589
'''
@@ -725,7 +681,7 @@ def __array__(self):
725681
(``__getitem__``) below, or ``subheader.data_from_fileobj(frame)``
726682
'''
727683
data = np.empty(self.shape)
728-
frame_mapping = self._subheader._mlist.get_frame_order()
684+
frame_mapping = get_frame_order(self._subheader._mlist)
729685
for i in sorted(frame_mapping):
730686
data[:,:,:,i] = self._subheader.data_from_fileobj(frame_mapping[i][0])
731687
return data
@@ -737,7 +693,7 @@ def __getitem__(self, sliceobj):
737693
# Indices into sliceobj referring to image axes
738694
ax_inds = [i for i, obj in enumerate(sliceobj) if not obj is None]
739695
assert len(ax_inds) == len(self.shape)
740-
frame_mapping = self._subheader._mlist.get_frame_order()
696+
frame_mapping = get_frame_order(self._subheader._mlist)
741697
# Analyze index for 4th axis
742698
slice3 = sliceobj[ax_inds[3]]
743699
# We will load volume by volume. Make slicer into volume by dropping
@@ -769,7 +725,6 @@ class EcatImage(SpatialImage):
769725
_header = EcatHeader
770726
header_class = _header
771727
_subheader = EcatSubHeader
772-
_mlist = EcatMlist
773728
files_types = (('image', '.v'), ('header', '.v'))
774729

775730
ImageArrayProxy = EcatImageArrayProxy
@@ -795,8 +750,8 @@ def __init__(self, dataobj, affine, header,
795750
meta data for this image format
796751
subheader : None or subheader instance
797752
meta data for each sub-image for frame in the image
798-
mlist : None or mlist instance
799-
meta data with array giving offset and order of data in file
753+
mlist : None or array
754+
Matrix list array giving offset and order of data in file
800755
extra : None or mapping, optional
801756
metadata associated with this image that cannot be
802757
stored in header or subheader
@@ -871,7 +826,8 @@ def shape(self):
871826
return(x, y, z, nframes)
872827

873828
def get_mlist(self):
874-
""" get access to the mlist """
829+
""" get access to the mlist
830+
"""
875831
return self._mlist
876832

877833
def get_subheaders(self):
@@ -904,29 +860,29 @@ def from_file_map(klass, file_map):
904860
header = klass._header.from_fileobj(hdr_fid)
905861
hdr_copy = header.copy()
906862
### LOAD MLIST
907-
mlist = klass._mlist(hdr_fid, hdr_copy)
863+
mlist = np.zeros((header['num_frames'], 4), dtype=np.int32)
864+
mlist_data = read_mlist(hdr_fid, hdr_copy.endianness)
865+
mlist[:len(mlist_data)] = mlist_data
908866
### LOAD SUBHEADERS
909-
subheaders = klass._subheader(hdr_copy,
910-
mlist,
911-
hdr_fid)
867+
subheaders = klass._subheader(hdr_copy, mlist, hdr_fid)
912868
### LOAD DATA
913869
## Class level ImageArrayProxy
914870
data = klass.ImageArrayProxy(subheaders)
915-
916871
## Get affine
917872
if not subheaders._check_affines():
918-
warnings.warn('Affines different across frames, loading affine from FIRST frame',
919-
UserWarning )
873+
warnings.warn('Affines different across frames, loading affine '
874+
'from FIRST frame', UserWarning )
920875
aff = subheaders.get_frame_affine()
921-
img = klass(data, aff, header, subheaders, mlist, extra=None, file_map = file_map)
876+
img = klass(data, aff, header, subheaders, mlist,
877+
extra=None, file_map=file_map)
922878
return img
923879

924880
def _get_empty_dir(self):
925881
'''
926882
Get empty directory entry of the form
927883
[numAvail, nextDir, previousDir, numUsed]
928884
'''
929-
return np.array([31, 2, 0, 0], dtype=np.uint32)
885+
return np.array([31, 2, 0, 0], dtype=np.int32)
930886

931887
def _write_data(self, data, stream, pos, dtype=None, endianness=None):
932888
'''
@@ -962,9 +918,11 @@ def to_file_map(self, file_map=None):
962918
if file_map is None:
963919
file_map = self.file_map
964920

921+
# It appears to be necessary to load the data before saving even if the
922+
# data itself is not used.
965923
data = self.get_data()
966924
hdr = self.get_header()
967-
mlist = self.get_mlist()._mlist
925+
mlist = self._mlist
968926
subheaders = self.get_subheaders()
969927
dir_pos = 512
970928
entry_pos = dir_pos + 16 #528
@@ -999,8 +957,7 @@ def to_file_map(self, file_map=None):
999957
self._write_data(image, imgf, pos+2, endianness='>')
1000958

1001959
#Move to dictionnary offset and write dictionnary entry
1002-
self._write_data(mlist[index], imgf, entry_pos,
1003-
np.uint32, endianness='>')
960+
self._write_data(mlist[index], imgf, entry_pos, endianness='>')
1004961

1005962
entry_pos = entry_pos + 16
1006963

@@ -1022,7 +979,7 @@ def to_file_map(self, file_map=None):
1022979
#Fill directory with empty data until directory is full
1023980
while current_dir[0] > 0:
1024981
entry_pos = dir_pos + 16 + (16 * current_dir[3])
1025-
self._write_data(np.array([0,0,0,0]), imgf, entry_pos, np.uint32)
982+
self._write_data(np.zeros(4, dtype=np.int32), imgf, entry_pos)
1026983
current_dir[0] = current_dir[0] - 1
1027984
current_dir[3] = current_dir[3] + 1
1028985

nibabel/tests/test_ecat.py

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
import numpy as np
1414

1515
from ..openers import Opener
16-
from ..ecat import EcatHeader, EcatMlist, EcatSubHeader, EcatImage
16+
from ..ecat import (EcatHeader, EcatSubHeader, EcatImage, read_mlist,
17+
get_frame_order, get_series_framenumbers)
1718

1819
from unittest import TestCase
19-
from nose.tools import (assert_true, assert_false, assert_equal,
20-
assert_not_equal, assert_raises)
20+
from nose.tools import (assert_true, assert_false, assert_equal, assert_raises)
2121

2222
from numpy.testing import assert_array_equal, assert_array_almost_equal
2323

@@ -79,13 +79,12 @@ def test_from_eg_file(self):
7979

8080
class TestEcatMlist(TestCase):
8181
header_class = EcatHeader
82-
mlist_class = EcatMlist
8382
example_file = ecat_file
8483

8584
def test_mlist(self):
8685
fid = open(self.example_file, 'rb')
8786
hdr = self.header_class.from_fileobj(fid)
88-
mlist = self.mlist_class(fid, hdr)
87+
mlist = read_mlist(fid, hdr.endianness)
8988
fid.seek(0)
9089
fid.seek(512)
9190
dat=fid.read(128*32)
@@ -95,68 +94,64 @@ def test_mlist(self):
9594
fid.close()
9695
#tests
9796
assert_true(mats['matlist'][0,0] + mats['matlist'][0,3] == 31)
98-
assert_true(mlist.get_frame_order()[0][0] == 0)
99-
assert_true(mlist.get_frame_order()[0][1] == 16842758.0)
97+
assert_true(get_frame_order(mlist)[0][0] == 0)
98+
assert_true(get_frame_order(mlist)[0][1] == 16842758.0)
10099
# test badly ordered mlist
101-
badordermlist = mlist
102-
badordermlist._mlist = np.array([[ 1.68427540e+07, 3.00000000e+00,
103-
1.20350000e+04, 1.00000000e+00],
104-
[ 1.68427530e+07, 1.20360000e+04,
105-
2.40680000e+04, 1.00000000e+00],
106-
[ 1.68427550e+07, 2.40690000e+04,
107-
3.61010000e+04, 1.00000000e+00],
108-
[ 1.68427560e+07, 3.61020000e+04,
109-
4.81340000e+04, 1.00000000e+00],
110-
[ 1.68427570e+07, 4.81350000e+04,
111-
6.01670000e+04, 1.00000000e+00],
112-
[ 1.68427580e+07, 6.01680000e+04,
113-
7.22000000e+04, 1.00000000e+00]])
100+
badordermlist = np.array([[1.68427540e+07, 3.00000000e+00,
101+
1.20350000e+04, 1.00000000e+00],
102+
[1.68427530e+07, 1.20360000e+04,
103+
2.40680000e+04, 1.00000000e+00],
104+
[1.68427550e+07, 2.40690000e+04,
105+
3.61010000e+04, 1.00000000e+00],
106+
[1.68427560e+07, 3.61020000e+04,
107+
4.81340000e+04, 1.00000000e+00],
108+
[1.68427570e+07, 4.81350000e+04,
109+
6.01670000e+04, 1.00000000e+00],
110+
[1.68427580e+07, 6.01680000e+04,
111+
7.22000000e+04, 1.00000000e+00]])
114112
with suppress_warnings(): # STORED order
115-
assert_true(badordermlist.get_frame_order()[0][0] == 1)
113+
assert_true(get_frame_order(badordermlist)[0][0] == 1)
116114

117115
def test_mlist_errors(self):
118116
fid = open(self.example_file, 'rb')
119117
hdr = self.header_class.from_fileobj(fid)
120118
hdr['num_frames'] = 6
121-
mlist = self.mlist_class(fid, hdr)
122-
mlist._mlist = np.array([[ 1.68427540e+07, 3.00000000e+00,
123-
1.20350000e+04, 1.00000000e+00],
124-
[ 1.68427530e+07, 1.20360000e+04,
125-
2.40680000e+04, 1.00000000e+00],
126-
[ 1.68427550e+07, 2.40690000e+04,
127-
3.61010000e+04, 1.00000000e+00],
128-
[ 1.68427560e+07, 3.61020000e+04,
129-
4.81340000e+04, 1.00000000e+00],
130-
[ 1.68427570e+07, 4.81350000e+04,
131-
6.01670000e+04, 1.00000000e+00],
132-
[ 1.68427580e+07, 6.01680000e+04,
133-
7.22000000e+04, 1.00000000e+00]])
119+
mlist = read_mlist(fid, hdr.endianness)
120+
mlist = np.array([[1.68427540e+07, 3.00000000e+00,
121+
1.20350000e+04, 1.00000000e+00],
122+
[1.68427530e+07, 1.20360000e+04,
123+
2.40680000e+04, 1.00000000e+00],
124+
[1.68427550e+07, 2.40690000e+04,
125+
3.61010000e+04, 1.00000000e+00],
126+
[1.68427560e+07, 3.61020000e+04,
127+
4.81340000e+04, 1.00000000e+00],
128+
[1.68427570e+07, 4.81350000e+04,
129+
6.01670000e+04, 1.00000000e+00],
130+
[1.68427580e+07, 6.01680000e+04,
131+
7.22000000e+04, 1.00000000e+00]])
134132
with suppress_warnings(): # STORED order
135-
series_framenumbers = mlist.get_series_framenumbers()
133+
series_framenumbers = get_series_framenumbers(mlist)
136134
# first frame stored was actually 2nd frame acquired
137135
assert_true(series_framenumbers[0] == 2)
138136
order = [series_framenumbers[x] for x in sorted(series_framenumbers)]
139137
# true series order is [2,1,3,4,5,6], note counting starts at 1
140138
assert_true(order == [2, 1, 3, 4, 5, 6])
141-
mlist._mlist[0,0] = 0
139+
mlist[0,0] = 0
142140
with suppress_warnings():
143-
frames_order = mlist.get_frame_order()
141+
frames_order = get_frame_order(mlist)
144142
neworder =[frames_order[x][0] for x in sorted(frames_order)]
145143
assert_true(neworder == [1, 2, 3, 4, 5])
146144
with suppress_warnings():
147-
assert_raises(IOError,
148-
mlist.get_series_framenumbers)
149-
150-
145+
assert_raises(IOError, get_series_framenumbers, mlist)
146+
151147

152148
class TestEcatSubHeader(TestCase):
153149
header_class = EcatHeader
154-
mlist_class = EcatMlist
155150
subhdr_class = EcatSubHeader
156151
example_file = ecat_file
157152
fid = open(example_file, 'rb')
158153
hdr = header_class.from_fileobj(fid)
159-
mlist = mlist_class(fid, hdr)
154+
mlist = read_mlist(fid, hdr.endianness)
160155
subhdr = subhdr_class(hdr, mlist, fid)
161156

162157
def test_subheader_size(self):
@@ -269,5 +264,5 @@ def test_data_regression(self):
269264

270265
def test_mlist_regreesion(self):
271266
# Test mlist is as same as for nibabel 1.3.0
272-
assert_array_equal(self.img.get_mlist()._mlist,
267+
assert_array_equal(self.img.get_mlist(),
273268
[[16842758, 3, 3011, 1]])

0 commit comments

Comments
 (0)