U
    Cvf@c                    @  s~  d dl mZ d dlZd dlZd dlZd dlZd dlZd dl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lmZ d dlmZmZmZmZmZmZmZmZmZ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(m)Z) d d
l*m+Z+m,Z, d dl-m.Z. d dl-m/Z0 d dl-m1Z1m2Z2m3Z3m4Z4m5Z5 d dl6m7Z7 d dl8m9Z9m:Z:m;Z; d dl<m=Z= d dl>m?Z?m@Z@mAZA d dlBmCZC d dlDmEZEmFZF d dlGmHZH d dlImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZS d dlTmUZUmVZV d dlWmXZXmYZYmZZZm[Z[ d dl\m]Z] d dl^m_Z_m`Z` d dlambZbmcZc d dldmeZemfZf d dlgmhZhmiZimjZjmkZkmlZlmmZmmnZnmoZompZpmqZqmrZrmsZs d dltmuZumvZvmwZwmxZxmyZy d dlzm{Z{ erd dl|m}Z} d d l~mZmZ d d!lmZmZ d d"lDmZ d d#lmZ d d$lmZ d d%lWmZ d d&lmZ d d'lmZmZ d d(ldmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ d d)lmZ zd d*lmZ W n ek
r   dZY nX zd d+lmZ W n ek
r   dZY nX d,d-d.d/d0d1d2d3d4d5d6d7d8d9gZd\d:d;d<d=d>d?Zd]dAdBdCdDdEdFZdGdH Zd^dKdLZdMdNdOdPdQZdRdS ZdTdU ZG dVdW dWeedXf ZG dYdZ dZeef ZG d[dN dNe?e7e=eedXf ZdS )_    )annotationsN)defaultdict)escape)Number)methodcaller)PathLike)IOTYPE_CHECKINGAnyCallable
CollectionGenericHashableIterableIteratorLiteralMappingMutableMappingSequencecastoverload)convert_calendarinterp_calendar)CFTimeIndex_parse_array_of_cftime_strings)	alignment)dtypes)duck_array_ops
formattingformatting_htmlopsutils)DatasetAggregations)_broadcast_helper%_get_broadcast_dims_map_common_coordsalign)DatasetArithmetic)DataWithCoords_contains_datetime_like_objectsget_chunksizesunify_chunks)DatasetCoordinatesassert_coordinate_consistent)datetime_to_numeric)
IndexIndexesPandasIndexPandasMultiIndexassert_no_index_corruptedcreate_default_index_implicitfilter_indexes_from_coordsisel_indexesremove_unused_levels_categoriesroll_indexes)is_fancy_indexermap_index_queries)dataset_merge_methoddataset_update_methodmerge_coordinates_without_alignmerge_data_and_coords)get_clean_interp_index)OPTIONS_get_keep_attrs)
array_typeis_duck_dask_array)QuantileMethods	T_Dataset)DefaultFrozenHybridMappingProxy
OrderedSet_defaultdecode_numpy_dict_valuesdrop_dims_from_indexerseither_dict_or_kwargs
infix_dimsis_dict_like	is_scalarmaybe_wrap_array)IndexVariableVariableas_variablebroadcast_variablescalculate_dimensions)DatasetPlotAccessor)	ArrayLike)AbstractDataStore	ZarrStore)T_NetcdfEngineT_NetcdfTypes)Coordinates	DataArrayDatasetGroupBy)CoercibleMappingDatasetResample)DatasetCoarsenDatasetRolling)
CFCalendarCoarsenBoundaryOptionsCombineAttrsOptionsCompatOptionsDatetimeLikeDatetimeUnitOptionsDimsErrorOptionsErrorOptionsWithWarnInterpOptionsJoinOptionsPadModeOptionsPadReflectOptionsQueryEngineOptionsQueryParserOptionsReindexMethodOptionsSideOptionsT_XarrayDatasetWeighted)Delayed)	DataFrameyearmonthdayhourminutesecondmicrosecondZ
nanoseconddatetimeZ	dayofyearZ
weekofyearZ	dayofweekZquarterr   Mapping | Nonez#tuple[Hashable, Hashable, Variable])key	dim_sizesreturnc                 C  s   ddl m} |dkri }||krLtjt|| |d}t|f|}|||fS t|ts^t||	dd}t
|dkr~t||\}}| | }	t|	r||	}	t|	j|j}nt|	|j}t|	j|}
|||
fS )ziGet a virtual variable (e.g., 'time.year') from a dict of xarray.Variable
    objects (if possible)

    r   r^   Nname.      )xarray.core.dataarrayr_   pdr/   rangerR   
isinstancestrKeyErrorsplitlenr(   getattrdtdatarS   dims)	variablesr   r   r_   r   variableZ	split_keyref_namevar_nameZref_varZvirtual_var r   7/tmp/pip-unpacked-wheel-h316xyqg/xarray/core/dataset.py_get_virtual_variable   s(    

r   %stupler   None)argsmsgr   c                 C  s   | rt ||  d S N)
ValueError)r   r   r   r   r   _assert_empty   s    r   c              	     sX  ddl m} t| tri S | j}| j}| jdi tfddt	||D }t t
sb dkrnt|  t fddt	||D }|jj||| j|d}| jrJt	|||D ]\}}}	z| }
W n tk
r   Y qY nX t|
t
rt|
||
nt|
dd	 }tt|	dd	 |}|rtd
| dt| d qtt	||S )z]
    Return map from each dim to chunk sizes, accounting for backend's preferred chunks.
    r   Npreferred_chunksc                 3  s   | ]\}}  ||V  qd S r   get).0dimsize)r   r   r   	<genexpr>   s    z_get_chunk.<locals>.<genexpr>autoc                 3  s"   | ]\}}  |d p|V  qd S r   r   )r   r   preferred_chunk_sizeschunksr   r   r      s   )shapedtypeZprevious_chunkszFThe specified Dask chunks separate the stored chunks along dimension "z" starting at index zM. This could degrade performance. Instead, consider rechunking after loading.)
dask.arrayarrayr   rR   r   r   encodingr   r   zipr   dictfromkeyscoreZnormalize_chunksr   r   r   r   	itertools
accumulateset
differencewarningswarnmin)varr   dar   r   Zpreferred_chunk_shapeZchunk_shaper   r   Zchunk_sizesr   Zpreferred_stopsZbreaksr   )r   r   r   
_get_chunk   sL    
   
r   xarray-Fc                   s   ddl m}  d k	r( fdd|jD  |jr|| |r:|n|j }	| |  d|	 }
|j |
||d}|r|jd k	rtdd |jD |jd	< |S |S d S )
Nr   )tokenizec                   s   i | ]}| kr| | qS r   r   r   r   r   r   r   
<dictcomp>  s       z _maybe_chunk.<locals>.<dictcomp>-)r   lockinline_arrayc                 s  s   | ]}|d  V  qdS r   Nr   r   xr   r   r   r      s     z_maybe_chunk.<locals>.<genexpr>r   )		dask.baser   r   ndim_datachunkr   r   r   )r   r   r   tokenr   name_prefixZoverwrite_encoded_chunksr   r   Ztoken2Zname2r   r   r   _maybe_chunk	  s    
r   r
   Dataset)objr   c                 C  s(   t | dr|  } t| ts$t| } | S )zCast the given object to a Dataset.

    Handles Datasets, DataArrays and dictionaries of variables. A new Dataset
    object is only created if the provided object is not already one.
    
to_dataset)hasattrr   r   r   )r   r   r   r   
as_dataset&  s
    

r   c                 C  sv   zt | j}W n$ tk
r4   i }|s0tdY nX |r@|}n.t|dd }tdd | D rntd||fS )zkUse `inspect.signature` to try accessing `func` args. Otherwise, ensure
    they are provided by user.
    zGUnable to inspect `func` signature, and `param_names` was not provided.r   Nc                 S  s   g | ]}|j |j|jfkqS r   )kindVAR_POSITIONALVAR_KEYWORDr   pr   r   r   
<listcomp>D  s     z"_get_func_args.<locals>.<listcomp>zN`param_names` must be provided because `func` takes variable length arguments.)inspect	signature
parametersr   listanyvalues)funcparam_names	func_argsparamsr   r   r   _get_func_args3  s$    
r   c                 C  s   dd }dd | D }dd | D }| D ]}||krV|| j || jk	rV|| j ||< ||krt|| ||< || || d k s|| || d kr||| d || d ||< ||kr(|| ||< q(||fS )zpSet initial guess and bounds for curvefit.
    Priority: 1) passed args 2) func signature 3) scipy defaults
    c                 S  s`   t | }t |}t d| |  t||@  | d t|| @  |d t| |@  g}|S )Ng      ?r   )npisfiniteZnansumint)ZlbZubZ	lb_finiteZ	ub_finitep0r   r   r   _initialize_feasibleQ  s    

z9_initialize_curvefit_params.<locals>._initialize_feasiblec                 S  s   i | ]
}|d qS r   r   r   r   r   r   r   ^  s      z/_initialize_curvefit_params.<locals>.<dictcomp>c                 S  s   i | ]}|t j t jfqS r   )r   infr   r   r   r   r   _  s      r   r   )defaultemptyr   )r   r   boundsr   r   param_defaultsbounds_defaultsr   r   r   r   _initialize_curvefit_paramsL  s    (r   c                   @  s   e Zd ZdZddddZdddd	Zd
dddZdddddZdddddZddddZ	e
ddddZe
ddddZdd Zd S )!DataVariables_datasetr   datasetc                 C  s
   || _ d S r   r   selfr  r   r   r   __init__o  s    zDataVariables.__init__Iterator[Hashable]r   c                   s    fdd j jD S )Nc                 3  s   | ]}| j jkr|V  qd S r   r   _coord_namesr   r   r  r   r   r   s  s   z)DataVariables.__iter__.<locals>.<genexpr>)r   
_variablesr
  r   r
  r   __iter__r  s    
zDataVariables.__iter__r   c                 C  s   t | jjt | jj S r   )r   r   r  r  r
  r   r   r   __len__y  s    zDataVariables.__len__r   boolr   r   c                 C  s   || j jko|| j jkS r   )r   r  r  r  r   r   r   r   __contains__|  s    zDataVariables.__contains__r_   c                 C  s(   || j jkrtd| j | S t|d S )Nr_   )r   r  r   r   r  r   r   r   __getitem__  s    zDataVariables.__getitem__r   c                 C  s
   t | S r   )r   Zdata_vars_reprr
  r   r   r   __repr__  s    zDataVariables.__repr__zMapping[Hashable, Variable]c                   s   | j j t fdd| D S )Nc                   s   i | ]}| | qS r   r   r   kZall_variablesr   r   r     s      z+DataVariables.variables.<locals>.<dictcomp>)r   r   rG   r
  r   r  r   r     s    zDataVariables.variablesFrozen[Hashable, np.dtype]c                 C  s   | j jS )zMapping from data variable names to dtypes.

        Cannot be modified directly, but is updated when adding new variables.

        See Also
        --------
        Dataset.dtype
        )r   r   r
  r   r   r   r     s    
zDataVariables.dtypesc                   s    fdd j  D S )z6Provide method for the key-autocompletions in IPython.c                   s   g | ]}| j jkr|qS r   r  r	  r
  r   r   r     s   z;DataVariables._ipython_key_completions_.<locals>.<listcomp>)r   _ipython_key_completions_r
  r   r
  r   r    s    
z'DataVariables._ipython_key_completions_N)__name__
__module____qualname__	__slots__r  r  r  r  r  r  propertyr   r   r  r   r   r   r   r   l  s   r   r_   c                   @  s<   e Zd ZdZddddZdddddZd	d
ddZdS )_LocIndexerr   rE   c                 C  s
   || _ d S r   r   r  r   r   r   r    s    z_LocIndexer.__init__Mapping[Any, Any]r  c                 C  s   t |std| j|S )Nz-can only lookup dictionaries from Dataset.loc)r!   rO   	TypeErrorr  selr  r   r   r   r    s    
z_LocIndexer.__getitem__r   r  c                 C  s4   t |std| t| j|j}|| j|< d S )NzFcan only set locations defined by dictionaries from Dataset.loc. Got: )r!   rO   r   r:   r  dim_indexers)r  r   valuer"  r   r   r   __setitem__  s    
z_LocIndexer.__setitem__N)r  r  r  r  r  r  r$  r   r   r   r   r    s   r  c                   @  s  e Zd ZU dZded< ded< ded< ded	< ded
< ded< ded< ded< dZddddddddZeddddddZe	dddd Z
e	d!dd"d#Zejd$dd%d&d#Ze	d!dd'd(Zejd$dd%d)d(Ze	d*dd+d,Ze	d*dd-d.Ze	d/dd0d1Zddd2d3d4Zd5d6 Zd7d8 Zd9d: Zd;d< Ze	d=d> Ze	d?d@ ZdAdB ZdCdD ZddEddFdGdHZddIddJdKddLdMdNZddd2dOdPZddd2dQdRZddd2dSdTZedddUddVdWdXdWdddY	dZd[Zddde de d\fdd]d^dVd_d`dadbddc	dddeZ!de dd\fdddfd_d`dbddgdhdiZ"dde d\fdddfdjd_dbddkdldmZ#dddndodpdpdqddrdsdtZ$dddbduddvdwdxZ%dddbdudyddzd{d|Z&ddd2d}d~Z'dddyddddZ(ddd2ddZ)ddddddZ*dddddZ+e	ddddZ,e	ddddZ-ddbdddZ.ddddZ/dbdddZ0ddddZ1dddZ2e	ddddZ3e	ddd2ddZ4e5dddddZ6e5ddddddZ6ddddddZ6ddddddZ7dd Z8dddddZ9dZ:d ddbdddZ;d dbdddZ<d dbdddZ=d dbdddZ>e	ddddZ?e	ddddńZ@e	ddddȄZAe	dddd˄ZBdddddd΄ZCddddbddМdd҄ZDdddԜddքZEe5dddddddddbdbdd
ddZFe5ddddddddddbdd
ddZFe5dd\ddddddddddbdd
ddZFdddddddddbdbdd
ddZFe5dddddddddddbddddddZGe5dddddddddddddddddbdddddZGdddddddbddddbddddddZGdddd ZHddddZIddddddZJe	dddd	ZKe	ddd
dZLi ddd\d\fdddddbdbdddddZMdd$dddddZNd$ddddZOdd ZPddddbdddddd ZQdd!dd$dbddd"d#d$ZRddddېd%dbddd&d'd(ZSddd)ddd*d+d,ZTddd)ddd*d-d.ZUddd)ddd*d/d0ZVddd1ddd2d3d4ZWd5d6dddd7d7d d8d9d:ZXdddeYjZfdd1d;d%dbddd<d=d>Z[ddddeYjZfddd;d%dbdddd?d@dAZ\ddddeYjZd\fdddېd%dbddbdddB	dCdDZ]ddddGdbdHddddIdJdKZ^dĐd1dGdbdHdd dLdMdNZ_dOddPdQZ`dRddSdTdUZadRdRdVdWdXdYZbdRdRdZdWd[d\Zcddd]ddd^d_d`Zdddd]ddd^dadbZeddd]dddcdddeZfddd]ddd^dfdgZgddd]ddhdidjZhdʐdkdldd dmdndoZidːdpdbdqd drdsdtZjdddqdbddudvdwZkdddxdyddzd{d|Zlddd}d~ddddZmdϐddddZnddddddddddZoddepfdddddddddZqdddddddddZrdddddbddddZsddddbddddZtdeYjZd\fddddbddddZuddddddZvew ddeYjZdfddd̐ddddddddZxdddbddddZydddd̐dddddZzdddd̐dddddZ{dԐddddddddZ|dՐddddddddZ}dddd2ddZ~dddddddddZdd!dddddddZddddddddŜdƐdǄZddddȜdɐdʄZddddGddːdddd͜dΐdτZddddddМdѐd҄ZddddddМdӐdԄZdddddՐdքZddd\d\dלdddddbdbdddٜdڐdۄZddddddddޜdߐdZddddddddޜddZddddddddZdddddddZddddddZddddZddddZddddddZdddddddZdddddddZeddddbddd dZdddbddddZddbdbddddZedd$dd	d
dZddd2ddZdd dddZddd2ddZddbd dddZdd ZdddddddddZdeYjZfddddddd d!Zddddbddd"d#d$Zddd%dbdd&d'd(Zddd)dϐd*dbddd+dd,	d-d.Zddddbddd/d0d1Zdddd2d3dd4d5d6Zdddqd7dd8d9d:Zdd;d<Zdddqd7dd8d=d>Ze	ddd2d?d@Ze	ddd2dAdBZeeZddd2dCdDZddd2dEdFZddGdHdHdIdJdKdLdMZddddddNdOdbdPddQ	dRdSZdddUdVdWdXdWdYddddZ
d[d\ZddeYjZdfddddddd]d^d_ZddeYjZdfddddddd]d`daZdddddbdcddZdddddbdedfZddddhdiddddjdkdlZdddmdnddbdododpdoddq
drdsZddd̐duddvdwdxZdddzdd{d|ddd}d~dZddddddddZdddbdbddddZddd)dbdddbdbdbdd	ddZdddddZdddddddddZddddddddddZddddddddddddddddZdS (  r   ax  A multi-dimensional, in memory, array database.

    A dataset resembles an in-memory representation of a NetCDF file,
    and consists of variables, coordinates and attributes which
    together form a self describing dataset.

    Dataset implements the mapping interface with keys given by variable
    names and values given by DataArray objects for each variable name.

    One dimensional variables with name equal to their dimension are
    index coordinates used for label based indexing.

    To load data from a file or file-like object, use the `open_dataset`
    function.

    Parameters
    ----------
    data_vars : dict-like, optional
        A mapping from variable names to :py:class:`~xarray.DataArray`
        objects, :py:class:`~xarray.Variable` objects or to tuples of
        the form ``(dims, data[, attrs])`` which can be used as
        arguments to create a new ``Variable``. Each dimension must
        have the same length in all variables in which it appears.

        The following notations are accepted:

        - mapping {var name: DataArray}
        - mapping {var name: Variable}
        - mapping {var name: (dimension name, array-like)}
        - mapping {var name: (tuple of dimension names, array-like)}
        - mapping {dimension name: array-like}
          (it will be automatically moved to coords, see below)

        Each dimension must have the same length in all variables in
        which it appears.
    coords : dict-like, optional
        Another mapping in similar form as the `data_vars` argument,
        except the each item is saved on the dataset as a "coordinate".
        These variables have an associated meaning: they describe
        constant/fixed/independent quantities, unlike the
        varying/measured/dependent quantities that belong in
        `variables`. Coordinates values may be given by 1-dimensional
        arrays or scalars, in which case `dims` do not need to be
        supplied: 1D arrays will be assumed to give index values along
        the dimension with the same name.

        The following notations are accepted:

        - mapping {coord name: DataArray}
        - mapping {coord name: Variable}
        - mapping {coord name: (dimension name, array-like)}
        - mapping {coord name: (tuple of dimension names, array-like)}
        - mapping {dimension name: array-like}
          (the dimension name is implicitly set to be the same as the
          coord name)

        The last notation implies that the coord name is the same as
        the dimension name.

    attrs : dict-like, optional
        Global attributes to save on this dataset.

    Examples
    --------
    Create data:

    >>> np.random.seed(0)
    >>> temperature = 15 + 8 * np.random.randn(2, 2, 3)
    >>> precipitation = 10 * np.random.rand(2, 2, 3)
    >>> lon = [[-99.83, -99.32], [-99.79, -99.23]]
    >>> lat = [[42.25, 42.21], [42.63, 42.59]]
    >>> time = pd.date_range("2014-09-06", periods=3)
    >>> reference_time = pd.Timestamp("2014-09-05")

    Initialize a dataset with multiple dimensions:

    >>> ds = xr.Dataset(
    ...     data_vars=dict(
    ...         temperature=(["x", "y", "time"], temperature),
    ...         precipitation=(["x", "y", "time"], precipitation),
    ...     ),
    ...     coords=dict(
    ...         lon=(["x", "y"], lon),
    ...         lat=(["x", "y"], lat),
    ...         time=time,
    ...         reference_time=reference_time,
    ...     ),
    ...     attrs=dict(description="Weather related data."),
    ... )
    >>> ds
    <xarray.Dataset>
    Dimensions:         (x: 2, y: 2, time: 3)
    Coordinates:
        lon             (x, y) float64 -99.83 -99.32 -99.79 -99.23
        lat             (x, y) float64 42.25 42.21 42.63 42.59
      * time            (time) datetime64[ns] 2014-09-06 2014-09-07 2014-09-08
        reference_time  datetime64[ns] 2014-09-05
    Dimensions without coordinates: x, y
    Data variables:
        temperature     (x, y, time) float64 29.11 18.2 22.83 ... 18.28 16.15 26.63
        precipitation   (x, y, time) float64 5.68 9.256 0.7104 ... 7.992 4.615 7.805
    Attributes:
        description:  Weather related data.

    Find out where the coldest temperature was and what values the
    other variables had:

    >>> ds.isel(ds.temperature.argmin(...))
    <xarray.Dataset>
    Dimensions:         ()
    Coordinates:
        lon             float64 -99.32
        lat             float64 42.21
        time            datetime64[ns] 2014-09-08
        reference_time  datetime64[ns] 2014-09-05
    Data variables:
        temperature     float64 7.182
        precipitation   float64 8.326
    Attributes:
        description:  Weather related data.
    zdict[Hashable, Any] | None_attrszdict[str, Any]_cachezset[Hashable]r  zdict[Hashable, int]_dims	_encodingzCallable[[], None] | None_closezdict[Hashable, Index]_indexeszdict[Hashable, Variable]r  )	r%  r&  r  r'  r(  r)  r*  r  __weakref__NzMapping[Any, Any] | Noner   )	data_varscoordsattrsr   c           
      C  s   |d kri }|d kri }t |t |@ }|r<td|dt|trL|j}t||dd\}}}}}	|d k	rtt|nd | _d | _d | _	|| _
|| _|| _|| _d S )Nz
variables z' are found in both data_vars and coordsbroadcast_equalscompat)r   r   r   r   r   r>   r   r%  r)  r(  r  r  r'  r*  )
r  r,  r-  r.  Zboth_data_and_coordsr   coord_namesr   indexes_r   r   r   r  M  s.    


  zDataset.__init__ztype[T_Dataset]rE   )clsr   c                 C  s:   |  \}}|r|||\}}| ||d}||j |S )zWCreate a new dataset from the contents of a backends.*DataStore
        object
        r.  )loadZ	set_closeclose)r5  storedecoderr   
attributesr   r   r   r   
load_storeq  s    zDataset.load_storezFrozen[Hashable, Variable]r  c                 C  s
   t | jS )a5  Low level interface to Dataset contents as dict of Variable objects.

        This ordered dictionary is frozen to prevent mutation that could
        violate Dataset invariants. It contains all variable objects
        constituting the Dataset, including both data variables and
        coordinates.
        )rG   r  r
  r   r   r   r   }  s    	zDataset.variableszdict[Any, Any]c                 C  s   | j dkri | _ | j S )z/Dictionary of global attributes on this datasetN)r%  r
  r   r   r   r.    s    
zDataset.attrsr  )r#  r   c                 C  s   t || _d S r   )r   r%  r  r#  r   r   r   r.    s    c                 C  s   | j dkri | _ | j S )z8Dictionary of global encoding attributes on this datasetN)r(  r
  r   r   r   r     s    
zDataset.encodingc                 C  s   t || _d S r   )r   r(  r=  r   r   r   r     s    zFrozen[Hashable, int]c                 C  s
   t | jS )at  Mapping from dimension names to lengths.

        Cannot be modified directly, but is updated when adding new variables.

        Note that type of this object differs from `DataArray.dims`.
        See `Dataset.sizes` and `DataArray.sizes` for consistently named
        properties.

        See Also
        --------
        Dataset.sizes
        DataArray.dims
        )rG   r'  r
  r   r   r   r     s    zDataset.dimsc                 C  s   | j S )a1  Mapping from dimension names to lengths.

        Cannot be modified directly, but is updated when adding new variables.

        This is an alias for `Dataset.dims` provided for the benefit of
        consistency with `DataArray.sizes`.

        See Also
        --------
        DataArray.sizes
        r   r
  r   r   r   sizes  s    zDataset.sizesr  c                   s   t  fdd j D S )zMapping from data variable names to dtypes.

        Cannot be modified directly, but is updated when adding new variables.

        See Also
        --------
        DataArray.dtype
        c                   s"   i | ]\}}| j kr||jqS r   )r  r   )r   nvr
  r   r   r     s   
 z"Dataset.dtypes.<locals>.<dictcomp>)rG   r  itemsr
  r   r
  r   r     s
    

zDataset.dtypes)r  r   c                 K  s|   dd | j  D }|rTddlm} |j| |}t||D ]\}}|| j | _q>| j  D ]\}}||kr^|  q^| S )a  Manually trigger loading and/or computation of this dataset's data
        from disk or a remote source into memory and return this dataset.
        Unlike compute, the original dataset is modified and returned.

        Normally, it should not be necessary to call this method in user code,
        because all xarray functions should either work on deferred data or
        load data automatically. However, this method can be necessary when
        working with many file objects on disk.

        Parameters
        ----------
        **kwargs : dict
            Additional keyword arguments passed on to ``dask.compute``.

        See Also
        --------
        dask.compute
        c                 S  s"   i | ]\}}t |jr||jqS r   rC   r   r   r  rA  r   r   r   r     s    
  z Dataset.load.<locals>.<dictcomp>r   N)	r   rB  r   r   computer   r   r   r7  )r  kwargs	lazy_datar   evaluated_datar  r   rA  r   r   r   r7    s    
zDataset.loadc                 C  s&   ddl m} |t| | j| j| jfS )Nr   )normalize_token)r   rI  typer  r  r%  )r  rI  r   r   r   __dask_tokenize__  s    zDataset.__dask_tokenize__c                 C  s~   dd | j  D }dd | D }|s.d S zddlm} |j|  W S  tk
rx   ddlm} |j|   Y S X d S )Nc                 S  s   i | ]\}}||  qS r   )__dask_graph__rD  r   r   r   r     s      z*Dataset.__dask_graph__.<locals>.<dictcomp>c                 S  s   i | ]\}}|d k	r||qS r   r   rD  r   r   r   r      s       r   HighLevelGraph)	sharedict)	r   rB  dask.highlevelgraphrN  merger   ImportErrordaskrO  )r  ZgraphsrN  rO  r   r   r   rL    s    zDataset.__dask_graph__c                   s    dd l   fdd| j D S )Nr   c                   s   g | ]}  |r| qS r   )is_dask_collection__dask_keys__r   rA  rS  r   r   r     s   
z)Dataset.__dask_keys__.<locals>.<listcomp>)rS  r   r   r
  r   rW  r   rU    s    
zDataset.__dask_keys__c                   s&   dd l  t fdd| j D dS )Nr   c                 3  s    | ]}  |r| V  qd S r   )rT  __dask_layers__rV  rW  r   r   r     s   
z*Dataset.__dask_layers__.<locals>.<genexpr>r   )rS  sumr   r   r
  r   rW  r   rX    s    
zDataset.__dask_layers__c                 C  s   dd l m} |jjS Nr   )r   r   Array__dask_optimize__r  r   r   r   r   r\  "  s    zDataset.__dask_optimize__c                 C  s   dd l m} |jjS rZ  )r   r   r[  __dask_scheduler__r]  r   r   r   r^  (  s    zDataset.__dask_scheduler__c                 C  s
   | j dfS Nr   )_dask_postcomputer
  r   r   r   __dask_postcompute__.  s    zDataset.__dask_postcompute__c                 C  s
   | j dfS r_  )_dask_postpersistr
  r   r   r   __dask_postpersist__1  s    zDataset.__dask_postpersist__zIterable[Variable])r  resultsr   c           	   	   C  s~   dd l }i }t|}| j D ]8\}}||rN| \}}|t|f| }|||< qt| || j	| j
| j| j| j| jS rZ  )rS  iterr  rB  rT  ra  nextrJ  _construct_directr  r'  r%  r*  r(  r)  )	r  rd  rS  r   Zresults_iterr  rA  rebuildr   r   r   r   r`  4  s"    

zDataset._dask_postcomputerenamer   zMapping[str, str] | None)r  dskrj  r   c             	     s*  ddl m} ddlm} ddlm} i }| j D ]\}}||sL|||< q2t||r|	 }	 rt fdd|	D }	|
|	}
nR rddlm}m  fdd|| D }|||\}
}n||| \}
}| \}} rd	 ini }||
f||||< q2t| || j| j| j| j| j| jS )
Nr   )rT  rM  )cullc                   s   g | ]}  ||qS r   r   r  ri  r   r   r   _  s     z-Dataset._dask_postpersist.<locals>.<listcomp>)flattenreplace_name_in_keyc                   s   g | ]}| qS r   r   r  rj  rn  r   r   r   f  s    rj  )rS  rT  rP  rN  Zdask.optimizationrl  r  rB  r   rX  Zcull_layersr   rm  rn  rU  rc  rJ  rg  r  r'  r%  r*  r(  r)  )r  rk  rj  rT  rN  rl  r   r  rA  ZlayersZdsk2rm  keysr4  rh  r   rF  r   ro  r   rb  J  s@    

zDataset._dask_postpersistc                 K  s   | j dd}|jf |S )a  Manually trigger loading and/or computation of this dataset's data
        from disk or a remote source into memory and return a new dataset.
        Unlike load, the original dataset is left unaltered.

        Normally, it should not be necessary to call this method in user code,
        because all xarray functions should either work on deferred data or
        load data automatically. However, this method can be necessary when
        working with many file objects on disk.

        Parameters
        ----------
        **kwargs : dict
            Additional keyword arguments passed on to ``dask.compute``.

        See Also
        --------
        dask.compute
        Fdeep)copyr7  r  rF  newr   r   r   rE  }  s    zDataset.computec                 K  sT   dd | j  D }|rPddl}|j| |}t||D ]\}}|| j | _q:| S )z!Persist all Dask arrays in memoryc                 S  s"   i | ]\}}t |jr||jqS r   rC  rD  r   r   r   r     s    
  z,Dataset._persist_inplace.<locals>.<dictcomp>r   N)r   rB  rS  persistr   r   r   )r  rF  rG  rS  rH  r  r   r   r   r   _persist_inplace  s    zDataset._persist_inplacec                 K  s   | j dd}|jf |S )aZ  Trigger computation, keeping data as dask arrays

        This operation can be used to trigger computation on underlying dask
        arrays, similar to ``.compute()`` or ``.load()``.  However this
        operation keeps the data as dask arrays. This is particularly useful
        when using the dask.distributed scheduler and you want to load a large
        amount of data into distributed memory.

        Parameters
        ----------
        **kwargs : dict
            Additional keyword arguments passed on to ``dask.persist``.

        See Also
        --------
        dask.persist
        Frq  )rs  rw  rt  r   r   r   rv    s    zDataset.persistzdict[Any, Variable]zdict[Any, int] | Nonezdict | Nonezdict[Any, Index] | None)	r5  r   r2  r   r.  r3  r   r8  r   c           	      C  sT   |dkrt |}|dkri }t| }||_||_||_||_||_||_||_	|S )zaShortcut around __init__ for internal use when we want to skip
        costly validation
        N)
rV   object__new__r  r  r'  r*  r%  r)  r(  )	r5  r   r2  r   r.  r3  r   r8  r   r   r   r   rg    s    
zDataset._construct_directFzdict[Hashable, Variable] | Nonezset[Hashable] | Nonez$dict[Hashable, Any] | None | Defaultzdict[Hashable, Index] | Nonezdict | None | Defaultr  )	r  r   r2  r   r.  r3  r   inplacer   c           	      C  s   |r^|dk	r|| _ |dk	r || _|dk	r.|| _|tk	r<|| _|dk	rJ|| _|tk	rX|| _| }n|dkrp| j  }|dkr| j }|dkr| j }|tkrt| j}|dkr| j }|tkrt| j}| ||||||}|S )a5  Fastpath constructor for internal use.

        Returns an object with optionally with replaced attributes.

        Explicitly passed arguments are *not* copied when placed on the new
        dataset. It is up to the caller to ensure that they have the right type
        and are not used elsewhere.
        N)	r  r  r'  rJ   r%  r*  r(  rs  rg  )	r  r   r2  r   r.  r3  r   rz  r   r   r   r   _replace  sF    



     zDataset._replacez
set | None)r  r   r2  r.  r3  rz  r   c                 C  s   t |}| j||||||dS )z/Replace variables with recalculated dimensions.rz  rV   r{  )r  r   r2  r.  r3  rz  r   r   r   r   _replace_with_new_dims  s    	     zDataset._replace_with_new_dimszdict[Hashable, int] | None)r  r   r2  r   r.  rz  r   c                 C  s&   |dkrt |}| j||||d|dS )zDeprecated version of _replace_with_new_dims().

        Unlike _replace_with_new_dims(), this method always recalculates
        indexes from variables.
        N)r3  rz  r}  )r  r   r2  r   r.  rz  r   r   r   _replace_vars_and_dims  s         zDataset._replace_vars_and_dimszMapping[Hashable, Index]z"Mapping[Hashable, Variable] | Nonezlist[Hashable] | Nonez"Mapping[Hashable, Hashable] | None)r  r3  r   drop_variablesdrop_indexesrename_dimsr   c                 C  s  |s| S |dkri }|dkr g }|dkr,g }| j  }| j }t| j}i }	i }
| D ]R\}}| j |}|dk	r|j|j |j	|j	 ||kr||	|< qZ||
|< qZ|D ]}|| ||< q|	 D ]\}}|
| |||< q|
D ]}|| q||
 |D ]}|| q
|D ]&}|| ||d || q | j|||d}|r||}|i |\}}|j|||dS |S dS )zsMaybe replace indexes.

        This function may do a lot more depending on index query
        results.

        Nr   r2  r3  )r   r2  r   )r  rs  r  r   r*  rB  r   r.  updater   addpopremover{  _rename_dims_rename_vars)r  r3  r   r  r  r  new_variablesnew_coord_namesnew_indexesindex_variablesZno_index_variablesr   r   Zold_varr  Zreplacedr   r   r   r   _overwrite_indexes(  sb    








  
  zDataset._overwrite_indexeszMapping[Any, ArrayLike] | None)r  rr  r   r   c                 C  s   | j ||dS )a  Returns a copy of this dataset.

        If `deep=True`, a deep copy is made of each of the component variables.
        Otherwise, a shallow copy of each of the component variable is made, so
        that the underlying memory region of the new dataset is the same as in
        the original dataset.

        Use `data` to create a new object with the same structure as
        original but entirely new data.

        Parameters
        ----------
        deep : bool, default: False
            Whether each component variable is loaded into memory and copied onto
            the new object. Default is False.
        data : dict-like or None, optional
            Data to use in the new object. Each item in `data` must have same
            shape as corresponding data variable in original. When `data` is
            used, `deep` is ignored for the data variables and only used for
            coords.

        Returns
        -------
        object : Dataset
            New object with dimensions, attributes, coordinates, name, encoding,
            and optionally data copied from original.

        Examples
        --------
        Shallow copy versus deep copy

        >>> da = xr.DataArray(np.random.randn(2, 3))
        >>> ds = xr.Dataset(
        ...     {"foo": da, "bar": ("x", [-1, 2])},
        ...     coords={"x": ["one", "two"]},
        ... )
        >>> ds.copy()
        <xarray.Dataset>
        Dimensions:  (dim_0: 2, dim_1: 3, x: 2)
        Coordinates:
          * x        (x) <U3 'one' 'two'
        Dimensions without coordinates: dim_0, dim_1
        Data variables:
            foo      (dim_0, dim_1) float64 1.764 0.4002 0.9787 2.241 1.868 -0.9773
            bar      (x) int64 -1 2

        >>> ds_0 = ds.copy(deep=False)
        >>> ds_0["foo"][0, 0] = 7
        >>> ds_0
        <xarray.Dataset>
        Dimensions:  (dim_0: 2, dim_1: 3, x: 2)
        Coordinates:
          * x        (x) <U3 'one' 'two'
        Dimensions without coordinates: dim_0, dim_1
        Data variables:
            foo      (dim_0, dim_1) float64 7.0 0.4002 0.9787 2.241 1.868 -0.9773
            bar      (x) int64 -1 2

        >>> ds
        <xarray.Dataset>
        Dimensions:  (dim_0: 2, dim_1: 3, x: 2)
        Coordinates:
          * x        (x) <U3 'one' 'two'
        Dimensions without coordinates: dim_0, dim_1
        Data variables:
            foo      (dim_0, dim_1) float64 7.0 0.4002 0.9787 2.241 1.868 -0.9773
            bar      (x) int64 -1 2

        Changing the data using the ``data`` argument maintains the
        structure of the original object, but with the new data. Original
        object is unaffected.

        >>> ds.copy(data={"foo": np.arange(6).reshape(2, 3), "bar": ["a", "b"]})
        <xarray.Dataset>
        Dimensions:  (dim_0: 2, dim_1: 3, x: 2)
        Coordinates:
          * x        (x) <U3 'one' 'two'
        Dimensions without coordinates: dim_0, dim_1
        Data variables:
            foo      (dim_0, dim_1) int64 0 1 2 3 4 5
            bar      (x) <U1 'a' 'b'

        >>> ds
        <xarray.Dataset>
        Dimensions:  (dim_0: 2, dim_1: 3, x: 2)
        Coordinates:
          * x        (x) <U3 'one' 'two'
        Dimensions without coordinates: dim_0, dim_1
        Data variables:
            foo      (dim_0, dim_1) float64 7.0 0.4002 0.9787 2.241 1.868 -0.9773
            bar      (x) int64 -1 2

        See Also
        --------
        pandas.DataFrame.copy
        )rr  r   _copy)r  rr  r   r   r   r   rs  r  s    czDataset.copyzdict[int, Any] | None)r  rr  r   memor   c                 C  s  |d kri }nt |s td|rrt| j }t| }|| }|rXtd||| }|rrtd|| jj|d\}}	i }
| j	
 D ]8\}}||	kr|	| |
|< q|j||||d|
|< q|rt| j|n
t| j}|rt| j|n
t| j}| j|
|||dS )NzData must be dict-likezIData must only contain variables in original dataset. Extra variables: {}zGData must contain all variables in original dataset. Data is missing {}rq  )rr  r   r  )r3  r.  r   )r!   rO   r   r   r,  rp  formatxindexesZcopy_indexesr  rB  r  r   rs  deepcopyr%  r(  r{  )r  rr  r   r  Zvar_keysZ	data_keysZkeys_not_in_varsZkeys_missing_from_datar3  
index_varsr   r  rA  r.  r   r   r   r   r    s>    
zDataset._copyc                 C  s   | j ddS )NFrq  r  r
  r   r   r   __copy__  s    zDataset.__copy__)r  r  r   c                 C  s   | j d|dS )NT)rr  r  r  )r  r  r   r   r   __deepcopy__  s    zDataset.__deepcopy__c                 C  s    dd | j  D }| j|dS )z
        Coerces wrapped data and coordinates into numpy arrays, returning a Dataset.

        See also
        --------
        DataArray.as_numpy
        DataArray.to_numpy : Returns only the data as a numpy.ndarray object.
        c                 S  s   i | ]\}}||  qS r   )as_numpyrD  r   r   r   r     s      z$Dataset.as_numpy.<locals>.<dictcomp>r   )r   rB  r{  )r  Znumpy_variablesr   r   r   r    s    	zDataset.as_numpyzIterable[Hashable])r  namesr   c              	     s^  i }t  }i }|D ]}zj| ||< W q tk
r   tj|j\}}}|||< |jksj|jkrt|| |f|jkrt||\ }	| fdd|	D  ||	 ||	 Y qX qt	 }
|
 D ]}|
|j qЇfdd|
D }jD ]>}|jkrqt j| j|
krj| ||< || q|tj| j||||dS )zCreate a new Dataset with the listed variables from this dataset and
        the all relevant coordinates. Skips all validation.
        c                   s   i | ]
}| qS r   r   r  indexr   r   r   (  s      z(Dataset._copy_listed.<locals>.<dictcomp>c                   s   i | ]}| j | qS r   r>  r  r
  r   r   r   0  s      r3  )r   r  r   r   r   r  r  r4   r  rI   r   r   r5   r*  r{  )r  r  r   r2  r3  r   r   r   r   r  needed_dimsrA  r   r  r   )r  r  r   _copy_listed  s@      



zDataset._copy_listedr   r_   )r   r   c           	      C  s   ddl m} z| j| }W n* tk
rD   t| j|| j\}}}Y nX t|j}i }| jD ]0}|| jkrZt| j| j|krZ| j| ||< qZt	| j
t|}|||||ddS )z.Construct a DataArray by indexing this datasetr   r^   T)r   r3  fastpath)r   r_   r  r   r   r   r   r  r   r5   r*  )	r  r   r_   r   r4  r  r-  r  r3  r   r   r   _construct_dataarray?  s    

zDataset._construct_dataarrayz Iterable[Mapping[Hashable, Any]]c                 c  s   | j E dH  | jV  dS )z2Places to look-up items for attribute-style accessN)_item_sourcesr.  r
  r   r   r   _attr_sourcesT  s    zDataset._attr_sourcesc                 c  s.   | j V  t| j| jdV  t| j| dV  dS )z*Places to look-up items for key-completion)rp  mappingN)r,  rH   r  r-  r   r
  r   r   r   r  Z  s    zDataset._item_sourcesrx  r  c                 C  s
   || j kS )zzThe 'in' operator will return true or false depending on whether
        'key' is an array in the dataset or not.
        r  r  r   r   r   r  c  s    zDataset.__contains__r   c                 C  s
   t | jS r   )r   r,  r
  r   r   r   r  i  s    zDataset.__len__c                 C  s
   t | jS r   )r  r,  r
  r   r   r   __bool__l  s    zDataset.__bool__r  c                 C  s
   t | jS r   )re  r,  r
  r   r   r   r  o  s    zDataset.__iter__c                 C  s   t dd S )Nzcannot directly convert an xarray.Dataset into a numpy array. Instead, create an xarray.DataArray first, either with indexing on the Dataset or by invoking the `to_array()` method.)r   )r  r   r   r   r   	__array__r  s    zDataset.__array__c                 C  s   t dd | j D S )z
        Total bytes consumed by the data arrays of all variables in this dataset.

        If the backend array for any variable does not include ``nbytes``, estimates
        the total bytes for that array based on the ``size`` and ``dtype``.
        c                 s  s   | ]}|j V  qd S r   )nbytesrV  r   r   r   r     s     z!Dataset.nbytes.<locals>.<genexpr>)rY  r   r   r
  r   r   r   r  z  s    zDataset.nbytesz_LocIndexer[T_Dataset]c                 C  s   t | S )zAttribute for location based indexing. Only supports __getitem__,
        and only when the key is a dict of the form {dim: labels}.
        )r  r
  r   r   r   loc  s    zDataset.locc                 C  s   d S r   r   r  r   r   r   r    s    zDataset.__getitem__)r  r   r   c                 C  s   d S r   r   r  r   r   r   r    s    z1Mapping[Any, Any] | Hashable | Iterable[Hashable]zT_Dataset | DataArrayc                 C  sT   t |r| jf |S t |r*| |S t |r>| |S tdt| dS )zAccess variables or coordinates of this dataset as a
        :py:class:`~xarray.DataArray` or a subset of variables or a indexed dataset.

        Indexing with a list of names will return a new ``Dataset`` object.
        Unsupported key-type N)	r!   rO   iselhashabler  iterable_of_hashabler  r   rJ  r  r   r   r   r    s    




z'Hashable | Iterable[Hashable] | Mappingr
   )r   r#  r   c           	      C  s  ddl m} t|r| ||}g }|  D ]f\}}z|| ||< || W q. tk
r } z$|r~td| d| |n|W 5 d}~X Y q.X q.nt	|rt
|trtd| ||i nt|rt|}t|dkrtdt|dkr| |d |i nt|t|kr@td	t| d
t| dt
|trh| tt||j  n*t
||r~tdn| tt|| ntdt| dS )a  Add an array to this dataset.
        Multiple arrays can be added at the same time, in which case each of
        the following operations is applied to the respective value.

        If key is dict-like, update all variables in the dataset
        one by one with the given value at the given location.
        If the given value is also a dataset, select corresponding variables
        in the given value and in the dataset to be changed.

        If value is a `
        from .dataarray import DataArray`, call its `select_vars()` method, rename it
        to `key` and merge the contents of the resulting dataset into this
        dataset.

        If value is a `Variable` object (or tuple of form
        ``(dims, data[, attrs])``), add it to this dataset as a new
        variable.
        r   r^   z8An error occurred while setting values of the variable 'z;'. The following variables have been successfully updated:
NzoCannot assign a Dataset to a single key - only a DataArray or Variable object can be stored under a single key.z!Empty list of variables to be setr   z*Different lengths of variables to be set (z&) and data used as input for setting ()z/Cannot assign single DataArray to multiple keysr  )r   r_   r!   rO   _setitem_checkrB  append	ExceptionRuntimeErrorr  r   r   r   r  r  r   r   r   r   r   r,  r   rJ  )	r  r   r#  r_   	processedr   r   eZkeylistr   r   r   r$    sL    



zDataset.__setitem__c                   s  ddl m} ddlm} ttrP fddjD }|rttd| d  n$tfdd|t	t
fD sttd	t }  D ] \}}z|| }	W n: tk
r }
 ztd
| d| d|
W 5 d}
~
X Y nX ttr| nt|rfjD ]$}||	jkrtd
| d| dqtfdd|	jD }|jkrptd
| d| dj n
tj|	jdd||< qt|sttr| | ddd |S )zConsistency check for __setitem__

        When assigning values to a subset of a Dataset, do consistency check beforehand
        to avoid leaving the dataset in a partially updated state when an error occurs.
        r   )r%   r^   c                   s   g | ]}| j kr|qS r   )r,  r   r   r
  r   r   r     s    
 z*Dataset._setitem_check.<locals>.<listcomp>z
Variables z2 in new values not available in original dataset:
c                   s   g | ]}t  |qS r   r   )r   t)r#  r   r   r     s     zBDataset assignment only accepts DataArrays, Datasets, and scalars.z
Variable 'z': indexer z not availableNz': dimension 'z<' appears in new values but not in the indexed original datac                 3  s   | ]}| j kr|V  qd S r   r>  r   )valr   r   r     s     
 z)Dataset._setitem_check.<locals>.<genexpr>z:': dimension order differs between original and new data:
z
vs.
Frs  exactjoinrs  )xarray.core.alignmentr%   r   r_   r   r   r,  r   r   r   r   r   rB  r  r   r   r   r   r   astyper   )r  r   r#  r%   r_   Zmissing_vars	new_valuer   r   Zvar_kr  r   r   r   )r  r  r#  r   r    sV    






zDataset._setitem_checkc                 C  sD   t | j|h || jkr | j|= | j|= | j| t| j| _dS )z$Remove a variable from this dataset.N)r3   r  r*  r  r  discardrV   r'  r  r   r   r   __delitem__-  s    
zDataset.__delitem__r   )other
compat_strr   c                   s6   dddd fdd}| j |j ko4tj| j|j|dS )z(Helper function for equals and identicalrS   r  )r   yr   c                   s   t |  |S r   )r   r   r  r  r   r   r1  @  s    z#Dataset._all_compat.<locals>.compatr0  )r  r!   
dict_equivr  )r  r  r  r1  r   r  r   _all_compat;  s      zDataset._all_compat)r  r   c              	   C  s.   z|  |dW S  ttfk
r(   Y dS X dS )a  Two Datasets are broadcast equal if they are equal after
        broadcasting all variables against each other.

        For example, variables that are scalar in one dataset but non-scalar in
        the other dataset can still be broadcast equal if the the non-scalar
        variable is a constant.

        See Also
        --------
        Dataset.equals
        Dataset.identical
        r/  FNr  r   AttributeErrorr  r  r   r   r   r/  G  s    zDataset.broadcast_equalsc              	   C  s.   z|  |dW S  ttfk
r(   Y dS X dS )a  Two Datasets are equal if they have matching variables and
        coordinates, all of which are equal.

        Datasets can still be equal (like pandas objects) if they have NaN
        values in the same locations.

        This method is necessary because `v1 == v2` for ``Dataset``
        does element-wise comparisons (like numpy.ndarrays).

        See Also
        --------
        Dataset.broadcast_equals
        Dataset.identical
        equalsFNr  r  r   r   r   r  Y  s    zDataset.equalsc              	   C  s>   zt | j|jo| |dW S  ttfk
r8   Y dS X dS )zLike equals, but also checks all dataset attributes and the
        attributes on all variables and coordinates.

        See Also
        --------
        Dataset.broadcast_equals
        Dataset.equals
        	identicalFN)r!   r  r.  r  r   r  r  r   r   r   r  m  s    	 zDataset.identicalzIndexes[pd.Index]c                 C  s
   | j  S )zMapping of pandas.Index objects used for label based indexing.

        Raises an error if this Dataset has indexes that cannot be coerced
        to pandas.Index objects.

        See Also
        --------
        Dataset.xindexes

        )r  Zto_pandas_indexesr
  r   r   r   r3  }  s    zDataset.indexeszIndexes[Index]c                   s   t  j fdd jD S )z>Mapping of xarray Index objects used for label based indexing.c                   s   i | ]}| j | qS r   r  r  r
  r   r   r     s      z$Dataset.xindexes.<locals>.<dictcomp>)r0   r*  r
  r   r
  r   r    s    zDataset.xindexesr,   c                 C  s   t | S )z]Dictionary of xarray.DataArray objects corresponding to coordinate
        variables
        )r,   r
  r   r   r   r-    s    zDataset.coordsr   c                 C  s   t | S )z?Dictionary of DataArray objects corresponding to data variables)r   r
  r   r   r   r,    s    zDataset.data_varszHashable | Iterable[Hashable]c                 C  sF   t |tst |ts|g}nt|}| | |  }|j| |S )ax  Given names of one or more variables, set them as coordinates

        Parameters
        ----------
        names : hashable or iterable of hashable
            Name(s) of variables in this dataset to convert into coordinates.

        Returns
        -------
        Dataset

        See Also
        --------
        Dataset.swap_dims
        Dataset.assign_coords
        )r   r   r   r   _assert_all_in_datasetrs  r  r  )r  r  r   r   r   r   
set_coords  s    
zDataset.set_coordsrm   )r  r  dropr   c                 C  s   |dkr| j t| j }nRt|ts.t|ts6|g}nt|}| | t|t| j@ }|rltd| | 	 }|j 
| |r|D ]}|j|= q|S )a  Given names of coordinates, reset them to become variables

        Parameters
        ----------
        names : str, Iterable of Hashable or None, optional
            Name(s) of non-index coordinates in this dataset to reset into
            variables. By default, all non-index coordinates are reset.
        drop : bool, default: False
            If True, remove coordinates instead of converting them into
            variables.

        Returns
        -------
        Dataset
        Nz3cannot remove index coordinates with reset_coords: )r  r   r*  r   r   r   r   r  r   rs  difference_updater  )r  r  r  Z
bad_coordsr   r   r   r   r   reset_coords  s"    

zDataset.reset_coordsrY   )r9  r   c                 K  s   ddl m} || |f| dS )z7Store dataset contents to a backends.*DataStore object.r   )dump_to_storeN)xarray.backends.apir  )r  r9  rF  r  r   r   r   r    s    zDataset.dump_to_storewTzLiteral[('w', 'a')]zT_NetcdfTypes | Nonez
str | NonezT_NetcdfEngine | Nonez&Mapping[Any, Mapping[str, Any]] | NonezIterable[Hashable] | Nonebytes)
pathmoder  groupenginer   unlimited_dimsrE  invalid_netcdfr   c
           
      C  s   d S r   r   
r  r  r  r  r  r  r   r  rE  r  r   r   r   	to_netcdf  s    zDataset.to_netcdfzstr | PathLikezLiteral[True]c
           
      C  s   d S r   r   r  r   r   r   r    s    )r  zLiteral[False]r{   c          
      C  s   d S r   r   r  r   r   r   r    s    zstr | PathLike | Nonezbytes | Delayed | Nonec
                 C  s6   |dkri }ddl m}
 |
| ||||||||d|	dS )aI  Write dataset contents to a netCDF file.

        Parameters
        ----------
        path : str, path-like or file-like, optional
            Path to which to save this dataset. File-like objects are only
            supported by the scipy engine. If no path is provided, this
            function returns the resulting netCDF file as bytes; in this case,
            we need to use scipy, which does not support netCDF version 4 (the
            default format becomes NETCDF3_64BIT).
        mode : {"w", "a"}, default: "w"
            Write ('w') or append ('a') mode. If mode='w', any existing file at
            this location will be overwritten. If mode='a', existing variables
            will be overwritten.
        format : {"NETCDF4", "NETCDF4_CLASSIC", "NETCDF3_64BIT",                   "NETCDF3_CLASSIC"}, optional
            File format for the resulting netCDF file:

            * NETCDF4: Data is stored in an HDF5 file, using netCDF4 API
              features.
            * NETCDF4_CLASSIC: Data is stored in an HDF5 file, using only
              netCDF 3 compatible API features.
            * NETCDF3_64BIT: 64-bit offset version of the netCDF 3 file format,
              which fully supports 2+ GB files, but is only compatible with
              clients linked against netCDF version 3.6.0 or later.
            * NETCDF3_CLASSIC: The classic netCDF 3 file format. It does not
              handle 2+ GB files very well.

            All formats are supported by the netCDF4-python library.
            scipy.io.netcdf only supports the last two formats.

            The default format is NETCDF4 if you are saving a file to disk and
            have the netCDF4-python library available. Otherwise, xarray falls
            back to using scipy to write netCDF files and defaults to the
            NETCDF3_64BIT format (scipy does not support netCDF4).
        group : str, optional
            Path to the netCDF4 group in the given file to open (only works for
            format='NETCDF4'). The group(s) will be created if necessary.
        engine : {"netcdf4", "scipy", "h5netcdf"}, optional
            Engine to use when writing netCDF files. If not provided, the
            default engine is chosen based on available dependencies, with a
            preference for 'netcdf4' if writing to a file on disk.
        encoding : dict, optional
            Nested dictionary with variable names as keys and dictionaries of
            variable specific encodings as values, e.g.,
            ``{"my_variable": {"dtype": "int16", "scale_factor": 0.1,
            "zlib": True}, ...}``

            The `h5netcdf` engine supports both the NetCDF4-style compression
            encoding parameters ``{"zlib": True, "complevel": 9}`` and the h5py
            ones ``{"compression": "gzip", "compression_opts": 9}``.
            This allows using any compression plugin installed in the HDF5
            library, e.g. LZF.

        unlimited_dims : iterable of hashable, optional
            Dimension(s) that should be serialized as unlimited dimensions.
            By default, no dimensions are treated as unlimited dimensions.
            Note that unlimited_dims may also be set via
            ``dataset.encoding["unlimited_dims"]``.
        compute: bool, default: True
            If true compute immediately, otherwise return a
            ``dask.delayed.Delayed`` object that can be computed later.
        invalid_netcdf: bool, default: False
            Only valid along with ``engine="h5netcdf"``. If True, allow writing
            hdf5 files which are invalid netcdf as described in
            https://github.com/h5netcdf/h5netcdf.

        Returns
        -------
            * ``bytes`` if path is None
            * ``dask.delayed.Delayed`` if compute is False
            * None otherwise

        See Also
        --------
        DataArray.to_netcdf
        Nr   )r  F)	r  r  r  r  r   r  rE  Z	multifiler  )r  r  )r  r  r  r  r  r  r   r  rE  r  r  r   r   r   r    s     Yz+MutableMapping | str | PathLike[str] | Nonez&MutableMapping | str | PathLike | Nonez%Literal[('w', 'w-', 'a', 'r+', None)]r   zbool | NonezHashable | NonezMapping[str, slice] | Nonezdict[str, str] | Nonez
int | NonerZ   )r9  chunk_storer  r  r   rE  consolidated
append_dimregionsafe_chunksstorage_optionszarr_versionr   c                 C  s   d S r   r   )r  r9  r  r  synchronizerr  r   rE  r  r  r  r  r  r  r   r   r   to_zarr  s    zDataset.to_zarr)r  r  r  r  r  )r9  r  r  r  r   rE  r  r  r  r  r  r   c                C  s   d S r   r   )r  r9  r  r  r  r  r   rE  r  r  r  r  r  r   r   r   r    s    zZarrStore | Delayedc                 C  s0   ddl m} || ||||||||||	|
||dS )a  Write dataset contents to a zarr group.

        Zarr chunks are determined in the following way:

        - From the ``chunks`` attribute in each variable's ``encoding``
          (can be set via `Dataset.chunk`).
        - If the variable is a Dask array, from the dask chunks
        - If neither Dask chunks nor encoding chunks are present, chunks will
          be determined automatically by Zarr
        - If both Dask chunks and encoding chunks are present, encoding chunks
          will be used, provided that there is a many-to-one relationship between
          encoding chunks and dask chunks (i.e. Dask chunks are bigger than and
          evenly divide encoding chunks); otherwise raise a ``ValueError``.
          This restriction ensures that no synchronization / locks are required
          when writing. To disable this restriction, use ``safe_chunks=False``.

        Parameters
        ----------
        store : MutableMapping, str or path-like, optional
            Store or path to directory in local or remote file system.
        chunk_store : MutableMapping, str or path-like, optional
            Store or path to directory in local or remote file system only for Zarr
            array chunks. Requires zarr-python v2.4.0 or later.
        mode : {"w", "w-", "a", "r+", None}, optional
            Persistence mode: "w" means create (overwrite if exists);
            "w-" means create (fail if exists);
            "a" means override existing variables (create if does not exist);
            "r+" means modify existing array *values* only (raise an error if
            any metadata or shapes would change).
            The default mode is "a" if ``append_dim`` is set. Otherwise, it is
            "r+" if ``region`` is set and ``w-`` otherwise.
        synchronizer : object, optional
            Zarr array synchronizer.
        group : str, optional
            Group path. (a.k.a. `path` in zarr terminology.)
        encoding : dict, optional
            Nested dictionary with variable names as keys and dictionaries of
            variable specific encodings as values, e.g.,
            ``{"my_variable": {"dtype": "int16", "scale_factor": 0.1,}, ...}``
        compute : bool, optional
            If True write array data immediately, otherwise return a
            ``dask.delayed.Delayed`` object that can be computed to write
            array data later. Metadata is always updated eagerly.
        consolidated : bool, optional
            If True, apply zarr's `consolidate_metadata` function to the store
            after writing metadata and read existing stores with consolidated
            metadata; if False, do not. The default (`consolidated=None`) means
            write consolidated metadata and attempt to read consolidated
            metadata for existing stores (falling back to non-consolidated).

            When the experimental ``zarr_version=3``, ``consolidated`` must be
            either be ``None`` or ``False``.
        append_dim : hashable, optional
            If set, the dimension along which the data will be appended. All
            other dimensions on overridden variables must remain the same size.
        region : dict, optional
            Optional mapping from dimension names to integer slices along
            dataset dimensions to indicate the region of existing zarr array(s)
            in which to write this dataset's data. For example,
            ``{'x': slice(0, 1000), 'y': slice(10000, 11000)}`` would indicate
            that values should be written to the region ``0:1000`` along ``x``
            and ``10000:11000`` along ``y``.

            Two restrictions apply to the use of ``region``:

            - If ``region`` is set, _all_ variables in a dataset must have at
              least one dimension in common with the region. Other variables
              should be written in a separate call to ``to_zarr()``.
            - Dimensions cannot be included in both ``region`` and
              ``append_dim`` at the same time. To create empty arrays to fill
              in with ``region``, use a separate call to ``to_zarr()`` with
              ``compute=False``. See "Appending to existing Zarr stores" in
              the reference documentation for full details.
        safe_chunks : bool, optional
            If True, only allow writes to when there is a many-to-one relationship
            between Zarr chunks (specified in encoding) and Dask chunks.
            Set False to override this restriction; however, data may become corrupted
            if Zarr arrays are written in parallel. This option may be useful in combination
            with ``compute=False`` to initialize a Zarr from an existing
            Dataset with arbitrary chunk structure.
        storage_options : dict, optional
            Any additional parameters for the storage backend (ignored for local
            paths).
        zarr_version : int or None, optional
            The desired zarr spec version to target (currently 2 or 3). The
            default of None will attempt to determine the zarr version from
            ``store`` when possible, otherwise defaulting to 2.

        Returns
        -------
            * ``dask.delayed.Delayed`` if compute is False
            * ZarrStore otherwise

        References
        ----------
        https://zarr.readthedocs.io/

        Notes
        -----
        Zarr chunking behavior:
            If chunks are found in the encoding argument or attribute
            corresponding to any DataArray, those chunks are used.
            If a DataArray is a dask array, it is written with those chunks.
            If not other chunks are found, Zarr uses its own heuristics to
            choose automatic chunk sizes.

        encoding:
            The encoding attribute (if exists) of the DataArray(s) will be
            used. Override any existing encodings by providing the ``encoding`` kwarg.

        See Also
        --------
        :ref:`io.zarr`
            The I/O user guide, with more details and examples.
        r   )r  )r9  r  r  r  r  r  r   rE  r  r  r  r  r  )r  r  )r  r9  r  r  r  r  r   rE  r  r  r  r  r  r  r  r   r   r   r    s$     c                 C  s
   t | S r   )r   dataset_reprr
  r   r   r   r  D  s    zDataset.__repr__c                 C  s*   t d dkr dtt|  dS t| S )NZdisplay_styletextz<pre>z</pre>)r@   r   reprr   r  r
  r   r   r   _repr_html_G  s    zDataset._repr_html_z	IO | None)bufr   c           	      C  s(  |dkrt j}g }|d |d | j D ] \}}|d| d| d q0|d | j D ]l\}}dtt|j}|d|j	 d	| d
| d |j
 D ]&\}}|d| d| d| d qqf|d | j
 D ] \}}|d| d| d q|d |d| dS )a  
        Concise summary of a Dataset variables and attributes.

        Parameters
        ----------
        buf : file-like, default: sys.stdout
            writable buffer

        See Also
        --------
        pandas.DataFrame.assign
        ncdump : netCDF's ncdump
        Nzxarray.Dataset {zdimensions:	z = z ;z
variables:,  (z) ;z		:z
// global attributes:z	:}
)sysstdoutr  r   rB  r   r  mapr   r   r.  write)	r  r  linesr   r   r   r   r  rA  r   r   r   infoL  s$    


 "

zDataset.infoz"Mapping[Hashable, tuple[int, ...]]c                 C  s   t | j S )a  
        Mapping from dimension names to block lengths for this dataset's data, or None if
        the underlying data is not a dask array.
        Cannot be modified directly, but can be modified by calling .chunk().

        Same as Dataset.chunksizes, but maintained for backwards compatibility.

        See Also
        --------
        Dataset.chunk
        Dataset.chunksizes
        xarray.unify_chunks
        r)   r   r   r
  r   r   r   r   o  s    zDataset.chunksc                 C  s   t | j S )ao  
        Mapping from dimension names to block lengths for this dataset's data, or None if
        the underlying data is not a dask array.
        Cannot be modified directly, but can be modified by calling .chunk().

        Same as Dataset.chunks.

        See Also
        --------
        Dataset.chunk
        Dataset.chunks
        xarray.unify_chunks
        r  r
  r   r   r   
chunksizes  s    zDataset.chunksizesr   zHint | Literal['auto'] | Mapping[Any, None | int | str | tuple[int, ...]]z"None | int | str | tuple[int, ...])r  r   r   r   r   r   chunks_kwargsr   c           	        s    dkr"|dkr"t jdtd i  t tttfrBt| j	  nt
 |d   | j	  }|rrtd|  fdd| j D }| |S )a  Coerce all arrays in this dataset into dask arrays with the given
        chunks.

        Non-dask arrays in this dataset will be converted to dask arrays. Dask
        arrays will be rechunked to the given chunk sizes.

        If neither chunks is not provided for one or more dimensions, chunk
        sizes along that dimension will not be updated; non-dask arrays will be
        converted into dask arrays with a single block.

        Parameters
        ----------
        chunks : int, tuple of int, "auto" or mapping of hashable to int, optional
            Chunk sizes along each dimension, e.g., ``5``, ``"auto"``, or
            ``{"x": 5, "y": 5}``.
        name_prefix : str, default: "xarray-"
            Prefix for the name of any new dask arrays.
        token : str, optional
            Token uniquely identifying this dataset.
        lock : bool, default: False
            Passed on to :py:func:`dask.array.from_array`, if the array is not
            already as dask array.
        inline_array: bool, default: False
            Passed on to :py:func:`dask.array.from_array`, if the array is not
            already as dask array.
        **chunks_kwargs : {dim: chunks, ...}, optional
            The keyword arguments form of ``chunks``.
            One of chunks or chunks_kwargs must be provided

        Returns
        -------
        chunked : xarray.Dataset

        See Also
        --------
        Dataset.chunks
        Dataset.chunksizes
        xarray.unify_chunks
        dask.array.from_array
        Nz]None value for 'chunks' is deprecated. It will raise an error in the future. Use instead '{}')categoryr   z4some chunks keys are not dimensions on this object: c              
     s$   i | ]\}}|t || qS r   )r   rD  r   r   r   r   r   r   r     s    z!Dataset.chunk.<locals>.<dictcomp>)r   r   FutureWarningr   r   r   r   r   r   r   rM   rp  r   r   rB  r{  )	r  r   r   r   r   r   r  Zbad_dimsr   r   r  r   r     s$    3zDataset.chunkraisero   z>Iterator[tuple[Hashable, int | slice | np.ndarray | Variable]])indexersmissing_dimsr   c                 c  sH  ddl m} ddlm} t|| j|}| D ]\}}t|tt	t
frT||fV  q.t||rl||jfV  q.t|tr|t|fV  q.t|trtdq.t|trt|dkr|tjdddfV  q.t|}|jjdkr| j|  }t|tjr|d	}nt||rt||j}|jd
kr8td |||fV  q.dS )zHere we make sure
        + indexer has a valid keys
        + indexer is in a valid data type
        + string indexers are cast to the appropriate date type if the
          associated index is a DatetimeIndex or CFTimeIndex
        r   )r   r^   z"cannot use a Dataset as an indexerr   int64r   ZUSzdatetime64[ns]r   zAUnlabeled multi-dimensional array cannot be used for indexing: {}N)!xarray.coding.cftimeindexr   r   r_   rL   r   rB  r   r   slicerS   r   r   rT   r   r   r   r   r   r   asarrayr   r   r*  Zto_pandas_indexr   ZDatetimeIndexr  r   Z	date_typer   
IndexErrorr  )r  r  r  r   r_   r  rA  r  r   r   r   _validate_indexers  s8    	




zDataset._validate_indexersz#Iterator[tuple[Hashable, Variable]])r  r   c                 c  s   |  |D ]\}}t|trB|jdkr6|| fV  q||fV  q
t|trj|td|| j| jdfV  q
t|tj	r|jdkr|td|| j| jdfV  q|jdkr|t
|f|| j| jdfV  qt q
tt|q
dS )z:Variant of _validate_indexers to be used for interpolationr   r   r6  r   N)r
  r   rS   r   to_index_variabler   r-  r.  r   ndarrayrR   AssertionErrorr   rJ  )r  r  r  rA  r   r   r   _validate_interp_indexers	  s    




 z!Dataset._validate_interp_indexersc                   s   ddl m} g }| D ]`\}}t||r|jjdkrh|jdkrRtd|j|||j	
 d  j}n|j}|| qt|\}}t |  fdd| D }	 fdd| D }
|	|
fS )	zExtract coordinates and indexes from indexers.

        Only coordinate with a name different from any of self.variables will
        be attached.
        r   r^   br   zh{:d}d-boolean array is used for indexing along dimension {!r}, but only 1d boolean arrays are supported.c                   s    i | ]\}}| j kr||qS r   r  rD  r
  r   r   r   >	  s     
  z<Dataset._get_indexers_coords_and_indexes.<locals>.<dictcomp>c                   s    i | ]\}}| j kr||qS r   r  rD  r
  r   r   r   ?	  s    
  )r   r_   rB  r   r   r   r   r   r  r   Znonzeror-  r  r=   r-   )r  r  r_   Zcoords_listr  rA  Zv_coordsr-  r3  Zattached_coordsZattached_indexesr   r
  r    _get_indexers_coords_and_indexes	  s,    

 

z(Dataset._get_indexers_coords_and_indexes)r  r  r  r  indexers_kwargsr   c              	     s  t ||d}tdd | D r2| j|||dS t|| j|}i }i }| j }t| j	|\}}	| j
 D ]|\}
 |
|	kr|	|
  nF fdd| D }|r̈ | |r̈ jdkr|
|kr||
 ql ||
< |t j j ql| j|||| j|| j| jdS )	a  Returns a new dataset with each array indexed along the specified
        dimension(s).

        This method selects values from each array using its `__getitem__`
        method, except this method does not require knowing the order of
        each array's dimensions.

        Parameters
        ----------
        indexers : dict, optional
            A dict with keys matching dimensions and values given
            by integers, slice objects or arrays.
            indexer can be a integer, slice, array-like or DataArray.
            If DataArrays are passed as indexers, xarray-style indexing will be
            carried out. See :ref:`indexing` for the details.
            One of indexers or indexers_kwargs must be provided.
        drop : bool, default: False
            If ``drop=True``, drop coordinates variables indexed by integers
            instead of making them scalar.
        missing_dims : {"raise", "warn", "ignore"}, default: "raise"
            What to do if dimensions that should be selected from are not present in the
            Dataset:
            - "raise": raise an exception
            - "warn": raise a warning, and ignore the missing dimensions
            - "ignore": ignore the missing dimensions

        **indexers_kwargs : {dim: indexer, ...}, optional
            The keyword arguments form of ``indexers``.
            One of indexers or indexers_kwargs must be provided.

        Returns
        -------
        obj : Dataset
            A new Dataset with the same contents as this dataset, except each
            array and dimension is indexed by the appropriate indexers.
            If indexer DataArrays have coordinates that do not conflict with
            this object, then these coordinates will be attached.
            In general, each array's data will be a view of the array's data
            in this dataset, unless vectorized indexing was triggered by using
            an array indexer, in which case the data will be a copy.

        See Also
        --------
        Dataset.sel
        DataArray.isel
        r  c                 s  s   | ]}t |V  qd S r   )r9   )r   idxr   r   r   r   z	  s     zDataset.isel.<locals>.<genexpr>)r  r  c                   s    i | ]\}}| j kr||qS r   r>  rD  r   r   r   r   	  s     
  z Dataset.isel.<locals>.<dictcomp>r   )r   r2  r   r.  r3  r   r8  )rM   r   r   _isel_fancyrL   r   r  rs  r6   r  r  rB  r  r   r  r  r   r   rg  r%  r(  r)  )r  r  r  r  r  r   r   r2  r3  r  r   var_indexersr   r  r   r  D	  s8    5



zDataset.iselr  )r  r  r  r  r   c                  s  t | ||}i }t| j|\}}| j D ]\} ||krH|| }	n^ fdd| D }
|
r j|
d}	|| jkr|r|	jdkrq.n j	dd}	||kr|	
 }	|	||< q.| j| @ }| |||}||\}}|| || | j| @ | B }| j|||dS )Nc                   s    i | ]\}}| j kr||qS r   r>  rD  r  r   r   r   	  s    
  z'Dataset._isel_fancy.<locals>.<dictcomp>r  r   Frq  r  )r   r
  r6   r  r   rB  r  r-  r   rs  to_base_variabler  rp  r~  r  r  )r  r  r  r  Zvalid_indexersr   r3  r  r   new_varr  r2  selected
coord_varsr  r   r  r   r  	  s0    




zDataset._isel_fancyz*int | float | Iterable[int | float] | None)r  r  method	tolerancer  r  r   c                 K  s   t ||d}t| |||d}|rdi }|j D ].\}}	|	jrF|	||< q.|| jkr.|j| q.||_| j|j	|d}
|
j
| dd  S )ad  Returns a new dataset with each array indexed by tick labels
        along the specified dimension(s).

        In contrast to `Dataset.isel`, indexers for this method should use
        labels instead of integers.

        Under the hood, this method is powered by using pandas's powerful Index
        objects. This makes label based indexing essentially just as fast as
        using integer indexing.

        It also means this method uses pandas's (well documented) logic for
        indexing. This means you can use string shortcuts for datetime indexes
        (e.g., '2000-01' to select all values in January 2000). It also means
        that slices are treated as inclusive of both the start and stop values,
        unlike normal Python indexing.

        Parameters
        ----------
        indexers : dict, optional
            A dict with keys matching dimensions and values given
            by scalars, slices or arrays of tick labels. For dimensions with
            multi-index, the indexer may also be a dict-like object with keys
            matching index level names.
            If DataArrays are passed as indexers, xarray-style indexing will be
            carried out. See :ref:`indexing` for the details.
            One of indexers or indexers_kwargs must be provided.
        method : {None, "nearest", "pad", "ffill", "backfill", "bfill"}, optional
            Method to use for inexact matches:

            * None (default): only exact matches
            * pad / ffill: propagate last valid index value forward
            * backfill / bfill: propagate next valid index value backward
            * nearest: use nearest valid index value
        tolerance : optional
            Maximum distance between original and new labels for inexact
            matches. The values of the index at the matching locations must
            satisfy the equation ``abs(index[indexer] - target) <= tolerance``.
        drop : bool, optional
            If ``drop=True``, drop coordinates variables in `indexers` instead
            of making them scalar.
        **indexers_kwargs : {dim: indexer, ...}, optional
            The keyword arguments form of ``indexers``.
            One of indexers or indexers_kwargs must be provided.

        Returns
        -------
        obj : Dataset
            A new Dataset with the same contents as this dataset, except each
            variable and dimension is indexed by the appropriate indexers.
            If indexer DataArrays have coordinates that do not conflict with
            this object, then these coordinates will be attached.
            In general, each array's data will be a view of the array's data
            in this dataset, unless vectorized indexing was triggered by using
            an array indexer, in which case the data will be a copy.

        See Also
        --------
        Dataset.isel
        DataArray.sel
        r!  )r  r  r  )r  r  r   N)rM   r:   r   rB  r   r  Zdrop_coordsr  r  r"  r  as_tuple)r  r  r  r  r  r  Zquery_resultsZno_scalar_variablesr  rA  resultr   r   r   r!  	  s"    D   

zDataset.selzMapping[Any, int] | int | None)r  r  r  r   c                   s   |s* dkrd t  ts*t s*tdt  trH fdd| jD  t |d   D ]H\}}t |tstd|dt|q\|d	k r\td
|d| q\dd   D }| 	|S )a  Returns a new dataset with the first `n` values of each array
        for the specified dimension(s).

        Parameters
        ----------
        indexers : dict or int, default: 5
            A dict with keys matching dimensions and integer values `n`
            or a single integer `n` applied over all dimensions.
            One of indexers or indexers_kwargs must be provided.
        **indexers_kwargs : {dim: n, ...}, optional
            The keyword arguments form of ``indexers``.
            One of indexers or indexers_kwargs must be provided.

        See Also
        --------
        Dataset.tail
        Dataset.thin
        DataArray.head
        N   5indexers must be either dict-like or a single integerc                   s   i | ]
}| qS r   r   r   r  r   r   r   <
  s      z Dataset.head.<locals>.<dictcomp>head,expected integer type indexer for dimension , found r   3expected positive integer as indexer for dimension c                 S  s   i | ]\}}|t |qS r   r  r   r  r  r   r   r   r   I
  s      
r   r   rO   r   r   rM   rB  rJ  r   r  r  r  r  r  rA  Zindexers_slicesr   r  r   r"  
  s&    

zDataset.headc                   s   |s* dkrd t  ts*t s*tdt  trH fdd| jD  t |d   D ]H\}}t |tstd|dt|q\|d	k r\td
|d| q\dd   D }| 	|S )a  Returns a new dataset with the last `n` values of each array
        for the specified dimension(s).

        Parameters
        ----------
        indexers : dict or int, default: 5
            A dict with keys matching dimensions and integer values `n`
            or a single integer `n` applied over all dimensions.
            One of indexers or indexers_kwargs must be provided.
        **indexers_kwargs : {dim: n, ...}, optional
            The keyword arguments form of ``indexers``.
            One of indexers or indexers_kwargs must be provided.

        See Also
        --------
        Dataset.head
        Dataset.thin
        DataArray.tail
        Nr   r!  c                   s   i | ]
}| qS r   r   r   r  r   r   r   j
  s      z Dataset.tail.<locals>.<dictcomp>tailr#  r$  r   r%  c                 S  s.   i | ]&\}}||d kr"t | dnt |qS r   r&  r'  r   r   r   r   w
  s    r(  r)  r   r  r   r*  L
  s*    

zDataset.tailc                   s   |st  tst stdt  tr< fdd| jD  t |d   D ]Z\}}t |ts|td|dt|qP|dk rtd|d| qP|dkrPtd	qPd
d   D }| 	|S )aJ  Returns a new dataset with each array indexed along every `n`-th
        value for the specified dimension(s)

        Parameters
        ----------
        indexers : dict or int
            A dict with keys matching dimensions and integer values `n`
            or a single integer `n` applied over all dimensions.
            One of indexers or indexers_kwargs must be provided.
        **indexers_kwargs : {dim: n, ...}, optional
            The keyword arguments form of ``indexers``.
            One of indexers or indexers_kwargs must be provided.

        Examples
        --------
        >>> x_arr = np.arange(0, 26)
        >>> x_arr
        array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
               17, 18, 19, 20, 21, 22, 23, 24, 25])
        >>> x = xr.DataArray(
        ...     np.reshape(x_arr, (2, 13)),
        ...     dims=("x", "y"),
        ...     coords={"x": [0, 1], "y": np.arange(0, 13)},
        ... )
        >>> x_ds = xr.Dataset({"foo": x})
        >>> x_ds
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 13)
        Coordinates:
          * x        (x) int64 0 1
          * y        (y) int64 0 1 2 3 4 5 6 7 8 9 10 11 12
        Data variables:
            foo      (x, y) int64 0 1 2 3 4 5 6 7 8 9 ... 16 17 18 19 20 21 22 23 24 25

        >>> x_ds.thin(3)
        <xarray.Dataset>
        Dimensions:  (x: 1, y: 5)
        Coordinates:
          * x        (x) int64 0
          * y        (y) int64 0 3 6 9 12
        Data variables:
            foo      (x, y) int64 0 3 6 9 12
        >>> x.thin({"x": 2, "y": 5})
        <xarray.DataArray (x: 1, y: 3)>
        array([[ 0,  5, 10]])
        Coordinates:
          * x        (x) int64 0
          * y        (y) int64 0 5 10

        See Also
        --------
        Dataset.head
        Dataset.tail
        DataArray.thin
        r!  c                   s   i | ]
}| qS r   r   r   r  r   r   r   
  s      z Dataset.thin.<locals>.<dictcomp>thinr#  r$  r   r%  zstep cannot be zeroc                 S  s   i | ]\}}|t d d |qS r   r&  r'  r   r   r   r   
  s      r(  r)  r   r  r   r+  }
  s.    =


zDataset.thinzDataset | DataArray)r  r  excluder   c                 C  sP   |dkrt  }nt |}t|| dd|d}t||\}}ttd|d |||S )an  Broadcast this DataArray against another Dataset or DataArray.
        This is equivalent to xr.broadcast(other, self)[1]

        Parameters
        ----------
        other : Dataset or DataArray
            Object against which to broadcast this array.
        exclude : iterable of hashable, optional
            Dimensions that must not be broadcasted

        NouterF)r  rs  r,  rE   r   )r   r%   r$   r#   r   )r  r  r,  r   Zdims_mapZcommon_coordsr   r   r   broadcast_like
  s       zDataset.broadcast_likezalignment.Alignerzdict[Hashable, Any]zfrozenset[Hashable])alignerdim_pos_indexersr   r3  
fill_valueexclude_dimsexclude_varsr   c                   s    }|  }	| D ],\}
}| j|
}|dk	r|j|_|j|_q| j D ]0\}
}| j|
 }t|j|krP||	|
< |||
< qP|st|	t| j r| 	|	|}n| j |j d}nZ fdd| j
 D }tj|||j ||jd}|| | jt|	B }| j|||	d}|S )zCCallback called from ``Aligner`` to create a new reindexed Dataset.Nrq  c                   s&   i | ]\}}|kr| kr||qS r   r   rD  r3  r   r   r   r     s
     z-Dataset._reindex_callback.<locals>.<dictcomp>rs  r1  sparser  )rs  rB  r  r   r.  r   r*  r   r   r  r   r   Zreindex_variablesr6  r  r  r~  )r  r/  r0  r   r3  r1  r2  r3  r  r  r   r  r   r  	reindexedZ
to_reindexZreindexed_varsr  r   r4  r   _reindex_callback
  sD    



  zDataset._reindex_callbackrv   )r  r  r  r  rs  r1  r   c                 C  s   t j| |||||dS )un	  Conform this object onto the indexes of another object, filling in
        missing values with ``fill_value``. The default fill value is NaN.

        Parameters
        ----------
        other : Dataset or DataArray
            Object with an 'indexes' attribute giving a mapping from dimension
            names to pandas.Index objects, which provides coordinates upon
            which to index the variables in this dataset. The indexes on this
            other object need not be the same as the indexes on this
            dataset. Any mis-matched index values will be filled in with
            NaN, and any mis-matched dimension names will simply be ignored.
        method : {None, "nearest", "pad", "ffill", "backfill", "bfill", None}, optional
            Method to use for filling index values from other not found in this
            dataset:

            - None (default): don't fill gaps
            - "pad" / "ffill": propagate last valid index value forward
            - "backfill" / "bfill": propagate next valid index value backward
            - "nearest": use nearest valid index value

        tolerance : optional
            Maximum distance between original and new labels for inexact
            matches. The values of the index at the matching locations must
            satisfy the equation ``abs(index[indexer] - target) <= tolerance``.
            Tolerance may be a scalar value, which applies the same tolerance
            to all values, or list-like, which applies variable tolerance per
            element. List-like must be the same size as the index and its dtype
            must exactly match the index’s type.
        copy : bool, default: True
            If ``copy=True``, data in the return value is always copied. If
            ``copy=False`` and reindexing is unnecessary, or can be performed
            with only slice operations, then the output may share memory with
            the input. In either case, a new xarray object is always returned.
        fill_value : scalar or dict-like, optional
            Value to use for newly missing values. If a dict-like maps
            variable names to fill values.

        Returns
        -------
        reindexed : Dataset
            Another dataset, with this dataset's data but coordinates from the
            other object.

        See Also
        --------
        Dataset.reindex
        align
        )r  r  r  rs  r1  )r   reindex_like)r  r  r  r  rs  r1  r   r   r   r9  )  s    9zDataset.reindex_like)r  r  r  r  rs  r1  r  r   c                 K  s$   t ||d}tj| |||||dS )ud"  Conform this object onto a new set of indexes, filling in
        missing values with ``fill_value``. The default fill value is NaN.

        Parameters
        ----------
        indexers : dict, optional
            Dictionary with keys given by dimension names and values given by
            arrays of coordinates tick labels. Any mis-matched coordinate
            values will be filled in with NaN, and any mis-matched dimension
            names will simply be ignored.
            One of indexers or indexers_kwargs must be provided.
        method : {None, "nearest", "pad", "ffill", "backfill", "bfill", None}, optional
            Method to use for filling index values in ``indexers`` not found in
            this dataset:

            - None (default): don't fill gaps
            - "pad" / "ffill": propagate last valid index value forward
            - "backfill" / "bfill": propagate next valid index value backward
            - "nearest": use nearest valid index value

        tolerance : optional
            Maximum distance between original and new labels for inexact
            matches. The values of the index at the matching locations must
            satisfy the equation ``abs(index[indexer] - target) <= tolerance``.
            Tolerance may be a scalar value, which applies the same tolerance
            to all values, or list-like, which applies variable tolerance per
            element. List-like must be the same size as the index and its dtype
            must exactly match the index’s type.
        copy : bool, default: True
            If ``copy=True``, data in the return value is always copied. If
            ``copy=False`` and reindexing is unnecessary, or can be performed
            with only slice operations, then the output may share memory with
            the input. In either case, a new xarray object is always returned.
        fill_value : scalar or dict-like, optional
            Value to use for newly missing values. If a dict-like,
            maps variable names (including coordinates) to fill values.
        sparse : bool, default: False
            use sparse-array.
        **indexers_kwargs : {dim: indexer, ...}, optional
            Keyword arguments in the same form as ``indexers``.
            One of indexers or indexers_kwargs must be provided.

        Returns
        -------
        reindexed : Dataset
            Another dataset, with this dataset's data but replaced coordinates.

        See Also
        --------
        Dataset.reindex_like
        align
        pandas.Index.get_indexer

        Examples
        --------
        Create a dataset with some fictional data.

        >>> x = xr.Dataset(
        ...     {
        ...         "temperature": ("station", 20 * np.random.rand(4)),
        ...         "pressure": ("station", 500 * np.random.rand(4)),
        ...     },
        ...     coords={"station": ["boston", "nyc", "seattle", "denver"]},
        ... )
        >>> x
        <xarray.Dataset>
        Dimensions:      (station: 4)
        Coordinates:
          * station      (station) <U7 'boston' 'nyc' 'seattle' 'denver'
        Data variables:
            temperature  (station) float64 10.98 14.3 12.06 10.9
            pressure     (station) float64 211.8 322.9 218.8 445.9
        >>> x.indexes
        Indexes:
            station  Index(['boston', 'nyc', 'seattle', 'denver'], dtype='object', name='station')

        Create a new index and reindex the dataset. By default values in the new index that
        do not have corresponding records in the dataset are assigned `NaN`.

        >>> new_index = ["boston", "austin", "seattle", "lincoln"]
        >>> x.reindex({"station": new_index})
        <xarray.Dataset>
        Dimensions:      (station: 4)
        Coordinates:
          * station      (station) <U7 'boston' 'austin' 'seattle' 'lincoln'
        Data variables:
            temperature  (station) float64 10.98 nan 12.06 nan
            pressure     (station) float64 211.8 nan 218.8 nan

        We can fill in the missing values by passing a value to the keyword `fill_value`.

        >>> x.reindex({"station": new_index}, fill_value=0)
        <xarray.Dataset>
        Dimensions:      (station: 4)
        Coordinates:
          * station      (station) <U7 'boston' 'austin' 'seattle' 'lincoln'
        Data variables:
            temperature  (station) float64 10.98 0.0 12.06 0.0
            pressure     (station) float64 211.8 0.0 218.8 0.0

        We can also use different fill values for each variable.

        >>> x.reindex(
        ...     {"station": new_index}, fill_value={"temperature": 0, "pressure": 100}
        ... )
        <xarray.Dataset>
        Dimensions:      (station: 4)
        Coordinates:
          * station      (station) <U7 'boston' 'austin' 'seattle' 'lincoln'
        Data variables:
            temperature  (station) float64 10.98 0.0 12.06 0.0
            pressure     (station) float64 211.8 100.0 218.8 100.0

        Because the index is not monotonically increasing or decreasing, we cannot use arguments
        to the keyword method to fill the `NaN` values.

        >>> x.reindex({"station": new_index}, method="nearest")
        Traceback (most recent call last):
        ...
            raise ValueError('index must be monotonic increasing or decreasing')
        ValueError: index must be monotonic increasing or decreasing

        To further illustrate the filling functionality in reindex, we will create a
        dataset with a monotonically increasing index (for example, a sequence of dates).

        >>> x2 = xr.Dataset(
        ...     {
        ...         "temperature": (
        ...             "time",
        ...             [15.57, 12.77, np.nan, 0.3081, 16.59, 15.12],
        ...         ),
        ...         "pressure": ("time", 500 * np.random.rand(6)),
        ...     },
        ...     coords={"time": pd.date_range("01/01/2019", periods=6, freq="D")},
        ... )
        >>> x2
        <xarray.Dataset>
        Dimensions:      (time: 6)
        Coordinates:
          * time         (time) datetime64[ns] 2019-01-01 2019-01-02 ... 2019-01-06
        Data variables:
            temperature  (time) float64 15.57 12.77 nan 0.3081 16.59 15.12
            pressure     (time) float64 481.8 191.7 395.9 264.4 284.0 462.8

        Suppose we decide to expand the dataset to cover a wider date range.

        >>> time_index2 = pd.date_range("12/29/2018", periods=10, freq="D")
        >>> x2.reindex({"time": time_index2})
        <xarray.Dataset>
        Dimensions:      (time: 10)
        Coordinates:
          * time         (time) datetime64[ns] 2018-12-29 2018-12-30 ... 2019-01-07
        Data variables:
            temperature  (time) float64 nan nan nan 15.57 ... 0.3081 16.59 15.12 nan
            pressure     (time) float64 nan nan nan 481.8 ... 264.4 284.0 462.8 nan

        The index entries that did not have a value in the original data frame (for example, `2018-12-29`)
        are by default filled with NaN. If desired, we can fill in the missing values using one of several options.

        For example, to back-propagate the last valid value to fill the `NaN` values,
        pass `bfill` as an argument to the `method` keyword.

        >>> x3 = x2.reindex({"time": time_index2}, method="bfill")
        >>> x3
        <xarray.Dataset>
        Dimensions:      (time: 10)
        Coordinates:
          * time         (time) datetime64[ns] 2018-12-29 2018-12-30 ... 2019-01-07
        Data variables:
            temperature  (time) float64 15.57 15.57 15.57 15.57 ... 16.59 15.12 nan
            pressure     (time) float64 481.8 481.8 481.8 481.8 ... 284.0 462.8 nan

        Please note that the `NaN` value present in the original dataset (at index value `2019-01-03`)
        will not be filled by any of the value propagation schemes.

        >>> x2.where(x2.temperature.isnull(), drop=True)
        <xarray.Dataset>
        Dimensions:      (time: 1)
        Coordinates:
          * time         (time) datetime64[ns] 2019-01-03
        Data variables:
            temperature  (time) float64 nan
            pressure     (time) float64 395.9
        >>> x3.where(x3.temperature.isnull(), drop=True)
        <xarray.Dataset>
        Dimensions:      (time: 2)
        Coordinates:
          * time         (time) datetime64[ns] 2019-01-03 2019-01-07
        Data variables:
            temperature  (time) float64 nan nan
            pressure     (time) float64 395.9 nan

        This is because filling while reindexing does not look at dataset values, but only compares
        the original and desired indexes. If you do want to fill in the `NaN` values present in the
        original dataset, use the :py:meth:`~Dataset.fillna()` method.

        reindex)r  r  r  rs  r1  r!   rM   r   r:  )r  r  r  r  rs  r1  r  r   r   r   r:  k  s     OzDataset.reindex)	r  r  r  r  rs  r1  r6  r  r   c              	   K  s&   t ||d}tj| ||||||dS )z=
        Same as reindex but supports sparse option.
        r:  )r  r  r  rs  r1  r6  r;  )r  r  r  r  rs  r1  r6  r  r   r   r   _reindexC  s    zDataset._reindexlinearnearestrp   zMapping[str, Any] | None)r  r-  r  assume_sortedrF  method_non_numericcoords_kwargsr   c                   s
  ddl m} |dkri }t||d}t||rvtjjdd  D  	|
 }fdd|D  |r~nd	d |D d
d dd   fdd D }	|dkr|	 D ](\}
}||
|i\}||
 |	|
< q̈ rdd |	 D }i }d}j D ]\}|kr:q$tjrL|}n|	}jj}|dkrfdd| D }|j||f|||< nB|dkr|
 j@ rd}n"tfddjD r$||< q$|rdd |	 D }tj|||
 d}t|j}||j nfddj D }j|
 @ }j| ||d} D ]b\}
}t|tsvt |j|
fkrt!||
|jd}|"|
|i}|||
< || n|||
< q^|#|\}}|| || j|
 @ |
 B }j|||dS )ao  Interpolate a Dataset onto new coordinates

        Performs univariate or multivariate interpolation of a Dataset onto
        new coordinates using scipy's interpolation routines. If interpolating
        along an existing dimension, :py:class:`scipy.interpolate.interp1d` is
        called.  When interpolating along multiple existing dimensions, an
        attempt is made to decompose the interpolation into multiple
        1-dimensional interpolations. If this is possible,
        :py:class:`scipy.interpolate.interp1d` is called. Otherwise,
        :py:func:`scipy.interpolate.interpn` is called.

        Parameters
        ----------
        coords : dict, optional
            Mapping from dimension names to the new coordinates.
            New coordinate can be a scalar, array-like or DataArray.
            If DataArrays are passed as new coordinates, their dimensions are
            used for the broadcasting. Missing values are skipped.
        method : {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial",             "barycentric", "krog", "pchip", "spline", "akima"}, default: "linear"
            String indicating which method to use for interpolation:

            - 'linear': linear interpolation. Additional keyword
              arguments are passed to :py:func:`numpy.interp`
            - 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'polynomial':
              are passed to :py:func:`scipy.interpolate.interp1d`. If
              ``method='polynomial'``, the ``order`` keyword argument must also be
              provided.
            - 'barycentric', 'krog', 'pchip', 'spline', 'akima': use their
              respective :py:class:`scipy.interpolate` classes.

        assume_sorted : bool, default: False
            If False, values of coordinates that are interpolated over can be
            in any order and they are sorted first. If True, interpolated
            coordinates are assumed to be an array of monotonically increasing
            values.
        kwargs : dict, optional
            Additional keyword arguments passed to scipy's interpolator. Valid
            options and their behavior depend whether ``interp1d`` or
            ``interpn`` is used.
        method_non_numeric : {"nearest", "pad", "ffill", "backfill", "bfill"}, optional
            Method for non-numeric types. Passed on to :py:meth:`Dataset.reindex`.
            ``"nearest"`` is used by default.
        **coords_kwargs : {dim: coordinate, ...}, optional
            The keyword arguments form of ``coords``.
            One of coords or coords_kwargs must be provided.

        Returns
        -------
        interpolated : Dataset
            New dataset on the new coordinates.

        Notes
        -----
        scipy is required.

        See Also
        --------
        scipy.interpolate.interp1d
        scipy.interpolate.interpn

        Examples
        --------
        >>> ds = xr.Dataset(
        ...     data_vars={
        ...         "a": ("x", [5, 7, 4]),
        ...         "b": (
        ...             ("x", "y"),
        ...             [[1, 4, 2, 9], [2, 7, 6, np.nan], [6, np.nan, 5, 8]],
        ...         ),
        ...     },
        ...     coords={"x": [0, 1, 2], "y": [10, 12, 14, 16]},
        ... )
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 3, y: 4)
        Coordinates:
          * x        (x) int64 0 1 2
          * y        (y) int64 10 12 14 16
        Data variables:
            a        (x) int64 5 7 4
            b        (x, y) float64 1.0 4.0 2.0 9.0 2.0 7.0 6.0 nan 6.0 nan 5.0 8.0

        1D interpolation with the default method (linear):

        >>> ds.interp(x=[0, 0.75, 1.25, 1.75])
        <xarray.Dataset>
        Dimensions:  (x: 4, y: 4)
        Coordinates:
          * y        (y) int64 10 12 14 16
          * x        (x) float64 0.0 0.75 1.25 1.75
        Data variables:
            a        (x) float64 5.0 6.5 6.25 4.75
            b        (x, y) float64 1.0 4.0 2.0 nan 1.75 6.25 ... nan 5.0 nan 5.25 nan

        1D interpolation with a different method:

        >>> ds.interp(x=[0, 0.75, 1.25, 1.75], method="nearest")
        <xarray.Dataset>
        Dimensions:  (x: 4, y: 4)
        Coordinates:
          * y        (y) int64 10 12 14 16
          * x        (x) float64 0.0 0.75 1.25 1.75
        Data variables:
            a        (x) float64 5.0 7.0 7.0 4.0
            b        (x, y) float64 1.0 4.0 2.0 9.0 2.0 7.0 ... 6.0 nan 6.0 nan 5.0 8.0

        1D extrapolation:

        >>> ds.interp(
        ...     x=[1, 1.5, 2.5, 3.5],
        ...     method="linear",
        ...     kwargs={"fill_value": "extrapolate"},
        ... )
        <xarray.Dataset>
        Dimensions:  (x: 4, y: 4)
        Coordinates:
          * y        (y) int64 10 12 14 16
          * x        (x) float64 1.0 1.5 2.5 3.5
        Data variables:
            a        (x) float64 7.0 5.5 2.5 -0.5
            b        (x, y) float64 2.0 7.0 6.0 nan 4.0 nan ... 4.5 nan 12.0 nan 3.5 nan

        2D interpolation:

        >>> ds.interp(x=[0, 0.75, 1.25, 1.75], y=[11, 13, 15], method="linear")
        <xarray.Dataset>
        Dimensions:  (x: 4, y: 3)
        Coordinates:
          * x        (x) float64 0.0 0.75 1.25 1.75
          * y        (y) int64 11 13 15
        Data variables:
            a        (x) float64 5.0 6.5 6.25 4.75
            b        (x, y) float64 2.5 3.0 nan 4.0 5.625 nan nan nan nan nan nan nan
        r   )missingNinterpc                 S  s   g | ]}t |jqS r   r   r   )r   Znxr   r   r   r     s     z"Dataset.interp.<locals>.<listcomp>c                   s   i | ]}| j | qS r   r  r   dr
  r   r   r     s      z"Dataset.interp.<locals>.<dictcomp>c                 S  s   g | ]}|qS r   r   r  r   r   r   r     s     c                 S  s<   z| j | W S  tk
r6   t|t| j| f Y S X d S r   )r  r   rT   r   r   )r   r  r   r   r   maybe_variable   s    z&Dataset.interp.<locals>.maybe_variablec                 S  s&   t | rt |std|| |fS )NzWhen interpolating over a datetime-like coordinate, the coordinates to interpolate to must be either datetime strings or datetimes. Instead got
{})r(   r   r  )r   Znew_xr   r   r   _validate_interp_indexer  s    z0Dataset.interp.<locals>._validate_interp_indexerc                   s"   i | ]\}}| ||qS r   r   rD  )rH  rG  r   r   r   r     s    )r=  r>  c                 S  s.   i | ]&\}\}}||   |   fqS r   )r  r   )r   r  r  destr   r   r   r   &  s   
 FZuifcc                   s    i | ]\}}| j kr||qS r   r>  rD  r  r   r   r   9  s     
  ZObUTc                 3  s   | ]}| kV  qd S r   r   rE  r  r   r   r   C  s     z!Dataset.interp.<locals>.<genexpr>c                 S  s&   i | ]\}\}}|j |fkr||qS r   r>  )r   r  r4  rA  r   r   r   r   J  s   
   )r  r  r3  c                   s   i | ]\}}| kr||qS r   r   rD  r  r   r   r   W  s       r  )Zcoord_dtype)$xarray.corerB  rM   r   r  r   r   intersectionr   r   rp  r  sortbyrB  Z	_localizerL  r  rC   r   r   r   rC  allr   r:  r*  r   r  r~  rs  r   rS   r  r1   create_variablesr  )r  r-  r  r?  rF  r@  rA  rB  ZsdimsZvalidated_indexersr  rA  ZnewidxZdask_indexersr   r:  r   Zuse_indexersZ
dtype_kindr  Zreindex_indexersr7  r3  r2  r  r  r  r  r  r   )rH  r  rG  r   r  r   r   rC  [  s     




  

zDataset.interp)r  r  r?  rF  r@  r   c                 C  s   |dkri }i }|j }| jD ]*}|j|dd}	t|	dkr|	| ||< qi }
i }| D ]&\}}|jjdkrv||
|< qX|||< qX| }|r| |}|j|
||||dS )a
  Interpolate this object onto the coordinates of another object,
        filling the out of range values with NaN.

        If interpolating along a single existing dimension,
        :py:class:`scipy.interpolate.interp1d` is called. When interpolating
        along multiple existing dimensions, an attempt is made to decompose the
        interpolation into multiple 1-dimensional interpolations. If this is
        possible, :py:class:`scipy.interpolate.interp1d` is called. Otherwise,
        :py:func:`scipy.interpolate.interpn` is called.

        Parameters
        ----------
        other : Dataset or DataArray
            Object with an 'indexes' attribute giving a mapping from dimension
            names to an 1d array-like, which provides coordinates upon
            which to index the variables in this dataset. Missing values are skipped.
        method : {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial",             "barycentric", "krog", "pchip", "spline", "akima"}, default: "linear"
            String indicating which method to use for interpolation:

            - 'linear': linear interpolation. Additional keyword
              arguments are passed to :py:func:`numpy.interp`
            - 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'polynomial':
              are passed to :py:func:`scipy.interpolate.interp1d`. If
              ``method='polynomial'``, the ``order`` keyword argument must also be
              provided.
            - 'barycentric', 'krog', 'pchip', 'spline', 'akima': use their
              respective :py:class:`scipy.interpolate` classes.

        assume_sorted : bool, default: False
            If False, values of coordinates that are interpolated over can be
            in any order and they are sorted first. If True, interpolated
            coordinates are assumed to be an array of monotonically increasing
            values.
        kwargs : dict, optional
            Additional keyword passed to scipy's interpolator.
        method_non_numeric : {"nearest", "pad", "ffill", "backfill", "bfill"}, optional
            Method for non-numeric types. Passed on to :py:meth:`Dataset.reindex`.
            ``"nearest"`` is used by default.

        Returns
        -------
        interpolated : Dataset
            Another dataset by interpolating this dataset's data along the
            coordinates of the other object.

        Notes
        -----
        scipy is required.
        If the dataset has object-type coordinates, reindex is used for these
        coordinates instead of the interpolation.

        See Also
        --------
        Dataset.interp
        Dataset.reindex_like
        Nignoreerrorsr   ZuifcMm)r-  r  r?  rF  r@  )	r  r   get_all_coordsr   rB  r   r   r:  rC  )r  r  r  r?  rF  r@  r-  Zother_indexesr   Zother_dim_coordsZnumeric_coordsZobject_coordsr  rA  dsr   r   r   interp_liker  s0    A



zDataset.interp_likez.tuple[dict[Hashable, Variable], set[Hashable]]c           	        s   i }t  }| j D ]n\}}|jdd}t fdd|jD |_|||}||krftd|d|||< || jkr|	| q||fS )NFrq  c                 3  s   | ]}  ||V  qd S r   r   r   	dims_dictr   r   r     s     z'Dataset._rename_vars.<locals>.<genexpr>zthe new name z
 conflicts)
r   r   rB  rs  r   r   r   r   r  r  )	r  	name_dictrV  r   r2  r  rA  r   r   r   rU  r   r    s    
zDataset._rename_varszMapping[Any, Hashable])rW  r   c                   s    fdd| j  D S )Nc                   s   i | ]\}}  |||qS r   r   rD  rW  r   r   r     s     
 z(Dataset._rename_dims.<locals>.<dictcomp>)r   rB  )r  rW  r   rX  r   r    s    zDataset._rename_dimsz6tuple[dict[Hashable, Index], dict[Hashable, Variable]])rW  rV  r   c           	        s   j si i fS i }i }j D ]f\}}| | fdd|D }|fdd|D  fddt||D }|| q ||fS )Nc                   s   g | ]}  ||qS r   r   r  rX  r   r   r     s     z+Dataset._rename_indexes.<locals>.<listcomp>c                   s   i | ]
}| qS r   r   r  )	new_indexr   r   r     s      z+Dataset._rename_indexes.<locals>.<dictcomp>c                   s   i | ]\}}| j | qS r   r  )r   oldru  r
  r   r   r     s    )r*  r  Zgroup_by_indexrj  r  rN  r   )	r  rW  rV  r3  r   r  r2  r  Znew_index_varsr   )rW  rY  r  r   _rename_indexes  s    
zDataset._rename_indexeszZtuple[dict[Hashable, Variable], set[Hashable], dict[Hashable, int], dict[Hashable, Index]]c                   sL   |  ||\}}| |}| ||\}  fdd| D }||||fS )Nc                   s   i | ]\}}|  ||qS r   r   rD  r  r   r   r   
  s      z'Dataset._rename_all.<locals>.<dictcomp>)r  r  r[  rB  )r  rW  rV  r   r2  r   r3  r   r\  r   _rename_all  s
    
zDataset._rename_allzMapping[Any, Hashable] | None)r  rW  r  r   c                 K  s   t ||d}| D ]}|| kr:|| jkr:td|dd}|| }|| jkrz|| jkrz| j||  j}||fkrd}n.|| jkr|| jkr| j| j}||fkrd}|rtjd|d|| dtd	d
 q| j	||d\}}}	}
| j
|||	|
dS )zsAlso used internally by DataArray so that the warning (if any)
        is raised at the right stack level.
        rj  cannot rename z: because it is not a variable or dimension in this datasetFTzrename  to z} does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.   
stacklevelrW  rV  r   r3  )rM   rp  r   r   r  r  r   r   UserWarningr]  r{  )r  rW  r  r  Zcreate_dim_coordZnew_kZ
coord_dimsr   r2  r   r3  r   r   r   _rename  s6    


 zDataset._renamec                 K  s   | j f d|i|S )a  Returns a new object with renamed variables, coordinates and dimensions.

        Parameters
        ----------
        name_dict : dict-like, optional
            Dictionary whose keys are current variable, coordinate or dimension names and
            whose values are the desired names.
        **names : optional
            Keyword form of ``name_dict``.
            One of name_dict or names must be provided.

        Returns
        -------
        renamed : Dataset
            Dataset with renamed variables, coordinates and dimensions.

        See Also
        --------
        Dataset.swap_dims
        Dataset.rename_vars
        Dataset.rename_dims
        DataArray.rename
        rW  )rf  )r  rW  r  r   r   r   rj  8  s    zDataset.rename)r  rV  r   r   c           	   	   K  s   t ||d}| D ]P\}}|| jkr6td|d|| jksH|| krtd| d| d| dq| ji |d\}}}}| j||||d	S )
a  Returns a new object with renamed dimensions only.

        Parameters
        ----------
        dims_dict : dict-like, optional
            Dictionary whose keys are current dimension names and
            whose values are the desired names. The desired names must
            not be the name of an existing dimension or Variable in the Dataset.
        **dims : optional
            Keyword form of ``dims_dict``.
            One of dims_dict or dims must be provided.

        Returns
        -------
        renamed : Dataset
            Dataset with renamed dimensions.

        See Also
        --------
        Dataset.swap_dims
        Dataset.rename
        Dataset.rename_vars
        DataArray.rename
        r  r^  z. because it is not a dimension in this datasetzCannot rename r_  z	 because z- already exists. Try using swap_dims instead.rc  rd  )rM   rB  r   r   r]  r{  )	r  rV  r   r  rA  r   r2  r?  r3  r   r   r   r  V  s    

 zDataset.rename_dimsc                 K  sV   t ||d}|D ]}|| krtd|dq| j|i d\}}}}| j||||dS )a  Returns a new object with renamed variables including coordinates

        Parameters
        ----------
        name_dict : dict-like, optional
            Dictionary whose keys are current variable or coordinate names and
            whose values are the desired names.
        **names : optional
            Keyword form of ``name_dict``.
            One of name_dict or names must be provided.

        Returns
        -------
        renamed : Dataset
            Dataset with renamed variables including coordinates

        See Also
        --------
        Dataset.swap_dims
        Dataset.rename
        Dataset.rename_dims
        DataArray.rename
        rename_varsr^  z; because it is not a variable or coordinate in this datasetrc  rd  )rM   r   r]  r{  )r  rW  r  r  r   r2  r   r3  r   r   r   rg    s    
 zDataset.rename_vars)r  rV  r   c                   sr  t  |d   D ]R\}}|jkr6td|d|jkrj| j|fkrtd|d|q fddjD }j }|fdd  D  i }i }j D ]\}}t	 fd	d
|jD }	||krJ|
 }
|	|
_|jkrj| ||< |
||< n8t|
\}|fdd|D  || || q| }
|	|
_|
||< qj|||dS )a  Returns a new object with swapped dimensions.

        Parameters
        ----------
        dims_dict : dict-like
            Dictionary whose keys are current dimension names and whose values
            are new names.
        **dims_kwargs : {existing_dim: new_dim, ...}, optional
            The keyword arguments form of ``dims_dict``.
            One of dims_dict or dims_kwargs must be provided.

        Returns
        -------
        swapped : Dataset
            Dataset with swapped dimensions.

        Examples
        --------
        >>> ds = xr.Dataset(
        ...     data_vars={"a": ("x", [5, 7]), "b": ("x", [0.1, 2.4])},
        ...     coords={"x": ["a", "b"], "y": ("x", [0, 1])},
        ... )
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 2)
        Coordinates:
          * x        (x) <U1 'a' 'b'
            y        (x) int64 0 1
        Data variables:
            a        (x) int64 5 7
            b        (x) float64 0.1 2.4

        >>> ds.swap_dims({"x": "y"})
        <xarray.Dataset>
        Dimensions:  (y: 2)
        Coordinates:
            x        (y) <U1 'a' 'b'
          * y        (y) int64 0 1
        Data variables:
            a        (y) int64 5 7
            b        (y) float64 0.1 2.4

        >>> ds.swap_dims({"x": "z"})
        <xarray.Dataset>
        Dimensions:  (z: 2)
        Coordinates:
            x        (z) <U1 'a' 'b'
            y        (z) int64 0 1
        Dimensions without coordinates: z
        Data variables:
            a        (z) int64 5 7
            b        (z) float64 0.1 2.4

        See Also
        --------
        Dataset.rename
        DataArray.swap_dims
        	swap_dimszcannot swap from dimension z( because it is not an existing dimensionzreplacement dimension z. is not a 1D variable along the old dimension c                   s   h | ]}  ||qS r   r   r   rU  r   r   	<setcomp>  s     z$Dataset.swap_dims.<locals>.<setcomp>c                   s   h | ]}| j kr|qS r   r  r   r
  r   r   ri    s     
 c                 3  s   | ]}  ||V  qd S r   r   r   rU  r   r   r     s     z$Dataset.swap_dims.<locals>.<genexpr>c                   s   i | ]
}| qS r   r   r  r  r   r   r     s      z%Dataset.swap_dims.<locals>.<dictcomp>r  )rM   rB  r   r   r   r  rs  r  r   r   r  r*  r4   r  r~  )r  rV  Zdims_kwargsr  rA  Zresult_dimsr2  r   r3  r   r   r  r   )rV  r  r  r   rh    s>    @






zDataset.swap_dimsz8None | Hashable | Sequence[Hashable] | Mapping[Any, Any]zNone | int | Sequence[int])r   axis
dim_kwargsr   c              	     s
  |dkr
nzt |trt|}nft |tr2tdnRt |tsFt |tsP|di}n4t |trt|tt|krvt	ddd |D }t
||d}t |tst|dkrttt|}nt |ts|g}t|t|krt	d|D ]J}|| jkrt	d	| d
|| jkrt| j| st	dj|dqi }t| j}| j }| D ]n\}}	t|	drt|	|}
|
||< ||
  || || j||< nt |	trntdj|dqP| j D ],\}}	||kr||kr|	||< nt|	jt|  |D ]:}|  k s& d |k rtd| d| d  q fdd|D }t|tt|krtt	dtt || }tt |	j|	j!}|D ]\}}|"|| q|	#t|||< n.||krt$|	#|\}
}|
||< || q| j%|||dS )a  Return a new object with an additional axis (or axes) inserted at
        the corresponding position in the array shape.  The new object is a
        view into the underlying array, not a copy.

        If dim is already a scalar coordinate, it will be promoted to a 1D
        coordinate consisting of a single value.

        Parameters
        ----------
        dim : hashable, sequence of hashable, mapping, or None
            Dimensions to include on the new variable. If provided as hashable
            or sequence of hashable, then dimensions are inserted with length
            1. If provided as a mapping, then the keys are the new dimensions
            and the values are either integers (giving the length of the new
            dimensions) or array-like (giving the coordinates of the new
            dimensions).
        axis : int, sequence of int, or None, default: None
            Axis position(s) where new axis is to be inserted (position(s) on
            the result array). If a sequence of integers is passed,
            multiple axes are inserted. In this case, dim arguments should be
            same length list. If axis=None is passed, all the axes will be
            inserted to the start of the result array.
        **dim_kwargs : int or sequence or ndarray
            The keywords are arbitrary dimensions being inserted and the values
            are either the lengths of the new dims (if int is given), or their
            coordinates. Note, this is an alternative to passing a dict to the
            dim kwarg and will only be used if dim is None.

        Returns
        -------
        expanded : Dataset
            This object, but with additional dimension(s).

        See Also
        --------
        DataArray.expand_dims
        Nz:dim should be hashable or sequence of hashables or mappingr   z)dims should not contain duplicate values.c                 S  s   i | ]
}|d qS r   r   rE  r   r   r   r   R  s      z'Dataset.expand_dims.<locals>.<dictcomp>expand_dimsz,lengths of dim and axis should be identical.z
Dimension z already exists.z4{dim} already exists as coordinate or variable name.r   r  z<The value of new dimension {k} must be an iterable or an int)r  zAxis z of variable z1 is out of bounds of the expanded dimension size c                   s    g | ]}|d kr|n | qS r  r   )r   aZresult_ndimr   r   r     s     z'Dataset.expand_dims.<locals>.<listcomp>z(axis should not contain duplicate valuesr2  r3  )&r   r   r   r   r   r   r   r   r   r   rM   r   r  r   r   r   r  r!   rP   r  r*  r  rs  rB  r   r1   r  rN  r  r   r	  sortedr   r   insertset_dimsr4   r~  )r  r   rj  rk  rF  r   r3  r2  r  rA  r  rn  Zaxis_posZzip_axis_dimZall_dimscr  r   ro  r   rl    s    +













  zDataset.expand_dimsz2Mapping[Any, Hashable | Sequence[Hashable]] | NonezHashable | Sequence[Hashable])r3  r  indexes_kwargsr   c                   s  t ||d}i }i }t  t i t }| D ]\}}	t|	tsPt|	tsX|	g}
nt|	}
t|
tj }|rtd	dd |D d |
|
 
|
 jj|dd}t|}|
D ]}|
jj|dd q 
| 
| t|
dkr|r|jkr|
d	 }j| }|j|fkrNtd
|d|d|j tj||ii d||i}|jkr܈| nV|rfdd|D }ni }t||fdd|
D \}jjD ]}||< q|
fdd|D  |
| q2D ]8}||kr||kr|jkrj|  ||< q fddj D }|
| fddj D }|
| | D ]H\}}tfdd|jD rfdd|jD }|j|d||< qj t|B }j|||dS )a  Set Dataset (multi-)indexes using one or more existing coordinates
        or variables.

        This legacy method is limited to pandas (multi-)indexes and
        1-dimensional "dimension" coordinates. See
        :py:meth:`~Dataset.set_xindex` for setting a pandas or a custom
        Xarray-compatible index from one or more arbitrary coordinates.

        Parameters
        ----------
        indexes : {dim: index, ...}
            Mapping from names matching dimensions and values given
            by (lists of) the names of existing coordinates or variables to set
            as new (multi-)index.
        append : bool, default: False
            If True, append the supplied index(es) to the existing index(es).
            Otherwise replace the existing index(es) (default).
        **indexes_kwargs : optional
            The keyword arguments form of ``indexes``.
            One of indexes or indexes_kwargs must be provided.

        Returns
        -------
        obj : Dataset
            Another dataset, with this dataset's data but replaced coordinates.

        Examples
        --------
        >>> arr = xr.DataArray(
        ...     data=np.ones((2, 3)),
        ...     dims=["x", "y"],
        ...     coords={"x": range(2), "y": range(3), "a": ("x", [3, 4])},
        ... )
        >>> ds = xr.Dataset({"v": arr})
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 3)
        Coordinates:
          * x        (x) int64 0 1
          * y        (y) int64 0 1 2
            a        (x) int64 3 4
        Data variables:
            v        (x, y) float64 1.0 1.0 1.0 1.0 1.0 1.0
        >>> ds.set_index(x="a")
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 3)
        Coordinates:
          * x        (x) int64 3 4
          * y        (y) int64 0 1 2
        Data variables:
            v        (x, y) float64 1.0 1.0 1.0 1.0 1.0 1.0

        See Also
        --------
        Dataset.reset_index
        Dataset.set_xindex
        Dataset.swap_dims
        	set_indexr  c                 S  s   g | ]}t |qS r   )r   rV  r   r   r   r     s     z%Dataset.set_index.<locals>.<listcomp>z variable(s) do not existrO  rP  r   r   z7dimension mismatch: try setting an index for dimension z with variable z that has dimensions optionsc                   s   i | ]}| j | qS r   r  r  r
  r   r   r     s     z%Dataset.set_index.<locals>.<dictcomp>c                   s   i | ]}| j | qS r   r  r  r
  r   r   r   !  s      c                   s   i | ]
}| qS r   r   r  r  r   r   r   &  s      c                   s   i | ]\}}| kr||qS r   r   rD  r  r   r   r   2  s      c                   s   i | ]\}}| kr||qS r   r   rD  r  r   r   r   7  s      c                 3  s   | ]}| kV  qd S r   r   rE  replace_dimsr   r   r   >  s     z$Dataset.set_index.<locals>.<genexpr>c                   s   g | ]}  ||qS r   r   rE  r|  r   r   r   ?  s     r>  rp  )rM   r   rB  r   r   r   r   r  r   r  r  r  rR  r   r*  r   r1   from_variablesrN  r  r  r2   Zfrom_variables_maybe_expandr  r  r  r   r{  r~  )r  r3  r  ru  Z
dim_coordsr  r  Zall_var_namesr   Z
_var_names	var_namesZinvalid_varsZindex_coord_namesZall_index_coord_namesr  r   r   idx_varsZcurrent_variablesr@  Zindexes_r   rA  Znew_dimsr2  r   )r  r  r  r}  r  r   rv    s    @



 





  zDataset.set_index)r  dims_or_levelsr  r   c                   s  t  tst  ts g t tj }|rBtt| dt t t }i }i fdd} D ]}j| }||krqr|| tj	|}	
|	 t |trb|jj}
 fdd|
D |j krLrL|}|
fdd|D  
| t ts4
 |fdd|
D  n|j ||
 qr||	 qrfd	dj D }|
| fd
dj D }|
 j }j|||dS )a  Reset the specified index(es) or multi-index level(s).

        This legacy method is specific to pandas (multi-)indexes and
        1-dimensional "dimension" coordinates. See the more generic
        :py:meth:`~Dataset.drop_indexes` and :py:meth:`~Dataset.set_xindex`
        method to respectively drop and set pandas or custom indexes for
        arbitrary coordinates.

        Parameters
        ----------
        dims_or_levels : Hashable or Sequence of Hashable
            Name(s) of the dimension(s) and/or multi-index level(s) that will
            be reset.
        drop : bool, default: False
            If True, remove the specified indexes and/or multi-index levels
            instead of extracting them as new coordinates (default: False).

        Returns
        -------
        obj : Dataset
            Another dataset, with this dataset's data but replaced coordinates.

        See Also
        --------
        Dataset.set_index
        Dataset.set_xindex
        Dataset.drop_indexes
        z" are not coordinates with an indexc                   s0    r |  nfdd| D } | d S )Nc                   s   i | ]}| j |  qS r   )r  r  r  r
  r   r   r   |  s     z@Dataset.reset_index.<locals>.drop_or_convert.<locals>.<dictcomp>)r  )r  Z	base_vars)r  r  r  r  r   r   drop_or_convertx  s    
z,Dataset.reset_index.<locals>.drop_or_convertc                   s    i | ]}| kr|j | qS r   r  r  )r  r  r   r   r     s    z'Dataset.reset_index.<locals>.<dictcomp>c                   s   i | ]
}| qS r   r   r  ry  r   r   r     s      c                   s   g | ]}| kr|qS r   r   r  )keep_level_varsr   r   r     s      z'Dataset.reset_index.<locals>.<listcomp>c                   s   i | ]\}}| kr||qS r   r   rD  rz  r   r   r     s       c                   s   i | ]\}}| kr||qS r   r   rD  r{  r   r   r     s      rp  )r   r   r   r   r*  r   r   r  r  rR  r  r2   r  r  r   Zkeep_levelsrN  rB  r  r  r~  )r  r  r  invalid_coordsseenr  r  r   r  Zidx_var_namesZlevel_namesr  r3  r   r2  r   )r  r  r  r  r  r  r  r  r   reset_indexH  sd    !	












  zDataset.reset_indexzstr | Sequence[Hashable]ztype[Index] | None)r  r2  	index_clsr   c              	     s*  t |st|ts|g}|dkr8t|dkr2t}qPt}nt|tsPt| dt	| j
 }|rdg}|t	 j }|| }|r|d|  |r|d| d td|t	|t	 j@ }|rtd	|  fd
d|D }	|j|	|d}
|
|	}t|
tr |
jgt| }t|dkrn j } j }t| }||krd|| ||< |
||< ni } j D ]\}}||kr||||< q|i } j D ]\}}||kr|||< q|D ]D}z|| ||< W n$ tk
r    j| ||< Y nX |
||< qʈ j| j
t	|B |dS )a  Set a new, Xarray-compatible index from one or more existing
        coordinate(s).

        Parameters
        ----------
        coord_names : str or list
            Name(s) of the coordinate(s) used to build the index.
            If several names are given, their order matters.
        index_cls : subclass of :class:`~xarray.indexes.Index`, optional
            The type of index to create. By default, try setting
            a ``PandasIndex`` if ``len(coord_names) == 1``,
            otherwise a ``PandasMultiIndex``.
        **options
            Options passed to the index constructor.

        Returns
        -------
        obj : Dataset
            Another dataset, with this dataset's data and with a new index.

        Nr   z" is not a subclass of xarray.Indexzinvalid coordinate(s)zthose variables don't exist: z$those variables are data variables: z, use `set_coords` firstr  z)those coordinates already have an index: c                   s   i | ]}| j | qS r   r  r  r
  r   r   r     s      z&Dataset.set_xindex.<locals>.<dictcomp>rw  r  )rP   r   r   r   r1   r2   
issubclassr/   r   r   r  r  r  r   r  r*  r~  rN  r   r   rs  r  rB  r   r{  )r  r2  r  rx  r  r   Zno_varsr,  Zindexed_coordsr  r  Znew_coord_varsr   r3  r   r   r  r   r
  r   
set_xindex  sp    








zDataset.set_xindexz-Mapping[Any, Sequence[int | Hashable]] | NonezSequence[int | Hashable])r  	dim_orderdim_order_kwargsr   c           
        s   t ||d}j }tj}i i | D ]t\}}j| }t|ts\td| dfdd|D }|	|  
|}	 fdd|	D  |	 q0fddj D }| fddj D }| j||d	S )
a  Rearrange index levels using input order.

        Parameters
        ----------
        dim_order : dict-like of Hashable to Sequence of int or Hashable, optional
            Mapping from names matching dimensions and values given
            by lists representing new level orders. Every given dimension
            must have a multi-index.
        **dim_order_kwargs : Sequence of int or Hashable, optional
            The keyword arguments form of ``dim_order``.
            One of dim_order or dim_order_kwargs must be provided.

        Returns
        -------
        obj : Dataset
            Another dataset, with this dataset's data but replaced
            coordinates.
        reorder_levelszcoordinate z has no MultiIndexc                   s   i | ]}| j | qS r   r  r  r
  r   r   r   J  s      z*Dataset.reorder_levels.<locals>.<dictcomp>c                   s   i | ]
}| qS r   r   r  ry  r   r   r   M  s      c                   s   i | ]\}}| kr||qS r   r   rD  )r  r   r   r   P  s       c                   s   i | ]\}}| kr||qS r   r   rD  )r  r   r   r   S  s       r  )rM   r  rs  r   r*  rB  r   r2   r   r  rN  r  r{  )
r  r  r  r   r3  r   orderr  Z
level_varsr  r   )r  r  r  r  r   r  '  s&    







zDataset.reorder_levelsz-tuple[Index | None, dict[Hashable, Variable]]c           
      C  s   d}i }| j  D ]\}}| j| }|jdkr|jd |kr|sL| j|r`|rt|jt	jk	r|dk	r||k	r|rt
d|ddi f  S |}|||< q|r|dkr|| jkr| j| }nt| j|| j\}	}	}tdg|}||i}||fS )a  Used by stack and unstack to get one pandas (multi-)index among
        the indexed coordinates along dimension `dim`.

        If exactly one index is found, return it with its corresponding
        coordinate variables(s), otherwise return None and an empty dict.

        If `create_index=True`, create a new index if none is found or raise
        an error if multiple indexes are found.

        Nr   r   zcannot stack dimension zQ with `create_index=True` and with more than one index found along that dimension)r*  rB  r  r   r   r  Zis_multirJ  unstackr/   r   r   r1   )
r  r   multicreate_indexZstack_indexZstack_coordsr   r  r   r4  r   r   r   _get_stack_indexX  s>    

	


zDataset._get_stack_indexzSequence[Hashable | ellipsis]ztype[Index])r  r   new_dimr  r  r   c                   s  |dkrt dd|kr(tt|j}i }g }g  j D ]\}tfdd|D rfdd|D }tj| }	fdd|	D }
|	|
}|jf ||i}|||< |	| q>j
dd	||< q>|D ]} tjj|d
d7  qi }tj}|s|d kri }|D ],}j||d\}d k	r|| qt|t|kr|||||< |fdd|D  |}|D ]}||d  q|| ||  fddj D }|| j|||dS )N.z/Please use [...] for dims, rather than just ...c                 3  s   | ]}| j kV  qd S r   r>  rE  r  r   r   r     s     z&Dataset._stack_once.<locals>.<genexpr>c                   s   g | ]}| j kr|qS r   r>  rE  r  r   r   r     s     
 z'Dataset._stack_once.<locals>.<listcomp>c                   s   g | ]} j | qS r   r>  rE  r
  r   r   r     s     Frq  rO  rP  )r  c                   s   i | ]
}| qS r   r   r  ry  r   r   r     s      z'Dataset._stack_once.<locals>.<dictcomp>c                   s   i | ]\}}| kr||qS r   r   rD  rz  r   r   r     s       rp  )r   r   rN   r   r   rB  r   rs  stackr  rs  r  rR  r   r  r  r  r   rN  r  r*  r~  )r  r   r  r  r  r  Zstacked_var_namesr   Zadd_dimsZvdimsr   Zexp_varZstacked_varr  r  Zproduct_varsr   r  r  r3  r   )r  r  r  r   r   _stack_once  sV    





  zDataset._stack_oncez2Mapping[Any, Sequence[Hashable | ellipsis]] | None)r  
dimensionsr  r  dimensions_kwargsr   c                 K  s6   t ||d}| }| D ]\}}|||||}q|S )a  
        Stack any number of existing dimensions into a single new dimension.

        New dimensions will be added at the end, and by default the corresponding
        coordinate variables will be combined into a MultiIndex.

        Parameters
        ----------
        dimensions : mapping of hashable to sequence of hashable
            Mapping of the form `new_name=(dim1, dim2, ...)`. Names of new
            dimensions, and the existing dimensions that they replace. An
            ellipsis (`...`) will be replaced by all unlisted dimensions.
            Passing a list containing an ellipsis (`stacked_dim=[...]`) will stack over
            all dimensions.
        create_index : bool or None, default: True

            - True: create a multi-index for each of the stacked dimensions.
            - False: don't create any index.
            - None. create a multi-index only if exactly one single (1-d) coordinate
              index is found for every dimension to stack.

        index_cls: Index-class, default: PandasMultiIndex
            Can be used to pass a custom multi-index type (must be an Xarray index that
            implements `.stack()`). By default, a pandas multi-index wrapper is used.
        **dimensions_kwargs
            The keyword arguments form of ``dimensions``.
            One of dimensions or dimensions_kwargs must be provided.

        Returns
        -------
        stacked : Dataset
            Dataset with stacked data.

        See Also
        --------
        Dataset.unstack
        r  )rM   rB  r  )r  r  r  r  r  r  r  r   r   r   r   r    s
    ,zDataset.stackr   zCollection[Hashable])r  sample_dimsvariable_dimr   r   c                   s   ddl m} tfddjD D ]0}| j}tt|k}|s(td|q(fdd  fdd	jD }	||	d
}
|dk	r||
_|
S )a  Combine variables of differing dimensionality into a DataArray
        without broadcasting.

        This method is similar to Dataset.to_array but does not broadcast the
        variables.

        Parameters
        ----------
        new_dim : hashable
            Name of the new stacked coordinate
        sample_dims : Collection of hashables
            List of dimensions that **will not** be stacked. Each array in the
            dataset must share these dimensions. For machine learning
            applications, these define the dimensions over which samples are
            drawn.
        variable_dim : hashable, default: "variable"
            Name of the level in the stacked coordinate which corresponds to
            the variables.
        name : hashable, optional
            Name of the new data array.

        Returns
        -------
        stacked : DataArray
            DataArray with the specified dimensions and data variables
            stacked together. The stacked coordinate is named ``new_dim``
            and represented by a MultiIndex object with a level containing the
            data variable names. The name of this level is controlled using
            the ``variable_dim`` argument.

        See Also
        --------
        Dataset.to_array
        Dataset.stack
        DataArray.to_unstacked_dataset

        Examples
        --------
        >>> data = xr.Dataset(
        ...     data_vars={
        ...         "a": (("x", "y"), [[0, 1, 2], [3, 4, 5]]),
        ...         "b": ("x", [6, 7]),
        ...     },
        ...     coords={"y": ["u", "v", "w"]},
        ... )

        >>> data
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 3)
        Coordinates:
          * y        (y) <U1 'u' 'v' 'w'
        Dimensions without coordinates: x
        Data variables:
            a        (x, y) int64 0 1 2 3 4 5
            b        (x) int64 6 7

        >>> data.to_stacked_array("z", sample_dims=["x"])
        <xarray.DataArray 'a' (x: 2, z: 4)>
        array([[0, 1, 2, 6],
               [3, 4, 5, 7]])
        Coordinates:
          * z         (z) object MultiIndex
          * variable  (z) object 'a' 'a' 'a' 'b'
          * y         (z) object 'u' 'v' 'w' nan
        Dimensions without coordinates: x

        r   )concatc                 3  s   | ]}| kr|V  qd S r   r   r   )r  r   r   r   H  s      z+Dataset.to_stacked_array.<locals>.<genexpr>z<All variables in the dataset must contain the dimensions {}.c                   sn   | j i}D ]}|| jkrd ||< qtt| j}| t|}| jf || f iS r   )	r   r   r   r   r  r   assign_coordsrl  r  )r  r  r   rl  )r  stacking_dimsr  r   r   ensure_stackableS  s    



z2Dataset.to_stacked_array.<locals>.ensure_stackablec                   s   g | ]} | qS r   r   r	  )r  r  r   r   r   e  s     z,Dataset.to_stacked_array.<locals>.<listcomp>rm  N)	Zxarray.core.concatr  r   r   r   r   r  r,  r   )r  r  r  r  r   r  r   r   Zdims_include_sample_dimsZstackable_vars
data_arrayr   )r  r  r  r  r  r  r   to_stacked_array  s"    J
zDataset.to_stacked_arrayz&tuple[Index, dict[Hashable, Variable]])r  r   index_and_varsr6  r   c                   s   |\}}i } fdd| j  D }| \}	}
||	 |	 D ]\}}||| qB| j D ]R\}}||krf |jkrt|tr|| }n|}|j	|
 ||d||< qf|||< qft
| j h t
|	B }| j|||dS )Nc                   s   i | ]\}}| kr||qS r   r   rD  rm  r   r   r   v  s       z)Dataset._unstack_once.<locals>.<dictcomp>)r  r   r1  r6  rp  )r*  rB  r  r  rN  r   r   r   r   _unstack_oncer   r  r~  )r  r   r  r1  r6  r  r  r   r3  r  clean_indexr   r  r   fill_value_r2  r   rm  r   r  m  s4    




  zDataset._unstack_oncec                   sF  |\}}i } fdd| j  D }| \}	}
||	 i }|	 D ]\}}||| qFdd | D }|| tjj|
j|
j	d}|

|r| }n:t| tfdd|D |}| j|d||d}|j D ]8\}}||kr |jkr| |i||< q|||< qt| j h t|B }| j|||dS )	Nc                   s   i | ]\}}| kr||qS r   r   rD  rm  r   r   r     s       z1Dataset._unstack_full_reindex.<locals>.<dictcomp>c                 S  s   i | ]\}}||j qS r   r   rD  r   r   r   r     s      r  c                   s   i | ]
}| qS r   r   r  )xr_full_idxr   r   r     s      Fr5  rp  )r*  rB  r  r  rN  r   
MultiIndexZfrom_productlevelsr  r  r2   r0   r<  r   r   r   r  r~  )r  r   r  r1  r6  r  r  r   r3  r  r  Znew_index_variablesr   r  Znew_dim_sizesZfull_idxr   r  r   r2  r   )r   r  r   _unstack_full_reindex  sL    

 

   
  zDataset._unstack_full_reindex)r  r   r1  r6  r   c                   sT  |dkrt  j}nHt|ts(t|ts0|g}nt |} fdd|D }|r\td| i }|D ]*} j|dd\}}	|dk	rd||	f||< qd|dkrt |}n&t|t| }
|
rtdt|
  j	dd	} fd
dt j
t j D }tdtfdd|D }|D ]6}|r8|||| ||}n|||| ||}q|S )aZ  
        Unstack existing dimensions corresponding to MultiIndexes into
        multiple new dimensions.

        New dimensions will be added at the end.

        Parameters
        ----------
        dim : str, Iterable of Hashable or None, optional
            Dimension(s) over which to unstack. By default unstacks all
            MultiIndexes.
        fill_value : scalar or dict-like, default: nan
            value to be filled. If a dict-like, maps variable names to
            fill values. If not provided or if the dict-like does not
            contain all variables, the dtype's NA value will be used.
        sparse : bool, default: False
            use sparse-array if True

        Returns
        -------
        unstacked : Dataset
            Dataset with unstacked data.

        See Also
        --------
        Dataset.stack
        Nc                   s   g | ]}| j kr|qS r   r>  rE  r
  r   r   r     s     
 z#Dataset.unstack.<locals>.<listcomp>)Dataset does not contain the dimensions: T)r  zDcannot unstack dimensions that do not have exactly one multi-index: Frq  c                   s   g | ]} j | qS r   r  r  r
  r   r   r     s    r6  c                 3  s4   | ],}t |jp*t|j p*t|jtj V  qd S r   )rC   r   r   r   r  rV  )sparse_array_typer   r   r     s
   

z"Dataset.unstack.<locals>.<genexpr>)r   r   r   r   r   r   r  r   r   rs  r   r*  rB   r   r  r  )r  r   r1  r6  r   r  Zstacked_indexesrF  r  r  Znon_multi_dimsr  Z
nonindexesZneeds_full_reindexr   )r  r  r   r    sP    "

   zDataset.unstackrb   )r  r  r   c                 C  s"   t | |}| jf ddi| S )a1  Update this dataset's variables with those from another dataset.

        Just like :py:meth:`dict.update` this is a in-place operation.
        For a non-inplace version, see :py:meth:`Dataset.merge`.

        Parameters
        ----------
        other : Dataset or mapping
            Variables with which to update this dataset. One of:

            - Dataset
            - mapping {var name: DataArray}
            - mapping {var name: Variable}
            - mapping {var name: (dimension name, array-like)}
            - mapping {var name: (tuple of dimension names, array-like)}

        Returns
        -------
        updated : Dataset
            Updated dataset. Note that since the update is in-place this is the input
            dataset.

            It is deprecated since version 0.17 and scheduled to be removed in 0.21.

        Raises
        ------
        ValueError
            If any dimensions would have inconsistent sizes in the updated
            dataset.

        See Also
        --------
        Dataset.assign
        Dataset.merge
        rz  T)r<   r{  _asdict)r  r  merge_resultr   r   r   r  .  s    $
zDataset.updateZno_conflictsr-  overridezCoercibleMapping | DataArrayrj   rq   ri   )r  r  overwrite_varsr1  r  r1  combine_attrsr   c           	   	   C  sH   ddl m} t||r| n|}t| ||||||d}| jf | S )a  Merge the arrays of two datasets into a single dataset.

        This method generally does not allow for overriding data, with the
        exception of attributes, which are ignored on the second dataset.
        Variables with the same name are checked for conflicts via the equals
        or identical methods.

        Parameters
        ----------
        other : Dataset or mapping
            Dataset or variables to merge with this dataset.
        overwrite_vars : hashable or iterable of hashable, optional
            If provided, update variables of these name(s) without checking for
            conflicts in this dataset.
        compat : {"identical", "equals", "broadcast_equals",                   "no_conflicts", "override", "minimal"}, default: "no_conflicts"
            String indicating how to compare variables of the same name for
            potential conflicts:

            - 'identical': all values, dimensions and attributes must be the
              same.
            - 'equals': all values and dimensions must be the same.
            - 'broadcast_equals': all values must be equal when variables are
              broadcast against each other to ensure common dimensions.
            - 'no_conflicts': only values which are not null in both datasets
              must be equal. The returned dataset then contains the combination
              of all non-null values.
            - 'override': skip comparing and pick variable from first dataset
            - 'minimal': drop conflicting coordinates

        join : {"outer", "inner", "left", "right", "exact", "override"},                default: "outer"
            Method for joining ``self`` and ``other`` along shared dimensions:

            - 'outer': use the union of the indexes
            - 'inner': use the intersection of the indexes
            - 'left': use indexes from ``self``
            - 'right': use indexes from ``other``
            - 'exact': error instead of aligning non-equal indexes
            - 'override': use indexes from ``self`` that are the same size
              as those of ``other`` in that dimension

        fill_value : scalar or dict-like, optional
            Value to use for newly missing values. If a dict-like, maps
            variable names (including coordinates) to fill values.
        combine_attrs : {"drop", "identical", "no_conflicts", "drop_conflicts",                          "override"} or callable, default: "override"
            A callable or a string indicating how to combine attrs of the objects being
            merged:

            - "drop": empty attrs on returned Dataset.
            - "identical": all attrs must be the same on every object.
            - "no_conflicts": attrs from all objects are combined, any that have
              the same name must also have the same value.
            - "drop_conflicts": attrs from all objects are combined, any that have
              the same name but different values are dropped.
            - "override": skip comparing and copy attrs from the first dataset to
              the result.

            If a callable, it must expect a sequence of ``attrs`` dicts and a context object
            as its only parameters.

        Returns
        -------
        merged : Dataset
            Merged dataset.

        Raises
        ------
        MergeError
            If any variables conflict (see ``compat``).

        See Also
        --------
        Dataset.update
        r   r^   )r  r1  r  r1  r  )r   r_   r   r   r;   r{  r  )	r  r  r  r1  r  r1  r  r_   r  r   r   r   rQ  U  s    U	zDataset.merge)r  virtual_okayr   c                 C  s0   t |t | j }|r || j8 }|r,tdd S )NzFOne or more of the specified variables cannot be found in this dataset)r   r  Zvirtual_variablesr   )r  r  r  Z	bad_namesr   r   r   r    s    
zDataset._assert_all_in_datasetrP  rn   )r  r  rQ  r   c          
        s  t  st ts h nt  |dkr4|   t } D ]F}| j|d}t|tr>t|jj	|j
g }|t  }|| q>|r t|O  tjd|dtdd t| j   fdd| j D fd	d
| jD } fdd| j D }	| j||	dS )a  Drop variables from this dataset.

        Parameters
        ----------
        names : hashable or iterable of hashable
            Name(s) of variables to drop.
        errors : {"raise", "ignore"}, default: "raise"
            If 'raise', raises a ValueError error if any of the variable
            passed are not in the dataset. If 'ignore', any given names that are in the
            dataset are dropped and no error is raised.

        Returns
        -------
        dropped : Dataset

        r   NzDeleting a single level of a MultiIndex is deprecated. Previously, this deleted all levels of a MultiIndex. Please also drop the following variables: z! to avoid an error in the future.r   ra  c                   s   i | ]\}}| kr||qS r   r   rD  r  r   r   r     s       z%Dataset.drop_vars.<locals>.<dictcomp>c                   s   h | ]}| kr|qS r   r   r  r  r   r   ri    s      z$Dataset.drop_vars.<locals>.<setcomp>c                   s   i | ]\}}| kr||qS r   r   rD  r  r   r   r     s       rp  )rP   r   r   r   r  r*  r   r2   r  r  r   r  r   r   DeprecationWarningr3   r  r  rB  r  r~  )
r  r  rQ  Zother_namesr   Z
maybe_midxZidx_coord_namesZidx_other_namesr2  r3  r   )r  r   r   	drop_vars  s8    


  zDataset.drop_vars)r  r2  rQ  r   c          	        s   t  st ts h nt  |dkrj | j }|rFtd| t t| j }|rjtd| t| j dd i }| j	
 D ]&\}}| kr| ||< q|||< q fdd| j
 D }| j||dS )	a8  Drop the indexes assigned to the given coordinates.

        Parameters
        ----------
        coord_names : hashable or iterable of hashable
            Name(s) of the coordinate(s) for which to drop the index.
        errors : {"raise", "ignore"}, default: "raise"
            If 'raise', raises a ValueError error if any of the coordinates
            passed have no index or are not in the dataset.
            If 'ignore', no error is raised.

        Returns
        -------
        dropped : Dataset
            A new dataset with dropped indexes.

        r   zthose coordinates don't exist: z(those coordinates do not have an index: zremove index(es))actionc                   s   i | ]\}}| kr||qS r   r   rD  r2  r   r   r   -  s       z(Dataset.drop_indexes.<locals>.<dictcomp>)r   r3  )rP   r   r   r   r  r   r*  r3   r  r  rB  r  r{  )	r  r2  rQ  r  Zunindexed_coordsr   r   r   r3  r   r  r   r    s(    

zDataset.drop_indexes)r  rQ  r   c                K  s   |dkrt dt|r@t|ts@tjdtdd | j||dS |sNt|trj|dk	r^t dt||d	}|dkrt	|st|t
rtjd
tdd | j||dS |dk	rtjdtdd | j||ifd|i|S tjdtdd | j||dS )zBackward compatible method based on `drop_vars` and `drop_sel`

        Using either `drop_vars` or `drop_sel` is encouraged

        See Also
        --------
        Dataset.drop_vars
        Dataset.drop_sel
        r   rO  )errors must be either "raise" or "ignore"zBdropping coordinates using `drop` is be deprecated; use drop_vars.r   ra  rP  Nz+cannot specify dim and dict-like arguments.r  zRdropping variables using `drop` will be deprecated; using drop_vars is encouraged.zdropping labels using list-like labels is deprecated; using dict-like arguments with `drop_sel`, e.g. `ds.drop_sel(dim=[labels]).rQ  zNdropping labels using `drop` will be deprecated; using drop_sel is encouraged.)r   rO   r   r   r   r   r  r  rM   rP   r   PendingDeprecationWarningr  drop_sel)r  labelsr   rQ  labels_kwargsr   r   r   r  1  sB    zDataset.dropc          	   	   K  s   |dkrt dt||d}| }| D ]r\}}t|r@|g}t|}z| |}W n$ tk
r|   t d|dY nX |j	||d}|j
||i }q(|S )a%  Drop index labels from this dataset.

        Parameters
        ----------
        labels : mapping of hashable to Any
            Index labels to drop
        errors : {"raise", "ignore"}, default: "raise"
            If 'raise', raises a ValueError error if
            any of the index labels passed are not
            in the dataset. If 'ignore', any given labels that are in the
            dataset are dropped and no error is raised.
        **labels_kwargs : {dim: label, ...}, optional
            The keyword arguments form of ``dim`` and ``labels``

        Returns
        -------
        dropped : Dataset

        Examples
        --------
        >>> data = np.arange(6).reshape(2, 3)
        >>> labels = ["a", "b", "c"]
        >>> ds = xr.Dataset({"A": (["x", "y"], data), "y": labels})
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 3)
        Coordinates:
          * y        (y) <U1 'a' 'b' 'c'
        Dimensions without coordinates: x
        Data variables:
            A        (x, y) int64 0 1 2 3 4 5
        >>> ds.drop_sel(y=["a", "c"])
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 1)
        Coordinates:
          * y        (y) <U1 'b'
        Dimensions without coordinates: x
        Data variables:
            A        (x, y) int64 1 4
        >>> ds.drop_sel(y="b")
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 2)
        Coordinates:
          * y        (y) <U1 'a' 'c'
        Dimensions without coordinates: x
        Data variables:
            A        (x, y) int64 0 2 3 5
        r  r  r  z
dimension z  does not have coordinate labelsrP  )r   rM   rB  r!   rP   r   r  	get_indexr   r  r  )	r  r  rQ  r  rS  r   Zlabels_for_dimr  rY  r   r   r   r  i  s    3

zDataset.drop_selc           	      K  sj   t ||d}| }i }| D ]>\}}t|r4|g}t|}| |}||}|||< q|j| }|S )aB  Drop index positions from this Dataset.

        Parameters
        ----------
        indexers : mapping of hashable to Any
            Index locations to drop
        **indexers_kwargs : {dim: position, ...}, optional
            The keyword arguments form of ``dim`` and ``positions``

        Returns
        -------
        dropped : Dataset

        Raises
        ------
        IndexError

        Examples
        --------
        >>> data = np.arange(6).reshape(2, 3)
        >>> labels = ["a", "b", "c"]
        >>> ds = xr.Dataset({"A": (["x", "y"], data), "y": labels})
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 3)
        Coordinates:
          * y        (y) <U1 'a' 'b' 'c'
        Dimensions without coordinates: x
        Data variables:
            A        (x, y) int64 0 1 2 3 4 5
        >>> ds.drop_isel(y=[0, 2])
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 1)
        Coordinates:
          * y        (y) <U1 'b'
        Dimensions without coordinates: x
        Data variables:
            A        (x, y) int64 1 4
        >>> ds.drop_isel(y=1)
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 2)
        Coordinates:
          * y        (y) <U1 'a' 'c'
        Dimensions without coordinates: x
        Data variables:
            A        (x, y) int64 0 2 3 5
        	drop_isel)	rM   rB  r!   rP   r   r  r  deleter  )	r  r  r  rS  Zdimension_indexr   Zpos_for_dimr  rY  r   r   r   r    s    1





zDataset.drop_iselzstr | Iterable[Hashable])r  	drop_dimsrQ  r   c                  s~   |dkrt dt ts$t ts, h nt  |dkr\ t| j }|r\t d|  fdd| j D }| |S )a  Drop dimensions and associated variables from this dataset.

        Parameters
        ----------
        drop_dims : str or Iterable of Hashable
            Dimension or dimensions to drop.
        errors : {"raise", "ignore"}, default: "raise"
            If 'raise', raises a ValueError error if any of the
            dimensions passed are not in the dataset. If 'ignore', any given
            dimensions that are in the dataset are dropped and no error is raised.

        Returns
        -------
        obj : Dataset
            The dataset without the given dimensions (or any variables
            containing those dimensions).
        r  r  r   r  c                   s"   h | ]\}}t |j @ r|qS r   rD  rD  r  r   r   ri    s      z$Dataset.drop_dims.<locals>.<setcomp>)	r   r   r   r   r   r   r  rB  r  )r  r  rQ  r  r  r   r  r   r    s    zDataset.drop_dims)r  r   r  r   c                  s   t |dkrLt|d trLdd |d D }tdd| d|d  dt |dkrjtt|| j|}|  }| j	 D ].\} t
 fdd	|D } j| |j|< q||S )
a  Return a new Dataset object with all array dimensions transposed.

        Although the order of dimensions on each array will change, the dataset
        dimensions themselves will remain in fixed (sorted) order.

        Parameters
        ----------
        *dims : hashable, optional
            By default, reverse the dimensions on each array. Otherwise,
            reorder the dimensions to this order.
        missing_dims : {"raise", "warn", "ignore"}, default: "raise"
            What to do if dimensions that should be selected from are not present in the
            Dataset:
            - "raise": raise an exception
            - "warn": raise a warning, and ignore the missing dimensions
            - "ignore": ignore the missing dimensions

        Returns
        -------
        transposed : Dataset
            Each array in the dataset (including) coordinates will be
            transposed to the given order.

        Notes
        -----
        This operation returns a view of each array's data. It is
        lazy for dask-backed DataArrays but not for numpy-backed DataArrays
        -- the data will be fully loaded into memory.

        See Also
        --------
        numpy.transpose
        DataArray.transpose
        r   c                 S  s&   g | ]}t |trt| n| qS r   )r   r   r  r   r   r   r   r   C  s     z%Dataset.transpose.<locals>.<listcomp>zFtranspose requires dims to be passed as multiple arguments. Expected `r  z`. Received `z	` insteadc                 3  s    | ]}| j d  kr|V  qdS )).Nr>  r   r  r   r   r   N  s      z$Dataset.transpose.<locals>.<genexpr>)r   r   r   r   r  rN   r   rs  r  rB  r   	transpose)r  r  r   Zlist_fixr4  rS  r   Zvar_dimsr   r  r   r    s    (zDataset.transposer   zLiteral[('any', 'all')])r  r   howthreshsubsetr   c                   s   j krt  d|dkr*tj}tjj   tjd}td}|D ]\}j| } |j krN fdd|j D }	|t	|
|	7 }|tfdd|	D 7 }qN|dk	r||k}
nD|dkr||k}
n2|d	kr|dk}
n |dk	rtd
| ntd |
iS )a&  Returns a new dataset with dropped labels for missing values along
        the provided dimension.

        Parameters
        ----------
        dim : hashable
            Dimension along which to drop missing values. Dropping along
            multiple dimensions simultaneously is not yet supported.
        how : {"any", "all"}, default: "any"
            - any : if any NA values are present, drop that label
            - all : if all values are NA, drop that label

        thresh : int or None, optional
            If supplied, require this many non-NA values.
        subset : iterable of hashable or None, optional
            Which variables to check for missing values. By default, all
            variables in the dataset are checked.

        Returns
        -------
        Dataset
        z# must be a single dataset dimensionNr  r   c                   s   g | ]}| kr|qS r   r   rE  rm  r   r   r     s      z"Dataset.dropna.<locals>.<listcomp>c                   s   g | ]} j | qS r   r>  rE  r
  r   r   r     s     r   rM  zinvalid how option: zmust specify how or thresh)r   r   re  r,  r   zerosr  int_r  r  countmathprodr   r  )r  r   r  r  r  r  r   r  r   r   maskr   )r   r  r   dropnaR  s,    !







zDataset.dropna)r  r#  r   c                 C  sH   t |r8t|d| }t|t| j ks8tdt| |}|S )u	  Fill missing values in this object.

        This operation follows the normal broadcasting and alignment rules that
        xarray uses for binary arithmetic, except the result is aligned to this
        object (``join='left'``) instead of aligned to the intersection of
        index coordinates (``join='inner'``).

        Parameters
        ----------
        value : scalar, ndarray, DataArray, dict or Dataset
            Used to fill all matching missing values in this dataset's data
            variables. Scalars, ndarrays or DataArrays arguments are used to
            fill all data with aligned coordinates (for DataArrays).
            Dictionaries or datasets match data variables and then align
            coordinates if necessary.

        Returns
        -------
        Dataset

        Examples
        --------
        >>> ds = xr.Dataset(
        ...     {
        ...         "A": ("x", [np.nan, 2, np.nan, 0]),
        ...         "B": ("x", [3, 4, np.nan, 1]),
        ...         "C": ("x", [np.nan, np.nan, np.nan, 5]),
        ...         "D": ("x", [np.nan, 3, np.nan, 4]),
        ...     },
        ...     coords={"x": [0, 1, 2, 3]},
        ... )
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 4)
        Coordinates:
          * x        (x) int64 0 1 2 3
        Data variables:
            A        (x) float64 nan 2.0 nan 0.0
            B        (x) float64 3.0 4.0 nan 1.0
            C        (x) float64 nan nan nan 5.0
            D        (x) float64 nan 3.0 nan 4.0

        Replace all `NaN` values with 0s.

        >>> ds.fillna(0)
        <xarray.Dataset>
        Dimensions:  (x: 4)
        Coordinates:
          * x        (x) int64 0 1 2 3
        Data variables:
            A        (x) float64 0.0 2.0 0.0 0.0
            B        (x) float64 3.0 4.0 0.0 1.0
            C        (x) float64 0.0 0.0 0.0 5.0
            D        (x) float64 0.0 3.0 0.0 4.0

        Replace all `NaN` elements in column ‘A’, ‘B’, ‘C’, and ‘D’, with 0, 1, 2, and 3 respectively.

        >>> values = {"A": 0, "B": 1, "C": 2, "D": 3}
        >>> ds.fillna(value=values)
        <xarray.Dataset>
        Dimensions:  (x: 4)
        Coordinates:
          * x        (x) int64 0 1 2 3
        Data variables:
            A        (x) float64 0.0 2.0 0.0 0.0
            B        (x) float64 3.0 4.0 1.0 1.0
            C        (x) float64 2.0 2.0 2.0 5.0
            D        (x) float64 3.0 3.0 3.0 4.0
        r,  zSall variables in the argument to `fillna` must be contained in the original dataset)	r!   rO   r   rp  r   r,  r   r    fillna)r  r#  Z
value_keysoutr   r   r   r    s    F
zDataset.fillnazbool | HashablezFint | float | str | pd.Timedelta | np.timedelta64 | datetime.timedelta)r  r   r  limituse_coordinatemax_gaprF  r   c           
      K  s2   ddl m}m} ||| f|||||d|}	|	S )a  Fill in NaNs by interpolating according to different methods.

        Parameters
        ----------
        dim : Hashable or None, optional
            Specifies the dimension along which to interpolate.
        method : {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial",             "barycentric", "krog", "pchip", "spline", "akima"}, default: "linear"
            String indicating which method to use for interpolation:

            - 'linear': linear interpolation. Additional keyword
              arguments are passed to :py:func:`numpy.interp`
            - 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'polynomial':
              are passed to :py:func:`scipy.interpolate.interp1d`. If
              ``method='polynomial'``, the ``order`` keyword argument must also be
              provided.
            - 'barycentric', 'krog', 'pchip', 'spline', 'akima': use their
              respective :py:class:`scipy.interpolate` classes.

        use_coordinate : bool or Hashable, default: True
            Specifies which index to use as the x values in the interpolation
            formulated as `y = f(x)`. If False, values are treated as if
            eqaully-spaced along ``dim``. If True, the IndexVariable `dim` is
            used. If ``use_coordinate`` is a string, it specifies the name of a
            coordinate variariable to use as the index.
        limit : int, default: None
            Maximum number of consecutive NaNs to fill. Must be greater than 0
            or None for no limit. This filling is done regardless of the size of
            the gap in the data. To only interpolate over gaps less than a given length,
            see ``max_gap``.
        max_gap : int, float, str, pandas.Timedelta, numpy.timedelta64, datetime.timedelta, default: None
            Maximum size of gap, a continuous sequence of NaNs, that will be filled.
            Use None for no limit. When interpolating along a datetime64 dimension
            and ``use_coordinate=True``, ``max_gap`` can be one of the following:

            - a string that is valid input for pandas.to_timedelta
            - a :py:class:`numpy.timedelta64` object
            - a :py:class:`pandas.Timedelta` object
            - a :py:class:`datetime.timedelta` object

            Otherwise, ``max_gap`` must be an int or a float. Use of ``max_gap`` with unlabeled
            dimensions has not been implemented yet. Gap length is defined as the difference
            between coordinate values at the first data point after a gap and the last value
            before a gap. For gaps at the beginning (end), gap length is defined as the difference
            between coordinate values at the first (last) valid data point and the first (last) NaN.
            For example, consider::

                <xarray.DataArray (x: 9)>
                array([nan, nan, nan,  1., nan, nan,  4., nan, nan])
                Coordinates:
                  * x        (x) int64 0 1 2 3 4 5 6 7 8

            The gap lengths are 3-0 = 3; 6-3 = 3; and 8-6 = 2 respectively
        **kwargs : dict, optional
            parameters passed verbatim to the underlying interpolation function

        Returns
        -------
        interpolated: Dataset
            Filled in Dataset.

        See Also
        --------
        numpy.interp
        scipy.interpolate

        Examples
        --------
        >>> ds = xr.Dataset(
        ...     {
        ...         "A": ("x", [np.nan, 2, 3, np.nan, 0]),
        ...         "B": ("x", [3, 4, np.nan, 1, 7]),
        ...         "C": ("x", [np.nan, np.nan, np.nan, 5, 0]),
        ...         "D": ("x", [np.nan, 3, np.nan, -1, 4]),
        ...     },
        ...     coords={"x": [0, 1, 2, 3, 4]},
        ... )
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 5)
        Coordinates:
          * x        (x) int64 0 1 2 3 4
        Data variables:
            A        (x) float64 nan 2.0 3.0 nan 0.0
            B        (x) float64 3.0 4.0 nan 1.0 7.0
            C        (x) float64 nan nan nan 5.0 0.0
            D        (x) float64 nan 3.0 nan -1.0 4.0

        >>> ds.interpolate_na(dim="x", method="linear")
        <xarray.Dataset>
        Dimensions:  (x: 5)
        Coordinates:
          * x        (x) int64 0 1 2 3 4
        Data variables:
            A        (x) float64 nan 2.0 3.0 1.5 0.0
            B        (x) float64 3.0 4.0 2.5 1.0 7.0
            C        (x) float64 nan nan nan 5.0 0.0
            D        (x) float64 nan 3.0 1.0 -1.0 4.0

        >>> ds.interpolate_na(dim="x", method="linear", fill_value="extrapolate")
        <xarray.Dataset>
        Dimensions:  (x: 5)
        Coordinates:
          * x        (x) int64 0 1 2 3 4
        Data variables:
            A        (x) float64 1.0 2.0 3.0 1.5 0.0
            B        (x) float64 3.0 4.0 2.5 1.0 7.0
            C        (x) float64 20.0 15.0 10.0 5.0 0.0
            D        (x) float64 5.0 3.0 1.0 -1.0 4.0
        r   )_apply_over_vars_with_dim	interp_na)r   r  r  r  r  )xarray.core.missingr  r  )
r  r   r  r  r  r  rF  r  r  ru  r   r   r   interpolate_na  s    y
zDataset.interpolate_na)r  r   r  r   c                 C  s$   ddl m}m} ||| ||d}|S )a  Fill NaN values by propagating values forward

        *Requires bottleneck.*

        Parameters
        ----------
        dim : Hashable
            Specifies the dimension along which to propagate values when
            filling.
        limit : int or None, optional
            The maximum number of consecutive NaN values to forward fill. In
            other words, if there is a gap with more than this number of
            consecutive NaNs, it will only be partially filled. Must be greater
            than 0 or None for no limit. Must be None or greater than or equal
            to axis length if filling along chunked axes (dimensions).

        Returns
        -------
        Dataset
        r   )r  ffillr   r  )r  r  r  )r  r   r  r  r  ru  r   r   r   r  g  s    zDataset.ffillc                 C  s$   ddl m}m} ||| ||d}|S )a  Fill NaN values by propagating values backward

        *Requires bottleneck.*

        Parameters
        ----------
        dim : Hashable
            Specifies the dimension along which to propagate values when
            filling.
        limit : int or None, optional
            The maximum number of consecutive NaN values to backward fill. In
            other words, if there is a gap with more than this number of
            consecutive NaNs, it will only be partially filled. Must be greater
            than 0 or None for no limit. Must be None or greater than or equal
            to axis length if filling along chunked axes (dimensions).

        Returns
        -------
        Dataset
        r   )r  bfillr  )r  r  r  )r  r   r  r  r  ru  r   r   r   r    s    zDataset.bfillc                 C  s   t j| |ddd}|S )a  Combine two Datasets, default to data_vars of self.

        The new coordinates follow the normal broadcasting and alignment rules
        of ``join='outer'``.  Vacant cells in the expanded coordinates are
        filled with np.nan.

        Parameters
        ----------
        other : Dataset
            Used to fill all matching missing values in this array.

        Returns
        -------
        Dataset
        r-  )r  Zdataset_join)r    r  )r  r  r  r   r   r   combine_first  s    zDataset.combine_first)
keep_attrskeepdimsnumeric_onlyr   )r  r   r   r  r  r  rF  r   c                  s  | dddk	rtd|dks(|dkr4tj n$t|tsHt|tsP|h nt| fdd D }|r|td| |dkrtdd	}i j	 D ]\}}	 fd
d|	jD }
|j
kr|
s|	|< q|
r|rt|	jtjs|	jtjkrt|
|	jkr|	jdkrdn|
}|	j|f|||d||< qfddj
D }fddj	 D }|rpjnd}j|||dS )aa  Reduce this dataset by applying `func` along some dimension(s).

        Parameters
        ----------
        func : callable
            Function which can be called in the form
            `f(x, axis=axis, **kwargs)` to return the result of reducing an
            np.ndarray over an integer valued axis.
        dim : str, Iterable of Hashable or None, optional
            Dimension(s) over which to apply `func`. By default `func` is
            applied over all dimensions.
        keep_attrs : bool or None, optional
            If True, the dataset's attributes (`attrs`) will be copied from
            the original object to the new one.  If False (default), the new
            object will be returned without attributes.
        keepdims : bool, default: False
            If True, the dimensions which are reduced are left in the result
            as dimensions of size one. Coordinates that use these dimensions
            are removed.
        numeric_only : bool, default: False
            If True, only apply ``func`` to variables with a numeric dtype.
        **kwargs : Any
            Additional keyword arguments passed on to ``func``.

        Returns
        -------
        reduced : Dataset
            Dataset with this object's DataArrays replaced with new DataArrays
            of summarized data and the indicated dimension(s) removed.
        rj  NzPpassing 'axis' to Dataset reduce methods is ambiguous. Please use 'dim' instead..c                   s   g | ]}| j kr|qS r   r>  rE  r
  r   r   r     s     
 z"Dataset.reduce.<locals>.<listcomp>r  Fr   c                   s   g | ]}| kr|qS r   r   rE  r>  r   r   r     s      r   )r   r  r  c                   s   h | ]}| kr|qS r   r   r  r  r   r   ri    s      z!Dataset.reduce.<locals>.<setcomp>c                   s   i | ]\}}| kr||qS r   r   rD  r  r   r   r     s       z"Dataset.reduce.<locals>.<dictcomp>r2  r.  r3  )r   r   r   r   r   r   r   rA   r  rB  r-  r   
issubdtyper   numberbool_r   r   reducer*  r.  r~  )r  r   r   r  r  r  rF  Zmissing_dimensionsr   r   reduce_dimsZreduce_maybe_singler2  r3  r.  r   r   r  r   r   r    sl    (



   zDataset.reducer   zIterable[Any])r  r   r  r   rF  r   c           	        sr   |dkrt dd} fdd| j D }|rT| D ]\}}|| j|  q:|r^| jnd}t| ||dS )ac  Apply a function to each data variable in this dataset

        Parameters
        ----------
        func : callable
            Function which can be called in the form `func(x, *args, **kwargs)`
            to transform each DataArray `x` in this dataset into another
            DataArray.
        keep_attrs : bool or None, optional
            If True, both the dataset's and variables' attributes (`attrs`) will be
            copied from the original objects to the new ones. If False, the new dataset
            and variables will be returned without copying the attributes.
        args : iterable, optional
            Positional arguments passed on to `func`.
        **kwargs : Any
            Keyword arguments passed on to `func`.

        Returns
        -------
        applied : Dataset
            Resulting dataset from applying ``func`` to each data variable.

        Examples
        --------
        >>> da = xr.DataArray(np.random.randn(2, 3))
        >>> ds = xr.Dataset({"foo": da, "bar": ("x", [-1, 2])})
        >>> ds
        <xarray.Dataset>
        Dimensions:  (dim_0: 2, dim_1: 3, x: 2)
        Dimensions without coordinates: dim_0, dim_1, x
        Data variables:
            foo      (dim_0, dim_1) float64 1.764 0.4002 0.9787 2.241 1.868 -0.9773
            bar      (x) int64 -1 2
        >>> ds.map(np.fabs)
        <xarray.Dataset>
        Dimensions:  (dim_0: 2, dim_1: 3, x: 2)
        Dimensions without coordinates: dim_0, dim_1, x
        Data variables:
            foo      (dim_0, dim_1) float64 1.764 0.4002 0.9787 2.241 1.868 0.9773
            bar      (x) float64 1.0 2.0
        NFr  c                   s(   i | ] \}}|t ||f qS r   )rQ   rD  r   r   rF  r   r   r   E  s    zDataset.map.<locals>.<dictcomp>r6  )rA   r,  rB  _copy_attrs_fromr.  rJ  )	r  r   r  r   rF  r   r  rA  r.  r   r  r   r    s    0
zDataset.mapc                 K  s"   t jdtdd | j|||f|S )zv
        Backward compatible implementation of ``map``

        See Also
        --------
        Dataset.map
        zNDataset.apply may be deprecated in the future. Using Dataset.map is encouragedr   ra  )r   r   r  r  )r  r   r  r   rF  r   r   r   applyO  s    zDataset.apply)r  r   variables_kwargsr   c                 K  s@   t ||d}|  }||}|jt|  || |S )az  Assign new data variables to a Dataset, returning a new object
        with all the original variables in addition to the new ones.

        Parameters
        ----------
        variables : mapping of hashable to Any
            Mapping from variables names to the new values. If the new values
            are callable, they are computed on the Dataset and assigned to new
            data variables. If the values are not callable, (e.g. a DataArray,
            scalar, or array), they are simply assigned.
        **variables_kwargs
            The keyword arguments form of ``variables``.
            One of variables or variables_kwargs must be provided.

        Returns
        -------
        ds : Dataset
            A new Dataset with the new variables in addition to all the
            existing variables.

        Notes
        -----
        Since ``kwargs`` is a dictionary, the order of your arguments may not
        be preserved, and so the order of the new variables is not well
        defined. Assigning multiple variables within the same ``assign`` is
        possible, but you cannot reference other variables created within the
        same ``assign`` call.

        See Also
        --------
        pandas.DataFrame.assign

        Examples
        --------
        >>> x = xr.Dataset(
        ...     {
        ...         "temperature_c": (
        ...             ("lat", "lon"),
        ...             20 * np.random.rand(4).reshape(2, 2),
        ...         ),
        ...         "precipitation": (("lat", "lon"), np.random.rand(4).reshape(2, 2)),
        ...     },
        ...     coords={"lat": [10, 20], "lon": [150, 160]},
        ... )
        >>> x
        <xarray.Dataset>
        Dimensions:        (lat: 2, lon: 2)
        Coordinates:
          * lat            (lat) int64 10 20
          * lon            (lon) int64 150 160
        Data variables:
            temperature_c  (lat, lon) float64 10.98 14.3 12.06 10.9
            precipitation  (lat, lon) float64 0.4237 0.6459 0.4376 0.8918

        Where the value is a callable, evaluated on dataset:

        >>> x.assign(temperature_f=lambda x: x.temperature_c * 9 / 5 + 32)
        <xarray.Dataset>
        Dimensions:        (lat: 2, lon: 2)
        Coordinates:
          * lat            (lat) int64 10 20
          * lon            (lon) int64 150 160
        Data variables:
            temperature_c  (lat, lon) float64 10.98 14.3 12.06 10.9
            precipitation  (lat, lon) float64 0.4237 0.6459 0.4376 0.8918
            temperature_f  (lat, lon) float64 51.76 57.75 53.7 51.62

        Alternatively, the same behavior can be achieved by directly referencing an existing dataarray:

        >>> x.assign(temperature_f=x["temperature_c"] * 9 / 5 + 32)
        <xarray.Dataset>
        Dimensions:        (lat: 2, lon: 2)
        Coordinates:
          * lat            (lat) int64 10 20
          * lon            (lon) int64 150 160
        Data variables:
            temperature_c  (lat, lon) float64 10.98 14.3 12.06 10.9
            precipitation  (lat, lon) float64 0.4237 0.6459 0.4376 0.8918
            temperature_f  (lat, lon) float64 51.76 57.75 53.7 51.62

        assign)rM   rs  Z_calc_assign_resultsr-  Z_maybe_drop_multiindex_coordsr   rp  r  )r  r   r  r   rd  r   r   r   r  d  s    V

zDataset.assign)r   r   r   c                   s   ddl m}  fdd jD }t| }tjdd |D dd}|f|d j }t|| jdd}d	d
  j	
 D }	t jt|	}
tt j|}||
|< |	|  |||	||
S )a  Convert this dataset into an xarray.DataArray

        The data variables of this dataset will be broadcast against each other
        and stacked along the first axis of the new array. All coordinates of
        this dataset will remain coordinates.

        Parameters
        ----------
        dim : Hashable, default: "variable"
            Name of the new dimension.
        name : Hashable or None, optional
            Name of the new data array.

        Returns
        -------
        array : xarray.DataArray
        r   r^   c                   s   g | ]} j | qS r   r  r  r
  r   r   r     s     z$Dataset.to_array.<locals>.<listcomp>c                 S  s   g | ]
}|j qS r   r   )r   r  r   r   r   r     s     rj  T)r  c                 S  s   i | ]\}}||j qS r   )r   rD  r   r   r   r     s      z$Dataset.to_array.<locals>.<dictcomp>)r   r_   r,  rU   r   r  r   rS   r.  r-  rB  r5   r*  r   r1   r   r  rN  rg  )r  r   r   r_   r,  Zbroadcast_varsr   r   r   r-  r3  Znew_dim_indexr   r
  r   to_array  s    zDataset.to_arrayzSequence[Hashable] | None)r  r   c                   sR   |dkrt  j}n(t|t jkr<td|t  j fdd|D }|S )a  
        Check the validity of the provided dimensions if any and return the mapping
        between dimension name and their size.

        Parameters
        ----------
        dim_order: Sequence of Hashable or None, optional
            Dimension order to validate (default to the alphabetical order if None).

        Returns
        -------
        result : dict[Hashable, int]
            Validated dimensions mapping.

        NzEdim_order {} does not match the set of dimensions of this Dataset: {}c                   s   i | ]}| j | qS r   r>  r  r
  r   r   r     s      z0Dataset._normalize_dim_order.<locals>.<dictcomp>)r   r   r   r   r  r  r  ordered_dimsr   r
  r   _normalize_dim_order  s     zDataset._normalize_dim_orderzpd.Series | pd.DataFramec                 C  sR   t | jdkr&tdd |  D S t | jdkr<|  S tdt | j dS )a<  Convert this dataset into a pandas object without changing the number of dimensions.

        The type of the returned object depends on the number of Dataset
        dimensions:

        * 0D -> `pandas.Series`
        * 1D -> `pandas.DataFrame`

        Only works for Datasets with 1 or fewer dimensions.
        r   c                 S  s   i | ]\}}||  qS r   )itemrD  r   r   r   r     s      z%Dataset.to_pandas.<locals>.<dictcomp>r   zcannot convert Datasets with %s dimensions into pandas objects without changing the number of dimensions. Please use Dataset.to_dataframe() instead.N)r   r   r   ZSeriesrB  to_dataframer   r
  r   r   r   	to_pandas  s    zDataset.to_pandaszMapping[Any, int]r  c                   sN   fddj D } fdd|D }j }tjtt|||dS )Nc                   s   g | ]}| j kr|qS r   r>  r  r
  r   r   r     s     
 z)Dataset._to_dataframe.<locals>.<listcomp>c                   s$   g | ]}j |  jd qS )r   )r  rs  r   reshaper  r  r  r   r   r     s   r  )r   r-  Zto_indexr   r|   r   r   )r  r  columnsr   r  r   r  r   _to_dataframe  s    zDataset._to_dataframezpd.DataFramec                 C  s   | j |d}| j|dS )a  Convert this dataset into a pandas.DataFrame.

        Non-index variables in this dataset form the columns of the
        DataFrame. The DataFrame is indexed by the Cartesian product of
        this dataset's indices.

        Parameters
        ----------
        dim_order: Sequence of Hashable or None, optional
            Hierarchical dimension order for the resulting dataframe. All
            arrays are transposed to this order and then written out as flat
            vectors in contiguous order, so the last dimension in this list
            will be contiguous in the resulting DataFrame. This has a major
            influence on which operations are efficient on the resulting
            dataframe.

            If provided, must include all dimensions of this dataset. By
            default, dimensions are sorted alphabetically.

        Returns
        -------
        result : DataFrame
            Dataset as a pandas DataFrame.

        r  r  )r  r  r  r   r   r   r  $  s    zDataset.to_dataframezpd.Indexz!list[tuple[Hashable, np.ndarray]]r   )r  arraysr   r   c              	   C  s   ddl m} t|tjrNtjdd |jD dd}|j}t	dd |j
D }n t|jdd	}d
}|jf}|D ]F\}}	t|	j\}
}tj|	|
d}	|||	|d||d}||f| |< qrd S )Nr   )COOc                 S  s   g | ]}t |qS r   r   r  )r   coder   r   r   r   I  s     z;Dataset._set_sparse_data_from_dataframe.<locals>.<listcomp>r  c                 s  s   | ]}|j V  qd S r   r  r   levr   r   r   r   K  s     z:Dataset._set_sparse_data_from_dataframe.<locals>.<genexpr>r   r   Tr  F)Zhas_duplicatesrq  r1  )r6  r  r   r   r  r   r  codesZis_monotonic_increasingr   r  aranger   r  xrdtypesmaybe_promoter   r  )r  r  r  r   r  r-  Z	is_sortedr   r   r   r   r1  r   r   r   r   _set_sparse_data_from_dataframeC  s(    z'Dataset._set_sparse_data_from_dataframec                 C  s   t |tjs*|D ]\}}||f| |< qd S tdd |jD }t|j}t||jd k}|D ]N\}}|rt	
|j\}	}
t||
|	}nt||j}|||< ||f| |< q`d S )Nc                 s  s   | ]}|j V  qd S r   r  r  r   r   r   r   o  s     z9Dataset._set_numpy_data_from_dataframe.<locals>.<genexpr>r   )r   r   r  r   r  r  r  r  r   r  r   r   r   fullr  )r  r  r  r   r   r   r   indexerZmissing_valuesr   r1  r   r   r   r   _set_numpy_data_from_dataframec  s    
z&Dataset._set_numpy_data_from_dataframe)r5  	dataframer6  r   c                 C  s   |j jstdt|j}t|tjr4|js4tddd | D }i }i }t|tjrt	dd t
|jD }t||jD ](\}}	t|	|}
|
||< ||
  q~n:|jdk	r|jnd}|f}t||}
|
||< ||
  | j|t||d	}|r|||| n|||| |S )
aU  Convert a pandas.DataFrame into an xarray.Dataset

        Each column will be converted into an independent variable in the
        Dataset. If the dataframe's index is a MultiIndex, it will be expanded
        into a tensor product of one-dimensional indices (filling in missing
        values with NaN). This method will produce a Dataset very similar to
        that on which the 'to_dataframe' method was called, except with
        possibly redundant dimensions (since all dataset variables will have
        the same dimensionality)

        Parameters
        ----------
        dataframe : DataFrame
            DataFrame from which to copy data and indices.
        sparse : bool, default: False
            If true, create a sparse arrays instead of dense numpy arrays. This
            can potentially save a large amount of memory if the DataFrame has
            a MultiIndex. Requires the sparse package (sparse.pydata.org).

        Returns
        -------
        New Dataset.

        See Also
        --------
        xarray.DataArray.from_series
        pandas.DataFrame.to_xarray
        z0cannot convert DataFrame with non-unique columnszCcannot convert a DataFrame with a non-unique MultiIndex into xarrayc                 S  s   g | ]\}}|t |fqS r   r  rD  r   r   r   r     s     z*Dataset.from_dataframe.<locals>.<listcomp>c                 s  s&   | ]\}}|d k	r|nd| V  qd S )Nzlevel_%ir   )r   r@  r   r   r   r   r     s   z)Dataset.from_dataframe.<locals>.<genexpr>Nr  r  )r  Z	is_uniquer   r7   r  r   r   r  rB  r   	enumerater  r   r  r1   r  rN  r   rg  r   r  r  )r5  r  r6  r  r  r3  r  r   r   r  Zxr_idxZ
index_namer   r   r   r   from_dataframe  s8    $


zDataset.from_dataframeDaskDataFrame)r  rv  r   c              	     s:  ddl m} ddlm}  j|d}t|}| fdd jD  | j g }|D ]}z j	| }	W n< t
k
r    j| }
|j|
|
tjd}t|f|}	Y nX t|	tr|	 }	|	| jj}|j|d|gd}|| qZ|j|d	d
}|r6|}t|d	kr,|\}||}n
||}|S )ap  
        Convert this dataset into a dask.dataframe.DataFrame.

        The dimensions, coordinates and data variables in this dataset form
        the columns of the DataFrame.

        Parameters
        ----------
        dim_order : list, optional
            Hierarchical dimension order for the resulting dataframe. All
            arrays are transposed to this order and then written out as flat
            vectors in contiguous order, so the last dimension in this list
            will be contiguous in the resulting DataFrame. This has a major
            influence on which operations are efficient on the resulting dask
            dataframe.

            If provided, must include all dimensions of this dataset. By
            default, dimensions are sorted alphabetically.
        set_index : bool, default: False
            If set_index=True, the dask DataFrame is indexed by this dataset's
            coordinate. Since dask DataFrames do not support multi-indexes,
            set_index only works if the dataset only contains one dimension.

        Returns
        -------
        dask.dataframe.DataFrame
        r   Nr  c                 3  s   | ]}| j kr|V  qd S r   r>  r  r
  r   r   r     s     
 z,Dataset.to_dask_dataframe.<locals>.<genexpr>)r   r   r   )r  r   r  )r   r   dask.dataframer  r  r   extendr-  r,  r   r   r   r  r   r  rS   r   rR   r  rs  r   r   r   Z
from_arrayr  r  r  r   rv  )r  r  rv  r   ddr  r  Zseries_listr   r   r   r   Z
dask_arrayZseriesZdfr   r   r
  r   to_dask_dataframe  s6    


zDataset.to_dask_dataframe)r   r   r   c                 C  s   i t | jt| ji d}| jD ]&}|d || | jj||di q | jD ]&}|d || | jj||di qN|rt| j	|d< |S )aZ  
        Convert this dataset to a dictionary following xarray naming
        conventions.

        Converts all variables and attributes to native Python objects
        Useful for converting to json. To avoid datetime incompatibility
        use decode_times=False kwarg in xarrray.open_dataset.

        Parameters
        ----------
        data : bool, default: True
            Whether to include the actual data in the dictionary. When set to
            False, returns just the schema.
        encoding : bool, default: False
            Whether to include the Dataset's encoding in the dictionary.

        Returns
        -------
        d : dict
            Dict with keys: "coords", "attrs", "dims", "data_vars" and optionally
            "encoding".

        See Also
        --------
        Dataset.from_dict
        DataArray.to_dict
        )r-  r.  r   r,  r-  )r   r   r,  r   )
rK   r.  r   r   r-  r  r   to_dictr,  r   )r  r   r   rF  r  r   r   r   r     s     

zDataset.to_dict)r5  rF  r   c              
   C  s   ddh t|s| }n,ddl}||di  |di  }zdd |D }W n< tk
r } ztdjt	|j
d dW 5 d}~X Y nX | |}t|di t|d	i  }||}|j|d
i  |j|di  |S )a  Convert a dictionary into an xarray.Dataset.

        Parameters
        ----------
        d : dict-like
            Mapping with a minimum structure of
                ``{"var_0": {"dims": [..], "data": [..]},                             ...}``

        Returns
        -------
        obj : Dataset

        See also
        --------
        Dataset.to_dict
        DataArray.from_dict

        Examples
        --------
        >>> d = {
        ...     "t": {"dims": ("t"), "data": [0, 1, 2]},
        ...     "a": {"dims": ("t"), "data": ["a", "b", "c"]},
        ...     "b": {"dims": ("t"), "data": [10, 20, 30]},
        ... }
        >>> ds = xr.Dataset.from_dict(d)
        >>> ds
        <xarray.Dataset>
        Dimensions:  (t: 3)
        Coordinates:
          * t        (t) int64 0 1 2
        Data variables:
            a        (t) <U1 'a' 'b' 'c'
            b        (t) int64 10 20 30

        >>> d = {
        ...     "coords": {
        ...         "t": {"dims": "t", "data": [0, 1, 2], "attrs": {"units": "s"}}
        ...     },
        ...     "attrs": {"title": "air temperature"},
        ...     "dims": "t",
        ...     "data_vars": {
        ...         "a": {"dims": "t", "data": [10, 20, 30]},
        ...         "b": {"dims": "t", "data": ["a", "b", "c"]},
        ...     },
        ... }
        >>> ds = xr.Dataset.from_dict(d)
        >>> ds
        <xarray.Dataset>
        Dimensions:  (t: 3)
        Coordinates:
          * t        (t) int64 0 1 2
        Data variables:
            a        (t) int64 10 20 30
            b        (t) <U1 'a' 'b' 'c'
        Attributes:
            title:    air temperature

        r-  r,  r   Nc                 S  s*   i | ]"\}}||d  |d | dfqS )r   r   r.  r   rD  r   r   r   r     s     z%Dataset.from_dict.<locals>.<dictcomp>z1cannot convert dict without the key '{dims_data}')Z	dims_datar   r.  r   )issubsetr   rB  r   chainr   r   r   r  r   r   r  r.  r  r   )r5  rF  r   r   Zvariable_dictr  r   r-  r   r   r   	from_dictN  s.    ?
 
 
zDataset.from_dictc           	      O  s   i }| dd }|d kr"tdd}| j D ]@\}}|| jkrH|||< q,||f||||< |r,|j|| _q,|rx| jnd }| j||dS )Nr  Tr  r6  )r  rA   r  rB  r  r%  r.  r~  )	r  fr   rF  r   r  r  rA  r.  r   r   r   	_unary_op  s    


zDataset._unary_opc           
        s   ddl m} ddlm} t||r&tS |d kr6td n|}t||tfr\t| ||dd\} }|sd n
 fdd}| j	|||d	}	|	S )
Nr   r^   GroupByZarithmetic_joinFr  c                   s
    || S r   r   r  r  r   r   <lambda>      z$Dataset._binary_op.<locals>.<lambda>)r  )
r   r_   xarray.core.groupbyr  r   NotImplementedr@   r   r%   _calculate_binary_op)
r  r  r  Z	reflexiver  r_   r  Z
align_typegrS  r   r  r   
_binary_op  s    
zDataset._binary_opc                 C  s   ddl m} ddlm} t||r*tdt||tfrF|j| dd}t	|}| j
||dd}| j|j|j|j|jdd	 | S )
Nr   r^   r  zLin-place operations between a Dataset and a grouped object are not permittedFr  Tr|  )r.  r3  rz  )r   r_   r  r  r   r   r   r9  r    Zinplace_to_noninplace_opr  r~  r  r  r%  r*  )r  r  r  r_   r  r  rS  r   r   r   _inplace_binary_op  s$    

zDataset._inplace_binary_opinner)rz  r   c           
        s    fdd}t |rBt|tsB|j|j|}t|S t|dd }j|}t|tr||j|jj	|j	}	n$t|d| fddjD }	|j
|	 t|j
|_|S )Nc                   s   r0t | t |kr0tdt|  dt| i }| D ]@}||kr\ || || ||< q8dkr8 || tj||< q8|D ](}||kr~dkr~ || tj||< q~|S )NzOdatasets must have the same data variables for in-place arithmetic operations: r  )leftr-  )rightr-  )r   r   r   r   nan)Zlhs_data_varsZrhs_data_varsZlhs_varsZrhs_varsZ	dest_varsr  )r  rz  r  r   r   apply_over_both  s    z5Dataset._calculate_binary_op.<locals>.apply_over_bothr-  r   c                   s   i | ]}| j | qS r   r  r  )r  other_variabler  r   r   r     s      z0Dataset._calculate_binary_op.<locals>.<dictcomp>)r!   rO   r   r   r,  rJ  r   r-  rQ  r   r  r  rV   r'  )
r  r  r  r  rz  r"  Znew_data_varsZother_coordsrS  Znew_varsr   )r  rz  r  r#  r  r   r    s.       
   zDataset._calculate_binary_opc                 C  s6   |j | _ |jD ]"}|| jkr|j| j | j| _ qd S r   )r.  r   )r  r  rA  r   r   r   r  	  s    

zDataset._copy_attrs_fromr   upperzLiteral[('upper', 'lower')])r  r   r@  labelr   c                 C  s  |dkr| S |dk r"t d| |tddi}|tddi}|dkrL|}n|dkrZ|}nt dt| j|\}}i }	| j D ]d\}
}|
|kr||
 |	|
< q||jkr|
| jkr|||| |	|
< q|||	|
< q||	|
< q| j	|	|d	}|dkr|
||d S |S dS )
a"  Calculate the n-th order discrete difference along given axis.

        Parameters
        ----------
        dim : Hashable
            Dimension over which to calculate the finite difference.
        n : int, default: 1
            The number of times values are differenced.
        label : {"upper", "lower"}, default: "upper"
            The new coordinate in dimension ``dim`` will have the
            values of either the minuend's or subtrahend's coordinate
            for values 'upper' and 'lower', respectively.

        Returns
        -------
        difference : Dataset
            The n-th order finite difference of this object.

        Notes
        -----
        `n` matches numpy's behavior and is different from pandas' first argument named
        `periods`.

        Examples
        --------
        >>> ds = xr.Dataset({"foo": ("x", [5, 5, 6, 6])})
        >>> ds.diff("x")
        <xarray.Dataset>
        Dimensions:  (x: 3)
        Dimensions without coordinates: x
        Data variables:
            foo      (x) int64 0 1 0
        >>> ds.diff("x", 2)
        <xarray.Dataset>
        Dimensions:  (x: 2)
        Dimensions without coordinates: x
        Data variables:
            foo      (x) int64 1 -1

        See Also
        --------
        Dataset.differentiate
        r   z'order `n` must be non-negative but got Nr   r   r$  lowerz8The 'label' argument has to be either 'upper' or 'lower'r  )r   r  r6   r  r   rB  r   r,  r  r~  diff)r  r   r@  r%  Zslice_startZ	slice_endZ	slice_newr3  r  r   r   r   r   r   r   r   r'    s2    1



zDataset.diffzMapping[Any, int] | None)r  shiftsr1  shifts_kwargsr   c           	        s   t ||d} fdd|D }|r2td|di } j D ]`\}| jkrt|trj||tj	n|}fdd| D }j
||d||< q@||< q@ |S )	a  Shift this dataset by an offset along one or more dimensions.

        Only data variables are moved; coordinates stay in place. This is
        consistent with the behavior of ``shift`` in pandas.

        Values shifted from beyond array bounds will appear at one end of
        each dimension, which are filled according to `fill_value`. For periodic
        offsets instead see `roll`.

        Parameters
        ----------
        shifts : mapping of hashable to int
            Integer offset to shift along each of the given dimensions.
            Positive offsets shift to the right; negative offsets shift to the
            left.
        fill_value : scalar or dict-like, optional
            Value to use for newly missing values. If a dict-like, maps
            variable names (including coordinates) to fill values.
        **shifts_kwargs
            The keyword arguments form of ``shifts``.
            One of shifts or shifts_kwargs must be provided.

        Returns
        -------
        shifted : Dataset
            Dataset with the same coordinates and attributes but shifted data
            variables.

        See Also
        --------
        roll

        Examples
        --------
        >>> ds = xr.Dataset({"foo": ("x", list("abcde"))})
        >>> ds.shift(x=2)
        <xarray.Dataset>
        Dimensions:  (x: 5)
        Dimensions without coordinates: x
        Data variables:
            foo      (x) object nan nan 'a' 'b' 'c'
        shiftc                   s   g | ]}| j kr|qS r   r>  r  r
  r   r   r     s     
 z!Dataset.shift.<locals>.<listcomp>dimensions  do not existc                   s    i | ]\}}| j kr||qS r   r>  rD  r  r   r   r     s     
  z!Dataset.shift.<locals>.<dictcomp>)r1  r(  )rM   r   r   rB  r,  r   r   r   r  NAr*  r{  )	r  r(  r1  r)  invalidr   r   r  Z
var_shiftsr   r  r   r   r*  f  s    1

zDataset.shift)r  r(  roll_coordsr)  r   c           
        s   t ||d} fdd|D }|r2td|d|rLt j|\}}d}n t j}t jj}t j}i } j	 D ]R\}	|	|kr||	 ||	< qz|	|krĈj
fdd|	 D d	||	< qz||	< qz j||d
S )a  Roll this dataset by an offset along one or more dimensions.

        Unlike shift, roll treats the given dimensions as periodic, so will not
        create any missing values to be filled.

        Also unlike shift, roll may rotate all variables, including coordinates
        if specified. The direction of rotation is consistent with
        :py:func:`numpy.roll`.

        Parameters
        ----------
        shifts : mapping of hashable to int, optional
            A dict with keys matching dimensions and values given
            by integers to rotate each of the given dimensions. Positive
            offsets roll to the right; negative offsets roll to the left.
        roll_coords : bool, default: False
            Indicates whether to roll the coordinates by the offset too.
        **shifts_kwargs : {dim: offset, ...}, optional
            The keyword arguments form of ``shifts``.
            One of shifts or shifts_kwargs must be provided.

        Returns
        -------
        rolled : Dataset
            Dataset with the same attributes but rolled data and coordinates.

        See Also
        --------
        shift

        Examples
        --------
        >>> ds = xr.Dataset({"foo": ("x", list("abcde"))}, coords={"x": np.arange(5)})
        >>> ds.roll(x=2)
        <xarray.Dataset>
        Dimensions:  (x: 5)
        Coordinates:
          * x        (x) int64 0 1 2 3 4
        Data variables:
            foo      (x) <U1 'd' 'e' 'a' 'b' 'c'

        >>> ds.roll(x=2, roll_coords=True)
        <xarray.Dataset>
        Dimensions:  (x: 5)
        Coordinates:
          * x        (x) int64 3 4 0 1 2
        Data variables:
            foo      (x) <U1 'd' 'e' 'a' 'b' 'c'

        rollc                   s   g | ]}| j kr|qS r   r>  r  r
  r   r   r     s     
 z Dataset.roll.<locals>.<listcomp>r+  r,  r   c                   s    i | ]\}}| j kr||qS r   r>  )r   r  sr  r   r   r     s     
  z Dataset.roll.<locals>.<dictcomp>)r(  r  )rM   r   r8   r  r   r*  r   r   r-  rB  r1  r{  )
r  r(  r0  r)  r.  r3  r  Zunrolled_varsr   r  r   r/  r   r1    s(    8


zDataset.rollz1Hashable | DataArray | list[Hashable | DataArray])r  r   	ascendingr   c                   s   ddl m  t|ts|g}n|} fdd|D }tf|ddi}|d }|dd }tt}|D ],}|jdkrtd	|j\}	||	 	| qji }
|
 D ]4\}	}ttt|}|r|n|ddd
 |
|	< q||
S )a  
        Sort object by labels or values (along an axis).

        Sorts the dataset, either along specified dimensions,
        or according to values of 1-D dataarrays that share dimension
        with calling object.

        If the input variables are dataarrays, then the dataarrays are aligned
        (via left-join) to the calling object prior to sorting by cell values.
        NaNs are sorted to the end, following Numpy convention.

        If multiple sorts along the same dimension is
        given, numpy's lexsort is performed along that dimension:
        https://numpy.org/doc/stable/reference/generated/numpy.lexsort.html
        and the FIRST key in the sequence is used as the primary sort key,
        followed by the 2nd key, etc.

        Parameters
        ----------
        variables : Hashable, DataArray, or list of hashable or DataArray
            1D DataArray objects or name(s) of 1D variable(s) in
            coords/data_vars whose values are used to sort the dataset.
        ascending : bool, default: True
            Whether to sort by ascending or descending order.

        Returns
        -------
        sorted : Dataset
            A new dataset where all the specified dims are sorted by dim
            labels.

        See Also
        --------
        DataArray.sortby
        numpy.sort
        pandas.sort_values
        pandas.sort_index

        Examples
        --------
        >>> ds = xr.Dataset(
        ...     {
        ...         "A": (("x", "y"), [[1, 2], [3, 4]]),
        ...         "B": (("x", "y"), [[5, 6], [7, 8]]),
        ...     },
        ...     coords={"x": ["b", "a"], "y": [1, 0]},
        ... )
        >>> ds = ds.sortby("x")
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 2, y: 2)
        Coordinates:
          * x        (x) <U1 'a' 'b'
          * y        (y) int64 1 0
        Data variables:
            A        (x, y) int64 3 4 1 2
            B        (x, y) int64 7 8 5 6
        r   r^   c                   s"   g | ]}t | r|n| qS r   r  rV  r_   r  r   r   r   E  s     z"Dataset.sortby.<locals>.<listcomp>r  r  r   NzInput DataArray is not 1-D.r   )r   r_   r   r   r%   r   r   r   r   r  rB  r   Zlexsortr   reversedr  )r  r   r3  r  Zaligned_varsZaligned_selfZaligned_other_varsZvars_by_dimr  r   indicesr  r   r4  r   rL     s&    ?

zDataset.sortbyrX   rD   zQuantileMethods | None)	r  qr   r  r  r  skipnainterpolationr   c                   s  |dk	r(t dt |dkr$td|}t|tr:|h n$|dksJ|dkrVtj nt| tt	fdd D d t
j|t
jd	}i j D ]x\}}	 fd
d|	jD }
|
s|	js|jkr|rt
|	jt
js|	jt
jkr|	j||
|||d|< q|	|< qfddjD }fddj D }|dkrRtdd}|r^jnd}j|||d}|j|dS )a  Compute the qth quantile of the data along the specified dimension.

        Returns the qth quantiles(s) of the array elements for each variable
        in the Dataset.

        Parameters
        ----------
        q : float or array-like of float
            Quantile to compute, which must be between 0 and 1 inclusive.
        dim : str or Iterable of Hashable, optional
            Dimension(s) over which to apply quantile.
        method : str, default: "linear"
            This optional parameter specifies the interpolation method to use when the
            desired quantile lies between two data points. The options sorted by their R
            type as summarized in the H&F paper [1]_ are:

                1. "inverted_cdf" (*)
                2. "averaged_inverted_cdf" (*)
                3. "closest_observation" (*)
                4. "interpolated_inverted_cdf" (*)
                5. "hazen" (*)
                6. "weibull" (*)
                7. "linear"  (default)
                8. "median_unbiased" (*)
                9. "normal_unbiased" (*)

            The first three methods are discontiuous.  The following discontinuous
            variations of the default "linear" (7.) option are also available:

                * "lower"
                * "higher"
                * "midpoint"
                * "nearest"

            See :py:func:`numpy.quantile` or [1]_ for details. The "method" argument
            was previously called "interpolation", renamed in accordance with numpy
            version 1.22.0.

            (*) These methods require numpy version 1.22 or newer.

        keep_attrs : bool, optional
            If True, the dataset's attributes (`attrs`) will be copied from
            the original object to the new one.  If False (default), the new
            object will be returned without attributes.
        numeric_only : bool, optional
            If True, only apply ``func`` to variables with a numeric dtype.
        skipna : bool, optional
            If True, skip missing values (as marked by NaN). By default, only
            skips missing values for float dtypes; other dtypes either do not
            have a sentinel missing value (int) or skipna=True has not been
            implemented (object, datetime64 or timedelta64).

        Returns
        -------
        quantiles : Dataset
            If `q` is a single quantile, then the result is a scalar for each
            variable in data_vars. If multiple percentiles are given, first
            axis of the result corresponds to the quantile and a quantile
            dimension is added to the return Dataset. The other dimensions are
            the dimensions that remain after the reduction of the array.

        See Also
        --------
        numpy.nanquantile, numpy.quantile, pandas.Series.quantile, DataArray.quantile

        Examples
        --------
        >>> ds = xr.Dataset(
        ...     {"a": (("x", "y"), [[0.7, 4.2, 9.4, 1.5], [6.5, 7.3, 2.6, 1.9]])},
        ...     coords={"x": [7, 9], "y": [1, 1.5, 2, 2.5]},
        ... )
        >>> ds.quantile(0)  # or ds.quantile(0, dim=...)
        <xarray.Dataset>
        Dimensions:   ()
        Coordinates:
            quantile  float64 0.0
        Data variables:
            a         float64 0.7
        >>> ds.quantile(0, dim="x")
        <xarray.Dataset>
        Dimensions:   (y: 4)
        Coordinates:
          * y         (y) float64 1.0 1.5 2.0 2.5
            quantile  float64 0.0
        Data variables:
            a         (y) float64 0.7 4.2 2.6 1.5
        >>> ds.quantile([0, 0.5, 1])
        <xarray.Dataset>
        Dimensions:   (quantile: 3)
        Coordinates:
          * quantile  (quantile) float64 0.0 0.5 1.0
        Data variables:
            a         (quantile) float64 0.7 3.4 9.4
        >>> ds.quantile([0, 0.5, 1], dim="x")
        <xarray.Dataset>
        Dimensions:   (quantile: 3, y: 4)
        Coordinates:
          * y         (y) float64 1.0 1.5 2.0 2.5
          * quantile  (quantile) float64 0.0 0.5 1.0
        Data variables:
            a         (quantile, y) float64 0.7 4.2 2.6 1.5 3.6 ... 1.7 6.5 7.3 9.4 1.9

        References
        ----------
        .. [1] R. J. Hyndman and Y. Fan,
           "Sample quantiles in statistical packages,"
           The American Statistician, 50(4), pp. 361-365, 1996
        NzAThe `interpolation` argument to quantile was renamed to `method`.r=  z.Cannot pass interpolation and method keywords!.c                 3  s   | ]}| j kr|V  qd S r   r>  rE  r
  r   r   r     s     
 z#Dataset.quantile.<locals>.<genexpr>z+Dataset does not contain the dimensions: %sr  c                   s   g | ]}| kr|qS r   r   rE  r>  r   r   r     s      z$Dataset.quantile.<locals>.<listcomp>)r   r  r  r8  c                   s   h | ]}| kr|qS r   r   r  r  r   r   ri    s      z#Dataset.quantile.<locals>.<setcomp>c                   s   i | ]\}}| kr||qS r   r   rD  r  r   r   r      s       z$Dataset.quantile.<locals>.<dictcomp>Fr  r  )quantile)r   r   r  r   r   r   r   r   r   r   r   r  float64r   rB  r-  r  r   r  r  r:  r*  rA   r.  r~  r  )r  r7  r   r  r  r  r8  r9  r   r   r  r2  r3  r.  ru  r   r  r   r:  V  sb    y

	


   zDataset.quantile)r  r   pctr  r   c           	      C  s   t d std|| jkr(td| i }| j D ]8\}}|| jkrf||jkrn|j||d||< q6|||< q6t| j	}|dkrt
dd}|r| jnd}| j|||dS )	a  Ranks the data.

        Equal values are assigned a rank that is the average of the ranks that
        would have been otherwise assigned to all of the values within
        that set.
        Ranks begin at 1, not 0. If pct is True, computes percentage ranks.

        NaNs in the input array are returned as NaNs.

        The `bottleneck` library is required.

        Parameters
        ----------
        dim : Hashable
            Dimension over which to compute rank.
        pct : bool, default: False
            If True, compute percentage ranks, otherwise compute integer ranks.
        keep_attrs : bool or None, optional
            If True, the dataset's attributes (`attrs`) will be copied from
            the original object to the new one.  If False, the new
            object will be returned without attributes.

        Returns
        -------
        ranked : Dataset
            Variables that do not depend on `dim` are dropped.
        Zuse_bottleneckz`rank requires bottleneck to be enabled. Call `xr.set_options(use_bottleneck=True)` to enable it.z(Dataset does not contain the dimension: )r<  NFr  r6  )r@   r  r   r   r   rB  r,  rankr   r-  rA   r.  r{  )	r  r   r<  r  r   r   r   r2  r.  r   r   r   r=  	  s"    !





zDataset.rankzLiteral[(1, 2)]zDatetimeUnitOptions | None)r  coord
edge_orderdatetime_unitr   c                 C  s<  ddl m} || jkr0|| jkr0td| d| | j}|jdkrVtd||j|jd }t|r|j	j
dkr|dkrtd	t|j	d }n|dkrd
}|j|d}i }| j D ]v\}}	|| jkr(||	jkr(|| jkr(t|	r|	j|d}	tj|	j|j||	|d}
||	j|
||< q|	||< q| |S )a*   Differentiate with the second order accurate central
        differences.

        .. note::
            This feature is limited to simple cartesian geometry, i.e. coord
            must be one dimensional.

        Parameters
        ----------
        coord : Hashable
            The coordinate to be used to compute the gradient.
        edge_order : {1, 2}, default: 1
            N-th order accurate differences at the boundaries.
        datetime_unit : None or {"Y", "M", "W", "D", "h", "m", "s", "ms",             "us", "ns", "ps", "fs", "as", None}, default: None
            Unit to compute gradient. Only valid for datetime coordinate.

        Returns
        -------
        differentiated: Dataset

        See also
        --------
        numpy.gradient: corresponding numpy function
        r   rS   Coordinate  does not exist.r   9Coordinate {} must be 1 dimensional but is {} dimensionalmMNrl   r2  r@  )r?  rj  )xarray.core.variablerS   r   r   r   r   r   r  r(   r   r   r   r   datetime_dataZ_to_numericrB  r,  r-  r   Zgradientr   get_axis_numr{  )r  r>  r?  r@  rS   	coord_varr   r   r  rA  Zgradr   r   r   differentiateA  sF    

 
 $
zDataset.differentiaterl   )r  r>  r@  r   c                 C  s4   t |ttfs|f}| }|D ]}|j||d}q|S )a  Integrate along the given coordinate using the trapezoidal rule.

        .. note::
            This feature is limited to simple cartesian geometry, i.e. coord
            must be one dimensional.

        Parameters
        ----------
        coord : hashable, or sequence of hashable
            Coordinate(s) used for the integration.
        datetime_unit : {'Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns',                         'ps', 'fs', 'as', None}, optional
            Specify the unit if datetime coordinate is used.

        Returns
        -------
        integrated : Dataset

        See also
        --------
        DataArray.integrate
        numpy.trapz : corresponding numpy function

        Examples
        --------
        >>> ds = xr.Dataset(
        ...     data_vars={"a": ("x", [5, 5, 6, 6]), "b": ("x", [1, 2, 1, 0])},
        ...     coords={"x": [0, 1, 2, 3], "y": ("x", [1, 7, 3, 5])},
        ... )
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 4)
        Coordinates:
          * x        (x) int64 0 1 2 3
            y        (x) int64 1 7 3 5
        Data variables:
            a        (x) int64 5 5 6 6
            b        (x) int64 1 2 1 0
        >>> ds.integrate("x")
        <xarray.Dataset>
        Dimensions:  ()
        Data variables:
            a        float64 16.5
            b        float64 3.5
        >>> ds.integrate("y")
        <xarray.Dataset>
        Dimensions:  ()
        Data variables:
            a        float64 20.0
            b        float64 4.0
        rF  r   r   r   _integrate_oner  r>  r@  r  rt  r   r   r   	integrate  s    8zDataset.integratec                   s  ddl m} || jkr0|| jkr0td| d| | j}|jdkrVtd||j|jd }t|r|j	j
dkr|d krt|j	\}}n|d krd}|jt|j|d	d
}i  t }| j D ]\}	}
|	| jkr||
jks|r|
 |	< ||	 q|	| jkr||
jkrt|
r&t|
|d	}
|rNtj|
j|j|
|d}|
j}n.tj|
j|j|
|d}t|
j}|| ||| |	< q|
 |	< qć fdd| j D }| j ||dS )Nr   rA  rB  rC  r   rD  rE  r2  rF  r  r  c                   s   i | ]\}}| kr||qS r   r   rD  r  r   r   r     s       z*Dataset._integrate_one.<locals>.<dictcomp>rp  )rG  rS   r   r   r   r   r   r  r(   r   r   r   rH  r{  r.   r   r   rB  r-  r  r,  r   Zcumulative_trapezoidrI  Ztrapzr   r  r*  r~  )r  r>  r@  
cumulativerS   rJ  r   r4  r2  r  rA  ZintegZv_dimsr3  r   r  r   rM    sh    

 


    


  zDataset._integrate_onec                 C  s6   t |ttfs|f}| }|D ]}|j||dd}q|S )a  Integrate along the given coordinate using the trapezoidal rule.

        .. note::
            This feature is limited to simple cartesian geometry, i.e. coord
            must be one dimensional.

            The first entry of the cumulative integral of each variable is always 0, in
            order to keep the length of the dimension unchanged between input and
            output.

        Parameters
        ----------
        coord : hashable, or sequence of hashable
            Coordinate(s) used for the integration.
        datetime_unit : {'Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns',                         'ps', 'fs', 'as', None}, optional
            Specify the unit if datetime coordinate is used.

        Returns
        -------
        integrated : Dataset

        See also
        --------
        DataArray.cumulative_integrate
        scipy.integrate.cumulative_trapezoid : corresponding scipy function

        Examples
        --------
        >>> ds = xr.Dataset(
        ...     data_vars={"a": ("x", [5, 5, 6, 6]), "b": ("x", [1, 2, 1, 0])},
        ...     coords={"x": [0, 1, 2, 3], "y": ("x", [1, 7, 3, 5])},
        ... )
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 4)
        Coordinates:
          * x        (x) int64 0 1 2 3
            y        (x) int64 1 7 3 5
        Data variables:
            a        (x) int64 5 5 6 6
            b        (x) int64 1 2 1 0
        >>> ds.cumulative_integrate("x")
        <xarray.Dataset>
        Dimensions:  (x: 4)
        Coordinates:
          * x        (x) int64 0 1 2 3
            y        (x) int64 1 7 3 5
        Data variables:
            a        (x) float64 0.0 5.0 10.5 16.5
            b        (x) float64 0.0 1.5 3.0 3.5
        >>> ds.cumulative_integrate("y")
        <xarray.Dataset>
        Dimensions:  (x: 4)
        Coordinates:
          * x        (x) int64 0 1 2 3
            y        (x) int64 1 7 3 5
        Data variables:
            a        (x) float64 0.0 30.0 8.0 20.0
            b        (x) float64 0.0 9.0 3.0 4.0
        T)r@  rP  rL  rN  r   r   r   cumulative_integrate  s    B  zDataset.cumulative_integratec                 C  s   | j dd ddS )zt
        The real part of each data variable.

        See Also
        --------
        numpy.ndarray.real
        c                 S  s   | j S r   )realr   r   r   r   r  N  r  zDataset.real.<locals>.<lambda>Tr  r  r
  r   r   r   rR  E  s    	zDataset.realc                 C  s   | j dd ddS )zy
        The imaginary part of each data variable.

        See Also
        --------
        numpy.ndarray.imag
        c                 S  s   | j S r   )imagrS  r   r   r   r  Y  r  zDataset.imag.<locals>.<lambda>TrT  rU  r
  r   r   r   rV  P  s    	zDataset.imagc           	      K  sz   g }| j  D ]b\}}d}| D ]:\}}|j|}t|rF||sN||krTd}q"d} q^q"|dkr|| q| | S )a  Returns a ``Dataset`` with variables that match specific conditions.

        Can pass in ``key=value`` or ``key=callable``.  A Dataset is returned
        containing only the variables for which all the filter tests pass.
        These tests are either ``key=value`` for which the attribute ``key``
        has the exact value ``value`` or the callable passed into
        ``key=callable`` returns True. The callable will be passed a single
        value, either the value of the attribute ``key`` or ``None`` if the
        DataArray does not have an attribute with the name ``key``.

        Parameters
        ----------
        **kwargs
            key : str
                Attribute name.
            value : callable or obj
                If value is a callable, it should return a boolean in the form
                of bool = func(attr) where attr is da.attrs[key].
                Otherwise, value will be compared to the each
                DataArray's attrs[key].

        Returns
        -------
        new : Dataset
            New dataset with variables filtered by attribute.

        Examples
        --------
        >>> temp = 15 + 8 * np.random.randn(2, 2, 3)
        >>> precip = 10 * np.random.rand(2, 2, 3)
        >>> lon = [[-99.83, -99.32], [-99.79, -99.23]]
        >>> lat = [[42.25, 42.21], [42.63, 42.59]]
        >>> dims = ["x", "y", "time"]
        >>> temp_attr = dict(standard_name="air_potential_temperature")
        >>> precip_attr = dict(standard_name="convective_precipitation_flux")

        >>> ds = xr.Dataset(
        ...     dict(
        ...         temperature=(dims, temp, temp_attr),
        ...         precipitation=(dims, precip, precip_attr),
        ...     ),
        ...     coords=dict(
        ...         lon=(["x", "y"], lon),
        ...         lat=(["x", "y"], lat),
        ...         time=pd.date_range("2014-09-06", periods=3),
        ...         reference_time=pd.Timestamp("2014-09-05"),
        ...     ),
        ... )

        Get variables matching a specific standard_name:

        >>> ds.filter_by_attrs(standard_name="convective_precipitation_flux")
        <xarray.Dataset>
        Dimensions:         (x: 2, y: 2, time: 3)
        Coordinates:
            lon             (x, y) float64 -99.83 -99.32 -99.79 -99.23
            lat             (x, y) float64 42.25 42.21 42.63 42.59
          * time            (time) datetime64[ns] 2014-09-06 2014-09-07 2014-09-08
            reference_time  datetime64[ns] 2014-09-05
        Dimensions without coordinates: x, y
        Data variables:
            precipitation   (x, y, time) float64 5.68 9.256 0.7104 ... 7.992 4.615 7.805

        Get all variables that have a standard_name attribute:

        >>> standard_name = lambda v: v is not None
        >>> ds.filter_by_attrs(standard_name=standard_name)
        <xarray.Dataset>
        Dimensions:         (x: 2, y: 2, time: 3)
        Coordinates:
            lon             (x, y) float64 -99.83 -99.32 -99.79 -99.23
            lat             (x, y) float64 42.25 42.21 42.63 42.59
          * time            (time) datetime64[ns] 2014-09-06 2014-09-07 2014-09-08
            reference_time  datetime64[ns] 2014-09-05
        Dimensions without coordinates: x, y
        Data variables:
            temperature     (x, y, time) float64 29.11 18.2 22.83 ... 18.28 16.15 26.63
            precipitation   (x, y, time) float64 5.68 9.256 0.7104 ... 7.992 4.615 7.805

        FT)r   rB  r.  r   callabler  )	r  rF  Z	selectionr   r   Zhas_value_flag	attr_namepattern
attr_valuer   r   r   filter_by_attrs]  s    QzDataset.filter_by_attrsc                 C  s   t | d S )zUnify chunk size along all chunked dimensions of this Dataset.

        Returns
        -------
        Dataset with consistent chunk sizes for all dask-array variables

        See Also
        --------
        dask.array.core.unify_chunks
        r   r*   r
  r   r   r   r+     s    zDataset.unify_chunkszCallable[..., T_Xarray]zSequence[Any]zDataArray | Dataset | Nonerx   )r   r   rF  templater   c                 C  s   ddl m} ||| |||S )aw  
        Apply a function to each block of this Dataset.

        .. warning::
            This method is experimental and its signature may change.

        Parameters
        ----------
        func : callable
            User-provided function that accepts a Dataset as its first
            parameter. The function will receive a subset or 'block' of this Dataset (see below),
            corresponding to one chunk along each chunked dimension. ``func`` will be
            executed as ``func(subset_dataset, *subset_args, **kwargs)``.

            This function must return either a single DataArray or a single Dataset.

            This function cannot add a new chunked dimension.
        args : sequence
            Passed to func after unpacking and subsetting any xarray objects by blocks.
            xarray objects in args must be aligned with obj, otherwise an error is raised.
        kwargs : Mapping or None
            Passed verbatim to func after unpacking. xarray objects, if any, will not be
            subset to blocks. Passing dask collections in kwargs is not allowed.
        template : DataArray, Dataset or None, optional
            xarray object representing the final result after compute is called. If not provided,
            the function will be first run on mocked-up data, that looks like this object but
            has sizes 0, to determine properties of the returned object such as dtype,
            variable names, attributes, new dimensions and new indexes (if any).
            ``template`` must be provided if the function changes the size of existing dimensions.
            When provided, ``attrs`` on variables in `template` are copied over to the result. Any
            ``attrs`` set by ``func`` will be ignored.

        Returns
        -------
        A single DataArray or Dataset with dask backend, reassembled from the outputs of the
        function.

        Notes
        -----
        This function is designed for when ``func`` needs to manipulate a whole xarray object
        subset to each block. Each block is loaded into memory. In the more common case where
        ``func`` can work on numpy arrays, it is recommended to use ``apply_ufunc``.

        If none of the variables in this object is backed by dask arrays, calling this function is
        equivalent to calling ``func(obj, *args, **kwargs)``.

        See Also
        --------
        dask.array.map_blocks, xarray.apply_ufunc, xarray.Dataset.map_blocks
        xarray.DataArray.map_blocks

        Examples
        --------
        Calculate an anomaly from climatology using ``.groupby()``. Using
        ``xr.map_blocks()`` allows for parallel operations with knowledge of ``xarray``,
        its indices, and its methods like ``.groupby()``.

        >>> def calculate_anomaly(da, groupby_type="time.month"):
        ...     gb = da.groupby(groupby_type)
        ...     clim = gb.mean(dim="time")
        ...     return gb - clim
        ...
        >>> time = xr.cftime_range("1990-01", "1992-01", freq="M")
        >>> month = xr.DataArray(time.month, coords={"time": time}, dims=["time"])
        >>> np.random.seed(123)
        >>> array = xr.DataArray(
        ...     np.random.rand(len(time)),
        ...     dims=["time"],
        ...     coords={"time": time, "month": month},
        ... ).chunk()
        >>> ds = xr.Dataset({"a": array})
        >>> ds.map_blocks(calculate_anomaly, template=ds).compute()
        <xarray.Dataset>
        Dimensions:  (time: 24)
        Coordinates:
          * time     (time) object 1990-01-31 00:00:00 ... 1991-12-31 00:00:00
            month    (time) int64 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12
        Data variables:
            a        (time) float64 0.1289 0.1132 -0.0856 ... 0.2287 0.1906 -0.05901

        Note that one must explicitly use ``args=[]`` and ``kwargs={}`` to pass arguments
        to the function being applied in ``xr.map_blocks()``:

        >>> ds.map_blocks(
        ...     calculate_anomaly,
        ...     kwargs={"groupby_type": "time.year"},
        ...     template=ds,
        ... )
        <xarray.Dataset>
        Dimensions:  (time: 24)
        Coordinates:
          * time     (time) object 1990-01-31 00:00:00 ... 1991-12-31 00:00:00
            month    (time) int64 dask.array<chunksize=(24,), meta=np.ndarray>
        Data variables:
            a        (time) float64 dask.array<chunksize=(24,), meta=np.ndarray>
        r   )
map_blocks)Zxarray.core.parallelr]  )r  r   r   rF  r\  r]  r   r   r   r]    s    gzDataset.map_blockszfloat | NonezHashable | Anyzbool | Literal['unscaled'])	r  r   degr8  rcondr  r  covr   c               
     s$  ddl m} i }	|}
t|  dd}|   j d}t|d }t||}|dkrl|jd tj	|j
j }|dk	rt|tr| j| }t|}|jdkrtd|jd |jd krtd	  d
||ddtjf 9 }t|| jdd}|| }t| jd}tj|}|rx|||d d}||	|j< tjj|dd}|||f|t|d ddi|d d}||	|j< | j D ]\}} |jkrqt|jr||ks|s|dkrd}
n|dkrt t!|" }
 fdd|jD }i }|rHt|d}|j# f| $||i}||| i}|ddtjf }n|}|}|dk	rp||ddtjf 9 }t%& B |rt%'dtj( nt%'dtj( t)j*||j||
d\}}W 5 Q R X t|t+r| d}nd}||| |gt,|-  |t|ddd i||d d}|r*|.|}||	|j< |sD|dkr||rP|n|/ t,|- ||d d}|r~|.|}||	|j< |rtj0t1|j2|}|t3|| }|dkrd}n*|jd |krt4d||jd |  }||dd | }||	|d! < qt5| |	| j67 d"S )#a)
  
        Least squares polynomial fit.

        This replicates the behaviour of `numpy.polyfit` but differs by skipping
        invalid values when `skipna = True`.

        Parameters
        ----------
        dim : hashable
            Coordinate along which to fit the polynomials.
        deg : int
            Degree of the fitting polynomial.
        skipna : bool or None, optional
            If True, removes all invalid values before fitting each 1D slices of the array.
            Default is True if data is stored in a dask.array or if there is any
            invalid values, False otherwise.
        rcond : float or None, optional
            Relative condition number to the fit.
        w : hashable or Any, optional
            Weights to apply to the y-coordinate of the sample points.
            Can be an array-like object or the name of a coordinate in the dataset.
        full : bool, default: False
            Whether to return the residuals, matrix rank and singular values in addition
            to the coefficients.
        cov : bool or "unscaled", default: False
            Whether to return to the covariance matrix in addition to the coefficients.
            The matrix is not scaled if `cov='unscaled'`.

        Returns
        -------
        polyfit_results : Dataset
            A single dataset which contains (for each "var" in the input dataset):

            [var]_polyfit_coefficients
                The coefficients of the best fit for each variable in this dataset.
            [var]_polyfit_residuals
                The residuals of the least-square computation for each variable (only included if `full=True`)
                When the matrix rank is deficient, np.nan is returned.
            [dim]_matrix_rank
                The effective rank of the scaled Vandermonde coefficient matrix (only included if `full=True`)
                The rank is computed ignoring the NaN values that might be skipped.
            [dim]_singular_values
                The singular values of the scaled Vandermonde coefficient matrix (only included if `full=True`)
            [var]_polyfit_covariance
                The covariance matrix of the polynomial coefficient estimates (only included if `full=False` and `cov=True`)

        Warns
        -----
        RankWarning
            The rank of the coefficient matrix in the least-squares fit is deficient.
            The warning is not raised with in-memory (not dask) data and `full=True`.

        See Also
        --------
        numpy.polyfit
        numpy.polyval
        xarray.polyval
        r   r^   F)strictr4  r   Nz!Expected a 1-d array for weights.zExpected w and z to have the same lengthr  Zdegreematrix_rankr   )Z
compute_uvr   Zsingular_values)r   r-  r   Tc                   s   g | ]}| kr|qS r   r   )r   Zdimnamerm  r   r   r     s      z#Dataset.polyfit.<locals>.<listcomp>ZstackedrO  once)r_  r8   Zpolyfit_coefficientsZpolyfit_residualsZunscaledzKThe number of data points must exceed order to scale the covariance matrix.)cov_icov_jr>  Zpolyfit_covariance)r,  r.  )8r   r_   r?   r   r   r   Zvanderr   r   Zfinfor   Zepsr   r   r-  r  r   r   ZnewaxissqrtrY  r!   Zget_temp_dimnamer   Zlinalgrb  Zsvdr  r,  rB  rC   r   r  r   Zisnullr  r  r   catch_warningssimplefilterZRankWarningr   Zleast_squaresr   r   rp  r  squeezeinvdotTr-  r   rJ  r.  rs  ) r  r   r^  r8  r_  r  r  r`  r_   r   Z	skipna_dar   Zxnamer  lhsZscaleZ
degree_dimr=  Z_singZsingr   r   Zdims_to_stackZstacked_coordsZstacked_dimrhsZscale_daZcoeffsZ	residualsZVbaseZfacZ
covariancer   rm  r   polyfit5  s    D








   





zDataset.polyfitconstantz*Mapping[Any, int | tuple[int, int]] | Nonerr   z<int | tuple[int, int] | Mapping[Any, tuple[int, int]] | NonezFfloat | tuple[float, float] | Mapping[Any, tuple[float, float]] | Noners   )
r  	pad_widthr  stat_lengthconstant_values
end_valuesreflect_typer  pad_width_kwargsr   c              
     sb  t ||d}|dkr(|}	||||d}
nd}	i }
|dkrBtdd}i }| j}t|}i }| D ] \}}|||s`|||< q`| j D ]\}  fdd	| D }|s ||< q|| jkr j	|||||||d
||< q j	f ||	|d|
||< |f j
kr||| i}tj|i d}||}|||< || ||< q|rN| jnd}| j|||dS )a  Pad this dataset along one or more dimensions.

        .. warning::
            This function is experimental and its behaviour is likely to change
            especially regarding padding of dimension coordinates (or IndexVariables).

        When using one of the modes ("edge", "reflect", "symmetric", "wrap"),
        coordinates will be padded with the same mode, otherwise coordinates
        are padded using the "constant" mode with fill_value dtypes.NA.

        Parameters
        ----------
        pad_width : mapping of hashable to tuple of int
            Mapping with the form of {dim: (pad_before, pad_after)}
            describing the number of values padded along each dimension.
            {dim: pad} is a shortcut for pad_before = pad_after = pad
        mode : {"constant", "edge", "linear_ramp", "maximum", "mean", "median",             "minimum", "reflect", "symmetric", "wrap"}, default: "constant"
            How to pad the DataArray (taken from numpy docs):

            - "constant": Pads with a constant value.
            - "edge": Pads with the edge values of array.
            - "linear_ramp": Pads with the linear ramp between end_value and the
              array edge value.
            - "maximum": Pads with the maximum value of all or part of the
              vector along each axis.
            - "mean": Pads with the mean value of all or part of the
              vector along each axis.
            - "median": Pads with the median value of all or part of the
              vector along each axis.
            - "minimum": Pads with the minimum value of all or part of the
              vector along each axis.
            - "reflect": Pads with the reflection of the vector mirrored on
              the first and last values of the vector along each axis.
            - "symmetric": Pads with the reflection of the vector mirrored
              along the edge of the array.
            - "wrap": Pads with the wrap of the vector along the axis.
              The first values are used to pad the end and the
              end values are used to pad the beginning.

        stat_length : int, tuple or mapping of hashable to tuple, default: None
            Used in 'maximum', 'mean', 'median', and 'minimum'.  Number of
            values at edge of each axis used to calculate the statistic value.
            {dim_1: (before_1, after_1), ... dim_N: (before_N, after_N)} unique
            statistic lengths along each dimension.
            ((before, after),) yields same before and after statistic lengths
            for each dimension.
            (stat_length,) or int is a shortcut for before = after = statistic
            length for all axes.
            Default is ``None``, to use the entire axis.
        constant_values : scalar, tuple or mapping of hashable to tuple, default: 0
            Used in 'constant'.  The values to set the padded values for each
            axis.
            ``{dim_1: (before_1, after_1), ... dim_N: (before_N, after_N)}`` unique
            pad constants along each dimension.
            ``((before, after),)`` yields same before and after constants for each
            dimension.
            ``(constant,)`` or ``constant`` is a shortcut for ``before = after = constant`` for
            all dimensions.
            Default is 0.
        end_values : scalar, tuple or mapping of hashable to tuple, default: 0
            Used in 'linear_ramp'.  The values used for the ending value of the
            linear_ramp and that will form the edge of the padded array.
            ``{dim_1: (before_1, after_1), ... dim_N: (before_N, after_N)}`` unique
            end values along each dimension.
            ``((before, after),)`` yields same before and after end values for each
            axis.
            ``(constant,)`` or ``constant`` is a shortcut for ``before = after = constant`` for
            all axes.
            Default is 0.
        reflect_type : {"even", "odd", None}, optional
            Used in "reflect", and "symmetric".  The "even" style is the
            default with an unaltered reflection around the edge value.  For
            the "odd" style, the extended part of the array is created by
            subtracting the reflected values from two times the edge value.
        keep_attrs : bool or None, optional
            If True, the attributes (``attrs``) will be copied from the
            original object to the new one. If False, the new object
            will be returned without attributes.
        **pad_width_kwargs
            The keyword arguments form of ``pad_width``.
            One of ``pad_width`` or ``pad_width_kwargs`` must be provided.

        Returns
        -------
        padded : Dataset
            Dataset with the padded coordinates and data.

        See Also
        --------
        Dataset.shift, Dataset.roll, Dataset.bfill, Dataset.ffill, numpy.pad, dask.array.pad

        Notes
        -----
        By default when ``mode="constant"`` and ``constant_values=None``, integer types will be
        promoted to ``float`` and padded with ``np.nan``. To avoid type promotion
        specify ``constant_values=np.nan``

        Padding coordinates will drop their corresponding index (if any) and will reset default
        indexes for dimension coordinates.

        Examples
        --------
        >>> ds = xr.Dataset({"foo": ("x", range(5))})
        >>> ds.pad(x=(1, 2))
        <xarray.Dataset>
        Dimensions:  (x: 8)
        Dimensions without coordinates: x
        Data variables:
            foo      (x) float64 nan 0.0 1.0 2.0 3.0 4.0 nan nan
        pad)ZedgeZreflectZ	symmetricwrap)rs  rt  ru  rv  rq  NTr  c                   s    i | ]\}}| j kr||qS r   r>  rD  r  r   r   r     s     
  zDataset.pad.<locals>.<dictcomp>)rr  r  rs  rt  ru  rv  r  )rr  r  r  rw  )r3  r.  )rM   rA   r  r   rB  rK  Zget_all_dimsr   r,  rx  r   r1   r~  rN  r%  r~  )r  rr  r  rs  rt  ru  rv  r  rw  Zcoord_pad_modeZcoord_pad_optionsr   r  Zpad_dimsr3  r  r  r   Zvar_pad_widthZdim_varr  r  r.  r   r  r   rx    s`    






zDataset.pad)r  r   r8  r1  r  r   c              	   C  s   |  td||||dS )aK  Return the coordinate label of the minimum value along a dimension.

        Returns a new `Dataset` named after the dimension with the values of
        the coordinate labels along that dimension corresponding to minimum
        values along that dimension.

        In comparison to :py:meth:`~Dataset.argmin`, this returns the
        coordinate label while :py:meth:`~Dataset.argmin` returns the index.

        Parameters
        ----------
        dim : Hashable, optional
            Dimension over which to apply `idxmin`.  This is optional for 1D
            variables, but required for variables with 2 or more dimensions.
        skipna : bool or None, optional
            If True, skip missing values (as marked by NaN). By default, only
            skips missing values for ``float``, ``complex``, and ``object``
            dtypes; other dtypes either do not have a sentinel missing value
            (``int``) or ``skipna=True`` has not been implemented
            (``datetime64`` or ``timedelta64``).
        fill_value : Any, default: NaN
            Value to be filled in case all of the values along a dimension are
            null.  By default this is NaN.  The fill value and result are
            automatically converted to a compatible dtype if possible.
            Ignored if ``skipna`` is False.
        keep_attrs : bool or None, optional
            If True, the attributes (``attrs``) will be copied from the
            original object to the new one. If False, the new object
            will be returned without attributes.

        Returns
        -------
        reduced : Dataset
            New `Dataset` object with `idxmin` applied to its data and the
            indicated dimension removed.

        See Also
        --------
        DataArray.idxmin, Dataset.idxmax, Dataset.min, Dataset.argmin

        Examples
        --------
        >>> array1 = xr.DataArray(
        ...     [0, 2, 1, 0, -2], dims="x", coords={"x": ["a", "b", "c", "d", "e"]}
        ... )
        >>> array2 = xr.DataArray(
        ...     [
        ...         [2.0, 1.0, 2.0, 0.0, -2.0],
        ...         [-4.0, np.NaN, 2.0, np.NaN, -2.0],
        ...         [np.NaN, np.NaN, 1.0, np.NaN, np.NaN],
        ...     ],
        ...     dims=["y", "x"],
        ...     coords={"y": [-1, 0, 1], "x": ["a", "b", "c", "d", "e"]},
        ... )
        >>> ds = xr.Dataset({"int": array1, "float": array2})
        >>> ds.min(dim="x")
        <xarray.Dataset>
        Dimensions:  (y: 3)
        Coordinates:
          * y        (y) int64 -1 0 1
        Data variables:
            int      int64 -2
            float    (y) float64 -2.0 -4.0 1.0
        >>> ds.argmin(dim="x")
        <xarray.Dataset>
        Dimensions:  (y: 3)
        Coordinates:
          * y        (y) int64 -1 0 1
        Data variables:
            int      int64 4
            float    (y) int64 4 0 2
        >>> ds.idxmin(dim="x")
        <xarray.Dataset>
        Dimensions:  (y: 3)
        Coordinates:
          * y        (y) int64 -1 0 1
        Data variables:
            int      <U1 'e'
            float    (y) object 'e' 'a' 'c'
        idxminr   r8  r1  r  r  r   r  r   r8  r1  r  r   r   r   rz    s    WzDataset.idxminc              	   C  s   |  td||||dS )aC  Return the coordinate label of the maximum value along a dimension.

        Returns a new `Dataset` named after the dimension with the values of
        the coordinate labels along that dimension corresponding to maximum
        values along that dimension.

        In comparison to :py:meth:`~Dataset.argmax`, this returns the
        coordinate label while :py:meth:`~Dataset.argmax` returns the index.

        Parameters
        ----------
        dim : str, optional
            Dimension over which to apply `idxmax`.  This is optional for 1D
            variables, but required for variables with 2 or more dimensions.
        skipna : bool or None, optional
            If True, skip missing values (as marked by NaN). By default, only
            skips missing values for ``float``, ``complex``, and ``object``
            dtypes; other dtypes either do not have a sentinel missing value
            (``int``) or ``skipna=True`` has not been implemented
            (``datetime64`` or ``timedelta64``).
        fill_value : Any, default: NaN
            Value to be filled in case all of the values along a dimension are
            null.  By default this is NaN.  The fill value and result are
            automatically converted to a compatible dtype if possible.
            Ignored if ``skipna`` is False.
        keep_attrs : bool or None, optional
            If True, the attributes (``attrs``) will be copied from the
            original object to the new one. If False, the new object
            will be returned without attributes.

        Returns
        -------
        reduced : Dataset
            New `Dataset` object with `idxmax` applied to its data and the
            indicated dimension removed.

        See Also
        --------
        DataArray.idxmax, Dataset.idxmin, Dataset.max, Dataset.argmax

        Examples
        --------
        >>> array1 = xr.DataArray(
        ...     [0, 2, 1, 0, -2], dims="x", coords={"x": ["a", "b", "c", "d", "e"]}
        ... )
        >>> array2 = xr.DataArray(
        ...     [
        ...         [2.0, 1.0, 2.0, 0.0, -2.0],
        ...         [-4.0, np.NaN, 2.0, np.NaN, -2.0],
        ...         [np.NaN, np.NaN, 1.0, np.NaN, np.NaN],
        ...     ],
        ...     dims=["y", "x"],
        ...     coords={"y": [-1, 0, 1], "x": ["a", "b", "c", "d", "e"]},
        ... )
        >>> ds = xr.Dataset({"int": array1, "float": array2})
        >>> ds.max(dim="x")
        <xarray.Dataset>
        Dimensions:  (y: 3)
        Coordinates:
          * y        (y) int64 -1 0 1
        Data variables:
            int      int64 2
            float    (y) float64 2.0 2.0 1.0
        >>> ds.argmax(dim="x")
        <xarray.Dataset>
        Dimensions:  (y: 3)
        Coordinates:
          * y        (y) int64 -1 0 1
        Data variables:
            int      int64 1
            float    (y) int64 0 2 2
        >>> ds.idxmax(dim="x")
        <xarray.Dataset>
        Dimensions:  (y: 3)
        Coordinates:
          * y        (y) int64 -1 0 1
        Data variables:
            int      <U1 'b'
            float    (y) object 'a' 'c' 'c'
        idxmaxr{  r|  r}  r   r   r   r~     s    WzDataset.idxmax)r  r   r   c                 K  sv   |dkrt jdtdd |dks<t|ts2|dk	s<t|trjttd}| j|fd|dkr\dn|gi|S t	ddS )	a   Indices of the minima of the member variables.

        If there are multiple minima, the indices of the first one found will be
        returned.

        Parameters
        ----------
        dim : Hashable, optional
            The dimension over which to find the minimum. By default, finds minimum over
            all dimensions - for now returning an int for backward compatibility, but
            this is deprecated, in future will be an error, since DataArray.argmin will
            return a dict with indices for all dimensions, which does not make sense for
            a Dataset.
        keep_attrs : bool, optional
            If True, the attributes (`attrs`) will be copied from the original
            object to the new one.  If False (default), the new object will be
            returned without attributes.
        skipna : bool, optional
            If True, skip missing values (as marked by NaN). By default, only
            skips missing values for float dtypes; other dtypes either do not
            have a sentinel missing value (int) or skipna=True has not been
            implemented (object, datetime64 or timedelta64).

        Returns
        -------
        result : Dataset

        See Also
        --------
        DataArray.argmin
        NOnce the behaviour of DataArray.argmin() and Variable.argmin() without dim changes to return a dict of indices of each dimension, for consistency it will be an error to call Dataset.argmin() with no argument,since we don't return a dict of Datasets.r   ra  .argminr   When dim is a sequence or ..., DataArray.argmin() returns a dict. dicts cannot be contained in a Dataset, so cannot call Dataset.argmin() with a sequence or ... for dim
r   r   r  r   r   r   r   r   r  r   )r  r   rF  Zargmin_funcr   r   r   r  u   s2     	
zDataset.argminc                 K  sv   |dkrt jdtdd |dks<t|ts2|dk	s<t|trjttd}| j|fd|dkr\dn|gi|S t	ddS )	a  Indices of the maxima of the member variables.

        If there are multiple maxima, the indices of the first one found will be
        returned.

        Parameters
        ----------
        dim : str, optional
            The dimension over which to find the maximum. By default, finds maximum over
            all dimensions - for now returning an int for backward compatibility, but
            this is deprecated, in future will be an error, since DataArray.argmax will
            return a dict with indices for all dimensions, which does not make sense for
            a Dataset.
        keep_attrs : bool, optional
            If True, the attributes (`attrs`) will be copied from the original
            object to the new one.  If False (default), the new object will be
            returned without attributes.
        skipna : bool, optional
            If True, skip missing values (as marked by NaN). By default, only
            skips missing values for float dtypes; other dtypes either do not
            have a sentinel missing value (int) or skipna=True has not been
            implemented (object, datetime64 or timedelta64).

        Returns
        -------
        result : Dataset

        See Also
        --------
        DataArray.argmax

        Nr  r   ra  .argmaxr   r  r  )r  r   rF  Zargmax_funcr   r   r   r     s2    !	
zDataset.argmaxpandasru   rt   )r  queriesparserr  r  queries_kwargsr   c           
        sn   t ||d}| D ]0\}}t|tsd| dt| d}t|q fdd| D }	j|	|dS )u$  Return a new dataset with each array indexed along the specified
        dimension(s), where the indexers are given as strings containing
        Python expressions to be evaluated against the data variables in the
        dataset.

        Parameters
        ----------
        queries : dict-like, optional
            A dict-like with keys matching dimensions and values given by strings
            containing Python expressions to be evaluated against the data variables
            in the dataset. The expressions will be evaluated using the pandas
            eval() function, and can contain any valid Python expressions but cannot
            contain any Python statements.
        parser : {"pandas", "python"}, default: "pandas"
            The parser to use to construct the syntax tree from the expression.
            The default of 'pandas' parses code slightly different than standard
            Python. Alternatively, you can parse an expression using the 'python'
            parser to retain strict Python semantics.
        engine : {"python", "numexpr", None}, default: None
            The engine used to evaluate the expression. Supported engines are:

            - None: tries to use numexpr, falls back to python
            - "numexpr": evaluates expressions using numexpr
            - "python": performs operations as if you had eval’d in top level python

        missing_dims : {"raise", "warn", "ignore"}, default: "raise"
            What to do if dimensions that should be selected from are not present in the
            Dataset:

            - "raise": raise an exception
            - "warn": raise a warning, and ignore the missing dimensions
            - "ignore": ignore the missing dimensions

        **queries_kwargs : {dim: query, ...}, optional
            The keyword arguments form of ``queries``.
            One of queries or queries_kwargs must be provided.

        Returns
        -------
        obj : Dataset
            A new Dataset with the same contents as this dataset, except each
            array and dimension is indexed by the results of the appropriate
            queries.

        See Also
        --------
        Dataset.isel
        pandas.eval

        Examples
        --------
        >>> a = np.arange(0, 5, 1)
        >>> b = np.linspace(0, 1, 5)
        >>> ds = xr.Dataset({"a": ("x", a), "b": ("x", b)})
        >>> ds
        <xarray.Dataset>
        Dimensions:  (x: 5)
        Dimensions without coordinates: x
        Data variables:
            a        (x) int64 0 1 2 3 4
            b        (x) float64 0.0 0.25 0.5 0.75 1.0
        >>> ds.query(x="a > 2")
        <xarray.Dataset>
        Dimensions:  (x: 2)
        Dimensions without coordinates: x
        Data variables:
            a        (x) int64 3 4
            b        (x) float64 0.75 1.0
        queryzexpr for dim z# must be a string to be evaluated, z givenc              	     s&   i | ]\}}|t j|g d qS ))Z	resolversr  r  )r   eval)r   r   exprr  r  r  r   r   r   D!  s    z!Dataset.query.<locals>.<dictcomp>r  )rM   rB  r   r   rJ  r   r  )
r  r  r  r  r  r  r   r  r   r  r   r  r   r     s    O

zDataset.queryz+str | DataArray | Iterable[str | DataArray]zCallable[..., Any]zdict[str, Any] | NonezSequence[str] | None)
r  r-  r   r  r8  r   r   r   rF  r   c	                   s  ddl m ddlm}	 ddlm}
 ddlm}m} |dkr@i }|dkrLi }|dkrXi }|sbg n$t	|t
svt	|ts~|gnt|t	|t
st	||st	|ts|g}fdd|D }|D ]fd	djD 7 qttttjt std
|	| }fdd|D }t|\}}t||||\ t||dfdd|D  |d fdd|D  fdd|D g 	fdd}t }j D ]\}}||krd}nt
| d}|
||f|ddfddtt|d D dgddggdditjtjft|d\}}|||d < |||d  < q||||d}j |_|S )!aM  
        Curve fitting optimization for arbitrary functions.

        Wraps `scipy.optimize.curve_fit` with `apply_ufunc`.

        Parameters
        ----------
        coords : hashable, DataArray, or sequence of hashable or DataArray
            Independent coordinate(s) over which to perform the curve fitting. Must share
            at least one dimension with the calling object. When fitting multi-dimensional
            functions, supply `coords` as a sequence in the same order as arguments in
            `func`. To fit along existing dimensions of the calling object, `coords` can
            also be specified as a str or sequence of strs.
        func : callable
            User specified function in the form `f(x, *params)` which returns a numpy
            array of length `len(x)`. `params` are the fittable parameters which are optimized
            by scipy curve_fit. `x` can also be specified as a sequence containing multiple
            coordinates, e.g. `f((x0, x1), *params)`.
        reduce_dims : str, Iterable of Hashable or None, optional
            Additional dimension(s) over which to aggregate while fitting. For example,
            calling `ds.curvefit(coords='time', reduce_dims=['lat', 'lon'], ...)` will
            aggregate all lat and lon points and fit the specified function along the
            time dimension.
        skipna : bool, default: True
            Whether to skip missing values when fitting. Default is True.
        p0 : dict-like, optional
            Optional dictionary of parameter names to initial guesses passed to the
            `curve_fit` `p0` arg. If none or only some parameters are passed, the rest will
            be assigned initial values following the default scipy behavior.
        bounds : dict-like, optional
            Optional dictionary of parameter names to bounding values passed to the
            `curve_fit` `bounds` arg. If none or only some parameters are passed, the rest
            will be unbounded following the default scipy behavior.
        param_names : sequence of hashable, optional
            Sequence of names for the fittable parameters of `func`. If not supplied,
            this will be automatically determined by arguments of `func`. `param_names`
            should be manually supplied when fitting a function that takes a variable
            number of parameters.
        **kwargs : optional
            Additional keyword arguments to passed to scipy curve_fit.

        Returns
        -------
        curvefit_results : Dataset
            A single dataset which contains:

            [var]_curvefit_coefficients
                The coefficients of the best fit.
            [var]_curvefit_covariance
                The covariance matrix of the coefficient estimates.

        See Also
        --------
        Dataset.polyfit
        scipy.optimize.curve_fit
        r   )	curve_fit)	broadcast)apply_ufunc)_THIS_ARRAYr_   Nc                   s"   g | ]}t |tr | n|qS r   )r   r   r   r>  r
  r   r   r   !  s    z$Dataset.curvefit.<locals>.<listcomp>c                   s   g | ]}  | r|qS r   )r  r   rt  )r>  r  r   r   r   !  s      zNo arguments to `coords` were identified as a dimension on the calling object, and no dims were supplied to `reduce_dims`. This would result in fitting on scalar data.c                   s   g | ]}|j  d qS ))r,  )r.  r  )preserved_dimsr  r   r   r   !  s    r   c                   s   g | ]} | qS r   r   r   )r   r   r   r   !  s     r   c                   s   g | ]} | d  qS r  r   r   r   r   r   r   !  s     c                   s   g | ]} | d  qS r   r   r   r  r   r   r   !  s     c                   s   t dd |D }|  }rt jt jt | ddt | gdd}|d d |f }|| }t|st gt j}t gt j}||fS t 	|} ||f|\}}||fS )Nc                 S  s   g | ]}|  qS r   )ravelr  r   r   r   r   !  s     z6Dataset.curvefit.<locals>._wrapper.<locals>.<listcomp>r   r  )
r   Zvstackr  rM  r   isnanr   r  r!  rj  )Ycoords_rF  r   r  r  poptpcov)r  r   n_paramsr8  r   r   _wrapper!  s    ,
z"Dataset.curvefit.<locals>._wrapperrd  r4  TZparallelizedc                   s   g | ]} qS r   r   rE  )reduce_dims_r   r   r   !  s     r   paramre  rf  Zoutput_sizes)r  re  rf  )Z	vectorizerS  Zinput_core_dimsZoutput_core_dimsZdask_gufunc_kwargsZoutput_dtypesr2  rF  Zcurvefit_coefficientsZcurvefit_covariance)Zscipy.optimizer  r  r  xarray.core.computationr  r   r  r_   r   r   r   r   r   r   r   r   r   r   
setdefaultrJ  r,  rB  r   r   r;  r  r.  rs  )r  r-  r   r  r8  r   r   r   rF  r  r  r  r_   r  r   r   r  r  r   r   r  r  r   )
r   r>  r  r   r  r   r  r  r  r8  r   curvefitL!  s    C
   



zDataset.curvefitfirstz!Literal[('first', 'last', False)])r  r   keepr   c                   s|   t |tr|f}n&|dkr"j}nt |ts4|g}n|}t|tj }|r^td| d fdd|D }|S )a  Returns a new Dataset with duplicate dimension values removed.

        Parameters
        ----------
        dim : dimension label or labels
            Pass `...` to drop duplicates along all dimensions.
        keep : {"first", "last", False}, default: "first"
            Determines which duplicates (if any) to keep.
            - ``"first"`` : Drop duplicates except for the first occurrence.
            - ``"last"`` : Drop duplicates except for the last occurrence.
            - False : Drop all duplicates.

        Returns
        -------
        Dataset

        See Also
        --------
        DataArray.drop_duplicates
        .'z' not found in dimensionsc                   s"   i | ]}| |j d  qS ))r  )r  Z
duplicatedr   r  r  r   r   r   ("  s      z+Dataset.drop_duplicates.<locals>.<dictcomp>)r   r   r   r   r   r   r  )r  r   r  r   r  r3  r   r  r   drop_duplicates"  s    

zDataset.drop_duplicatesr   rg   zLiteral[('date', 'year', None)]z
Any | None)r  calendarr   align_onrB  
use_cftimer   c                 C  s   t | |||||dS )a  Convert the Dataset to another calendar.

        Only converts the individual timestamps, does not modify any data except
        in dropping invalid/surplus dates or inserting missing dates.

        If the source and target calendars are either no_leap, all_leap or a
        standard type, only the type of the time array is modified.
        When converting to a leap year from a non-leap year, the 29th of February
        is removed from the array. In the other direction the 29th of February
        will be missing in the output, unless `missing` is specified,
        in which case that value is inserted.

        For conversions involving `360_day` calendars, see Notes.

        This method is safe to use with sub-daily data as it doesn't touch the
        time part of the timestamps.

        Parameters
        ---------
        calendar : str
            The target calendar name.
        dim : Hashable, default: "time"
            Name of the time coordinate.
        align_on : {None, 'date', 'year'}, optional
            Must be specified when either source or target is a `360_day` calendar,
            ignored otherwise. See Notes.
        missing : Any or None, optional
            By default, i.e. if the value is None, this method will simply attempt
            to convert the dates in the source calendar to the same dates in the
            target calendar, and drop any of those that are not possible to
            represent.  If a value is provided, a new time coordinate will be
            created in the target calendar with the same frequency as the original
            time coordinate; for any dates that are not present in the source, the
            data will be filled with this value.  Note that using this mode requires
            that the source data have an inferable frequency; for more information
            see :py:func:`xarray.infer_freq`.  For certain frequency, source, and
            target calendar combinations, this could result in many missing values, see notes.
        use_cftime : bool or None, optional
            Whether to use cftime objects in the output, only used if `calendar`
            is one of {"proleptic_gregorian", "gregorian" or "standard"}.
            If True, the new time axis uses cftime objects.
            If None (default), it uses :py:class:`numpy.datetime64` values if the
            date range permits it, and :py:class:`cftime.datetime` objects if not.
            If False, it uses :py:class:`numpy.datetime64`  or fails.

        Returns
        -------
        Dataset
            Copy of the dataarray with the time coordinate converted to the
            target calendar. If 'missing' was None (default), invalid dates in
            the new calendar are dropped, but missing dates are not inserted.
            If `missing` was given, the new data is reindexed to have a time axis
            with the same frequency as the source, but in the new calendar; any
            missing datapoints are filled with `missing`.

        Notes
        -----
        Passing a value to `missing` is only usable if the source's time coordinate as an
        inferable frequencies (see :py:func:`~xarray.infer_freq`) and is only appropriate
        if the target coordinate, generated from this frequency, has dates equivalent to the
        source. It is usually **not** appropriate to use this mode with:

        - Period-end frequencies : 'A', 'Y', 'Q' or 'M', in opposition to 'AS' 'YS', 'QS' and 'MS'
        - Sub-monthly frequencies that do not divide a day evenly : 'W', 'nD' where `N != 1`
            or 'mH' where 24 % m != 0).

        If one of the source or target calendars is `"360_day"`, `align_on` must
        be specified and two options are offered.

        - "year"
            The dates are translated according to their relative position in the year,
            ignoring their original month and day information, meaning that the
            missing/surplus days are added/removed at regular intervals.

            From a `360_day` to a standard calendar, the output will be missing the
            following dates (day of year in parentheses):

            To a leap year:
                January 31st (31), March 31st (91), June 1st (153), July 31st (213),
                September 31st (275) and November 30th (335).
            To a non-leap year:
                February 6th (36), April 19th (109), July 2nd (183),
                September 12th (255), November 25th (329).

            From a standard calendar to a `"360_day"`, the following dates in the
            source array will be dropped:

            From a leap year:
                January 31st (31), April 1st (92), June 1st (153), August 1st (214),
                September 31st (275), December 1st (336)
            From a non-leap year:
                February 6th (37), April 20th (110), July 2nd (183),
                September 13th (256), November 25th (329)

            This option is best used on daily and subdaily data.

        - "date"
            The month/day information is conserved and invalid dates are dropped
            from the output. This means that when converting from a `"360_day"` to a
            standard calendar, all 31st (Jan, March, May, July, August, October and
            December) will be missing as there is no equivalent dates in the
            `"360_day"` calendar and the 29th (on non-leap years) and 30th of February
            will be dropped as there are no equivalent dates in a standard calendar.

            This option is best used with data on a frequency coarser than daily.
        )r   r  rB  r  )r   )r  r  r   r  rB  r  r   r   r   r   +"  s    rzDataset.convert_calendarz*pd.DatetimeIndex | CFTimeIndex | DataArray)r  targetr   r   c                 C  s   t | ||dS )a  Interpolates the Dataset to another calendar based on decimal year measure.

        Each timestamp in `source` and `target` are first converted to their decimal
        year equivalent then `source` is interpolated on the target coordinate.
        The decimal year of a timestamp is its year plus its sub-year component
        converted to the fraction of its year. For example "2000-03-01 12:00" is
        2000.1653 in a standard calendar or 2000.16301 in a `"noleap"` calendar.

        This method should only be used when the time (HH:MM:SS) information of
        time coordinate is not important.

        Parameters
        ----------
        target: DataArray or DatetimeIndex or CFTimeIndex
            The target time coordinate of a valid dtype
            (np.datetime64 or cftime objects)
        dim : Hashable, default: "time"
            The time coordinate name.

        Return
        ------
        DataArray
            The source interpolated on the decimal years of target,
        rm  )r   )r  r  r   r   r   r   r   "  s    zDataset.interp_calendarz$Hashable | DataArray | IndexVariablera   )r  rj  restore_coord_dimsr   c                 C  s6   ddl m} t|ts&td| d|| |||dS )a  Returns a DatasetGroupBy object for performing grouped operations.

        Parameters
        ----------
        group : Hashable, DataArray or IndexVariable
            Array whose unique values should be used to group this array. If a
            string, must be the name of a variable contained in this dataset.
        squeeze : bool, default: True
            If "group" is a dimension of any arrays in this dataset, `squeeze`
            controls whether the subarrays have a dimension of length 1 along
            that dimension or if the dimension is squeezed out.
        restore_coord_dims : bool, default: False
            If True, also restore the dimension order of multi-dimensional
            coordinates.

        Returns
        -------
        grouped : DatasetGroupBy
            A `DatasetGroupBy` object patterned after `pandas.GroupBy` that can be
            iterated over in the form of `(unique_value, grouped_array)` pairs.

        See Also
        --------
        Dataset.groupby_bins
        DataArray.groupby
        core.groupby.DatasetGroupBy
        pandas.DataFrame.groupby
        Dataset.resample
        DataArray.resample
        r   r`   z%`squeeze` must be True or False, but z was supplied)rj  r  )r  ra   r   r  r   )r  r  rj  r  ra   r   r   r   groupby"  s    $

   zDataset.groupbyr`  zArrayLike | None)	r  binsr   r  	precisioninclude_lowestrj  r  r   c	           
      C  s*   ddl m}	 |	| ||||||||ddS )a6
  Returns a DatasetGroupBy object for performing grouped operations.

        Rather than using all unique values of `group`, the values are discretized
        first by applying `pandas.cut` [1]_ to `group`.

        Parameters
        ----------
        group : Hashable, DataArray or IndexVariable
            Array whose binned values should be used to group this array. If a
            string, must be the name of a variable contained in this dataset.
        bins : int or array-like
            If bins is an int, it defines the number of equal-width bins in the
            range of x. However, in this case, the range of x is extended by .1%
            on each side to include the min or max values of x. If bins is a
            sequence it defines the bin edges allowing for non-uniform bin
            width. No extension of the range of x is done in this case.
        right : bool, default: True
            Indicates whether the bins include the rightmost edge or not. If
            right == True (the default), then the bins [1,2,3,4] indicate
            (1,2], (2,3], (3,4].
        labels : array-like or bool, default: None
            Used as labels for the resulting bins. Must be of the same length as
            the resulting bins. If False, string bin labels are assigned by
            `pandas.cut`.
        precision : int, default: 3
            The precision at which to store and display the bins labels.
        include_lowest : bool, default: False
            Whether the first interval should be left-inclusive or not.
        squeeze : bool, default: True
            If "group" is a dimension of any arrays in this dataset, `squeeze`
            controls whether the subarrays have a dimension of length 1 along
            that dimension or if the dimension is squeezed out.
        restore_coord_dims : bool, default: False
            If True, also restore the dimension order of multi-dimensional
            coordinates.

        Returns
        -------
        grouped : DatasetGroupBy
            A `DatasetGroupBy` object patterned after `pandas.GroupBy` that can be
            iterated over in the form of `(unique_value, grouped_array)` pairs.
            The name of the group has the added suffix `_bins` in order to
            distinguish it from the original variable.

        See Also
        --------
        Dataset.groupby
        DataArray.groupby_bins
        core.groupby.DatasetGroupBy
        pandas.DataFrame.groupby

        References
        ----------
        .. [1] http://pandas.pydata.org/pandas-docs/stable/generated/pandas.cut.html
        r   r`   )r   r  r  r  )rj  r  r  Z
cut_kwargs)r  ra   )
r  r  r  r   r  r  r  rj  r  ra   r   r   r   groupby_bins"  s    BzDataset.groupby_binsrz   )weightsr   c                 C  s   ddl m} || |S )ae  
        Weighted Dataset operations.

        Parameters
        ----------
        weights : DataArray
            An array of weights associated with the values in this Dataset.
            Each value in the data contributes to the reduction operation
            according to its associated weight.

        Notes
        -----
        ``weights`` must be a DataArray and cannot contain missing values.
        Missing values can be replaced by ``weights.fillna(0)``.

        Returns
        -------
        core.weighted.DatasetWeighted

        See Also
        --------
        DataArray.weighted
        r   ry   )xarray.core.weightedrz   )r  r  rz   r   r   r   weightedL#  s    zDataset.weightedzbool | Mapping[Any, bool]rf   )r   min_periodscenterwindow_kwargsr   c                 K  s(   ddl m} t||d}|| |||dS )a  
        Rolling window object for Datasets.

        Parameters
        ----------
        dim : dict, optional
            Mapping from the dimension name to create the rolling iterator
            along (e.g. `time`) to its moving window size.
        min_periods : int or None, default: None
            Minimum number of observations in window required to have a value
            (otherwise result is NA). The default, None, is equivalent to
            setting min_periods equal to the size of the window.
        center : bool or Mapping to int, default: False
            Set the labels at the center of the window.
        **window_kwargs : optional
            The keyword arguments form of ``dim``.
            One of dim or window_kwargs must be provided.

        Returns
        -------
        core.rolling.DatasetRolling

        See Also
        --------
        core.rolling.DatasetRolling
        DataArray.rolling
        r   )rf   rolling)r  r  )xarray.core.rollingrf   rM   )r  r   r  r  r  rf   r   r   r   r  h#  s    "zDataset.rollingr  r  meanrh   z'SideOptions | Mapping[Any, SideOptions]z-str | Callable | Mapping[Any, str | Callable]re   )r   boundaryside
coord_funcr  r   c                 K  s*   ddl m} t||d}|| ||||dS )a  
        Coarsen object for Datasets.

        Parameters
        ----------
        dim : mapping of hashable to int, optional
            Mapping from the dimension name to the window size.
        boundary : {"exact", "trim", "pad"}, default: "exact"
            If 'exact', a ValueError will be raised if dimension size is not a
            multiple of the window size. If 'trim', the excess entries are
            dropped. If 'pad', NA will be padded.
        side : {"left", "right"} or mapping of str to {"left", "right"}, default: "left"
        coord_func : str or mapping of hashable to str, default: "mean"
            function (name) that is applied to the coordinates,
            or a mapping from coordinate name to function (name).

        Returns
        -------
        core.rolling.DatasetCoarsen

        See Also
        --------
        core.rolling.DatasetCoarsen
        DataArray.coarsen
        r   )re   coarsen)r  r  r  )r  re   rM   )r  r   r  r  r  r  re   r   r   r   r  #  s    !zDataset.coarsen	start_dayzMapping[Any, str] | NonezSideOptions | Nonez.pd.Timedelta | datetime.timedelta | str | Nonezstr | DatetimeLikezdatetime.timedelta | str | Nonerd   )r  r8  closedr%  baseoffsetoriginr  loffsetr  indexer_kwargsr   c                 K  s4   ddl m} | jf ||||||||||	|
d|S )a
  Returns a Resample object for performing resampling operations.

        Handles both downsampling and upsampling. The resampled
        dimension must be a datetime-like coordinate. If any intervals
        contain no values from the original object, they will be given
        the value ``NaN``.

        Parameters
        ----------
        indexer : Mapping of Hashable to str, optional
            Mapping from the dimension name to resample frequency [1]_. The
            dimension must be datetime-like.
        skipna : bool, optional
            Whether to skip missing values when aggregating in downsampling.
        closed : {"left", "right"}, optional
            Side of each interval to treat as closed.
        label : {"left", "right"}, optional
            Side of each interval to use for labeling.
        base : int, optional
            For frequencies that evenly subdivide 1 day, the "origin" of the
            aggregated intervals. For example, for "24H" frequency, base could
            range from 0 through 23.
        origin : {'epoch', 'start', 'start_day', 'end', 'end_day'}, pd.Timestamp, datetime.datetime, np.datetime64, or cftime.datetime, default 'start_day'
            The datetime on which to adjust the grouping. The timezone of origin
            must match the timezone of the index.

            If a datetime is not used, these values are also supported:
            - 'epoch': `origin` is 1970-01-01
            - 'start': `origin` is the first value of the timeseries
            - 'start_day': `origin` is the first day at midnight of the timeseries
            - 'end': `origin` is the last value of the timeseries
            - 'end_day': `origin` is the ceiling midnight of the last day
        offset : pd.Timedelta, datetime.timedelta, or str, default is None
            An offset timedelta added to the origin.
        loffset : timedelta or str, optional
            Offset used to adjust the resampled time labels. Some pandas date
            offset strings are supported.
        restore_coord_dims : bool, optional
            If True, also restore the dimension order of multi-dimensional
            coordinates.
        **indexer_kwargs : str
            The keyword arguments form of ``indexer``.
            One of indexer or indexer_kwargs must be provided.

        Returns
        -------
        resampled : core.resample.DataArrayResample
            This object resampled.

        See Also
        --------
        DataArray.resample
        pandas.Series.resample
        pandas.DataFrame.resample
        Dataset.groupby
        DataArray.groupby

        References
        ----------
        .. [1] http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
        r   rc   )Zresample_clsr  r8  r  r%  r  r  r  r  r  r  )xarray.core.resamplerd   Z	_resample)r  r  r8  r  r%  r  r  r  r  r  r  r  rd   r   r   r   resample#  s     KzDataset.resample)NNN)N)NNNNN)NNNN)FN)FNN)N)N)NF)	Nr  NNNNNTF)r  NNNNNTF)r  NNNNN)	Nr  NNNNNTF)NNNNNNTNNNTNN)NNNNNN)NNNNNNTNNNTNN)N)r   )NFr   )NNNF)N)N)N)N)Nr=  FNr>  )r=  FNr>  )N)N)N)N)N)NN)NF)F)N)N)FF)T)r   N)F)F)NN)N)N)r   NN)Nr=  NTN)N)N)N)Nr   )Nr   )N)r   N)N)N)F)NF)TF)FN)r  F)r   r$  )NF)T)Nr=  FNNN)FN)r   N)N)NF)N)r   NN)NNNFF)Nrq  NNNNN)N)N)Nr  Nr   )NTNNNN)r  )r   NNN)r   )TF)TNr`  FTF)NNF)Nr  r  r  )
NNNNNNr  NNN)r  r  r  __doc____annotations__r  r  classmethodr<  r  r   r.  setterr   r   r?  r   r7  rK  rL  rU  rX  r\  r^  ra  rc  r`  rb  rE  rw  rv  rg  rJ   r{  r~  r  r  rs  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r$  r  r  __hash__r  r/  r  r  r3  r  r-  r,  r  r  r  r  r  r  r  r  r   r  r   r
  r  r  r  r  r!  r"  r*  r+  r.  r8  r  r-  r9  r:  r<  rC  rT  r  r  r[  r]  rf  rj  r  rg  rh  rl  rv  r  r  r  r  r  r2   r  r  r  r  r  r  	frozensetrQ  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r'  r*  r1  rL  r:  r=  rK  rO  rM  rQ  rR  rV  r!   ZUncachedAccessorrW   Zplotr[  r+   r]  rp  rx  rz  r~  r  r  r  r  r  r   r   r  r  r  r  r  r  r   r   r   r   r     s.  
z  $
'	

3    " 5   K  g  ++	I@  (	        $       $     &        "l            *     
*            ( #(M+(  "`$+   $X03X*>(D( [(    (     &b, 1)m      'r r 4 <$=&6  v (5f*,d"<"7  9 GE$,";  ">R    * *h $? $`  &	   % O  I.Z  ,	  Y H  WY     , 7 ; "H ?8 K


_  (o    , G      4 = c a;>   (d     4 :,   (~"  9     .R  $)   *.         )N)r   )NNr   FF)
__future__r   rs  datetimer   r   r  r  r   collectionsr   htmlr   Znumbersr   operatorr   osr   typingr   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   Znumpyr   r  r   Zxarray.coding.calendar_opsr   r   r  r   r   rJ  r   r   r  r   r   r   r    r!   Zxarray.core._aggregationsr"   r  r#   r$   r%   Zxarray.core.arithmeticr&   Zxarray.core.commonr'   r(   r)   r  r+   Zxarray.core.coordinatesr,   r-   Zxarray.core.duck_array_opsr.   Zxarray.core.indexesr/   r0   r1   r2   r3   r4   r5   r6   r7   r8   Zxarray.core.indexingr9   r:   Zxarray.core.merger;   r<   r=   r>   r  r?   Zxarray.core.optionsr@   rA   Zxarray.core.pycompatrB   rC   Zxarray.core.typesrD   rE   Zxarray.core.utilsrF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rG  rR   rS   rT   rU   rV   Zxarray.plot.accessorrW   Znumpy.typingrX   Zxarray.backendsrY   rZ   r  r[   r\   r]   r   r_   r  ra   rb   r  rd   r  re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   rq   rr   rs   rt   ru   rv   rw   rx   r  rz   Zdask.delayedr{   rR  r	  r|   r  Z_DATETIMEINDEX_COMPONENTSr   r   r   r   r   r   r   r   r  r   r   r   r   r   <module>   s   D08P

 %?     
 5

