using CairoMakie
CairoMakie.activate!()Interactive Dashboard with explore_potts
Writing code, re-running a simulation, and squinting at a static plot is a slow feedback loop for parameter tuning. explore_potts replaces this cycle with a live, reactive dashboard: adjust a slider, and the full simulation re-runs automatically while metric plots update in real time. This tutorial builds a cell-sorting model and walks through every feature of the dashboard.
Packages
using PottsToolkit
using MakiePotts
using StatisticsModel definition
Two cell populations (A and B) with differential adhesion. The sorting behaviour is exquisitely sensitive to temperature and the A–B adhesion energy — exactly the parameters we will expose as interactive sliders.
A = CellType(:A)
B = CellType(:B)
Medium = CellType(:Medium, is_background = true)
sys = PottsSystem(
cell_types = [Medium, A, B],
penalties = [
VolumeComponent(
A => (λ = 5.0f0, target = 500),
B => (λ = 5.0f0, target = 500)
),
AdhesionComponent(
(A, Medium) => 16.0f0,
(B, Medium) => 16.0f0,
(A, A) => 2.0f0,
(B, B) => 2.0f0,
(A, B) => 14.0f0 # heterotypic — start high for sorting
)
]
)
prob = PottsProblem(
sys,
Dict(A => 25, B => 25),
(200, 200);
tspan = (0, 600),
topology = VonNeumannTopology{2}()
)Metric definitions
A metric is a "Label" => function pair. The function receives the current integrator state u — a mutable struct with fields:
u.N_cells[]— current live cell count (RefValue)u.cell_data.volumes— GPU/CPU array of per-cell volumesu.cell_data.types— array of cell-type indicesu.grid— the 2-D lattice (CuArray or Array)
Metrics are plotted in a time-series panel beneath the lattice view.
metrics = [
"Mean Volume" => u -> begin
n = u.N_cells[]
n == 0 ? 0.0 : mean(Array(u.cell_data.volumes)[1:n])
end,
"N Cells" => u -> u.N_cells[],
"Sorting Index" => u -> begin
# Fraction of A-cell neighbours that are also A
lat = Array(u.grid)
types = Array(u.cell_data.cell_types)
n_same = 0;
n_total = 0
for I in CartesianIndices(lat)
id = lat[I]
id == 0 && continue
for dI in (CartesianIndex(1, 0), CartesianIndex(0, 1))
J = I + dI
checkbounds(Bool, lat, J) || continue
jd = lat[J]
jd == 0 && continue
n_total += 1
types[id] == types[jd] && (n_same += 1)
end
end
n_total == 0 ? 0.5 : n_same / n_total
end
]3-element Vector{Pair{String, Function}}:
"Mean Volume" => Main.var"#4#5"()
"N Cells" => Main.var"#6#7"()
"Sorting Index" => Main.var"#8#9"()Parameter definitions
A parameter is a "Label" => NamedTuple where:
range— the slider step range (must be a StepRange of the correct type)start— initial slider valueaction— a three-argument function(prob, alg, val) -> new_alg_or_probthat returns a new algorithm (or modified problem) for each slider position. The dashboard re-solves from scratch.
The adhesion J slider rebuilds the entire PottsSystem with the new J_AB value. This is intentional: the action closure has full Julia power available.
parameters = [
"Temperature" => (
range = 0.5f0:0.5f0:6.0f0,
start = 2.0f0,
action = (prob, alg, val) -> CheckerboardMetropolis(T = val, sweeps_per_step = 10)
),
"Adhesion J_AB" => (
range = 2.0f0:2.0f0:30.0f0,
start = 14.0f0,
action = (prob, alg, val) -> begin
# Rebuild the system with the new heterotypic adhesion energy
new_sys = PottsSystem(
cell_types = [Medium, A, B],
penalties = [
VolumeComponent(
A => (λ = 5.0f0, target = 500),
B => (λ = 5.0f0, target = 500)
),
AdhesionComponent(
(A, Medium) => 16.0f0,
(B, Medium) => 16.0f0,
(A, A) => 2.0f0,
(B, B) => 2.0f0,
(A, B) => val
)
]
)
# Return the same algorithm; the dashboard detects the system change
CheckerboardMetropolis(T = 2.0f0, sweeps_per_step = 10)
end
)
]2-element Vector{Pair{String, NamedTuple{(:range, :start, :action)}}}:
"Temperature" => (range = 0.5f0:0.5f0:6.0f0, start = 2.0f0, action = Main.var"#12#13"())
"Adhesion J_AB" => (range = 2.0f0:2.0f0:30.0f0, start = 14.0f0, action = Main.var"#14#15"())Dashboard layout
The explore_potts window is organised as follows:
┌─────────────────────────────────┐ │ Lattice (grid view) │ ├──────────────┬──────────────────┤ │ Mean Volume │ Sorting Index │ ← metric time-series ├──────────────┴──────────────────┤ │ Temperature [======●===] │ ← sliders │ Adhesion J [===●======] │ └─────────────────────────────────┘
Note: explore_potts uses MemoryBackend internally. Out-of-core backends (ZarrBackend, HDF5Backend) are not supported in interactive mode because the dashboard needs to replay saved frames in random order.
alg = CheckerboardMetropolis(T = 2.0f0, sweeps_per_step = 10)
fig = explore_potts(
prob, alg;
metrics = metrics,
parameters = parameters
)This page was generated using Literate.jl.