mirror of
https://gitlab.rlp.net/mobitar/ReCo.jl.git
synced 2024-12-21 00:51:21 +00:00
Snapshot graphic with CairoMakie
This commit is contained in:
parent
4e054653f5
commit
70abd1d4c7
6 changed files with 171 additions and 74 deletions
|
@ -48,7 +48,7 @@ end
|
||||||
function radial_distribution(;
|
function radial_distribution(;
|
||||||
sim_dirs::Vector{String}, n_radii::Int64, n_last_snapshots::Int64, n_particles::Int64
|
sim_dirs::Vector{String}, n_radii::Int64, n_last_snapshots::Int64, n_particles::Int64
|
||||||
)
|
)
|
||||||
sim_consts::ReCo.SimConsts = JLD2.load_object("$(sim_dirs[1])/sim_consts.jld2")
|
sim_consts = ReCo.load_sim_consts(sim_dirs[1])
|
||||||
|
|
||||||
particle_radius = sim_consts.particle_radius
|
particle_radius = sim_consts.particle_radius
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ function init_cairomakie!()
|
||||||
return nothing
|
return nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
function gen_figure(; padding=4)
|
function gen_figure(; padding=5)
|
||||||
text_width_in_pt = 405
|
text_width_in_pt = 405
|
||||||
|
|
||||||
return Figure(;
|
return Figure(;
|
||||||
|
@ -22,8 +22,10 @@ function set_gaps!(fig::Figure)
|
||||||
return nothing
|
return nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
function save_fig(filename::String, fig::Figure, parent_dir="exports/graphics")
|
function save_fig(filename::String, fig::Figure; parent_dir="exports/graphics")
|
||||||
mkpath(parent_dir)
|
mkpath(parent_dir)
|
||||||
|
|
||||||
return save("$parent_dir/$filename", fig; pt_per_unit=1)
|
save("$parent_dir/$filename", fig; pt_per_unit=1)
|
||||||
|
|
||||||
|
return nothing
|
||||||
end
|
end
|
196
src/Animation.jl
196
src/Animation.jl
|
@ -1,47 +1,60 @@
|
||||||
module Animation
|
module Animation
|
||||||
|
|
||||||
export animate
|
export animate_with_gl, animate_with_cairo
|
||||||
|
|
||||||
|
using CairoMakie
|
||||||
using GLMakie
|
using GLMakie
|
||||||
using ColorSchemes: cyclic_mrybm_35_75_c68_n256_s25
|
using ColorSchemes: ColorSchemes
|
||||||
using LaTeXStrings: @L_str
|
using LaTeXStrings: @L_str
|
||||||
using JLD2: JLD2
|
using JLD2: JLD2
|
||||||
using ProgressMeter: ProgressMeter
|
using ProgressMeter: ProgressMeter
|
||||||
|
|
||||||
using ..ReCo: ReCo
|
using ..ReCo: ReCo
|
||||||
|
|
||||||
|
include("../graphics/common_CairoMakie.jl")
|
||||||
|
|
||||||
|
const DEFAULT_CENTER_OF_MASS_CIRCLE_COLOR = RGBAf(1, 1, 1, 0.5)
|
||||||
|
|
||||||
|
function angle_color(φ::Float64, color_scheme::ColorSchemes.ColorScheme)
|
||||||
|
return get(color_scheme, rem2pi(φ, RoundDown) / (2 * π))
|
||||||
|
end
|
||||||
|
|
||||||
function animate_bundle!(args, sim_consts::ReCo.SimConsts)
|
function animate_bundle!(args, sim_consts::ReCo.SimConsts)
|
||||||
bundle_t = args.bundle.t
|
bundle_t = args.bundle.t
|
||||||
bundle_c = args.bundle.c
|
bundle_c = args.bundle.c
|
||||||
bundle_φ = args.bundle.φ
|
bundle_φ = args.bundle.φ
|
||||||
|
|
||||||
π2 = 2 * π
|
for snapshot in 1:length(bundle_t)
|
||||||
|
@simd for particle_ind in 1:(sim_consts.n_particles)
|
||||||
|
c = bundle_c[particle_ind, snapshot]
|
||||||
|
φ = bundle_φ[particle_ind, snapshot]
|
||||||
|
|
||||||
for frame in 1:length(bundle_t)
|
args.circles[][particle_ind] = Circle(
|
||||||
@simd for i in 1:(sim_consts.n_particles)
|
Point2(c[1], c[2]), sim_consts.particle_radius
|
||||||
c = bundle_c[i, frame]
|
)
|
||||||
args.circles[][i] = Circle(Point2(c[1], c[2]), sim_consts.particle_radius)
|
|
||||||
|
|
||||||
color = get(args.color_scheme, rem2pi(bundle_φ[i, frame], RoundDown) / π2)
|
color = angle_color(φ, args.color_scheme)
|
||||||
args.colors[][i] = RGBAf(color)
|
args.colors[][particle_ind] = RGBAf(color)
|
||||||
|
|
||||||
if args.show_interaction_circle
|
if args.show_interaction_circle
|
||||||
args.interaction_circles[][i] = Circle(
|
args.interaction_circles[][particle_ind] = Circle(
|
||||||
Point2(c[1], c[2]), sim_consts.interaction_r
|
Point2(c[1], c[2]), sim_consts.interaction_r
|
||||||
)
|
)
|
||||||
args.interaction_colors[][i] = RGBAf(color, 0.08)
|
args.interaction_colors[][particle_ind] = RGBAf(color, 0.08)
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.show_skin_circle
|
if args.show_skin_circle
|
||||||
args.skin_circles[][i] = Circle(Point2(c[1], c[2]), sim_consts.skin_r)
|
args.skin_circles[][particle_ind] = Circle(
|
||||||
|
Point2(c[1], c[2]), sim_consts.skin_r
|
||||||
|
)
|
||||||
|
|
||||||
args.skin_colors[][i] = RGBAf(color, 0.04)
|
args.skin_colors[][particle_ind] = RGBAf(color, 0.04)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.show_center_of_mass
|
if args.show_center_of_mass
|
||||||
center_of_mass = ReCo.center_of_mass(
|
center_of_mass = ReCo.center_of_mass(
|
||||||
view(bundle_c, :, frame), sim_consts.half_box_len
|
view(bundle_c, :, snapshot), sim_consts.half_box_len
|
||||||
)
|
)
|
||||||
args.center_of_mass_circle[] = Circle(
|
args.center_of_mass_circle[] = Circle(
|
||||||
Point2(center_of_mass[1], center_of_mass[2]),
|
Point2(center_of_mass[1], center_of_mass[2]),
|
||||||
|
@ -49,11 +62,15 @@ function animate_bundle!(args, sim_consts::ReCo.SimConsts)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.n_bundle == 1 # First and only frame of first bundle
|
if args.n_bundle == 1 && snapshot == 1
|
||||||
poly!(args.ax, args.circles; color=args.colors)
|
poly!(args.ax, args.circles; color=args.colors)
|
||||||
|
|
||||||
if args.show_center_of_mass
|
if args.show_center_of_mass
|
||||||
poly!(args.ax, args.center_of_mass_circle; color=RGBAf(1, 1, 1, 0.5))
|
poly!(
|
||||||
|
args.ax,
|
||||||
|
args.center_of_mass_circle;
|
||||||
|
color=DEFAULT_CENTER_OF_MASS_CIRCLE_COLOR,
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.show_interaction_circle
|
if args.show_interaction_circle
|
||||||
|
@ -66,20 +83,20 @@ function animate_bundle!(args, sim_consts::ReCo.SimConsts)
|
||||||
|
|
||||||
println("Recording started!")
|
println("Recording started!")
|
||||||
else
|
else
|
||||||
if args.show_frame_diff && frame > 1
|
if args.show_frame_diff && snapshot > 1
|
||||||
@simd for i in 1:(sim_consts.n_particles)
|
@simd for i in 1:(sim_consts.n_particles)
|
||||||
first_ind = 2 * i - 1
|
first_ind = 2 * i - 1
|
||||||
second_ind = 2 * i
|
second_ind = 2 * i
|
||||||
frame_min_1 = frame - 1
|
frame_min_1 = snapshot - 1
|
||||||
|
|
||||||
args.segments_x[][first_ind] = bundle_c[i, frame_min_1][1]
|
args.segments_x[][first_ind] = bundle_c[i, frame_min_1][1]
|
||||||
args.segments_x[][second_ind] = bundle_c[i, frame][1]
|
args.segments_x[][second_ind] = bundle_c[i, snapshot][1]
|
||||||
|
|
||||||
args.segments_y[][first_ind] = bundle_c[i, frame_min_1][2]
|
args.segments_y[][first_ind] = bundle_c[i, frame_min_1][2]
|
||||||
args.segments_y[][second_ind] = bundle_c[i, frame][2]
|
args.segments_y[][second_ind] = bundle_c[i, snapshot][2]
|
||||||
end
|
end
|
||||||
|
|
||||||
if frame == 2
|
if snapshot == 2
|
||||||
linesegments!(
|
linesegments!(
|
||||||
args.ax, args.segments_x, args.segments_y; color=args.colors
|
args.ax, args.segments_x, args.segments_y; color=args.colors
|
||||||
)
|
)
|
||||||
|
@ -107,7 +124,7 @@ function animate_bundle!(args, sim_consts::ReCo.SimConsts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
args.ax.title = "t = $(round(bundle_t[frame], digits=3))"
|
args.ax.title = "t = $(round(bundle_t[snapshot], digits=3))"
|
||||||
|
|
||||||
recordframe!(args.io)
|
recordframe!(args.io)
|
||||||
end
|
end
|
||||||
|
@ -115,20 +132,7 @@ function animate_bundle!(args, sim_consts::ReCo.SimConsts)
|
||||||
return nothing
|
return nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
function animate_with_sim_consts(
|
function gen_axis_and_colorbar(fig, sim_consts::ReCo.SimConsts)
|
||||||
dir::String,
|
|
||||||
sim_consts::ReCo.SimConsts,
|
|
||||||
framerate::Int64,
|
|
||||||
show_center_of_mass::Bool,
|
|
||||||
show_interaction_circle::Bool,
|
|
||||||
show_skin_circle::Bool,
|
|
||||||
show_frame_diff::Bool,
|
|
||||||
show_progress::Bool,
|
|
||||||
)
|
|
||||||
GLMakie.activate!()
|
|
||||||
set_theme!(theme_black())
|
|
||||||
|
|
||||||
fig = Figure(; resolution=(1080, 1080))
|
|
||||||
ax = Axis(
|
ax = Axis(
|
||||||
fig[1, 1];
|
fig[1, 1];
|
||||||
limits=(
|
limits=(
|
||||||
|
@ -142,13 +146,36 @@ function animate_with_sim_consts(
|
||||||
ylabel=L"y",
|
ylabel=L"y",
|
||||||
)
|
)
|
||||||
|
|
||||||
color_scheme = cyclic_mrybm_35_75_c68_n256_s25
|
color_scheme = ColorSchemes.cyclic_mrybm_35_75_c68_n256_s25
|
||||||
|
|
||||||
Colorbar(fig[1, 2]; limits=(0, 2), colormap=color_scheme, label=L"\frac{\varphi}{\pi}")
|
Colorbar(fig[1, 2]; limits=(0, 2), colormap=color_scheme, label=L"\varphi / \pi")
|
||||||
|
|
||||||
|
return (ax, color_scheme)
|
||||||
|
end
|
||||||
|
|
||||||
|
function animate_with_gl(
|
||||||
|
sim_dir::String;
|
||||||
|
framerate::Int64=1,
|
||||||
|
show_center_of_mass::Bool=false,
|
||||||
|
show_interaction_circle::Bool=false,
|
||||||
|
show_skin_circle::Bool=false,
|
||||||
|
show_frame_diff::Bool=false,
|
||||||
|
show_progress::Bool=true,
|
||||||
|
)
|
||||||
|
println("Generating animation...")
|
||||||
|
|
||||||
|
GLMakie.activate!()
|
||||||
|
set_theme!(theme_black())
|
||||||
|
|
||||||
|
fig = Figure(; resolution=(1080, 1080))
|
||||||
|
|
||||||
|
sim_consts = ReCo.load_sim_consts(sim_dir)
|
||||||
|
|
||||||
|
ax, color_scheme = gen_axis_and_colorbar(fig, sim_consts)
|
||||||
|
|
||||||
n_particles = sim_consts.n_particles
|
n_particles = sim_consts.n_particles
|
||||||
|
|
||||||
animation_path = "$dir/animation.mkv"
|
animation_path = "$sim_dir/animation.mkv"
|
||||||
|
|
||||||
record(fig, animation_path; framerate=framerate) do io
|
record(fig, animation_path; framerate=framerate) do io
|
||||||
circles = Observable(Vector{Circle}(undef, n_particles))
|
circles = Observable(Vector{Circle}(undef, n_particles))
|
||||||
|
@ -183,7 +210,7 @@ function animate_with_sim_consts(
|
||||||
segments_y = Observable(zeros(2 * n_particles))
|
segments_y = Observable(zeros(2 * n_particles))
|
||||||
end
|
end
|
||||||
|
|
||||||
bundle_paths = ReCo.sorted_bundle_paths(dir)
|
bundle_paths = ReCo.sorted_bundle_paths(sim_dir)
|
||||||
|
|
||||||
progress = ProgressMeter.Progress(
|
progress = ProgressMeter.Progress(
|
||||||
length(bundle_paths); dt=2, enabled=show_progress, desc="Animation: "
|
length(bundle_paths); dt=2, enabled=show_progress, desc="Animation: "
|
||||||
|
@ -222,36 +249,71 @@ function animate_with_sim_consts(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
function animate(
|
|
||||||
dir::String;
|
|
||||||
framerate::Int64=1,
|
|
||||||
show_center_of_mass::Bool=false,
|
|
||||||
show_interaction_circle::Bool=false,
|
|
||||||
show_skin_circle::Bool=false,
|
|
||||||
show_frame_diff::Bool=false,
|
|
||||||
show_progress::Bool=true,
|
|
||||||
)
|
|
||||||
println("Generating animation...")
|
|
||||||
|
|
||||||
sim_consts::ReCo.SimConsts = JLD2.load_object("$dir/sim_consts.jld2")
|
|
||||||
|
|
||||||
animate_with_sim_consts(
|
|
||||||
dir,
|
|
||||||
sim_consts,
|
|
||||||
framerate,
|
|
||||||
show_center_of_mass,
|
|
||||||
show_interaction_circle,
|
|
||||||
show_skin_circle,
|
|
||||||
show_frame_diff,
|
|
||||||
show_progress,
|
|
||||||
)
|
|
||||||
|
|
||||||
println("Animation done.")
|
println("Animation done.")
|
||||||
|
|
||||||
return nothing
|
return nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function get_wanted_snapshot_number(n_snapshots::Int64)
|
||||||
|
print("There are $n_snapshots snapshots. Enter the wanted snapshot number: ")
|
||||||
|
answer = readline()
|
||||||
|
|
||||||
|
snapshot = parse(Int64, answer)
|
||||||
|
|
||||||
|
@assert 0 < snapshot <= n_snapshots
|
||||||
|
|
||||||
|
return snapshot
|
||||||
|
end
|
||||||
|
|
||||||
|
function animate_with_cairo(sim_dir::String; show_center_of_mass::Bool=false)
|
||||||
|
bundles_info = ReCo.BundlesInfo(sim_dir)
|
||||||
|
snapshot = get_wanted_snapshot_number(bundles_info.total_n_snapshots)
|
||||||
|
|
||||||
|
bundle_path = ""
|
||||||
|
snapshot_counter = 1
|
||||||
|
|
||||||
|
for bundle_ind in bundles_info.n_bundles
|
||||||
|
snapshot_counter += bundles_info.bundle_n_snapshots[bundle_ind]
|
||||||
|
if snapshot_counter >= snapshot
|
||||||
|
bundle_path = bundles_info.sorted_bundle_paths[bundle_ind]
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
bundle::ReCo.Bundle = JLD2.load_object(bundle_path)
|
||||||
|
sim_consts = ReCo.load_sim_consts(sim_dir)
|
||||||
|
|
||||||
|
println("Initializing")
|
||||||
|
|
||||||
|
init_cairomakie!()
|
||||||
|
fig = gen_figure()
|
||||||
|
|
||||||
|
ax, color_scheme = gen_axis_and_colorbar(fig, sim_consts)
|
||||||
|
|
||||||
|
@simd for particle_ind in 1:(sim_consts.n_particles)
|
||||||
|
c = bundle.c[particle_ind, snapshot]
|
||||||
|
φ = bundle.φ[particle_ind, snapshot]
|
||||||
|
|
||||||
|
color = angle_color(φ, color_scheme)
|
||||||
|
|
||||||
|
poly!(ax, Circle(Point2(c[1], c[2]), sim_consts.particle_radius); color=color)
|
||||||
|
end
|
||||||
|
|
||||||
|
if show_center_of_mass
|
||||||
|
center_of_mass = ReCo.center_of_mass(
|
||||||
|
view(bundle.c, :, snapshot), sim_consts.half_box_len
|
||||||
|
)
|
||||||
|
circle = Circle(
|
||||||
|
Point2(center_of_mass[1], center_of_mass[2]), 3 * sim_consts.particle_radius
|
||||||
|
)
|
||||||
|
poly!(ax, circle; color=DEFAULT_CENTER_OF_MASS_CIRCLE_COLOR)
|
||||||
|
end
|
||||||
|
|
||||||
|
set_gaps!(fig)
|
||||||
|
|
||||||
|
save_fig("$snapshot.pdf", fig; parent_dir="$sim_dir/graphics")
|
||||||
|
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
|
||||||
end # module
|
end # module
|
|
@ -1,6 +1,6 @@
|
||||||
module ReCo
|
module ReCo
|
||||||
|
|
||||||
export init_sim, run_sim, run_rl, animate, LocalCOMEnv
|
export init_sim, run_sim, run_rl, animate_with_gl, animate_with_cairo, LocalCOMEnv
|
||||||
|
|
||||||
using StaticArrays: SVector
|
using StaticArrays: SVector
|
||||||
using JLD2: JLD2
|
using JLD2: JLD2
|
||||||
|
|
35
src/data.jl
35
src/data.jl
|
@ -114,7 +114,7 @@ function append_bundle_properties!(
|
||||||
bundle_paths = ReCo.sorted_bundle_paths(sim_dir)
|
bundle_paths = ReCo.sorted_bundle_paths(sim_dir)
|
||||||
|
|
||||||
for bundle_ind in first_bundle:length(bundle_paths)
|
for bundle_ind in first_bundle:length(bundle_paths)
|
||||||
bundle::ReCo.Bundle = JLD2.load_object(bundle_paths[bundle_ind])
|
bundle::Bundle = JLD2.load_object(bundle_paths[bundle_ind])
|
||||||
|
|
||||||
for (v_ind, v) in enumerat(vs)
|
for (v_ind, v) in enumerat(vs)
|
||||||
property = properties[v_ind]
|
property = properties[v_ind]
|
||||||
|
@ -132,3 +132,36 @@ function append_bundle_properties!(
|
||||||
|
|
||||||
return nothing
|
return nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
|
struct BundlesInfo
|
||||||
|
n_bundles::Int64
|
||||||
|
total_n_snapshots::Int64
|
||||||
|
bundle_n_snapshots::Vector{Int64}
|
||||||
|
sorted_bundle_paths::Vector{String}
|
||||||
|
end
|
||||||
|
|
||||||
|
function BundlesInfo(sim_dir::String)
|
||||||
|
bundle_paths = sorted_bundle_paths(sim_dir)
|
||||||
|
|
||||||
|
bundle_n_snapshots = Vector{Int64}(undef, length(bundle_paths))
|
||||||
|
|
||||||
|
n_bundles = length(bundle_paths)
|
||||||
|
|
||||||
|
total_n_snapshots = 0
|
||||||
|
|
||||||
|
for bundle_ind in 1:n_bundles
|
||||||
|
bundle_path = bundle_paths[bundle_ind]
|
||||||
|
bundle::Bundle = JLD2.load_object(bundle_path)
|
||||||
|
|
||||||
|
total_n_snapshots += bundle.n_snapshots
|
||||||
|
bundle_n_snapshots[bundle_ind] = bundle.n_snapshots
|
||||||
|
end
|
||||||
|
|
||||||
|
return BundlesInfo(n_bundles, total_n_snapshots, bundle_n_snapshots, bundle_paths)
|
||||||
|
end
|
||||||
|
|
||||||
|
function load_sim_consts(dir::String)
|
||||||
|
sim_consts::ReCo.SimConsts = JLD2.load_object("$dir/sim_consts.jld2")
|
||||||
|
|
||||||
|
return sim_consts
|
||||||
|
end
|
|
@ -23,7 +23,7 @@ function run_sim(
|
||||||
|
|
||||||
Random.seed!(seed)
|
Random.seed!(seed)
|
||||||
|
|
||||||
sim_consts::SimConsts = JLD2.load_object("$dir/sim_consts.jld2")
|
sim_consts = load_sim_consts(dir)
|
||||||
|
|
||||||
integration_steps = floor(Int64, duration / sim_consts.δt) + 1
|
integration_steps = floor(Int64, duration / sim_consts.δt) + 1
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue