U
    Cvfg                     @  sH  d dl mZ d dlZd dlZd dlmZ d dlmZ d dl	m
Z
mZmZmZmZmZ d dlZd dlZd dlmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZmZm Z  d dl!m"Z"m#Z# d dl$m%Z%m&Z& d dl'm(Z(m)Z) d dl*m+Z+m,Z, d dl-m.Z.m/Z/ e
rd dl0m1Z1 d dl2m3Z3 ddddddZ4G dd dZ5G dd de5Z6G dd de5Z7G dd de5Z8dWd d!Z9dXdd#d$d%d&d'Z:dYd)d*d+d,d-d.d/d0d1Z;d2d3 Z<dZd5d6Z=d[d7d8Z>d\d9d:Z?d;d< Z@d]d+d$d>d?d@ZAdAdB ZBdCdD ZCdEdF ZDdGdH ZEd+dIdJdKZFd+dIdLdMZGdNdO ZHdPdQ ZId"dRdSdTZJdUdV ZKdS )^    )annotationsN)partial)Number)TYPE_CHECKINGAnyCallableHashableSequenceget_args)Version)utils)_contains_datetime_like_objects	ones_like)apply_ufunc)datetime_to_numericpushtimedelta_to_numeric)OPTIONS_get_keep_attrs)is_duck_dask_arraymod_version)Interp1dOptionsInterpOptions)
OrderedSet	is_scalar)Variablebroadcast_variables)	DataArray)DatasetzDataset | DataArray | Variabler   r   )objdimindexc                 C  s   t |g|}t| | }|  }||}|j|d|d }|j|dd|| | i|j|d| d|d |	  }|S )zv
    Return an object where each NaN element in 'obj' is replaced by the
    length of the gap the element is in.
    )r    r   upper)r    label)
r   r   ZnotnullwhereffillZfillnaZdiffZreindexbfillmax)r   r    r!   arangeZvalidZvalid_arangeZcumulative_nansnan_block_lengths r+   7/tmp/pip-unpacked-wheel-h316xyqg/xarray/core/missing.py_get_nan_block_lengths   s&    	

 	r-   c                   @  sB   e Zd ZU dZded< ded< ded< ded< d	d
 Zdd ZdS )BaseInterpolatorz@Generic interpolator class for normalizing interpolation methodszdict[str, Any]cons_kwargscall_kwargsr   fstrmethodc                 C  s   | j |f| jS N)r1   r0   selfxr+   r+   r,   __call__A   s    zBaseInterpolator.__call__c                 C  s   dj | jj| jdS )Nz{type}: method={method})typer3   )format	__class____name__r3   )r6   r+   r+   r,   __repr__D   s     zBaseInterpolator.__repr__N)r<   
__module____qualname____doc____annotations__r8   r=   r+   r+   r+   r,   r.   9   s   
r.   c                   @  s"   e Zd ZdZdddZdd ZdS )	NumpyInterpolatorzVOne-dimensional linear interpolation.

    See Also
    --------
    numpy.interp
    linearNc                 C  s   |dkrt d|| _tj| _i | _d|i| _|| _|| _|j	j
dkrLtjntjtjd  }|d krr|| _|| _nPt|trt|dkr|d | _|d | _n$t|r|| _|| _nt | d	d S )
NrC   z7only method `linear` is valid for the NumpyInterpolatorperiodc              ?   r      z is not a valid fill_value)
ValueErrorr3   npinterpr1   r/   r0   _xi_yidtypekindnan_left_right
isinstancer	   lenr   )r6   xiyir3   
fill_valuerD   rP   r+   r+   r,   __init__R   s&    
"
zNumpyInterpolator.__init__c                 C  s&   | j || j| jf| j| jd| jS )N)leftright)r1   rL   rM   rQ   rR   r0   r5   r+   r+   r,   r8   m   s    zNumpyInterpolator.__call__)rC   NN)r<   r>   r?   r@   rX   r8   r+   r+   r+   r,   rB   J   s   
rB   c                   @  s   e Zd ZdZdddZdS )ScipyInterpolatorznInterpolate a 1-D function using Scipy interp1d

    See Also
    --------
    scipy.interpolate.interp1d
    NTFc	                 K  s   ddl m}
 |d krtd|dkr8|d kr4td|}|| _|	| _i | _|jjdkr\tj	ntj	tj	d  }|d kr|dkr||f}n|d kr|}|
||f| j||||d	| j| _
d S )
Nr   )interp1dzPmethod is a required argument, please supply a valid scipy.inter1d method (kind)Z
polynomialz(order is required when method=polynomialrE   rF   rC   )rO   rW   bounds_errorassume_sortedcopy)scipy.interpolater\   rI   r3   r/   r0   rN   rO   rJ   rP   r1   )r6   rU   rV   r3   rW   r^   r_   r]   orderkwargsr\   rP   r+   r+   r,   rX      s:    "
zScipyInterpolator.__init__)NNTFFNr<   r>   r?   r@   rX   r+   r+   r+   r,   r[   x   s         r[   c                   @  s   e Zd ZdZdddZdS )	SplineInterpolatorzOne-dimensional smoothing spline fit to a given set of data points.

    See Also
    --------
    scipy.interpolate.UnivariateSpline
    splineN   r   c           
      K  sb   ddl m}	 |dkrtd|| _|| _||d| _|d k	rDtd|	||fd|i| j| _d S )Nr   )UnivariateSplinere   z8only method `spline` is valid for the SplineInterpolator)nuextz.SplineInterpolator does not support fill_valuek)r`   rg   rI   r3   r/   r0   r1   )
r6   rU   rV   r3   rW   ra   rh   ri   rb   rg   r+   r+   r,   rX      s    zSplineInterpolator.__init__)re   Nrf   r   Nrc   r+   r+   r+   r,   rd      s        rd   c                 K  sX   t ||j|jd}|j D ]4\}}||jkrJ| |fd|i|||< q|||< q|S )zWrapper for datasets)coordsattrsr    )r9   rk   rl   Z	data_varsitemsdims)funcr6   r    rb   Zdsnamevarr+   r+   r,   _apply_over_vars_with_dim   s    

rr   Tz
str | boolbool)r    use_coordinatestrictc              	   C  s`  ddl m} |dkr4| |}tj| j| tjdS |dkrH| |}n4| j| }|j	dkrtt
d| d|j	 d	| }t|tjr||_|r|jst
d
|jd|jst
d
|jdt||tjfrt|d ddd}t||r|j}tt||dd|fd}z|jtj}W n8 tt
fk
rZ   td
|jdt|j dY nX |S )aS  Return index to use for x values in interpolation or curve fitting.

    Parameters
    ----------
    arr : DataArray
        Array to interpolate or fit to a curve.
    dim : str
        Name of dimension along which to fit.
    use_coordinate : str or bool
        If use_coordinate is True, the coordinate that shares the name of the
        dimension along which interpolation is being performed will be used as the
        x values. If False, the x values are set as an equally spaced sequence.
    strict : bool
        Whether to raise errors if the index is either non-unique or non-monotonic (default).

    Returns
    -------
    Variable
        Numerical values for the x-coordinates.

    Notes
    -----
    If indexing is along the time dimension, datetime coordinates are converted
    to time deltas with respect to 1970-01-01.
    r   CFTimeIndexF)rN   TrH   z/Coordinates used for interpolation must be 1D, z is zD.zIndex z! must be monotonically increasingz has duplicate valuesi  ns)offsetZdatetime_unit)datarn   zL must be castable to float64 to support interpolation or curve fitting, got .)xarray.coding.cftimeindexrw   get_axis_numrJ   r)   shapefloat64Z	get_indexrk   ndimrI   to_indexrS   pdZ
MultiIndexrp   Zis_monotonic_increasingZ	is_uniqueDatetimeIndexr9   valuesr   r   Zastype	TypeErrorr<   )arrr    rt   ru   rw   axisr!   ry   r+   r+   r,   get_clean_interp_index   sD    




r   rC   zHashable | Nonez
bool | strr   z
int | Nonez@int | float | str | pd.Timedelta | np.timedelta64 | dt.timedeltazbool | None)r    rt   r3   limitmax_gap
keep_attrsc                 K  s  ddl m} |dkrtd|dk	r0t| ||}	|dk	rt|j}
t|sRtd|| jkrt	| j| 
 tj|fr|rt|}|st	|ttjfstd|
 dt| ||d}t|f|\}}tt|f|}|dkrtd	d
}t T tddt tddt t|| ||g|gg|gg| jgdd	|d	j| j }W 5 Q R X |dk	rZ||	}|dk	r|| j krxtdt!| ||}|||k}|S )z2Interpolate values according to different methods.r   rv   Nzdim is a required argumentzmax_gap must be a scalar.zPExpected integer or floating point max_gap since use_coordinate=False. Received r{   )rt   T)defaultignoreZoverflowzinvalid valueZparallelized)Zinput_core_dimsZoutput_core_dimsoutput_dtypesdaskZ	vectorizer   z6max_gap not implemented for unlabeled coordinates yet.)"r|   rw   NotImplementedError_get_valid_fill_maskr9   r<   r   rI   Z_indexesrS   Zto_pandas_indexr   r   r   r   rJ   numberr   r   _get_interpolatorr   func_interpolate_nar   warningscatch_warningsfilterwarningsRuntimeWarningr   rN   	transposern   r%   rk   r-   )r6   r    rt   r3   r   r   r   rb   rw   ZvalidsZmax_typer!   interp_classinterpolatorr   r*   r+   r+   r,   	interp_na5  sn    
 







r   c           	      K  sf   |  }t|}| }| }|dks8|t|d kr<|S | || || f|}||| ||< |S )z8helper function to apply interpolation along 1 dimensionr   rH   )r_   r   isnullsumrT   )	r   yr7   rb   outZnansZnonansZn_nansr1   r+   r+   r,   r     s    
r   r$   c                 C  s*   t j| |d} t| ||d} t j| |dS )zinverse of ffillr   )r   n)rJ   Zflipr   )r   r   r   r+   r+   r,   _bfill  s    r   c              
   C  sX   t d std| |}|dk	r&|n| j| }tt| dd| jgt||ddj| j	 S )zforward fill missing valuesuse_bottleneckzaffill requires bottleneck to be enabled. Call `xr.set_options(use_bottleneck=True)` to enable it.NallowedTr   r   r   r   r   rb   )
r   RuntimeErrorr}   r~   r   r   rN   dictr   rn   r   r    r   r   Z_limitr+   r+   r,   r&     s     

r&   c              
   C  sX   t d std| |}|dk	r&|n| j| }tt| dd| jgt||ddj| j	 S )zbackfill missing valuesr   zabfill requires bottleneck to be enabled. Call `xr.set_options(use_bottleneck=True)` to enable it.Nr   Tr   r   )
r   r   r}   r~   r   r   rN   r   r   rn   r   r+   r+   r,   r'     s     

r'   c              
   C  sR   zddl m} t|| W S  tk
rL } ztd| d|W 5 d}~X Y nX dS )z*Import interpolant from scipy.interpolate.r   )interpolatezInterpolation with method z requires scipy.N)Zscipyr   getattrImportError)Zinterpolantr3   r   er+   r+   r,   _import_interpolant  s
    r   F)r3   vectorizeable_onlyc                 K  s  t t}tdd t tD }| dkrL|dddksL|sL|j| d t}n| |kr| |krp|j| d t}n|rt|  d| nx| d	krt	d
| }nd| dkrt	d| }nP| dkrt	d| }n<| dkr|j| d t
}n"| dkrt	d| }nt|  dnt|  d||fS )helper function to select the appropriate interpolator class

    returns interpolator class and keyword arguments for the class
    c                 s  s    | ]}t |D ]
}|V  qqd S r4   )r
   ).0vvvr+   r+   r,   	<genexpr>  s     
  z$_get_interpolator.<locals>.<genexpr>rC   rW   NZextrapolater3   z< is not a vectorizeable interpolator. Available methods are ZbarycentricZBarycentricInterpolatorZkrogZKroghInterpolatorZpchipZPchipInterpolatorre   ZakimaZAkima1DInterpolatorz" is not a valid scipy interpolatorz is not a valid interpolator)r
   r   tupler   getupdaterB   r[   rI   r   rd   )r3   r   rb   Zinterp1d_methodsvalid_methodsr   r+   r+   r,   r     s@    
r   c                 K  s>   ddg}| |kr(|j | d td| }nt|  d||fS )r   rC   nearestr   ZinterpnzH is not a valid interpolator for interpolating over multiple dimensions.)r   r   rI   )r3   rb   r   r   r+   r+   r,   _get_interpolator_nd  s    r   c                 C  sJ   ||d i}t | jd}|  jf ddi|j|ddj|dd|kS )zQhelper function to determine values that can be filled when limit is not
    NonerH   Z_windowZmin_periodsF)rW   )Zskipna)r   Zget_temp_dimnamern   r   ZrollingZ	constructr   )r   r    r   kwZnew_dimr+   r+   r,   r     s      r   c                 C  s   i }|  D ]\}\}}t|j}t|j}| }|j|gdd }	|j|gdd }
tt	|	d d|
d ||< |||  |f||< q| j
f ||fS )zwSpeed up for linear and nearest neighbor method.
    Only consider a subspace that is needed for the interpolation
    r   r   rG   r   )rm   rJ   Znanminr   Znanmaxr   Zget_indexeritemslicer(   Zisel)rq   indexes_coordsZindexesr    r7   new_xminvalmaxvalr!   ZiminZimaxr+   r+   r,   	_localize-  s    r   c                 C  st   t | } t |}tt| D ]N}t| | r| | j }| | j|tjd| |< || j|tjd||< q| |fS )zrMake x and new_x float.
    This is particularly useful for datetime dtype.
    x, new_x: tuple of np.ndarray
    )ry   rN   )	listrangerT   r   r   minZ_to_numericrJ   r   )r7   r   iZxminr+   r+   r,   _floatize_x=  s    r   r   c                   s   s|   S |dd|d< | }tD ]̉|} t tfdd D  \}}t| } fdd| jD }|  }	|t|d j }
t| j|	 j	||||}t
|
|| jd}t }| jD ],}| kr|| d j q|| q|j| }q(|S )	a  Make an interpolation of Variable

    Parameters
    ----------
    var : Variable
    indexes_coords
        Mapping from dimension name to a pair of original and new coordinates.
        Original coordinates should be sorted in strictly ascending order.
        Note that all the coordinates should be Variable objects.
    method : string
        One of {'linear', 'nearest', 'zero', 'slinear', 'quadratic',
        'cubic'}. For multidimensional interpolation, only
        {'linear', 'nearest'} can be used.
    **kwargs
        keyword arguments to be passed to scipy.interpolate

    Returns
    -------
    Interpolated Variable

    See Also
    --------
    DataArray.interp
    Dataset.interp
    r]   Fc                   s   g | ]} | qS r+   r+   r   dr   r+   r,   
<listcomp>x  s     zinterp.<locals>.<listcomp>c                   s   g | ]}| kr|qS r+   r+   r   rn   r+   r,   r   |  s      r   )rl   rH   )r_   r   decompose_interpr   zipr   rn   interp_funcr   rz   r   rl   r   r   add)rq   r   r3   rb   resultr7   r   ZdestinationZbroadcast_dimsZoriginal_dimsZnew_dimsZinterpedZout_dimsr   r+   )rn   r   r,   rK   Q  s6    
    
rK   c                   s  |s|   S t|dkr2t|fddi|\}}nt|f|\}}t| rddlm} | jt|  tt	 tt	d j  } fddt
|D }dd |D }fd	dD }	d
d |	D }	| t	f||	}
|j|
 \}}tdd t||
ddd D }
|dt|d d  d fddt	d jD }|dkodd jdk	}t| jjtjstj}n| j}tdtdk rd}n| j}|jt|f|
|||d|||ddS t| |||S )a~  
    multi-dimensional interpolation for array-like. Interpolated axes should be
    located in the last position.

    Parameters
    ----------
    var : np.ndarray or dask.array.Array
        Array to be interpolated. The final dimension is interpolated.
    x : a list of 1d array.
        Original coordinates. Should not contain NaN.
    new_x : a list of 1d array
        New coordinates. Should not contain NaN.
    method : string
        {'linear', 'nearest', 'zero', 'slinear', 'quadratic', 'cubic'} for
        1-dimensional interpolation.
        {'linear', 'nearest'} for multidimensional interpolation
    **kwargs
        Optional keyword arguments to be passed to scipy.interpolator

    Returns
    -------
    interpolated: array
        Interpolated array

    Notes
    -----
    This requiers scipy installed.

    See Also
    --------
    scipy.interpolate.interp1d
    rH   r   Tr   Nc                   s   g | ]\}}| | fgqS r+   r+   )r   r!   _xnconstr+   r,   r     s     zinterp_func.<locals>.<listcomp>c                 S  s   g | ]}|D ]}|qqS r+   r+   r   pairr   r+   r+   r,   r     s       c                   s(   g | ] }| fd dt |jD gqS )c                   s   g | ]} | qS r+   r+   )r   r!   r   r+   r,   r     s     z*interp_func.<locals>.<listcomp>.<listcomp>)r   r   r   r   r   r+   r,   r     s    c                 S  s   g | ]}|D ]}|qqS r+   r+   r   r+   r+   r,   r     s       c                 s  s   | ]}|D ]
}|V  q
qd S r4   r+   )r   r   elemr+   r+   r,   r     s       zinterp_func.<locals>.<genexpr>rG   c                   s<   i | ]4} | d  j dk	r*d  j | nd  j| qS )r   N)chunksr~   )r   r   )r   r   r+   r,   
<dictcomp>  s
   zinterp_func.<locals>.<dictcomp>)rC   r   r   z2020.12F)r   interp_kwargslocalizeZconcatenaterN   new_axesmetaZalign_arrays)r_   rT   r   r   r   Z
dask.arrayarrayr   r   r   	enumerateZunify_chunksr   r   r   
issubclassrN   r9   rJ   ZinexactZfloat_r   r   Z_metaZ	blockwise_dask_aware_interpnd	_interpnd)rq   r7   r   r3   rb   ro   daZout_indZ	x_argindsZnew_x_argindsargs_Z	rechunkedr   r   rN   r   r+   )r   r   r   r,   r     sf    !
$
"r   c                 C  sl   |d |d  }}||| fddi|t |}|jdkrV|| jd d |j S |jdkrh|d S |S )Nr   r^   TrH   r$   ).r$   )rJ   ravelr   reshaper~   )rq   r7   r   ro   rb   rsltr+   r+   r,   	_interp1d  s     

r   c                 C  s   t ||\}}t|dkr*t| ||||S | tt| | jt| } tjdd |D dd}||| |f|}|t|j d d}||j	d d |d j	 S )NrH   c                 S  s   g | ]}|j  qS r+   )r   r   )r   x1r+   r+   r,   r     s     z_interpnd.<locals>.<listcomp>r$   r   r   )
r   rT   r   r   r   r   rJ   stackr   r~   )rq   r7   r   ro   rb   rU   r   r+   r+   r,   r   
  s     r   )r   c                  s   t |d }t j| fddt|d| D }fdd||d D }|rtdd tt jD dd t||D  t \ t fd	d D  \}}jt||||S )
zWrapper for `_interpnd` through `blockwise`

    The first half arrays in `coords` are original coordinates,
    the other half are destination coordinates
    rG   c                   s&   g | ]\}}t d  |  g|qS Zdim_)r   )r   r    r   r   r+   r,   r   $  s     z(_dask_aware_interpnd.<locals>.<listcomp>Nc                   s.   g | ]&}t  fd dtt|jD |qS )c                   s    g | ]}d t  j|  qS r   )rT   r~   r   r    rq   r+   r,   r   &  s     z3_dask_aware_interpnd.<locals>.<listcomp>.<listcomp>)r   r   rT   r~   r   r   r+   r,   r   %  s   c                 S  s   g | ]}d | qS r   r+   r   r+   r+   r,   r   ,  s     c                 S  s    i | ]\}}|j d  ||fqS )r   r   )r   r   Z_new_xr+   r+   r,   r   .  s      z(_dask_aware_interpnd.<locals>.<dictcomp>c                   s   g | ]} | qS r+   r+   r   r   r+   r,   r   2  s     )	rT   r~   r   r   r   r   r   rz   r   )rq   r   r   r   rk   Zn_xr7   r   r+   )r   r   rq   r,   r     s    

r   c           	      c  s   dd |   D }g }i }t|   D ]z\}}||g |t|d krN q||| g7 }||d d }dd |D }dd |D }||s&|V  g }i }q&|V  dS )z\Decompose the interpolation into a succession of independent interpolation keeping the orderc                 S  s.   g | ]&\}}|d  j dkr$|d  jn|gqS )rH   r   )r   rn   )r   r    destr+   r+   r,   r   =  s   z$decompose_interp.<locals>.<listcomp>rH   Nc                 S  s   h | ]}|D ]}|qqS r+   r+   r   rn   r    r+   r+   r,   	<setcomp>L  s       z#decompose_interp.<locals>.<setcomp>c                 S  s   h | ]}|D ]}|qqS r+   r+   r   r+   r+   r,   r   M  s       )rm   r   r   rT   intersection)	r   Z	dest_dimsZpartial_dest_dimsZpartial_indexes_coordsr   Zindex_coordsZ
other_dimsZs_partial_dest_dimsZs_other_dimsr+   r+   r,   r   :  s$    
r   )N)TT)NTrC   NNN)Nr$   )NN)NN)F)L
__future__r   datetimedtr   	functoolsr   Znumbersr   typingr   r   r   r   r	   r
   ZnumpyrJ   Zpandasr   Zpackaging.versionr   Zxarray.corer   Zxarray.core.commonr   r   Zxarray.core.computationr   Zxarray.core.duck_array_opsr   r   r   Zxarray.core.optionsr   r   Zxarray.core.pycompatr   r   Zxarray.core.typesr   r   Zxarray.core.utilsr   r   Zxarray.core.variabler   r   Zxarray.core.dataarrayr   Zxarray.core.datasetr   r-   r.   rB   r[   rd   rr   r   r   r   r   r&   r'   r   r   r   r   r   r   rK   r   r   r   r   r   r+   r+   r+   r,   <module>   sj    .9"
   W      M


 3?o 