Wandering usr values in par(no.readonly=TRUW) (PR#2283)

Marc Schwartz mschwartz@medanalytics.com
Wed, 13 Nov 2002 11:01:49 -0600


Marc Schwartz wrote:
>
> SNIP
>
> I am guessing that this may be the result of par("ylog") and
> par("xlog") being read only and perhaps impacting the restoration of 
> the par("usr") values when the plotting device is still open, but
> that may be incorrect.   

In follow up to my own note from last evening on this and now that I
have had a couple of cups of coffee this morning, I need to partially
correct my above statement and point to a presumed typo in the ?par help
file.  For confirmation, this is R 1.6.1 under WinXP Pro.

par("xlog") and par("ylog") are not Read Only parameters as listed in
the help file and can be set by the user.  Indeed this is confirmed in
the comments in par.r:

#.Pars.readonly <- c("cin","cra","csi","cxy","din")

I noted this today as I was comparing the output of par() with
par(no.readonly = TRUE) and noted that the latter returns '$xlog' and
$ylog' as being settable. The other 5 par values listed in ?par as
"R.O." (cin, cra, csi, cxy and din) return errors when one attempts to
set them with par(args), however xlog and ylog do not.

Jari and I had an offline exchange earlier this morning in which I
offered the following example code as a short term fix for the problem
he identified. This replaces the on.exit(par(op)) with code to reset the
par("usr") values explicity at the end of the function, since the
"looping" use of the function is stopped anyway if the function exits
prematurely.

plot2.log <- function (x=1:2,y=1:2)
{
  op <- par(no.readonly=TRUE)

  cat(op$usr, "\n")
  plot(x, y, log="y")

  # restore par
  par(op)

  # show post restoration par("usr")
  cat(par("usr"), "\n")

  # set up usr for log transform
  usr <- par("usr")
  usr[3:4] <- log10(usr[3:4])
  par(usr = usr)

  # show post transform par("usr")
  cat(par("usr"), "\n")
}



However, upon now noting the presumed typos in ?par, I have played
around with the following code to see the impact of setting par("ylog")
on the restoration of the par("usr") values after the log scale plot is
created.  Indeed, if I reset par("ylog") explicitly to "FALSE" prior to
the par(op), par("usr") is properly restored. Thus it would appear that
I was partially correct in presuming that the value of par("ylog")
impacts the value of par("usr") when restoring the initial values.


plot2.log <- function (x=1:2,y=1:2)
{
  op <- par(no.readonly=TRUE)

  # show current op$usr
  cat(op$usr, "\n")

  plot(x, y, log="y")

  # restore par, first setting 'ylog' to FALSE
  par(ylog = FALSE)
  par(op)

  # show post restoration par("usr")
  cat(par("usr"), "\n")
}



As a test of this theory, I also tried the following, which uses the
same underlying code, except that it now plots a normal linear y axis
and I explicitly set par("ylog") to TRUE prior to par(op).  Note the
value of par("usr") post restoration.

plot2.log <- function (x=1:2,y=1:2)
{
  op <- par(no.readonly=TRUE)

  # show current op$usr
  cat(op$usr, "\n")

  plot(x, y)

  # restore par, first setting 'ylog' to FALSE
  par(ylog = TRUE)
  par(op)

  # show post restoration par("usr")
  cat(par("usr"), "\n")
}


So it would seem that the values of 'xlog' and 'ylog' do impact the
proper restoration of the par("usr") values.

I have now reviewed par.c and have found the following code in
Specify():

            ...

	if (Rf_gpptr(dd)->ylog) {
	    R_DEV_2(logusr[2]) = REAL(value)[2];
	    R_DEV_2(logusr[3]) = REAL(value)[3];
	    R_DEV_2(usr[2]) = pow(10., REAL(value)[2]);
	    R_DEV_2(usr[3]) = pow(10., REAL(value)[3]);

            ...

There is similar code for 'xlog'.

Thus, this would confirm that the values of 'xlog' and 'ylog' do indeed
affect the restoration values of par("usr").

Lastly, there is a note in ?par that read as follows:

Note:

     The effect of restoring all the (settable) graphics parameters as
     in the examples is hard to predict if the device has been resized.
     Several of them are attempting to set the same things in different
     ways, and those last in the alphabet will win.  In particular, the
     settings of `mai', `mar', `pin', `plt' and `pty' interact, as do
     the outer margin settings, the figure layout and figure region
     size.

In this case, the device is not being resized and it is not clear from
the note that par("usr") is affected. However, given that both 'xlog'
and 'ylog' are alphabetically after it, once could infer that this
behavior is sort of documented, since 'usr' would be set prior to 'xlog'
and 'ylog' being set back to FALSE in this scenario.

I may need yet more coffee, but at the moment I cannot envision possible
impacts of first checking to see if 'xlog' and/or 'ylog' are being set
back to FALSE as part of the above code in par.c, before setting
par("usr"). This could be feasibly be accomplished by moving the code
for setting 'xlog' and 'ylog' in par.c to before the code for 'usr'.

If there are in fact other issues that such a fix would create, I would
suggest a note be added to ?par that would identify that par("usr") is
not restored properly from saved values if a log scaled axis is used and
that a solution would be to explicitly set the values of 'xlog' and
'ylog' to FALSE prior to restoration.

Hope this helps,

Marc Schwartz


-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._