|
import matplotlib.pyplot as plt |
|
from typing import Dict, List, Tuple |
|
|
|
|
|
def plot_telemetry( |
|
metrics_log: Dict[str, List[float]], |
|
k_floor: float = 0.5, |
|
c_floor: float = 0.3, |
|
s_floor: float = 0.5, |
|
) -> Tuple[plt.Figure, List[plt.Axes]]: |
|
"""Plot K, C, S metrics over time with cluster transitions. |
|
|
|
Args: |
|
metrics_log: Dictionary with keys ``negentropy``, ``lz_complexity``, |
|
``symbiosis_score`` and optional ``clusters`` listing cluster |
|
assignments per step. |
|
k_floor: Threshold for negentropy (K). |
|
c_floor: Threshold for LZ complexity (C). |
|
s_floor: Threshold for symbiosis score (S). |
|
|
|
Returns: |
|
(figure, axes) tuple for further customization or saving. |
|
""" |
|
steps = list(range(len(metrics_log.get("negentropy", [])))) |
|
fig, axes = plt.subplots(3, 1, sharex=True, figsize=(10, 6)) |
|
metrics = [ |
|
("negentropy", k_floor, "K"), |
|
("lz_complexity", c_floor, "C"), |
|
("symbiosis_score", s_floor, "S"), |
|
] |
|
for ax, (key, floor, label) in zip(axes, metrics): |
|
values = metrics_log.get(key, []) |
|
ax.plot(steps, values, label=label) |
|
ax.axhline(floor, color="r", linestyle="--", linewidth=1) |
|
violations = [i for i, v in enumerate(values) if v < floor] |
|
if violations: |
|
ax.scatter( |
|
[steps[i] for i in violations], |
|
[values[i] for i in violations], |
|
color="r", |
|
zorder=5, |
|
label="violation", |
|
) |
|
ax.set_ylabel(label) |
|
ax.legend(loc="upper right") |
|
|
|
clusters = metrics_log.get("clusters") |
|
if clusters is not None: |
|
prev = clusters[0] |
|
for t, c in enumerate(clusters): |
|
if t > 0 and c != prev: |
|
for ax in axes: |
|
ax.axvline(t, color="gray", linestyle=":", alpha=0.5) |
|
prev = c |
|
|
|
axes[-1].set_xlabel("step") |
|
plt.tight_layout() |
|
return fig, axes |
|
|