_mio5_params.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. ''' Constants and classes for matlab 5 read and write
  2. See also mio5_utils.pyx where these same constants arise as c enums.
  3. If you make changes in this file, don't forget to change mio5_utils.pyx
  4. '''
  5. import numpy as np
  6. from ._miobase import convert_dtypes
  7. __all__ = [
  8. 'MDTYPES', 'MatlabFunction', 'MatlabObject', 'MatlabOpaque',
  9. 'NP_TO_MTYPES', 'NP_TO_MXTYPES', 'OPAQUE_DTYPE', 'codecs_template',
  10. 'mat_struct', 'mclass_dtypes_template', 'mclass_info', 'mdtypes_template',
  11. 'miCOMPRESSED', 'miDOUBLE', 'miINT16', 'miINT32', 'miINT64', 'miINT8',
  12. 'miMATRIX', 'miSINGLE', 'miUINT16', 'miUINT32', 'miUINT64', 'miUINT8',
  13. 'miUTF16', 'miUTF32', 'miUTF8', 'mxCELL_CLASS', 'mxCHAR_CLASS',
  14. 'mxDOUBLE_CLASS', 'mxFUNCTION_CLASS', 'mxINT16_CLASS', 'mxINT32_CLASS',
  15. 'mxINT64_CLASS', 'mxINT8_CLASS', 'mxOBJECT_CLASS',
  16. 'mxOBJECT_CLASS_FROM_MATRIX_H', 'mxOPAQUE_CLASS', 'mxSINGLE_CLASS',
  17. 'mxSPARSE_CLASS', 'mxSTRUCT_CLASS', 'mxUINT16_CLASS', 'mxUINT32_CLASS',
  18. 'mxUINT64_CLASS', 'mxUINT8_CLASS'
  19. ]
  20. miINT8 = 1
  21. miUINT8 = 2
  22. miINT16 = 3
  23. miUINT16 = 4
  24. miINT32 = 5
  25. miUINT32 = 6
  26. miSINGLE = 7
  27. miDOUBLE = 9
  28. miINT64 = 12
  29. miUINT64 = 13
  30. miMATRIX = 14
  31. miCOMPRESSED = 15
  32. miUTF8 = 16
  33. miUTF16 = 17
  34. miUTF32 = 18
  35. mxCELL_CLASS = 1
  36. mxSTRUCT_CLASS = 2
  37. # The March 2008 edition of "Matlab 7 MAT-File Format" says that
  38. # mxOBJECT_CLASS = 3, whereas matrix.h says that mxLOGICAL = 3.
  39. # Matlab 2008a appears to save logicals as type 9, so we assume that
  40. # the document is correct. See type 18, below.
  41. mxOBJECT_CLASS = 3
  42. mxCHAR_CLASS = 4
  43. mxSPARSE_CLASS = 5
  44. mxDOUBLE_CLASS = 6
  45. mxSINGLE_CLASS = 7
  46. mxINT8_CLASS = 8
  47. mxUINT8_CLASS = 9
  48. mxINT16_CLASS = 10
  49. mxUINT16_CLASS = 11
  50. mxINT32_CLASS = 12
  51. mxUINT32_CLASS = 13
  52. # The following are not in the March 2008 edition of "Matlab 7
  53. # MAT-File Format," but were guessed from matrix.h.
  54. mxINT64_CLASS = 14
  55. mxUINT64_CLASS = 15
  56. mxFUNCTION_CLASS = 16
  57. # Not doing anything with these at the moment.
  58. mxOPAQUE_CLASS = 17 # This appears to be a function workspace
  59. # Thread 'saving/loading symbol table of annymous functions',
  60. # octave-maintainers, April-May 2007
  61. # https://lists.gnu.org/archive/html/octave-maintainers/2007-04/msg00031.html
  62. # https://lists.gnu.org/archive/html/octave-maintainers/2007-05/msg00032.html
  63. # (Was/Deprecated: https://www-old.cae.wisc.edu/pipermail/octave-maintainers/2007-May/002824.html)
  64. mxOBJECT_CLASS_FROM_MATRIX_H = 18
  65. mdtypes_template = {
  66. miINT8: 'i1',
  67. miUINT8: 'u1',
  68. miINT16: 'i2',
  69. miUINT16: 'u2',
  70. miINT32: 'i4',
  71. miUINT32: 'u4',
  72. miSINGLE: 'f4',
  73. miDOUBLE: 'f8',
  74. miINT64: 'i8',
  75. miUINT64: 'u8',
  76. miUTF8: 'u1',
  77. miUTF16: 'u2',
  78. miUTF32: 'u4',
  79. 'file_header': [('description', 'S116'),
  80. ('subsystem_offset', 'i8'),
  81. ('version', 'u2'),
  82. ('endian_test', 'S2')],
  83. 'tag_full': [('mdtype', 'u4'), ('byte_count', 'u4')],
  84. 'tag_smalldata':[('byte_count_mdtype', 'u4'), ('data', 'S4')],
  85. 'array_flags': [('data_type', 'u4'),
  86. ('byte_count', 'u4'),
  87. ('flags_class','u4'),
  88. ('nzmax', 'u4')],
  89. 'U1': 'U1',
  90. }
  91. mclass_dtypes_template = {
  92. mxINT8_CLASS: 'i1',
  93. mxUINT8_CLASS: 'u1',
  94. mxINT16_CLASS: 'i2',
  95. mxUINT16_CLASS: 'u2',
  96. mxINT32_CLASS: 'i4',
  97. mxUINT32_CLASS: 'u4',
  98. mxINT64_CLASS: 'i8',
  99. mxUINT64_CLASS: 'u8',
  100. mxSINGLE_CLASS: 'f4',
  101. mxDOUBLE_CLASS: 'f8',
  102. }
  103. mclass_info = {
  104. mxINT8_CLASS: 'int8',
  105. mxUINT8_CLASS: 'uint8',
  106. mxINT16_CLASS: 'int16',
  107. mxUINT16_CLASS: 'uint16',
  108. mxINT32_CLASS: 'int32',
  109. mxUINT32_CLASS: 'uint32',
  110. mxINT64_CLASS: 'int64',
  111. mxUINT64_CLASS: 'uint64',
  112. mxSINGLE_CLASS: 'single',
  113. mxDOUBLE_CLASS: 'double',
  114. mxCELL_CLASS: 'cell',
  115. mxSTRUCT_CLASS: 'struct',
  116. mxOBJECT_CLASS: 'object',
  117. mxCHAR_CLASS: 'char',
  118. mxSPARSE_CLASS: 'sparse',
  119. mxFUNCTION_CLASS: 'function',
  120. mxOPAQUE_CLASS: 'opaque',
  121. }
  122. NP_TO_MTYPES = {
  123. 'f8': miDOUBLE,
  124. 'c32': miDOUBLE,
  125. 'c24': miDOUBLE,
  126. 'c16': miDOUBLE,
  127. 'f4': miSINGLE,
  128. 'c8': miSINGLE,
  129. 'i8': miINT64,
  130. 'i4': miINT32,
  131. 'i2': miINT16,
  132. 'i1': miINT8,
  133. 'u8': miUINT64,
  134. 'u4': miUINT32,
  135. 'u2': miUINT16,
  136. 'u1': miUINT8,
  137. 'S1': miUINT8,
  138. 'U1': miUTF16,
  139. 'b1': miUINT8, # not standard but seems MATLAB uses this (gh-4022)
  140. }
  141. NP_TO_MXTYPES = {
  142. 'f8': mxDOUBLE_CLASS,
  143. 'c32': mxDOUBLE_CLASS,
  144. 'c24': mxDOUBLE_CLASS,
  145. 'c16': mxDOUBLE_CLASS,
  146. 'f4': mxSINGLE_CLASS,
  147. 'c8': mxSINGLE_CLASS,
  148. 'i8': mxINT64_CLASS,
  149. 'i4': mxINT32_CLASS,
  150. 'i2': mxINT16_CLASS,
  151. 'i1': mxINT8_CLASS,
  152. 'u8': mxUINT64_CLASS,
  153. 'u4': mxUINT32_CLASS,
  154. 'u2': mxUINT16_CLASS,
  155. 'u1': mxUINT8_CLASS,
  156. 'S1': mxUINT8_CLASS,
  157. 'b1': mxUINT8_CLASS, # not standard but seems MATLAB uses this
  158. }
  159. ''' Before release v7.1 (release 14) matlab (TM) used the system
  160. default character encoding scheme padded out to 16-bits. Release 14
  161. and later use Unicode. When saving character data, R14 checks if it
  162. can be encoded in 7-bit ascii, and saves in that format if so.'''
  163. codecs_template = {
  164. miUTF8: {'codec': 'utf_8', 'width': 1},
  165. miUTF16: {'codec': 'utf_16', 'width': 2},
  166. miUTF32: {'codec': 'utf_32','width': 4},
  167. }
  168. def _convert_codecs(template, byte_order):
  169. ''' Convert codec template mapping to byte order
  170. Set codecs not on this system to None
  171. Parameters
  172. ----------
  173. template : mapping
  174. key, value are respectively codec name, and root name for codec
  175. (without byte order suffix)
  176. byte_order : {'<', '>'}
  177. code for little or big endian
  178. Returns
  179. -------
  180. codecs : dict
  181. key, value are name, codec (as in .encode(codec))
  182. '''
  183. codecs = {}
  184. postfix = byte_order == '<' and '_le' or '_be'
  185. for k, v in template.items():
  186. codec = v['codec']
  187. try:
  188. " ".encode(codec)
  189. except LookupError:
  190. codecs[k] = None
  191. continue
  192. if v['width'] > 1:
  193. codec += postfix
  194. codecs[k] = codec
  195. return codecs.copy()
  196. MDTYPES = {}
  197. for _bytecode in '<>':
  198. _def = {'dtypes': convert_dtypes(mdtypes_template, _bytecode),
  199. 'classes': convert_dtypes(mclass_dtypes_template, _bytecode),
  200. 'codecs': _convert_codecs(codecs_template, _bytecode)}
  201. MDTYPES[_bytecode] = _def
  202. class mat_struct:
  203. """Placeholder for holding read data from structs.
  204. We use instances of this class when the user passes False as a value to the
  205. ``struct_as_record`` parameter of the :func:`scipy.io.loadmat` function.
  206. """
  207. pass
  208. class MatlabObject(np.ndarray):
  209. """Subclass of ndarray to signal this is a matlab object.
  210. This is a simple subclass of :class:`numpy.ndarray` meant to be used
  211. by :func:`scipy.io.loadmat` and should not be instantiated directly.
  212. """
  213. def __new__(cls, input_array, classname=None):
  214. # Input array is an already formed ndarray instance
  215. # We first cast to be our class type
  216. obj = np.asarray(input_array).view(cls)
  217. # add the new attribute to the created instance
  218. obj.classname = classname
  219. # Finally, we must return the newly created object:
  220. return obj
  221. def __array_finalize__(self,obj):
  222. # reset the attribute from passed original object
  223. self.classname = getattr(obj, 'classname', None)
  224. # We do not need to return anything
  225. class MatlabFunction(np.ndarray):
  226. """Subclass for a MATLAB function.
  227. This is a simple subclass of :class:`numpy.ndarray` meant to be used
  228. by :func:`scipy.io.loadmat` and should not be directly instantiated.
  229. """
  230. def __new__(cls, input_array):
  231. obj = np.asarray(input_array).view(cls)
  232. return obj
  233. class MatlabOpaque(np.ndarray):
  234. """Subclass for a MATLAB opaque matrix.
  235. This is a simple subclass of :class:`numpy.ndarray` meant to be used
  236. by :func:`scipy.io.loadmat` and should not be directly instantiated.
  237. """
  238. def __new__(cls, input_array):
  239. obj = np.asarray(input_array).view(cls)
  240. return obj
  241. OPAQUE_DTYPE = np.dtype(
  242. [('s0', 'O'), ('s1', 'O'), ('s2', 'O'), ('arr', 'O')])