How to write units raised to some number in titles of axes in an IDL plot window? - idl-programming-language

The titles of axes in a plot usually consists of units of some physical parameter. How do we represent such a unit, especially when it contains some letter raised to the power some number?
For example, if the x-axis represents velocity, how can we represent m s^-1 properly as the xtitle?

It depends on the graphics system you are using.
If you are using function graphics, then you can do something like:
IDL> p = plot(/test, ytitle='velocity $m s^{-1}$')
If you are using direct graphics, then do:
IDL> plot, findgen(10), ytitle='velocity m s!E-1!N'
See the Doc Center for a complete listing of the embedded graphics format codes.
There are also helpful library routines to help with direct graphics.

Related

How to rasterize a single layer of a ggplot?

Matplotlib allows to rasterize individual elements of a plot and save it as a mixed pixel/vector graphic (.pdf) (see e.g. this answer). How can the same achieved in R with ggplot2?
The following is a toy problem in which I would like to rasterize only the geom_point layer.
set.seed(1)
x <- rlnorm(10000,4)
y <- 1+rpois(length(x),lambda=x/10+1/x)
z <- sample(letters[1:2],length(x), replace=TRUE)
p <- ggplot(data.frame(x,y,z),aes(x=x,y=y)) +
facet_wrap("z") +
geom_point(size=0.1,alpha=0.1) +
scale_x_log10()+scale_y_log10() +
geom_smooth(method="gam",formula = y ~ s(x, bs = "cs"))
print(p)
ggsave("out.pdf", p)
When saved as .pdf as is, Adobe reader DC needs ~1s to render the figure. Below you can see a .png version:
Of course, it is often possible to avoid the problem by not plotting raw data
Thanks to the ggrastr package by Viktor Petukhov & Evan Biederstedt, it is now possible to rasterize individual layers. However, currently (2018-08-13), only geom_point and geom_tile are supported. and work by Teun van den Brand it is now possible to rasterize any individual ggplot layer by wrapping it in ggrastr::rasterise():
# install.packages('devtools')
# remotes::install_github('VPetukhov/ggrastr')
df %>% ggplot(aes(x=x, y=y)) +
# this layer will be rasterized:
ggrastr::rasterise(geom_point(size=0.1, alpha=0.1)) +
# this one will still be "vector":
geom_smooth()
Previously, only a few geoms were supported:
To use it, you had to replace geom_point by ggrastr::geom_point_rast.
For example:
# install.packages('devtools')
# devtools::install_github('VPetukhov/ggrastr')
library(ggplot2)
set.seed(1)
x <- rlnorm(10000, 4)
y <- 1+rpois(length(x), lambda = x/10+1/x)
z <- sample(letters[1:2], length(x), replace = TRUE)
ggplot(data.frame(x, y, z), aes(x=x, y=y)) +
facet_wrap("z") +
ggrastr::geom_point_rast(size=0.1, alpha=0.1) +
scale_x_log10() + scale_y_log10() +
geom_smooth(method="gam", formula = y ~ s(x, bs = "cs"))
ggsave("out.pdf")
This yields a pdf that contains only the geom_point layer as raster and everything else as vector graphic. Overall the figure looks as the one in the question, but zooming in reveals the difference:
Compare this to an all-raster graphic:
I think you've set yourself up to not have this question answered. You write:
I expect an answer to provide an extension to ggplot2 that allows to export plots with rasterized layers with minimal changes to to existing plotting commands, i.e. as wrapper for geom_... commands or as an additional parameter to these or a ggsave command that expects a list of unevaluated parts of a plot command (every second to be rasterized), not a hacky workaround as provided in the linked question.
This is a major development effort that could easily require several weeks or more of effort by a highly skilled developer. It's unlikely anybody will do this just because of a Stack Overflow question. In lieu of a functioning implementation, I'll describe here how one could implement what you're asking for and why it's rather challenging.
The players
Let's start with the key players we'll be dealing with. At the highest level sits the ggplot2 library. It takes data frames and turns them into figures. ggplot2 itself doesn't know anything about low-level drawing, though. It only deals with lines, polygons, text, etc., which it hands off to the grid library in the form of graphics objects (grobs).
The grid library itself is a fairly high-level library. It also doesn't know much about low-level drawing. It primarily deals with lines, polygons, text, etc., which it hands off to an R graphics device. The device does the actual drawing.
There are many different R graphics devices. Enter ?Devices in an R command line to see an incomplete list. There are vector-graphics devices, such as pdf, postscript, or svg, raster devices such as png, jpeg, or tiff, and interactive devices such as X11 or quartz. Obviously, rasterization as a concept only makes sense for vector-graphics devices, since raster devices raster everything anyways. Importantly, neither ggplot2 nor grid know or care which graphics device you're currently drawing on. They deal with graphical objects that can be drawn on any device.
Ideal high-level interface
The high-level interface should consist of an option rasterize in the layer() function of ggplot2. In this way, one could simply write, e.g., geom_point(rasterize = TRUE) to rasterize the points layer. This would work transparently for all geoms and stats, since they all call layer().
Possible implementations
I see four possible routes of implementation, ordered from most impossible to least.
1. Ideally, the layer() function would simply hand off the rasterize option to the grid library, which would hand it off to the graphics device to tell it which parts of the plot to rasterize. This approach would require major changes in the graphics device API. I don't see this happening. Not in my lifetime, at least.
2. Alternatively, one could write a new grob type that can take any arbitrary grob and rasterize it on demand when the grob is drawn on a graphics device. This approach would not require changes in the graphics device API, but it would require detailed knowledge of the low-level implementation of the grid library. It would also possibly make interactive viewing of such figures very slow.
3. A slightly simpler alternative to 2. would be to rasterize the arbitrary grob only once, on grob construction, and then reuse whenever that grob is drawn. This would be quite a bit faster on interactive graphics devices but the drawing would get distorted if the aspect ratio is changed interactively. Nevertheless, since the primary use of this functionality would be to generate pdf output (I assume), this option might be sufficient.
4. Finally, rasterization could also happen in the layer() function, and that function could simply place a regular raster grob into the grob tree. That solution is similar to the technique described here. Technically, it's not much different from 3. Either way, one needs to write code to rasterize a grob tree and then replace it by a raster grob.
Technical hurdles
To rasterize parts of the grob tree, we'd have to send them to an R raster graphics device to render. However, there isn't one that renders to memory. So, one would have to render to a temporary file (e.g., using png()), and then read the file back in. That's possible but ugly. It also depends on functionality (such as png()) that isn't guaranteed to be available on every R installation.
Second, to render parts of the grob tree separately from the overall rendering, we'll have to open a new graphics device in addition to the one currently open. That's possible but can lead to unexpected bugs. I'm dealing with such bugs all the time, see e.g. here or here for issues related to code using this technique. Whoever implements the rasterization functionality would have to deal with such issues.
Finally, we'll have to get the rasterization code accepted into the ggplot2 library, since we need to replace the layer() function and I don't think there's a way to do that from a separate package. Given how hackish the rasterization solutions are going to be (see previous two paragraphs), that may be a tall order.

Where do the values for the graphical parameters in R come from?

Both base graphics in R and the ggplot2 package use the same encodings for different shapes and line types. See here for the shapes and here for the line types.
These encoding systems seem very arbitrary to me, and thus I find them very difficult to remember or understand. In particular, since ggplot2 is all about an explicit philosophy of "grammar of graphics" it is somewhat surprising to me that it would continue the use of such arbitrary encoding systems from base R graphics.
Question: What is the reason or motivation for these encodings?
Or if there is none, then what is the historical source for them? E.g. why should '2' be an empty triangle instead of a solid circle?
The R documentation for the points() function indicates that some of the conventions are based on those used in the S language. But that only raises two questions (1) where did S get those conventions from, and (2) where did the remaining R conventions come from?
From the S+ Documentation:
pch="c" the character to be used for plotting points. If pch is a period, a centered plotting dot is used.
pch=n the number of a plotting symbol to be drawn when plotting points. Basic marks are: square (0); octagon (1); triangle (2); cross (3); X (4); diamond (5) and inverted triangle (6). To get superimposed versions of the above use the following arithmetic(!): 7==0+4; 8==3+4; 9==3+5; 10==1+3; 11==2+6; 12==0+3; 13==1+4; 14==0+2. Filled marks are square (15), octagon (16), triangle (17), and diamond (18). Use the mkh graphics parameter to control the size of these marks. See the EXAMPLES section for a display of the plotting symbols. Using the numbers 32 through 126 for pch yields the 95 ASCII characters from space through tilde (see the SPLUS data set font). The numbers between 161 and 252 yield characters, accents, ligatures, or nothing, depending on the font (which is device dependent).
https://www.uni-muenster.de/ZIV.BennoSueselbeck/s-html/helpfiles/par.html

plot every tick on axis[SAS]

I have dataset include about 100 observations, say all of them are in (x,y) format, all of y is in integer format. I need proc sgplot to make a graphic about them. The range about my y is from 1 to 150. I hope I can force the graphic to show every corresponding y value on the y-axis instead of automatically reducing the ticks to a small number in order to show them clearly. For example, if the first five value of my y is (1,3,4,6,7,....), I hope the y tick shows exactly (1,3,4,6,7,....) instead (1,5,...).
I tried
yaxis value=(1 to 150 by 1) valueshint display=all;
It does not work as maybe I have too many observations. I know the result maybe overwhelming, but I just want to see the result. Thanks.
You don't say if you're using SAS/GRAPH or ODS GRAPHICS (SGPLOT etc.), so I'll answer the latter which is what I know; the answer should be useful for both in concept.
You likely cannot get SAS to plot so much on the axis unless the axis is very large itself. This means you have two options.
Raise the size of the graphic produced a lot in terms of pixels(and then shrink that to a usable size via image physical size, or using an external tool). Not necessarily usable in all cases, but produces a very high resolution plot (which is very big size-wise). This page explains how to do that for ODS graphics (use image_dpi as a high number, and width and height in inches as a normal number), and this page explains for SAS/GRAPH. You may need to make your font small to make it work (if you're adding numbers, which I assume you are), or you may need to make an initially large plot first and then go into paint/photoshop/gimp/etc. and make it smaller.
Use annotate to create the axis marks. This is fairly easy if you know how to use annotate, as you're just writing to the location of the axis (y) and the item (x), and then a bit below that for the text. This will make it very easy to make a total garbage plot, but it will likely work ultimately.
These likely work in both SAS/GRAPH and ODS GRAPHICS, and I can't test either as you don't post any code or simulated data to test with, but I think both approaches have some merit (as does the approach of "don't do this", but you've thought that through).

Export graphics from R in vector format

I'd like to export graphics from R (for example, histograms and ROC curves) in vector format in order to make layout edits in a graphic design program like Intaglio. Is this possible?
pdf("myfile.pdf")
# graph goes here
dev.off()
Other devices (besides PDF) exist as well. (#Justin points out what is probably the most useful one in a comment).

Is there an interactive output device to view 3D graphs in R?

I'm currently generating 3D graphs in R using the persp-command. To change the viewpoint one has to set the parameters theta and phi. To evaluate (a good viewpoint on) the graph, one has to try lots of combinations for these parameters.
I was wondering if one can define an interactive output device that allows to rotate the graph using the mouse. It would be also nice if this device gives the current values for theta and phi.
Is there such a device/package?
See the rgl package: http://cran.r-project.org/web/packages/rgl/index.html
It won't report the theta and phi values you need, IIRC (though see #Dieter's comment below for a solution to this), but you can use rgl.snapshot() or rgl.postscript() to grab the current display as a bitmap or vector image. The package has persp3d() which is very similar to persp().
See the package rggobi http://cran.r-project.org/web/packages/rggobi/index.html
For data visualisation in 3 or even more dimensions, try the package rggobi which makes use of the program ggobi. It is possible to manipulate the data using the mouse, "brush" data, identify points in the data all while visualizing in a number of dimensions.

Resources