Skip to content

Commit d270889

Browse files
committed
Initial commit
1 parent 33b8e51 commit d270889

File tree

1 file changed

+210
-0
lines changed

1 file changed

+210
-0
lines changed

mhd_utils.py

+210
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
#!/usr/bin/env python
2+
3+
#
4+
# Original Version: bjian 2008/10/27
5+
# 3-D extension: PJackson 2013/06/06
6+
# More datatypes, Multiple Channels, Python 3, ...: Peter Fischer
7+
#
8+
9+
from __future__ import division, print_function
10+
import os
11+
import numpy
12+
import array
13+
14+
15+
def read_meta_header(filename):
16+
"""Return a dictionary of meta data from meta header file"""
17+
fileIN = open(filename, "r")
18+
line = fileIN.readline()
19+
20+
meta_dict = {}
21+
tag_set = []
22+
tag_set.extend(['ObjectType', 'NDims', 'DimSize', 'ElementType', 'ElementDataFile', 'ElementNumberOfChannels'])
23+
tag_set.extend(['BinaryData', 'BinaryDataByteOrderMSB', 'CompressedData', 'CompressedDataSize'])
24+
tag_set.extend(['Offset', 'CenterOfRotation', 'AnatomicalOrientation', 'ElementSpacing', 'TransformMatrix'])
25+
tag_set.extend(['Comment', 'SeriesDescription', 'AcquisitionDate', 'AcquisitionTime', 'StudyDate', 'StudyTime'])
26+
27+
tag_flag = [False] * len(tag_set)
28+
while line:
29+
tags = str.split(line, '=')
30+
# print(tags[0])
31+
for i in range(len(tag_set)):
32+
tag = tag_set[i]
33+
if (str.strip(tags[0]) == tag) and (not tag_flag[i]):
34+
# print(tags[1])
35+
content = str.strip(tags[1])
36+
if tag in ['ElementSpacing', 'Offset', 'CenterOfRotation', 'TransformMatrix']:
37+
meta_dict[tag] = [float(s) for s in content.split()]
38+
elif tag in ['NDims', 'ElementNumberOfChannels']:
39+
meta_dict[tag] = int(content)
40+
elif tag in ['DimSize']:
41+
meta_dict[tag] = [int(s) for s in content.split()]
42+
elif tag in ['BinaryData', 'BinaryDataByteOrderMSB', 'CompressedData']:
43+
if content == "True":
44+
meta_dict[tag] = True
45+
else:
46+
meta_dict[tag] = False
47+
else:
48+
meta_dict[tag] = content
49+
tag_flag[i] = True
50+
line = fileIN.readline()
51+
# print(comment)
52+
fileIN.close()
53+
return meta_dict
54+
55+
56+
def load_raw_data_with_mhd(filename):
57+
meta_dict = read_meta_header(filename)
58+
dim = int(meta_dict['NDims'])
59+
if "ElementNumberOfChannels" in meta_dict:
60+
element_channels = int(meta_dict["ElementNumberOfChannels"])
61+
else:
62+
element_channels = 1
63+
# print(dim)
64+
# print(meta_dict['ElementType'])
65+
if meta_dict['ElementType'] == 'MET_FLOAT':
66+
array_string = 'f'
67+
numpy_type = numpy.float32
68+
elif meta_dict['ElementType'] == 'MET_DOUBLE':
69+
array_string = 'd'
70+
numpy_type = numpy.float64
71+
elif meta_dict['ElementType'] == 'MET_CHAR':
72+
array_string = 'b'
73+
numpy_type = numpy.byte
74+
elif meta_dict['ElementType'] == 'MET_UCHAR':
75+
array_string = 'B'
76+
numpy_type = numpy.ubyte
77+
elif meta_dict['ElementType'] == 'MET_SHORT':
78+
array_string = 'h'
79+
numpy_type = numpy.short
80+
elif meta_dict['ElementType'] == 'MET_USHORT':
81+
array_string = 'H'
82+
numpy_type = numpy.ushort
83+
elif meta_dict['ElementType'] == 'MET_INT':
84+
array_string = 'i'
85+
numpy_type = numpy.int32
86+
elif meta_dict['ElementType'] == 'MET_UINT':
87+
array_string = 'I'
88+
numpy_type = numpy.uint32
89+
else:
90+
raise NotImplementedError("ElementType " + meta_dict['ElementType'] + " not understood.")
91+
arr = list(meta_dict['DimSize'])
92+
# print(arr)
93+
volume = numpy.prod(arr[0:dim - 1])
94+
# print(volume)
95+
pwd = os.path.split(filename)[0]
96+
if pwd:
97+
data_file = pwd + '/' + meta_dict['ElementDataFile']
98+
else:
99+
data_file = meta_dict['ElementDataFile']
100+
# print(data_file)
101+
fid = open(data_file, 'rb')
102+
binvalues = array.array(array_string)
103+
binvalues.fromfile(fid, volume * arr[dim - 1] * element_channels)
104+
fid.close()
105+
data = numpy.array(binvalues, numpy_type)
106+
data = numpy.reshape(data, (arr[dim - 1], volume, element_channels))
107+
# Begin 3D fix
108+
arr.reverse()
109+
if element_channels > 1:
110+
data = data.reshape(arr + [element_channels])
111+
else:
112+
data = data.reshape(arr)
113+
# End 3D fix
114+
return (data, meta_dict)
115+
116+
117+
def write_meta_header(filename, meta_dict):
118+
header = ''
119+
# do not use tags = meta_dict.keys() because the order of tags matters
120+
tags = ['ObjectType', 'NDims', 'BinaryData',
121+
'BinaryDataByteOrderMSB', 'CompressedData', 'CompressedDataSize',
122+
'TransformMatrix', 'Offset', 'CenterOfRotation',
123+
'AnatomicalOrientation', 'ElementSpacing',
124+
'DimSize', 'ElementNumberOfChannels', 'ElementType', 'ElementDataFile',
125+
'Comment', 'SeriesDescription', 'AcquisitionDate',
126+
'AcquisitionTime', 'StudyDate', 'StudyTime']
127+
for tag in tags:
128+
if tag in meta_dict.keys():
129+
header += '%s = %s\n' % (tag, meta_dict[tag])
130+
f = open(filename, 'w')
131+
f.write(header)
132+
f.close()
133+
134+
135+
def dump_raw_data(filename, data, dsize, element_channels=1):
136+
""" Write the data into a raw format file. Big endian is always used. """
137+
data = data.reshape(dsize[0], -1, element_channels)
138+
rawfile = open(filename, 'wb')
139+
if data.dtype == numpy.float32:
140+
array_string = 'f'
141+
elif data.dtype == numpy.double or data.dtype == numpy.float64:
142+
array_string = 'd'
143+
elif data.dtype == numpy.short:
144+
array_string = 'h'
145+
elif data.dtype == numpy.ushort:
146+
array_string = 'H'
147+
elif data.dtype == numpy.int32:
148+
array_string = 'i'
149+
elif data.dtype == numpy.uint32:
150+
array_string = 'I'
151+
else:
152+
raise NotImplementedError("ElementType " + str(data.dtype) + " not implemented.")
153+
a = array.array(array_string)
154+
a.fromlist(list(data.ravel()))
155+
# if is_little_endian():
156+
# a.byteswap()
157+
a.tofile(rawfile)
158+
rawfile.close()
159+
160+
161+
def write_mhd_file(mhdfile, data, **meta_dict):
162+
assert(mhdfile[-4:] == '.mhd')
163+
meta_dict['ObjectType'] = 'Image'
164+
meta_dict['BinaryData'] = 'True'
165+
meta_dict['BinaryDataByteOrderMSB'] = 'False'
166+
if data.dtype == numpy.float32:
167+
meta_dict['ElementType'] = 'MET_FLOAT'
168+
elif data.dtype == numpy.double or data.dtype == numpy.float64:
169+
meta_dict['ElementType'] = 'MET_DOUBLE'
170+
elif data.dtype == numpy.byte:
171+
meta_dict['ElementType'] = 'MET_CHAR'
172+
elif data.dtype == numpy.uint8 or data.dtype == numpy.ubyte:
173+
meta_dict['ElementType'] = 'MET_UCHAR'
174+
elif data.dtype == numpy.short or data.dtype == numpy.int16:
175+
meta_dict['ElementType'] = 'MET_SHORT'
176+
elif data.dtype == numpy.ushort or data.dtype == numpy.uint16:
177+
meta_dict['ElementType'] = 'MET_USHORT'
178+
elif data.dtype == numpy.int32:
179+
meta_dict['ElementType'] = 'MET_INT'
180+
elif data.dtype == numpy.uint32:
181+
meta_dict['ElementType'] = 'MET_UINT'
182+
else:
183+
raise NotImplementedError("ElementType " + str(data.dtype) + " not implemented.")
184+
dsize = list(data.shape)
185+
if 'ElementNumberOfChannels' in meta_dict.keys():
186+
element_channels = int(meta_dict['ElementNumberOfChannels'])
187+
assert(dsize[-1] == element_channels)
188+
dsize = dsize[:-1]
189+
else:
190+
element_channels = 1
191+
dsize.reverse()
192+
meta_dict['NDims'] = str(len(dsize))
193+
meta_dict['DimSize'] = dsize
194+
meta_dict['ElementDataFile'] = os.path.split(mhdfile)[1].replace('.mhd',
195+
'.raw')
196+
197+
# Tags that need conversion of list to string
198+
tags = ['ElementSpacing', 'Offset', 'DimSize', 'CenterOfRotation', 'TransformMatrix']
199+
for tag in tags:
200+
if tag in meta_dict.keys():
201+
meta_dict[tag] = ' '.join([str(i) for i in meta_dict[tag]])
202+
write_meta_header(mhdfile, meta_dict)
203+
204+
pwd = os.path.split(mhdfile)[0]
205+
if pwd:
206+
data_file = pwd + '/' + meta_dict['ElementDataFile']
207+
else:
208+
data_file = meta_dict['ElementDataFile']
209+
210+
dump_raw_data(data_file, data, dsize, element_channels=element_channels)

0 commit comments

Comments
 (0)