Creating Custom Plots

library(rbcmodel)
#basic plot
Rbc_wheat <- Enzyme("aestivum_Iñiguez_2021",enzyme_name="wheat")
wheat_DH<-DHScale("aestivum_orr_2016_dH",data="abridged")
wheat_DH<-modify_DHScale(wheat_DH,Ko_dH=26.7)
wheat_carbon<-CO2_dependence(Rbc_wheat,wheat_DH)
CO2_seq<-O2_seq<-seq(0,1000,by=10)
temp_seq<-seq(0,40,by=.1)
wheat_grid<-make_4D_grid(wheat_carbon,CO2_seq,O2_seq,temp_seq,var_names=c("CO2","O2","T","wheat"))
s1<-slice_4D_grid(wheat_grid,dim=3,25)
s2<-slice_4D_grid(wheat_grid,dim=2,300)

Overview

This vignette walks through more of the ways to customize the plot_slice_3D() graphs created by rbcmodel. The basic plot workflow is discussed in the introductory vignette. Here, we start with a description of all of the plot_slice_3D() arguments. We then discuss how to customize labels for the plot, change the color palette, and add other elements using the base R plot functions. Finally, we include a description of permute_4D_grid(), a utility function to change the 4D grid created by make_4D_grid() in anticipation of slicing and plotting.

1. plot_slice_3D() arguments

For customization, plot_slice_3D() accepts the following named arguments. When the default is NULL, any default response from the function is listed in parentheses next to it. Furthermore, additional arguments whose name does not match the list will be passed to the image2D() function in the package plot3D used under the hood.

Argument Description Default Accepted Inputs
grid_slice The 3D slice to plot (required) Any 3D slice created from slice_4D_grid() or transpose_3D_slice()
contours The values of the contour lines to be drawn NULL (no contours) Any vector of values
contour_col The color used for contours "black" Any color word or hex code
lwd Contour line width 2 Any number
dims Specification of which element of the grid is the horizontal, vertical, and contour/color variables of the plot NULL (auto-detects)* Integer vector, length 3. e.g., c(1,2,4)
cmin The minimum value of the color scale NULL (min(z)) Any number
cmax The maximum value of the color scale NULL (max(z)) Any number
colors The color scale used "default" Any list of hex codes
NA_col The color used for NA values "grey" Any color word or hex code
xlabel The label for the x-axis "" Any string
ylabel The label for the y-axis "" Any string
clabel The label for the color scale c("Carbon", "(C/s)") Any string

*The function will attempt to automatically determine which variable should be the horizontal and the vertical values, and assume that the last element of the grid is the contour/color variable. If this is not successful, dims can be specified like so: c(1,3,4).

2. Changing labels

plot_slice_3D() uses the same formatting constraints as the base R plot() function for labels, so some tricks used in other plotting packages (such as ggplot2) to get subscripts, superscripts, Greek letters, etc. may not work in plot_slice_3D(). We recommend using the Unicode characters for degree symbols. To make a subscript or superscript, you can use the base R function expression() to create them. Greek letters can also be created using expression(). Below, we provide an example of a CO2 vs. T plot that includes formatted labels that you can use:

plot_slice_3D(s2,contours=c(2,4,6,8),xlabel=expression(CO[2]~(μM)),ylabel="T (°C)")

#plot_slice_3D(s2,contours=c(2,4,6,8),xlabel=expression(CO[2]~(mu*M)),ylabel="T (°C)") will create mu just as easily.

3. Creating a custom color palette

We have provided an automatic color palette (red for positive values, white at 0, blue for negative values) for all plot_slice_3D() graphs. Pure red ("#ff0000") is used for the maximum value of the color scale, and pure blue ("#0000ff") is used for the minimum value of the color scale. To adjust the color scale boundaries, you can use the arguments cmin and cmax. Any values that are present on the graph that do not fall within that range will end up the color specified by NA_col, which be default is "grey".

plot_slice_3D(s1,contours=c(1.5,2,2.5),xlabel=expression(CO[2]~(μM)),ylabel=expression(O[2]~(μM)))

plot_slice_3D(s1,contours=c(1.5,2,2.5),xlabel=expression(CO[2]~(μM)),ylabel=expression(O[2]~(μM)), cmax=5)

Alternatively, you can specify your own color palette from scratch using colors. This should be a list of many hex code values, and can be created using functions like ramp.col() from the plot3D package, a dependency of rbcmodel.

green_ex<-plot3D::ramp.col(c("white","green"),n=125)
#print color scale for visualization of data structure
green_ex
#>   [1] "#FFFFFFFF" "#FCFFFCFF" "#FAFFFAFF" "#F8FFF8FF" "#F6FFF6FF" "#F4FFF4FF"
#>   [7] "#F2FFF2FF" "#F0FFF0FF" "#EEFFEEFF" "#ECFFECFF" "#EAFFEAFF" "#E8FFE8FF"
#>  [13] "#E6FFE6FF" "#E4FFE4FF" "#E2FFE2FF" "#E0FFE0FF" "#DEFFDEFF" "#DCFFDCFF"
#>  [19] "#D9FFD9FF" "#D7FFD7FF" "#D5FFD5FF" "#D3FFD3FF" "#D1FFD1FF" "#CFFFCFFF"
#>  [25] "#CDFFCDFF" "#CBFFCBFF" "#C9FFC9FF" "#C7FFC7FF" "#C5FFC5FF" "#C3FFC3FF"
#>  [31] "#C1FFC1FF" "#BFFFBFFF" "#BDFFBDFF" "#BBFFBBFF" "#B9FFB9FF" "#B7FFB7FF"
#>  [37] "#B4FFB4FF" "#B2FFB2FF" "#B0FFB0FF" "#AEFFAEFF" "#ACFFACFF" "#AAFFAAFF"
#>  [43] "#A8FFA8FF" "#A6FFA6FF" "#A4FFA4FF" "#A2FFA2FF" "#A0FFA0FF" "#9EFF9EFF"
#>  [49] "#9CFF9CFF" "#9AFF9AFF" "#98FF98FF" "#96FF96FF" "#94FF94FF" "#92FF92FF"
#>  [55] "#8FFF8FFF" "#8DFF8DFF" "#8BFF8BFF" "#89FF89FF" "#87FF87FF" "#85FF85FF"
#>  [61] "#83FF83FF" "#81FF81FF" "#7FFF7FFF" "#7DFF7DFF" "#7BFF7BFF" "#79FF79FF"
#>  [67] "#77FF77FF" "#75FF75FF" "#73FF73FF" "#71FF71FF" "#6FFF6FFF" "#6CFF6CFF"
#>  [73] "#6AFF6AFF" "#68FF68FF" "#66FF66FF" "#64FF64FF" "#62FF62FF" "#60FF60FF"
#>  [79] "#5EFF5EFF" "#5CFF5CFF" "#5AFF5AFF" "#58FF58FF" "#56FF56FF" "#54FF54FF"
#>  [85] "#52FF52FF" "#50FF50FF" "#4EFF4EFF" "#4CFF4CFF" "#4AFF4AFF" "#47FF47FF"
#>  [91] "#45FF45FF" "#43FF43FF" "#41FF41FF" "#3FFF3FFF" "#3DFF3DFF" "#3BFF3BFF"
#>  [97] "#39FF39FF" "#37FF37FF" "#35FF35FF" "#33FF33FF" "#31FF31FF" "#2FFF2FFF"
#> [103] "#2DFF2DFF" "#2BFF2BFF" "#29FF29FF" "#27FF27FF" "#25FF25FF" "#22FF22FF"
#> [109] "#20FF20FF" "#1EFF1EFF" "#1CFF1CFF" "#1AFF1AFF" "#18FF18FF" "#16FF16FF"
#> [115] "#14FF14FF" "#12FF12FF" "#10FF10FF" "#0EFF0EFF" "#0CFF0CFF" "#0AFF0AFF"
#> [121] "#08FF08FF" "#06FF06FF" "#04FF04FF" "#02FF02FF" "#00FF00FF"
plot_slice_3D(s1,contours=c(1.5,2,2.5),xlabel=expression(CO[2]~(μM)),ylabel=expression(O[2]~(μM)),colors=green_ex)

4. Adding elements to the graph

Because plot_slice_3D() is based on the base R plot functions, any of the base R plot functions can be combined with the graph created by plot_slice_3D(). To start, plot_slice_3D() passes on any unused variables to plot3D::image2D() and from there to plot():

#passing an unused variable to image2D()
plot_slice_3D(s1,contours=c(1.5,2,2.5),xlabel=expression(CO[2]~(μM)),ylabel=expression(O[2]~(μM)),rasterImage=TRUE)

Adding a title is as simple as invoking title() after plot_slice_3D():

plot_slice_3D(s1,contours=c(1.5,2,2.5),xlabel=expression(CO[2]~(μM)),ylabel=expression(O[2]~(μM)))
title("My title")

It is also possible to add points, horizontal/vertical lines, and other shapes as you would with any base R plot. In this example, we will add a horizontal line at 300μM O2:

plot_slice_3D(s1,contours=c(1.5,2,2.5),xlabel=expression(CO[2]~(μM)),ylabel=expression(O[2]~(μM)))
abline(h=300)

5. permute_4D_grid()

In the introduction, we described a workflow that starts with make_4D_grid(), followed by slice_4D_grid() and possibly transpose_3D_slice(), before visualizing via plot_slice_3D(). Occasionally, we may want the axes of multiple plots to be transposed. For example, we may want to produce plots of CO2 versus temperature and O2 versus temperature, both of which with temperature on the x-axis. In such case it may be more convenient to permute the 4D grid so that temperature becomes the first variable. This can be achieved using the permute_4D_grid() function:

g2 <- permute_4D_grid(wheat_grid, c(3, 1, 2))
names(g2)
#> [1] "T"     "CO2"   "O2"    "wheat"

Now we can make two slices and plot:

s3 <- slice_4D_grid(g2, dim=2, val=500)
plot_slice_3D(s3, contours=c(2, 4, 6),xlabel=expression("T (°C)"),ylabel=expression(O[2]~(μM)))

s3 <- slice_4D_grid(g2, dim=3, val=500)
plot_slice_3D(s3, contours=c(2, 4, 6), xlabel=expression("T (°C)"), ylabel=expression(CO[2]~(μM)))

Compare this with the workflow described in the introduction, where 2 separate transpose_3D_slice() calls would be needed.