3
PdT                 @   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
mZm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/m0Z0 dd
l1m2Z2 dd Z3dd Z4dd Z5dd Z6G dd deZ7dd Z8G dd de9Z:dd Z;e!e d d Z<e!e d d Z=e!e d d Z>e!e d d Z?G d d! d!e9Z@G d"d# d#e9ZAdS )$z 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)
    N)BytesIO)asbytesasstr   )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"t | d tS )zBDetermine if elem is an array and if first array item is a struct.r   )
isinstancenpndarraysizer#   )elem r*   H/var/www/html/virt/lib64/python3.6/site-packages/scipy/io/matlab/mio5.py_has_structk   s    r,   c             C   sR   g }xH| D ]@}t |tr(|jt| q
t|r@|jt| q
|j| q
W |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/   q   s    

r/   c             C   sX   i }xN| j D ]D}| j| }t|tr2t|||< qt|rHt|||< q|||< qW |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   sN   xH| D ]@}t | | tr*t| | | |< qt| | rt| | | |< qW | S )z,Convert mat objects in dict to nested dicts.)r%   r#   r.   r,   r/   )r2   keyr*   r*   r+   _simplify_cells   s    
r5   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 stardard 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          
      sB   t t| j|||||||||
	 |	s,tj }	|	| _d| _d| _dS )zInitializer 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)superr6   __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+   r8      s    
zMatFile5Reader.__init__c             C   s4   | j jd | j jd}| j jd |dkr0dp2dS )z4 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 j j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 j \}}|dkstd| jj | }|tkrbt| j|}| jj| | j	}| jj \}}nd}| jj| j |t
kstd| | j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_streamrA   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 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   sv  t |tr|g}n|dk	r"t|}| jjd | j  | j }g |d< x| j s\| j \}}t	|j
}||krtjd| tdd |dkrd}d	}nd
}|dk	r||kr| jj| qJy| j||}W nD tk
r } z&tjd||f tdd d| }W Y dd}~X nX | jj| |||< |jr:|d j| |dk	rJ|j| t|dkrJP qJW | jrnt|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__zDuplicate 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 "%s", because "%s"zRead error: %s)r%   strlistr?   rH   rW   rV   end_of_streamr_   r   namewarningswarnr   ra   r   Warning	is_globalr-   removelenrB   r5   )	r>   Zvariable_namesmdictrU   next_positionri   r`   reserrr*   r*   r+   get_variables'  sR    




zMatFile5Reader.get_variablesc             C   s   | j jd | j  | j  g }xp| j s| j \}}t|j}|dkrLd}| jj	|}|j
rdd}ntj|jd}|j|||f | j j| q"W |S )z list variables from stream r   rd   re   logicalunknown)r?   rH   rW   rV   rh   r_   r   ri   r=   Zshape_from_header
is_logicalr"   getmclassr-   )r>   varsrU   rq   ri   shapeinfor*   r*   r+   list_variablesa  s     

zMatFile5Reader.list_variables)	NFFTFTTNF)T)N)__name__
__module____qualname____doc__r	   r8   rK   rV   rW   r_   ra   rt   r}   __classcell__r*   r*   )rC   r+   r6      s$           #

:r6   c             C   s   t | }| jd tt d d j}| j|}| jd |j  |j  | j }g }xt|j	 s|}|j
 \}}t|j}| j| || }	| j|	}
t }|j| |j|
 |jd |j||f qVW |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

    BytesIO is from the ``io`` module in Python 3, and is ``cStringIO`` for
    Python < 3.

    >>> 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   )r6   rH   r   r   itemsizerI   rW   rV   rY   rh   r_   r   ri   r   writer-   )Zfile_objrdrZhdr_lenZraw_hdrrq   Z
named_matsZstart_positionrU   ri   r\   Zvar_strZout_objr*   r*   r+   varmats_from_matz  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   s  t | tjr| S | dkrdS t| do8t| do8t| d}t | tjrHn,| rtt| drttdd | jj D } d}|rg }g }xF| j D ]:\}}t |tr|d	 d
kr|j	t|t
f |j	| qW |rtjt|g|S tS tj| }|jjt
tjfkr|jf kr|| krd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.
    Nkeysvaluesitemsr1   c             s   s$   | ]\}}|j d s||fV  qdS )_N)
startswith).0r4   valuer*   r*   r+   	<genexpr>  s    zto_writeable.<locals>.<genexpr>Tr   Z_0123456789)r%   r&   r'   hasattrZgenericdictr1   r   rf   r-   objectarraytupler   Z
asanyarraydtypetypeZobject_r{   )sourceZ
is_mappingr   r   fieldr   narrr*   r*   r+   to_writeable  s6    


r   rL   rM   Ztag_fullZtag_smalldataZarray_flagsc               @   s   e Zd ZdZejf 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[   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+   r8     s    zVarWriter5.__init__c             C   s   | j 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 j| d S )N)r   r   )r>   sr*   r*   r+   write_string  s    zVarWriter5.write_stringNc             C   sj   |dkrt |jjdd  }|jjtkr4|j j }|j|j }|dkrX| j	||| n| j
||| dS )z write tag and data Nr      )r   r   rf   	byteorderr   byteswapZ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 jf t}|d> | |d< |jdd|d< | j| d S )N   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 jf t}||d< ||d< | j| | j| |d }|rP| jjdd|   d S )Nr[   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 | _| j| j tjf t	}t
|d< d|d< |d> |d> B |d> B }	||	d> B |d< ||d< | j| | jtj|d	d
 tj|}|dkr| j|td n| j|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
        Z	data_typerP   r\      rE   r   Zflags_classnzmaxi4)r   rd   r   FN)r   r   r   rY   Z_mat_tag_posr   mat_tagr&   r   NDT_ARRAY_FLAGSr   r   r   Zasarrayr   r   )
r>   r{   ry   
is_complexrw   r   ri   rm   afflagsr*   r*   r+   write_header2  s$    

zVarWriter5.write_headerc             C   sX   | j j }| j j| || d }|dkr2td|| jd< | j| j | j j| d S )NrP   rE       z-Matrix too large to save with Matlab 5 formatr\   l        )r   rY   rH   r   r   r   )r>   	start_posZcurr_posr\   r*   r*   r+   update_matrix_tag]  s    

zVarWriter5.update_matrix_tagc             C   s   || _ || _| j| 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   ri   rm   r*   r*   r+   	write_toph  s    zVarWriter5.write_topc             C   s   | j j }tjj|r.| j| | j| dS t|}|dkrRtd|t	|f t
|trh| j| nt
|tr|tdnn|tkr| j  n\|jjr| j| nH|jjr| j| n4|jjdkr| jrd}nd}| j|| n
| j| | j| 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 %s (type %s) to arrayzCannot write matlab functionsUSUTF8ascii)r   r   )r   rY   scipysparseissparsewrite_sparser   r   rZ   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   |  s4    	







zVarWriter5.writec             C   s   |j jdk}|j jdk}yt|j jdd   }W nB tk
rr   |rP|jd}n|r`|jd}n
|jd}t}Y nX | jt|| j	|||d |r| j
|j | j
|j n
| j
| d S )Ncbr   Zc128i1Zf8)r   rw   )r   r   r   rf   KeyErrorastyper!   r   r
   r   r   realimag)r>   r   ZimagfZlogifry   r*   r*   r+   r     s&    

zVarWriter5.write_numericr   c             C   s   |j dkstj|dkrJd	tj|jdg }| j|t | j|td dS t	|}|j
}| j|t |jjdkr|j rtj|}tjf t|||jj d}|j j|}tjt|fd|d}| j|td dS )
z5 Write string array `arr` with given `codec`
        r   rd   rE   Nr   )r{   r   bufferZS1)r[   )r   )r(   r&   allmaxndimr   r   r   r   r   r{   r   r   prodr'   r   TcopyrS   encodero   r   )r>   r   r   r{   Zn_charsZst_arrstr*   r*   r+   r     s$    

zVarWriter5.write_charc             C   s   |j  }|j  |jjdk}|jjdk}|j}| jt|| jt|||dkrNdn|d | j	|j
jd | j	|jjd | j	|jj |r| j	|jj dS )z  Sparse matrices are 2D
        r   r   r   r   )r   rw   r   r   N)ZtocscZsort_indicesr   r   Znnzr   r
   r   r    r   indicesr   Zindptrr   r   r   )r>   r   Ar   rw   Znzr*   r*   r+   r     s    zVarWriter5.write_sparsec             C   s@   | j t|| jt tj|jd}x|D ]}| j| q*W 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<   | j dt | jtjdtjd | jtjg tjd d S )Nr   )r   )r   r   )r   r   r   r&   r   Zint32Zint8)r>   r*   r*   r+   r     s    zVarWriter5.write_empty_structc             C   s"   | j t|| jt | j| d S )N)r   r
   r   r   _write_items)r>   r   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  | jtj|gdd	 | jtj|d
| d	td tj	|j
d}x(|D ] }x|D ]}| j||  qW qW d S )Nc             S   s   g | ]}|d  qS )r   r*   )r   r3   r*   r*   r+   
<listcomp>  s    z+VarWriter5._write_items.<locals>.<listcomp>c             S   s   g | ]}t |qS r*   )ro   )r   	fieldnamer*   r*   r+   r     s    r   @   r   z+Field names are restricted to %d charactersr   )r   zS%d)r[   r   )r   descrr   r   rX   r   r&   r   r   r   r   r   )r>   r   
fieldnameslength
max_lengthr   r   r3   r*   r*   r+   r     s    

zVarWriter5._write_itemsc             C   s<   | j t|| jt | jtj|jddtd | j	| 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+   r   !  s
    zVarWriter5.write_object)N)FFr   )r   )r~   r   r   r   r&   r   r   r   r   r8   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r*   r*   r*   r+   r     s.   	
  
&(
+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+   r8   /  s    zMatFile5Writer.__init__c             C   sX   t jf t}dtjtj f |d< d|d< t jf dt jdd|d< | j	j
|j  d S )	Nz0MATLAB 5.0 MAT-file Platform: %s, Created on: %srN      rO   ZS2iIM  )r{   r   r   Zendian_test)r&   r   NDT_FILE_HDRosri   timeasctimer'   Zuint16r   r   r   )r>   rU   r*   r*   r+   write_file_headerL  s    z MatFile5Writer.write_file_headerc       	      C   s   |dkr| j j dk}|r"| j  t| | _x|j D ]\}}|d dkrLq6|| jk}| jrt }|| j_ | jj	|t
|| tj|j }tjf t}t|d< t||d< | j j|j  | j j| q6| jj	|t
|| q6W d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   r[   r\   )r   rY   r   r   r   r   r   r   r   r   r   zlibcompressgetvaluer&   emptyr   r   ro   r   r   )	r>   rp   r   ri   varrm   r]   Zout_strr   r*   r*   r+   put_variablesW  s(    

zMatFile5Writer.put_variables)FFNFr   )N)r~   r   r   r   r	   r8   r   r  r*   r*   r*   r+   r   ,  s       r   )Br   r   r   r9   r   ior   rj   Znumpyr&   Znumpy.compatr   r   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#   streamsr$   r,   r/   r.   r5   r6   r   r   r   r   r   r   r   r   r   r   r*   r*   r*   r+   <module>   s>   B,P
 dE4  1