Source code for mllm_shap.viz.colors

"""SHAP-inspired diverging colors for signed attributions.

@domain viz
@see [[knowledge/architecture/viz]]
"""

from typing import cast

WHITE = (1.0, 1.0, 1.0)
SHAP_RED_RGB = (1.0, 13 / 255, 87 / 255)
SHAP_BLUE_RGB = (30 / 255, 136 / 255, 229 / 255)


[docs] def diverging_rgba(value: float, vmax: float) -> tuple[float, float, float, float]: """Map a signed attribution to an RGBA tuple (SHAP red / blue scale).""" return token_background_rgba(value, vmax)
[docs] def token_background_rgba( value: float, vmax: float ) -> tuple[float, float, float, float]: """Return a soft highlight color for one token (white center, saturated tails).""" if vmax <= 0.0: return (0.97, 0.97, 0.98, 1.0) scaled = 0.5 + 0.5 * max(-1.0, min(1.0, value / vmax)) if scaled <= 0.5: intensity = 1.0 - (scaled / 0.5) red, green, blue = _blend(SHAP_BLUE_RGB, WHITE, intensity * 0.92) alpha = 0.28 + 0.5 * intensity else: intensity = (scaled - 0.5) / 0.5 red, green, blue = _blend(SHAP_RED_RGB, WHITE, intensity * 0.92) alpha = 0.28 + 0.5 * intensity return (red, green, blue, alpha)
[docs] def bar_color(value: float) -> str: """Return the SHAP primary color for a signed bar attribution.""" return "#FF0D57" if value >= 0 else "#1E88E5"
[docs] def rgba_css(red: float, green: float, blue: float, alpha: float) -> str: """Format an rgba() string for HTML/CSS.""" return f"rgba({int(red * 255)},{int(green * 255)},{int(blue * 255)},{alpha:.2f})"
[docs] def token_background_css(value: float, vmax: float) -> str: """Return a CSS background color for one token span.""" red, green, blue, alpha = token_background_rgba(value, vmax) return rgba_css(red, green, blue, alpha)
def _blend( foreground: tuple[float, float, float], background: tuple[float, float, float], weight: float, ) -> tuple[float, float, float]: clamped = max(0.0, min(1.0, weight)) return cast( tuple[float, float, float], tuple( background[channel] * (1.0 - clamped) + foreground[channel] * clamped for channel in range(3) ), )