
`9Sc           @   sm   d  d l  Z  d  d l Z d  d l Z d  d l Z d  d l Td  d l m Z d g Z d e	 f d     YZ
 d S(   iN(   t   *(   t   txtt   MatlabProcessc           B   s   e  Z d  Z e   Z e e  Z e e  Z d   Z	 d d  Z d   Z d   Z d d  Z d   Z d   Z d	   Z d
   Z e d    Z e d d   Z e d    Z d   Z d   Z d   Z d   Z d   Z d   Z RS(   s
  Base class for wrappers around standalone optimization procedures
    implemented in Matlab language.

    Call 'startRetrieval' to launch the Matlab process; use 'getErrorMessage'
    and 'getRetrievalOutput' to get the retrieval results upon completion.

    Signals:
      - 'retrievalFinished': the retrieval process has either successfully
        completed or terminated with an error.
      - 'outputAvailable(outputLine)': new line of text has been printed by the
        Malab application to either standard output or standard error stream.
      - 'iterationCompleted(iterCount)': a new iteration has been completed by
        the optimization process. 'iterCount' is the number of the iteration,
        starting with 0 for the initial approximation.

    Matlab scripts (named '<program-name>.m') are assumed to be stored in the
    'code/binary/MATLAB' subdirectory of the program package root, so that
    compiled Matlab executables are placed in
    'code/binary/MATLAB/<program-name>/distrib'.

    Auxiliary data files in HDF5 format (with a predefined structure) are
    used to pass input data as well as optimization results (including the
    whole set of intermediate data that realized during the steps of the
    iterative process) to and from the Matlab program.

    Data type used to represent the retrieval results is not predetermined;
    the value returned by 'readOutputData' actually defines it.

    Redefine 'getMatlabProgramName' method to specify the name of the Matlab
    application. Redefine 'writeInputData' along with 'readOutputData' to
    implement the procedure of passing the data to and from the auxiliary data
    file. Use 'extendArray', 'readArray', and 'readScalar' for assistance in
    the process of data preparation and extraction, if required.c         C   s   t  j |   t j j d |  j   d  } t j j | |  j   d  |  _ t j j | d  |  _ t   |  _	 |  j	 j
 t j  |  j	 j j |  j  |  j	 j j |  j  |  j	 j j |  j  d  |  _ d  |  _ d  S(   Ns   code/binary/MATLABt   distribs   .exes   data.h5(   t   QObjectt   __init__t   ost   patht   joint   getMatlabProgramNamet   applicationFilePatht   dataFilePatht   QProcesst   matlabProcesst   setProcessChannelModet   MergedChannelst	   readyReadt   connectt   onOutputAvailablet   errort   onProcessErrort   finishedt   onProcessFinishedt   Nonet   errorMessaget   retrievalOutputs(   t   selft	   matlabDir(    (    s   code\MatlabProcess.pyR   G   s    	c         C   s   | d k	 r, | |  _ t j d |  j  d Sy |  j   Wn6 t j k
 rr } | j |  _ t j d |  j  d SX|  j	 j
 t j j |  j   |  j	 j |  j  d S(   s  Launch the optimization process and return immediately.

        If 'errorMessage' is not 'None', the optimization process won't start,
        and 'retrievalFinished' signal will be fired as soon as program control
        returns to the application event loop (with 'getErrorMessage' returning
        the specified error message). The same thing will happen (but with a
        different error message) if problems would arise during initialization
        of the auxiliary data file.i    N(   R   R   t   QTimert
   singleShott   onInitFailedt   writeMatlabInputR   t   Errort   textR   t   setWorkingDirectoryR   R   t   dirnameR   t   startR
   (   R   R   t   e(    (    s   code\MatlabProcess.pyt   startRetrieval`   s    		c         C   s=   |  j  j j |  j  |  j  j j |  j  |  j  j   d S(   sa   Stop the running retrieval process or do nothing if the process has
        not been started yet.N(   R   R   t
   disconnectR   R   R   t   kill(   R   (    (    s   code\MatlabProcess.pyt   cancelRetrieval   s    c         C   s   |  j  S(   s   Return a rich text message describing a failed retrieval or 'None'
        if the retrieval has succeeded or has not finished yet.(   R   (   R   (    (    s   code\MatlabProcess.pyt   getErrorMessage   s    ic         C   s   |  j  d k r d S|  j  | S(   sR  Return a data instance (specific to the particular optimization
        procedure) describing a successful retrieval, or 'None' if the
        retrieval has failed or has not finished yet.

        If 'iteration' is not '-1', optimization process snapshot at the given
        iteration is returned instead of the final retrieval results.N(   R   R   (   R   t	   iteration(    (    s   code\MatlabProcess.pyt   getRetrievalOutput   s    c         C   s   |  j  S(   s   Return the complete list of the output data instances (specific to
        the particular optimization procedure), representing optimization
        process snapshots for all the iterations.(   R   (   R   (    (    s   code\MatlabProcess.pyt   getAllRetrievalOutputs   s    c         C   s   d S(   sp   Return the name of the Matlab script performing the optimization
        procedure (without the '.m' extension).N(   R   (   R   (    (    s   code\MatlabProcess.pyR	      s    c         C   s   d S(   s)  Write data required by the optimization process to the 'input'
        subgroup of the auxiliary HDF5 file.

        The 'input' HDF group (passed as the argument) is opened for writing.
        Apart from the name of the group, there are no restrictions imposed on
        the format of the data.N(    (   R   t   hdfGroup(    (    s   code\MatlabProcess.pyt   writeInputData   s    c         C   s   d S(   s  Extract data describing the given iteration of the optimization
        process from the 'output' subgroup of the auxiliary data file,
        returning a proper data instance.

        If the format of the data file is invalid, raise 'txt.Error' exception
        using the given error prefix.

        The 'output' HDF group (passed as the argument) is opened for reading.
        This group must contain a scalar integer dataset named 'iterCount'
        containing the total number of iterations (including the initial
        appoximation, i.e. the zeroth one) that have been realized in the
        optimization process.

        Apart from the name of the output group and the 'iterCount' dataset,
        there are no restrictions imposed on the format of the data.
        Nevertheless, these data should contain information about any of the
        iterations of the optimization process (normally, that should be
        achieved by adding an extra dimension to the respective HDF
        datasets).N(   R   (   R   R.   R+   t   errorPrefix(    (    s   code\MatlabProcess.pyt   readOutputData   s    c         C   su   | | t  |   k s t  t  |   d k s4 t  t j | t j  } |  | | | t  |   +|  d | d | +| S(   s  Return a copy of the given Numpy array converted to 'float64' data
        type, padded with 'firstDataIndex' copies of its first element at the
        beginning and with appropriate number of zeros at the end, so that the
        final length of the array is 'extendedSize'.i    (   t   lent   AssertionErrort   numpyt   zerost   float64(   t	   dataArrayt   firstDataIndext   extendedSizet   extArray(    (    s   code\MatlabProcess.pyt   extendArray   s    c   	      C   s   y |  | } Wn1 t  k
 rA t j | d t j |    n Xy | | | f } Wn1 t k
 r t j | d t j |    n Xt j | d t j } | d k	 r | t	 |  k  r t j
 | | f  } n  | S(   s}  Return a Numpy array with 'float32' data type corresponding to the
        'arrayIndex' row and 'iteration' layer (3-rd dimension) of an
        'hdfGroup's 3-dimensional dataset with the given name.

        If 'arraySize' is not 'None', return at most 'arraySize' first elements
        of the dataset row only.

        Raise 'txt.Error' using the given error prefix on failure.s   there is no dataset named %ss   %s dataset has invalid shapet   dtypeN(   t   KeyErrorR   R    t   quotet
   ValueErrorR4   t   arrayt   float32R   R2   t   resize(	   R.   t   datasetNamet
   arrayIndexR+   R0   t	   arraySizet   datasett	   arrayDataR7   (    (    s   code\MatlabProcess.pyt	   readArray   s    c         C   sW   t  j |  | | | |  } | j d k rM t j | d t j |    n  t |  S(   s  Same as 'readArray', but assume that the resulting array length is 1
        and return a scalar floating-point value representing that single array
        element.

        Raise 'txt.Error' using the given error prefix if the array has an
        unexpected shape.i   s   %s dataset has invalid shape(   i   (   R   RH   t   shapeR   R    R>   t   float(   R.   RC   RD   R+   R0   t   data(    (    s   code\MatlabProcess.pyt
   readScalar  s    	c         C   s~   yG t  j |  j d  } z  | j d  } |  j |  Wd | j   XWn0 t k
 ry t j d t j	 |  j    n Xd S(   s.   Prepare input file for the Matlab application.t   wt   inputNs*   Failed to write the Matlab input file (%s)(
   t   h5pyt   FileR   t   create_groupR/   t   closet   IOErrorR   R    t	   quotePath(   R   t   hdfFilet
   inputGroup(    (    s   code\MatlabProcess.pyR     s    	c   	      C   s  g  } y t  j |  j d  } Wn0 t k
 rQ t j d t j |  j    n Xzd t j |  j  } y | d } Wn1 t k
 r t j | d t j d    n Xy | d } Wn1 t k
 r t j | d t j d    n Xt	 j
 |  } | j d k r0t j | d	 t j d    n  t |  } x0 t |  D]" } | j |  j | | |   qIWWd
 | j   X| S(   s&  Construct a list of the output data instances representing snapshots
        of the optimization process at different iterations, based on the
        Matlab application output file.

        Final retrieval results will normally be represented by the last
        element of the returned list.t   rs*   Failed to read the Matlab output file (%s)s,   Failed to read the Matlab output file (%s): t   outputs   there is no group named %st	   iterCounts   there is no dataset named %si   s   %s dataset has invalid shapeN(   i   (   RO   RP   R   RS   R   R    RT   R=   R>   R4   R@   RI   t   intt   ranget   appendR1   RR   (	   R   R   RU   t   invalidFormatPrefixt   outputGroupt   iterDatasett	   iterArrayRY   R+   (    (    s   code\MatlabProcess.pyt   readMatlabOutput+  s:    				c         C   s   |  j  j   d  S(   N(   t   retrievalFinishedt   emit(   R   (    (    s   code\MatlabProcess.pyR   c  s    c         C   s   x |  j  j   r t |  j  j    } | j d  r< q n  |  j j |  t j d |  } | d  k	 r |  j
 j t | j d    q q Wd  S(   Ns   MATLAB:I18n:InconsistentLocales#   \s+(\d+)\s+\d+\s+\d\.\d+e[+-]\d+\s+i   (   R   t   canReadLinet   QStringt   readLinet
   startsWitht   outputAvailableRc   t   ret   matchR   t   iterationCompletedRZ   t   group(   R   t
   outputLinet   matchObj(    (    s   code\MatlabProcess.pyR   g  s    		c         C   sU   | t  j k r+ d t j |  j  |  _ n d t j |  j  |  _ |  j j   d  S(   Ns+   Failed to start the retrieval algorithm: %ss)   Failed to run the retrieval algorithm: %s(   R   t   FailedToStartR   RT   R
   R   Rb   Rc   (   R   t   processError(    (    s   code\MatlabProcess.pyR   z  s    c         C   s\   |  j  d  k	 r d  Sy |  j   |  _ Wn" t j k
 rJ } | j |  _  n X|  j j   d  S(   N(	   R   R   Ra   R   R   R    R!   Rb   Rc   (   R   t   exitCodet
   exitStatusR%   (    (    s   code\MatlabProcess.pyR     s    N(   t   __name__t
   __module__t   __doc__t
   pyqtSignalRb   Re   Rh   RZ   Rk   R   R   R&   R)   R*   R,   R-   R	   R/   R1   t   staticmethodR;   RH   RL   R   Ra   R   R   R   R   (    (    (    s   code\MatlabProcess.pyR      s.   !		$	
								8			(   RO   R4   t   os.pathR   Ri   t   PyQt4.QtCoret   common.utilsR   t   __all__R   R   (    (    (    s   code\MatlabProcess.pyt   <module>   s   
	