U
    CvfI$                    @  sV  U d Z ddlm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
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mZmZm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' ddl(m)Z)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3 e
rTddl4m5Z5 ddl6m7Z7 ddl8m9Z9 ddl-m:Z:m;Z; e<dZ=e<dZ>e?ddhZ@dd ZAdd ZBG dd dZCdd d!d"d#ZDdd$d%d&d'ZEe? d(fddd)d*d+d,d-d.ZFde? d(d/dd0d1d2d3d4ZGd5d6d7d8d9ZHd5d6d7d:d;ZId<d= ZJeIeHeKdeKd>eJd?ZLd@eMdA< ddBdCd6dDdEdFZNddBd6dGdHdIdJdKZOdLdM ZPdNdOdPdQdRdSZQdddTddUdVdWZRdXdYdZd[d\d]d^ZSdde=e? d(d_dd`dadbdcZTddde ZUdfdg ZVe? fdhd)didjdkdlZWeXdZYdmdndnd dodpdqZZdrds Z[e? dtddud(ddvddwdadxdyZ\dtdzd{d|Z]dd}e? dudde=dddtddddd~dd ddd)dd0dCdGdddCddd dd dddZ^dddZ_dddZ`dddddddZadddddddZbdddd dddZcdddZdeddddddddZeeddd[dd[dddZeedd[ddd[dddZeedd[d[dd[dddZeeddddddddZeddddddddZedddddZfddejgdddddd ddddZheded dZieded dZjeded dZkedddddZleddddddZledddddddZleddd!ddZlddd!ddZldS )zO
Functions for applying functions that act on arrays to xarray's labeled data.
    )annotationsN)Counter)TYPE_CHECKINGAbstractSetAnyCallableHashableIterableMappingSequenceTypeVarUnionoverload)dtypesduck_array_opsutils)align
deep_align)
zeros_like)datetime_to_numeric)Indexfilter_indexes_from_coords)merge_attrsmerge_coordinates_without_align)OPTIONS_get_keep_attrsis_duck_dask_array)T_DataArray)is_dict_like	is_scalarVariable)Coordinates	DataArrayDataset)CombineAttrsOptionsJoinOptionsz<no-fill-value>z<default-name>innerexactc                 C  s(   | D ]}t ||r|  S qtddS )z@Return either first object of type 'kind' or raise if not found.zThis should be unreachable.N)
isinstance
ValueError)argskindarg r1   ;/tmp/pip-unpacked-wheel-h316xyqg/xarray/core/computation.py_first_of_type2   s    

r3   c                   s    fdd| D S )z!Return all objects of type 'kind'c                   s   g | ]}t | r|qS r1   r,   .0r0   r/   r1   r2   
<listcomp><   s     
 z _all_of_type.<locals>.<listcomp>r1   )r.   r/   r1   r7   r2   _all_of_type:   s    r9   c                   @  s   e Zd ZdZdZdddZedd Zedd	 Zed
d Z	edd Z
edd Zedd Zdd Zdd Zdd Zdd Ze fddZdS )_UFuncSignatureaJ  Core dimensions signature for a given function.

    Based on the signature provided by generalized ufuncs in NumPy.

    Attributes
    ----------
    input_core_dims : tuple[tuple]
        Core dimension names on each input variable.
    output_core_dims : tuple[tuple]
        Core dimension names on each output variable.
    )input_core_dimsoutput_core_dims_all_input_core_dims_all_output_core_dims_all_core_dimsr1   c                 C  s>   t dd |D | _t dd |D | _d | _d | _d | _d S )Nc                 s  s   | ]}t |V  qd S Ntupler6   ar1   r1   r2   	<genexpr>U   s     z+_UFuncSignature.__init__.<locals>.<genexpr>c                 s  s   | ]}t |V  qd S rA   rB   rD   r1   r1   r2   rF   V   s     )rC   r;   r<   r=   r>   r?   )selfr;   r<   r1   r1   r2   __init__T   s
    z_UFuncSignature.__init__c                 C  s&   | j d kr tdd | jD | _ | j S )Nc                 s  s   | ]}|D ]
}|V  q
qd S rA   r1   r6   dimsdimr1   r1   r2   rF   ^   s      z6_UFuncSignature.all_input_core_dims.<locals>.<genexpr>)r=   	frozensetr;   rG   r1   r1   r2   all_input_core_dims[   s
    

z#_UFuncSignature.all_input_core_dimsc                 C  s&   | j d kr tdd | jD | _ | j S )Nc                 s  s   | ]}|D ]
}|V  q
qd S rA   r1   rI   r1   r1   r2   rF   f   s      z7_UFuncSignature.all_output_core_dims.<locals>.<genexpr>)r>   rL   r<   rM   r1   r1   r2   all_output_core_dimsc   s
    

z$_UFuncSignature.all_output_core_dimsc                 C  s   | j d kr| j| jB | _ | j S rA   )r?   rN   rO   rM   r1   r1   r2   all_core_dimsk   s    
z_UFuncSignature.all_core_dimsc                 C  s   dd t t| jD S )Nc                 S  s   i | ]\}}|d | qS rK   r1   )r6   nZcore_dimr1   r1   r2   
<dictcomp>s   s     z,_UFuncSignature.dims_map.<locals>.<dictcomp>)	enumeratesortedrP   rM   r1   r1   r2   dims_mapq   s    z_UFuncSignature.dims_mapc                 C  s
   t | jS rA   )lenr;   rM   r1   r1   r2   
num_inputsw   s    z_UFuncSignature.num_inputsc                 C  s
   t | jS rA   )rW   r<   rM   r1   r1   r2   num_outputs{   s    z_UFuncSignature.num_outputsc                 C  s6   z| j |j ko| j|jkW S  tk
r0   Y dS X d S )NF)r;   r<   AttributeErrorrG   otherr1   r1   r2   __eq__   s    
z_UFuncSignature.__eq__c                 C  s
   | |k S rA   r1   r[   r1   r1   r2   __ne__   s    z_UFuncSignature.__ne__c                 C  s    d t| jt| jt| jS )Nz{}({!r}, {!r}))formattype__name__listr;   r<   rM   r1   r1   r2   __repr__   s
    z_UFuncSignature.__repr__c                 C  s:   d dd | jD }d dd | jD }| d| S )N,c                 s  s   | ]}d  d|V  qdS z({})rd   Nr_   joinr6   rJ   r1   r1   r2   rF      s     z*_UFuncSignature.__str__.<locals>.<genexpr>c                 s  s   | ]}d  d|V  qdS re   rf   rh   r1   r1   r2   rF      s     z->)rg   r;   r<   )rG   lhsrhsr1   r1   r2   __str__   s    z_UFuncSignature.__str__c                   sz   fddj D }fddjD }rdfddD t fdd  fdd|D }t||}t|S )zCreate an equivalent signature string for a NumPy gufunc.

        Unlike __str__, handles dimensions that don't map to Python
        identifiers.

        Also creates unique names for input_core_dims contained in exclude_dims.
        c                   s   g | ]} fd d|D qS )c                   s   g | ]} j | qS r1   rV   r6   rK   rM   r1   r2   r8      s     ?_UFuncSignature.to_gufunc_string.<locals>.<listcomp>.<listcomp>r1   r6   	core_dimsrM   r1   r2   r8      s   z4_UFuncSignature.to_gufunc_string.<locals>.<listcomp>c                   s   g | ]} fd d|D qS )c                   s   g | ]} j | qS r1   rl   rm   rM   r1   r2   r8      s     rn   r1   ro   rM   r1   r2   r8      s   c                   s   g | ]} j | qS r1   rl   rm   rM   r1   r2   r8      s     c                   s.   | kr* |  }  | g |  d| } | S )N_)update)rK   rR   )counterexclude_dimsr1   r2   
_enumerate   s
    z4_UFuncSignature.to_gufunc_string.<locals>._enumeratec                   s   g | ]} fd d|D qS )c                   s   g | ]} |qS r1   r1   rm   ru   r1   r2   r8      s     rn   r1   r5   rv   r1   r2   r8      s    )r;   r<   r   r`   str)rG   rt   r;   r<   Zalt_signaturer1   )ru   rs   rt   rG   r2   to_gufunc_string   s    


z _UFuncSignature.to_gufunc_stringN)r@   )ra   
__module____qualname____doc__	__slots__rH   propertyrN   rO   rP   rV   rX   rY   r]   r^   rc   rk   rL   rx   r1   r1   r1   r2   r:   ?   s(   






	r:   zIterable[Any]r   )objectsreturnc                 C  s4   dd | D }| t t|dkr,|\}nd }|S )Nc                 S  s   h | ]}t |d tqS )name)getattr_DEFAULT_NAMEr6   objr1   r1   r2   	<setcomp>   s     zresult_name.<locals>.<setcomp>   )discardr   rW   )r~   namesr   r1   r1   r2   result_name   s    
r   zlist[Coordinates])r.   r   c              	   C  s<   g }| D ].}z
|j }W n tk
r*   Y qX || q|S rA   )coordsrZ   append)r.   coords_listr0   r   r1   r1   r2   _get_coords_list   s    
r   overrider   r(   z8tuple[list[dict[Any, Variable]], list[dict[Any, Index]]])r.   	signaturert   combine_attrsr   c                   s   t | }t|dkr4|s4|\}t|j}t|j}nt|||d\}}g }g }	|jD ]X}
|jt|
   r fdd|	 D }t
|t|}n|}|}|| |	| qT||	fS )a  Build output coordinates and indexes for an operation.

    Parameters
    ----------
    args : Iterable
        List of raw operation arguments. Any valid types for xarray operations
        are OK, e.g., scalars, Variable, DataArray, Dataset.
    signature : _UfuncSignature
        Core dimensions signature for the operation.
    exclude_dims : set, optional
        Dimensions excluded from the operation. Coordinates along these
        dimensions are dropped.
    combine_attrs : {"drop", "identical", "no_conflicts", "drop_conflicts",                      "override"} or callable, default: "drop"
        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
    -------
    Dictionaries of Variable and Index objects with merged coordinates.
    r   )rt   r   c                   s"   i | ]\}}  |jr||qS r1   )
isdisjointrJ   )r6   kvZdropped_dimsr1   r2   rS     s      z3build_output_coords_and_indexes.<locals>.<dictcomp>)r   rW   dict	variablesZxindexesr   r<   rN   setitemsr   r   )r.   r   rt   r   r   Zunpacked_coordsZmerged_varsZmerged_indexesZoutput_coordsZoutput_indexesoutput_dimsZfiltered_coordsZfiltered_indexesr1   r   r2   build_output_coords_and_indexes   s6    '
  


 
r   )rg   rt   
keep_attrsr)   z!tuple[DataArray, ...] | DataArray)r   rg   r   c                  s  ddl m  t|dkr*t||d|dd}t| }|dkrFt|nt| }|jt||||d\}}	dd	 |D }
| |
 }|j	dkrt
 fd
dt|||	D }n|\}|	\} |||dd}tdd	 |D |d}t|t
r|D ]
}||_qn||_|S )zYApply a variable level function over DataArray, Variable and/or ndarray
    objects.
    r   r$   r   Frg   copyexcludeZraise_on_invaliddropr   c                 S  s   g | ]}t |d |qS )variabler   rD   r1   r1   r2   r8   :  s     z)apply_dataarray_vfunc.<locals>.<listcomp>c                 3  s&   | ]\}}} |||d dV  qdS )Tr   indexesr   fastpathNr1   )r6   r   r   r   r%   r   r1   r2   rF   ?  s       z(apply_dataarray_vfunc.<locals>.<genexpr>Tr   c                 S  s   g | ]
}|j qS r1   attrsr6   xr1   r1   r2   r8   N  s     )xarray.core.dataarrayr%   rW   r   r9   r   r3   r   r   rY   rC   zipr   r,   r   )funcr   rg   rt   r   r.   objsZ	first_objZresult_coordsZresult_indexes	data_varsZ
result_varoutr   r   r   dar1   r   r2   apply_dataarray_vfunc  sZ        


   

  
	    

r   zlist[Iterable]r	   )all_keysr   c                 C  s   dd | D   S )Nc                 S  s   i | ]}|D ]
}|d qqS rA   r1   )r6   keyskeyr1   r1   r2   rS   Y  s
        z%ordered_set_union.<locals>.<dictcomp>r   )r   r1   r1   r2   ordered_set_unionX  s    r   c                   s>   t | d  | dd  D ]} | q fdd| d D S )Nr   r   c                   s   g | ]}| kr|qS r1   r1   )r6   r   intersectionr1   r2   r8   `  s      z,ordered_set_intersection.<locals>.<listcomp>)r   intersection_update)r   r   r1   r   r2   ordered_set_intersection\  s    r   c                 C  s:   | d }| dd  D ] }||krt d|d|q|S )Nr   r   z6exact match required for all data variable names, but  != )r-   )r   Z
first_keysr   r1   r1   r2   assert_and_return_exact_matchc  s    r   )r*   outerleftrightr+   zdict[str, Callable]_JOINERSzIterable[Mapping | Any]rw   )r~   howr   c                 C  s   t | }dd | D }||S )Nc                 S  s   g | ]}t |d r| qS r   )hasattrr   r   r1   r1   r2   r8   y  s     
 z"join_dict_keys.<locals>.<listcomp>)r   )r~   r   joinerr   r1   r1   r2   join_dict_keysw  s    r   objectz
list[list])r~   r   
fill_valuer   c                   s    fdd|D S )Nc                   s    g | ]  fd dD qS )c                   s$   g | ]}t |r| n|qS r1   )r   getr   )r   r   r1   r2   r8     s     z2collect_dict_values.<locals>.<listcomp>.<listcomp>r1   )r6   r   r~   )r   r2   r8     s   z'collect_dict_values.<locals>.<listcomp>r1   )r~   r   r   r1   r   r2   collect_dict_values}  s    r   c                 C  sL   z| j W S  tk
rF   z| jW  Y S  tk
r@   |  Y  Y S X Y nX d S rA   )r   rZ   r   )r0   r1   r1   r2   _as_variables_or_variable  s    r   z"Mapping[Any, tuple[Variable, ...]]intz$tuple[dict[Hashable, Variable], ...])result_varsrY   r   c                 C  sH   t dd t|D }|  D ]$\}}t||D ]\}}|||< q0q|S )Nc                 s  s   | ]
}i V  qd S rA   r1   )r6   rq   r1   r1   r2   rF     s     z&_unpack_dict_tuples.<locals>.<genexpr>)rC   ranger   r   )r   rY   r   r   valuesvalueZresults_dictr1   r1   r2   _unpack_dict_tuples  s
    r   )rg   r   r   c          
      G  sl   t dd |D }t||d}t|||}i }t||D ]\}}	| |	 ||< q8|jdkrdt||jS |S dS )zjApply a variable level function over dicts of DataArray, DataArray,
    Variable and ndarray objects.
    c                 s  s   | ]}t |V  qd S rA   )r   r5   r1   r1   r2   rF     s     z0apply_dict_of_variables_vfunc.<locals>.<genexpr>)r   r   N)rC   r   r   r   rY   r   )
r   r   rg   r   r.   r   Zgrouped_by_namer   r   Zvariable_argsr1   r1   r2   apply_dict_of_variables_vfunc  s    
r   zdict[Hashable, Variable]zMapping[Hashable, Variable]zdict[Hashable, Index]r'   )r   coord_variablesr   r   c                 C  s.   ddl m} | | t|}|j| ||dS )zdCreate a dataset as quickly as possible.

    Beware: the `variables` dict is modified INPLACE.
    r   r&   r   )xarray.core.datasetr'   rr   r   Z_construct_direct)r   r   r   r'   Zcoord_namesr1   r1   r2   _fast_dataset  s    	
r   )rg   dataset_joinr   rt   r   zDataset | tuple[Dataset, ...])r   r   c                G  s  ddl m} |tkr$|tkr$tdt||}	t|dkrLt||d|dd}t||||d\}
}t	dd	 |D }t
| f||||d
}|jdkrt	dd	 t||
|D }n|
\}|\}t|||d}tdd |	D |d}t|t	r|D ]
}||_qn||_|S )zuApply a variable level function over Dataset, dict of DataArray,
    DataArray, Variable and/or ndarray objects.
    r   r&   zto apply an operation to datasets with different data variables with apply_ufunc, you must supply the dataset_fill_value argument.r   Fr   r   c                 s  s   | ]}t |d |V  qdS )r   Nr   r5   r1   r1   r2   rF     s     z&apply_dataset_vfunc.<locals>.<genexpr>)r   rg   r   c                 s  s   | ]}t | V  qd S rA   )r   )r6   r.   r1   r1   r2   rF     s   r   c                 S  s   g | ]
}|j qS r1   r   r   r1   r1   r2   r8     s     z'apply_dataset_vfunc.<locals>.<listcomp>)r   r'   _JOINS_WITHOUT_FILL_VALUES_NO_FILL_VALUE	TypeErrorr9   rW   r   r   rC   r   rY   r   r   r   r,   r   )r   r   rg   r   r   rt   r   r.   r'   r   Zlist_of_coordsZlist_of_indexesr   r   Z
coord_varsr   r   dsr1   r1   r2   apply_dataset_vfunc  sV    
       
  




r   c              
   c  sf   ddl m} d}|D ]L}z| jf ||i}W n, ttfk
rX   |dkrP|| }|}Y nX |V  qdS )zBIterate over selections of an xarray object in the provided order.r   )_dummy_copyN)xarray.core.groupbyr   selKeyError
IndexError)r   rK   r   r   dummyr   Zobj_selr1   r1   r2   _iter_over_selections  s    
r   c                   sD  ddl m m} ddlm}  fdd|D }|s:td|d tfdd|d	d
 D rhtdjj	}j
j}g }|D ]f}t| rdd |D }	n>t|dr||jkrt||rtdt|||}	n
t|}	||	 qfddt| D }
||
\}}
jt|tr8tfddt|
 D }n|
}|S )zvApply a dataset or datarray level function over GroupBy, Dataset,
    DataArray, Variable and/or ndarray objects.
    r   )GroupBypeek_atr!   c                   s   g | ]}t | r|qS r1   r4   r5   r   r1   r2   r8     s     
 z&apply_groupby_func.<locals>.<listcomp>z.must have at least one groupby to iterate overc                 3  s   | ]} j |j  V  qd S rA   )_groupequals)r6   gb)first_groupbyr1   r2   rF     s     z%apply_groupby_func.<locals>.<genexpr>r   Nzrapply_ufunc can only perform operations over multiple GroupBy objects at once if they are all grouped the same wayc                 s  s   | ]\}}|V  qd S rA   r1   )r6   rq   r   r1   r1   r2   rF     s     rJ   zugroupby operations cannot be performed with xarray.Variable objects that share a dimension with the grouped dimensionc                 3  s   | ]} | V  qd S rA   r1   )r6   Zzipped_args)r   r1   r2   rF   ,  s     c                 3  s   | ]} |V  qd S rA   r1   )r6   output)combiner1   r2   rF   0  s     )r   r   r   xarray.core.variabler"   AssertionErroranyr-   r   r   Z_unique_coordr   r,   r   rJ   r   	itertoolsrepeatr   r   Z_combinerC   )r   r.   r   r"   ZgroupbysZgrouped_dimZunique_values	iteratorsr0   iteratorZappliedZapplied_exampleZcombinedr1   )r   r   r   r   r2   apply_groupby_func  s<    


r   zIterable[Variable]zdict[Hashable, int])r   rt   r   c              	   C  s   i }| D ]}t t|jt |jk r8tdt|j t|j|jD ]L\}}||krF||krh|||< qF|| |krFtd| d||  d| qFq|S )Nz?broadcasting cannot handle duplicate dimensions on a variable: zLoperands cannot be broadcast together with mismatched lengths for dimension z: z vs )rW   r   rJ   r-   rb   r   shape)r   rt   	dim_sizesvarrK   sizer1   r1   r2   unified_dim_sizes6  s    
r   r"   ztuple[Hashable, ...])r   broadcast_dimsrp   r   c                   s  | j }| j || }| kr |S t fdd|D }|rRtdt||t|fdd D }|rtd|dtfdd|D }|| }| krt fd	d|D }	t||	}||krg }
|D ](}|kr|
	t
 q|
r|
	tj q|t|
 }|S )
Nc                   s   g | ]}| kr|qS r1   r1   r6   dset_old_dimsr1   r2   r8   a  s      z)broadcast_compat_data.<locals>.<listcomp>zxoperand to apply_ufunc has required core dimensions {}, but some of these dimensions are absent on an input variable: {}c                   s   g | ]}| kr|qS r1   r1   r   )set_new_dimsr1   r2   r8   k  s      z9operand to apply_ufunc encountered unexpected dimensions zS on an input variable: these are core dimensions on other input or output variablesc                 3  s   | ]}| kr|V  qd S rA   r1   r   r   r1   r2   rF   t  s      z(broadcast_compat_data.<locals>.<genexpr>c                 3  s   | ]}  |V  qd S rA   )indexr   )old_dimsr1   r2   rF   w  s     )datarJ   r   r-   r_   rb   rC   r   	transposer   
SLICE_NONEnpZnewaxis)r   r   rp   r  Znew_dimsZmissing_core_dimsZunexpected_dimsZold_broadcast_dimsZreordered_dimsorder	key_partsrK   r1   )r  r  r   r2   broadcast_compat_dataR  sD     

r
  c                 C  s0   |j rtj| |||d} ntj| |d} | S )N)otypesr   )r  )rP   r  	vectorizerx   )r   r   output_dtypesrt   r1   r1   r2   
_vectorize  s    r  	forbiddenF)rt   daskr  r  r   dask_gufunc_kwargszVariable | tuple[Variable, ...]c             
     sb  ddl m m}	 tdd |D d}
tfdd|
D fddjD } fd	dt|jD }td
d |D r|dkrt	dq$|dkr| dkri n
 dd}|dkrJtt|jD ]b\}\}}t|rt|t| dD ]:\}}t|j| dkrt	d| d| d| dqqdd< di }|ri }| D ]4\}}|jkrt	d| d||j| < qh|d< jD ],}|jkr||krt	d| dqfdd} n|dkrnt	d|nr$t| d} | | }jdkr@|f}n.t|tr\t|jkrnt	d j|t| }td!d |D |d"}g }t||D ]\}}|	|}|jt|krt	d#|j d$t| d%| ||dd&}|j D ]8\}}||
kr||
| krt	d'||
| |q||_|| qjdkrV|d S t|S dS )(zDApply a ndarray level function over Variable and/or ndarray objects.r   )r"   as_compatible_datac                 s  s   | ]}t |d r|V  qdS )rJ   N)r   rD   r1   r1   r2   rF     s     
 z'apply_variable_ufunc.<locals>.<genexpr>)rt   c                 3  s   | ]}| j kr|V  qd S rA   )rP   rm   r   r1   r2   rF     s    
 c                   s   g | ]} | qS r1   r1   )r6   r   r   r1   r2   r8     s     z(apply_variable_ufunc.<locals>.<listcomp>c                   s*   g | ]"\}}t | r"t||n|qS r1   )r,   r
  )r6   r0   rp   )r"   r   r1   r2   r8     s   c                 s  s   | ]}t |V  qd S rA   r   )r6   arrayr1   r1   r2   rF     s     r  apply_ufunc encountered a dask array on an argument, but handling for dask arrays has not been enabled. Either set the ``dask`` argument or load your data into memory first with ``.load()`` or ``.compute()``parallelizedNallow_rechunk)startr   z
dimension  on zth function argument to apply_ufunc with dask='parallelized' consists of multiple chunks, but is also a core dimension. To fix, either rechunk into a single dask array chunk along this dimension, i.e., ``.chunk(dict(z=-1))``, or pass ``allow_rechunk=True`` in ``dask_gufunc_kwargs`` but beware that this may significantly increase memory usage.Toutput_sizeszdimension 'z7' in 'output_sizes' must correspond to output_core_dimszI' in 'output_core_dims' needs corresponding (dim, size) in 'output_sizes'c                    s4   dd l m} |jf| d }|S )Nr   )r  r  )
dask.arrayr  Zapply_gufuncrx   )arraysr   res)r  rt   
numpy_funcr  r   r  r1   r2   r     s    	z"apply_variable_ufunc.<locals>.funcallowedz:unknown setting for dask array handling in apply_ufunc: {})r  rt   zapplied function does not have the number of outputs specified in the ufunc signature. Result is not a tuple of {} elements: {!r}c                 S  s   g | ]
}|j qS r1   r   r   r1   r1   r2   r8     s     r   zNapplied function returned data with unexpected number of dimensions. Received z dimension(s) but expected z dimensions with names: )r   zsize of dimension {!r} on inputs was unexpectedly changed by applied function from {} to {}. Only dimensions specified in ``exclude_dims`` with xarray.apply_ufunc are allowed to change size.)r   r"   r  r   rC   r<   r   r;   r   r-   r   r   rT   r   rW   chunkspopr   rO   rV   rN   r_   r  rY   r,   r9   r   ndimsizesr   r   )r   r   rt   r  r  r  r   r  r.   r  r   r   Z
input_datar  rR   r  rp   axisrK   r  Zoutput_sizes_renamedr   r   Zresult_datar   r   r   rJ   r   Znew_sizer1   )r"   r   r  rt   r  r  r   r  r2   apply_variable_ufunc  s     




	



    
  	r%  )r  c                G  sV   t dd |D rN|dkr$tdn*|dkr6tdn|dkr@ntd| | | S )	z4Apply a ndarray level function over ndarray objects.c                 s  s   | ]}t |V  qd S rA   r   r5   r1   r1   r2   rF   9  s     z$apply_array_ufunc.<locals>.<genexpr>r  r  r  z\cannot use dask='parallelized' for apply_ufunc unless at least one input is an xarray objectr  z)unknown setting for dask array handling: )r   r-   )r   r  r.   r1   r1   r2   apply_array_ufunc7  s    r&  r@   )r;   r<   rt   r  rg   r   dataset_fill_valuer   kwargsr  r  r  metar  r   zSequence[Sequence] | Noneboolzbool | str | NonezMapping | NonezSequence | NonezMapping[Any, int] | Nonezdict[str, Any] | None)r   r.   r;   r<   rt   r  rg   r   r'  r   r(  r  r  r  r)  r  r   c                  sx  ddl m  ddlm ddlm |dkr:dt| }n4t|t|krntdt| d| d	t| d
|	dkrzi }	t||}|rt	|t
stdt|j d||jkstd||j  d|
dkr4|dkri }n| }|dk	rtjdtdd |d| |dk	r4tjdtdd |d| |	rHtj| f|	} |dkr\tdd}t	|trv|rrdnd}tjt| ||||
|||d	}tfdd|D rtjt| ||||||||
|||d}t|f| S tdd |D rt|f|||||||dS t fd d|D r@t|f|||||d!S tfd"d|D r`|| S t| f|d#|
iS dS )$aD+  Apply a vectorized function for unlabeled arrays on xarray objects.

    The function will be mapped over the data variable(s) of the input
    arguments using xarray's standard rules for labeled computation, including
    alignment, broadcasting, looping over GroupBy/Dataset variables, and
    merging of coordinates.

    Parameters
    ----------
    func : callable
        Function to call like ``func(*args, **kwargs)`` on unlabeled arrays
        (``.data``) that returns an array or tuple of arrays. If multiple
        arguments with non-matching dimensions are supplied, this function is
        expected to vectorize (broadcast) over axes of positional arguments in
        the style of NumPy universal functions [1]_ (if this is not the case,
        set ``vectorize=True``). If this function returns multiple outputs, you
        must set ``output_core_dims`` as well.
    *args : Dataset, DataArray, DataArrayGroupBy, DatasetGroupBy, Variable,         numpy.ndarray, dask.array.Array or scalar
        Mix of labeled and/or unlabeled arrays to which to apply the function.
    input_core_dims : sequence of sequence, optional
        List of the same length as ``args`` giving the list of core dimensions
        on each input argument that should not be broadcast. By default, we
        assume there are no core dimensions on any input arguments.

        For example, ``input_core_dims=[[], ['time']]`` indicates that all
        dimensions on the first argument and all dimensions other than 'time'
        on the second argument should be broadcast.

        Core dimensions are automatically moved to the last axes of input
        variables before applying ``func``, which facilitates using NumPy style
        generalized ufuncs [2]_.
    output_core_dims : list of tuple, optional
        List of the same length as the number of output arguments from
        ``func``, giving the list of core dimensions on each output that were
        not broadcast on the inputs. By default, we assume that ``func``
        outputs exactly one array, with axes corresponding to each broadcast
        dimension.

        Core dimensions are assumed to appear as the last dimensions of each
        output in the provided order.
    exclude_dims : set, optional
        Core dimensions on the inputs to exclude from alignment and
        broadcasting entirely. Any input coordinates along these dimensions
        will be dropped. Each excluded dimension must also appear in
        ``input_core_dims`` for at least one argument. Only dimensions listed
        here are allowed to change size between input and output objects.
    vectorize : bool, optional
        If True, then assume ``func`` only takes arrays defined over core
        dimensions as input and vectorize it automatically with
        :py:func:`numpy.vectorize`. This option exists for convenience, but is
        almost always slower than supplying a pre-vectorized function.
        Using this option requires NumPy version 1.12 or newer.
    join : {"outer", "inner", "left", "right", "exact"}, default: "exact"
        Method for joining the indexes of the passed objects along each
        dimension, and the variables of Dataset objects with mismatched
        data variables:

        - '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': raise `ValueError` instead of aligning when indexes to be
          aligned are not equal
    dataset_join : {"outer", "inner", "left", "right", "exact"}, default: "exact"
        Method for joining variables of Dataset objects with mismatched
        data variables.

        - 'outer': take variables from both Dataset objects
        - 'inner': take only overlapped variables
        - 'left': take only variables from the first object
        - 'right': take only variables from the last object
        - 'exact': data variables on all Dataset objects must match exactly
    dataset_fill_value : optional
        Value used in place of missing variables on Dataset inputs when the
        datasets do not share the exact same ``data_vars``. Required if
        ``dataset_join not in {'inner', 'exact'}``, otherwise ignored.
    keep_attrs : {"drop", "identical", "no_conflicts", "drop_conflicts", "override"} or bool, optional
        - 'drop' or False: empty attrs on returned xarray object.
        - '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' or True: skip comparing and copy attrs from the first object to the result.
    kwargs : dict, optional
        Optional keyword arguments passed directly on to call ``func``.
    dask : {"forbidden", "allowed", "parallelized"}, default: "forbidden"
        How to handle applying to objects containing lazy data in the form of
        dask arrays:

        - 'forbidden' (default): raise an error if a dask array is encountered.
        - 'allowed': pass dask arrays directly on to ``func``. Prefer this option if
          ``func`` natively supports dask arrays.
        - 'parallelized': automatically parallelize ``func`` if any of the
          inputs are a dask array by using :py:func:`dask.array.apply_gufunc`. Multiple output
          arguments are supported. Only use this option if ``func`` does not natively
          support dask arrays (e.g. converts them to numpy arrays).
    dask_gufunc_kwargs : dict, optional
        Optional keyword arguments passed to :py:func:`dask.array.apply_gufunc` if
        dask='parallelized'. Possible keywords are ``output_sizes``, ``allow_rechunk``
        and ``meta``.
    output_dtypes : list of dtype, optional
        Optional list of output dtypes. Only used if ``dask='parallelized'`` or
        ``vectorize=True``.
    output_sizes : dict, optional
        Optional mapping from dimension names to sizes for outputs. Only used
        if dask='parallelized' and new dimensions (not found on inputs) appear
        on outputs. ``output_sizes`` should be given in the ``dask_gufunc_kwargs``
        parameter. It will be removed as direct parameter in a future version.
    meta : optional
        Size-0 object representing the type of array wrapped by dask array. Passed on to
        :py:func:`dask.array.apply_gufunc`. ``meta`` should be given in the
        ``dask_gufunc_kwargs`` parameter . It will be removed as direct parameter
        a future version.

    Returns
    -------
    Single value or tuple of Dataset, DataArray, Variable, dask.array.Array or
    numpy.ndarray, the first type on that list to appear on an input.

    Notes
    -----
    This function is designed for the more common case where ``func`` can work on numpy
    arrays. If ``func`` needs to manipulate a whole xarray object subset to each block
    it is possible to use :py:func:`xarray.map_blocks`.

    Note that due to the overhead :py:func:`xarray.map_blocks` is considerably slower than ``apply_ufunc``.

    Examples
    --------
    Calculate the vector magnitude of two arguments:

    >>> def magnitude(a, b):
    ...     func = lambda x, y: np.sqrt(x**2 + y**2)
    ...     return xr.apply_ufunc(func, a, b)
    ...

    You can now apply ``magnitude()`` to :py:class:`DataArray` and :py:class:`Dataset`
    objects, with automatically preserved dimensions and coordinates, e.g.,

    >>> array = xr.DataArray([1, 2, 3], coords=[("x", [0.1, 0.2, 0.3])])
    >>> magnitude(array, -array)
    <xarray.DataArray (x: 3)>
    array([1.41421356, 2.82842712, 4.24264069])
    Coordinates:
      * x        (x) float64 0.1 0.2 0.3

    Plain scalars, numpy arrays and a mix of these with xarray objects is also
    supported:

    >>> magnitude(3, 4)
    5.0
    >>> magnitude(3, np.array([0, 4]))
    array([3., 5.])
    >>> magnitude(array, 0)
    <xarray.DataArray (x: 3)>
    array([1., 2., 3.])
    Coordinates:
      * x        (x) float64 0.1 0.2 0.3

    Other examples of how you could use ``apply_ufunc`` to write functions to
    (very nearly) replicate existing xarray functionality:

    Compute the mean (``.mean``) over one dimension:

    >>> def mean(obj, dim):
    ...     # note: apply always moves core dimensions to the end
    ...     return apply_ufunc(
    ...         np.mean, obj, input_core_dims=[[dim]], kwargs={"axis": -1}
    ...     )
    ...

    Inner product over a specific dimension (like :py:func:`dot`):

    >>> def _inner(x, y):
    ...     result = np.matmul(x[..., np.newaxis, :], y[..., :, np.newaxis])
    ...     return result[..., 0, 0]
    ...
    >>> def inner_product(a, b, dim):
    ...     return apply_ufunc(_inner, a, b, input_core_dims=[[dim], [dim]])
    ...

    Stack objects along a new dimension (like :py:func:`concat`):

    >>> def stack(objects, dim, new_coord):
    ...     # note: this version does not stack coordinates
    ...     func = lambda *x: np.stack(x, axis=-1)
    ...     result = apply_ufunc(
    ...         func,
    ...         *objects,
    ...         output_core_dims=[[dim]],
    ...         join="outer",
    ...         dataset_fill_value=np.nan
    ...     )
    ...     result[dim] = new_coord
    ...     return result
    ...

    If your function is not vectorized but can be applied only to core
    dimensions, you can use ``vectorize=True`` to turn into a vectorized
    function. This wraps :py:func:`numpy.vectorize`, so the operation isn't
    terribly fast. Here we'll use it to calculate the distance between
    empirical samples from two probability distributions, using a scipy
    function that needs to be applied to vectors:

    >>> import scipy.stats
    >>> def earth_mover_distance(first_samples, second_samples, dim="ensemble"):
    ...     return apply_ufunc(
    ...         scipy.stats.wasserstein_distance,
    ...         first_samples,
    ...         second_samples,
    ...         input_core_dims=[[dim], [dim]],
    ...         vectorize=True,
    ...     )
    ...

    Most of NumPy's builtin functions already broadcast their inputs
    appropriately for use in ``apply_ufunc``. You may find helper functions such as
    :py:func:`numpy.broadcast_arrays` helpful in writing your function. ``apply_ufunc`` also
    works well with :py:func:`numba.vectorize` and :py:func:`numba.guvectorize`.

    See Also
    --------
    numpy.broadcast_arrays
    numba.vectorize
    numba.guvectorize
    dask.array.apply_gufunc
    xarray.map_blocks
    :ref:`dask.automatic-parallelization`
        User guide describing :py:func:`apply_ufunc` and :py:func:`map_blocks`.

    References
    ----------
    .. [1] https://numpy.org/doc/stable/reference/ufuncs.html
    .. [2] https://numpy.org/doc/stable/reference/c-api/generalized-ufuncs.html
    r   r$   r   r!   Nr@   z_input_core_dims must be None or a tuple with the length same to the number of arguments. Given z input_core_dims: z,  but number of args is .z/Expected exclude_dims to be a 'set'. Received 'z
' instead.zfeach dimension in `exclude_dims` must also be a core dimension in the function signature. Please make z a core dimensionr  z}``meta`` should be given in the ``dask_gufunc_kwargs`` parameter. It will be removed as direct parameter in a future version.   )
stacklevelr)  z``output_sizes`` should be given in the ``dask_gufunc_kwargs`` parameter. It will be removed as direct parameter in a future version.r  Fdefaultr   r   )r   rt   r   r  r  r  r  c                 3  s   | ]}t | V  qd S rA   r4   rD   r   r1   r2   rF     s     zapply_ufunc.<locals>.<genexpr>)r;   r<   rt   rg   r   r'  r   r  r  r  r  c                 s  s   | ]}t |V  qd S rA   )r   rD   r1   r1   r2   rF     s     )r   rg   rt   r   r   r   c                 3  s   | ]}t | V  qd S rA   r4   rD   r$   r1   r2   rF     s     )r   rg   rt   r   c                 3  s   | ]}t | V  qd S rA   r4   rD   r!   r1   r2   rF     s     r  )r   r%   r   r   r   r"   rW   r-   r:   r,   r   r   r`   ra   rP   r   warningswarnFutureWarning
setdefault	functoolspartialr   r*  r%  r   apply_ufuncr   r   r   r&  )r   r;   r<   rt   r  rg   r   r'  r   r(  r  r  r  r)  r  r.   r   Zvariables_vfuncZ
this_applyr1   )r%   r   r"   r2   r6  N  s     ~







	r6  r   c                   sT   ddl m  t fdd| |fD rBtddd | |fD t| |||dd	S )
aK  
    Compute covariance between two DataArray objects along a shared dimension.

    Parameters
    ----------
    da_a : DataArray
        Array to compute.
    da_b : DataArray
        Array to compute.
    dim : str, optional
        The dimension along which the covariance will be computed
    ddof : int, optional
        If ddof=1, covariance is normalized by N-1, giving an unbiased estimate,
        else normalization is by N.

    Returns
    -------
    covariance : DataArray

    See Also
    --------
    pandas.Series.cov : corresponding pandas function
    xarray.corr : respective function to calculate correlation

    Examples
    --------
    >>> from xarray import DataArray
    >>> da_a = DataArray(
    ...     np.array([[1, 2, 3], [0.1, 0.2, 0.3], [3.2, 0.6, 1.8]]),
    ...     dims=("space", "time"),
    ...     coords=[
    ...         ("space", ["IA", "IL", "IN"]),
    ...         ("time", pd.date_range("2000-01-01", freq="1D", periods=3)),
    ...     ],
    ... )
    >>> da_a
    <xarray.DataArray (space: 3, time: 3)>
    array([[1. , 2. , 3. ],
           [0.1, 0.2, 0.3],
           [3.2, 0.6, 1.8]])
    Coordinates:
      * space    (space) <U2 'IA' 'IL' 'IN'
      * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03
    >>> da_b = DataArray(
    ...     np.array([[0.2, 0.4, 0.6], [15, 10, 5], [3.2, 0.6, 1.8]]),
    ...     dims=("space", "time"),
    ...     coords=[
    ...         ("space", ["IA", "IL", "IN"]),
    ...         ("time", pd.date_range("2000-01-01", freq="1D", periods=3)),
    ...     ],
    ... )
    >>> da_b
    <xarray.DataArray (space: 3, time: 3)>
    array([[ 0.2,  0.4,  0.6],
           [15. , 10. ,  5. ],
           [ 3.2,  0.6,  1.8]])
    Coordinates:
      * space    (space) <U2 'IA' 'IL' 'IN'
      * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03
    >>> xr.cov(da_a, da_b)
    <xarray.DataArray ()>
    array(-3.53055556)
    >>> xr.cov(da_a, da_b, dim="time")
    <xarray.DataArray (space: 3)>
    array([ 0.2       , -0.5       ,  1.69333333])
    Coordinates:
      * space    (space) <U2 'IA' 'IL' 'IN'
    r   r$   c                 3  s   | ]}t |  V  qd S rA   r4   r6   arrr$   r1   r2   rF     s     zcov.<locals>.<genexpr>(Only xr.DataArray is supported.Given {}.c                 S  s   g | ]}t |qS r1   r`   r7  r1   r1   r2   r8     s     zcov.<locals>.<listcomp>cov)rK   ddofmethodr   r%   r   r   r_   	_cov_corr)da_ada_brK   r<  r1   r$   r2   r;    s    Er;  c                   sR   ddl m  t fdd| |fD rBtddd | |fD t| ||dd	S )
a  
    Compute the Pearson correlation coefficient between
    two DataArray objects along a shared dimension.

    Parameters
    ----------
    da_a : DataArray
        Array to compute.
    da_b : DataArray
        Array to compute.
    dim : str, optional
        The dimension along which the correlation will be computed

    Returns
    -------
    correlation: DataArray

    See Also
    --------
    pandas.Series.corr : corresponding pandas function
    xarray.cov : underlying covariance function

    Examples
    --------
    >>> from xarray import DataArray
    >>> da_a = DataArray(
    ...     np.array([[1, 2, 3], [0.1, 0.2, 0.3], [3.2, 0.6, 1.8]]),
    ...     dims=("space", "time"),
    ...     coords=[
    ...         ("space", ["IA", "IL", "IN"]),
    ...         ("time", pd.date_range("2000-01-01", freq="1D", periods=3)),
    ...     ],
    ... )
    >>> da_a
    <xarray.DataArray (space: 3, time: 3)>
    array([[1. , 2. , 3. ],
           [0.1, 0.2, 0.3],
           [3.2, 0.6, 1.8]])
    Coordinates:
      * space    (space) <U2 'IA' 'IL' 'IN'
      * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03
    >>> da_b = DataArray(
    ...     np.array([[0.2, 0.4, 0.6], [15, 10, 5], [3.2, 0.6, 1.8]]),
    ...     dims=("space", "time"),
    ...     coords=[
    ...         ("space", ["IA", "IL", "IN"]),
    ...         ("time", pd.date_range("2000-01-01", freq="1D", periods=3)),
    ...     ],
    ... )
    >>> da_b
    <xarray.DataArray (space: 3, time: 3)>
    array([[ 0.2,  0.4,  0.6],
           [15. , 10. ,  5. ],
           [ 3.2,  0.6,  1.8]])
    Coordinates:
      * space    (space) <U2 'IA' 'IL' 'IN'
      * time     (time) datetime64[ns] 2000-01-01 2000-01-02 2000-01-03
    >>> xr.corr(da_a, da_b)
    <xarray.DataArray ()>
    array(-0.57087777)
    >>> xr.corr(da_a, da_b, dim="time")
    <xarray.DataArray (space: 3)>
    array([ 1., -1.,  1.])
    Coordinates:
      * space    (space) <U2 'IA' 'IL' 'IN'
    r   r$   c                 3  s   | ]}t |  V  qd S rA   r4   r7  r$   r1   r2   rF   ]  s     zcorr.<locals>.<genexpr>r9  c                 S  s   g | ]}t |qS r1   r:  r7  r1   r1   r2   r8   `  s     zcorr.<locals>.<listcomp>corr)rK   r=  r>  )r@  rA  rK   r1   r$   r2   rB    s    CrB  r   )r@  rA  r   c                 C  s   t | |ddd\} }|  | @ }| |} ||}||| }| | j|d }||j|d }|| j|ddd| }	|dkr|	S | j|d}
|j|d}|	|
|  }|S d	S )
z
    Internal method for xr.cov() and xr.corr() so only have to
    sanitize the input arrays once and we don't repeat code.
    r*   F)rg   r   rQ   Tr   )rK   skipnaZ	min_countr;  N)r   ZnotnullwheresumZmeanZstd)r@  rA  rK   r<  r=  Zvalid_valuesZvalid_countZdemeaned_da_aZdemeaned_da_br;  Zda_a_stdZda_b_stdrB  r1   r1   r2   r?  f  s     

r?  zDataArray | Variabler   )rE   brK   r   c                C  sB  || j krtd|dn||j kr6td|dd| j|   krPdksnn td|d| j|  n6d|j|   krdksn td|d|j|  tt| j |j  }| j| |j| krt| ts.|t| d	i kr.t|ts.|t|d	i kr.t	| |d
dt
||h d\} }nt| j| |j| dkr| j| |j| k r| j|did
d} t| jr| |din| } n0|j|did
d}t|jr||din|}n(t|d| j| dkrdnd dttj| ||g|gg| j| dkr|gng gdt| |gd}|j|ddi}|S )a  
    Compute the cross product of two (arrays of) vectors.

    The cross product of `a` and `b` in :math:`R^3` is a vector
    perpendicular to both `a` and `b`. The vectors in `a` and `b` are
    defined by the values along the dimension `dim` and can have sizes
    1, 2 or 3. Where the size of either `a` or `b` is
    1 or 2, the remaining components of the input vector is assumed to
    be zero and the cross product calculated accordingly. In cases where
    both input vectors have dimension 2, the z-component of the cross
    product is returned.

    Parameters
    ----------
    a, b : DataArray or Variable
        Components of the first and second vector(s).
    dim : hashable
        The dimension along which the cross product will be computed.
        Must be available in both vectors.

    Examples
    --------
    Vector cross-product with 3 dimensions:

    >>> a = xr.DataArray([1, 2, 3])
    >>> b = xr.DataArray([4, 5, 6])
    >>> xr.cross(a, b, dim="dim_0")
    <xarray.DataArray (dim_0: 3)>
    array([-3,  6, -3])
    Dimensions without coordinates: dim_0

    Vector cross-product with 2 dimensions, returns in the perpendicular
    direction:

    >>> a = xr.DataArray([1, 2])
    >>> b = xr.DataArray([4, 5])
    >>> xr.cross(a, b, dim="dim_0")
    <xarray.DataArray ()>
    array(-3)

    Vector cross-product with 3 dimensions but zeros at the last axis
    yields the same results as with 2 dimensions:

    >>> a = xr.DataArray([1, 2, 0])
    >>> b = xr.DataArray([4, 5, 0])
    >>> xr.cross(a, b, dim="dim_0")
    <xarray.DataArray (dim_0: 3)>
    array([ 0,  0, -3])
    Dimensions without coordinates: dim_0

    One vector with dimension 2:

    >>> a = xr.DataArray(
    ...     [1, 2],
    ...     dims=["cartesian"],
    ...     coords=dict(cartesian=(["cartesian"], ["x", "y"])),
    ... )
    >>> b = xr.DataArray(
    ...     [4, 5, 6],
    ...     dims=["cartesian"],
    ...     coords=dict(cartesian=(["cartesian"], ["x", "y", "z"])),
    ... )
    >>> xr.cross(a, b, dim="cartesian")
    <xarray.DataArray (cartesian: 3)>
    array([12, -6, -3])
    Coordinates:
      * cartesian  (cartesian) <U1 'x' 'y' 'z'

    One vector with dimension 2 but coords in other positions:

    >>> a = xr.DataArray(
    ...     [1, 2],
    ...     dims=["cartesian"],
    ...     coords=dict(cartesian=(["cartesian"], ["x", "z"])),
    ... )
    >>> b = xr.DataArray(
    ...     [4, 5, 6],
    ...     dims=["cartesian"],
    ...     coords=dict(cartesian=(["cartesian"], ["x", "y", "z"])),
    ... )
    >>> xr.cross(a, b, dim="cartesian")
    <xarray.DataArray (cartesian: 3)>
    array([-10,   2,   5])
    Coordinates:
      * cartesian  (cartesian) <U1 'x' 'y' 'z'

    Multiple vector cross-products. Note that the direction of the
    cross product vector is defined by the right-hand rule:

    >>> a = xr.DataArray(
    ...     [[1, 2, 3], [4, 5, 6]],
    ...     dims=("time", "cartesian"),
    ...     coords=dict(
    ...         time=(["time"], [0, 1]),
    ...         cartesian=(["cartesian"], ["x", "y", "z"]),
    ...     ),
    ... )
    >>> b = xr.DataArray(
    ...     [[4, 5, 6], [1, 2, 3]],
    ...     dims=("time", "cartesian"),
    ...     coords=dict(
    ...         time=(["time"], [0, 1]),
    ...         cartesian=(["cartesian"], ["x", "y", "z"]),
    ...     ),
    ... )
    >>> xr.cross(a, b, dim="cartesian")
    <xarray.DataArray (time: 2, cartesian: 3)>
    array([[-3,  6, -3],
           [ 3, -6,  3]])
    Coordinates:
      * time       (time) int64 0 1
      * cartesian  (cartesian) <U1 'x' 'y' 'z'

    Cross can be called on Datasets by converting to DataArrays and later
    back to a Dataset:

    >>> ds_a = xr.Dataset(dict(x=("dim_0", [1]), y=("dim_0", [2]), z=("dim_0", [3])))
    >>> ds_b = xr.Dataset(dict(x=("dim_0", [4]), y=("dim_0", [5]), z=("dim_0", [6])))
    >>> c = xr.cross(
    ...     ds_a.to_array("cartesian"), ds_b.to_array("cartesian"), dim="cartesian"
    ... )
    >>> c.to_dataset(dim="cartesian")
    <xarray.Dataset>
    Dimensions:  (dim_0: 1)
    Dimensions without coordinates: dim_0
    Data variables:
        x        (dim_0) int64 -3
        y        (dim_0) int64 6
        z        (dim_0) int64 -3

    See Also
    --------
    numpy.cross : Corresponding numpy function
    
Dimension z	 not on az	 not on br      zThe size of zF on a must be 1, 2, or 3 to be compatible with a cross product but is zF on b must be 1, 2, or 3 to be compatible with a cross product but is r   r   r   )r   rg   r   r,  )r   r   )Zconstant_valuesr   r  rE   rF  zR is incompatible: dimensions without coordinates must have have a length of 2 or 3r  )r;   r<   r  r  missing_dimsignore)rJ   r-   r#  rb   r   fromkeysr,   r"   r   r   r   minpadr   r  chunkr6  r  crossZresult_typer  )rE   rF  rK   all_dimscr1   r1   r2   rO    sd     

  "
	rO  rJ   z*str | Iterable[Hashable] | ellipsis | None)rJ   r(  c                   s  ddl m  ddlm t fdd|D rHtddd |D t|dkr\td	tj	d
d |D  }g |D ]}fdd|j
D 7 qxdfddtD | dkr} nNt| tr| f} n<| dkrt }|D ]}||j
 qtdd | D } t| | fdd|D }fddD g}fdd|D }d|}	|	ddfdd|d D  7 }	td }
|
dkrd}
tjtj|	f|}t|f||||
dd}|jddiS ) a3  Generalized dot product for xarray objects. Like np.einsum, but
    provides a simpler interface based on array dimensions.

    Parameters
    ----------
    *arrays : DataArray or Variable
        Arrays to compute.
    dims : ..., str or tuple of str, optional
        Which dimensions to sum over. Ellipsis ('...') sums over all dimensions.
        If not specified, then all the common dimensions are summed over.
    **kwargs : dict
        Additional keyword arguments passed to numpy.einsum or
        dask.array.einsum

    Returns
    -------
    DataArray

    Examples
    --------
    >>> da_a = xr.DataArray(np.arange(3 * 2).reshape(3, 2), dims=["a", "b"])
    >>> da_b = xr.DataArray(np.arange(3 * 2 * 2).reshape(3, 2, 2), dims=["a", "b", "c"])
    >>> da_c = xr.DataArray(np.arange(2 * 3).reshape(2, 3), dims=["c", "d"])

    >>> da_a
    <xarray.DataArray (a: 3, b: 2)>
    array([[0, 1],
           [2, 3],
           [4, 5]])
    Dimensions without coordinates: a, b

    >>> da_b
    <xarray.DataArray (a: 3, b: 2, c: 2)>
    array([[[ 0,  1],
            [ 2,  3]],
    <BLANKLINE>
           [[ 4,  5],
            [ 6,  7]],
    <BLANKLINE>
           [[ 8,  9],
            [10, 11]]])
    Dimensions without coordinates: a, b, c

    >>> da_c
    <xarray.DataArray (c: 2, d: 3)>
    array([[0, 1, 2],
           [3, 4, 5]])
    Dimensions without coordinates: c, d

    >>> xr.dot(da_a, da_b, dims=["a", "b"])
    <xarray.DataArray (c: 2)>
    array([110, 125])
    Dimensions without coordinates: c

    >>> xr.dot(da_a, da_b, dims=["a"])
    <xarray.DataArray (b: 2, c: 2)>
    array([[40, 46],
           [70, 79]])
    Dimensions without coordinates: b, c

    >>> xr.dot(da_a, da_b, da_c, dims=["b", "c"])
    <xarray.DataArray (a: 3, d: 3)>
    array([[  9,  14,  19],
           [ 93, 150, 207],
           [273, 446, 619]])
    Dimensions without coordinates: a, d

    >>> xr.dot(da_a, da_b)
    <xarray.DataArray (c: 2)>
    array([110, 125])
    Dimensions without coordinates: c

    >>> xr.dot(da_a, da_b, dims=...)
    <xarray.DataArray ()>
    array(235)
    r   r$   r!   c                 3  s   | ]}t | f V  qd S rA   r4   r7  )r%   r"   r1   r2   rF     s     zdot.<locals>.<genexpr>z9Only xr.DataArray and xr.Variable are supported.Given {}.c                 S  s   g | ]}t |qS r1   r:  r7  r1   r1   r2   r8     s     zdot.<locals>.<listcomp>z#At least one array should be given.c                 s  s   | ]}t |jV  qd S rA   )r   rJ   r7  r1   r1   r2   rF     s     c                   s   g | ]}| kr|qS r1   r1   r   )rP  r1   r2   r8     s      abcdefghijklmnopqrstuvwxyzc                   s   i | ]\}}| | qS r1   r1   )r6   ir   )einsum_axesr1   r2   rS     s      zdot.<locals>.<dictcomp>.Nc                 s  s   | ]\}}|d kr|V  qdS )r   Nr1   )r6   r   rQ  r1   r1   r2   rF     s      c                   s    g | ]} fd d|j D qS )c                   s   g | ]}| kr|qS r1   r1   r   r  r1   r2   r8     s      z"dot.<locals>.<listcomp>.<listcomp>rR  r7  r  r1   r2   r8     s    c                   s    g | ]}|kr| kr|qS r1   r1   r   )r   dot_dimsr1   r2   r8     s       c                   s(   g | ] }d d  fdd|D  qS )z... c                 3  s   | ]} | V  qd S rA   r1   r   dim_mapr1   r2   rF     s     z!dot.<locals>.<listcomp>.<genexpr>)rg   )r6   r   rX  r1   r2   r8     s    rd   z->...rW  c                 3  s   | ]} | V  qd S rA   r1   r   rX  r1   r2   rF     s     Zarithmetic_joinr+   r*   r  )r;   r<   rg   r  rI  rJ  )r   r%   r   r"   r   r   r_   rW   r   r   rJ   rT   r,   rw   r   rr   rC   r   rg   r   r4  r5  r   Zeinsumr6  r  )rJ   r  r(  Zcommon_dimsr8  Z
dim_countsr;   r<   Zsubscripts_listZ
subscriptsrg   r   resultr1   )r%   r"   rP  r   rY  rV  rU  r2   dot]  sh    Q




$
r[  c              
   C  s   ddl m} |dkrtdd}ttj| ||ddd|d}|d	krt|d
rt||rt||si |_t	|dd|j
krt	|d
i ||j _n:t	|d
i |_t	|dg D ]}t	t	||dd
i || _qt	|dg D ]}t	t	||dd
i || _q|S )a	  Return elements from `x` or `y` depending on `cond`.

    Performs xarray-like broadcasting across input arguments.

    All dimension coordinates on `x` and `y`  must be aligned with each
    other and with `cond`.

    Parameters
    ----------
    cond : scalar, array, Variable, DataArray or Dataset
        When True, return values from `x`, otherwise returns values from `y`.
    x : scalar, array, Variable, DataArray or Dataset
        values to choose from where `cond` is True
    y : scalar, array, Variable, DataArray or Dataset
        values to choose from where `cond` is False
    keep_attrs : bool or str or callable, optional
        How to treat attrs. If True, keep the attrs of `x`.

    Returns
    -------
    Dataset, DataArray, Variable or array
        In priority order: Dataset, DataArray, Variable or array, whichever
        type appears as an input argument.

    Examples
    --------
    >>> x = xr.DataArray(
    ...     0.1 * np.arange(10),
    ...     dims=["lat"],
    ...     coords={"lat": np.arange(10)},
    ...     name="sst",
    ... )
    >>> x
    <xarray.DataArray 'sst' (lat: 10)>
    array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
    Coordinates:
      * lat      (lat) int64 0 1 2 3 4 5 6 7 8 9

    >>> xr.where(x < 0.5, x, x * 100)
    <xarray.DataArray 'sst' (lat: 10)>
    array([ 0. ,  0.1,  0.2,  0.3,  0.4, 50. , 60. , 70. , 80. , 90. ])
    Coordinates:
      * lat      (lat) int64 0 1 2 3 4 5 6 7 8 9

    >>> y = xr.DataArray(
    ...     0.1 * np.arange(9).reshape(3, 3),
    ...     dims=["lat", "lon"],
    ...     coords={"lat": np.arange(3), "lon": 10 + np.arange(3)},
    ...     name="sst",
    ... )
    >>> y
    <xarray.DataArray 'sst' (lat: 3, lon: 3)>
    array([[0. , 0.1, 0.2],
           [0.3, 0.4, 0.5],
           [0.6, 0.7, 0.8]])
    Coordinates:
      * lat      (lat) int64 0 1 2
      * lon      (lon) int64 10 11 12

    >>> xr.where(y.lat < 1, y, -1)
    <xarray.DataArray (lat: 3, lon: 3)>
    array([[ 0. ,  0.1,  0.2],
           [-1. , -1. , -1. ],
           [-1. , -1. , -1. ]])
    Coordinates:
      * lat      (lat) int64 0 1 2
      * lon      (lon) int64 10 11 12

    >>> cond = xr.DataArray([True, False], dims=["x"])
    >>> x = xr.DataArray([1, 2], dims=["y"])
    >>> xr.where(cond, x, 0)
    <xarray.DataArray (x: 2, y: 2)>
    array([[1, 2],
           [0, 0]])
    Dimensions without coordinates: x, y

    See Also
    --------
    numpy.where : corresponding numpy function
    Dataset.where, DataArray.where :
        equivalent methods
    r   r&   NFr.  r+   r  )rg   r   r  r   Tr   r   r   r   )r   r'   r   r6  r   rD  r   r,   r   r   r   r   )Zcondr   yr   r'   rZ  r   rQ  r1   r1   r2   rD    s0    S
rD  degreer%   )coordcoeffs
degree_dimr   c                 C  s   d S rA   r1   r^  r_  r`  r1   r1   r2   polyvalm  s    rb  c                 C  s   d S rA   r1   ra  r1   r1   r2   rb  t  s    c                 C  s   d S rA   r1   ra  r1   r1   r2   rb  {  s    c                 C  s   d S rA   r1   ra  r1   r1   r2   rb    s    zDataset | DataArrayc                 C  s   d S rA   r1   ra  r1   r1   r2   rb    s    c                 C  s   ||j krtd| dt|| jtsHtd| d|| j d||   }|j|t	|d iddd}t
| } t| |j||id	d
 }t|d ddD ]"}|| 9 }||j||id	d
7 }q|S )a  Evaluate a polynomial at specific values

    Parameters
    ----------
    coord : DataArray or Dataset
        Values at which to evaluate the polynomial.
    coeffs : DataArray or Dataset
        Coefficients of the polynomial.
    degree_dim : Hashable, default: "degree"
        Name of the polynomial degree dimension in `coeffs`.

    Returns
    -------
    DataArray or Dataset
        Evaluated polynomial.

    See Also
    --------
    xarray.DataArray.polyfit
    numpy.polynomial.polynomial.polyval
    zDimension `z.` should be a coordinate variable with labels.z'` should be of integer dtype. Received z	 instead.r   r   F)r   r   T)r   r   )Z_indexesr-   r  Z
issubdtypedtyper   maxitemZreindexZarange_ensure_numericr   Ziselr   )r^  r_  r`  Zmax_degr  degr1   r1   r2   rb    s(    

  )r  r   c                   sP   ddl m} ddddd ddd fdd	}t| |rD| |S || S d
S )a  Converts all datetime64 variables to float64

    Parameters
    ----------
    data : DataArray or Dataset
        Variables with possible datetime dtypes.

    Returns
    -------
    DataArray or Dataset
        Variables with datetime64 dtypes converted to float64.
    r   r&   r%   r   )r   r   c                 S  s.   |   jd }t|s| }t|dddS )Nr   i  r   )Zcomputer  r    re  r`   )r   Zscalarr1   r1   r2   	_cfoffset  s    z"_ensure_numeric.<locals>._cfoffsetc                   s\   | j jdkrB| j jdkr"tdn | }| jt| j|dddS | j jdkrX| tS | S )NZMOMz
1970-01-01ns)offsetZdatetime_unitr  m)	rc  r/   r  Z
datetime64r   r   r  Zastypefloat)r   rk  rh  r1   r2   to_floatable  s    
z%_ensure_numeric.<locals>.to_floatableN)r   r'   r,   map)r  r'   rp  r1   ro  r2   rf    s    

rf  )rK   rC  r   r   zHashable | Nonezbool | None)r   rK   rC  r   r   c                 C  sh  | j std|dk	rn| j dkr.| jd }ntd|| jkrPtd| d|| jkrjtd| dd	}|s|dkr| jj|kr|  |}| 	| d} || |d||d
}t
| jrddl}	tt| j| j}
|	jj| | j|
| d}|j||j  |jd}||_n| | |f }|j|= |sN|dkr\| jj|kr\|	| |}|j|_|S )z.Apply common operations for idxmin and idxmax.z(This function does not apply for scalarsNr   r   z6Must supply 'dim' argument for multidimensional arrayszDimension "z" not in dimensionz" does not have coordinatesZcfO)rK   r$  r   rC  )r   rl  )r"  r-   rJ   r   r   rc  r/   ZisnullallrD  r   r  r  r   r   r   r  Z
from_arrayr   ZravelZreshaper   r   r   )r  r   rK   rC  r   r   Z	na_dtypesZallnaZindxr  r   Z
dask_coordr  r1   r1   r2   _calc_idxminmax  s8    


rs  _T)r'   r%   )bound_U_Vz	tuple[_T])__objr   c                 C  s   d S rA   r1   )rx  r1   r1   r2   unify_chunks3  s    ry  ztuple[_T, _U])__obj1__obj2r   c                 C  s   d S rA   r1   )rz  r{  r1   r1   r2   ry  8  s    ztuple[_T, _U, _V])rz  r{  __obj3r   c                 C  s   d S rA   r1   )rz  r{  r|  r1   r1   r2   ry  =  s    ztuple[Dataset | DataArray, ...]c                  G  s   d S rA   r1   )r~   r1   r1   r2   ry  B  s    c                    sZ  ddl m   fdd| D }g }i }|D ]}|j D ]~}|jdk	r8|j D ]T\}}z.|| |krtd|d||  d| W qP tk
r   |||< Y qPX qP||j	|j
g7 }q8q*|s| S dd	lm} || \}	}
t|
}g }t| |D ]`\}}|j D ],\}}|jdk	r|jt|d
|j|< q|t| rJ||n| qt|S )uv  
    Given any number of Dataset and/or DataArray objects, returns
    new objects with unified chunk size along all chunked dimensions.

    Returns
    -------
    unified (DataArray or Dataset) – Tuple of objects with the same type as
    *objects with consistent chunk sizes for all dask-array variables

    See Also
    --------
    dask.array.core.unify_chunks
    r   r$   c                   s&   g | ]}t | r| n| qS r1   )r,   Z_to_temp_datasetr   r   r$   r1   r2   r8   X  s   z unify_chunks.<locals>.<listcomp>NrG  z size mismatch: r   )ry  rl  )r   r%   Z
_variablesr   r   r#  r   r-   r   _dataZ_dimsZdask.array.corery  iterr   r   nextr   r,   Z_from_temp_datasetrC   )r~   ZdatasetsZunify_chunks_argsr#  r   r   rK   r   ry  rq   Z	dask_dataZdask_data_iterr   r   r   r1   r$   r2   ry  G  s<    

")r*   )N)Nr   )N)Nr   N)N)r]  )r]  )r]  )r]  )r]  )r]  )mr{   
__future__r   r4  r   operatorr0  collectionsr   typingr   r   r   r   r   r	   r
   r   r   r   r   Znumpyr  Zxarray.corer   r   r   Zxarray.core.alignmentr   r   Zxarray.core.commonr   Zxarray.core.duck_array_opsr   Zxarray.core.indexesr   r   Zxarray.core.merger   r   Zxarray.core.optionsr   r   Zxarray.core.pycompatr   Zxarray.core.typesr   Zxarray.core.utilsr   r    r   r"   Zxarray.core.coordinatesr#   r   r%   r   r'   r(   r)   Z
ReprObjectr   r   rL   r   r3   r9   r:   r   r   r   r   r   r   r   
itemgetterr   __annotations__r   r   r   r   r   r   r   r   r   r   slicer  r
  r  r%  r&  r6  r;  rB  r?  rO  r[  rD  rb  rf  ZNArs  rt  rv  rw  ry  r1   r1   r1   r2   <module>   s  4

K;	 	
 ;/6 #2  |
P
O     ' S 
z      3.?