Skip to content

color

Color

Bases: StrEnum

Contains color aliases and converters to go between the various color formats. The color values are defined by the standard Tailwind CSS color theme.

MuJoCo uses a normalized rgba (all color channels clamped between 0 and 1). This enum defines with hex values, but they can be easily transformed with the provided methods (for example: Color.WHITE.rgba).

rgba property

Python
rgba: Vec4

Returns the normalized RGBA array for MuJoCo.

with_alpha

Python
with_alpha(alpha: float) -> Vec4

Returns the color with a custom transparency level.

Source code in src/mujoco_mojo/utils/color.py
Python
def with_alpha(self, alpha: float) -> Vec4:
    """Returns the color with a custom transparency level."""
    return Color.hex_to_rgba(self.value, alpha=alpha)

hex_to_rgba classmethod

Python
hex_to_rgba(hex_str: str, alpha: float = 1.0) -> Vec4

Converts '#RRGGBB' or 'RRGGBB' to normalized [0, 1] RGBA.

Source code in src/mujoco_mojo/utils/color.py
Python
@classmethod
def hex_to_rgba(cls, hex_str: str, alpha: float = 1.0) -> Vec4:
    """Converts '#RRGGBB' or 'RRGGBB' to normalized [0, 1] RGBA."""
    hex_str = hex_str.lstrip("#")
    # Convert hex to integers using bit-shifting
    lv = len(hex_str)
    if lv == 6:
        rgb = tuple(int(hex_str[i : i + 2], 16) for i in (0, 2, 4))
    else:
        raise ValueError(f"Invalid hex color: {hex_str}. Expected 6 characters.")

    return np.array([*(np.array(rgb) / 255.0), alpha])

rgba255_to_rgba classmethod

Python
rgba255_to_rgba(rgba255: Vec4) -> Vec4

Converts [0-255, 0-255, 0-255, 0-1] to normalized [0, 1] RGBA.

Source code in src/mujoco_mojo/utils/color.py
Python
@classmethod
def rgba255_to_rgba(cls, rgba255: Vec4) -> Vec4:
    """Converts [0-255, 0-255, 0-255, 0-1] to normalized [0, 1] RGBA."""
    res = np.array(rgba255, dtype=float)
    res[:3] /= 255.0
    return res

rgba_to_hex classmethod

Python
rgba_to_hex(rgba: Vec4) -> str

Converts normalized RGBA to '#RRGGBB' (alpha is discarded).

Source code in src/mujoco_mojo/utils/color.py
Python
@classmethod
def rgba_to_hex(cls, rgba: Vec4) -> str:
    """Converts normalized RGBA to '#RRGGBB' (alpha is discarded)."""
    rgba = np.asarray(rgba, dtype=float)
    rgb255 = (rgba[:3] * 255).astype(int)
    return "#{:02x}{:02x}{:02x}".format(*rgb255)

rgba_to_rgba255 classmethod

Python
rgba_to_rgba255(rgba: Vec4) -> Vec4

Converts normalized RGBA to [0-255, 0-255, 0-255, 0-1].

Source code in src/mujoco_mojo/utils/color.py
Python
@classmethod
def rgba_to_rgba255(cls, rgba: Vec4) -> Vec4:
    """Converts normalized RGBA to [0-255, 0-255, 0-255, 0-1]."""
    res = np.array(rgba, dtype=float)
    res[:3] *= 255.0
    return res

parse classmethod

Python
parse(v: Any) -> str | None

Normalizes arbitrary color input: None/"" -> None (hidden/unset), a member name (case-insensitive) -> its canonical uppercase name, a #rrggbb hex code -> its canonical member name if that exact hex matches one, otherwise its uppercase hex form. Anything else raises ValueError.

Returns a plain str, not a Color, since a caller (e.g. VisualizationSettings's color fields) may need to store an arbitrary hex with no matching member, not just a member name - not every valid return value corresponds to an actual enum member.

Source code in src/mujoco_mojo/utils/color.py
Python
@classmethod
def parse(cls, v: Any) -> str | None:
    """
    Normalizes arbitrary color input: `None`/`""` -> `None` (hidden/unset), a member name (case-insensitive) -> its canonical uppercase name, a `#rrggbb` hex code -> its canonical member name if that exact hex matches one, otherwise its uppercase hex form. Anything else raises `ValueError`.

    Returns a plain `str`, not a `Color`, since a caller (e.g. `VisualizationSettings`'s color fields) may need to store an arbitrary hex with no matching member, not just a member name - not every valid return value corresponds to an actual enum member.
    """
    if v is None or v == "":
        return None
    if not isinstance(v, str):
        msg = f"{v!r} is not a valid Color name or hex code."
        raise ValueError(msg)
    if _HEX_COLOR_RE.match(v):
        hex_upper = v.upper()
        return _HEX_TO_COLOR_NAME.get(hex_upper, hex_upper)
    upper = v.upper()
    if upper in cls.__members__:
        return upper
    msg = f"'{v}' is not a valid Color name (e.g. 'ROSE_500') or hex code (e.g. '#F43F5E')."
    raise ValueError(msg)