When I started using R, one of the first things I wanted to do is make reliable colourplots. Colourplots are a way of representing 3D data as a 2D image, with the x and y coordinates representing variables and the z values represented as a colour.
For simple colorplots, the
image() function from the
base package, and the
image.plot() function from the
fields package are excellent choices. However, in my work, there is often a need to plot non-rectangular datasets, and this can become problematic.
The most common way around this, and the method used in graphing packages like Origin, is to interpolate a non-rectangular dataset to a rectangular grid. The result of this method can be seen in R too, using the
disp.plot() function from my
For this example, I’ll be using the example dataset for a surface plasmon dispersion diagram available in the
wavelength angle reflection 1 4.00e-07 7 0.4687 2 4.02e-07 7 0.4734 3 4.04e-07 7 0.4413 4 4.06e-07 7 0.4499 5 4.08e-07 7 0.4469 6 4.10e-07 7 0.4604
This is a standard rectangular dataset with reflection from a sample (in this case a zigzag grating) measured as a function of equally spaced steps of wavelength of the illuminating light and polar angle.
If we were to plot this as a non-rectangular dataset (such as a dispersion plot) using the method of interpolation to a rectangular grid, it would look like this:
angle <- SPPdispersion$angle wavelength <- SPPdispersion$wavelength reflection <- SPPdispersion$reflection kx <- (2 * pi/wavelength) * sin(angle * pi/180) omega <- 2 * pi * 3e+08/wavelength disp.plot(kx, omega, reflection)
- There is a horrible jagged edge to the dataset.
- There are missing values from poor interpolation.
- Overall resolution of the data has been lost due to interpolation.
The solution to all these problems is to plot the data as a non-rectangular dataset, with each element in the plot not being required to be the same shape, and certainly not requiring them to be square. We are going to fill the space using arbitrary trapezia, coloured based on the central value for that (x,y) coordinate.
The function we use for this is the
disp.plot3() function from
disp.plot3(x = wavelength, y = angle, z = reflection, fx = kx, fy = omega)
This is already far better. Absolutley no resolution from the dataset has been lost, and no values are missing. There is also no horrible jagged edge.
disp.plot3 the original and transformed datasets have to be specified. See
?disp.plot3 for more details.
Finally, we can take the best of both worlds and use a function that interpolates the rectangular dataset, and then transforms and plots using non-rectangular elements. The function for this is, again, in
photonMonkey and is called
disp.plot4. This function works a little differently, as now the transformed coordinates must be supplied as functions.
wavelength<-wavelength*1e9 kx<-function(x,y) (2*pi/(x*1e-9))*sin(y*pi/180) omega<-function(x,y) 2*pi*3e8/(x*1e-9) disp.plot4(x=wavelength,y=angle,z=reflection, fx=kx,fy=omega,nx=300,ny=300)
Note, for the interpolation to work we needed to make the x and y scales similar. See
?disp.plot4 for details.
We can now use the utility functions in
photonMonkey to tart this plot up nicely,
library(scales) disp.plot4(x=wavelength,y=angle,z=reflection, fx=kx,fy=omega,nx=300,ny=300, xlab=label_in_plane_wavevector(), ylab=label_angular_frequency(), xaxt='n',yaxt='n') lines(c(0,0),c(0,0)) # This is a silly work-a-round for a bug in R. axis(1,at=axTicks(1),labels=label_scientific10(axTicks(1))) axis(2,at=axTicks(2),labels=label_scientific10(axTicks(2))) add.diffraction(kgx=2*pi/600e-9,kgv=2*pi/150e-9)
This isn’t just for dispersion plots, any functions can be used. disp.plot3 or 4 are also a great options for polar colourplots:
px<-function(x,y) x*sin(y*pi/180) py<-function(x,y) x*cos(y*pi/180) disp.plot4(x=wavelength,y=angle,z=reflection, fx=px,fy=py,nx=300,ny=300,asp=1)