【问题标题】:Animated rgl graphs with knitr带有knitr的动画rgl图
【发布时间】:2014-10-01 21:32:12
【问题描述】:

我想通过knitr 在我的.Rnw 文档中包含动画rgl 图表。这是我的 MWE:

\documentclass{article}

<< label = setup, include = FALSE>>=
opts_chunk$set(fig.path = 'figure/',  cache = FALSE, dev = "pdf",  fig.align = 'center', fig.show = 'hold', fig.width = 3, fig.height = 3,  echo = TRUE, warning = FALSE, message = FALSE, size = 'footnotesize', comment=NA, results='hold')

knit_hooks$set(par = function(before, options, envir){
if (before && options$fig.show!='none')
 par(mar = c(4, 4, 0.1, 0.1), cex.lab = 0.95, cex.axis = 0.9, mgp = c(2, 0.7, 0), tcl = -0.3)
}
)
knit_hooks$set(rgl = function(before, options, envir) {
  if (!before) {
    ## after a chunk has been evaluated
    if (rgl.cur() == 0) return()  # no active device
    name = paste(options$fig.path, options$label, sep = '')
    rgl.snapshot(paste(name, '.png', sep = ''), fmt = 'png')
    return(paste('\\includegraphics{', name, '}\n', sep = ''))
  }
}
)

options(replace.assign = TRUE, width = 60)
@ 
\begin{document}

<< label=packages >>=
library(car)
@
<< label=rgl1, rgl=TRUE, fig.show='animate' >>=
scatter3d(prestige ~ income + education, data=Duncan)
@

\end{document}

我的针织文档中没有图表。

更新

我仍然无法让它工作并收到以下警告:

Warning messages:
1: In rgl.snapshot(paste(name, ".png", sep = ""), fmt = "png") :
  RGL: Pixmap save: unable to open file 'D:\A B\C D UAF\Test\knitr\rglAnimation\figure\rgl1.png' for writing
2: In rgl.snapshot(paste(name, ".png", sep = ""), fmt = "png") :
  snapshot failed
3: running command '"C:\PROGRA~2\MIKTEX~1.9\miktex\bin\x64\texi2dvi.exe" --quiet --pdf "rglAnimation.tex" --max-iterations=20 -I "C:/PROGRA~1/R/R-31~1.1/share/texmf/tex/latex" -I "C:/PROGRA~1/R/R-31~1.1/share/texmf/bibtex/bst"' had status 1 

我的sessionInfo()

R version 3.1.1 (2014-07-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)

locale:
[1] LC_COLLATE=English_United States.1252 
[2] LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] tools     stats     graphics  grDevices utils     datasets  methods  
[8] base     

other attached packages:
[1] mgcv_1.8-2    nlme_3.1-117  rgl_0.93.1098 car_2.0-21    knitr_1.6.15 

loaded via a namespace (and not attached):
[1] evaluate_0.5.5  formatR_1.0     grid_3.1.1      highr_0.3      
[5] lattice_0.20-29 MASS_7.3-34     Matrix_1.1-4    nnet_7.3-8     
[9] stringr_0.6.2  

已编辑

opts_chunk$set 中的fig.path = 'figure/' 更改为fig.path = '' 会编译带有png 图形但没有任何动画的文档。如何使用fig.path = 'figure/' 获得动画rgl 图表。

【问题讨论】:

  • 这个例子在我的环境中完美运行。
  • Pixmap save 错误中引用的文件名看起来很奇怪。你的工作目录是什么?
  • 感谢@BenBolker 对我的问题感兴趣。我的工作目录是D:\A B\C D UAF\Test\knitr\rglAnimation
  • 我强烈建议您尝试在路径名中没有空格的工作目录。这可能没有在文档中明确禁止,并且可能在包代码级别可以修复,但这种事情经常会破坏依赖于系统调用的 R 代码。
  • 你是对的@BenBolker。即使从工作目录的名称中删除空格也不起作用。

标签: r animation knitr rgl rnw


【解决方案1】:

我有一个基于您的示例,该示例在 RStudio 0.99.441 中的 Windows 8.1 上使用 knitr。

这会产生一个 40 帧的情节动画。它使用内置的hook_plot_custom 来包含通过动画 3d 绘图手动生成的绘图。动画代码基于play3dmovie3d的帮助和源代码。 movied3d本身不能使用,因为它的文件命名太不灵活了。

我已将其发布在 github 的 https://github.com/NikNakk/testAnimateRgl/ 上。 pdf位于https://github.com/NikNakk/testAnimateRgl/raw/master/rglKnitr.pdf

\documentclass{article}
\usepackage{animate}

<< label = setup, include = FALSE>>=
library("rgl")
library("car")
library("knitr")
knit_hooks$set(rgl = hook_plot_custom)
@ 
\begin{document}

<< label=rgl1, rgl=TRUE, fig.show='animate', fig.width=5, fig.height=5, out.width='.6\\linewidth', dev='png', fig.num = 40, interval=0.1>>=
scatter3d(prestige ~ income + education, data=Duncan)
M <- par3d("userMatrix")
par3d(windowRect = 100 + opts_current$get("dpi") *
        c(0, 0, opts_current$get("fig.width"), 
        opts_current$get("fig.height")))
spinFunc <- par3dinterp(userMatrix=list(M,
                             rotate3d(M, pi/2, 1, 0, 0),
                             rotate3d(M, pi/2, 0, 1, 0)))
for(i in 1:40) {
  par3d(spinFunc(i / 10))
  Sys.sleep(0.05)
  rgl.snapshot(fig_path(".png", number = i), fmt = "png")
}
@

\end{document}

编辑:新版本

这是另一个版本,它演示了使用自定义块选项来为更简单的spin3d 设置参数。请注意,在此版本中,块只是一行(scatter3d 图)。 spin3d.axis用于设置轴参数为spin3dspin3d.rpm 用于设置rpm 参数。使用标准fig.numinterval参数设置图像的数量和图像之间的间隔。

\documentclass{article}
\usepackage{animate}

<< label = setup, include = FALSE>>=
  library("rgl")
library("car")
library("knitr")
hook_rgl_spin <- function(before, options, envir) {
  if (!before) {
    par3d(windowRect = 100 + options$dpi *
          c(0, 0, options$fig.width, 
            options$fig.height))
    if (!is.null(options$spin3d.axis)) {
      spin3d.axis <- options$spin3d.axis
    } else {
      spin3d.axis <- c(0, 0, 1)
    }
    if (!is.null(options$spin3d.rpm)) {
      spin3d.rpm <- options$spin3d.rpm
    } else {
      spin3d.rpm <- c(0, 0, 1)
    }
    spinFunc <- spin3d(axis = spin3d.axis, rpm = spin3d.rpm)
    for(i in 1:options$fig.num) {
      par3d(spinFunc(i * options$interval))
      Sys.sleep(0.05)
      rgl.snapshot(fig_path(".png", number = i), fmt = "png")
    }

    hook_plot_custom(before, options, envir)
  }
}
knit_hooks$set(rgl = hook_rgl_spin)
@ 
  \begin{document}

<< label=rgl1, rgl=TRUE, fig.show='animate', fig.width=5, fig.height=5, out.width='.6\\linewidth', dev='png', fig.num = 40, interval=0.1, spin3d.axis=c(0, 0, 1), spin3d.rpm = 20>>=
  scatter3d(prestige ~ income + education, data=Duncan)
@

  \end{document}

【讨论】:

  • 感谢@NickK 的出色回答。在我的机器上,fig.path = 'figure/' 不起作用,所以我必须将 fig.path = 'figure/' 更改为 fig.path = ''。知道这段代码将如何为fig.path = 'figure/' 工作。如果您告诉我 Adob​​e Reader 播放动画也将不胜感激。谢谢
  • 我不得不手动创建 'figure' 子文件夹,之后它运行良好。您能否确认您是否已经有一个具有该名称的文件夹?如果没有,请使用您喜欢的任何方式创建一个(例如dir.create("figure"))。我也会尝试使用png("figure/test.png"); plot(1); dev.off() 在此处手动保存 png。我在 Windows 上使用了 Adob​​e Reader XI(当前版本),也在 Windows 上使用了 Acrobat X。它在 Sumatra(RStudio 中的 PDF 阅读器)或我尝试过的任何 iOS pdf 阅读器(包括 Adob​​e 自己的)中都没有动画。
  • 通过将生成的 PNG 传递给 ffmpeg 以生成 .mp4 文件,然后使用 media9 嵌入它,可以生成适用于 Okular 和 Adob​​e Reader 的动画。但我不认为knitr 直接支持这一点,因此它会涉及更多编码。理论上,iOS 上的 ezPDFreader 也支持这一点,尽管我还没有测试过。
  • 我在 RStudio PDF 查看器中运行第一个示例,它会显示一些动画大约 1 秒,然后我得到 Error: chunk 2 (label = rgl1) Error in par3d(windowRect = 100 + opts_current$get("dpi") * c(0, 0, opts_current$get("fig.width"), : parameter "windowRect" has the wrong length Execution halted
  • @akhmed 你确定你没有抄错什么吗?您可以省略该行,它仍然可以工作,但会小于设置的大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2013-08-19
  • 1970-01-01
  • 2021-03-25
  • 1970-01-01
  • 2023-01-22
相关资源
最近更新 更多