使用 Plots.jl 有效地对子图进行动画处理

2024-01-04

我正在尝试使用 Plots.jl 和 GR 后端在 Julia 中创建具有三个子图(一个表面,两个热图)的动画。到目前为止,我的代码中最慢的部分是这些图的生成,因此我试图找到最有效的方法来完成它。

我尝试重新调用动画循环内的绘图,但这比就地修改要慢得多,如下所示:

using Plots,Profile

function mcve(n)
    A = rand(n,100,100)
    B = rand(n,100,100)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        surface!(p[1],1:100,1:100,A[i,:,:])
        heatmap!(p[2],A[i,:,:])
        heatmap!(p[3],B[i,:,:])
    end
    gif(anim,"example.gif")
end

mcve(1)
@profile mcve(10)
Profile.print()

跟踪结果https://pastebin.com/Lv9uCLE5 https://pastebin.com/Lv9uCLE5

根据探查器,近一半的运行时间花费在调用 C 库的函数“setcharheight”上。有没有办法减少我需要拨打的电话次数?


我做了一些实验,发现有两件事可以极大地加快绘图过程。

首先,我没有使用 surface!() 和 heatmap!() 重新绘制绘图,而是简单地替换了它们的 :z 系列。通过比较代码示例中的第一到第三和第二到第四个函数可以看出这一点。

第二,GR.jl; setcharheight 非常慢。这可能是由于 ccall() 造成的,这意味着它可能依赖于操作系统。通过将 xticks 和 yticks 设置为 false,可以实现显着的加速。这通过比较示例中的第一到第二和第三到第四函数来显示。

using Plots

function mcve(n,A,B)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        surface!(p[1],1:100,1:100,A[i,:,:])
        heatmap!(p[2],A[i,:,:])
        heatmap!(p[3],B[i,:,:])
    end
    gif(anim,"example1.gif")
end

function mcve4(n,A,B)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false,xticks=false,yticks=false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false,xticks=false,yticks=false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1,xticks=false,yticks=false)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        surface!(p[1],1:100,1:100,A[i,:,:],xticks=false,yticks=false)
        heatmap!(p[2],A[i,:,:],xticks=false,yticks=false)
        heatmap!(p[3],B[i,:,:],xticks=false,yticks=false)
    end
    gif(anim,"example4.gif")
end


function mcve2(n,A,B)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false,xticks =false,yticks= false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false,xticks = false,yticks= false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1,xticks = false,yticks= false)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        p[1][1][:z] = A[i,:,:]
        p[2][1][:z] = A[i,:,:]
        p[3][1][:z] = B[i,:,:]
    end
    gif(anim,"example2.gif")
end


function mcve3(n,A,B)

    l = @layout [ a b ; c]
    p1 = surface(1:100,1:100,A[1,:,:],clims=(0,1),legend=false)
    p2 = heatmap(A[1,:,:],clims=(0,1),aspect_ratio=1,legend=false)
    p3 = heatmap(B[1,:,:],aspect_ratio=1)
    p = plot(p1,p2,p3,layout = l)

    anim = @animate for i=1:n
        p[1][1][:z] = A[i,:,:]
        p[2][1][:z] = A[i,:,:]
        p[3][1][:z] = B[i,:,:]
    end
    gif(anim,"example3.gif")
end

A = rand(1,100,100)
B = rand(1,100,100)

mcve(1,A,B)
mcve2(1,A,B)
mcve3(1,A,B)
mcve4(1,A,B)

A = rand(10,100,100)
B = rand(10,100,100)

println("Replot,ticks on")
@time mcve(10,A,B)
println("Replot,ticks off")
@time mcve4(10,A,B)
println(":z replace, ticks on")
@time mcve3(10,A,B)
println(":z replace, ticks off")
@time mcve2(10,A,B)

这导致

Replot,ticks on
 19.347849 seconds (12.78 M allocations: 399.848 MiB, 0.30% gc time)
Replot,ticks off
  6.227432 seconds (8.71 M allocations: 298.890 MiB, 0.88% gc time)
:z replace, ticks on
  8.572728 seconds (5.43 M allocations: 149.359 MiB, 0.24% gc time)
:z replace, ticks off
  1.805316 seconds (1.36 M allocations: 48.450 MiB, 0.40% gc time)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Plots.jl 有效地对子图进行动画处理 的相关文章

  • 类型稳定性如何让 Julia 如此之快?

    我听说类型稳定性使 Julia 如此之快 同时仍然与其他解释语言 例如 Python 一样具有表达能力 类型稳定性允许编译器在编译时直接根据输入类型确定函数的输出类型 因为 Julia 专门针对每种输入类型进行编译 这意味着如果所有函数都是
  • 带有 varargs 的 Julia @evalpoly 宏

    我正在尝试使用 Julia 的 evalpoly宏 当我手动提供系数时它可以工作 但我一直无法弄清楚如何通过数组提供这些系数 julia gt VERSION v 0 3 5 julia gt evalpoly 0 5 1 2 3 4 3
  • 如何在 Julia 中提供可重现的样本数据

    Here on stackoverflow com 当我提供样本数据来制作可重现的示例时 我该如何以朱利安方式做到这一点 In R例如dput df 将输出一个字符串 您可以用它来创建df再次 因此 您只需将结果发布到 stackoverf
  • 如何创建并推送到共享或分布式数组数组?

    我编写了 Julia 代码 其中初始化一个空数组 如下所示 a 稍后在代码中 我简单地推送到该数组 如下所示 推 a b 其中 b c d e 是另一个数组 每个 b 可以具有不同的长度 这在非并行化代码中工作得很好 但是 我想在并行代码中
  • Julia:显示函数体(以查找丢失的代码)

    在 R 语言中 我可以声明一个函数并查看函数体 如下所示 gt megafoobar function x return x 10000 gt body megafoobar return x 10000 类似的事情在 Julia 中也可能
  • 有没有办法在 writetable() 中使用字符串作为分隔符 - Julia

    当使用 writetable 将数据帧写入文件时 我希望能够将分隔符设为空格然后逗号 即 作为分隔符 我知道 writetable 只能选择将单个字符作为分隔符参数 是否有可能的解决方法能够将字符串作为分隔符 或者 是否可以简单地在数据框中
  • 在 Julia 中提取参数类型

    假设我在 Julia 中编写了一个函数 它接受Dict K V 作为参数 然后创建类型的数组Array K 1 and Array V 1 我怎样才能提取类型K and V来自 Dict 对象 以便我可以使用它们来创建数组 斯文和约翰的答案
  • Julia:如何让多个工作人员访问模块中的函数?

    我有以下测试模块 MyMod jl 来在 Julia 中存储一些测试函数 一些核心函数是串行编写的 其他函数并行调用核心函数 module MyMod export Dummy distribute data getfrom recombi
  • 使用 Julia 的 Debugger.jl - 如何进入类似于 Python 的 pdb.set_trace() 或 ipdb.set_trace() 的调试模式?

    Julia 的新 Debugger jl 很棒 但有时要达到我想要达到的代码中的确切位置有点痛苦 有没有办法可以进入交互式调试模式 类似于 Python 在 pdb set trace 或 ipdb set trace 中的模式 例如 我希
  • 如何在 Julia `DataFrame` 中折叠具有重复时间戳的数据

    我有一个DataFrame对象如下所示 Row timestamp price volume 1 2011 08 14T14 14 40 10 40 0 779 2 2011 08 14T15 15 17 10 40 0 101 3 201
  • 估算缺失数据,同时强制相关系数保持不变

    考虑以下 excel 数据集 m r 2 0 3 3 0 8 4 0 1 3 2 1 5 2 2 3 1 9 2 5 1 2 3 0 2 0 2 6 我的目标是使用以下条件填充缺失值 将上述两列之间的成对相关性表示为 R 大约 0 68 将
  • 如何制作任意级别的嵌套for循环

    我可以像这样做一个两级嵌套循环 for i1 in 1 n for i2 in 1 n do something with i1 i2 如何将其扩展到任意级别的嵌套循环 例如 我可以在 Python 中执行此操作以循环 n m 的笛卡尔积
  • 是否可以从 Julia 调用 Python 函数并返回其结果?

    我正在使用 Python 从网络上抓取数据 我想使用这些数据在 Julia 中运行计算 是否可以在 Julia 中调用该函数并返回其结果 或者我最好直接导出到 CSV 并以这种方式加载数据 绝对地 看PyCall jl https gith
  • 如何在 Julia 中引用结构本身

    我有这个代码 struct MyStruct text String function MyStruct text String text text do other things end end 当我写这篇文章时 我意识到朱莉娅没有认识到
  • 如何在 Julia 中转置字符串数组?

    它适用于数字 但不适用于字符串 The 1 2 有效 但是 a b 没有 为什么 以及如何做到这一点 Why a b 不起作用 因为 运算符实际上计算矩阵的 惰性 伴随 请注意 如文档中所述 adjoint https docs julia
  • 可选参数的 Julia 约定

    假设我有一个函数 例如f x y 但是y参数是可选的 首选设置方式是什么y作为可选参数 对我有用的一种选择 function f x y nothing do stuff if y nothing do stuff else do stuf
  • 如何使用 Julia 查找矩阵中的连通分量

    假设我有以下矩阵 此处用 Julia 语言定义 mat 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 1 1 将一组值为 1 的相邻元素视为一个 分量 如何识别该矩阵有 2 个分量以及每个分量由哪些顶点组成 对于矩
  • 从 Julia 更新 C 结构体的字段值

    我的问题很简单 但我不知道最好的方法 或者 Julia 目前没有提供这样的方法 如何从 Julia 设置 C 结构的字段值 假设您有一个结构类型来表示 C 库中树的节点 typedef struct node s int type node
  • 在向量的参数向量上调度时出现 MethodError

    我编写了一个函数 该函数在向量的向量上进行分派Integers 但是 当我尝试使用它时 出现 MethodError julia gt foo x Vector Vector lt Integer last last x julia gt
  • 为什么这两种不同的构造数组的方式会产生不同的行为?

    当我以两种不同的方式构造一个 2 元素数组时 例如a and b 当我将一个元素添加到内部数组之一时 我得到两个不同的结果 这也会发生在append 根据构建每个之后的输出 我希望它们完全相同 julia gt a 2 element Ar

随机推荐