Commit 2726d1dc by PLN (Algolia)

midiviz: the column glow lives 30% longer than the cells

parent b227c7aa
...@@ -426,6 +426,10 @@ THEME_MENU: dict[str, str] = { ...@@ -426,6 +426,10 @@ THEME_MENU: dict[str, str] = {
} }
TAU = 0.85 # seconds; brightness e-folding time TAU = 0.85 # seconds; brightness e-folding time
# PLN, 2026-09-24: the column glow dies noticeably faster than the cells do —
# at 0.85 s it is gone while the last-moved cell is still lit. The column is
# the "this orbit is live" signal, so it keeps its own, 30 % slower curve.
TAU_COL = TAU * 1.3
IDLE_AFTER = 2.0 # seconds of silence before the slow pulse IDLE_AFTER = 2.0 # seconds of silence before the slow pulse
# 40 ms = 25 fps. Profiling a frame (see MAX_DROPS) put the cost squarely in the # 40 ms = 25 fps. Profiling a frame (see MAX_DROPS) put the cost squarely in the
# number of drawText calls, and at this size 25 fps is indistinguishable from 33 # number of drawText calls, and at this size 25 fps is indistinguishable from 33
...@@ -1676,11 +1680,12 @@ def build_widget(port_label: str, reader: "Reader | None", scale: float = 1.0, ...@@ -1676,11 +1680,12 @@ def build_widget(port_label: str, reader: "Reader | None", scale: float = 1.0,
if max(frame) > 0.04: if max(frame) > 0.04:
self._spec_hot_t = now self._spec_hot_t = now
def _lv(self, age: float, floor: int = 0) -> int: def _lv(self, age: float, floor: int = 0, tau: float = TAU) -> int:
"""Age in seconds → LUT level. The only decay curve in the file.""" """Age in seconds → LUT level. The only decay shape in the file;
the time constant is a parameter so the column can outlive the cells."""
if age < 0: if age < 0:
return LEVELS - 1 return LEVELS - 1
lv = int((LEVELS - 1) * math.exp(-age / TAU)) lv = int((LEVELS - 1) * math.exp(-age / tau))
return max(floor, min(LEVELS - 1, lv)) return max(floor, min(LEVELS - 1, lv))
# ── paint ────────────────────────────────────────────────────────── # ── paint ──────────────────────────────────────────────────────────
...@@ -1880,7 +1885,7 @@ def build_widget(port_label: str, reader: "Reader | None", scale: float = 1.0, ...@@ -1880,7 +1885,7 @@ def build_widget(port_label: str, reader: "Reader | None", scale: float = 1.0,
for col in range(1, 9): for col in range(1, 9):
if not self.col_t[col]: if not self.col_t[col]:
continue continue
lv = self._lv(now - self.col_t[col]) lv = self._lv(now - self.col_t[col], tau=TAU_COL)
if lv > 1: if lv > 1:
# A SURFACE, not ink: this is the slab a live column stands # A SURFACE, not ink: this is the slab a live column stands
# on. Sampled from the ink ramp it would paint a dark bar # on. Sampled from the ink ramp it would paint a dark bar
...@@ -1893,7 +1898,8 @@ def build_widget(port_label: str, reader: "Reader | None", scale: float = 1.0, ...@@ -1893,7 +1898,8 @@ def build_widget(port_label: str, reader: "Reader | None", scale: float = 1.0,
# column digits = orbit numbers, brightening with that orbit's activity # column digits = orbit numbers, brightening with that orbit's activity
col_base = self.col_y + self.u_asc col_base = self.col_y + self.u_asc
for col in range(1, 9): for col in range(1, 9):
lv = self._lv(now - self.col_t[col], floor=4) if self.col_t[col] \ lv = self._lv(now - self.col_t[col], floor=4, tau=TAU_COL) \
if self.col_t[col] \
else 4 + int(2 * pulse) else 4 + int(2 * pulse)
p.setPen(self.lut[FAM_LEVEL][min(LEVELS - 1, lv)]) p.setPen(self.lut[FAM_LEVEL][min(LEVELS - 1, lv)])
p.drawText(round(mx + (col - 1) * cw + (cw - self.uw) / 2), p.drawText(round(mx + (col - 1) * cw + (cw - self.uw) / 2),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment