๓
฿ศ[c           @` s  d  Z  d d l m Z m Z m Z m Z d d l m Z d d l m	 Z	 d d l
 Z
 d d l Z d d l m Z m Z d d l m Z m Z d d l Z d d	 l m Z d d
 l m Z d d l m Z d d l m Z d d g Z d g Z d e d  Z d e f d     YZ  d S(   u(   General purpose timer related functions.i    (   t   absolute_importt   divisiont   print_functiont   unicode_literalsi   (   t   six(   t   rangeN(   t   Iterablet   OrderedDict(   t   partialt   wraps(   t   units(   t   log(   t   modelingi   (   t   AstropyUserWarningu   timefuncu   RunTimePredictorc         ` s      f d   } | S(   uU  Decorator to time a function or method.

    Parameters
    ----------
    num_tries : int, optional
        Number of calls to make. Timer will take the
        average run time.

    verbose : bool, optional
        Extra log information.

    Returns
    -------
    tt : float
        Average run time in seconds.

    result
        Output(s) from the function.

    Examples
    --------
    To add timer to time `numpy.log` for 100 times with
    verbose output::

        import numpy as np
        from astropy.utils.timer import timefunc

        @timefunc(100)
        def timed_log(x):
            return np.log(x)

    To run the decorated function above:

    >>> t, y = timed_log(100)
    INFO: timed_log took 9.29832458496e-06 s on AVERAGE for 100 call(s). [...]
    >>> t
    9.298324584960938e-06
    >>> y
    4.6051701859880918

    c         ` s%   t         f d    } | S(   Nc          ` s~   t  j    } x# t   D] }   |  |   } q Wt  j    } | |  }  rt t j d j   j |    n  | | f S(   Nu*   {0} took {1} s on AVERAGE for {2} call(s).(   t   timeR   R   t   infot   formatt   __name__(   t   argst   kwargst   tst   it   resultt   tet   tt(   t   functiont	   num_triest   verbose(    s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   wrapperI   s    (   R	   (   R   R   (   R   R   (   R   s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   real_decoratorH   s    !(    (   R   R   R   (    (   R   R   s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   timefunc   s    *t   RunTimePredictorc           B` s   e  Z d  Z d   Z e d    Z e d d d e  d    Z d   Z	 d   Z
 d d d d	 d
  Z d   Z d d d d d  Z RS(   uฉ  Class to predict run time.

    .. note:: Only predict for single varying numeric input parameter.

    Parameters
    ----------
    func : function
        Function to time.

    args : tuple
        Fixed positional argument(s) for the function.

    kwargs : dict
        Fixed keyword argument(s) for the function.

    Examples
    --------
    >>> from astropy.utils.timer import RunTimePredictor

    Set up a predictor for :math:`10^{x}`:

    >>> p = RunTimePredictor(pow, 10)

    Give it baseline data to use for prediction and
    get the function output values:

    >>> p.time_func(range(10, 1000, 200))
    >>> for input, result in sorted(p.results.items()):
    ...     print("pow(10, {0})\n{1}".format(input, result))
    pow(10, 10)
    10000000000
    pow(10, 210)
    10000000000...
    pow(10, 410)
    10000000000...
    pow(10, 610)
    10000000000...
    pow(10, 810)
    10000000000...

    Fit a straight line assuming :math:`\text{arg}^{1}` relationship
    (coefficients are returned):

    >>> p.do_fit()  # doctest: +SKIP
    array([1.16777420e-05,  1.00135803e-08])

    Predict run time for :math:`10^{5000}`:

    >>> p.predict_time(5000)  # doctest: +SKIP
    6.174564361572262e-05

    Plot the prediction:

    >>> p.plot(xlabeltext='Power of 10')  # doctest: +SKIP

    .. image:: /_static/timer_prediction_pow10.png
        :width: 450px
        :alt: Example plot from `astropy.utils.timer.RunTimePredictor`

    When the changing argument is not the last, e.g.,
    :math:`x^{2}`, something like this might work:

    >>> p = RunTimePredictor(lambda x: pow(x, 2))
    >>> p.time_func([2, 3, 5])
    >>> sorted(p.results.items())
    [(2, 4), (3, 9), (5, 25)]

    c         O` sd   | j  |  _ t | | |  |  _ t   |  _ g  |  _ t   |  _ t   |  _ d  |  _
 d  |  _ d  S(   N(   R   t	   _funcnameR   t   _pfuncR   t   _cache_goodt
   _cache_badt
   _cache_estt
   _cache_outt   Nonet	   _fit_funct   _power(   t   selft   funcR   R   (    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   __init__   s    		c         C` s   |  j  S(   uจ   Function outputs from `time_func`.

        A dictionary mapping input arguments (fixed arguments
        are not included) to their respective output values.

        (   R%   (   R)   (    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   resultsง   s    R   i   R   c         C` s   |  j  |  S(   u1   Run partial func once for single arg and time it.(   R!   (   R)   t   arg(    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   _timed_pfuncฑ   s    c         C` s   | |  j  k r | |  j k r y |  j |  } Wn9 t k
 rl } t j t |  t  |  j j |  q X| d |  j  | <| d |  j	 | <n  d S(   u(   Cache timing results without repetition.i    i   N(
   R"   R#   R.   t	   Exceptiont   warningst   warnt   strR   t   appendR%   (   R)   R-   R   t   e(    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   _cache_timeถ   s    c         C` s=   t  | t  s | g } n  x | D] } |  j |  q" Wd S(   uE  Time the partial function for a list of single args
        and store run time in a cache. This forms a baseline for
        the prediction.

        This also stores function outputs in `results`.

        Parameters
        ----------
        arglist : list of numbers
            List of input arguments to time.

        N(   t
   isinstanceR   R5   (   R)   t   arglistR-   (    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyt	   time_funcย   s    i   c         C` s=  | |  _  t   |  _ t j t t j |  j    } | j	 | k  rc t
 d j | | j	    n  | d k r t j j d  } n3 t | t j j  sท t j j d j |    n  | d k rี t j j   } n3 t | t j j  st j j d j |    n  | | | | t t j |  j    |  _ |  j j S(   u5  Fit a function to the lists of arguments and
        their respective run time in the cache.

        By default, this does a linear least-square fitting
        to a straight line on run time w.r.t. argument values
        raised to the given power, and returns the optimal
        intercept and slope.

        Parameters
        ----------
        model : `astropy.modeling.Model`
            Model for the expected trend of run time (Y-axis)
            w.r.t. :math:`\text{arg}^{\text{power}}` (X-axis).
            If `None`, will use `~astropy.modeling.polynomial.Polynomial1D`
            with ``degree=1``.

        fitter : `astropy.modeling.fitting.Fitter`
            Fitter for the given model to extract optimal coefficient values.
            If `None`, will use `~astropy.modeling.fitting.LinearLSQFitter`.

        power : int, optional
            Power of values to fit.

        min_datapoints : int, optional
            Minimum number of data points required for fitting.
            They can be built up with `time_func`.

        Returns
        -------
        a : array-like
            Fitted `~astropy.modeling.FittableModel` parameters.

        Raises
        ------
        ValueError
            Insufficient data points for fitting.

        ModelsError
            Invalid model or fitter.

        u   requires {0} points but has {1}i   u   {0} is not a model.u   {0} is not a fitter.N(   R(   R   R$   t   npt   arrayt   listR   t   iterkeysR"   t   sizet
   ValueErrorR   R&   R   t   modelst   Polynomial1DR6   t   coret   Modelt   fittingt   ModelsErrort   LinearLSQFittert   Fittert
   itervaluesR'   t
   parameters(   R)   t   modelt   fittert   powert   min_datapointst   x_arr(    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   do_fitื   s&    +	!			(c         C` sd   | |  j  k r |  j  | } nA |  j d k r= t d   n  |  j | |  j  } | |  j  | <| S(   uช  Predict run time for given argument.
        If prediction is already cached, cached value is returned.

        Parameters
        ----------
        arg : number
            Input argument to predict run time for.

        Returns
        -------
        t_est : float
            Estimated run time for given argument.

        Raises
        ------
        RuntimeError
            No fitted data for prediction.

        u   no fitted data for predictionN(   R$   R'   R&   t   RuntimeErrorR(   (   R)   R-   t   t_est(    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   predict_time  s    u   linearu   argsu    c      	   C` s|  d d l  j } t |  j  } t j g  | D] } |  j | ^ q+  } t |  d k rh t d   n  | j   t	 j
 }	 x[ t	 j t	 j
 t	 j t	 j t	 j f D]5 }
 |	 j |
  } d | k oฬ d k n r  Pq  q  W| t	 j
 j |
  } | j   \ } } | j | | d d d |  j d k	 r๏t t j |  j   } t j t t j |  j    t	 j
 j |
  } | j | | d	 d
 d d d d t j t | |   } |  j | |  j  t	 j
 j |
  } | j | | d d d n  | j |  | j |  | j |  | j d j |
 j      | j! |  j"  | j# d d d d  | j$   | rx| j% |  n  d S(   uา  Plot prediction.

        .. note:: Uses `matplotlib <http://matplotlib.org/>`_.

        Parameters
        ----------
        xscale, yscale : {'linear', 'log', 'symlog'}
            Scaling for `matplotlib.axes.Axes`.

        xlabeltext : str, optional
            Text for X-label.

        save_as : str, optional
            Save plot as given filename.

        Raises
        ------
        RuntimeError
            Insufficient data for plotting.

        i    Ni   u   insufficient data for plottingi่  u   kx-t   labelu   Actualt   markeru   ot   cu   ru	   Predictedu   b--u   Fitu   Run time ({})t   locu   bestt	   numpoints(&   t   matplotlib.pyplott   pyplott   sortedR"   R9   R:   t   lenRO   t   meant   ut   secondt   minutet   millisecondt   microsecondt
   nanosecondt   to_valuet   subplotst   plotR'   R&   R;   R   R<   R$   RG   t   scatterR(   t
   set_xscalet
   set_yscalet
   set_xlabelt
   set_ylabelR   t	   to_stringt	   set_titleR    t   legendt   drawt   savefig(   R)   t   xscalet   yscalet
   xlabeltextt   save_ast   pltRM   t   xt   y_arrt   qmeant   cur_ut   valt   figt   axt   x_estt   y_estt   x_fitt   y_fit(    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyRd   8  s@    )"
N(   R   t
   __module__t   __doc__R+   t   propertyR,   R   t   FalseR.   R5   R8   R&   RN   RQ   Rd   (    (    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyR   X   s   D	

		D		(!   R   t
   __future__R    R   R   R   t   externR   t   extern.six.movesR   R   R0   t   collectionsR   R   t	   functoolsR   R	   t   numpyR9   t    R
   R\   R   R   t
   exceptionsR   t   __all__t   __doctest_skip__t   TrueR   t   objectR   (    (    (    s2   lib/python2.7/site-packages/astropy/utils/timer.pyt   <module>   s    "	: