a
    BCCf,ƒ  ã                   @   sš  d Z ddlZddlZddlZddlZddlmZ ddlZddlZ	ddl
ZddlmZmZ ddlmZmZmZmZmZmZmZmZmZ ddlmZ ddlmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z- dd	l.m/Z/ d
d„ Z0dd„ Z1dd„ Z2dd„ Z3G dd„ deƒZ4dd„ Z5G dd„ dƒZ6dd„ Z7ee d d Z8ee d d Z9ee d d Z:ee d d Z;G dd „ d ƒZ<G d!d"„ d"ƒZ=dS )#a<   Classes for read / write of matlab (TM) 5 files

The matfile specification last found here:

https://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf

(as of December 5 2008)

=================================
 Note on functions and mat files
=================================

The document above does not give any hints as to the storage of matlab
function handles, or anonymous function handles. I had, therefore, to
guess the format of matlab arrays of ``mxFUNCTION_CLASS`` and
``mxOPAQUE_CLASS`` by looking at example mat files.

``mxFUNCTION_CLASS`` stores all types of matlab functions. It seems to
contain a struct matrix with a set pattern of fields. For anonymous
functions, a sub-fields of one of these fields seems to contain the
well-named ``mxOPAQUE_CLASS``. This seems to contain:

* array flags as for any matlab matrix
* 3 int8 strings
* a matrix

It seems that whenever the mat file contains a ``mxOPAQUE_CLASS``
instance, there is also an un-named matrix (name == '') at the end of
the mat file. I'll call this the ``__function_workspace__`` matrix.

When I saved two anonymous functions in a mat file, or appended another
anonymous function to the mat file, there was still only one
``__function_workspace__`` un-named matrix at the end, but larger than
that for a mat file with a single anonymous function, suggesting that
the workspaces for the two functions had been merged.

The ``__function_workspace__`` matrix appears to be of double class
(``mxCLASS_DOUBLE``), but stored as uint8, the memory for which is in
the format of a mini .mat file, without the first 124 bytes of the file
header (the description and the subsystem_offset), but with the version
U2 bytes, and the S2 endian test bytes. There follow 4 zero bytes,
presumably for 8 byte padding, and then a series of ``miMATRIX``
entries, as in a standard mat file. The ``miMATRIX`` entries appear to
be series of un-named (name == '') matrices, and may also contain arrays
of this same mini-mat format.

I guess that:

* saving an anonymous function back to a mat file will need the
  associated ``__function_workspace__`` matrix saved as well for the
  anonymous function to work correctly.
* appending to a mat file that has a ``__function_workspace__`` would
  involve first pulling off this workspace, appending, checking whether
  there were any more anonymous functions appended, and then somehow
  merging the relevant workspaces, and saving at the end of the mat
  file.

The mat files I was playing with are in ``tests/data``:

* sqr.mat
* parabola.mat
* some_functions.mat

See ``tests/test_mio.py:test_mio_funcs.py`` for the debugging
script I was working with.

Small fragments of current code adapted from matfile.py by Heiko
Henkelmann; parts of the code for simplify_cells=True adapted from
http://blog.nephics.com/2019/08/28/better-loadmat-for-scipy/.
é    N)ÚBytesIOé   )Únative_codeÚswapped_code)	ÚMatFileReaderÚ	docfillerÚmatdimsÚ
read_dtypeÚarr_to_charsÚarr_dtype_numberÚMatWriteErrorÚMatReadErrorÚMatReadWarning)Ú
VarReader5)ÚMatlabObjectÚMatlabFunctionÚMDTYPESÚNP_TO_MTYPESÚNP_TO_MXTYPESÚmiCOMPRESSEDÚmiMATRIXÚmiINT8ÚmiUTF8ÚmiUINT32ÚmxCELL_CLASSÚmxSTRUCT_CLASSÚmxOBJECT_CLASSÚmxCHAR_CLASSÚmxSPARSE_CLASSÚmxDOUBLE_CLASSÚmclass_infoÚ
mat_struct)ÚZlibInputStreamc                 C   s.   t | tjƒo,| jdko,| jdko,t | d tƒS )zBDetermine if elem is an array and if first array item is a struct.r   )Ú
isinstanceÚnpÚndarrayÚsizeÚndimr!   )Úelem© r)   úQ/var/www/html/django/DPS/env/lib/python3.9/site-packages/scipy/io/matlab/_mio5.pyÚ_has_structh   s     ÿr+   c                 C   sN   g }| D ]@}t |tƒr&| t|ƒ¡ qt|ƒr>| t|ƒ¡ q| |¡ q|S )zyConstruct lists from cell arrays (loaded as numpy ndarrays), recursing
    into items if they contain mat_struct objects.)r#   r!   ÚappendÚ_matstruct_to_dictr+   Ú_inspect_cell_array)r%   Z	elem_listZsub_elemr)   r)   r*   r.   n   s    
r.   c                 C   sT   i }| j D ]D}| j| }t|tƒr0t|ƒ||< q
t|ƒrFt|ƒ||< q
|||< q
|S )z/Construct nested dicts from mat_struct objects.)Ú_fieldnamesÚ__dict__r#   r!   r-   r+   r.   )ZmatobjÚdÚfr(   r)   r)   r*   r-   |   s    



r-   c                 C   sJ   | D ]@}t | | tƒr(t| | ƒ| |< qt| | ƒrt| | ƒ| |< q| S )z,Convert mat objects in dict to nested dicts.)r#   r!   r-   r+   r.   )r1   Úkeyr)   r)   r*   Ú_simplify_cellsŠ   s    r4   c                
       sb   e Zd ZdZed‡ fdd„	ƒZdd„ Zd	d
„ Zdd„ Zdd„ Z	ddd„Z
ddd„Zdd„ Z‡  ZS )ÚMatFile5ReaderaØ   Reader for Mat 5 mat files
    Adds the following attribute to base class

    uint16_codec - char codec to use for uint16 char arrays
        (defaults to system default codec)

    Uses variable reader that has the following standard interface (see
    abstract class in ``miobase``::

       __init__(self, file_reader)
       read_header(self)
       array_from_header(self)

    and added interface::

       set_stream(self, stream)
       read_full_tag(self)

    NFTc                    s>   t ƒ  |||||||||
¡	 |	s(t ¡ }	|	| _d| _d| _dS )züInitializer for matlab 5 file format reader

    %(matstream_arg)s
    %(load_args)s
    %(struct_arg)s
    uint16_codec : {None, string}
        Set codec to use for uint16 char arrays (e.g., 'utf-8').
        Use system default codec if None
        N)ÚsuperÚ__init__ÚsysÚgetdefaultencodingÚuint16_codecÚ_file_readerÚ_matrix_reader)ÚselfÚ
mat_streamÚ
byte_orderZ	mat_dtypeZ
squeeze_meZchars_as_stringsZmatlab_compatibleZstruct_as_recordÚ verify_compressed_data_integrityr:   Úsimplify_cells©Ú	__class__r)   r*   r7   ¨   s     ÷zMatFile5Reader.__init__c                 C   s4   | j  d¡ | j  d¡}| j  d¡ |dkr0dp2dS )z3 Guess byte order.
        Sets stream pointer to 0é~   é   r   s   IMú<ú>)r>   ÚseekÚread)r=   Úmir)   r)   r*   Úguess_byte_orderÏ   s    zMatFile5Reader.guess_byte_orderc                 C   sd   i }t | j d d }t| j|ƒ}|d  ¡  d¡|d< |d d? }|d d@ }d	||f |d
< |S )z Read in mat 5 file header ÚdtypesÚfile_headerÚdescriptions    	
 Z
__header__Úversioné   éÿ   z%d.%dÚ__version__)r   r?   r	   r>   ÚitemÚstrip)r=   ZhdictZ	hdr_dtypeÚhdrZv_majorZv_minorr)   r)   r*   Úread_file_header×   s    zMatFile5Reader.read_file_headerc                 C   s   t | ƒ| _t | ƒ| _dS )za Run when beginning read of variables

        Sets up readers from parameters in `self`
        N)r   r;   r<   ©r=   r)   r)   r*   Úinitialize_readâ   s    
zMatFile5Reader.initialize_readc                 C   sœ   | j  ¡ \}}|dkstdƒ‚| j ¡ | }|tkrbt| j|ƒ}| j |¡ | j	}| j ¡ \}}nd}| j | j¡ |t
ksˆtd| ƒ‚| j |¡}||fS )aœ   Read header, return header, next position

        Header has to define at least .name and .is_global

        Parameters
        ----------
        None

        Returns
        -------
        header : object
           object that can be passed to self.read_var_array, and that
           has attributes .name and .is_global
        next_position : int
           position in stream of next variable
        r   zDid not read any bytesFz$Expecting miMATRIX type here, got %d)r;   Zread_full_tagÚ
ValueErrorr>   Útellr   r"   r<   Z
set_streamr@   r   Ú	TypeErrorZread_header)r=   ÚmdtypeÚ
byte_countZnext_posÚstreamZcheck_stream_limitÚheaderr)   r)   r*   Úread_var_headerî   s    zMatFile5Reader.read_var_headerc                 C   s   | j  ||¡S )aµ   Read array, given `header`

        Parameters
        ----------
        header : header object
           object with fields defining variable header
        process : {True, False} bool, optional
           If True, apply recursive post-processing during loading of
           array.

        Returns
        -------
        arr : array
           array with post-processing applied or not according to
           `process`.
        )r<   Zarray_from_header)r=   r_   Úprocessr)   r)   r*   Úread_var_array  s    zMatFile5Reader.read_var_arrayc           	   
   C   sŠ  t |tƒr|g}n|dur"t|ƒ}| j d¡ |  ¡  |  ¡ }g |d< |  ¡ sr|  ¡ \}}|j	du rjdn
|j	 
d¡}||v r’tjd| tdd |d	kr¤d
}d}nd}|durÆ||vrÆ| j |¡ qFz|  ||¡}W nL ty" } z2tjd|› d|› dtdd d| }W Y d}~n
d}~0 0 | j |¡ |||< |jrN|d  |¡ |durF| |¡ t|ƒdkrFqrqF| jr‚t|ƒS |S dS )z· get variables from stream as dictionary

        variable_names   - optional list of variable names to get

        If variable_names is None, then get all variables in file
        Nr   Ú__globals__ÚNoneÚlatin1zŒDuplicate variable name "%s" in stream - replacing previous with new
Consider mio5.varmats_from_mat to split file into single variable filesrE   )Ú
stacklevelÚ Ú__function_workspace__FTzUnreadable variable "z", because "ú"zRead error: %s)r#   ÚstrÚlistr>   rH   rX   rV   Úend_of_streamr`   ÚnameÚdecodeÚwarningsÚwarnr   rb   r   ÚWarningÚ	is_globalr,   ÚremoveÚlenrA   r4   )	r=   Zvariable_namesÚmdictrU   Únext_positionrm   ra   ÚresÚerrr)   r)   r*   Úget_variables$  sV    

ýüþ
zMatFile5Reader.get_variablesc                 C   s¢   | j  d¡ |  ¡  |  ¡  g }|  ¡ sž|  ¡ \}}|jdu rBdn
|j d¡}|dkrZd}| j 	|¡}|j
rrd}nt |jd¡}| |||f¡ | j  |¡ q |S )	z list variables from stream r   Nrd   re   rg   rh   ZlogicalÚunknown)r>   rH   rX   rV   rl   r`   rm   rn   r<   Zshape_from_headerÚ
is_logicalr    ÚgetÚmclassr,   )r=   ÚvarsrU   rv   rm   ÚshapeÚinfor)   r)   r*   Úlist_variables]  s     zMatFile5Reader.list_variables)	NFFTFTTNF)T)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r7   rK   rV   rX   r`   rb   ry   r   Ú__classcell__r)   r)   rB   r*   r5   ”   s&            ö&#

9r5   c                 C   sÚ   t | ƒ}|  d¡ tt d d j}|  |¡}|  d¡ | ¡  | ¡  |  ¡ }g }| 	¡ sÖ|}| 
¡ \}}|jdu rzdn
|j d¡}|  |¡ || }	|  |	¡}
tƒ }| |¡ | |
¡ | d¡ | ||f¡ qT|S )a-   Pull variables out of mat 5 file as a sequence of mat file objects

    This can be useful with a difficult mat file, containing unreadable
    variables. This routine pulls the variables out in raw form and puts them,
    unread, back into a file stream for saving or reading. Another use is the
    pathological case where there is more than one variable of the same name in
    the file; this routine returns the duplicates, whereas the standard reader
    will overwrite duplicates in the returned dictionary.

    The file pointer in `file_obj` will be undefined. File pointers for the
    returned file-like objects are set at 0.

    Parameters
    ----------
    file_obj : file-like
        file object containing mat file

    Returns
    -------
    named_mats : list
        list contains tuples of (name, BytesIO) where BytesIO is a file-like
        object containing mat file contents as for a single variable. The
        BytesIO contains a string with the original header and a single var. If
        ``var_file_obj`` is an individual BytesIO instance, then save as a mat
        file with something like ``open('test.mat',
        'wb').write(var_file_obj.read())``

    Examples
    --------
    >>> import scipy.io
    >>> import numpy as np
    >>> from io import BytesIO
    >>> from scipy.io.matlab._mio5 import varmats_from_mat
    >>> mat_fileobj = BytesIO()
    >>> scipy.io.savemat(mat_fileobj, {'b': np.arange(10), 'a': 'a string'})
    >>> varmats = varmats_from_mat(mat_fileobj)
    >>> sorted([name for name, str_obj in varmats])
    ['a', 'b']
    r   rL   rM   Nrd   re   )r5   rH   r   r   ÚitemsizerI   rX   rV   rZ   rl   r`   rm   rn   r   Úwriter,   )Zfile_objÚrdrZhdr_lenZraw_hdrrv   Z
named_matsZstart_positionrU   rm   r]   Zvar_strZout_objr)   r)   r*   Úvarmats_from_matv  s,    (







rŠ   c                   @   s   e Zd ZdZdS )ÚEmptyStructMarkerz= Class to indicate presence of empty matlab struct on output N)r‚   rƒ   r„   r…   r)   r)   r)   r*   r‹   º  s   r‹   c                 C   sP  t | tjƒr| S | du rdS t| dƒr0t | ¡S t| dƒoLt| dƒoLt| dƒ}t | tjƒr\n&|s‚t| dƒr‚dd„ | j ¡ D ƒ} d	}|rìg }g }|  ¡ D ]:\}}t |tƒr–|d
 dvr–| 	t|ƒt
f¡ | 	|¡ q–|rèt t|ƒg|¡S tS zt | ¡}W n" ty   tj| t
d}Y n0 |jjt
tjfv rL|jdkrL|| krLdS |S )aÙ   Convert input object ``source`` to something we can write

    Parameters
    ----------
    source : object

    Returns
    -------
    arr : None or ndarray or EmptyStructMarker
        If `source` cannot be converted to something we can write to a matfile,
        return None.  If `source` is equivalent to an empty dictionary, return
        ``EmptyStructMarker``.  Otherwise return `source` converted to an
        ndarray with contents for writing to matfile.
    NZ	__array__ÚkeysÚvaluesÚitemsr0   c                 S   s    i | ]\}}|  d ¡s||“qS )Ú_)Ú
startswith)Ú.0r3   Úvaluer)   r)   r*   Ú
<dictcomp>Û  s   
ÿz to_writeable.<locals>.<dictcomp>Tr   Z_0123456789©Údtyper)   )r#   r$   r%   ÚhasattrÚasarrayZgenericr0   rŽ   rj   r,   ÚobjectÚarrayÚtupler‹   Z
asanyarrayrY   r•   ÚtypeZobject_r   )ÚsourceZ
is_mappingr•   r   Úfieldr’   Únarrr)   r)   r*   Úto_writeable¾  sJ    

ÿ

ÿÿÿrŸ   rL   rM   Ztag_fullZtag_smalldataZarray_flagsc                   @   sº   e Zd ZdZe de¡Zeed< dd„ Z	dd„ Z
dd	„ Zd,dd„Zdd„ Zdd„ Zd-dd„Zdd„ Zdd„ Zdd„ Zdd„ Zd.dd„Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd
S )/Ú
VarWriter5z% Generic matlab matrix writing class r)   r\   c                 C   s0   |j | _ |j| _|j| _|j| _d | _d| _d S )NF)Úfile_streamÚunicode_stringsÚlong_field_namesÚoned_asÚ	_var_nameÚ_var_is_global)r=   Zfile_writerr)   r)   r*   r7     s    zVarWriter5.__init__c                 C   s   | j  |jdd¡ d S )NÚF©Úorder)r¡   rˆ   Útobytes©r=   Úarrr)   r)   r*   Úwrite_bytes  s    zVarWriter5.write_bytesc                 C   s   | j  |¡ d S ©N)r¡   rˆ   )r=   Úsr)   r)   r*   Úwrite_string  s    zVarWriter5.write_stringNc                 C   sr   |du rt |jjdd…  }|jjtkr<| ¡  |j ¡ ¡}|j|j	 }|dkr`|  
|||¡ n|  |||¡ dS )z write tag and data Nr   é   )r   r•   rj   Ú	byteorderr   ÚbyteswapÚviewZnewbyteorderr&   r‡   Úwrite_smalldata_elementÚwrite_regular_element)r=   r¬   r\   r]   r)   r)   r*   Úwrite_element  s    zVarWriter5.write_elementc                 C   s:   t  dt¡}|d> | |d< |jdd|d< |  |¡ d S )Nr)   é   Zbyte_count_mdtyper§   r¨   Údata)r$   ÚzerosÚNDT_TAG_SMALLrª   r­   )r=   r¬   r\   r]   Útagr)   r)   r*   rµ     s    z"VarWriter5.write_smalldata_elementc                 C   sT   t  dt¡}||d< ||d< |  |¡ |  |¡ |d }|rP| j dd|  ¡ d S )Nr)   r\   r]   rP   ó    )r$   rº   ÚNDT_TAG_FULLr­   r¡   rˆ   )r=   r¬   r\   r]   r¼   Zbc_mod_8r)   r)   r*   r¶   &  s    

z VarWriter5.write_regular_elementFr   c           
      C   sÌ   | j }| j}| j ¡ | _|  | j¡ t dt	¡}t
|d< d|d< |d> |d> B |d> B }	||	d> B |d< ||d	< |  |¡ |  tj|d
d¡ t |¡}|dkr°|  |td¡ n|  |t¡ d| _ d| _dS )a›   Write header for given data options
        shape : sequence
           array shape
        mclass      - mat5 matrix class
        is_complex  - True if matrix is complex
        is_logical  - True if matrix is logical
        nzmax        - max non zero elements for sparse arrays

        We get the name and the global flag from the object, and reset
        them to defaults after we've used them
        r)   Z	data_typerP   r]   é   rE   r   Zflags_classÚnzmaxÚi4r”   rg   r   FN)r¥   r¦   r¡   rZ   Z_mat_tag_posr­   Úmat_tagr$   rº   ÚNDT_ARRAY_FLAGSr   r·   r™   r—   rµ   r   )
r=   r   r}   Ú
is_complexr{   rÀ   rm   rr   ÚafÚflagsr)   r)   r*   Úwrite_header2  s$    

zVarWriter5.write_headerc                 C   sX   | j  ¡ }| j  |¡ || d }|dkr2tdƒ‚|| jd< |  | j¡ | j  |¡ d S )NrP   l        z-Matrix too large to save with Matlab 5 formatr]   )r¡   rZ   rH   r   rÂ   r­   )r=   Ú	start_posÚcurr_posr]   r)   r)   r*   Úupdate_matrix_tag]  s    

zVarWriter5.update_matrix_tagc                 C   s   || _ || _|  |¡ dS )aˆ   Write variable at top level of mat file

        Parameters
        ----------
        arr : array_like
            array-like object to create writer for
        name : str, optional
            name as it will appear in matlab workspace
            default is empty string
        is_global : {False, True}, optional
            whether variable will be global on load into matlab
        N)r¦   r¥   rˆ   )r=   r¬   rm   rr   r)   r)   r*   Ú	write_toph  s    zVarWriter5.write_topc                 C   sþ   | j  ¡ }tj |¡r.|  |¡ |  |¡ dS t|ƒ}|du rXtd|› dt	|ƒ› dƒ‚t
|tƒrn|  |¡ n‚t
|tƒr‚tdƒ‚nn|tu r”|  ¡  n\|jjr¨|  |¡ nH|jjr¼|  |¡ n4|jjdv ræ| jrÔd}nd}|  ||¡ n
|  |¡ |  |¡ dS )	z¨ Write `arr` to stream at top and sub levels

        Parameters
        ----------
        arr : array_like
            array-like object to create writer for
        NzCould not convert z (type z
) to arrayzCannot write matlab functions)ÚUÚSÚUTF8Úascii)r¡   rZ   ÚscipyÚsparseÚissparseÚwrite_sparserÊ   rŸ   r[   r›   r#   r   Úwrite_objectr   r   r‹   Úwrite_empty_structr•   ÚfieldsÚwrite_structZ	hasobjectÚwrite_cellsÚkindr¢   Ú
write_charÚwrite_numeric)r=   r¬   Zmat_tag_posrž   Úcodecr)   r)   r*   rˆ   |  s2    	







zVarWriter5.writec                 C   s¸   |j jdk}|j jdk}zt|j jdd …  }W n@ typ   |rN| d¡}n|r^| d¡}n
| d¡}t}Y n0 | jt|| j	ƒ|||d |rª|  
|j¡ |  
|j¡ n
|  
|¡ d S )NÚcÚbr   Zc128Úi1Zf8)rÄ   r{   )r•   rÙ   r   rj   ÚKeyErrorÚastyper   rÇ   r   r¤   r·   ÚrealÚimag)r=   r¬   ZimagfZlogifr}   r)   r)   r*   rÛ   £  s(    

ýzVarWriter5.write_numericrÏ   c                 C   sÒ   |j dkst |dk¡rJdt |jdg¡ }|  |t¡ |  |td¡ dS t	|ƒ}|j
}|  |t¡ |jjdkrÀ|j rÀt |¡}tjdt||ƒ|j ¡ d}| ¡  |¡}tjt|ƒfd	|d}| j|td
 dS )z5 Write string array `arr` with given `codec`
        r   rg   ©r   rE   NrÌ   r)   ©r   r•   ÚbufferZS1©r\   )r&   r$   ÚallÚmaxr'   rÇ   r   rµ   r   r
   r   r•   rÙ   Úprodr%   r   ÚTÚcopyrS   Úencodert   r·   )r=   r¬   rÜ   r   Zn_charsZst_arrÚstr)   r)   r*   rÚ   ¼  s(    

þþzVarWriter5.write_charc                 C   sž   |  ¡ }| ¡  |jjdk}|jjdk}|j}| jt|| jƒt|||dkrNdn|d |  	|j
 d¡¡ |  	|j d¡¡ |  	|jj¡ |rš|  	|jj¡ dS )z  Sparse matrices are 2D
        rÝ   rÞ   r   r   )rÄ   r{   rÀ   rÁ   N)ZtocscZsort_indicesr•   rÙ   ZnnzrÇ   r   r¤   r   r·   Úindicesrá   Zindptrr¹   râ   rã   )r=   r¬   ÚArÄ   r{   Znzr)   r)   r*   rÓ   ç  s     ûzVarWriter5.write_sparsec                 C   s<   |   t|| jƒt¡ t |¡ d¡}|D ]}|  |¡ q(d S )Nr§   )rÇ   r   r¤   r   r$   Ú
atleast_2dÚflattenrˆ   )r=   r¬   rð   Úelr)   r)   r*   rØ   û  s    ÿzVarWriter5.write_cellsc                 C   s<   |   dt¡ |  tjdtjd¡ |  tjg tjd¡ d S )N)r   r   r   r”   )rÇ   r   r·   r$   r™   Zint32Zint8rW   r)   r)   r*   rÕ     s    zVarWriter5.write_empty_structc                 C   s"   |   t|| jƒt¡ |  |¡ d S r®   )rÇ   r   r¤   r   Ú_write_itemsr«   r)   r)   r*   r×   
  s    ÿzVarWriter5.write_structc                 C   s¶   dd„ |j jD ƒ}tdd„ |D ƒƒd }| jr2dp4d}||krNtd|d  ƒ‚|  tj|gdd	¡ | jtj|d
| d	td t 	|¡ 
d¡}|D ]}|D ]}|  || ¡ qœq”d S )Nc                 S   s   g | ]}|d  ‘qS rä   r)   )r‘   r2   r)   r)   r*   Ú
<listcomp>  ó    z+VarWriter5._write_items.<locals>.<listcomp>c                 S   s   g | ]}t |ƒ‘qS r)   )rt   )r‘   Ú	fieldnamer)   r)   r*   rõ     rö   r   é@   é    z+Field names are restricted to %d charactersrÁ   r”   zS%drç   r§   )r•   Údescrré   r£   rY   r·   r$   r™   r   rñ   rò   rˆ   )r=   r¬   Ú
fieldnamesÚlengthÚ
max_lengthrð   ró   r2   r)   r)   r*   rô     s     ÿþzVarWriter5._write_itemsc                 C   s<   |   t|| jƒt¡ | jtj|jddtd |  	|¡ dS )zmSame as writing structs, except different mx class, and extra
        classname element after header
        rÍ   r”   rç   N)
rÇ   r   r¤   r   r·   r$   r™   Ú	classnamer   rô   r«   r)   r)   r*   rÔ      s    ÿÿzVarWriter5.write_object)N)FFr   )rÏ   )r‚   rƒ   r„   r…   r$   rº   r¾   rÂ   r   r7   r­   r°   r·   rµ   r¶   rÇ   rÊ   rË   rˆ   rÛ   rÚ   rÓ   rØ   rÕ   r×   rô   rÔ   r)   r)   r)   r*   r    ý  s0   	
   û
+'
+r    c                   @   s0   e Zd ZdZeddd„ƒZdd„ Zdd	d
„ZdS )ÚMatFile5Writerz Class for writing mat5 files FNÚrowc                 C   s:   || _ || _|| _|r|| _ng | _|| _|| _d| _dS )a<   Initialize writer for matlab 5 format files

        Parameters
        ----------
        %(do_compression)s
        %(unicode_strings)s
        global_vars : None or sequence of strings, optional
            Names of variables to be marked as global for matlab
        %(long_fields)s
        %(oned_as)s
        N)r¡   Údo_compressionr¢   Úglobal_varsr£   r¤   Ú_matrix_writer)r=   r¡   r  r¢   r  r£   r¤   r)   r)   r*   r7   .  s    zMatFile5Writer.__init__c                 C   s\   t  dt¡}dtj› dt ¡ › |d< d|d< t jddt  d¡d	|d
< | j	 
| ¡ ¡ d S )Nr)   zMATLAB 5.0 MAT-file Platform: z, Created on: rN   é   rO   ZS2iIM  rå   Zendian_test)r$   rº   ÚNDT_FILE_HDRÚosrm   ÚtimeÚasctimer%   Zuint16r¡   rˆ   rª   )r=   rU   r)   r)   r*   Úwrite_file_headerK  s    
ÿ
þ
z MatFile5Writer.write_file_headerc           	      C   sæ   |du r| j  ¡ dk}|r"|  ¡  t| ƒ| _| ¡ D ]¬\}}|d dkrJq4|| jv }| jrÊtƒ }|| j_ | j 	|| 
d¡|¡ t | ¡ ¡}t dt¡}t|d< t|ƒ|d< | j  | ¡ ¡ | j  |¡ q4| j 	|| 
d¡|¡ q4dS )aò   Write variables in `mdict` to stream

        Parameters
        ----------
        mdict : mapping
           mapping with method ``items`` returns name, contents pairs where
           ``name`` which will appear in the matlab workspace in file load, and
           ``contents`` is something writeable to a matlab file, such as a NumPy
           array.
        write_header : {None, True, False}, optional
           If True, then write the matlab file header before writing the
           variables. If None (the default) then write the file header
           if we are at position 0 in the stream. By setting False
           here, and setting the stream position to the end of the file,
           you can append variables to a matlab file
        Nr   r   re   r)   r\   r]   )r¡   rZ   r	  r    r  rŽ   r  r  r   rË   rí   ÚzlibÚcompressÚgetvaluer$   Úemptyr¾   r   rt   rˆ   rª   )	r=   ru   rÇ   rm   Úvarrr   r^   Zout_strr¼   r)   r)   r*   Úput_variablesV  s(    

zMatFile5Writer.put_variables)FFNFr   )N)r‚   rƒ   r„   r…   r   r7   r	  r  r)   r)   r)   r*   rÿ   +  s        ûrÿ   )>r…   r  r  r8   r
  Úior   ro   Únumpyr$   Zscipy.sparserÐ   Z_byteordercodesr   r   Z_miobaser   r   r   r	   r
   r   r   r   r   Z_mio5_utilsr   Z_mio5_paramsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   Z_streamsr"   r+   r.   r-   r4   r5   rŠ   r‹   rŸ   r  r¾   r»   rÃ   r    rÿ   r)   r)   r)   r*   Ú<module>   s<   G,P
 cD9  0