U

����� g������������������������@���s��d�Z�ddddddddd	d
ddd
dddgZddlZddlZddlZddlZddlZddlZG�dd��de	�Z
dd��Zdd��Zd*dd�Z
dd��Zdd��Zd+dd
�Zd,dd�Zdd��Zdd��Zd-d d�Zd!d	��Zd"d
��Zd#d��Zd$d%��ZG�d&d'��d'e	�ZG�d(d��de�ZG�d)d��de�ZdS�).a��!Time manipulation and other numerical routines.

This module implements various simple numerical algorithms, such as
partial sorting, time manipulation or fraction-to-date conversions.
It also contains two array-like classes that take datetime objects as
indices.�partial_ordering�fcst_hr_min�split_fraction�to_fraction�to_datetime_rel�to_datetime�to_timedelta�	TimeArray�minutes_seconds_rest�nearest_datetime�is_at_timestep�great_arc_dist�timedelta_epsilon�TimeMapping�within_dt_epsilon�randint_zeromean�����Nc�������������������@���s"���e�Zd�ZdZddd�Zdd��ZdS�)r���au��!Sorts a pre-determined list of objects, placing unknown items
    at a specified location.

    This class is a drop-in replacement for cmp in sorting routines.
    It represents a partial ordering of objects by specifying the
    order of a known subset of those objects, and inserting all
    unknown objects in a specified location in the that list (at the
    end, by default) in an order determined by cmp(a,b).  Example:

    @code{.py}
    p=partial_ordering([3,2,1]) # list is ordered as [3,2,1] with
                                #  everything else after that

    sorted([0,1,2,3,6,4,5],p)  # = [3, 2, 1, 0, 4, 5, 6]
    p(1,-99)  # = -1, so -99 goes after 1 since -99 is not
              #   in the partial ordering
    p(1,3)    # = 1, so 3 goes before 1 since 3 is before 1
              #   in the partial ordering
    p(5,10)   # = -1 since cmp(5,10)=-1
    @endcodeNc�����������������C���sz���t���|�_||�_|dkr"td�|�_n||�_d}|D�]4}||�jk�sR||�jksR|d7�}q4||�j|<�|d7�}q0|�jdkrv||�_dS�)a��!partial_ordering constructor.

        Creates a partial ordering.  The subset that is ordered is
        specified by the ordered iterable "ordered" while the index at
        which to place unordered values is optionally specified by
        "unordered", which can be anything that can be compared to an
        int via less than and greater than.  If "unordered" is
        missing, then all objects not in "ordered" will be placed at
        the end of any list.  To place at the beginning of the list,
        give unordered=0.  To insert between the first and second
        elements, specify 1, between second and third elements:
        specify unordered=2, and so on.  Specify another tiebreaker
        key generator with "backup_keygen" (default: original value).

        @param ordering the ordering of known objects
        @param unordered Optional: where to put other objects

        @param unordered_key Optional: the tiebreaker key generator
        for unordered keys.  Default is the original value.

        N�infr�������)�dict�order�
backup_keygen�float�	unordered)�selfZorderingr���r����i�obj��r����:/lfs/h1/ops/prod/packages/hmon.v3.2.7/ush/hwrf/numerics.py�__init__+���s����



zpartial_ordering.__init__c�����������������C���s<���||�j�kr|�j�|�d�fS�|�jd�k	r2|�j|��|�fS�|�j|fS�)N)r���r���r���)r����ar���r���r����__call__^���s
����

zpartial_ordering.__call__)NN)�__name__�
__module__�__qualname__�__doc__r���r ���r���r���r���r���r������s���
3c�����������
���
���C���s����t�jd�}d}d}t|�|�}t|��|�}t|�|�}	t|�|�}
|dt��|�d�|���}|dt��|	�d�|���}||�t��tdt��t��||	�d��d�t��|�t��|	��t��||
�d��d�������S�)a_��!Great arc distance between two points on Earth.

    Calculates the great arc distance in meters between two points
    using the Haversine method.  Uses the local Earth radius at the
    latitude half-way between the two points.
    @param xlon1,ylat1 first point, degrees
    @param xlon2,ylat2 second point, degrees
    @returns distance in metersg������f@g���@�TXAgˡE��r@��������?g�������@)�math�pir����sin�asin�min�sqrt�cos)
Zxlon1Zylat1Zxlon2Zylat2Zdeg2radZRequatorZflattening_invZrlat1Zrlon1Zrlat2Zrlon2ZRearth1ZRearth2r���r���r���r���g���s����	
(��c�����������������C���s\���|�|�}|j�d�|jd��|jd��}t�|�\}}|dkrH|dk�sHt�t|d��}||fS�)au��!Return forecast time in hours and minutes.

    Given a forecast datetime.datetime and an analysis
    datetime.datetime, this returns a tuple containing the forecast
    hour and minute, rounded to the nearest integer minute.
    @param time forecast time as a datetime.datetime
    @param start analysis time as a datetime.datetime
    @returns a tuple (ihours,iminutes)�������g����t��Ar%����<���)�days�seconds�microsecondsr&����modf�AssertionError�round)�time�start�dtZfhours�fpartZihoursZiminutesr���r���r���r�������s����	c��������������������s����t�t������t|��}�|dkr$tj�n|j���dkrH�����k�sHtd��������fdd�t|��D��}t|�}|dkr�|dkr��d|�d��}||����krx||��d8��<�q�qxn6|dk�r��d|�d��}||���k�r�||��d7��<�q�q�t|�}qht|�dks�t�|S�)a��!Generates "count" numbers uniformly distributed between -imax
    and imax, inclusive, with a mean of zero.
    @param count number of numbers to return
    @param imax maximum value of any number
    @param randomizer the random module, or something that looks like itNr���zKIn randint_zeromean, imax=%d cannot be negated and fit within a Python int.c��������������������s���g�|�]}��������qS�r���r�����.0�x��imax�randintr���r����
<listcomp>����s�����z$randint_zeromean.<locals>.<listcomp>r���)�abs�int�randomr?����
OverflowError�range�sumr4���)�countr>���Z
randomizerZrandZcenZicenr���r=���r���r�������s6������
c�����������������C���s&���t�|��}|�|�}|t�|j�t�|j�fS�)a��!Splits a fraction into components.

    Splits a fraction.Fraction into integer, numerator and denominator
    parts.  For example, split_fraction(Fraction(13,7)) will return
    (1,6,7) since 1+6/7=13/7.

    @returns a tuple (integer,numerator,denominator))rB����	numerator�denominator)�fr����f2r���r���r���r�������s����c�����������������C���st���t�|tj�st|�}n:t�|�tj�s*t|��}�||��}t�|jd�|j�d|j��}t�|tj�sdt|�}t	|�t	|�k�S�)a$��!Returns True if time1 is within epsilon of time2, and False
    otherwise.
    @param time1,time2 the times being compared
    @param epsilon how close they need to be in order to be 
      considered equal.
    @returns True if the times are within epsilon of each other,
      False if not�@B��Q�)
�
isinstance�datetimer���r����	fractions�Fractionr2���r1���r0���rA���)Ztime1Ztime2�epsilonr8���r���r���r���r�������s����
��F�
���c�����������
������C���s����|rt�|��}�|dk	rt|�}d}d}t|�}|�D�]d}|dkrJt|�}|}n
t||�}|dk	r�tt||�dd�|��}	|dks�|	|k�r�|	dkr�|	}|}q0|dkr�|dkr�tjj	d|dd��t|�S�t|�S�)a���!Decides a reasonable epsilon for time equality comparisons.

    Given an iterable of datetime objects (or anything accepted by
    to_datetime_rel), computes the minimum time difference between any
    two adjacent times and divides it by "numerator" (default: 10).
    The "rel" argument is the relative time when calling
    to_datetime_rel.  If unspecified, it will be the first time seen
    (in which case that time must be acceptable to to_datetime).  The
    "default" is the return value when all elements in "times" are
    identical, or when there is only one element.  If the default is
    unspecified and it is needed, then NoTimespan is raised.  If sort
    is specified and True, then the times will be sorted before
    anything is done (it is False by default).
    
    @param times a list of example times for comparison
    @param rel a reference time to which the times will be compared
    @param default if too few unique times are found, this is returned
      If that happens and no default is provided, an exception is raised
    @param sort if True, sort times
    @param numerator A measure of how close times should be.  The least
      time difference will be at least numerator times the epsilon
    @returns an epsilon valueNT��negokr���znToo few non-identical times in input, and no default specified.  Cannot compute timespan in timedelta_epsilon.)r7����end)
�sortedr���rB���r���r���rA���r����hwrf�
exceptionsZ
NoTimespan)
�times�rel�default�sortrH���ZmindiffZpriorr6����now�diffr���r���r���r
�������s4������
���c�����������������C���s����d}|dk	rt��|�|�}n�t|�tj�rFt��|�jd�|�j�d|�j��}nrt|�t�r�t	�
d|��}|r�|�dddg�\}}}t��t|�t|��t|��t|��}nt|�t
�r�t�j�|���d�}|dkr�t��|��}|s�|dks�tj�d	t|��t|�f���|S�)
a���!Converts an object or two to a fraction.

    This routine is a wrapper around fraction.Fraction() which accepts
    additional inputs.  Fractions are needed to provide higher
    precision in time and resolution calculations (and also to match
    the WRF behavior).  The arguments are the same as for the
    fractions.Fraction constructor, but additional calling conventions
    are accepted: a single float argument, a single datetime.timedelta
    object, or a string containing an integer and a fraction.  If a
    float is provided, its denominator is restricted to be no more
    than 1000000.  If the resulting fraction is not larger than 0,
    then InvalidTimestep is thrown unless negok=True.

    Examples:
    @code
        to_fraction(0.855)            # 0.855 seconds
        to_fraction(33)               # 33 seconds
        to_fraction('12/5')           # 2.4 seconds
        to_fraction('7+1/2')          # 7.5 seconds
        to_fraction(0.0000001) # ERROR! Value of the float() is less
                               # than 1e-6
        to_fraction(1,10000000) # Valid as a fraction, even though value
                                # is less than 1e-6
    @endcode
    @param a,b the objects to convert
    @param negok if True, negative numbers are okay.NrL���rM���z<\s*(?P<ipart>[+-]?\d+)\s*(?P<num>[+-]\d+)\s*/\s*(?P<den>\d+)�ipart�numZdenr���z2to_fraction(%s,%s) resulted in a negative timestep)rP���rQ���rN���rO����	timedeltar2���r1���r0����str�re�match�groupsrB���r����
from_float�limit_denominatorrX���rY���ZInvalidTimestep�repr)r����brU����result�mr����n�dr���r���r���r�����s2������
&

��c�����������������C���s����t�|tj�st|�}t�|�tj�r$|�S�t�|�tj�r8||��S�t�|�t�r�t�d|��r�t|��dkrhtj�|�d�S�t|��dkr�tj�|�d�S�tj�|�d�S�|t	|���S�)a���!Converts objects to a datetime relative to another datetime.

    Given a datetime object "rel", converts "d" to a datetime.  Object
    "d" can be anything accepted by to_datetime, or anything accepted
    as a single argument by to_timedelta.  If it is a timedelta, it is
    added to "rel" to get the final time.
    @param d the object being converted
    @param rel the datetime.datetime to which it is to be convertedz7\A(?:\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d|\d{10}|\d{12})\ZrS����%Y%m%d%H�����
%Y%m%d%H%M�%Y-%m-%d %H:%M:%S)
rN���rO���r���rb���rc���rd���re����len�strptimer���)rn���r[���r���r���r���r���C��s����	
c�����������������C���s����t�|�t�rt|��}�t�|�tj�r"|�S�t�|�t�rpt|��dkrFtj�|�d�S�t|��dkr`tj�|�d�S�tj�|�d�S�ntdt|��f���dS�)a,��!Converts the argument to a datetime.  

    If the argument is already a datetime, it is simply returned.
    Otherwise it must be a string of the format YYYYMMDDHH,
    YYYYMMDDHHMM, or YYYY-MM-DD HH:MM:SS.
    @param d the object being converted
    @returns the resulting datetime.datetime objectrS���ro���rp���rq���rr���zmInvalid value %s for to_datetime.  Parameter must be a datetime or a string that matches YYYY-MM-DD HH:MM:SS.N)rN���rB���rc���rO���rs���rt����
ValueErrorri���)rn���r���r���r���r���^��s����
�
�Tc�����������
���
���C���sN��t�|�tj�r|�S�t�|�t��r|dk�rz�t�d|��}|r�d\}}}|���}d|krj|d�dk	rjt|d��}d|kr�|d�dk	r�t|d��}d|kr�|d�dk	r�t|d��}tj|||d�}d|kr�|d�dk	r�|d�d	kr�|�W�S�|W�S�W�n,�tt	t
fk
�r�}	�z��W�5�d}	~	X�Y�nX�t|�||d
�}
t�
|
�\}}tj|tt|d���d�S�)
af��!Converts an object to a datetime.timedelta.

    Returns a datetime.timedelta object.  If "a" is a timedelta, then
    that value is returned.  If "a" is a string of the format 08:13 or
    08:13:12, optionally preceded by a "-" then it is interpreted as
    HH:MM or HH:MM:SS, respectively (where a "-" negates).  Otherwise,
    the arguments are sent to the to_fraction() function, and the
    result is converted into a timedelta.

    @param a object being converted
    @param b second object, if a time range is sent
    @param negok if True, negative timespans are allowed
    @returns a datetime.timedeltaNz�(?ix) \A \s* (?P<negative>-)? 0* (?P<hours>\d+)
                :0*(?P<minutes>\d+)
                  (?: :0*(?P<seconds>\d+(?:\.\d*)?) )?
                \s*)���������rv���rv����hours�minutesr1���)rw���rx���r1����negative�-rT���g������.A)r1���r2���)rN���rO���rb���rc���rd����search�	groupdictr����	TypeErrorru����AttributeErrorr���r&���r3���rB���r5���)
r���rj���rU���rl���rw���rx���r1����mdictr8����erJ���r9���r`���r���r���r���r���w��s@������
�
�
�c�����������������C���s>���t�|��}�t|�d��}t|�|d���}|�|d��|�}|||fS�)z�!Splits the given fractions.Fraction of seconds into integer
    minutes, seconds and fractional remainder <=0.

    @param fraction the fraction to convert, assumed to be in seconds
    @returns a tuple (minutes,seconds,rest) as integersr/���)r���rB���)Zfractionrx���r1����restr���r���r���r	������s
����c�����������������C���sF���t�|��}t�|�}t|�}tt�t||��|���}tt�||��|�S�)a��!Return the nearest datetime.datetime to a target.

    Given a start time, a target time and a timestep, determine the
    nearest time not earlier than the target that lies exactly on a
    timestep.  Input start and target can be anything understood by
    to_datetime, and the timestep can be anything understood by
    to_fraction.  Return value is a datetime.datetime object.

    @param start the fixed start time of allowed return values
    @param target the time desired
    @param timestep the times between allowed return values)r���r���rB���r&����ceilr����floor)r7����target�timestepZdstartZdtargetr8���Zhow_many_dtr���r���r���r
������s
����c�����������������C���s0���t�t|�t|����}|t�|��}|t|��dk�S�)z�!Returns True if the target time lies exactly on a timestep, and
    False otherwise.

    @param start the fixed start time of allowed return values
    @param target the time desired
    @param timestep the times between allowed return valuesg�h㈵��>)r���r���rB���)r7���r����r�����spanZ	timestepsr���r���r���r������s����c�����������
������C���s|���t�t|���}|dk�}|r|�}t|�\}}}t|�d�}t|�d�d�}t|�d�}d|||f�}	|dkrxd|	||f�}	|	S�)aS��!Converts a timedelta to a string 

    Converts dt to a string of the format "DD:HH:MM:SS+num/den"
    * DD - number of days
    * HH - number of hours
    * MM - minutes
    * SS - seconds
    * num/den - fractional part
    The to_fraction is used to get the fractional part.

    @param dt anything convertible to a datetime.timedelta.r���r/���r.���z%02d:%02d:%02dz%s+%d/%d)r���r���r���rB���)
r8���Zfdt�negr���rm���rn���r1���rx���rw����outr���r���r����
str_timedelta���s�����r����c�������������������@���s����e�Zd�ZdZd-dd�Zdd��Zdd��Zed	d
���Zedd���Z	d
d��Z
d.dd�Zdd��Zdd��Z
dd��Zdd��Zdd��Zdd��Zdd��Zdd ��Zd!d"��Zd#d$��Zd%d&��Zd'd(��Zd)d*��Zd+d,��ZdS�)/�
TimeContaineraQ��!Abstract base class that maps from time to objects.

    This is the abstract base class of any class that represents a
    mapping from a set of times to a set of data.  It provides the
    underlying implementation of TimeArray and TimeMapping.  This is
    not exported by "from hwrf.numerics import *" to prevent
    accidental use.Nc��������������������sZ���||�_�t|�j��}��dkr2dg|�|�_dg|�|�_n$dg|�|�_��fdd�t|�D��|�_dS�)aV��!TimeContainer constructor.

        Initializes the internal arrays for the given list of times,
        which must not be empty.  Note that strange, potentially bad
        things will happen if there are duplicate times.

        Implementation notes:

        @code
          self._times[N]: a list of times
          self._data[N]: the data for each time
          self._assigned[N]: True if there is data for this time,
            False otherwise
        @endcode

        where N is the length of the input times array.  The _data
        will be filled with init() and _assigned filled with True if
        init is present and not None, otherwise _assigned will be
        False.

        @param times the times to map from
        @param init a constructor or function that creates initial
           values for all uninitialized array elementsNFTc��������������������s���g�|�]
}�����qS�r���r���r:�����initr���r���r@�����s�����z*TimeContainer.__init__.<locals>.<listcomp>)�_timesrs����	_assigned�_datarE���)r���rZ���r�����Nr���r����r���r������s����
zTimeContainer.__init__c�����������������C���s���|�j�|�st|��|�j|�S�)zz!Returns the data at the given index, or raises KeyError if
        no data exists.
        @param index the desired index)r�����KeyErrorr����)r����indexr���r���r����at_index��s����
�zTimeContainer.at_indexc�����������������C���s���t�d��dS�)z�!This virtual function should be implemented in a subclass.
        It should return the index of the time to use for the given
        time.
        @param when the time of interestz*TimeContainer.index_of is not implemented.N)�NotImplementedError)r����whenr���r���r����index_of ��s�����zTimeContainer.index_ofc�����������������C���s
���|�j�d�S�)zU!Returns the last time in the array or list of times, even
        if it has no data.������r�����r���r���r���r����lasttime'��s����zTimeContainer.lasttimec�����������������C���s
���|�j�d�S�)zV!Returns the first time in the array or list of times, even
        if it has no data.r���r����r����r���r���r����	firsttime,��s����zTimeContainer.firsttimec�����������������C���s*���|���|�\}}|�j|�s t|��|�j|�S�)z�!Returns the item at the latest time that is not later than
        "when".  If there is no data assigned at that time, then
        KeyError is raised.
        @param when the time of interest)r����r����r����r����)r���r�����iwhenr����r���r���r����__getitem__1��s����
zTimeContainer.__getitem__c�����������������C���sf���|���|�\}}|dk	r^tt||�dd��t|�kr6|S�tj�dt|�t|�tt|��f���n|S�dS�)a��!Returns a tuple containing the time nearest to "when"
        without going over, and the index of that time.  

        @param epsilon If specified, raise
        hwrf.exceptions.NoNearbyValues if no times are near that
        value.
        @param when the time of interestNTrT���zB%s: nearest value not after is %s, which is not within %s seconds.)r����rA���r���rX���rY���ZNoNearbyValuesrc���)r���r����rR���Zthenr����r���r���r����neartime:��s�����
���zTimeContainer.neartimec�����������������C���s*���|���t|��\}}|�j|�s |S�|�j|�S�)z�!Returns the item at the latest time that is not later than
        "when."  
        
        @param when the time of interest
        @param default If there is no data assigned at that time then the
        given default is returned.)r����r���r����r����)r���r����r\���r����r���r���r����getN��s����
zTimeContainer.getc��������������	���C���s2���|���|�\}}z|�j�||�W��S�d|�j|<�X�dS�)z�!Finds the latest time that is not later than "when" in
        self._times.  Assigns "val" to that time.
        @param when the time of interest
        @param val the value to assign to that timeTN)r����r����r�����__setitem__)r���r�����valr����r���r���r���r����Y��s����zTimeContainer.__setitem__c�����������������c���s.���t�t|�j��D�]}|�j|�r|�j|�V��qdS�)z!Iterates over all data.N�rE���rs���r����r����r�����r���r���r���r���r����__iter__c��s����
zTimeContainer.__iter__c�����������������c���s.���t�t|�j��D�]}|�j|�r|�j|�V��qdS�)z7!Iterates over data for all known times that have data.Nr����r����r���r���r����
itervaluesh��s����
zTimeContainer.itervaluesc�����������������c���s.���t�t|�j��D�]}|�j|�r|�j|�V��qdS�)z(!Iterates over all times that have data.N�rE���rs���r����r����r����r���r���r����iterkeysm��s����
zTimeContainer.iterkeysc�����������������c���s8���t�t|�j��D�]$}|�j|�r|�j|�|�j|�fV��qdS�)zw!Iterates over all known times that have data, returning a
        tuple containing the time and the data at that time.Nr����r����r���r���r����	iteritemsr��s����
zTimeContainer.iteritemsc�����������������c���s>���t�|�j�}t|�D�]&}||�d�}|�j|�r|�j|�V��qdS�)zH!Iterates over all known times that have data, in reverse
        order.r���N)rs���r����rE���r����r����)r���rm���r����jr���r���r����__reversed__x��s
����

zTimeContainer.__reversed__c�����������������C���s&���|���|�\}}d|�j|<�d|�j|<�dS�)z�!Finds the latest time that is not later than "when" and
        removes the data it is mapped to.  Later calls to __getitem__,
        get, __iter__ and so on, will not return any data for this
        time.
        @param when the time of disinterestFN)r����r����r�����r���r����r����r���r���r����__delitem__���s����
zTimeContainer.__delitem__c��������������
���C���sL���z|���|�\}}|�j|�W�S��tjjk
rF�}�z
W�Y��dS�d}~X�Y�nX�dS�)z�!Finds the latest time that is not later than "when" in
        self._times.  Returns True if there is data mapped to that
        time and False otherwise.
        @param when the time of interestFN)r����r����rX���rY����
NotInTimespan)r���r����r����r����r����r���r���r����__contains__���s
����zTimeContainer.__contains__c�����������������C���s
���t�|�j�S�)z,!Returns the number of times that have data.)rs���r����r����r���r���r����__len__���s����zTimeContainer.__len__c�����������������c���s���|�j�D�]
}|V��qdS�)z.!Iterates over all times in this TimeContainerNr����)r����tr���r���r���rZ������s����
zTimeContainer.timesc�����������������c���s.���t�t|�j��D�]}|�j|�r|�j|�V��qdS�)z@!Iterates over all times in this TimeContainer that map to data.Nr����r����r���r���r����	datatimes���s����
zTimeContainer.datatimesc��������������������s>����fdd���d����fdd�tt�j��D���}d�jj|f�S�)z0!Returns a string representation of this object.c��������������������sB�����j�|��}|�d�}��j|��r4d|t��j|���f�S�d|f�S�d�S�)Nz
%Y%m%d-%H%M%Sz%s:%sz%s:(unassigned))r�����strftimer����ri���r����)r���r�����str����r���r����idxstr���s
����


z%TimeContainer.__str__.<locals>.idxstrz, c��������������������s���g�|�]}��|��qS�r���r����r;���r���)r����r���r���r@������s�����z)TimeContainer.__str__.<locals>.<listcomp>z%s(%s))�joinrE���rs���r�����	__class__r!���)r����contentsr���)r����r���r����__str__���s����"zTimeContainer.__str__c�����������������c���s>���t�|�j�}t|�D�]&}||�d�}|�j|�r|�j|�V��qdS�)zY!Iterates in reverse order over all times in this
        TimeContainer that map to data.r���N)rs���r����rE���r����)r���r����r���r����r���r���r����datatimes_reversed���s
����

z TimeContainer.datatimes_reversed)N)N)r!���r"���r#���r$���r���r����r�����propertyr����r����r����r����r����r����r����r����r����r����r����r����r����r����rZ���r����r����r����r���r���r���r���r�������s0���
 

	

	
r����c�������������������@���s"���e�Zd�ZdZddd�Zdd��ZdS�)r���aL��!A time-indexed array that can only handle equally spaced times.

    This implements an array-like object that uses time as an index.
    It recognizes only discrete times as specified by a start, an end
    and a timestep.  The end is only used as a guideline: if it does
    not lie exactly on a timestep, the next timestep end is used.
    Note that all methods in this class have the same meaning as the
    built-in list class, but accept times as input, except if
    specified otherwise.  In all cases, the time "index" is anything
    accepted by to_datetime_rel(...,self.start).Nc��������������������s����t�|��_t|�j��_t|������_tt�j�j���j��d�}tj����fdd�t	|�D��|d���j�_
�j�_���_dS�)a��!TimeArray constructor.

        @param start,end,timestep Specifies the equally-spaced times.
        @param init The initializer for data values.  This is typically
         a constructor (dict, list, etc.) or a function that calls a
         constructor.r���c��������������������s���g�|�]}�j�t|������qS�r���)�_startr���r�����r8���r���r���r���r@������s�����z&TimeArray.__init__.<locals>.<listcomp>r����N)
r���r����r����_endr����	_timesteprB���r����r���rE���r7���rV���r����)r���r7���rV���r����r����rm���r���r����r���r������s����
$zTimeArray.__init__c�����������������C���sn���t�||�j�}tt||�j��|�j��}|dk�s:|t|�j�kr`tj�	d|�
��|�j�
��|�j�
��f���|�j|�|fS�)��!Returns the index of the specified time in the internal
        storage arrays or raises NotInTimespan if the time is not in
        the timespan.  
        @param when Anything accepted by
        to_datetime_rel(when,self._start)r���z%s: not in range [%s,%s])
r���r����rB���r���r����rs���r����rX���rY���r�����ctimer����r����r����r���r���r���r�������s�������zTimeArray.index_of)N�r!���r"���r#���r$���r���r����r���r���r���r���r������s���

c�������������������@���s"���e�Zd�ZdZddd�Zdd��ZdS�)r���ad��!Maps from an ordered list of times to arbitrary data.

    A TimeMapping is a mapping from an ordered list of times to a set
    of data.  The full set of possible times is given in the
    constructor: it is not possible to add new times to the mapping
    after creation of the TimeMapping.  A TimeMapping is more
    expensive than a TimeArray since every [] lookup (__getitem__) has
    to do a binary search.  However, it is more general since the
    times do not have to be exactly at an interval.

    Note that a TimeArray can replace a TimeMapping if a small enough
    timestep (the greatest common factor) is used since most of the
    TimeContainer methods only work on the indices that have data.
    However, if some timespans have dense timesteps and the rest are
    sparse, there may be significant memory and CPU savings in using a
    TimeMapping.Nc�����������������C���s*���t�dd��t|�D���}tj|�||d��dS�)a��!TimeMapping constructor
        @param times A list of times, which will be converted with to_datetime and sorted.
        @param init The initializer for data values.  This is typically
         a constructor (dict, list, etc.) or a function that calls a
         constructor.c�����������������S���s���g�|�]}t�|��qS�r���)r���r:���r���r���r���r@�����s�����z(TimeMapping.__init__.<locals>.<listcomp>r����N)rW����setr����r���)r���rZ���r����r���r���r���r������s����zTimeMapping.__init__c�����������	������C���s����t�|�}t|�j�}|dkr&tj�d��d}|�j|�}|d�}|�j|�}||k�rltj�dt|�t|�f���n||kr�|�j|�|fS�||d�kr�||�d�}|�j|�}||k�r�||�}}q�||�}}q�|�j|�|fS�)r����r���z6TimeMapping is empty: no data is in an empty timespan.r���z:Time %s is not earlier than first time (%s) in TimeMapping����)r���rs���r����rX���rY���r����rc���)	r���r����r����ZiearlyZearlyZilateZlateZimiddleZmiddler���r���r���r������s2����
�

��
zTimeMapping.index_of)Nr����r���r���r���r���r������s���
)N)NNFrS���)NF)NT)r$����__all__rP���r&���rO���rd���rC���Zhwrf.exceptionsrX����objectr���r���r���r���r���r���r
���r���r���r���r���r	���r
���r���r����r����r���r���r���r���r���r����<module>���sF���	���������(Q
&
1
2
1
�E9