Skip to content

Controller

Interactive controller for the entropy-tree visualizer.

Extends :class:bloqade.lanes.visualize.app.DebuggerController so the slider, Prev/Next buttons, and keyboard shortcuts come for free.

EntropyTreeController dataclass

EntropyTreeController(
    reducer: TreeStateReducer,
    arch_spec: Any,
    target: dict[int, LocationAddress],
    root_node_id: int,
    best_buffer_size: int,
    scorer: EntropyScorer | None = None,
    blocked_locations: tuple[LocationAddress, ...] = (),
    qid_label_map: dict[int, int] | None = None,
    blocked_location_labels: dict[Any, int] | None = None,
    step_index: int = 0,
)

Bases: DebuggerController


              flowchart TD
              bloqade.lanes.visualize.entropy_tree.controller.EntropyTreeController[EntropyTreeController]
              bloqade.lanes.visualize.app.DebuggerController[DebuggerController]

                              bloqade.lanes.visualize.app.DebuggerController --> bloqade.lanes.visualize.entropy_tree.controller.EntropyTreeController
                


              click bloqade.lanes.visualize.entropy_tree.controller.EntropyTreeController href "" "bloqade.lanes.visualize.entropy_tree.controller.EntropyTreeController"
              click bloqade.lanes.visualize.app.DebuggerController href "" "bloqade.lanes.visualize.app.DebuggerController"
            

Drives the interactive entropy-tree view.

attach

attach() -> Any

Build the figure and wire the event loop. Returns the Figure.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/visualize/entropy_tree/controller.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def attach(self) -> Any:
    """Build the figure and wire the event loop. Returns the Figure."""
    fig = plt.figure(figsize=(16, 9))
    # 3 content rows; a single slider lives below the grid in the area
    # reserved by `subplots_adjust(bottom=...)`. Keyboard shortcuts
    # (left / right / escape) replace the Prev / Next / Exit buttons.
    gs = GridSpec(
        3,
        2,
        figure=fig,
        width_ratios=[1.65, 2.35],
        height_ratios=[2.2, 3.8, 3.0],
    )
    self._ax_meta = fig.add_subplot(gs[0, 0])
    self._ax_tree = fig.add_subplot(gs[1:3, 0])
    self._ax_focus = fig.add_subplot(gs[0:3, 1])
    self._ax_meta.axis("off")
    fig.subplots_adjust(bottom=0.12, top=0.97, left=0.04, right=0.98)

    self._fig = fig
    self.run_mpl_event_loop(self._ax_tree, fig)
    return fig

on_slider_change

on_slider_change(value) -> None

Handle a slider drag/click event. Default is a no-op so legacy controllers without slider support continue to work.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/visualize/entropy_tree/controller.py
81
82
83
84
85
def on_slider_change(self, value) -> None:  # type: ignore[no-untyped-def]
    new_idx = int(value)
    if new_idx != self.step_index:
        self.step_index = new_idx
        self._render(new_idx)

run_mpl_event_loop

run_mpl_event_loop(ax, fig) -> None

Slider-only event loop — no Prev/Next/Exit buttons.

Overrides :meth:DebuggerController.run_mpl_event_loop to reclaim the figure area those buttons would otherwise occupy. Keyboard shortcuts (left / right / escape) still drive navigation via the inherited :meth:DebuggerController.on_key dispatcher.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/visualize/entropy_tree/controller.py
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
def run_mpl_event_loop(self, ax, fig) -> None:  # type: ignore[override,no-untyped-def]
    """Slider-only event loop — no Prev/Next/Exit buttons.

    Overrides :meth:`DebuggerController.run_mpl_event_loop` to reclaim the
    figure area those buttons would otherwise occupy. Keyboard shortcuts
    (``left`` / ``right`` / ``escape``) still drive navigation via the
    inherited :meth:`DebuggerController.on_key` dispatcher.
    """
    _ = ax  # kept for base-class signature compatibility
    self.slider = None

    num_steps = getattr(self, "num_steps", 1)
    if num_steps > 1:
        slider_ax = fig.add_axes((0.1, 0.04, 0.8, 0.04))
        initial_step = max(0, min(self.step_index, num_steps - 1))
        self.slider = Slider(
            ax=slider_ax,
            label="Step",
            valmin=0,
            valmax=num_steps - 1,
            valinit=initial_step,
            valstep=1,
            valfmt="%d",
        )
        self.slider.on_changed(self.on_slider_change)

    fig.canvas.mpl_connect("key_press_event", self.on_key)
    self.reset()
    self.run()

    if isinstance(fig, figure.Figure):
        plt.close(fig)