par() being ignored in customized device

13 views
Skip to first unread message

Frank

unread,
Feb 10, 2012, 9:35:52 AM2/10/12
to knitr
I am trying to control par() in my customized pdf device but the par()
call is being ignored. The output from the script below uses the
default bty='o' (completely framed box) instead of an L frame. I am
using the latest beta for knitr from github. -Frank

\documentclass{article}

<<>>=
require(knitr)
mpdf <- function(file, width, height) {
w <- opts_current$get('bty')
cat('file:', file, ' bty:', w, '\n', file='/tmp/z.txt') # shows
bty="l"
pdf(file, width = width, height = height)
par(bty=w)
}
options(replace.assign=TRUE)
@

\SweaveOpts{fig.path=figure/graphics-, fig.align=center, fig.width=4,
fig.height=3, fig.show=hold, comment=NA, dev=mpdf, fig.ext=pdf}

\begin{document}

<<test,bty=l>>=
plot(rnorm(5))
@
\end{document}

Yihui Xie

unread,
Feb 10, 2012, 3:03:24 PM2/10/12
to Frank, knitr
At the first glance, I thought this was a bug, but now I see the
misunderstanding. A device is only used to save plots _after_ the code
is executed; this is a slight difference with Sweave, as Sweave opens
a device, then runs the code and closes the device. In knitr, the
plots are first _recorded_, then saved, so par(bty) did not really go
into the recorded plot.

I recommend you to separate different functions apart: let a device
function only open a device, and let chunk hooks do the job of
executing R code before/after the chunk, e.g.

<<par-hook>>=
knit_hooks$set(par = function(before, options, envir) {
if (!before) return()
pars <- opts_current$get(c('bty', 'las'))
do.call(par, pars)
})
@

<<plot-par, par=TRUE, bty=l, las=2>>=
plot(rnorm(100))
@

Regards,
Yihui
--
Yihui Xie <xiey...@gmail.com>
Phone: 515-294-2465 Web: http://yihui.name
Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA

Frank Harrell

unread,
Feb 12, 2012, 12:14:16 AM2/12/12
to knitr
Now I understand. Thanks for the great explanation. I've make
par=TRUE a global option, and used the hook as you've specified.
Everything is working well.

Thanks for all your help Yihui. -Frank


On Feb 10, 2:03 pm, Yihui Xie <xieyi...@gmail.com> wrote:
> At the first glance, I thought this was a bug, but now I see the
> misunderstanding. A device is only used to save plots _after_ the code
> is executed; this is a slight difference with Sweave, as Sweave opens
> a device, then runs the code and closes the device. In knitr, the
> plots are first _recorded_, then saved, so par(bty) did not really go
> into the recorded plot.
>
> I recommend you to separate different functions apart: let a device
> function only open a device, and let chunk hooks do the job of
> executing R code before/after the chunk, e.g.
>
> <<par-hook>>=
> knit_hooks$set(par = function(before, options, envir) {
>   if (!before) return()
>   pars <- opts_current$get(c('bty', 'las'))
>   do.call(par, pars)})
>
> @
>
> <<plot-par, par=TRUE, bty=l, las=2>>=
> plot(rnorm(100))
> @
>
> Regards,
> Yihui
> --
> Yihui Xie <xieyi...@gmail.com>
> Phone:515-294-2465Web:http://yihui.name

Yihui Xie

unread,
Feb 12, 2012, 12:24:02 AM2/12/12
to Frank Harrell, knitr
You are welcome. I'm glad it helped :)

Regards,
Yihui
--
Yihui Xie <xiey...@gmail.com>
Phone: 515-294-2465 Web: http://yihui.name


Department of Statistics, Iowa State University
2215 Snedecor Hall, Ames, IA

Reply all
Reply to author
Forward
0 new messages