B
    -§,c'  ã               @   sL   d Z ddlmZmZmZmZ ddlZddlZddlm	Z	 G dd„ de	ƒZ
dS )zŒ
mrcfile
-------

Module which exports the :class:`MrcFile` class.

Classes:
    :class:`MrcFile`: An object which represents an MRC file.

é    )Úabsolute_importÚdivisionÚprint_functionÚunicode_literalsNé   )ÚMrcInterpreterc                   sv   e Zd ZdZd‡ fdd„	Zdd„ Zdd	„ Zd‡ fd
d„	Z‡ fdd„Zdd„ Z	‡ fdd„Z
dd„ Zd‡ fdd„	Z‡  ZS )ÚMrcFilea  An object which represents an MRC file.
    
    The header and data are handled as numpy arrays - see
    :class:`~mrcfile.mrcobject.MrcObject` for details.
        
    :class:`MrcFile` supports a permissive read mode for attempting to open
    corrupt or invalid files. See
    :class:`mrcfile.mrcinterpreter.MrcInterpreter` or the :doc:`usage guide
    <../usage_guide>` for more information.
    
    Usage:
        To create a new MrcFile object, pass a file name and optional mode. To
        ensure the file is written to disk and closed correctly, it's best to
        use the :keyword:`with` statement:
        
        >>> with MrcFile('tmp.mrc', 'w+') as mrc:
        ...     mrc.set_data(np.zeros((10, 10), dtype=np.int8))
        
        In mode ``r`` or ``r+``, the named file is opened from disk and read.
        In mode ``w+`` a new empty file is created and will be written to disk
        at the end of the :keyword:`with` block (or when
        :meth:`~.MrcInterpreter.flush` or :meth:`close` is called).
    
    ÚrFc                s¾   t t| ƒjf d|i|—Ž |dkr0td |¡ƒ‚t|ƒ}d|kr^tj |¡r^|s^td |¡ƒ‚|| _	| j	dk| _
|  |¡ y d|krŽ|  ¡  n
|  |¡ W n tk
r¸   |  ¡  ‚ Y nX dS )aÆ  Initialise a new :class:`MrcFile` object.
        
        The given file name is opened in the given mode. For mode ``r`` or
        ``r+`` the header, extended header and data are read from the file. For
        mode ``w+`` a new file is created with a default header and empty
        extended header and data arrays.
        
        Args:
            name: The file name to open, as a string or pathlib Path.
            mode: The file mode to use. This should be one of the following:
                ``r`` for read-only, ``r+`` for read and write, or ``w+`` for a
                new empty file. The default is ``r``.
            overwrite: Flag to force overwriting of an existing file if the
                mode is ``w+``. If :data:`False` and a file of the same name
                already exists, the file is not overwritten and an exception is
                raised. The default is :data:`False`.
            permissive: Read the file in permissive mode. (See
                :class:`mrcfile.mrcinterpreter.MrcInterpreter` for details.)
                The default is :data:`False`.
            header_only: Only read the header (and extended header) from the
                file. The default is :data:`False`.
        
        Raises:
            :exc:`ValueError`: If the mode is not one of ``r``, ``r+`` or
                ``w+``.
            :exc:`ValueError`: If the file is not a valid MRC file and
                ``permissive`` is :data:`False`.
            :exc:`ValueError`: If the mode is ``w+``, the file already exists
                and overwrite is :data:`False`.
            :exc:`OSError`: If the mode is ``r`` or ``r+`` and the file does
                not exist.
        
        Warns:
            RuntimeWarning: If the file appears to be a valid MRC file but the
                data block is longer than expected from the dimensions in the
                header.
            RuntimeWarning: If the file is not a valid MRC file and
                ``permissive`` is :data:`True`.
            RuntimeWarning: If the header's ``exttyp`` field is set to a known
                value but the extended header's size is not a multiple of the
                number of bytes in the corresponding dtype.
        Ú
permissive)r	   zr+zw+zMode '{0}' not supportedÚwz=File '{0}' already exists; set overwrite=True to overwrite itr	   N)Úsuperr   Ú__init__Ú
ValueErrorÚformatÚstrÚosÚpathÚexistsÚ_modeZ
_read_onlyÚ
_open_fileZ_create_default_attributesÚ_readÚ	ExceptionÚ_close_file)ÚselfÚnameÚmodeZ	overwriter
   Úheader_onlyÚkwargs)Ú	__class__© ú.lib/python3.7/site-packages/mrcfile/mrcfile.pyr   4   s"    ,

zMrcFile.__init__c             C   s   d  | jj| j¡S )NzMrcFile('{0}', mode='{1}'))r   Ú	_iostreamr   r   )r   r   r   r    Ú__repr__x   s    
zMrcFile.__repr__c             C   s   t || jd ƒ| _dS )z,Open a file object to use as the I/O stream.ÚbN)Úopenr   r!   )r   r   r   r   r    r   |   s    zMrcFile._open_filec                s    | j  d¡ tt| ƒ |¡ dS )z5Override _read() to move back to start of file first.r   N)r!   Úseekr   r   r   )r   r   )r   r   r    r   €   s    zMrcFile._readc                sj   |   ¡ }| jj| jj }|| }tt| ƒj|d | jdk	rf| jj}||k rfd || ¡}t	 
|t¡ dS )zAOverride _read_data() to check file size matches data block size.)Z	max_bytesNz*MRC file is {0} bytes larger than expected)Ú_get_file_sizeÚheaderÚnbytesZnsymbtr   r   Ú
_read_dataÚdatar   ÚwarningsÚwarnÚRuntimeWarning)r   Ú	file_sizeZheader_sizeZremaining_file_sizeZ	data_sizeÚmsg)r   r   r    r)   …   s    

zMrcFile._read_datac             C   s8   | j  ¡ }| j  dtj¡ | j  ¡ }| j  |tj¡ |S )z8Return the size of the underlying file object, in bytes.r   )r!   Útellr%   r   ÚSEEK_ENDÚSEEK_SET)r   ÚposÚsizer   r   r    r&   •   s
    

zMrcFile._get_file_sizec                s   t t| ƒ ¡  |  ¡  dS )zÊFlush any changes to disk and close the file.
        
        This override calls :meth:`.MrcInterpreter.close` to ensure the stream
        is flushed and closed, then closes the file object.
        N)r   r   Úcloser   )r   )r   r   r    r5      s    zMrcFile.closec             C   s   | j  ¡  dS )zClose the file object.N)r!   r5   )r   r   r   r    r   ¦   s    zMrcFile._close_fileNc                sr   t t| ƒj|d}| jdk	r^|  ¡ }| jj| jj | jj }||krntd 	||¡|d d}ntd|d d}|S )aˆ	  Validate this MRC file.
        
        The tests are:
        
        #. MRC format ID string: The ``map`` field in the header should
           contain "MAP ".
        #. Machine stamp: The machine stamp should contain one of
           ``0x44 0x44 0x00 0x00``, ``0x44 0x41 0x00 0x00`` or
           ``0x11 0x11 0x00 0x00``.
        #. MRC mode: the ``mode`` field should be one of the supported mode
           numbers: 0, 1, 2, 4, 6 or 12. (Note that MRC modes 3 and 101 are
           also valid according to the MRC 2014 specification but are not
           supported by mrcfile.)
        #. Map and cell dimensions: The header fields ``nx``, ``ny``, ``nz``,
           ``mx``, ``my``, ``mz``, ``cella.x``, ``cella.y`` and ``cella.z``
           must all be positive numbers.
        #. Axis mapping: Header fields ``mapc``, ``mapr`` and ``maps`` must
           contain the values 1, 2, and 3 (in any order).
        #. Volume stack dimensions: If the spacegroup is in the range 401--630,
           representing a volume stack, the ``nz`` field should be exactly
           divisible by ``mz`` to represent the number of volumes in the stack.
        #. Header labels: The ``nlabl`` field should be set to indicate the
           number of labels in use, and the labels in use should appear first
           in the label array.
        #. MRC format version: The ``nversion`` field should be 20140 or 20141
           for compliance with the MRC2014 standard.
        #. Extended header type: If an extended header is present, the
           ``exttyp`` field should be set to indicate the type of extended
           header.
        #. Data statistics: The statistics in the header should be correct for
           the actual data in the file, or marked as undetermined.
        #. File size: The size of the file on disk should match the expected
           size calculated from the MRC header.
        
        Args:
            print_file: The output text stream to use for printing messages
                about the validation. This is passed directly to the ``file``
                argument of Python's :func:`print` function. The default is
                :data:`None`, which means output will be printed to
                :data:`sys.stdout`.
        
        Returns:
            :data:`True` if the file is valid, or :data:`False` if the file
            does not meet the MRC format specification in any way.
        )Ú
print_fileNzgFile is larger than expected. Actual size: {0} bytes; expected size: {1} bytes (calculated from header))ÚfileFz4Data block could not be read - file size not checked)
r   r   Úvalidater*   r&   r'   r(   Zextended_headerÚprintr   )r   r6   Zvalidr.   Zmrc_size)r   r   r    r8   ª   s    .
zMrcFile.validate)r	   FFF)F)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r"   r   r   r)   r&   r5   r   r8   Ú__classcell__r   r   )r   r    r      s    C	r   )r=   Z
__future__r   r   r   r   r   r+   Zmrcinterpreterr   r   r   r   r   r    Ú<module>   s
   