Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/scipy/io/matlab/_mio.py: 5%
65 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-03 06:39 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-03 06:39 +0000
1"""
2Module for reading and writing matlab (TM) .mat files
3"""
4# Authors: Travis Oliphant, Matthew Brett
6from contextlib import contextmanager
8from ._miobase import _get_matfile_version, docfiller
9from ._mio4 import MatFile4Reader, MatFile4Writer
10from ._mio5 import MatFile5Reader, MatFile5Writer
12__all__ = ['mat_reader_factory', 'loadmat', 'savemat', 'whosmat']
15@contextmanager
16def _open_file_context(file_like, appendmat, mode='rb'):
17 f, opened = _open_file(file_like, appendmat, mode)
18 try:
19 yield f
20 finally:
21 if opened:
22 f.close()
25def _open_file(file_like, appendmat, mode='rb'):
26 """
27 Open `file_like` and return as file-like object. First, check if object is
28 already file-like; if so, return it as-is. Otherwise, try to pass it
29 to open(). If that fails, and `file_like` is a string, and `appendmat` is true,
30 append '.mat' and try again.
31 """
32 reqs = {'read'} if set(mode) & set('r+') else set()
33 if set(mode) & set('wax+'):
34 reqs.add('write')
35 if reqs.issubset(dir(file_like)):
36 return file_like, False
38 try:
39 return open(file_like, mode), True
40 except OSError as e:
41 # Probably "not found"
42 if isinstance(file_like, str):
43 if appendmat and not file_like.endswith('.mat'):
44 file_like += '.mat'
45 return open(file_like, mode), True
46 else:
47 raise OSError(
48 'Reader needs file name or open file-like object'
49 ) from e
52@docfiller
53def mat_reader_factory(file_name, appendmat=True, **kwargs):
54 """
55 Create reader for matlab .mat format files.
57 Parameters
58 ----------
59 %(file_arg)s
60 %(append_arg)s
61 %(load_args)s
62 %(struct_arg)s
64 Returns
65 -------
66 matreader : MatFileReader object
67 Initialized instance of MatFileReader class matching the mat file
68 type detected in `filename`.
69 file_opened : bool
70 Whether the file was opened by this routine.
72 """
73 byte_stream, file_opened = _open_file(file_name, appendmat)
74 mjv, mnv = _get_matfile_version(byte_stream)
75 if mjv == 0:
76 return MatFile4Reader(byte_stream, **kwargs), file_opened
77 elif mjv == 1:
78 return MatFile5Reader(byte_stream, **kwargs), file_opened
79 elif mjv == 2:
80 raise NotImplementedError('Please use HDF reader for matlab v7.3 '
81 'files, e.g. h5py')
82 else:
83 raise TypeError('Did not recognize version %s' % mjv)
86@docfiller
87def loadmat(file_name, mdict=None, appendmat=True, **kwargs):
88 """
89 Load MATLAB file.
91 Parameters
92 ----------
93 file_name : str
94 Name of the mat file (do not need .mat extension if
95 appendmat==True). Can also pass open file-like object.
96 mdict : dict, optional
97 Dictionary in which to insert matfile variables.
98 appendmat : bool, optional
99 True to append the .mat extension to the end of the given
100 filename, if not already present. Default is True.
101 byte_order : str or None, optional
102 None by default, implying byte order guessed from mat
103 file. Otherwise can be one of ('native', '=', 'little', '<',
104 'BIG', '>').
105 mat_dtype : bool, optional
106 If True, return arrays in same dtype as would be loaded into
107 MATLAB (instead of the dtype with which they are saved).
108 squeeze_me : bool, optional
109 Whether to squeeze unit matrix dimensions or not.
110 chars_as_strings : bool, optional
111 Whether to convert char arrays to string arrays.
112 matlab_compatible : bool, optional
113 Returns matrices as would be loaded by MATLAB (implies
114 squeeze_me=False, chars_as_strings=False, mat_dtype=True,
115 struct_as_record=True).
116 struct_as_record : bool, optional
117 Whether to load MATLAB structs as NumPy record arrays, or as
118 old-style NumPy arrays with dtype=object. Setting this flag to
119 False replicates the behavior of scipy version 0.7.x (returning
120 NumPy object arrays). The default setting is True, because it
121 allows easier round-trip load and save of MATLAB files.
122 verify_compressed_data_integrity : bool, optional
123 Whether the length of compressed sequences in the MATLAB file
124 should be checked, to ensure that they are not longer than we expect.
125 It is advisable to enable this (the default) because overlong
126 compressed sequences in MATLAB files generally indicate that the
127 files have experienced some sort of corruption.
128 variable_names : None or sequence
129 If None (the default) - read all variables in file. Otherwise,
130 `variable_names` should be a sequence of strings, giving names of the
131 MATLAB variables to read from the file. The reader will skip any
132 variable with a name not in this sequence, possibly saving some read
133 processing.
134 simplify_cells : False, optional
135 If True, return a simplified dict structure (which is useful if the mat
136 file contains cell arrays). Note that this only affects the structure
137 of the result and not its contents (which is identical for both output
138 structures). If True, this automatically sets `struct_as_record` to
139 False and `squeeze_me` to True, which is required to simplify cells.
141 Returns
142 -------
143 mat_dict : dict
144 dictionary with variable names as keys, and loaded matrices as
145 values.
147 Notes
148 -----
149 v4 (Level 1.0), v6 and v7 to 7.2 matfiles are supported.
151 You will need an HDF5 Python library to read MATLAB 7.3 format mat
152 files. Because SciPy does not supply one, we do not implement the
153 HDF5 / 7.3 interface here.
155 Examples
156 --------
157 >>> from os.path import dirname, join as pjoin
158 >>> import scipy.io as sio
160 Get the filename for an example .mat file from the tests/data directory.
162 >>> data_dir = pjoin(dirname(sio.__file__), 'matlab', 'tests', 'data')
163 >>> mat_fname = pjoin(data_dir, 'testdouble_7.4_GLNX86.mat')
165 Load the .mat file contents.
167 >>> mat_contents = sio.loadmat(mat_fname)
169 The result is a dictionary, one key/value pair for each variable:
171 >>> sorted(mat_contents.keys())
172 ['__globals__', '__header__', '__version__', 'testdouble']
173 >>> mat_contents['testdouble']
174 array([[0. , 0.78539816, 1.57079633, 2.35619449, 3.14159265,
175 3.92699082, 4.71238898, 5.49778714, 6.28318531]])
177 By default SciPy reads MATLAB structs as structured NumPy arrays where the
178 dtype fields are of type `object` and the names correspond to the MATLAB
179 struct field names. This can be disabled by setting the optional argument
180 `struct_as_record=False`.
182 Get the filename for an example .mat file that contains a MATLAB struct
183 called `teststruct` and load the contents.
185 >>> matstruct_fname = pjoin(data_dir, 'teststruct_7.4_GLNX86.mat')
186 >>> matstruct_contents = sio.loadmat(matstruct_fname)
187 >>> teststruct = matstruct_contents['teststruct']
188 >>> teststruct.dtype
189 dtype([('stringfield', 'O'), ('doublefield', 'O'), ('complexfield', 'O')])
191 The size of the structured array is the size of the MATLAB struct, not the
192 number of elements in any particular field. The shape defaults to 2-D
193 unless the optional argument `squeeze_me=True`, in which case all length 1
194 dimensions are removed.
196 >>> teststruct.size
197 1
198 >>> teststruct.shape
199 (1, 1)
201 Get the 'stringfield' of the first element in the MATLAB struct.
203 >>> teststruct[0, 0]['stringfield']
204 array(['Rats live on no evil star.'],
205 dtype='<U26')
207 Get the first element of the 'doublefield'.
209 >>> teststruct['doublefield'][0, 0]
210 array([[ 1.41421356, 2.71828183, 3.14159265]])
212 Load the MATLAB struct, squeezing out length 1 dimensions, and get the item
213 from the 'complexfield'.
215 >>> matstruct_squeezed = sio.loadmat(matstruct_fname, squeeze_me=True)
216 >>> matstruct_squeezed['teststruct'].shape
217 ()
218 >>> matstruct_squeezed['teststruct']['complexfield'].shape
219 ()
220 >>> matstruct_squeezed['teststruct']['complexfield'].item()
221 array([ 1.41421356+1.41421356j, 2.71828183+2.71828183j,
222 3.14159265+3.14159265j])
223 """
224 variable_names = kwargs.pop('variable_names', None)
225 with _open_file_context(file_name, appendmat) as f:
226 MR, _ = mat_reader_factory(f, **kwargs)
227 matfile_dict = MR.get_variables(variable_names)
229 if mdict is not None:
230 mdict.update(matfile_dict)
231 else:
232 mdict = matfile_dict
234 return mdict
237@docfiller
238def savemat(file_name, mdict,
239 appendmat=True,
240 format='5',
241 long_field_names=False,
242 do_compression=False,
243 oned_as='row'):
244 """
245 Save a dictionary of names and arrays into a MATLAB-style .mat file.
247 This saves the array objects in the given dictionary to a MATLAB-
248 style .mat file.
250 Parameters
251 ----------
252 file_name : str or file-like object
253 Name of the .mat file (.mat extension not needed if ``appendmat ==
254 True``).
255 Can also pass open file_like object.
256 mdict : dict
257 Dictionary from which to save matfile variables.
258 appendmat : bool, optional
259 True (the default) to append the .mat extension to the end of the
260 given filename, if not already present.
261 format : {'5', '4'}, string, optional
262 '5' (the default) for MATLAB 5 and up (to 7.2),
263 '4' for MATLAB 4 .mat files.
264 long_field_names : bool, optional
265 False (the default) - maximum field name length in a structure is
266 31 characters which is the documented maximum length.
267 True - maximum field name length in a structure is 63 characters
268 which works for MATLAB 7.6+.
269 do_compression : bool, optional
270 Whether or not to compress matrices on write. Default is False.
271 oned_as : {'row', 'column'}, optional
272 If 'column', write 1-D NumPy arrays as column vectors.
273 If 'row', write 1-D NumPy arrays as row vectors.
275 Examples
276 --------
277 >>> from scipy.io import savemat
278 >>> import numpy as np
279 >>> a = np.arange(20)
280 >>> mdic = {"a": a, "label": "experiment"}
281 >>> mdic
282 {'a': array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
283 17, 18, 19]),
284 'label': 'experiment'}
285 >>> savemat("matlab_matrix.mat", mdic)
286 """
287 with _open_file_context(file_name, appendmat, 'wb') as file_stream:
288 if format == '4':
289 if long_field_names:
290 message = "Long field names are not available for version 4 files"
291 raise ValueError(message)
292 MW = MatFile4Writer(file_stream, oned_as)
293 elif format == '5':
294 MW = MatFile5Writer(file_stream,
295 do_compression=do_compression,
296 unicode_strings=True,
297 long_field_names=long_field_names,
298 oned_as=oned_as)
299 else:
300 raise ValueError("Format should be '4' or '5'")
301 MW.put_variables(mdict)
304@docfiller
305def whosmat(file_name, appendmat=True, **kwargs):
306 """
307 List variables inside a MATLAB file.
309 Parameters
310 ----------
311 %(file_arg)s
312 %(append_arg)s
313 %(load_args)s
314 %(struct_arg)s
316 Returns
317 -------
318 variables : list of tuples
319 A list of tuples, where each tuple holds the matrix name (a string),
320 its shape (tuple of ints), and its data class (a string).
321 Possible data classes are: int8, uint8, int16, uint16, int32, uint32,
322 int64, uint64, single, double, cell, struct, object, char, sparse,
323 function, opaque, logical, unknown.
325 Notes
326 -----
327 v4 (Level 1.0), v6 and v7 to 7.2 matfiles are supported.
329 You will need an HDF5 python library to read matlab 7.3 format mat
330 files (e.g. h5py). Because SciPy does not supply one, we do not implement the
331 HDF5 / 7.3 interface here.
333 .. versionadded:: 0.12.0
335 Examples
336 --------
337 >>> from io import BytesIO
338 >>> import numpy as np
339 >>> from scipy.io import savemat, whosmat
341 Create some arrays, and use `savemat` to write them to a ``BytesIO``
342 instance.
344 >>> a = np.array([[10, 20, 30], [11, 21, 31]], dtype=np.int32)
345 >>> b = np.geomspace(1, 10, 5)
346 >>> f = BytesIO()
347 >>> savemat(f, {'a': a, 'b': b})
349 Use `whosmat` to inspect ``f``. Each tuple in the output list gives
350 the name, shape and data type of the array in ``f``.
352 >>> whosmat(f)
353 [('a', (2, 3), 'int32'), ('b', (1, 5), 'double')]
355 """
356 with _open_file_context(file_name, appendmat) as f:
357 ML, file_opened = mat_reader_factory(f, **kwargs)
358 variables = ML.list_variables()
359 return variables