_mio5_params.py 8.0 KB

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