
    dq                    0   d dl mZ d dlZd dlm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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mZ d d
lmZ d dl m!Z!m"Z" dZ#dZ$erYd dl%m&Z& d dl'm(Z( e)e)edf         ee*e*f         Z+eedf         Z,eee"f         Z-e	eef         Z.ee/ee         df         Z0ee(e&f         Z1dBdZ2dCdDdZ3dCdEdZ4dFdZ5dCdGdZ6	 dHdId#Z7	 	 	 	 	 	 	 dJdKd-Z8dLd0Z9dLd1Z:	 	 	 	 	 	 	 dMdNd8Z;	 	 	 	 	 	 	 dMdOd<Z<	 	 	 dPdQd>Z=d? Z>d@ Z?dA Z@dS )R    )annotationsN)defaultdict)HashableIterableMappingMutableMapping)TYPE_CHECKINGAnyUnion)stringstimes	variables)SerializationWarningpop_to)indexing)_contains_datetime_like_objectscontains_cftime_datetimes)is_duck_dask_array)IndexVariableVariable)
boundsgrid_mappingclimatologygeometrynode_coordinates
node_countpart_node_countinterior_ringcell_measuresformula_terms)r   r    AbstractDataStoreDataset.varr   return
T_VarTuplec                ~    | j         | j        | j                                        | j                                        fS N)dimsdataattrscopyencoding)r%   s    2lib/python3.11/site-packages/xarray/conventions.py_var_as_tupler0   3   s/    8SXsy~~//1B1B1D1DDD    nameT_Namenp.dtypec                   | j         j        dk    rt          d          | j        dk    rt	          j         t
                    S | d| j        z           }t          |t                    rt          j
        t                    S t          |t                    rt          j
        t                    S t	          j        |          j         }|j        dk    r|S t          d                    |                    )z]Given an object array with no missing values, infer its dtype from its
    first element
    Oz1infer_type must be called on a dtype=object arrayr   )r   zXunable to infer dtype on variable {!r}; xarray cannot serialize arbitrary Python objects)dtypekind	TypeErrorsizenpfloatndim
isinstancebytesr   create_vlen_dtypestrarray
ValueErrorformat)rB   r2   elementr7   s       r/   _infer_dtyperF   7   s     {3KLLLzQxD5:%&G '5!! .(///	GS	!	! .(---HW#EzS
	44:F4LL  r1   Nonec                    t          | t                    rNt          |                                 t          j                  r$t          d                    |                    d S d S )Nzvariable {!r} is a MultiIndex, which cannot yet be serialized to netCDF files. Instead, either use reset_index() to convert MultiIndex levels into coordinate variables instead or use https://cf-xarray.readthedocs.io/en/latest/coding.html.)r>   r   to_indexpd
MultiIndexNotImplementedErrorrD   )r%   r2   s     r/   ensure_not_multiindexrM   S   ss    #}%% 
*S\\^^R]*S*S 
!M NTVN N	
 
 	

 
 
 
r1   r7   np.typing.DTypeLikec                D    t          j        | j        |          }| |d<   |S )zCreate a copy of an array with the given dtype.

    We use this instead of np.array() to ensure that custom object dtypes end
    up on the resulting array.
    .)r;   emptyshape)r+   r7   results      r/   _copy_with_dtyperS   _   s%     Xdj%((FF3KMr1   c                   | j         j        dk    rt          |           \  }}}}t          j        |j                   | S t          |          rAt          j        d                    |          t                     |
                                }t          j        |          }|                                r||          }t          ||          }t          j        |          rd}	nnt          j        |          rd}	nWt#          j        |t"          j                  st#          j         t(                    }|                    t"          j                  }	t/          ||          }|	||<   nt/          |t          ||                    }|j         j        dk    s|j         j        sJ t3          ||||d          } | S )Nr6   a  variable {} has data in the form of a dask array with dtype=object, which means it is being loaded into memory to determine a data type that can be safely stored on disk. To avoid this, coerce this variable to a fixed-size dtype with astype() before saving it.r1    )r7   T)fastpath)r7   r8   r0   r   check_vlen_dtyper   warningswarnrD   r   computerJ   isnullanyrF   is_bytes_dtypeis_unicode_dtyper;   
issubdtypefloatingr<   typenanrS   metadatar   )
r%   r2   r*   r+   r,   r.   missingnon_missing_valuesinferred_dtype
fill_values
             r/   ensure_dtype_not_objectrh   j   s   
y~&3C&8&8#dE8 #DJ//;Jd## 		"M2 39&,,$   <<>>D)D//;;== 	J!%wh)*<dCCN %n55 9 

).99 9

 }^R[AA 5%'Xe__N+0088
#D???D&DMM#DT40H0HIIIDz#%%)<%%%tT5(TBBBJr1   T
needs_copyboolc           	        t          | |           t          j                    t          j                    t	          j                    t	          j                    t	          j                    t	          j                    t	          j	                    t	          j
                    fD ]}|                    | |          } t          | |          } t          D ]}t          | j        | j        |           | S )a  
    Converts an Variable into an Variable which follows some
    of the CF conventions:

        - Nans are masked using _FillValue (or the deprecated missing_value)
        - Rescaling via: scale_factor and add_offset
        - datetimes are converted to the CF 'units since time' format
        - dtype encodings are enforced.

    Parameters
    ----------
    var : Variable
        A variable holding un-encoded data.

    Returns
    -------
    out : Variable
        A variable which has been encoded as described above.
    r2   )rM   r   CFDatetimeCoderCFTimedeltaCoderr   CFScaleOffsetCoderCFMaskCoderUnsignedIntegerCoderNonStringCoderDefaultFillvalueCoderBooleanCoderencoderh   CF_RELATED_DATAr   r.   r,   )r%   ri   r2   coder	attr_names        r/   encode_cf_variablery      s    , #D)))) 	  $&&&(( ""'))  	 
+ 
+ ll3Tl** "#D
1
1
1C$ 3 3	s|SY	2222Jr1   r   concat_charactersmask_and_scaledecode_timesdecode_endiannessstack_char_dim
use_cftimebool | Nonedecode_timedeltac	                   t          |          r|S |j        }	||}|rP|r(t          j                                        ||           }t          j                                        |          }|rRt          j                    t          j                    t          j	                    fD ]}
|
                    ||           }|r(t          j                                        ||           }|r*t          j        |                              ||           }|r9|j        j        s-t          j                                        |          }|j        }	t          j                                        |          }t          j        |          \  }}}}|                    d|	           t%          |          st'          j        |          }t+          ||||d          S )a  
    Decodes a variable which may hold CF encoded information.

    This includes variables that have been masked and scaled, which
    hold CF style time variables (this is almost always the case if
    the dataset has been serialized) and which have strings encoded
    as character arrays.

    Parameters
    ----------
    name : str
        Name of the variable. Used for better error messages.
    var : Variable
        A variable holding potentially CF encoded information.
    concat_characters : bool
        Should character arrays be concatenated to strings, for
        example: ["h", "e", "l", "l", "o"] -> "hello"
    mask_and_scale : bool
        Lazily scale (using scale_factor and add_offset) and mask
        (using _FillValue). If the _Unsigned attribute is present
        treat integer arrays as unsigned.
    decode_times : bool
        Decode cf times ("hours since 2000-01-01") to np.datetime64.
    decode_endianness : bool
        Decode arrays from non-native to native endianness.
    stack_char_dim : bool
        Whether to stack characters into bytes along the last dimension of this
        array. Passed as an argument because we need to look at the full
        dataset to figure out if this is appropriate.
    use_cftime : bool, optional
        Only relevant if encoded dates come from a standard calendar
        (e.g. "gregorian", "proleptic_gregorian", "standard", or not
        specified).  If None (default), attempt to decode times to
        ``np.datetime64[ns]`` objects; if this is not possible, decode times to
        ``cftime.datetime`` objects. If True, always decode times to
        ``cftime.datetime`` objects, regardless of whether or not they can be
        represented using ``np.datetime64[ns]`` objects.  If False, always
        decode times to ``np.datetime64[ns]`` objects; if this is not possible
        raise an error.

    Returns
    -------
    out : Variable
        A variable holding the decoded equivalent of var.
    Nrl   )r   r7   T)r.   rV   )r   r7   r   CharacterArrayCoderdecodeEncodedStringCoderr   rq   rp   ro   r   rn   rm   isnativeEndianCoderrt   unpack_for_decoding
setdefaultr   r   LazilyIndexedArrayr   )r2   r%   rz   r{   r|   r}   r~   r   r   original_dtyperw   
dimensionsr+   
attributesr.   s                  r/   decode_cf_variabler      s   r 's++ 
YN' 7 	G-//66s6FFC(**11#66 /*,,!##(**
 	/ 	/E
 ,,s,..CC >$&&--c-== R#z:::AA#DAQQ #!3 ##%%,,S11

 
"
"
)
)#
.
.C-6-J3-O-O*Jj(000d## 1*400Jj8dSSSSr1   r   T_Variablesc                R    | j                     D ]}|j        }|                    d          }t          |t                    od|v }|r]d|v rY|d         | v rO| |d                  j        }|                    d|d                    d|v r|                    d|d                    dS )a  Adds time attributes to time bounds variables.

    Variables handling time bounds ("Cell boundaries" in the CF
    conventions) do not necessarily carry the necessary attributes to be
    decoded. This copies the attributes from the time variable to the
    associated boundaries.

    See Also:

    http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/
         cf-conventions.html#cell-boundaries

    https://github.com/pydata/xarray/issues/2565
    unitssincer   calendarN)valuesr,   getr>   rA   r   )r   vr,   r   has_date_unitsbounds_attrss         r/   _update_bounds_attributesr   +  s    " Y 	K 	K		'""#E3//DGu4D 	Kh%//X)++(x9?''w@@@&& ++Jj8IJJJ	K 	Kr1   c                    | j                     D ]\  }}|j        }|j        }d|v o	d|d         v }t          j        |j        t          j                  pt          |          }|rD|sBd|v r>|d         | v r4t          j	        d
                    ||d                   t                     |r]d|v rY|d         | v rO| |d                  j        }|                    d|d                    d|v r|                    d|d                    dS )a  Adds time encoding to time bounds variables.

    Variables handling time bounds ("Cell boundaries" in the CF
    conventions) do not necessarily carry the necessary attributes to be
    decoded. This copies the encoding from the time variable to the
    associated bounds variable so that we write CF-compliant files.

    See Also:

    http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/
         cf-conventions.html#cell-boundaries

    https://github.com/pydata/xarray/issues/2565
    r   r   r   a3  Variable '{0}' has datetime type and a bounds variable but {0}.encoding does not have units specified. The units encodings for '{0}' and '{1}' will be determined independently and may not be equal, counter to CF-conventions. If this is a concern, specify a units encoding for '{0}' before writing to a file.r   N)itemsr,   r.   r;   r_   r7   
datetime64r   rX   rY   rD   UserWarningr   )r   r2   r   r,   r.   r   is_datetime_typebounds_encodings           r/   _update_bounds_encodingr   H  sY   " #9?$$ Q Qa: H,MHW<M1M=GR]
 
 *&q)) 	
 	"	 E!!h9,,M2 39&uX2O2O	 	 	  	Qh%//X)++"+E(O"<"E**7HW4EFFF))#..z8J;OPPP=Q Qr1   r   T_Attrsdecode_coordsdrop_variablesT_DropVariables*tuple[T_Variables, T_Attrs, set[Hashable]]c	                V    t          t                      j                    D ]'}	|	j        D ]}
|
                             |	           (d fd}t                      }t          |t                    r|g}n|g }t          |          }|rt                      i }  j	                    D ]\  }}	||v r|o+|	j
        dk    o |	j        dk    o ||	j        d	                   }	 t          ||	||||||
          ||<   n0# t          $ r#} t          |          d|d|           d}~ww xY w|dv rp||         j        }d|v r_|d         }|                                }t#           fd|D                       r(|||         j        d<   |d= |                    |           |dk    rt(          D ]}||v r||         }|t*          vr|                                }n[d |                    d          D             }t-          |          dz  dk    rt/          j        d|ddd           |ddd         }t#           fd|D                       r&|||         j        |<   |                    |           n+ fd|D             }t/          j        d|dd|d           ||= |rtt          |                    dd          t                    rKt5          |          }|                    d          }|                    |                                           |||fS )zK
    Decode several CF encoded variables.

    See: decode_cf_variable
    dimr   r&   rj   c                r    | v rdS |          D ]&}|j         j        dk    s| |j        d         k    r dS 'dS )NFST)r7   r8   r*   )r   r   dimensions_used_byr   s     r/   	stackablez&decode_cf_variables.<locals>.stackable  sW    )5#C( 	 	Aw|s""cQVBZ&7&7uu '8tr1   NS1r   r   )rz   r{   r|   r~   r   r   zFailed to decode variable z: )Tcoordinatesallr   c              3      K   | ]}|v V  	d S r)    ).0kr   s     r/   	<genexpr>z&decode_cf_variables.<locals>.<genexpr>  s'      ??!qI~??????r1   r   c                @    g | ]}|                                 D ]}|S r   )split)r   partrole_or_names      r/   
<listcomp>z'decode_cf_variables.<locals>.<listcomp>  sG     + + + $04

+ + !- )+ + + +r1   :      z
Attribute sz
 malformed   
stacklevelc              3      K   | ]}|v V  	d S r)   r   )r   var_namer   s     r/   r   z&decode_cf_variables.<locals>.<genexpr>  s(      KKX8y0KKKKKKr1   c                    g | ]}|v|	S r   r   )r   	proj_namer   s     r/   r   z'decode_cf_variables.<locals>.<listcomp>  s.     < < < )(	99 &999r1   zVariable(s) referenced in z not in variables: )r   r   r&   rj   )r   listr   r*   appendsetr>   rA   r   r   r7   r=   r   	Exceptionra   r,   r   r   r.   updaterv   CF_RELATED_DATA_NEEDS_PARSINGlenrX   rY   r   dictpop)r   r   rz   r{   r|   r   r   r   r   r   dr   coord_namesnew_varsr   r~   e	var_attrs	coord_strvar_coord_namesrx   attr_val	var_namesroles_and_names referenced_vars_not_in_variablescrdsr   s   `                         @r/   decode_cf_variablesr   z  sN     %T**Y , , 	, 	,Aq!((++++	,       %%K.#&& ()		((N  -!),,,H	!! >- >-1 &4&
& 	!&*%%	 		C,"3-)-%!1	 	 	HQKK  	C 	C 	C$q''AqAAaAABBB	C888 )I	))%m4	"+//"3"3????????? 8:CHQK(7!-0&&777E!!, - -		))(3H (EEE$,NN$4$4		+ +(0s(;(;+ + +
 //!3q88$M DY D D D DQR    %4ADqD$9	KKKKKKKKK :B,Y7#**95555< < < <-6< < <8
 !}}}}Yy}}'(    "), )JNN=$$G$GMM )*%%
~~m,,4::<<(((Z,,s   +D
D3D..D3objT_DatasetOrAbstractstorer$   c                `   ddl m} ddlm}	 t	          | |	          r1| j        }
| j        }t          | j                  }| j	        }| j
        }n`t	          | |          rA|                                 \  }
}t                      }| j        }|                                 }nt          d          t          |
||||||||	  	        \  }
}} |	|
|          }|                    |                    |                              |
                    }|                    |           ||_
        |S )a  Decode the given Dataset or Datastore according to CF conventions into
    a new Dataset.

    Parameters
    ----------
    obj : Dataset or DataStore
        Object to decode.
    concat_characters : bool, optional
        Should character arrays be concatenated to strings, for
        example: ["h", "e", "l", "l", "o"] -> "hello"
    mask_and_scale : bool, optional
        Lazily scale (using scale_factor and add_offset) and mask
        (using _FillValue).
    decode_times : bool, optional
        Decode cf times (e.g., integers since "hours since 2000-01-01") to
        np.datetime64.
    decode_coords : bool or {"coordinates", "all"}, optional
        Controls which variables are set as coordinate variables:

        - "coordinates" or True: Set variables referred to in the
          ``'coordinates'`` attribute of the datasets or individual variables
          as coordinate variables.
        - "all": Set variables referred to in  ``'grid_mapping'``, ``'bounds'`` and
          other attributes as coordinate variables.
    drop_variables : str or iterable, optional
        A variable or list of variables to exclude from being parsed from the
        dataset. This may be useful to drop variables with problems or
        inconsistent values.
    use_cftime : bool, optional
        Only relevant if encoded dates come from a standard calendar
        (e.g. "gregorian", "proleptic_gregorian", "standard", or not
        specified).  If None (default), attempt to decode times to
        ``np.datetime64[ns]`` objects; if this is not possible, decode times to
        ``cftime.datetime`` objects. If True, always decode times to
        ``cftime.datetime`` objects, regardless of whether or not they can be
        represented using ``np.datetime64[ns]`` objects.  If False, always
        decode times to ``np.datetime64[ns]`` objects; if this is not possible
        raise an error.
    decode_timedelta : bool, optional
        If True, decode variables and coordinates with time units in
        {"days", "hours", "minutes", "seconds", "milliseconds", "microseconds"}
        into timedelta objects. If False, leave them encoded as numbers.
        If None (default), assume the same value of decode_time.

    Returns
    -------
    decoded : Dataset
    r   r!   r#   z,can only decode Dataset or DataStore objects)r   r   r   )r,   )xarray.backends.commonr"   xarray.core.datasetr$   r>   
_variablesr,   r   coords_closer.   loadcloseget_encodingr9   r   
set_coordsunionintersection	set_close)r   rz   r{   r|   r   r   r   r   r"   r$   varsr,   extra_coordsr   r.   r   dss                    r/   	decode_cfr     sW   t 988888++++++ #w H~	3:
<	C*	+	+ Hhhjjeuu	##%%FGGG2%)
  
  
 D% 
U	#	#	#B	{((66CCDII	J	JBLLBKIr1   tuple[T_Variables, T_Attrs]c                8    t          | ||||          \  } }}| |fS )a{  
    Decode a set of CF encoded variables and attributes.

    Parameters
    ----------
    variables : dict
        A dictionary mapping from variable name to xarray.Variable
    attributes : dict
        A dictionary mapping from attribute name to value
    concat_characters : bool
        Should character arrays be concatenated to strings, for
        example: ["h", "e", "l", "l", "o"] -> "hello"
    mask_and_scale : bool
        Lazily scale (using scale_factor and add_offset) and mask
        (using _FillValue).
    decode_times : bool
        Decode cf times ("hours since 2000-01-01") to np.datetime64.

    Returns
    -------
    decoded_variables : dict
        A dictionary mapping from variable name to xarray.Variable objects.
    decoded_attributes : dict
        A dictionary mapping from attribute name to values.

    See Also
    --------
    decode_cf_variable
    )r   )r   r   rz   r{   r|   _s         r/   
cf_decoderr   M  s4    H  3:0.,   Iz1 j  r1   c                   t          |          }t          |          D ]_}t          |t                    rHd|v rDt	          j        d                    |          t          d           |                    |           `|	                                }t          t                     }t                      |D ]|          j        } | j                    D ]\  }||vrI|j        vr@t          |          t          j                  k    r||                                        t          fdt          D                       r*                               |                               d  | j                    D             } t                      } | j                    D ]\  }}	|	j        }
|	j        }d|v rd|
v rt%          d|d	          d|v r|                    d          d|
v rB|
                    d          -|                    dd            |
                    dd            t+          |
|d          p|                    d          }|s6||         r.d                    fd
||         D                       }|r||d<   d|v r-|                    |d                                                    |                    |           |r]t5          |          }d|v rt	          j        d|dt                     n+d                    t7          t          |                    |d<   | |fS )N zcoordinate {!r} has a space in its name, which means it cannot be marked as a coordinate on disk and will be saved as a data variable instead   r   c              3  b   K   | ])}|j         v oj                             |          v V  *d S r)   )r.   r   )r   rx   
coord_namer   s     r/   r   z&_encode_coordinates.<locals>.<genexpr>  sV         QZ'SJ!*..:S:S,S     r1   c                B    i | ]\  }}||                     d           S )F)deep)r-   r   r   r   s      r/   
<dictcomp>z'_encode_coordinates.<locals>.<dictcomp>  s,    EEE41aAFFF&&EEEr1   r   z<'coordinates' found in both attrs and encoding for variable .c              3  >   K   | ]}|vt          |          V  d S r)   )rA   )r   r   not_technically_coordinatess     r/   r   z&_encode_coordinates.<locals>.<genexpr>  sA       ( (%@@@ J@@@@( (r1   z$cannot serialize global coordinates zu because the global attribute 'coordinates' already exists. This may prevent faithful roundtrippingof xarray datasets)r   r   r>   rA   rX   rY   rD   r   discardr-   r   r*   r   addr\   rv   r.   r,   rC   r   r   r   joinr   r   difference_updater   map)r   r   non_dim_coord_namesr2   global_coordinatesvariable_coordinatestarget_dimsr   written_coordsr%   r.   r,   
coords_strcoordinates_textr   r   r   s                 @@@r/   _encode_coordinatesr
  w  s   122()) 	. 	.dC   	.SD[[M3396$<<$     ''---,1133&s++"%%%) 7 7

+0#IO%% 	7 	7DAq,,,QVOO$$AF33$Q'++J777     !0     7 ,//
;;;"**:666	7 FE?9?3D3DEEEI UUN$Y_&& !@ !@	c<	E!!mx&?&?XtXXX   U""		-((0((]++3 IImT***LL---
 He];;Wuyy?W?W
 	8248 	8"xx ( ( ( ("6t"<( ( (    
   8'7m$E!!!!%"6"<"<">">??? ((888 
O*%%
J&&M&7I & & & %	    ),S:L1M1M(N(NJ}%j  r1   c                    t          | j                  t          | j                  z
  }t          | j        | j        |          S )a1  Encode coordinates on the given dataset object into variable specific
    and global attributes.

    When possible, this is done according to CF conventions.

    Parameters
    ----------
    dataset : Dataset
        Object to encode.

    Returns
    -------
    variables : dict
    attrs : dict
    )r  )r   r   r*   r
  r   r,   )datasetr  s     r/   encode_dataset_coordinatesr    sG      gn--GL0A0AAGM?R   r1   c                   t          |            d  | j                    D             }|                                D ]}d|j        v r|j        d         nd}|rc||v r_dD ]\}|||         j        v rK||j        v rB||         j        |         |j        |         k    r ||         j                            |           ]||fS )a  
    Encode a set of CF encoded variables and attributes.
    Takes a dicts of variables and attributes and encodes them
    to conform to CF conventions as much as possible.
    This includes masking, scaling, character array handling,
    and CF-time encoding.

    Parameters
    ----------
    variables : dict
        A dictionary mapping from variable name to xarray.Variable
    attributes : dict
        A dictionary mapping from attribute name to value

    Returns
    -------
    encoded_variables : dict
        A dictionary mapping from variable name to xarray.Variable,
    encoded_attributes : dict
        A dictionary mapping from attribute name to value

    See Also
    --------
    decode_cf_variable, encode_cf_variable
    c                8    i | ]\  }}|t          ||           S )rl   )ry   r   s      r/   r   zcf_encoder.<locals>.<dictcomp>  s,    OOOTQ%aa000OOOr1   r   N)	r   standard_nameaxispositiver   	long_name
leap_month	leap_yearmonth_lengths)r   r   r   r,   r   )r   r   r   r%   r   attrs         r/   
cf_encoderr    s    8 I&&&OO_Y_=N=NOOOH    9 9(0CI(=(=8$$4 	9f((
 9 9 8F+111dci6G6G'-d3syFF (.224888Zr1   )r%   r   r&   r'   r)   )r2   r3   r&   r4   )r%   r   r2   r3   r&   rG   )r7   rN   )r%   r   r2   r3   r&   r   )TN)r%   r   ri   rj   r2   r3   r&   r   )TTTTTNN)r2   r   r%   r   rz   rj   r{   rj   r|   rj   r}   rj   r~   rj   r   r   r   r   r&   r   )r   r   r&   rG   )TTTTNNN)r   r   r   r   rz   rj   r{   rj   r|   rj   r   rj   r   r   r   r   r   r   r&   r   )r   r   rz   rj   r{   rj   r|   rj   r   rj   r   r   r   r   r   r   r&   r$   )TTT)r   r   r   r   rz   rj   r{   rj   r|   rj   r&   r   )A
__future__r   rX   collectionsr   collections.abcr   r   r   r   typingr	   r
   r   numpyr;   pandasrJ   xarray.codingr   r   r   xarray.coding.variablesr   r   xarray.corer   xarray.core.commonr   r   xarray.core.pycompatr   xarray.core.variabler   r   rv   r   r   r"   r   r$   tupler   r'   r3   r   r   rA   r   r   r0   rF   rM   rS   rh   ry   r   r   r   r   r   r   r
  r  r  r   r1   r/   <module>r&     s   " " " " " "  # # # # # # G G G G G G G G G G G G , , , , , , , , , ,         3 3 3 3 3 3 3 3 3 3 @ @ @ @ @ @ @ @                    4 3 3 3 3 3 8 8 8 8 8 8 8 8!   	A888888++++++uXs]+S$<=J8T>"F#x-(KS#X&GC(!3T9:O$W.?%?@E E E E    8	
 	
 	
 	
 	
   / / / / /f <@) ) ) ) )^ #""$(`T `T `T `T `TFK K K K:/Q /Q /Q /Qj #&*"$(p- p- p- p- p-j #&*"$(] ] ] ] ]F #'! '! '! '! '!T]! ]! ]!@  ,4  4  4  4  4 r1   