Discussion:
[R] par("plt") behaving inconsistely? bug?
Murat Tasan
2014-10-06 18:00:14 UTC
Permalink
Hi all -- I just encountered a behavior that I believe has changed
from previous versions, though I haven't chased back the last version
that behaves as my existing code expects quite yet.
Perhaps this is a bug, though perhaps I'm missing a subtle detail
somewhere in the documentation...

Here's some code that works as expected (in R 3.1.1):

########################################
pdf()
plot.new()

original_plt <- par("plt")

plt_1 <- c(original_plt[1],
original_plt[1] + (original_plt[2] - original_plt[1]) / 2,
original_plt[3],
original_plt[3] + (original_plt[4] - original_plt[3]) / 2)
par("plt" = plt_1)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
plt_2 <- c(plt_1[2],
original_plt[2],
plt_1[4],
original_plt[4])
par("plt" = plt_2)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
par("plt" = original_plt)
box(lty = 2)
dev.off()
########################################

This will draw 3 boxes... one in the lower left corner (specified by
plt_1), one in the top right corner (specified by plt_2), and one
dotted box around the full plot box (original_plt).

Now, if you replace the first two box() calls by: rect(0, 0, 1, 1),
only the lower-left rectangle is drawn.
If you _add_ rect(0, 0, 1, 1) after each box() call, all boxes and
rectangles are correctly drawn.

It seems that after setting plt once, subsequent plt alterations put
the device into a state that will permits drawing of _some_ things
(e.g. box()), but not other things (e.g. rect, lines, points).

A kludge to fix this is to call box(col = "white")... but that's quite
the kludge, indeed!
Axis() works just like box(), too... but I haven't exhausted which
drawing functions work and which don't.

I'd classify this is a bug, but I thought I'd check here first.
I've also only checked this so far with the pdf() device, so I don't
know if it is somehow device-specific.

I detected this because some existing code (that worked on some
earlier version of R, sorry that I don't know which one yet...) has
suddenly stopped working!

Cheers!

-murat
Murat Tasan
2014-10-06 18:05:35 UTC
Permalink
Another (easier) kludge is augmenting a call to each par("plt" = ...) call:

par("plt" = some_plt_coordinates); box(lty = 0)

The box(lty = 0) addition makes downstream calls work as expected, but
yeah... this is a kuldge.

-m
Post by Murat Tasan
Hi all -- I just encountered a behavior that I believe has changed
from previous versions, though I haven't chased back the last version
that behaves as my existing code expects quite yet.
Perhaps this is a bug, though perhaps I'm missing a subtle detail
somewhere in the documentation...
########################################
pdf()
plot.new()
original_plt <- par("plt")
plt_1 <- c(original_plt[1],
original_plt[1] + (original_plt[2] - original_plt[1]) / 2,
original_plt[3],
original_plt[3] + (original_plt[4] - original_plt[3]) / 2)
par("plt" = plt_1)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
plt_2 <- c(plt_1[2],
original_plt[2],
plt_1[4],
original_plt[4])
par("plt" = plt_2)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
par("plt" = original_plt)
box(lty = 2)
dev.off()
########################################
This will draw 3 boxes... one in the lower left corner (specified by
plt_1), one in the top right corner (specified by plt_2), and one
dotted box around the full plot box (original_plt).
Now, if you replace the first two box() calls by: rect(0, 0, 1, 1),
only the lower-left rectangle is drawn.
If you _add_ rect(0, 0, 1, 1) after each box() call, all boxes and
rectangles are correctly drawn.
It seems that after setting plt once, subsequent plt alterations put
the device into a state that will permits drawing of _some_ things
(e.g. box()), but not other things (e.g. rect, lines, points).
A kludge to fix this is to call box(col = "white")... but that's quite
the kludge, indeed!
Axis() works just like box(), too... but I haven't exhausted which
drawing functions work and which don't.
I'd classify this is a bug, but I thought I'd check here first.
I've also only checked this so far with the pdf() device, so I don't
know if it is somehow device-specific.
I detected this because some existing code (that worked on some
earlier version of R, sorry that I don't know which one yet...) has
suddenly stopped working!
Cheers!
-murat
Greg Snow
2014-10-06 20:08:39 UTC
Permalink
I believe that what is happening is that the clipping region is being
reset when you call box, but not when you call rect. If you insert
the command "par(xpd=NA)" (or TRUE instead of NA) after the plot.new
and use the rect commands then you can see both rectangles (because
this turns the clipping off). Working with the clipping region
(indirectly in your case) is complex since some functions properly
reset the region and others do not (and making the others
automatically reset it may cause other problems when they reset a
clipping region that should not be reset).

So the options are:

1 dive into the source code enough to figure out if fixing rect to
work with the clipping region is simple or not and submitting a patch
2 wait for Prof Brian Ripley to notice this fact and do the above (he
has fixed a couple of other functions when made aware)
3 use par(xpd=TRUE) (or NA) to not clip to the plotting region (this
is simple, but will allow things to be drawn outside of the plotting
region, on simple example is using abline)
4 use a function that properly sets the clipping region (such as box)
before plotting anything else
5 call clip(0,1,0,1) (or with the actual user coordinates) to manually
set the clipping region
6 other?
Post by Murat Tasan
Hi all -- I just encountered a behavior that I believe has changed
from previous versions, though I haven't chased back the last version
that behaves as my existing code expects quite yet.
Perhaps this is a bug, though perhaps I'm missing a subtle detail
somewhere in the documentation...
########################################
pdf()
plot.new()
original_plt <- par("plt")
plt_1 <- c(original_plt[1],
original_plt[1] + (original_plt[2] - original_plt[1]) / 2,
original_plt[3],
original_plt[3] + (original_plt[4] - original_plt[3]) / 2)
par("plt" = plt_1)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
plt_2 <- c(plt_1[2],
original_plt[2],
plt_1[4],
original_plt[4])
par("plt" = plt_2)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
par("plt" = original_plt)
box(lty = 2)
dev.off()
########################################
This will draw 3 boxes... one in the lower left corner (specified by
plt_1), one in the top right corner (specified by plt_2), and one
dotted box around the full plot box (original_plt).
Now, if you replace the first two box() calls by: rect(0, 0, 1, 1),
only the lower-left rectangle is drawn.
If you _add_ rect(0, 0, 1, 1) after each box() call, all boxes and
rectangles are correctly drawn.
It seems that after setting plt once, subsequent plt alterations put
the device into a state that will permits drawing of _some_ things
(e.g. box()), but not other things (e.g. rect, lines, points).
A kludge to fix this is to call box(col = "white")... but that's quite
the kludge, indeed!
Axis() works just like box(), too... but I haven't exhausted which
drawing functions work and which don't.
I'd classify this is a bug, but I thought I'd check here first.
I've also only checked this so far with the pdf() device, so I don't
know if it is somehow device-specific.
I detected this because some existing code (that worked on some
earlier version of R, sorry that I don't know which one yet...) has
suddenly stopped working!
Cheers!
-murat
______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
--
Gregory (Greg) L. Snow Ph.D.
538280 at gmail.com
Murat Tasan
2014-10-07 02:33:54 UTC
Permalink
6. iteratively downgrade to earlier versions of R until it's working
again... then try to diff out the offending source code change.
i can try this, but i probably won't get to it for at least a few weeks :-/

in the meantime, i'm tacking on box(lty = 0) to every par(plt = ...) call, e.g.
Post by Murat Tasan
par("plt" = some_plt_coordinates); box(lty = 0)
in the short term, this works.
clip(...), a combination of par("new" = TRUE); plot.new(), and a whole
bunch of other kludges work, too... pick your poison :-)

cheers and thanks!

-murat
Post by Murat Tasan
I believe that what is happening is that the clipping region is being
reset when you call box, but not when you call rect. If you insert
the command "par(xpd=NA)" (or TRUE instead of NA) after the plot.new
and use the rect commands then you can see both rectangles (because
this turns the clipping off). Working with the clipping region
(indirectly in your case) is complex since some functions properly
reset the region and others do not (and making the others
automatically reset it may cause other problems when they reset a
clipping region that should not be reset).
1 dive into the source code enough to figure out if fixing rect to
work with the clipping region is simple or not and submitting a patch
2 wait for Prof Brian Ripley to notice this fact and do the above (he
has fixed a couple of other functions when made aware)
3 use par(xpd=TRUE) (or NA) to not clip to the plotting region (this
is simple, but will allow things to be drawn outside of the plotting
region, on simple example is using abline)
4 use a function that properly sets the clipping region (such as box)
before plotting anything else
5 call clip(0,1,0,1) (or with the actual user coordinates) to manually
set the clipping region
6 other?
Post by Murat Tasan
Hi all -- I just encountered a behavior that I believe has changed
from previous versions, though I haven't chased back the last version
that behaves as my existing code expects quite yet.
Perhaps this is a bug, though perhaps I'm missing a subtle detail
somewhere in the documentation...
########################################
pdf()
plot.new()
original_plt <- par("plt")
plt_1 <- c(original_plt[1],
original_plt[1] + (original_plt[2] - original_plt[1]) / 2,
original_plt[3],
original_plt[3] + (original_plt[4] - original_plt[3]) / 2)
par("plt" = plt_1)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
plt_2 <- c(plt_1[2],
original_plt[2],
plt_1[4],
original_plt[4])
par("plt" = plt_2)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
par("plt" = original_plt)
box(lty = 2)
dev.off()
########################################
This will draw 3 boxes... one in the lower left corner (specified by
plt_1), one in the top right corner (specified by plt_2), and one
dotted box around the full plot box (original_plt).
Now, if you replace the first two box() calls by: rect(0, 0, 1, 1),
only the lower-left rectangle is drawn.
If you _add_ rect(0, 0, 1, 1) after each box() call, all boxes and
rectangles are correctly drawn.
It seems that after setting plt once, subsequent plt alterations put
the device into a state that will permits drawing of _some_ things
(e.g. box()), but not other things (e.g. rect, lines, points).
A kludge to fix this is to call box(col = "white")... but that's quite
the kludge, indeed!
Axis() works just like box(), too... but I haven't exhausted which
drawing functions work and which don't.
I'd classify this is a bug, but I thought I'd check here first.
I've also only checked this so far with the pdf() device, so I don't
know if it is somehow device-specific.
I detected this because some existing code (that worked on some
earlier version of R, sorry that I don't know which one yet...) has
suddenly stopped working!
Cheers!
-murat
______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
--
Gregory (Greg) L. Snow Ph.D.
538280 at gmail.com
Paul Murrell
2014-10-09 02:16:29 UTC
Permalink
Hi

The canonical poison is this ...

par(plt)
plot.new()
...
par(plt)
par(new=TRUE)
plot.new()
...
par(plt)
par(new=TRUE)
plot.new()

The idea is to set up parameters that control the placement of a plot,
e.g., par(plt), and then start a plot, with plot.new(). If you want
more than one plot on a page (and par(mfrow) does not suffice) then you
set up new placement parameters, tell R not to start a new page, with
par(new=TRUE), then start another plot, with plot.new().

Your code does not follow the "spirit" of the R graphics model because
it starts a plot with one set of placement parameters and then changes
those placement parameters several times within the same plot (instead
of starting a new plot for each new set of placement parameters).

I had a look at the C code that leads to your "surprising" result and
there is at least one infelicity in there, but I could not see a simple
fix that would make your example "work" without a high risk of breaking
other things. So I'm afraid my best advice is to change your code to
work with the graphics system.

The layout() function might provide a less unpleasant approach to having
more than one plot region on the page, depending on how complex your
arrangement of plot regions is.

Another alternative is to use the 'grid' graphics package, which is
designed to allow for the flexible creation of multiple regions,
depending on what you want to draw in each of those regions.

Paul
Post by Murat Tasan
6. iteratively downgrade to earlier versions of R until it's working
again... then try to diff out the offending source code change.
i can try this, but i probably won't get to it for at least a few weeks :-/
in the meantime, i'm tacking on box(lty = 0) to every par(plt = ...) call, e.g.
Post by Murat Tasan
par("plt" = some_plt_coordinates); box(lty = 0)
in the short term, this works.
clip(...), a combination of par("new" = TRUE); plot.new(), and a whole
bunch of other kludges work, too... pick your poison :-)
cheers and thanks!
-murat
Post by Murat Tasan
I believe that what is happening is that the clipping region is being
reset when you call box, but not when you call rect. If you insert
the command "par(xpd=NA)" (or TRUE instead of NA) after the plot.new
and use the rect commands then you can see both rectangles (because
this turns the clipping off). Working with the clipping region
(indirectly in your case) is complex since some functions properly
reset the region and others do not (and making the others
automatically reset it may cause other problems when they reset a
clipping region that should not be reset).
1 dive into the source code enough to figure out if fixing rect to
work with the clipping region is simple or not and submitting a patch
2 wait for Prof Brian Ripley to notice this fact and do the above (he
has fixed a couple of other functions when made aware)
3 use par(xpd=TRUE) (or NA) to not clip to the plotting region (this
is simple, but will allow things to be drawn outside of the plotting
region, on simple example is using abline)
4 use a function that properly sets the clipping region (such as box)
before plotting anything else
5 call clip(0,1,0,1) (or with the actual user coordinates) to manually
set the clipping region
6 other?
Post by Murat Tasan
Hi all -- I just encountered a behavior that I believe has changed
from previous versions, though I haven't chased back the last version
that behaves as my existing code expects quite yet.
Perhaps this is a bug, though perhaps I'm missing a subtle detail
somewhere in the documentation...
########################################
pdf()
plot.new()
original_plt <- par("plt")
plt_1 <- c(original_plt[1],
original_plt[1] + (original_plt[2] - original_plt[1]) / 2,
original_plt[3],
original_plt[3] + (original_plt[4] - original_plt[3]) / 2)
par("plt" = plt_1)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
plt_2 <- c(plt_1[2],
original_plt[2],
plt_1[4],
original_plt[4])
par("plt" = plt_2)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
par("plt" = original_plt)
box(lty = 2)
dev.off()
########################################
This will draw 3 boxes... one in the lower left corner (specified by
plt_1), one in the top right corner (specified by plt_2), and one
dotted box around the full plot box (original_plt).
Now, if you replace the first two box() calls by: rect(0, 0, 1, 1),
only the lower-left rectangle is drawn.
If you _add_ rect(0, 0, 1, 1) after each box() call, all boxes and
rectangles are correctly drawn.
It seems that after setting plt once, subsequent plt alterations put
the device into a state that will permits drawing of _some_ things
(e.g. box()), but not other things (e.g. rect, lines, points).
A kludge to fix this is to call box(col = "white")... but that's quite
the kludge, indeed!
Axis() works just like box(), too... but I haven't exhausted which
drawing functions work and which don't.
I'd classify this is a bug, but I thought I'd check here first.
I've also only checked this so far with the pdf() device, so I don't
know if it is somehow device-specific.
I detected this because some existing code (that worked on some
earlier version of R, sorry that I don't know which one yet...) has
suddenly stopped working!
Cheers!
-murat
______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
--
Gregory (Greg) L. Snow Ph.D.
538280 at gmail.com
______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
--
Dr Paul Murrell
Department of Statistics
The University of Auckland
Private Bag 92019
Auckland
New Zealand
64 9 3737599 x85392
paul at stat.auckland.ac.nz
http://www.stat.auckland.ac.nz/~paul/
Murat Tasan
2014-10-13 03:09:06 UTC
Permalink
Fair enough, thanks for the reply, Paul.
I guess my follow-up thought is just on some undocumented
inconsistencies with which drawing functions handle upstream par(plt)
changes.
box() and axis(), for example, doesn't seem to mind at all, while more
data-oriented commands, e.g. points(...), balk without either (i)
something like par(new=TRUE); plot.new(); , or (ii) box() or axis()
appearing upstream.
But, at the same time, if no plot.new() call has ever been made on the
current device, both box() and points() give the same (or similar)
"plot.new() hasn't been called yet" error.

I'm not complaining, rather just sharing observations on some
seemingly (to me, perhaps not to all!) undocumented inconsistencies in
behavior.
I love having the par(plt) functionality around, and I think your
'best practices' description for its use is great.
Perhaps some version of your post can be added to the man page for par(plt)?

Cheers and thanks again!

-murat
Post by Paul Murrell
Hi
The canonical poison is this ...
par(plt)
plot.new()
...
par(plt)
par(new=TRUE)
plot.new()
...
par(plt)
par(new=TRUE)
plot.new()
The idea is to set up parameters that control the placement of a plot, e.g.,
par(plt), and then start a plot, with plot.new(). If you want more than one
plot on a page (and par(mfrow) does not suffice) then you set up new
placement parameters, tell R not to start a new page, with par(new=TRUE),
then start another plot, with plot.new().
Your code does not follow the "spirit" of the R graphics model because it
starts a plot with one set of placement parameters and then changes those
placement parameters several times within the same plot (instead of starting
a new plot for each new set of placement parameters).
I had a look at the C code that leads to your "surprising" result and there
is at least one infelicity in there, but I could not see a simple fix that
would make your example "work" without a high risk of breaking other things.
So I'm afraid my best advice is to change your code to work with the
graphics system.
The layout() function might provide a less unpleasant approach to having
more than one plot region on the page, depending on how complex your
arrangement of plot regions is.
Another alternative is to use the 'grid' graphics package, which is designed
to allow for the flexible creation of multiple regions, depending on what
you want to draw in each of those regions.
Paul
Post by Murat Tasan
6. iteratively downgrade to earlier versions of R until it's working
again... then try to diff out the offending source code change.
i can try this, but i probably won't get to it for at least a few weeks :-/
in the meantime, i'm tacking on box(lty = 0) to every par(plt = ...) call, e.g.
Post by Murat Tasan
par("plt" = some_plt_coordinates); box(lty = 0)
in the short term, this works.
clip(...), a combination of par("new" = TRUE); plot.new(), and a whole
bunch of other kludges work, too... pick your poison :-)
cheers and thanks!
-murat
Post by Murat Tasan
I believe that what is happening is that the clipping region is being
reset when you call box, but not when you call rect. If you insert
the command "par(xpd=NA)" (or TRUE instead of NA) after the plot.new
and use the rect commands then you can see both rectangles (because
this turns the clipping off). Working with the clipping region
(indirectly in your case) is complex since some functions properly
reset the region and others do not (and making the others
automatically reset it may cause other problems when they reset a
clipping region that should not be reset).
1 dive into the source code enough to figure out if fixing rect to
work with the clipping region is simple or not and submitting a patch
2 wait for Prof Brian Ripley to notice this fact and do the above (he
has fixed a couple of other functions when made aware)
3 use par(xpd=TRUE) (or NA) to not clip to the plotting region (this
is simple, but will allow things to be drawn outside of the plotting
region, on simple example is using abline)
4 use a function that properly sets the clipping region (such as box)
before plotting anything else
5 call clip(0,1,0,1) (or with the actual user coordinates) to manually
set the clipping region
6 other?
Post by Murat Tasan
Hi all -- I just encountered a behavior that I believe has changed
from previous versions, though I haven't chased back the last version
that behaves as my existing code expects quite yet.
Perhaps this is a bug, though perhaps I'm missing a subtle detail
somewhere in the documentation...
########################################
pdf()
plot.new()
original_plt <- par("plt")
plt_1 <- c(original_plt[1],
original_plt[1] + (original_plt[2] - original_plt[1]) / 2,
original_plt[3],
original_plt[3] + (original_plt[4] - original_plt[3]) / 2)
par("plt" = plt_1)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
plt_2 <- c(plt_1[2],
original_plt[2],
plt_1[4],
original_plt[4])
par("plt" = plt_2)
plot.window(xlim = c(0, 1), ylim = c(0, 1))
box()
par("plt" = original_plt)
box(lty = 2)
dev.off()
########################################
This will draw 3 boxes... one in the lower left corner (specified by
plt_1), one in the top right corner (specified by plt_2), and one
dotted box around the full plot box (original_plt).
Now, if you replace the first two box() calls by: rect(0, 0, 1, 1),
only the lower-left rectangle is drawn.
If you _add_ rect(0, 0, 1, 1) after each box() call, all boxes and
rectangles are correctly drawn.
It seems that after setting plt once, subsequent plt alterations put
the device into a state that will permits drawing of _some_ things
(e.g. box()), but not other things (e.g. rect, lines, points).
A kludge to fix this is to call box(col = "white")... but that's quite
the kludge, indeed!
Axis() works just like box(), too... but I haven't exhausted which
drawing functions work and which don't.
I'd classify this is a bug, but I thought I'd check here first.
I've also only checked this so far with the pdf() device, so I don't
know if it is somehow device-specific.
I detected this because some existing code (that worked on some
earlier version of R, sorry that I don't know which one yet...) has
suddenly stopped working!
Cheers!
-murat
______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
--
Gregory (Greg) L. Snow Ph.D.
538280 at gmail.com
______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
--
Dr Paul Murrell
Department of Statistics
The University of Auckland
Private Bag 92019
Auckland
New Zealand
64 9 3737599 x85392
paul at stat.auckland.ac.nz
http://www.stat.auckland.ac.nz/~paul/
Loading...