From f674ec4ab9248a27e7e1d4f8c3594d98f3a30d19 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Mon, 16 Jun 2025 19:44:39 +0200 Subject: [PATCH 01/11] trying to style that shit --- src/fhn_solver.jl | 20 +------------------- src/utils/templates.jl | 10 ++++++++-- src/visualization.jl | 40 ++++++++++++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/fhn_solver.jl b/src/fhn_solver.jl index 31dbc87..90a842f 100644 --- a/src/fhn_solver.jl +++ b/src/fhn_solver.jl @@ -24,7 +24,7 @@ using .Laplacian # Returns - `du`: calculated derivatives put back into the du array """ -function fhn!(du, u, p::FHNParams, t) +function fhn!(du, u, p::CombinedPDEParams, t) N = p.N u_mat = reshape(u[1:N^2], N, N) v_mat = reshape(u[N^2+1:end], N, N) @@ -48,7 +48,6 @@ function fhn!(du, u, p::FHNParams, t) end function step_fhn!(U, V, params_obs::Observable; dx=1) - """ p = params_obs[] # Flatten initial condition (activation u, recovery v) @@ -68,23 +67,6 @@ function step_fhn!(U, V, params_obs::Observable; dx=1) U .= u_new V .= v_new - return U - """ - - params = params_obs[] - - Δu = laplacian(U, params.dx) - Δv = laplacian(V, params.dx) - - u = U[2:end-1, 2:end-1] - v = V[2:end-1, 2:end-1] - - fu = params.Du .* Δu .+ u .- (u .^ 3) ./ 3 .- v - fv = params.Dv .* Δv .+ params.ϵ .* (u .+ params.a .- params.b .* v) - - U[2:end-1, 2:end-1] .+= 0.1 .* fu - V[2:end-1, 2:end-1] .+= 0.1 .* fv - return U end diff --git a/src/utils/templates.jl b/src/utils/templates.jl index 7298bf4..0e8f95b 100644 --- a/src/utils/templates.jl +++ b/src/utils/templates.jl @@ -1,4 +1,6 @@ +module Templates + # initial conditions for different patterns function zebra_conditions(N) # Turing-spot parameters @@ -61,7 +63,7 @@ function column_ic(N) u[col_start:col_end, :] .= -0.01 - return vec(u), vec(v) + return u, v end function two_rows_edge_distance_ic(N) @@ -194,5 +196,9 @@ function coral_ic(N) u[i-2:i+2, j-2:j+2] .= -0.534522 .+ 0.2 * rand(5, 5) end - return vec(u), vec(v) + return u, v end + +export blocks_ic, column_ic, squiggle_ic, three_circles_random_ic, circle_ic, center_band_ic, two_rows_edge_distance_ic + +end \ No newline at end of file diff --git a/src/visualization.jl b/src/visualization.jl index b4ded0a..0a34a3e 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -1,11 +1,13 @@ module Visualization -include("../src/utils/constants.jl") +include("utils/constants.jl") +include("utils/templates.jl") include("gray_scott_solver.jl") include("fhn_solver.jl") using Observables, Makie, GLMakie using .Constants +using .Templates using .GrayScottSolver: step_gray_scott! using .FHNSolver: step_fhn! @@ -68,7 +70,7 @@ end function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) reset!(U, V, heat_obs) - fig = Figure(size=(800, 800)) + fig = Figure(size=(1200, 800)) gh = GridLayout(fig[1, 1]) dropdown = Menu(fig, options=collect(zip(["Gray-Scott", "FHN"], [:gray_scott, :fhn]))) @@ -89,10 +91,15 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) btn_step = Button(buttongrid[1, 1], width=50, label="Step") btn_start = Button(buttongrid[1, 2], width=50, label=run_label) btn_reset = Button(buttongrid[1, 3], width=50, label="Reset") - slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:100, format="{}x", width=350, startvalue=stepsize[])) + slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:50, format="{}x", width=350, startvalue=stepsize[])) speed_slider = slidergrid.sliders[1].value + gh[1, 2] = templategrid = GridLayout(ax.scene, tellwidth=false) + btn_zebra = Button(templategrid[1, 1], width=100, label="Zebra Stripes") + btn_cheetah = Button(templategrid[1, 2], width=100, label="Cheetah Spots") + btn_coral = Button(templategrid[1, 3], width=100, label="Coral Pattern") + # place all the parameter boxes gh[2, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false) @@ -108,11 +115,12 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) param_box!(textboxgrid, 4, "a", param_obs_map.a, col=2) param_box!(textboxgrid, 5, "b", param_obs_map.b, col=2) - rowsize!(gh, 1, Fixed(50)) # small row for the menu + rowsize!(gh, 1, 50) # small row for the menu rowsize!(gh, 2, Relative(1.0)) for c in 1:4 - colsize!(textboxgrid, c, Relative(1.0 / 4.0)) + colsize!(textboxgrid, c, Relative(1.0 / 6.0)) end + #rowsize!(fig, 1, Relative(0.8)) # Events ############################################################## # Timer and state for animation @@ -129,7 +137,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) @warn "Invalid input for $s" end end - # Button Listeners + # Control Listeners on(btn_step.clicks) do _ multi_step!((U, V), stepsize[], heat_obs, params_obs; step_method=step_method[]) end @@ -150,6 +158,26 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) reset!(U, V, heat_obs) end + + # Template Control + on(btn_zebra.clicks) do _ + U, V = Templates.column_ic(params_obs[].N) + heat_obs[] = copy(U) + end + + # Template Control + on(btn_cheetah.clicks) do _ + U = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) # noise in [-0.05, 0.05] + V = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) + heat_obs[] = copy(U) + end + + # Template Control + on(btn_coral.clicks) do _ + U, V = Templates.coral_ic(params_obs[].N) + heat_obs[] = copy(U) + end + on(spoint) do pt r = 5 if pt === nothing From b189f1def7c57c5f98f0a17bc5217950d91da8d2 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Mon, 16 Jun 2025 21:13:31 +0200 Subject: [PATCH 02/11] Styled that shit --- src/visualization.jl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/visualization.jl b/src/visualization.jl index 0a34a3e..3deea86 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -70,7 +70,7 @@ end function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) reset!(U, V, heat_obs) - fig = Figure(size=(1200, 800)) + fig = Figure(size=(1200, 950)) gh = GridLayout(fig[1, 1]) dropdown = Menu(fig, options=collect(zip(["Gray-Scott", "FHN"], [:gray_scott, :fhn]))) @@ -91,7 +91,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) btn_step = Button(buttongrid[1, 1], width=50, label="Step") btn_start = Button(buttongrid[1, 2], width=50, label=run_label) btn_reset = Button(buttongrid[1, 3], width=50, label="Reset") - slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:50, format="{}x", width=350, startvalue=stepsize[])) + slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:50, format="{}x", width=750, startvalue=stepsize[], tellwidth=false)) speed_slider = slidergrid.sliders[1].value @@ -115,12 +115,11 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) param_box!(textboxgrid, 4, "a", param_obs_map.a, col=2) param_box!(textboxgrid, 5, "b", param_obs_map.b, col=2) - rowsize!(gh, 1, 50) # small row for the menu - rowsize!(gh, 2, Relative(1.0)) + rowsize!(gh, 1, Relative(0.2)) # small row for the menu + rowsize!(gh, 2, Relative(0.8)) for c in 1:4 - colsize!(textboxgrid, c, Relative(1.0 / 6.0)) + colsize!(textboxgrid, c, Relative(0.1)) end - #rowsize!(fig, 1, Relative(0.8)) # Events ############################################################## # Timer and state for animation From 5151adc995d67021d9e31161c593ca083b3763f5 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Mon, 16 Jun 2025 21:44:51 +0200 Subject: [PATCH 03/11] possible to change heatmap colors too --- src/visualization.jl | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/visualization.jl b/src/visualization.jl index 3f5b91d..5554233 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -163,20 +163,49 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) # Template Control on(btn_zebra.clicks) do _ + # add column to center of matrix U, V = Templates.column_ic(params_obs[].N) + + hm.colormap[] = :berlin + + # change params + param_obs_map.Du[] = 0.016 + param_obs_map.Dv[] = 0.1 + param_obs_map.ϵ[] = 0.1 + param_obs_map.a[] = 0.5 + param_obs_map.b[] = 0.9 heat_obs[] = copy(U) end # Template Control on(btn_cheetah.clicks) do _ + # fill matrix with random noise U = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) # noise in [-0.05, 0.05] V = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) + + hm.colormap[] = :magma + + # change params + param_obs_map.Du[] = 0.182 + param_obs_map.Dv[] = 0.5 + param_obs_map.ϵ[] = 0.05 + param_obs_map.a[] = 0.2 + param_obs_map.b[] = 2.0 heat_obs[] = copy(U) end # Template Control on(btn_coral.clicks) do _ U, V = Templates.coral_ic(params_obs[].N) + + hm.colormap[] = :plasma + + # change params + param_obs_map.Du[] = 0.001 + param_obs_map.Dv[] = 0.06 + param_obs_map.ϵ[] = 0.05 + param_obs_map.a[] = 0.0 + param_obs_map.b[] = 1.2 heat_obs[] = copy(U) end From a9d440973c738b85cf68b3b44ef8337359914287 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Mon, 16 Jun 2025 22:14:18 +0200 Subject: [PATCH 04/11] added captions --- src/visualization.jl | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/visualization.jl b/src/visualization.jl index 5554233..48b03b7 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -73,7 +73,7 @@ end function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) reset!(U, V, heat_obs) - fig = Figure(size=(1200, 950)) + fig = Figure(size=(1300, 950)) gh = GridLayout(fig[1, 1]) dropdown = Menu(fig, options=collect(zip(["Gray-Scott", "FHN"], [:gray_scott, :fhn]))) @@ -99,24 +99,30 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) speed_slider = slidergrid.sliders[1].value gh[1, 2] = templategrid = GridLayout(ax.scene, tellwidth=false) - btn_zebra = Button(templategrid[1, 1], width=100, label="Zebra Stripes") - btn_cheetah = Button(templategrid[1, 2], width=100, label="Cheetah Spots") - btn_coral = Button(templategrid[1, 3], width=100, label="Coral Pattern") + templategrid[1, 1] = Label(fig, "Templates:") + btn_zebra = Button(templategrid[1, 2], width=100, label="Zebra Stripes") + btn_cheetah = Button(templategrid[1, 3], width=100, label="Cheetah Spots") + btn_coral = Button(templategrid[1, 4], width=100, label="Coral Pattern") # place all the parameter boxes gh[2, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false) - param_box!(textboxgrid, 1, "Du", param_obs_map.Du, col=1) - param_box!(textboxgrid, 2, "Dv", param_obs_map.Dv, col=1) - param_box!(textboxgrid, 3, "Feed", param_obs_map.F, col=1) - param_box!(textboxgrid, 4, "Kill", param_obs_map.k, col=1) + # Create and assign column header labels + textboxgrid[1, 1] = Label(fig, "GrayScott:", halign=:center) + textboxgrid[1, 3] = Label(fig, "FHN:", halign=:center) + + # GrayScott column (col 1) + param_box!(textboxgrid, 2, "Du", param_obs_map.Du, col=1) + param_box!(textboxgrid, 3, "Dv", param_obs_map.Dv, col=1) + param_box!(textboxgrid, 4, "Feed", param_obs_map.F, col=1) + param_box!(textboxgrid, 5, "Kill", param_obs_map.k, col=1) # FHN column (col 2) - param_box!(textboxgrid, 1, "Du", param_obs_map.Du, col=2) - param_box!(textboxgrid, 2, "Dv", param_obs_map.Dv, col=2) - param_box!(textboxgrid, 3, "ϵ", param_obs_map.ϵ, col=2) - param_box!(textboxgrid, 4, "a", param_obs_map.a, col=2) - param_box!(textboxgrid, 5, "b", param_obs_map.b, col=2) + param_box!(textboxgrid, 2, "Du", param_obs_map.Du, col=2) + param_box!(textboxgrid, 3, "Dv", param_obs_map.Dv, col=2) + param_box!(textboxgrid, 4, "ϵ", param_obs_map.ϵ, col=2) + param_box!(textboxgrid, 5, "a", param_obs_map.a, col=2) + param_box!(textboxgrid, 6, "b", param_obs_map.b, col=2) rowsize!(gh, 1, Relative(0.2)) # small row for the menu rowsize!(gh, 2, Relative(0.8)) @@ -160,7 +166,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) reset!(U, V, heat_obs) end - + # Template Control on(btn_zebra.clicks) do _ # add column to center of matrix @@ -197,7 +203,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) # Template Control on(btn_coral.clicks) do _ U, V = Templates.coral_ic(params_obs[].N) - + hm.colormap[] = :plasma # change params From e14638689589ef3a16d7835c8911817fbe2d8193 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Mon, 16 Jun 2025 22:16:33 +0200 Subject: [PATCH 05/11] removed redundant code --- src/utils/templates.jl | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/utils/templates.jl b/src/utils/templates.jl index 0e8f95b..e4577c0 100644 --- a/src/utils/templates.jl +++ b/src/utils/templates.jl @@ -1,37 +1,6 @@ module Templates -# initial conditions for different patterns -function zebra_conditions(N) - # Turing-spot parameters - params = FHNParams(N=N, dx=1.0, Du=0.016, Dv=0.1, ϵ=0.1, a=0.5, b=0.9) - - # Or use this - u0, v0 = two_rows_edge_distance_ic(N) - - return params, vcat(u0, v0) -end - -function cheetah_conditions(N) - # Turing-spot parameters - #params = FHNParams(N=N, dx=1.0, Du=5e-6, Dv=2e-3, ϵ=0.025, a=0.6, b=0.15) - params = FHNParams(N=N, dx=1.0, Du=0.182, Dv=0.5, ϵ=0.05, a=0.2, b=2.0) - - u0 = 0.05 .* (2 .* rand(N, N) .- 1) # noise in [-0.05, 0.05] - v0 = 0.05 .* (2 .* rand(N, N) .- 1) - - return params, vcat(vec(u0), vec(v0)) -end - -function coral_conditions(N) - # Turing-spot parameters - params = FHNParams(N=N, dx=1.0, Du=0.001, Dv=0.06, ϵ=0.05, a=0.0, b=1.2) - - u0, v0 = coral_ic(N) - - return params, vcat(u0, v0) -end - # helper functions for filling cells in specific places of the matrix function blocks_ic(N) u = fill(1.0, N, N) From 9ead7760498d5d7693cb215abe3f8a6406564c4c Mon Sep 17 00:00:00 2001 From: Ruben-FreddyLoafers Date: Tue, 17 Jun 2025 13:58:08 +0200 Subject: [PATCH 06/11] last pattern wip --- src/fhn_solver.jl | 13 +++++++++- src/utils/laplacian.jl | 2 +- src/utils/templates.jl | 26 ++++++++++++++------ src/visualization.jl | 54 +++++++++++++++++++++++------------------- 4 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/fhn_solver.jl b/src/fhn_solver.jl index 90a842f..f22c072 100644 --- a/src/fhn_solver.jl +++ b/src/fhn_solver.jl @@ -57,7 +57,7 @@ function step_fhn!(U, V, params_obs::Observable; dx=1) # Define one integration step using your fhn! function prob = ODEProblem((du, u, p, t) -> fhn!(du, u, p, t), u_init, (0.0, 0.1), p) - sol = solve(prob, Tsit5(); dt=0.1, save_start=false, saveat=10.0) + sol = solve(prob, BS3(); save_start=false, saveat=10.0) # Extract solution and reshape u_new = reshape(sol[end][1:p.N^2], p.N, p.N) @@ -67,6 +67,17 @@ function step_fhn!(U, V, params_obs::Observable; dx=1) U .= u_new V .= v_new + # Apply periodic boundary conditions + U[1, :] .= U[end-1, :] + U[end, :] .= U[2, :] + U[:, 1] .= U[:, end-1] + U[:, end] .= U[:, 2] + + V[1, :] .= V[end-1, :] + V[end, :] .= V[2, :] + V[:, 1] .= V[:, end-1] + V[:, end] .= V[:, 2] + return U end diff --git a/src/utils/laplacian.jl b/src/utils/laplacian.jl index 814573a..ff74151 100644 --- a/src/utils/laplacian.jl +++ b/src/utils/laplacian.jl @@ -11,6 +11,6 @@ function laplacian(U::AbstractMatrix{<:Real}, dx::Real) return (up .+ down .+ left .+ right .- 4 .* center) ./ h2 end -export laplacian, laplacian5 +export laplacian end # module Laplacian diff --git a/src/utils/templates.jl b/src/utils/templates.jl index e4577c0..e328085 100644 --- a/src/utils/templates.jl +++ b/src/utils/templates.jl @@ -1,7 +1,8 @@ +# helper functions for filling cells in specific places of the matrix +# Not all functions are used. Those are for experimenting and debugging purposes module Templates -# helper functions for filling cells in specific places of the matrix function blocks_ic(N) u = fill(1.0, N, N) v = fill(0.0, N, N) @@ -9,9 +10,9 @@ function blocks_ic(N) function safe_block!(u, row_center, col_center) row_start = max(row_center - 8, 1) - row_end = min(row_center + 7, N) + row_end = min(row_center + 7, N) col_start = max(col_center - 8, 1) - col_end = min(col_center + 7, N) + col_end = min(col_center + 7, N) u[row_start:row_end, col_start:col_end] .= -0.01 end @@ -35,6 +36,17 @@ function column_ic(N) return u, v end +function stripe_ic(N) + u = zeros(N, N) + v = zeros(N, N) + for i in 1:N + for j in 1:N + u[i, j] = 0.1 + 0.05 * sin(2π * j / 10) + 0.01 * randn() + end + end + return u, v +end + function two_rows_edge_distance_ic(N) row_width = 8 distance_from_edge = 50 @@ -126,7 +138,7 @@ function three_circles_random_ic(N) end end - return vec(u), vec(v) + return u, v end function squiggle_ic(N, Lx=400.0, Ly=400.0) @@ -151,7 +163,7 @@ function squiggle_ic(N, Lx=400.0, Ly=400.0) v = fill(vplus, N, N) # Apply squiggle - u[Z .> 0.8] .= uminus + u[Z.>0.8] .= uminus return vec(u), vec(v) end @@ -160,7 +172,7 @@ function coral_ic(N) u = fill(0.534522, N, N) v = fill(0.381802, N, N) - for _ in 1:40 # place 15 noisy seeds + for _ in 1:20 # place 15 noisy seeds i, j = rand(10:N-10), rand(10:N-10) u[i-2:i+2, j-2:j+2] .= -0.534522 .+ 0.2 * rand(5, 5) end @@ -168,6 +180,6 @@ function coral_ic(N) return u, v end -export blocks_ic, column_ic, squiggle_ic, three_circles_random_ic, circle_ic, center_band_ic, two_rows_edge_distance_ic +export blocks_ic, column_ic, squiggle_ic, three_circles_random_ic, circle_ic, center_band_ic, two_rows_edge_distance_ic, coral_ic end \ No newline at end of file diff --git a/src/visualization.jl b/src/visualization.jl index 48b03b7..ad12daa 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -43,6 +43,7 @@ function reset!(U, V, heat_obs) radius = 10 U[center-radius:center+radius, center-radius:center+radius] .= 0.50 V[center-radius:center+radius, center-radius:center+radius] .= 0.25 + heat_obs[] = copy(U) end @@ -101,8 +102,9 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) gh[1, 2] = templategrid = GridLayout(ax.scene, tellwidth=false) templategrid[1, 1] = Label(fig, "Templates:") btn_zebra = Button(templategrid[1, 2], width=100, label="Zebra Stripes") - btn_cheetah = Button(templategrid[1, 3], width=100, label="Cheetah Spots") - btn_coral = Button(templategrid[1, 4], width=100, label="Coral Pattern") + btn_cow = Button(templategrid[1, 3], width=100, label="Cow Spots") + btn_cheetah = Button(templategrid[1, 4], width=100, label="Cheetah Spots") + #btn_coral = Button(templategrid[1, 4], width=100, label="Coral Pattern") # place all the parameter boxes gh[2, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false) @@ -130,7 +132,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) colsize!(textboxgrid, c, Relative(0.1)) end - # Events ############################################################## + # ======== Events ======== # Timer and state for animation running = Observable(false) @@ -163,6 +165,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) on(btn_reset.clicks) do _ running[] = false + hm.colormap[] = :viridis reset!(U, V, heat_obs) end @@ -172,24 +175,40 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) # add column to center of matrix U, V = Templates.column_ic(params_obs[].N) - hm.colormap[] = :berlin + hm.colormap[] = :grayC # change params - param_obs_map.Du[] = 0.016 - param_obs_map.Dv[] = 0.1 - param_obs_map.ϵ[] = 0.1 - param_obs_map.a[] = 0.5 - param_obs_map.b[] = 0.9 + param_obs_map.Du[] = 1.0 + param_obs_map.Dv[] = 2.0 + param_obs_map.ϵ[] = 0.3 + param_obs_map.a[] = 0.0 + param_obs_map.b[] = 1.4 heat_obs[] = copy(U) end # Template Control + on(btn_cow.clicks) do _ + # fill matrix with random noise + U = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) # noise in [-0.05, 0.05] + V = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) + + hm.colormap[] = :grayC + + # change params + param_obs_map.Du[] = 1.0 + param_obs_map.Dv[] = 10.0 + param_obs_map.ϵ[] = 0.01 + param_obs_map.a[] = -0.1 + param_obs_map.b[] = 1.2 + heat_obs[] = copy(U) + end + on(btn_cheetah.clicks) do _ # fill matrix with random noise U = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) # noise in [-0.05, 0.05] V = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) - hm.colormap[] = :magma + hm.colormap[] = cgrad(:lajolla, rev = true) # change params param_obs_map.Du[] = 0.182 @@ -200,21 +219,6 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) heat_obs[] = copy(U) end - # Template Control - on(btn_coral.clicks) do _ - U, V = Templates.coral_ic(params_obs[].N) - - hm.colormap[] = :plasma - - # change params - param_obs_map.Du[] = 0.001 - param_obs_map.Dv[] = 0.06 - param_obs_map.ϵ[] = 0.05 - param_obs_map.a[] = 0.0 - param_obs_map.b[] = 1.2 - heat_obs[] = copy(U) - end - on(spoint) do pt r = 5 if pt === nothing From 380d9aa228f7eb32d5bc54db84bf479fb072c209 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Tue, 17 Jun 2025 16:04:03 +0200 Subject: [PATCH 07/11] implemented basic wave pattern instead of animal pattern --- src/utils/templates.jl | 20 ++++++++++---------- src/visualization.jl | 19 +++++++++---------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/utils/templates.jl b/src/utils/templates.jl index e328085..bd7ce48 100644 --- a/src/utils/templates.jl +++ b/src/utils/templates.jl @@ -18,7 +18,7 @@ function blocks_ic(N) safe_block!(u, p, p) - return vec(u), vec(v) + return u, v end function column_ic(N) @@ -80,7 +80,7 @@ function two_rows_edge_distance_ic(N) # Apply the second column u[:, col2_start:col2_end] .= -0.01 - return vec(u), vec(v) + return u, v end function center_band_ic(N) @@ -94,7 +94,7 @@ function center_band_ic(N) u[row_start:row_end, :] .= 0.1 .+ 0.01 .* randn(band_width + 1, N) v[row_start:row_end, :] .= 0.1 .+ 0.01 .* randn(band_width + 1, N) - return vec(u), vec(v) + return u, v end function circle_ic(N) @@ -109,7 +109,7 @@ function circle_ic(N) end end - return vec(u), vec(v) + return u, v end function three_circles_random_ic(N) @@ -165,21 +165,21 @@ function squiggle_ic(N, Lx=400.0, Ly=400.0) # Apply squiggle u[Z.>0.8] .= uminus - return vec(u), vec(v) + return u, v end function coral_ic(N) - u = fill(0.534522, N, N) - v = fill(0.381802, N, N) + u = ones(N, N) + v = zeros(N, N) - for _ in 1:20 # place 15 noisy seeds - i, j = rand(10:N-10), rand(10:N-10) + for _ in 1:150 # place 15 noisy seeds + i, j = rand(5:N-5), rand(5:N-5) u[i-2:i+2, j-2:j+2] .= -0.534522 .+ 0.2 * rand(5, 5) end return u, v end -export blocks_ic, column_ic, squiggle_ic, three_circles_random_ic, circle_ic, center_band_ic, two_rows_edge_distance_ic, coral_ic +export blocks_ic, column_ic, squiggle_ic, three_circles_random_ic, circle_ic, center_band_ic, two_rows_edge_distance_ic, coral_ic, stripe_ic end \ No newline at end of file diff --git a/src/visualization.jl b/src/visualization.jl index ad12daa..be67517 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -101,10 +101,9 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) gh[1, 2] = templategrid = GridLayout(ax.scene, tellwidth=false) templategrid[1, 1] = Label(fig, "Templates:") - btn_zebra = Button(templategrid[1, 2], width=100, label="Zebra Stripes") + btn_waves = Button(templategrid[1, 2], width=100, label="Wave Pattern") btn_cow = Button(templategrid[1, 3], width=100, label="Cow Spots") btn_cheetah = Button(templategrid[1, 4], width=100, label="Cheetah Spots") - #btn_coral = Button(templategrid[1, 4], width=100, label="Coral Pattern") # place all the parameter boxes gh[2, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false) @@ -171,18 +170,18 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) end # Template Control - on(btn_zebra.clicks) do _ + on(btn_waves.clicks) do _ # add column to center of matrix - U, V = Templates.column_ic(params_obs[].N) + U, V = Templates.blocks_ic(params_obs[].N) - hm.colormap[] = :grayC + hm.colormap[] = :viridis # change params - param_obs_map.Du[] = 1.0 - param_obs_map.Dv[] = 2.0 - param_obs_map.ϵ[] = 0.3 - param_obs_map.a[] = 0.0 - param_obs_map.b[] = 1.4 + param_obs_map.Du[] = 0.0008 + param_obs_map.Dv[] = 0.1 + param_obs_map.ϵ[] = 0.01 + param_obs_map.a[] = 0.5 + param_obs_map.b[] = 0.15 heat_obs[] = copy(U) end From 53383487dcf1cb3f795c0d3d5c32485868d0bb28 Mon Sep 17 00:00:00 2001 From: Niki Laptop <2212719@stud.hs-mannheim.de> Date: Tue, 17 Jun 2025 17:49:33 +0200 Subject: [PATCH 08/11] add explicit fhn solving --- src/fhn_solver.jl | 100 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/src/fhn_solver.jl b/src/fhn_solver.jl index f22c072..2f8b7ec 100644 --- a/src/fhn_solver.jl +++ b/src/fhn_solver.jl @@ -24,48 +24,86 @@ using .Laplacian # Returns - `du`: calculated derivatives put back into the du array """ -function fhn!(du, u, p::CombinedPDEParams, t) - N = p.N - u_mat = reshape(u[1:N^2], N, N) - v_mat = reshape(u[N^2+1:end], N, N) +# function fhn!(du, u, p::CombinedPDEParams, t) +# N = p.N +# u_mat = reshape(u[1:N^2], N, N) +# v_mat = reshape(u[N^2+1:end], N, N) - Δu = laplacian(u_mat, p.dx) - Δv = laplacian(v_mat, p.dx) +# Δu = laplacian(u_mat, p.dx) +# Δv = laplacian(v_mat, p.dx) - u_in = u_mat[2:end-1, 2:end-1] - v_in = v_mat[2:end-1, 2:end-1] +# u_in = u_mat[2:end-1, 2:end-1] +# v_in = v_mat[2:end-1, 2:end-1] - fu = p.Du * Δu .+ u_in .- u_in .^ 3 ./ 3 .- v_in - fv = p.Dv * Δv .+ p.ϵ * (u_in .+ p.a .- p.b .* v_in) +# fu = p.Du * Δu .+ u_in .- u_in .^ 3 ./ 3 .- v_in +# fv = p.Dv * Δv .+ p.ϵ * (u_in .+ p.a .- p.b .* v_in) - # Construct output with zero boundary (padding) - fu_full = zeros(N, N) - fv_full = zeros(N, N) - fu_full[2:end-1, 2:end-1] .= fu - fv_full[2:end-1, 2:end-1] .= fv +# # Construct output with zero boundary (padding) +# fu_full = zeros(N, N) +# fv_full = zeros(N, N) +# fu_full[2:end-1, 2:end-1] .= fu +# fv_full[2:end-1, 2:end-1] .= fv - du .= vcat(vec(fu_full), vec(fv_full)) -end +# du .= vcat(vec(fu_full), vec(fv_full)) +# end -function step_fhn!(U, V, params_obs::Observable; dx=1) +# function step_fhn!(U, V, params_obs::Observable; dx=1) +# p = params_obs[] + +# # Flatten initial condition (activation u, recovery v) +# u0 = vec(U) +# v0 = vec(V) +# u_init = vcat(u0, v0) + +# # Define one integration step using your fhn! function +# prob = ODEProblem((du, u, p, t) -> fhn!(du, u, p, t), u_init, (0.0, 0.1), p) +# sol = solve(prob, BS3(); save_start=false, saveat=10.0) + +# # Extract solution and reshape +# u_new = reshape(sol[end][1:p.N^2], p.N, p.N) +# v_new = reshape(sol[end][p.N^2+1:end], p.N, p.N) + +# # Update matrices in-place +# U .= u_new +# V .= v_new + +# # Apply periodic boundary conditions +# U[1, :] .= U[end-1, :] +# U[end, :] .= U[2, :] +# U[:, 1] .= U[:, end-1] +# U[:, end] .= U[:, 2] + +# V[1, :] .= V[end-1, :] +# V[end, :] .= V[2, :] +# V[:, 1] .= V[:, end-1] +# V[:, end] .= V[:, 2] + +# return U +# end +function step_fhn!(U, V, params_obs::Observable; dx=1, dt=0.01) p = params_obs[] - # Flatten initial condition (activation u, recovery v) - u0 = vec(U) - v0 = vec(V) - u_init = vcat(u0, v0) + N = p.N - # Define one integration step using your fhn! function - prob = ODEProblem((du, u, p, t) -> fhn!(du, u, p, t), u_init, (0.0, 0.1), p) - sol = solve(prob, BS3(); save_start=false, saveat=10.0) + # Compute Laplacians on the interior + Δu = laplacian(U, dx) + Δv = laplacian(V, dx) - # Extract solution and reshape - u_new = reshape(sol[end][1:p.N^2], p.N, p.N) - v_new = reshape(sol[end][p.N^2+1:end], p.N, p.N) + # Extract interior + u_in = U[2:end-1, 2:end-1] + v_in = V[2:end-1, 2:end-1] - # Update matrices in-place - U .= u_new - V .= v_new + # Compute update using FHN reaction-diffusion terms + fu = p.Du .* Δu .+ u_in .- u_in .^ 3 ./ 3 .- v_in + fv = p.Dv .* Δv .+ p.ϵ .* (u_in .+ p.a .- p.b .* v_in) + + # Euler update + u_new = u_in .+ dt .* fu + v_new = v_in .+ dt .* fv + + # Write back interior updates + U[2:end-1, 2:end-1] .= u_new + V[2:end-1, 2:end-1] .= v_new # Apply periodic boundary conditions U[1, :] .= U[end-1, :] From a313cd7979b5a6e8d0f7cc03c4b82a19f60a5923 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Tue, 17 Jun 2025 18:21:08 +0200 Subject: [PATCH 09/11] removed unused function, adjusted color of btn_waves --- src/fhn_solver.jl | 71 -------------------------------------------- src/visualization.jl | 2 +- 2 files changed, 1 insertion(+), 72 deletions(-) diff --git a/src/fhn_solver.jl b/src/fhn_solver.jl index 2f8b7ec..c493932 100644 --- a/src/fhn_solver.jl +++ b/src/fhn_solver.jl @@ -9,77 +9,6 @@ using Observables using ..Constants using .Laplacian -""" - fhn(du, u, p:FHNParams, t:) - - Implements the spatial dynamics of FitzHugh-Nagumo (fhn). Designed to be - within a larger numerical solver of partial differential equations. - - # Arguments - - `du`: output argument which stores the calculated derivatives - - `u`: input vector containing the current state of the system at time t - - `p`: holds all the fixed parameters of the FHN model - - `t`: current time - - # Returns - - `du`: calculated derivatives put back into the du array -""" -# function fhn!(du, u, p::CombinedPDEParams, t) -# N = p.N -# u_mat = reshape(u[1:N^2], N, N) -# v_mat = reshape(u[N^2+1:end], N, N) - -# Δu = laplacian(u_mat, p.dx) -# Δv = laplacian(v_mat, p.dx) - -# u_in = u_mat[2:end-1, 2:end-1] -# v_in = v_mat[2:end-1, 2:end-1] - -# fu = p.Du * Δu .+ u_in .- u_in .^ 3 ./ 3 .- v_in -# fv = p.Dv * Δv .+ p.ϵ * (u_in .+ p.a .- p.b .* v_in) - -# # Construct output with zero boundary (padding) -# fu_full = zeros(N, N) -# fv_full = zeros(N, N) -# fu_full[2:end-1, 2:end-1] .= fu -# fv_full[2:end-1, 2:end-1] .= fv - -# du .= vcat(vec(fu_full), vec(fv_full)) -# end - -# function step_fhn!(U, V, params_obs::Observable; dx=1) -# p = params_obs[] - -# # Flatten initial condition (activation u, recovery v) -# u0 = vec(U) -# v0 = vec(V) -# u_init = vcat(u0, v0) - -# # Define one integration step using your fhn! function -# prob = ODEProblem((du, u, p, t) -> fhn!(du, u, p, t), u_init, (0.0, 0.1), p) -# sol = solve(prob, BS3(); save_start=false, saveat=10.0) - -# # Extract solution and reshape -# u_new = reshape(sol[end][1:p.N^2], p.N, p.N) -# v_new = reshape(sol[end][p.N^2+1:end], p.N, p.N) - -# # Update matrices in-place -# U .= u_new -# V .= v_new - -# # Apply periodic boundary conditions -# U[1, :] .= U[end-1, :] -# U[end, :] .= U[2, :] -# U[:, 1] .= U[:, end-1] -# U[:, end] .= U[:, 2] - -# V[1, :] .= V[end-1, :] -# V[end, :] .= V[2, :] -# V[:, 1] .= V[:, end-1] -# V[:, end] .= V[:, 2] - -# return U -# end function step_fhn!(U, V, params_obs::Observable; dx=1, dt=0.01) p = params_obs[] diff --git a/src/visualization.jl b/src/visualization.jl index 5234d5a..adeb0cd 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -174,7 +174,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) # add column to center of matrix U, V = Templates.blocks_ic(params_obs[].N) - hm.colormap[] = :viridis + hm.colormap[] = :seismic # change params param_obs_map.Du[] = 0.0008 From 1918c337702a549449c6504f0403dbe2459e4ab1 Mon Sep 17 00:00:00 2001 From: 2211567 Date: Tue, 17 Jun 2025 18:21:32 +0200 Subject: [PATCH 10/11] removed unused function, adjusted color of btn_waves --- src/visualization.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/visualization.jl b/src/visualization.jl index adeb0cd..0b4f169 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -164,7 +164,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) on(btn_reset.clicks) do _ running[] = false - hm.colormap[] = :viridis + hm.colormap[] = :seismic reset!(U, V, heat_obs) end From b129d9cec4465b0b81e503bf1924e9b1d1f9f8cc Mon Sep 17 00:00:00 2001 From: Niki Laptop <2212719@stud.hs-mannheim.de> Date: Tue, 17 Jun 2025 19:28:06 +0200 Subject: [PATCH 11/11] add scalar to single step button --- src/visualization.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/visualization.jl b/src/visualization.jl index 5234d5a..6212d9a 100644 --- a/src/visualization.jl +++ b/src/visualization.jl @@ -148,7 +148,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) end # Control Listeners on(btn_step.clicks) do _ - multi_step!((U, V), stepsize[], heat_obs, params_obs; step_method=step_method[]) + multi_step!((U, V), stepsize[] * 5, heat_obs, params_obs; step_method=step_method[]) end on(btn_start.clicks) do _ @@ -157,7 +157,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) on(btn_start.clicks) do _ @async while running[] - multi_step!((U, V), stepsize[] * 5, heat_obs, params_obs; step_method=step_method[]) + multi_step!((U, V), stepsize[], heat_obs, params_obs; step_method=step_method[]) sleep(0.0015) # ~20 FPS end end @@ -207,7 +207,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs) U = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) # noise in [-0.05, 0.05] V = 0.05 .* (2 .* rand(params_obs[].N, params_obs[].N) .- 1) - hm.colormap[] = cgrad(:lajolla, rev = true) + hm.colormap[] = cgrad(:lajolla, rev=true) # change params param_obs_map.Du[] = 0.182