
    d-W                        d dl mZ d dlZd dlZd dlZd dlmZmZmZm	Z	 d dl
mZmZm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 erd d	lmZ d
 Zd1dZd2dZd3dZd4dZd Zd5dZ d6d"Z!d7d(Z"	 	 	 d8d9d0Z#dS ):    )annotationsN)HashableIterableMappingSequence)TYPE_CHECKINGAnyCallable)align)	DataArray)Datasetis_dask_collection)T_Xarrayc                    t          |  S N)zip)iterables    4lib/python3.11/site-packages/xarray/core/parallel.pyunzipr      s    >    ar   bc                ,   |                                  } |                                 }t          | j                                      t          |j                            D ]1}| j        |         |j        |         k    rt	          d|d          2d S )NzChunk sizes along dimension z are not equal.)unify_chunkssetchunksintersection
ValueError)r   r   dims      r   assert_chunks_compatibler!      s    	A	A18}}))#ah--88 T T8C=AHSM))RCRRRSSS *T Tr   resultDataArray | DatasetexpectedMapping[str, Any]kindstrc                    |dk    rd}n|dk    rd}||         t          t          | |                    z
  }|rt          d| d| d          t          t          | |                    ||         z
  }|rt          d| d| d          d S )	Ncoords
coordinate	data_varsdataz4Result from applying user function does not contain z variables .z2Result from applying user function has unexpected )r   getattrr   )r"   r$   r&   nice_strmissingextras         r   check_result_variablesr2   !   s     x			 tns764#8#8999G 
// /$+/ / /
 
 	
 %%&&$7E 
-- -$)- - -
 
 	

 
r   objreturnr   c                   t          | t                    st          dt          |                      t	          | j                  dk    rt          d          t          t          | j                                                            S )NzExpected Dataset, got    zGTrying to convert Dataset with more than one data variable to DataArray)	
isinstancer   	TypeErrortypelenr+   nextitervalues)r3   s    r   dataset_to_dataarrayr>   8   s    c7## ><c<<===
3=AU
 
 	
 S]))++,,---r   c                f    | j         |                                 }n|                                 }|S r   )name_to_temp_dataset
to_dataset)r3   datasets     r   dataarray_to_datasetrD   D   s3     x&&((..""Nr   c                   t          | t                    r| }t          |           } nt          | t                    rd}n| S ddlm} t                      }| j                                        D ].\  }} ||j        |j	                  }|j
        ||j        f||<   /| j        |_        |                    | j                  }|t          |          S |S )zIf obj is a DataArray or Dataset, return a new object of the same type and with
    the same variables and dtypes, but where all variables have size 0 and numpy
    backend.
    If obj is neither a DataArray nor Dataset, return it unaltered.
    Nr   )meta_from_array)ndim)r7   r   rD   r   dask.array.utilsrF   	variablesitemsr,   rG   dimsattrs
set_coordsr)   r>   )r3   	obj_arrayrF   metar@   variablemeta_objs          r   	make_metarR   O   s     #y!! 	"3''	C	!	! 		
00000099D---// ? ?h"?8=x}EEEmXx~>T

DJ??3:&&D#D)))Kr   funcCallable[..., T_Xarray]r   c                    d |f|z   D             }	  | |i |}n"# t           $ r}t          d          |d}~ww xY wt          |t          t          f          st	          dt          |                     |S )z<Infer return object by running the function on meta objects.c                ,    g | ]}t          |          S  )rR   .0args     r   
<listcomp>z"infer_template.<locals>.<listcomp>o   s    999C3999r   zsCannot infer object returned from running user provided function. Please supply the 'template' kwarg to map_blocks.NzIFunction must return an xarray DataArray or Dataset. Instead it returned )	Exceptionr7   r   r   r8   r9   )rS   r3   argskwargs	meta_argstemplatees          r   infer_templaterb   k   s     :9C6D=999I4-f--   @
 
 	 h) 455 
 H~~   
 
 	

 Os    
:5:xdict[Hashable, Any]c                    t          | t                    r|                                 } d | j                                        D             S )zWMap variable name to numpy(-like) data
    (Dataset.to_dict() is too complicated).
    c                $    i | ]\  }}||j         S rW   )r,   )rY   kvs      r   
<dictcomp>zmake_dict.<locals>.<dictcomp>   s     666$!QAqv666r   )r7   r   rA   rI   rJ   rc   s    r   	make_dictrk      sI     !Y !  66!+"3"3"5"56666r   r    r   chunk_indexr   chunk_boundsc                    | |v r3||          }t          ||          |         ||          |dz                      S t          d           S )Nr6   )slice)r    rl   rm   which_chunks       r   _get_chunk_slicerrq      sL    
k!#&\#&{3\#5F{UV5WXXX;;r   rW   r]   Sequence[Any]r^   Mapping[str, Any] | Noner`   DataArray | Dataset | Nonec                  )*+,-./01234 dAd
}At          t          t          f          s%t          dt	                    j         d          t          |t                    st          d          |i }n$t          |t                    st          d          |                                D ] }t          |          rt          d          !t          |          s | |g|R i |S 	 ddl
*ddl*ddlm} n# t          $ r Y nw xY w|gt          |          z   }d |D             1d |D             }	t!          1fdt#          |          D                       \  }
}1fdt#          |          D             }t%          |ddi}t'          d |D                       }t!          t)          t          t+          |
|                    |z   d                     \  }}t-          |d         j                  /t-          |d         j                  0|dd         D ]L}t3          |d         |           /                    |j                   0                    |j                   Mt7          | |d         g|R i |t9          j                  }|t9          0          z  }|t9          0          z
  }0fd|D             --                    fd|D                        /fdj        D             3n,t-          j                  -j        33st?          d           3D ]q}|/v rktA          /|                   tA          3|                   k    r?t?          d!|d"tA          /|                    d#tA          3|                    d$          rt          t                    rd%}j!        }"                                n7t          t                    rd&}nt          d't	                               i ,tG          j$        t,                    }d(%                    *j&        '                    |           *j(        )                    |d         ||                    +d) /*                                D             }d* /*                                D             .d+ 3*                                D             2dB*fd14tW          j,        |                                 D ]Z}t-          t+          |-                                |                    ))+,.4fd2t+          1|          D             }i }3fd3)*                                D             |d4<   t9          j.        -                                          |d5<   t9          j/        -                                          |d6<   )-2fd7-D             |d8<   +f|z   }|| |||	|f,|<   i }j0        *                                D ]Q\  }}|-v r
| d9+ } | ||<   | f}!|j        D ]}|)v r|!)|         fz  }!|!d:z  }!tb          j2        ||f||          |!<   R\|3                    +,*fd;|D             <          }" |i |"j4        |i |"j5        +fd=|-                                D             <          }"t          d> -*                                D             j6        ?          }#|#j        D ]2}$|$         j6        |#|$         _6        |$         j7        |#|$         _7        3|*                                D ]\  }} |         j        }%g }&|%D ]w}|3v r|&8                    3|                    "||#j        v r"|&8                    |#j9        |         f           M|j        v r!|&8                    j9        |         f           x*j:        ;                    |"| |&|         j<        @          }'|%|'|         j6        f|#|<   |         j7        |#|         _7        |#=                    j>                  }#|rt          |#          }(||(_!        |(S |#S )Ca  Apply a function to each block of a DataArray or Dataset.

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

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

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

        This function cannot add a new chunked dimension.
    obj : DataArray, Dataset
        Passed to the function as its first argument, one block at a time.
    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
        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 or Dataset, 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 ``obj`` 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 ``obj`` 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()
    >>> array.map_blocks(calculate_anomaly, template=array).compute()
    <xarray.DataArray (time: 24)>
    array([ 0.12894847,  0.11323072, -0.0855964 , -0.09334032,  0.26848862,
            0.12382735,  0.22460641,  0.07650108, -0.07673453, -0.22865714,
           -0.19063865,  0.0590131 , -0.12894847, -0.11323072,  0.0855964 ,
            0.09334032, -0.26848862, -0.12382735, -0.22460641, -0.07650108,
            0.07673453,  0.22865714,  0.19063865, -0.0590131 ])
    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

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

    >>> array.map_blocks(
    ...     calculate_anomaly,
    ...     kwargs={"groupby_type": "time.year"},
    ...     template=array,
    ... )  # doctest: +ELLIPSIS
    <xarray.DataArray (time: 24)>
    dask.array<<this-array>-calculate_anomaly, shape=(24,), dtype=float64, chunksize=(24,), chunktype=numpy.ndarray>
    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>
    rS   r
   r]   listr^   dictarg_is_arrayIterable[bool]r$   c           
        d t          ||          D             } | |i |}t          |d                   t          |j                  z
  }|rt          d| d          |j                                        D ]\  }}	||d         v rM|j        |         |d         |         k    r0t          d|d|j        |          d|d         |          d          ||d	         v r<|d	         |         }
|	                    |
          st          d
|d|
d|	d          t          ||d           t          |t                    rt          ||d           t          |          S )z
        Wrapper function that receives datasets in args; converts to dataarrays when necessary;
        passes these to the user function `func` and checks returned objects for expected shapes/sizes/etc.
        c                :    g | ]\  }}|rt          |          n|S rW   )r>   )rY   is_arrayrZ   s      r   r[   z0map_blocks.<locals>._wrapper.<locals>.<listcomp>  s?     
 
 
# *2: %%%s
 
 
r   shapeszDimensions z missing on returned object.zReceived dimension z of length z. Expected length r-   indexeszExpected index  to be . Received 	 instead.r)   r+   )r   r   sizesr   _indexesrJ   equalsr2   r7   r   rk   )rS   r]   r^   rx   r$   converted_argsr"   missing_dimensionsr@   indexexpected_indexs              r   _wrapperzmap_blocks.<locals>._wrapper   s   
 
!$\4!8!8
 
 

 ~000 !(!344s6<7H7HH 	N0NNN  
 "?0022 	 	KD%x)))<%();D)AAA$Gd G GdAS G G+3H+=d+CG G G   x	***!))!4T!:||N33 $h$hhhhV[hhh  
 	vx:::fg&& 	B"68[AAA   r   Nz2template must be a DataArray or Dataset. Received r   z7args must be a sequence (for example, a list or tuple).z.kwargs must be a mapping (for example, a dict)zgCannot pass dask collections in kwargs yet. Please compute or load values before passing to map_blocks.r   )HighLevelGraphc                F    g | ]}t          |t          t          f          S rW   )r7   r   r   rX   s     r   r[   zmap_blocks.<locals>.<listcomp>I  s'    KKK3C'9!566KKKr   c                8    g | ]}t          |t                    S rW   )r7   r   rX   s     r   r[   zmap_blocks.<locals>.<listcomp>J  s"    ???s
3	**???r   c              3  6   K   | ]\  }}|         ||fV  d S r   rW   rY   r   rZ   	is_xarrays      r   	<genexpr>zmap_blocks.<locals>.<genexpr>M  sI       ( (#i>N(	( ( ( ( ( (r   c                .    g | ]\  }}|         ||fS rW   rW   r   s      r   r[   zmap_blocks.<locals>.<listcomp>P  s;       #)EBR	  r   joinexactc              3  b   K   | ]*}t          |t                    rt          |          n|V  +d S r   )r7   r   rD   rX   s     r   r   zmap_blocks.<locals>.<genexpr>V  sS         &0Y%?%?HS!!!S     r   c                    | d         S )Nr   rW   rj   s    r   <lambda>zmap_blocks.<locals>.<lambda>\  s    aPQd r   )keyr6   c                "    i | ]}||         S rW   rW   )rY   r    input_indexess     r   ri   zmap_blocks.<locals>.<dictcomp>m  s     HHHs3c*HHHr   c                ,    i | ]}|j         |         S rW   )r   )rY   rg   r`   s     r   ri   zmap_blocks.<locals>.<dictcomp>n  s#    EEEA8,Q/EEEr   c                *    i | ]}|v ||         S rW   rW   )rY   r    input_chunkss     r   ri   zmap_blocks.<locals>.<dictcomp>o  s1     =
 =
 =
'*sl?R?RCc"?R?R?Rr   zjProvided template has no dask arrays.  Please construct a template with appropriately chunked dask arrays.z~map_blocks requires that one block of the input maps to one block of output. Expected number of output chunks along dimension r   r   zP instead. Please provide template if not provided, or fix the provided template.TFz.func output must be DataArray or Dataset; got z{}-{}c                N    i | ]"\  }}|t          t          |                    #S rW   )ranger:   rY   r    chunks_vs      r   ri   zmap_blocks.<locals>.<dictcomp>  s,    RRRMCc5X''RRRr   c                D    i | ]\  }}|t          j        d |z             S r   npcumsumr   s      r   ri   zmap_blocks.<locals>.<dictcomp>  s9       ,9CRYth''  r   c                D    i | ]\  }}|t          j        d |z             S r   r   r   s      r   ri   zmap_blocks.<locals>.<dictcomp>  s9       ,9CRYth''  r   graphgnamer'   rC   r   c                   g }g }t                                                    }|j                                        D ]\  }}	                    |	j                  rZ|	                                }
|	j        D ]}|
|                  }
| d| d|
d          f|z   }t           |	j        |
|	j        gf| |<   nhfd|	j        D             }|		                    |          }| d| dj
                            |           f|z   }t           |j        ||j        gf| |<   ||j        v r|                    ||g           |                    ||g           t          t          |ft          |f|j        fS )z
        Creates a task that subsets an xarray dataset to a block determined by chunk_index.
        Block extents are determined by input_chunk_bounds.
        Also subtasks that subset the constituent variables of a dataset.
        -r   c                4    i | ]}|t          |          S rW   rq   )rY   r    rl   input_chunk_boundss     r   ri   z?map_blocks.<locals>.subset_dataset_to_block.<locals>.<dictcomp>  s9        *3=OPP  r   )tupler=   rI   rJ   r   r,   __dask_keys__rK   rL   iselbasetokenize_coord_namesappendr   rw   )r   r   rC   r   rl   r+   r)   chunk_tupler@   rP   chunkr    chunk_variable_task	subsettersubsetdasks      ``          r   subset_dataset_to_blockz+map_blocks.<locals>.subset_dataset_to_block  s    	K..0011%/5577 !	> !	>ND(&&x}55  ..00#= 4 4C!+c"23EE*.'C'C'C'Cq'C'C&E&S#]E8>:.)**    '}  	 "y11BBeBBdi&8&8&@&@BB'' # [&&,7.)* w+++t%89::::  $(;!<====$	*T6NGMJJr   c           	     <    g | ]\  }}|r |          n|S rW   rW   )rY   isxrrZ   rl   r   r   r   r   s      r   r[   zmap_blocks.<locals>.<listcomp>  sQ     
 
 
 c ##E5#7I;WWW
 
 
r   c                <    i | ]\  }}|v 	||         |         S rW   rW   )rY   rg   rh   output_chunkss      r   ri   zmap_blocks.<locals>.<dictcomp>  s:     
 
 
'+q!a=FXFXA}Q"FXFXFXr   r}   r+   r)   c           	     L    i | ] }||         t          |                   !S rW   r   )rY   r    rl   r~   output_chunk_boundss     r   ri   zmap_blocks.<locals>.<dictcomp>  sB     
 
 
 /[BUVVW
 
 
r   r~   r   r   c                >    g | ]}                     |          |S rW   r   )rY   rZ   r   s     r   r[   zmap_blocks.<locals>.<listcomp>  s,    LLLct/F/Fs/K/KLcLLLr   )dependenciesc                    i | ]}|hS rW   rW   )rY   r@   r   s     r   ri   zmap_blocks.<locals>.<dictcomp>  s    ;;;teW;;;r   c                >    i | ]\  }}||                                 S rW   )to_pandas_index)rY   rg   idxs      r   ri   zmap_blocks.<locals>.<dictcomp>&  s*    GGGVQ3&&((GGGr   )r)   rL   )r@   r   dtype)
rS   r
   r]   rv   r^   rw   rx   ry   r$   rw   )r   rw   r   r'   rC   r   )@r7   r   r   r8   r9   __name__r   r   r=   r   r   
dask.arraydask.highlevelgraphr   ImportErrorrv   r   	enumerater   r   sortedr   rw   r   r   r!   updaterb   r   rK   
chunksizesr   r:   r@   rA   collectionsdefaultdictformatutilsfuncnamer   r   rJ   	itertoolsproductkeysr+   r)   rI   operatorgetitemfrom_collectionslayersr   rL   encodingr   r   arrayArrayr   rM   r   r>   )5rS   r3   r]   r^   r`   r   valuer   all_argsr|   xarray_indicesxarray_objsothersaligned_npargsrZ   template_indexespreserved_indexesnew_indexesr    result_is_arraytemplate_name
new_layersichunkr   blocked_argsr$   from_wrappervar_key_mapr@   rP   gname_lr   hlgr"   r   rK   
var_chunksr,   darl   r   r   r   r~   r   r   r   r   r   r   r   s5       `                                    @@@@@@@@@@@@r   
map_blocksr      s
   P.! .! .! .!` Jx)W9M$N$NchAXccc
 
 	
 dH%% SQRRR~(( JHIII  e$$ 	<  	 c"" *tC)$)))&)))6666666    utDzz!HKK(KKKI??h???H #( ( ( ( ('0':':( ( ( # #NK   '0':':  F
 [/w//G      K
 tC4455>NNSSS IAv
 q	())L+,,M122 + + C000CJ'''S\****!$
DTDDDVDDx011,s=/A/AA&]););;HHHH6GHHHEEEEEEEFFF=
 =
 =
 =
.6m=
 =
 =
 x()) + 	W  
   ,3|C'8#9#9SsAS=T=T#T#T-DG- -RUVbcfVgRhRh- -c 233- - -   (I&& 	
 ,,..	Hg	&	& 
MT(^^MM
 
 	
 E?J?V@ @J NN
D!!49#5#5fQiv#N#N E
 SR\=O=O=Q=QRRRF =I=O=O=Q=Q   =J=P=P=R=R  4K 4K 4K 4K 4K 4Kn !(&--//: 4N 4N3v{{}}k::;;
 
 
 
 
 
 
 
 !F33	
 
 
 
 
 
 
/:/@/@/B/B
 
 
 !$H$6$;$;$=$= > > !5!5!7!788
 
 
 
 
 

 
 

 x+-'|VXxXl ,.&06688 	N 	NND(w''''G 'K$+:C}    +%%K,..CC 4KCC )1(8,'MJw$$+	N. 
)
)LLLLVLLL *  C .$3:$$

;;;;):):;;;
  C GGw}}GGGn  F
  : :&uo3u!)%!9u$**,, 8 8g~"
 	: 	:Cm##!!-"45555''!!6<#4"67777%%!!8>##6"8999zgj8L   
 
 dHTN$89t ( 7tx455F !&))	Ms   3D 
DD)r   r   r   r   )r"   r#   r$   r%   r&   r'   )r3   r   r4   r   )r3   r   r4   r   )rS   rT   r3   r#   r4   r   )rc   r#   r4   rd   )r    r   rl   r   rm   r   )rW   NN)rS   rT   r3   r#   r]   rr   r^   rs   r`   rt   r4   r   )$
__future__r   r   r   r   collections.abcr   r   r   r   typingr   r	   r
   numpyr   xarray.core.alignmentr   xarray.core.dataarrayr   xarray.core.datasetr   xarray.core.pycompatr   xarray.core.typesr   r   r!   r2   r>   rD   rR   rb   rk   rq   r   rW   r   r   <module>r     s   " " " " " "          A A A A A A A A A A A A / / / / / / / / / /     ' ' ' ' ' ' + + + + + + ' ' ' ' ' ' 3 3 3 3 3 3 +******  T T T T
 
 
 
.	. 	. 	. 	.     8   .7 7 7 7    '++/s s s s s s sr   