11
11
import sys
12
12
import warnings
13
13
import zlib
14
+ import os .path as op
14
15
from io import StringIO
15
16
from xml .parsers .expat import ExpatError
16
17
@@ -30,16 +31,27 @@ class GiftiParseError(ExpatError):
30
31
""" Gifti-specific parsing error """
31
32
32
33
33
- def read_data_block (encoding ,
34
- endian ,
35
- ordering ,
36
- datatype ,
37
- shape ,
38
- data ,
39
- darray ):
40
- """ Tries to unzip, decode, parse the funny string data """
41
- enclabel = gifti_encoding_codes .label [encoding ]
42
- dtype = data_type_codes .type [datatype ]
34
+ def read_data_block (darray , fname , data ):
35
+ """Parses data from a <Data> element, or loads from an external file.
36
+
37
+ Parameters
38
+ ----------
39
+ darray : GiftiDataArray
40
+ GiftiDataArray object representing the parent <DataArray> of this
41
+ <Data> element
42
+
43
+ fname : str or None
44
+ Name of GIFTI file being loaded, or None if in-memory
45
+
46
+ data : str or None
47
+ Data to parse, or None if data is in an external file
48
+
49
+ Returns
50
+ -------
51
+ numpy.ndarray containing the parsed data
52
+ """
53
+ enclabel = gifti_encoding_codes .label [darray .encoding ]
54
+ dtype = data_type_codes .type [darray .datatype ]
43
55
44
56
if enclabel == 'ASCII' :
45
57
# GIFTI_ENCODING_ASCII
@@ -54,9 +66,15 @@ def read_data_block(encoding,
54
66
# the data type/endianness/ordering specified by the other DataArray
55
67
# attributes
56
68
if enclabel == 'External' :
57
- with open (darray .ext_fname , 'rb' ) as f :
69
+ if fname is None :
70
+ raise GiftiParseError ('ExternalFileBinary is not supported '
71
+ 'when loading from in-memory XML' )
72
+ ext_fname = op .join (op .dirname (fname ), darray .ext_fname )
73
+ if not op .exists (ext_fname ):
74
+ raise GiftiParseError ('Cannot locate external file ' + ext_fname )
75
+ with open (ext_fname , 'rb' ) as f :
58
76
f .seek (darray .ext_offset )
59
- nbytes = np .prod (shape ) * dtype ().itemsize
77
+ nbytes = np .prod (darray . dims ) * dtype ().itemsize
60
78
buff = f .read (nbytes )
61
79
62
80
# Numpy arrays created from bytes objects are read-only.
@@ -75,13 +93,14 @@ def read_data_block(encoding,
75
93
buff = bytearray (zlib .decompress (dec ))
76
94
del dec
77
95
78
- sh = tuple (shape )
96
+ sh = tuple (darray . dims )
79
97
newarr = np .frombuffer (buff , dtype = dtype )
80
98
if len (newarr .shape ) != len (sh ):
81
- newarr = newarr .reshape (sh , order = array_index_order_codes .npcode [ordering ])
99
+ newarr = newarr .reshape (
100
+ sh , order = array_index_order_codes .npcode [darray .ind_ord ])
82
101
83
102
# check if we need to byteswap
84
- required_byteorder = gifti_endian_codes .byteorder [endian ]
103
+ required_byteorder = gifti_endian_codes .byteorder [darray . endian ]
85
104
if (required_byteorder in ('big' , 'little' ) and
86
105
required_byteorder != sys .byteorder ):
87
106
newarr = newarr .byteswap ()
@@ -339,10 +358,7 @@ def flush_chardata(self):
339
358
c .close ()
340
359
341
360
elif self .write_to == 'Data' :
342
- da_tmp = self .img .darrays [- 1 ]
343
- da_tmp .data = read_data_block (da_tmp .encoding , da_tmp .endian ,
344
- da_tmp .ind_ord , da_tmp .datatype ,
345
- da_tmp .dims , data , self .da )
361
+ self .da .data = read_data_block (self .da , self .fname , data )
346
362
# update the endianness according to the
347
363
# current machine setting
348
364
self .endian = gifti_endian_codes .code [sys .byteorder ]
0 commit comments