如何沿X轴随滑块移动Topoplot并添加连接线?
解决Makie交互式绘图的两个需求
以下是针对你的两个需求的修改方案和完整代码:
需求1:让Topoplot随滑块沿X轴移动并可部分超出屏幕
核心思路是将Topoplot的中心X坐标与滑块的time变量绑定,同时关闭轴的内容裁剪,允许Topoplot超出屏幕边界。
需求2:添加连接Topoplot与红色竖线的线条
通过将轴坐标转换为屏幕坐标,在Figure的全局场景中绘制跨轴连接线,确保线条始终跟随两者位置变化。
修改后的完整代码
using Makie using GLMakie using PyMNE using JLD2 # loading data using TopoPlots using StatsBase # mean/std using Pipe using ColorSchemes using Colors using LinearAlgebra function eegHeadMatrix(positions, center, radius) oldCenter = mean(positions) oldRadius, _ = findmax(x-> LinearAlgebra.norm(x .- oldCenter), positions) radF = radius/oldRadius return Makie.Mat4f(radF, 0, 0, 0, 0, radF, 0, 0, 0, 0, 1, 0, center[1]-oldCenter[1]*radF, center[2]-oldCenter[2]*radF, 0, 1) end struct NullInterpolator <: TopoPlots.Interpolator end function (ni::NullInterpolator)( xrange::LinRange, yrange::LinRange, positions::AbstractVector{<: Point{2}}, data::AbstractVector{<:Number}) return zeros(length(xrange),length(yrange)) end function posToColor(pos) cx = 0.5 - pos[1] cy = 0.5 - pos[2] rx = cx * 0.7071068 + cy * 0.7071068 ry = cx * -0.7071068 + cy * 0.7071068 b = 1.0 - (2*sqrt(cx^2+cy^2))^2 return RGB(0.5 - rx*1.414, 0.5 - ry*1.414, b) end # 主函数部分 f = Figure(backgroundcolor = RGBf(0.98, 0.98, 0.98), resolution = (1500, 700)) # interaction xs = range(-0.3, length=size(dat_e, 2), step=1 ./ 128) sg = SliderGrid(f[4, 1:2], (label="time", range=xs, format = "{:.3f} ms", startvalue = 0), ) time = sg.sliders[1].value str = lift(t -> "[$(round(t, digits = 3)) ms]", time) topo_slice = lift((t, data) -> mean(data[1:30, indexin(t, xs), :], dims=2)[:,1], time, dat_e) # butterfly plot ax = Axis(f[2:3, 1:2], xlabel = "Time [s]", ylabel = "Voltage amplitude [µV]") N = 1:length(pos) #1:4 hidespines!(ax, :t, :r) GLMakie.xlims!(-0.3, 1.2) hlines!(0, color = :gray, linewidth = 1) vlines!(0, color = :gray, linewidth = 1) times = range(-0.3, length=size(dat_e,2), step=1 ./ 128) specialColors = ColorScheme(vcat(RGB(1,1,1.),[posToColor(pos) for pos in pos[N]]...)) for i in N mean_trial = mean(dat_e[i,:,:], dims=2)[:,1] lines!(times, mean_trial, color = specialColors[i]) end hidedecorations!(ax, label = false, ticks = false, ticklabels = false) # 红色竖线和文本 red_vline = vlines!(time, color = :red, linewidth = 1) text!(time, 8, text = str, align = (:center, :center)) # topoplot topo_axis = Axis(f[1, 1:2], width = 178, height = 178, aspect = DataAspect()) # 关闭轴的内容裁剪,允许Topoplot超出边界 topo_axis.clipmode = :outside Makie.xlims!(low = -0.2, high = 1.2) Makie.ylims!(low = -0.2, high = 1.2) # 动态生成Topoplot的变换矩阵,中心X坐标跟随time topoMatrix = lift(t -> eegHeadMatrix(pos[N], (t, 0.5), 0.5), time) topo = eeg_topoplot!(topo_axis, topo_slice, raw.ch_names[1:30]; positions=pos, enlarge=1, extrapolation=GeomExtrapolation(enlarge=1.0, geometry=Circle), label_text=false) # 应用变换矩阵,让Topoplot随time移动 transform!(topo, topoMatrix) hidedecorations!(topo_axis) hidespines!(topo_axis) # 添加连接红色竖线和Topoplot的线条 # 定义两个锚点:红色竖线的顶部,Topoplot的底部 point_ax = lift(t -> Point2(t, ax.ylimits[][2]), time) point_topo = lift(t -> Point2(t, topo_axis.ylimits[][1]), time) # 将轴坐标转换为屏幕坐标 screen_points = lift(point_ax, point_topo) do pa, pt [project(ax, pa), project(topo_axis, pt)] end # 在Figure的全局场景中绘制连接线 lines!(f.scene, screen_points, color=:black, linewidth=1) f
关键修改说明
Topoplot移动实现:
- 用
lift将eegHeadMatrix的中心X参数绑定到time变量,动态生成变换矩阵 - 通过
transform!(topo, topoMatrix)将变换应用到Topoplot上 - 设置
topo_axis.clipmode = :outside,取消轴的内容裁剪,允许Topoplot部分超出屏幕
- 用
跨轴连接线实现:
- 定义两个锚点:红色竖线在Butterfly轴的顶部,Topoplot在自身轴的底部
- 使用
project函数将轴坐标转换为屏幕坐标,确保跨轴线条位置准确 - 在Figure的全局场景(
f.scene)中绘制线条,并用lift随时间更新线条的点坐标
内容的提问来源于stack exchange,提问作者Vladimir Mikheev
相关产品推荐
相关产品推荐

