U
    CvfHg                     @  s  d dl mZ d dlmZmZmZmZmZmZ d dl	Z
d dlmZmZ d dlmZ d dlmZ d dlmZmZ d dlmZmZmZmZ d d	lmZmZ d d
lmZ d dlmZ  erd dlm!Z!m"Z"m#Z#m$Z$ eddddej%ddfddddddddddd
ddZeddddej%ddfddddddddddd
d dZddddej%ddfdddd!d"dZd#d$d%d&d'Z&d(d) Z'dd*d+d,d-Z(ej%ddfd.d/d0d0ddddddd1
d2d3Z)ej%ddfdd/d0d0ddddddd4
d5d6Z*dS )7    )annotations)TYPE_CHECKINGAnyHashableIterablecastoverloadN)dtypesutils)align)lazy_array_equiv)IndexPandasIndex)_VALID_COMPATcollect_variables_and_indexesmerge_attrsmerge_collected)T_DataArray	T_Dataset)Variable)concat)CombineAttrsOptionsCompatOptionsConcatOptionsJoinOptionsall	differentequalsouteroverridezIterable[T_Dataset]z!Hashable | T_DataArray | pd.IndexzConcatOptions | list[Hashable]r   zIterable[Iterable[int]] | Noneobjectr   r   r   )
objsdim	data_varscoordscompat	positions
fill_valuejoincombine_attrsreturnc	           	      C  s   d S N 	r!   r"   r#   r$   r%   r&   r'   r(   r)   r,   r,   6/tmp/pip-unpacked-wheel-h316xyqg/xarray/core/concat.pyr      s    r   zIterable[T_DataArray]r   c	           	      C  s   d S r+   r,   r-   r,   r,   r.   r   -   s    )r%   r(   r)   c	                 C  s   ddl m}	 ddlm}
 zt| \}} W n tk
rF   tdY nX |tkr`td|dt	||	rt
| ||||||||d	S t	||
rt| ||||||||d	S tdt| d	S )
a  Concatenate xarray objects along a new or existing dimension.

    Parameters
    ----------
    objs : sequence of Dataset and DataArray
        xarray objects to concatenate together. Each object is expected to
        consist of variables and coordinates with matching shapes except for
        along the concatenated dimension.
    dim : Hashable or DataArray or pandas.Index
        Name of the dimension to concatenate along. This can either be a new
        dimension name, in which case it is added along axis=0, or an existing
        dimension name, in which case the location of the dimension is
        unchanged. If dimension is provided as a DataArray or Index, its name
        is used as the dimension to concatenate along and the values are added
        as a coordinate.
    data_vars : {"minimal", "different", "all"} or list of Hashable, optional
        These data variables will be concatenated together:
          * "minimal": Only data variables in which the dimension already
            appears are included.
          * "different": Data variables which are not equal (ignoring
            attributes) across all datasets are also concatenated (as well as
            all for which dimension already appears). Beware: this option may
            load the data payload of data variables into memory if they are not
            already loaded.
          * "all": All data variables will be concatenated.
          * list of dims: The listed data variables will be concatenated, in
            addition to the "minimal" data variables.

        If objects are DataArrays, data_vars must be "all".
    coords : {"minimal", "different", "all"} or list of Hashable, optional
        These coordinate variables will be concatenated together:
          * "minimal": Only coordinates in which the dimension already appears
            are included.
          * "different": Coordinates which are not equal (ignoring attributes)
            across all datasets are also concatenated (as well as all for which
            dimension already appears). Beware: this option may load the data
            payload of coordinate variables into memory if they are not already
            loaded.
          * "all": All coordinate variables will be concatenated, except
            those corresponding to other dimensions.
          * list of Hashable: The listed coordinate variables will be concatenated,
            in addition to the "minimal" coordinates.
    compat : {"identical", "equals", "broadcast_equals", "no_conflicts", "override"}, optional
        String indicating how to compare non-concatenated variables of the same name for
        potential conflicts. This is passed down to merge.

        - "broadcast_equals": all values must be equal when variables are
          broadcast against each other to ensure common dimensions.
        - "equals": all values and dimensions must be the same.
        - "identical": all values, dimensions and attributes must be the
          same.
        - "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
    positions : None or list of integer arrays, optional
        List of integer arrays which specifies the integer positions to which
        to assign each dataset along the concatenated dimension. If not
        supplied, objects are concatenated in the provided order.
    fill_value : scalar or dict-like, optional
        Value to use for newly missing values. If a dict-like, maps
        variable names to fill values. Use a data array's name to
        refer to its values.
    join : {"outer", "inner", "left", "right", "exact"}, optional
        String indicating how to combine differing indexes
        (excluding dim) in objects

        - "outer": use the union of object indexes
        - "inner": use the intersection of object indexes
        - "left": use indexes from the first object with each dimension
        - "right": use indexes from the last object with each dimension
        - "exact": instead of aligning, raise `ValueError` when indexes to be
          aligned are not equal
        - "override": if indexes are of same size, rewrite indexes to be
          those of the first object with that dimension. Indexes for the same
          dimension must have the same size in all objects.
    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
    -------
    concatenated : type of objs

    See also
    --------
    merge

    Examples
    --------
    >>> da = xr.DataArray(
    ...     np.arange(6).reshape(2, 3), [("x", ["a", "b"]), ("y", [10, 20, 30])]
    ... )
    >>> da
    <xarray.DataArray (x: 2, y: 3)>
    array([[0, 1, 2],
           [3, 4, 5]])
    Coordinates:
      * x        (x) <U1 'a' 'b'
      * y        (y) int64 10 20 30

    >>> xr.concat([da.isel(y=slice(0, 1)), da.isel(y=slice(1, None))], dim="y")
    <xarray.DataArray (x: 2, y: 3)>
    array([[0, 1, 2],
           [3, 4, 5]])
    Coordinates:
      * x        (x) <U1 'a' 'b'
      * y        (y) int64 10 20 30

    >>> xr.concat([da.isel(x=0), da.isel(x=1)], "x")
    <xarray.DataArray (x: 2, y: 3)>
    array([[0, 1, 2],
           [3, 4, 5]])
    Coordinates:
      * x        (x) <U1 'a' 'b'
      * y        (y) int64 10 20 30

    >>> xr.concat([da.isel(x=0), da.isel(x=1)], "new_dim")
    <xarray.DataArray (new_dim: 2, y: 3)>
    array([[0, 1, 2],
           [3, 4, 5]])
    Coordinates:
        x        (new_dim) <U1 'a' 'b'
      * y        (y) int64 10 20 30
    Dimensions without coordinates: new_dim

    >>> xr.concat([da.isel(x=0), da.isel(x=1)], pd.Index([-90, -100], name="new_dim"))
    <xarray.DataArray (new_dim: 2, y: 3)>
    array([[0, 1, 2],
           [3, 4, 5]])
    Coordinates:
        x        (new_dim) <U1 'a' 'b'
      * y        (y) int64 10 20 30
      * new_dim  (new_dim) int64 -90 -100
    r   	DataArrayDatasetz.must supply at least one object to concatenatezcompat=zY invalid: must be 'broadcast_equals', 'equals', 'identical', 'no_conflicts' or 'override')r"   r#   r$   r%   r&   r'   r(   r)   z?can only concatenate xarray Dataset and DataArray objects, got N)xarray.core.dataarrayr0   xarray.core.datasetr2   r
   Zpeek_atStopIteration
ValueErrorr   
isinstance_dataarray_concat_dataset_concat	TypeErrortype)r!   r"   r#   r$   r%   r&   r'   r(   r)   r0   r2   Z	first_objr,   r,   r.   r   <   sL     #


zHashable | Anyz#tuple[Hashable, PandasIndex | None])dim_or_datar*   c                 C  sr   ddl m} t| tr | }d}nJt| |tfsHt| dd}|dkrPd}n| j\}t| dd}t| ||d}||fS )zInfer the dimension name and 1d index / coordinate variable (if appropriate)
    for concatenating along the new dimension.

    r   r/   NnameZ
concat_dimdtypecoord_dtype)r3   r0   r7   strr   getattrdimsr   )r<   r0   r"   indexr@   r,   r,   r.   _calc_concat_dim_index
  s    
rE   c           
        s   t  i |kr"d} nd}g }D ]V}|rR|jkrR|krR|}fdd|j D  ||jd q. fdd}	|	|d |	|d	 |fS )
zR
    Determine which dataset variables need to be concatenated in the result,
    TFc                 3  s    | ]\}} |j kr|V  qd S r+   rC   .0kvr"   r,   r.   	<genexpr>9  s     
 z$_calc_concat_over.<locals>.<genexpr>   c                   sH  t | tr| dkrdkr.td dtd D ]b  kr<d  <  fddD }t|dkrx qn,t|tkr| dkrt d	 d
|dd  D ].}t|d |td <   dk	r qq  dkr  q<  d kr<d j   }g }dd  D ]p}|j  	 }|
| t||s&  d < tdd  |D ]\}}	|	j|j  _qv q<q&d < q<nR| dkrֈttd td j  n | dkrntd d|  nLfdd| D }
|
r:dkr,td|
 ntd|
 |  d S )Nr   r   zCannot specify both z#='different' and compat='override'.r   c                   s    g | ]} |j kr|j   qS r,   )	variablesrH   dsrI   r,   r.   
<listcomp>H  s    
 zA_calc_concat_over.<locals>.process_subset_opt.<locals>.<listcomp>rM   z@ not present in all datasets and coords='different'. Either add z= to datasets where it is missing or specify coords='minimal'.)equivTFr   Zminimalzunexpected value for z: c                   s"   g | ]}|t  d  kr|qS )r   )rB   rH   rI   )datasetssubsetr,   r.   rR     s      r$   zCsome variables in coords are not coordinates on the first dataset: zIsome variables in data_vars are not data variables on the first dataset: )r7   rA   r6   rB   lenr   addrN   loadZcomputeappendzipdataupdatesetrC   )optrV   rN   varZv_lhsZcomputedZds_rhsZv_rhsrP   rJ   Zinvalid_vars)r%   concat_overrU   r   )rI   rV   r.   process_subset_opt<  sr    


 





z-_calc_concat_over.<locals>.process_subset_optr#   r$   )	r^   rX   rC   
set_coordsr]   rN   itemsrZ   get)
rU   r"   	dim_namesr#   r$   r%   Zconcat_over_existing_dimconcat_dim_lengthsrP   rb   r,   )r%   ra   rU   r"   r   r.   _calc_concat_over%  s$    

V

rh   zRtuple[dict[Hashable, Variable], dict[Hashable, int], set[Hashable], set[Hashable]])rU   r*   c                 C  s   t  }t  }t  }i }i }| D ]d}||j ||j ||j |jD ]&}||krZqL||krL|j| j||< qL|t |jB }q||||fS r+   )r^   r]   rC   r$   r#   variable)rU   rC   Zall_coord_namesr#   
dim_coords
dims_sizesrP   r"   r,   r,   r.   _parse_datasets  s     
rl   zlist[T_Dataset]zstr | T_DataArray | pd.Indexzstr | list[str])
rU   r"   r#   r$   r%   r&   r'   r(   r)   r*   c	           '   	     s4  ddl m}	 ddlm  tt fddD s>tdt|	rPj}
ntt	r`}
nd}
t
\}dd	 D tt|d
g|dt\}}}t|}|| }||@ }|rt|d|d d |ks|kr|krfdd	D t||||\}}||B | | i }i }rfddtt D }t|||d\}}|| || || tdd	 D |}d j}dd D ](}|dkrt|j|stdqƇfdd}fdd}d jD ]t|krt|krtz|fdd	D }W n$ tk
rp   tdY nX t|}|rZt|tk rtdt| dt d|d ||d jkrd j } nd  ji} |fdd| D  !| }!|! D ].\}"tfdd	D |d |"_|"|< q(nt"|||d }#|#|< n|kr||< qt#d ||d!}$|t|$j }%|%rtd"|%d#|$$|}$||$_|$j%|d$d%}$|dk	r&|
dk	r
|!|
i}&n|! }&|& |$< ||< |$&|}$|$S )&zN
    Concatenate a sequence of datasets along a new or existing dimension
    r   r/   r1   c                 3  s   | ]}t | V  qd S r+   r7   )rH   Zdatasetr1   r,   r.   rL     s     z"_dataset_concat.<locals>.<genexpr>SThe elements in the input list need to be either all 'Dataset's or all 'DataArray'sNc                 S  s   g | ]}|  qS r,   )copyrO   r,   r,   r.   rR     s     z#_dataset_concat.<locals>.<listcomp>F)r(   ro   excluder'   z1 is a coordinate in some datasets but not others.c                   s   g | ]}t t| qS r,   )r   r   Zexpand_dimsrO   rK   r,   r.   rR     s     c                   s   i | ]\}}| kr||qS r,   r,   rG   )variables_to_merger,   r.   
<dictcomp>  s    z#_dataset_concat.<locals>.<dictcomp>)r%   r   c                 S  s   g | ]
}|j qS r,   attrsrO   r,   r,   r.   rR     s     rM   	identicalz$Dataset global attributes not equal.c                 3  sv   t tdd | D }|kr*f| }t| D ]<\} |j|krjt  fdd|D }|||}|V  q4d S )Nc                 S  s   g | ]}|j D ]}|qqS r,   rF   )rH   rJ   dr,   r,   r.   rR     s       z?_dataset_concat.<locals>.ensure_common_dims.<locals>.<listcomp>c                 3  s   | ]} | V  qd S r+   )re   )rH   rv   )dim_lenrk   r,   r.   rL     s     z>_dataset_concat.<locals>.ensure_common_dims.<locals>.<genexpr>)tuplepduniquer[   rC   set_dims)varsZcommon_dimsr`   Zcommon_shape)rg   r"   rk   )rw   r.   ensure_common_dims  s    

z+_dataset_concat.<locals>.ensure_common_dimsc                 3  s\    D ]R}| |j kr |j |  V  q| kr|j|  }|js|j}t||jdV  qd S )Nr?   )_indexesZ
_variablesrC   r{   valuesr   r>   )r=   rP   r`   r\   )rU   r"   r,   r.   get_indexes"  s    

z$_dataset_concat.<locals>.get_indexesc                   s   g | ]}|  j qS r,   )ri   rO   )r=   r,   r.   rR   1  s     z  is not present in all datasets.z> must have either an index or no index in all datasets, found /z datasets with an index.c                   s   i | ]
}| qS r,   r,   rT   )combined_idxr,   r.   rr   D  s      c                   s   g | ]}|j   jqS r,   )rN   rt   rO   rQ   r,   r.   rR   H  s     )r)   rs   z
Variables z1 are coordinates in some datasets but not others.ignore)errors)'r3   r0   r4   r2   listr   r:   r7   ri   r   rE   r   rl   r^   r6   poprh   r   rd   r   r]   r   encodingr
   Z
dict_equivrt   rN   KeyErrorrW   r   r~   ZxindexesZget_all_coordsZcreate_variablesconcat_varsr;   rc   Z	drop_varsZ_overwrite_indexes)'rU   r"   r#   r$   r%   r&   r'   r(   r)   r0   Zdim_varrD   rj   Zcoord_namesZ
data_namesrf   Zunlabeled_dimsZboth_data_and_coordsra   r   Zresult_varsZresult_indexesZgroupedZmerged_varsZmerged_indexesZresult_attrsZresult_encodingrP   r}   r   r|   ZindexesZidx_varsZcombined_idx_varsrJ   Zcombined_varresultZabsent_coord_namesZ
index_varsr,   )	r2   r   rg   rU   r"   rk   rI   r=   rq   r.   r9     s    

     

  





   






r9   )
arraysr"   r#   r$   r%   r&   r'   r(   r)   r*   c	                   s   ddl m  t| } t fdd| D s2td|dkrBtdg }	t| D ]R\}
}|
dkrf|j}n,||jkr|dkrtd	ntt	|
|}|	|  qNt|	||||||||d
	}tdd | D |}| d ||}||_|S )Nr   r/   c                 3  s   | ]}t | V  qd S r+   rm   )rH   arrayr/   r,   r.   rL     s     z$_dataarray_concat.<locals>.<genexpr>rn   r   zFdata_vars is not a valid argument when concatenating DataArray objectsru   zarray names not identical)r'   r(   r)   c                 S  s   g | ]
}|j qS r,   rs   )rH   dar,   r,   r.   rR     s     z%_dataarray_concat.<locals>.<listcomp>)r3   r0   r   r   r:   r6   	enumerater=   r   r   renamerZ   Z_to_temp_datasetr9   r   Z_from_temp_datasetrt   )r   r"   r#   r$   r%   r&   r'   r(   r)   rU   nZarrr=   rP   Zmerged_attrsr   r,   r/   r.   r8   q  sD    

r8   )+
__future__r   typingr   r   r   r   r   r   Zpandasry   Zxarray.corer	   r
   Zxarray.core.alignmentr   Zxarray.core.duck_array_opsr   Zxarray.core.indexesr   r   Zxarray.core.merger   r   r   r   Zxarray.core.typesr   r   Zxarray.core.variabler   r   r   r   r   r   r   ZNArE   rh   rl   r9   r8   r,   r,   r,   r.   <module>   sf    $$ Os"" F