
    h}                       S r SSKJr  SSKJrJr  SSKJrJr  SSK	r
SSKrSSKJr  SSKJrJrJr  SSKJr  / S	QrSS
KJr   " S S\R.                  \\\4   \R0                  R2                  5      r " S S\\\\4   \R0                  R2                  5      r " S S\\\\4   \R0                  R2                  5      r " S S\\\\4   \R0                  R2                  5      r " S S\\\\4   \R0                  R2                  5      r " S S\\\\4   \R0                  R2                  5      r " S S\\\\4   \R0                  R2                  5      r  " S S\\\\4   \R0                  R2                  5      r! " S S\\\\4   \R0                  R2                  5      r" " S S\\\\4   \R0                  R2                  5      r#g)aD  A collection of observation wrappers using a lambda function.

* ``TransformObservation`` - Transforms the observation with a function
* ``FilterObservation`` - Filters a ``Tuple`` or ``Dict`` to only include certain keys
* ``FlattenObservation`` - Flattens the observations
* ``GrayscaleObservation`` - Converts a RGB observation to a grayscale observation
* ``ResizeObservation`` - Resizes an array-based observation (normally a RGB observation)
* ``ReshapeObservation`` - Reshapes an array-based observation
* ``RescaleObservation`` - Rescales an observation to between a minimum and maximum value
* ``DtypeObservation`` - Convert an observation to a dtype
* ``RenderObservation`` - Allows the observation to the rendered frame
* ``DiscretizeObservation`` - Discretize a continuous Box observation space into a single Discrete space
    )annotations)CallableSequence)AnyFinalN)spaces)ActTypeObsTypeWrapperObsType)DependencyNotInstalled)
TransformObservationFilterObservationFlattenObservationGrayscaleObservationResizeObservationReshapeObservationRescaleObservationDtypeObservationAddRenderObservationDiscretizeObservation)rescale_boxc                  8    \ rS rSrSr      SS jrSS jrSrg)	r   ,   aJ  Applies a function to the ``observation`` received from the environment's :meth:`Env.reset` and :meth:`Env.step` that is passed back to the user.

The function :attr:`func` will be applied to all observations.
If the observations from :attr:`func` are outside the bounds of the ``env``'s observation space, provide an updated :attr:`observation_space`.

A vector version of the wrapper exists :class:`gymnasium.wrappers.vector.TransformObservation`.

Example:
    >>> import gymnasium as gym
    >>> from gymnasium.wrappers import TransformObservation
    >>> import numpy as np
    >>> np.random.seed(0)
    >>> env = gym.make("CartPole-v1")
    >>> env.reset(seed=42)
    (array([ 0.0273956 , -0.00611216,  0.03585979,  0.0197368 ], dtype=float32), {})
    >>> env = gym.make("CartPole-v1")
    >>> env = TransformObservation(env, lambda obs: obs + 0.1 * np.random.random(obs.shape), env.observation_space)
    >>> env.reset(seed=42)
    (array([0.08227695, 0.06540678, 0.09613613, 0.07422512]), {})

Change logs:
 * v0.15.4 - Initially added
 * v1.0.0 - Add requirement of ``observation_space``
c                    [         R                  R                  R                  XUS9  [         R                  R                  X5        Ub  X0l        X l        g)a  Constructor for the transform observation wrapper.

Args:
    env: The environment to wrap
    func: A function that will transform an observation. If this transformed observation is outside the observation space of ``env.observation_space`` then provide an `observation_space`.
    observation_space: The observation spaces of the wrapper, if None, then it is assumed the same as ``env.observation_space``.
funcobservation_spaceN)gymutilsRecordConstructorArgs__init__ObservationWrapperr   r   )selfenvr   r   s       b/home/james-whalen/.local/lib/python3.13/site-packages/gymnasium/wrappers/transform_observation.pyr!   TransformObservation.__init__I   sN     			''00/@ 	1 	
 	''2(%6"	    c                $    U R                  U5      $ )z"Apply function to the observation.)r   )r#   observations     r%   r)    TransformObservation.observation`   s    yy%%r'   r   N)r$   gym.Env[ObsType, ActType]r   zCallable[[ObsType], Any]r   z gym.Space[WrapperObsType] | None)r)   r
   returnr   )__name__
__module____qualname____firstlineno____doc__r!   r)   __static_attributes__ r'   r%   r   r   ,   s-    2& ' <	.&r'   r   c                  *    \ rS rSrSr    SS jrSrg)r   e   au  Filters a Dict or Tuple observation spaces by a set of keys or indexes.

A vector version of the wrapper exists :class:`gymnasium.wrappers.vector.FilterObservation`.

Example:
    >>> import gymnasium as gym
    >>> from gymnasium.wrappers import FilterObservation
    >>> env = gym.make("CartPole-v1")
    >>> env = gym.wrappers.TimeAwareObservation(env, flatten=False)
    >>> env.observation_space
    Dict('obs': Box([-4.8               -inf -0.41887903        -inf], [4.8               inf 0.41887903        inf], (4,), float32), 'time': Box(0, 500, (1,), int32))
    >>> env.reset(seed=42)
    ({'obs': array([ 0.0273956 , -0.00611216,  0.03585979,  0.0197368 ], dtype=float32), 'time': array([0], dtype=int32)}, {})
    >>> env = FilterObservation(env, filter_keys=['time'])
    >>> env.reset(seed=42)
    ({'time': array([0], dtype=int32)}, {})
    >>> env.step(0)
    ({'time': array([1], dtype=int32)}, 1.0, False, False, {})

Change logs:
 * v0.12.3 - Initially added, originally called `FilterObservationWrapper`
 * v1.0.0 - Rename to `FilterObservation` and add support for tuple observation spaces with integer ``filter_keys``
c           	       ^^ [        T[        5      (       d  [        S[        T5       35      e[        R
                  R                  R                  U TS9  [        TR                  [        R                  5      (       Ga  [        S T 5       5      (       d   e[        U4S jT 5       5      (       a{  T Vs/ s H/  nUTR                  R                  R                  5       ;  d  M-  UPM1     nn[        ST S[        TR                  R                  R                  5       5       SU 35      e[        R                  " T Vs0 s H  o3TR                  U   _M     sn5      n[!        U5      S:X  a  [        S	5      e["        R                  U TU4S
 jUS9  GOZ[        TR                  [        R$                  5      (       Ga  [        S T 5       5      (       d   e[!        ['        T5      5      [!        T5      :X  d
   ST 35       e[        U4S jT 5       5      (       a\  T Vs/ s H(  nSU:  d  M  U[!        TR                  5      :  d  M&  UPM*     nn[        ST S[!        TR                  5       SU 35      e[        R$                  " U4S jT 5       5      n[!        U5      S:X  a  [        S5      e["        R                  U TU4S jUS9  O![        S[        TR                  5       35      eTU l        gs  snf s  snf s  snf )zConstructor for the filter observation wrapper.

Args:
    env: The environment to wrap
    filter_keys: The set of subspaces to be *included*, use a list of strings for ``Dict`` and integers for ``Tuple`` spaces
z5Expects `filter_keys` to be a Sequence, actual type: filter_keysc              3  B   #    U  H  n[        U[        5      v   M     g 7fN)
isinstancestr.0keys     r%   	<genexpr>-FilterObservation.__init__.<locals>.<genexpr>        C{z#s++{   c              3  p   >#    U  H+  oTR                   R                  R                  5       ;  v   M-     g 7fr:   )r   r   keysr>   r?   r$   s     r%   r@   rA      s,      JU330077<<>>+s   36zNAll the `filter_keys` must be included in the observation space.
Filter keys: z
Observation keys: z
Missing keys: r   z@The observation space is empty due to filtering all of the keys.c                8   > T Vs0 s H  oX   _M	     sn$ s  snf r:   r3   )obsr?   r8   s     r%   <lambda>,FilterObservation.__init__.<locals>.<lambda>   s    ;!G;Csx-;!G!Gs   r$   r   r   c              3  B   #    U  H  n[        U[        5      v   M     g 7fr:   )r;   intr=   s     r%   r@   rA      rB   rC   z#Duplicate keys exist, filter_keys: c              3  l   >#    U  H)  nS U:  =(       a    U[        TR                  5      :  v   M+     g7fr   N)lenr   rF   s     r%   r@   rA      s0      IT#C=C3s'<'<#===s   14z\All the `filter_keys` must be included in the length of the observation space.
Filter keys: z, length of observation: z, missing indexes: c              3  B   >#    U  H  nTR                   U   v   M     g 7fr:   )r   rF   s     r%   r@   rA      s      26As%%c*ks   z9The observation space is empty due to filtering all keys.c                0   >^  [        U 4S jT 5       5      $ )Nc              3  .   >#    U  H
  nTU   v   M     g 7fr:   r3   )r>   r?   rH   s     r%   r@   ?FilterObservation.__init__.<locals>.<lambda>.<locals>.<genexpr>   s     &G;Cs3x;s   )tuple)rH   r8   s   `r%   rI   rJ      s    &G;&G!Gr'   z\FilterObservation wrapper is only usable with `Dict` and `Tuple` observations, actual type: N)r;   r   	TypeErrortyper   r   r    r!   r   r   DictallanyrE   
ValueErrorlistrP   r   Tuplesetr8   )r#   r$   r8   r?   missing_keysnew_observation_spacemissing_indexnew_observation_spacess    ``     r%   r!   FilterObservation.__init__   sL    +x00G[HYGZ[  			''00;0O c++V[[99C{CCCCC JU  
  + *#"7"7">">"C"C"EE *   
 !$$/= 1))-c.C.C.J.J.O.O.Q)R(S T%%1N4  %+KK<GHKSc++C00KH%! ()Q. V  !))G"7	 *  --v||<<C{CCCCCs;'(C-  C4[MBC   IT  
  +!*3w #&#c.C.C*D#D *  !
 !$$/=0I#cNcNcJdIe f((58  &,\\ 26A2 &" )*a/ O  !))G"8	 *  nostw  uJ  uJ  pK  oL  M  8CE  I.!s$   8,K;(K;L %
L3LLr7   N)r$   r+   r8   zSequence[str | int]r-   r.   r/   r0   r1   r!   r2   r3   r'   r%   r   r   e   s"    0XC,XC;NXCr'   r   c                  "    \ rS rSrSrSS jrSrg)r      aE  Flattens the environment's observation space and each observation from ``reset`` and ``step`` functions.

A vector version of the wrapper exists :class:`gymnasium.wrappers.vector.FlattenObservation`.

Example:
    >>> import gymnasium as gym
    >>> from gymnasium.wrappers import FlattenObservation
    >>> env = gym.make("CarRacing-v3")
    >>> env.observation_space.shape
    (96, 96, 3)
    >>> env = FlattenObservation(env)
    >>> env.observation_space.shape
    (27648,)
    >>> obs, _ = env.reset()
    >>> obs.shape
    (27648,)

Change logs:
 * v0.15.0 - Initially added
c                   ^ [         R                  R                  R                  U 5        [        R                  U TU4S j[
        R                  R                  TR                  5      S9  g)zConstructor for any environment's observation space that implements ``spaces.utils.flatten_space`` and ``spaces.utils.flatten``.

Args:
    env:  The environment to wrap
c                X   > [         R                  R                  TR                  U 5      $ r:   )r   r   flattenr   )rH   r$   s    r%   rI   -FlattenObservation.__init__.<locals>.<lambda>   s    V\\11#2G2GMr'   rK   N)r   r   r    r!   r   r   flatten_spacer   )r#   r$   s    `r%   r!   FlattenObservation.__init__   sQ     			''006%%M$ll889N9NO	 	& 	
r'   r3   N)r$   r+   rd   r3   r'   r%   r   r      s    *
r'   r   c                  &    \ rS rSrSrSSS jjrSrg)r   i  a$  Converts an image observation computed by ``reset`` and ``step`` from RGB to Grayscale.

The :attr:`keep_dim` will keep the channel dimension.

A vector version of the wrapper exists :class:`gymnasium.wrappers.vector.GrayscaleObservation`.

Example:
    >>> import gymnasium as gym
    >>> from gymnasium.wrappers import GrayscaleObservation
    >>> env = gym.make("CarRacing-v3")
    >>> env.observation_space.shape
    (96, 96, 3)
    >>> grayscale_env = GrayscaleObservation(env)
    >>> grayscale_env.observation_space.shape
    (96, 96)
    >>> grayscale_env = GrayscaleObservation(env, keep_dim=True)
    >>> grayscale_env.observation_space.shape
    (96, 96, 1)

Change logs:
 * v0.15.0 - Initially added, originally called ``GrayScaleObservation``
 * v1.0.0 - Renamed to ``GrayscaleObservation``
c                   [        UR                  [        R                  5      (       d   e[	        UR                  R
                  5      S:X  a  UR                  R
                  S   S:X  d   e[        R                  " UR                  R                  S:H  5      (       aZ  [        R                  " UR                  R                  S:H  5      (       a(  UR                  R                  [        R                  :X  d   e[        R                  R                  R                  XS9  X l        U(       aW  [        R                  " SSUR                  R
                  SS S-   [        R                  S	9n["        R                  U US
 US9  g[        R                  " SSUR                  R
                  SS [        R                  S	9n["        R                  U US US9  g)zConstructor for an RGB image based environments to make the image grayscale.

Args:
    env: The environment to wrap
    keep_dim: If to keep the channel in the observation, if ``True``, ``obs.shape == 3`` else ``obs.shape == 2``
   r      keep_dimN   )   lowhighshapedtypec                    [         R                  " [         R                  " [         R                  " U [         R                  " / SQ5      5      SS9R                  [         R                  5      SS9$ N)g333333?gjq?gL
F%u?rp   )axis)npexpand_dimssummultiplyarrayastypeuint8rH   s    r%   rI   /GrayscaleObservation.__init__.<locals>.<lambda>>  sE    FFC2J)KLSUfRXX&	"r'   rK   c           	         [         R                  " [         R                  " U [         R                  " / SQ5      5      SS9R	                  [         R
                  5      $ r|   )r~   r   r   r   r   r   r   s    r%   rI   r   M  s:    KKRXX.F%GHr"&""#r'   )r;   r   r   BoxrP   ry   r~   rY   rw   rx   rz   r   r   r   r    r!   rs   r   )r#   r$   rs   r`   s       r%   r!   GrayscaleObservation.__init__   s    #//<<<<%%++,1%%++B/14	
5 FF3((,,122s,,11S899%%++rxx7	
8 			''000I%-$*JJ++11"15<hh	%! !)) #8 * 
 %+JJCs'<'<'B'B2A'Fbhh%! !))# #8 * r'   rr   NF)r$   r+   rs   boolrd   r3   r'   r%   r   r     s    01 1r'   r   c                  "    \ rS rSrSrSS jrSrg)r   iT  a4  Resizes image observations using OpenCV to a specified shape.

A vector version of the wrapper exists :class:`gymnasium.wrappers.vector.ResizeObservation`.

Example:
    >>> import gymnasium as gym
    >>> from gymnasium.wrappers import ResizeObservation
    >>> env = gym.make("CarRacing-v3")
    >>> env.observation_space.shape
    (96, 96, 3)
    >>> resized_env = ResizeObservation(env, (32, 32))
    >>> resized_env.observation_space.shape
    (32, 32, 3)

Change logs:
 * v0.12.6 - Initially added
 * v1.0.0 - Requires ``shape`` with a tuple of two integers
c                  ^ ^ [        UR                  [        R                  5      (       d   e[	        UR                  R
                  5      S;   d   e[        R                  " UR                  R                  S:H  5      (       a2  [        R                  " UR                  R                  S:H  5      (       d   eUR                  R                  [        R                  :X  d   e[        U[        5      (       d   e[	        U5      S:X  d   e[        S U 5       5      (       d   e[        S U 5       5      (       d   e SSKm[        U5      T l        US	   US   4T l        [        R                  " SST R
                  UR                  R
                  SS -   [        R                  S
9n["        R$                  R&                  R)                  T US9  [*        R)                  T UUU 4S jUS9  g! [         a  n[        S5      UeSnAff = f)zConstructor that requires an image environment observation space with a shape.

Args:
    env: The environment to wrap
    shape: The resized observation shape
>   rt   ro   r   rq   rt   c              3  ~   #    U  H3  n[         R                  " [        U5      [         R                  5      v   M5     g 7fr:   r~   
issubdtyperW   integerr>   elems     r%   r@   -ResizeObservation.__init__.<locals>.<genexpr>{  &     KUT2==dRZZ88U   ;=c              3  *   #    U  H	  oS :  v   M     g7frO   r3   r>   xs     r%   r@   r   |  s     (%Qq5%s   NzCopencv (cv2) is not installed, run `pip install "gymnasium[other]"`ru   rv   ry   c                N   > TR                  U TR                  TR                  S9$ )N)interpolation)resize	cv2_shape
INTER_AREA)rH   cv2r#   s    r%   rI   ,ResizeObservation.__init__.<locals>.<lambda>  s"    SZZT^^3>> ( r'   rK   )r;   r   r   r   rP   ry   r~   rY   rw   rx   rz   r   rU   r   ImportErrorr   r   r   r   r    r!   r   )r#   r$   ry   er`   r   s   `    @r%   r!   ResizeObservation.__init__k  s    #//<<<<3((../6999vvc++//1455"&&!!&&#-;
 ;
 	
 
 $$**bhh666%''''5zQKUKKKKK(%(((((	 .35\
27(E!H1E &

**s44::12>>((	!
 			''00U0C%% 4 	& 	
#  	(U	s   >G. .
H	8HH	)r   ry   N)r$   r+   ry   ztuple[int, int]rd   r3   r'   r%   r   r   T  s    &-
r'   r   c                  "    \ rS rSrSrSS jrSrg)r   i  a  Reshapes Array based observations to a specified shape.

A vector version of the wrapper exists :class:`gymnasium.wrappers.vector.RescaleObservation`.

Example:
    >>> import gymnasium as gym
    >>> from gymnasium.wrappers import ReshapeObservation
    >>> env = gym.make("CarRacing-v3")
    >>> env.observation_space.shape
    (96, 96, 3)
    >>> reshape_env = ReshapeObservation(env, (24, 4, 96, 1, 3))
    >>> reshape_env.observation_space.shape
    (24, 4, 96, 1, 3)

Change logs:
 * v1.0.0 - Initially added
c                R  ^ [        UR                  [        R                  5      (       d   e[        R
                  " T5      [        R
                  " UR                  R                  5      :X  d   e[        T[        5      (       d   e[        S T 5       5      (       d   e[        S T 5       5      (       d   e[        R                  " [        R                  " [        R                  " UR                  R                  5      T5      [        R                  " [        R                  " UR                  R                  5      T5      TUR                  R                  S9nTU l        [        R                  R                   R#                  U TS9  [$        R#                  U UU4S jUS9  g)zConstructor for env with ``Box`` observation space that has a shape product equal to the new shape product.

Args:
    env: The environment to wrap
    shape: The reshaped observation space
c              3  ~   #    U  H3  n[         R                  " [        U5      [         R                  5      v   M5     g 7fr:   r   r   s     r%   r@   .ReshapeObservation.__init__.<locals>.<genexpr>  r   r   c              3  B   #    U  H  oS :  =(       d    US:H  v   M     g7f)r   rp   Nr3   r   s     r%   r@   r     s     3Uq5#AG#UrC   rv   r   c                2   > [         R                  " U T5      $ r:   )r~   reshape)rH   ry   s    r%   rI   -ReshapeObservation.__init__.<locals>.<lambda>  s    RZZU3r'   rK   N)r;   r   r   r   r~   prodry   rU   rY   r   ravelrw   rx   rz   r   r   r    r!   r   )r#   r$   ry   r`   s     ` r%   r!   ReshapeObservation.__init__  s:    #//<<<<wwu~)>)>)D)D!EEEE%''''KUKKKKK3U33333 &



288C$9$9$=$=>FBHHS%:%:%?%?@%H''--	!
 
		''00U0C%%33	 	& 	
r'   r   N)r$   r+   ry   int | tuple[int, ...]rd   r3   r'   r%   r   r     s    $
r'   r   c                  .    \ rS rSrSr      SS jrSrg)r   i  a,  Affinely (linearly) rescales a ``Box`` observation space of the environment to within the range of ``[min_obs, max_obs]``.

For unbounded components in the original observation space, the corresponding target bounds must also be infinite and vice versa.

A vector version of the wrapper exists :class:`gymnasium.wrappers.vector.RescaleObservation`.

Example:
    >>> import gymnasium as gym
    >>> from gymnasium.wrappers import RescaleObservation
    >>> env = gym.make("Pendulum-v1")
    >>> env.observation_space
    Box([-1. -1. -8.], [1. 1. 8.], (3,), float32)
    >>> env = RescaleObservation(env, np.array([-2, -1, -10], dtype=np.float32), np.array([1, 0, 1], dtype=np.float32))
    >>> env.observation_space
    Box([ -2.  -1. -10.], [1. 0. 1.], (3,), float32)

Change logs:
 * v1.0.0 - Initially added
c                   [        UR                  [        R                  5      (       d   e[        R
                  R                  R                  XUS9  [        UR                  X#5      u  pEn[        R                  U UUUS9  g)zConstructor that requires the env observation spaces to be a :class:`Box`.

Args:
    env: The environment to wrap
    min_obs: The new minimum observation bound
    max_obs: The new maximum observation bound
)min_obsmax_obsrK   N)
r;   r   r   r   r   r   r    r!   r   r   )r#   r$   r   r   	obs_spacer   _s          r%   r!   RescaleObservation.__init__  su     #//<<<<		''00PW0X()>)>Q	%%'	 	& 	
r'   r3   N)r$   r+   r   %np.floating | np.integer | np.ndarrayr   r   rd   r3   r'   r%   r   r     s(    (
&
 7
 7	
r'   r   c                  "    \ rS rSrSrSS jrSrg)r   i  aT  Modifies the dtype of an observation array to a specified dtype.

Note:
    This is only compatible with :class:`Box`, :class:`Discrete`, :class:`MultiDiscrete` and :class:`MultiBinary` observation spaces

A vector version of the wrapper exists :class:`gymnasium.wrappers.vector.DtypeObservation`.

Change logs:
 * v1.0.0 - Initially added
c                  ^ [        UR                  [        R                  [        R                  [        R
                  [        R                  45      (       d   eTU l        [        UR                  [        R                  5      (       a_  [        R                  " UR                  R                  UR                  R                  UR                  R                  U R                  S9nGOG[        UR                  [        R                  5      (       aa  [        R                  " UR                  R                  UR                  R                  UR                  R                  -   SU R                  S9nO[        UR                  [        R
                  5      (       a*  [        R
                  " UR                  R                  TS9nOj[        UR                  [        R                  5      (       a6  [        R                  " SSUR                  R                  U R                  S9nO[        S5      e[        R                   R"                  R%                  U TS9  [&        R%                  U UU4S jUS9  g	)
zConstructor for Dtype observation wrapper.

Args:
    env: The environment to wrap
    dtype: The new dtype of the observation
rv   r3   rz   r   ru   zJDtypeObservation is only compatible with value / array-based observations.c                   > T" U 5      $ r:   r3   )rH   rz   s    r%   rI   +DtypeObservation.__init__.<locals>.<lambda>@  s	    U3Zr'   rK   N)r;   r   r   r   DiscreteMultiDiscreteMultiBinaryrz   rw   rx   ry   startnnvecrV   r   r   r    r!   r   )r#   r$   rz   r`   s     ` r%   r!   DtypeObservation.__init__  s    !!ZZ&*>*>@R@RS
 
 	
 

 
c++VZZ88$*JJ))--**//++11jj	%! --v??$*JJ))//**0033H3H3J3JJjj	%! --v/C/CDD$*$8$8%%**%%! --v/A/ABB$*JJ++11jj	%! \  			''00U0C%%'3	 	& 	
r'   r   N)r$   r+   rz   r   rd   r3   r'   r%   r   r     s    	1
r'   r   c                  :    \ rS rSrSr   S       SS jjrSrg)r   iE  aU  Includes the rendered observations in the environment's observations.

Notes:
   This was previously called ``PixelObservationWrapper``.

No vector version of the wrapper exists.

Example - Replace the observation with the rendered image:
    >>> env = gym.make("CartPole-v1", render_mode="rgb_array")
    >>> env = AddRenderObservation(env, render_only=True)
    >>> env.observation_space
    Box(0, 255, (400, 600, 3), uint8)
    >>> obs, _ = env.reset(seed=123)
    >>> image = env.render()
    >>> np.all(obs == image)
    np.True_
    >>> obs, *_ = env.step(env.action_space.sample())
    >>> image = env.render()
    >>> np.all(obs == image)
    np.True_

Example - Add the rendered image to the original observation as a dictionary item:
    >>> env = gym.make("CartPole-v1", render_mode="rgb_array")
    >>> env = AddRenderObservation(env, render_only=False)
    >>> env.observation_space
    Dict('pixels': Box(0, 255, (400, 600, 3), uint8), 'state': Box([-4.8               -inf -0.41887903        -inf], [4.8               inf 0.41887903        inf], (4,), float32))
    >>> obs, info = env.reset(seed=123)
    >>> obs.keys()
    dict_keys(['state', 'pixels'])
    >>> obs["state"]
    array([ 0.01823519, -0.0446179 , -0.02796401, -0.03156282], dtype=float32)
    >>> np.all(obs["pixels"] == env.render())
    np.True_
    >>> obs, reward, terminates, truncates, info = env.step(env.action_space.sample())
    >>> image = env.render()
    >>> np.all(obs["pixels"] == image)
    np.True_

Change logs:
 * v0.15.0 - Initially added as ``PixelObservationWrapper``
 * v1.0.0 - Renamed to ``AddRenderObservation``
c                  ^ ^^ [         R                  R                  R                  T UTTS9  UR                  b  UR                  S:w  d   eUR                  5         UR                  5       nUb  [        U[        R                  5      (       d   e[        R                  " SSUR                  [        R                  S9nU(       a  Un[        R                  T UU 4S jUS9  g[        UR                  [        R                   5      (       at  TUR                  R                  R#                  5       ;  d   e[        R                   " TU0UR                  R                  E5      n[        R                  T UUU 4S	 jUS9  g[        R                   " TUR                  TU05      n[        R                  T UUUU 4S
 jUS9  g)aI  Constructor of the add render observation wrapper.

Args:
    env: The environment to wrap.
    render_only (bool): If ``True`` (default), the original observation returned
        by the wrapped environment will be discarded, and a dictionary
        observation will only include pixels. If ``False``, the
        observation dictionary will contain both the original
        observations and the pixel observations.
    render_key: Optional custom string specifying the pixel key. Defaults to "pixels"
    obs_key: Optional custom string specifying the obs key. Defaults to "state"
)pixels_only
pixels_keyobs_keyNhumanr   rq   rv   c                $   > TR                  5       $ r:   render)r   r#   s    r%   rI   /AddRenderObservation.__init__.<locals>.<lambda>  s    dkkmr'   rK   c                ,   > TTR                  5       0U E$ r:   r   )rH   
render_keyr#   s    r%   rI   r     s    *dkkm!Cs!Cr'   c                ,   > TU TTR                  5       0$ r:   r   )rH   r   r   r#   s    r%   rI   r     s    '3
DKKM!Jr'   )r   r   r    r!   render_moderesetr   r;   r~   ndarrayr   r   ry   r   r   r   rX   rE   )r#   r$   render_onlyr   r   pixelspixel_spacer   s   `  ``   r%   r!   AddRenderObservation.__init__t  s   & 			''00#!	 	1 	
 *s'/III		!j&D&DDDjjQSBHHU#I ))#$;y *  --v{{;;S%:%:%A%A%F%F%HHHH[IC,A,A,H,HII !))C"+	 *  #//[II !))J"+	 * r'   r3   N)Tr   state)r$   r+   r   r   r   r<   r   r<   rd   r3   r'   r%   r   r   E  sC    )\ !":&: : 	:
 : :r'   r   c                  J    \ rS rSrSr S
     SS jjrS rS rS rS r	Sr
g	)r   i  a  Uniformly discretizes a continuous Box observation space into a single Discrete space.

Example 1 - Discretize MountainCar observation space:
    >>> env = gym.make("MountainCar-v0")
    >>> env.observation_space
    Box([-1.2  -0.07], [0.6  0.07], (2,), float32)
    >>> obs, _ = env.reset(seed=42)
    >>> obs
    array([-0.4452088,  0.       ], dtype=float32)
    >>> env = DiscretizeObservation(env, bins=10)
    >>> env.observation_space
    Discrete(100)
    >>> obs, _ = env.reset(seed=42)
    >>> obs
    45

Example 2 - Discretize LunarLander observation space:
    >>> env = gym.make("LunarLander-v3")
    >>> env.observation_space
    Box([ -2.5        -2.5       -10.        -10.         -6.2831855 -10.
      -0.         -0.       ], [ 2.5        2.5       10.        10.         6.2831855 10.
      1.         1.       ], (8,), float32)
    >>> obs, _ = env.reset(seed=42)
    >>> obs
    array([ 0.00229702,  1.4181306 ,  0.2326471 ,  0.3204666 , -0.00265488,
           -0.05269805,  0.        ,  0.        ], dtype=float32)
    >>> env = DiscretizeObservation(env, bins=3)
    >>> env.observation_space
    Discrete(6561)
    >>> obs, _ = env.reset(seed=42)
    >>> obs
    4005

Example 3 - Discretize LunarLander observation space with MultiDiscrete:
    >>> env = gym.make("LunarLander-v3")
    >>> env.observation_space
    Box([ -2.5        -2.5       -10.        -10.         -6.2831855 -10.
      -0.         -0.       ], [ 2.5        2.5       10.        10.         6.2831855 10.
      1.         1.       ], (8,), float32)
    >>> obs, _ = env.reset(seed=42)
    >>> obs
    array([ 0.00229702,  1.4181306 ,  0.2326471 ,  0.3204666 , -0.00265488,
           -0.05269805,  0.        ,  0.        ], dtype=float32)
    >>> env = DiscretizeObservation(env, bins=3, multidiscrete=True)
    >>> env.observation_space
    MultiDiscrete([3 3 3 3 3 3 3 3])
    >>> obs, _ = env.reset(seed=42)
    >>> obs
    array([1, 2, 1, 1, 1, 1, 0, 0])
c           	        [        UR                  [        R                  5      (       d  [	        S5      eUR                  R
                  U l        UR                  R                  U l        U R
                  R                  S   U l        [        R                  " [        R                  " U R
                  5      5      (       d9  [        R                  " [        R                  " U R                  5      5      (       a%  [        SU R
                   SU R                   35      eX0l        [        R                  R                   R#                  XS9  [        R$                  R#                  X5        [        U[&        5      (       a*  [        R(                  " U/U R                  -  5      U l        OT[-        U5      U R                  :X  d    SU R                   S[-        U5       35       e[        R(                  " U5      U l        [/        U R                  5       Vs/ s HH  n[        R0                  " U R
                  U   U R                  U   U R*                  U   S-   5      SS	 PMJ     snU l        U R                  (       a&  [        R4                  " U R*                  5      U l        g
[        R6                  " [        R8                  " U R*                  5      5      U l        g
s  snf )zConstructor for the discretize observation wrapper.

Args:
    env: The environment to wrap.
    bins: int or tuple of ints (number of bins per dimension).
    multidiscrete: If True, use MultiDiscrete space instead of flattening to Discrete.
zJDiscretizeObservation is only compatible with Box continuous observations.r   zCDiscretization requires observation space to be finite. Found: low=z, high=)binsz,bins must match action dimensions: expected z, got ru   rp   N)r;   r   r   r   rV   rw   rx   ry   n_dimsr~   rZ   isinfr[   multidiscreter   r   r    r!   r"   rM   r   r   rP   rangelinspace	bin_edgesr   r   r   )r#   r$   r   r   is        r%   r!   DiscretizeObservation.__init__  s    #//<<\  ((,,))..	hhnnQ'66"((488$%%0C)D)D"hhZwtyyk; 
 +		''000A''2dC  $$++!56DI D	T[[(]=dkk]&QTUYQZP[\](DI 4;;'
' KKTYYq\499Q<!3CDQrJ'

 %+%9%9$))%DD"%+__RWWTYY5G%HD"
s   AKc           
        [         R                  " XR                  U R                  S-
  5      n[	        U R
                  5       Vs/ s H2  n[        [         R                  " X#   U R                  U   5      5      PM4     nnU R                  (       a#  [         R                  " U[         R                  S9$ [        U R                  U5      5      $ s  snf )zDiscretizes the observation.g:0yE>r   )r~   cliprw   rx   r   r   rM   digitizer   r   r   int64_flatten_indices)r#   r)   clippedr   indicess        r%   r)   !DiscretizeObservation.observation  s     ''+xxT1ABEJ4;;EW
EWCGJq(9:;EW 	 
 88G28844t,,W566
s   9Cc                H   U R                   (       a  [        R                  " U[        S9nOU R	                  U5      n/ n/ n[        U5       Hp  u  pV[        R                  " U R                  U   U R                  U   U R                  U   S-   5      nUR                  Xv   5        UR                  XvS-      5        Mr     [        R                  " X0R                  R                  R                  S9[        R                  " X@R                  R                  R                  S94$ )z_Reverts discretization. It returns the edges of the bin the discretized observation belongs to.r   ru   )r   r~   asarrayrM   _unflatten_index	enumerater   rw   rx   r   appendr   r$   r   rz   )r#   rH   r   lowshighsr   idxedgess           r%   revert_observation(DiscretizeObservation.revert_observation*  s    jjC0G++C0G(FAKKTYYq\499Q<!;KLEKK
#LLQw( ) xxHH$>$>$D$DErxx3399H
 
 	
r'   c                r    Sn[        U R                  5       H  nX R                  U   -  nX!U   -  nM     U$ Nr   )r   r   r   )r#   r   
flat_indexr   s       r%   r   &DiscretizeObservation._flatten_indices:  s>    
t{{#A))A,&J!*$J $ r'   c                r    / n[        U R                  5       H  nUR                  SX-  5        X-  nM     U$ r   )reversedr   insert)r#   r   r   bs       r%   r   &DiscretizeObservation._unflatten_indexA  s9    $))$ANN1jn-J % r'   )r   r   rx   rw   r   r   r   Nr   )r$   r+   r   r   r   r   )r-   r.   r/   r0   r1   r!   r)   r   r   r   r2   r3   r'   r%   r   r     sG    1n $	0I&0I $0I 	0Id7 
 r'   r   )$r1   
__future__r   collections.abcr   r   typingr   r   numpyr~   	gymnasiumr   r   gymnasium.corer	   r
   r   gymnasium.errorr   __all__gymnasium.wrappers.utilsr   r"   r   r    r   r   r   r   r   r   r   r   r   r   r3   r'   r%   <module>r
     s   # .     ; ; 2 16&>7G;<II##6&rtC'9:II##tCn%
'9:II##%
PM'9:II##M`D
'9:II##D
N2
'9:II##2
j/
'9:II##/
d@
'9:II##@
Fi'9:II##iXU'9:II##Ur'   