1111import sys
1212import warnings
1313import zlib
14+ import os .path as op
1415from io import StringIO
1516from xml .parsers .expat import ExpatError
1617
@@ -30,16 +31,27 @@ class GiftiParseError(ExpatError):
3031 """ Gifti-specific parsing error """
3132
3233
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 ]
4355
4456 if enclabel == 'ASCII' :
4557 # GIFTI_ENCODING_ASCII
@@ -54,9 +66,15 @@ def read_data_block(encoding,
5466 # the data type/endianness/ordering specified by the other DataArray
5567 # attributes
5668 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 :
5876 f .seek (darray .ext_offset )
59- nbytes = np .prod (shape ) * dtype ().itemsize
77+ nbytes = np .prod (darray . dims ) * dtype ().itemsize
6078 buff = f .read (nbytes )
6179
6280 # Numpy arrays created from bytes objects are read-only.
@@ -75,13 +93,14 @@ def read_data_block(encoding,
7593 buff = bytearray (zlib .decompress (dec ))
7694 del dec
7795
78- sh = tuple (shape )
96+ sh = tuple (darray . dims )
7997 newarr = np .frombuffer (buff , dtype = dtype )
8098 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 ])
82101
83102 # check if we need to byteswap
84- required_byteorder = gifti_endian_codes .byteorder [endian ]
103+ required_byteorder = gifti_endian_codes .byteorder [darray . endian ]
85104 if (required_byteorder in ('big' , 'little' ) and
86105 required_byteorder != sys .byteorder ):
87106 newarr = newarr .byteswap ()
@@ -339,10 +358,7 @@ def flush_chardata(self):
339358 c .close ()
340359
341360 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 )
346362 # update the endianness according to the
347363 # current machine setting
348364 self .endian = gifti_endian_codes .code [sys .byteorder ]
0 commit comments