You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何沿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

关键修改说明

  1. Topoplot移动实现:

    • 用lift将eegHeadMatrix的中心X参数绑定到time变量,动态生成变换矩阵
    • 通过transform!(topo, topoMatrix)将变换应用到Topoplot上
    • 设置topo_axis.clipmode = :outside,取消轴的内容裁剪,允许Topoplot部分超出屏幕
  2. 跨轴连接线实现:

    • 定义两个锚点:红色竖线在Butterfly轴的顶部,Topoplot在自身轴的底部
    • 使用project函数将轴坐标转换为屏幕坐标,确保跨轴线条位置准确
    • 在Figure的全局场景(f.scene)中绘制线条,并用lift随时间更新线条的点坐标

内容的提问来源于stack exchange,提问作者Vladimir Mikheev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 07:40:32