---
title: "Curves, Surfaces, and Colors"
author: "Statistical Computing, 36-350"
date: "Friday September 23, 2016"
---

Drawing a curve
===

To draw a curve of a function, use `curve()`

```{r}
curve(x^3) # Default is to plot between 0 and 1
curve(x^3, from=-3, to=3)
curve(x^3, from=-3, to=3, lwd=3, col="red")
```

Adding a curve to an existing plot
===

To add a curve to an existing plot, use `curve()` with `add=TRUE`

```{r}
n = 50
set.seed(0)
x = sort(runif(n, min=-2, max=2))
y = x^3 + rnorm(n)
plot(x, y)
curve(x^3, lwd=3, col="red", add=TRUE) # Note: the x argument here and the x vector we defined above are different!
```

Adding a rug to an existing plot
===

To add a rug to an existing plot (just tick marks, for where the x points occur), use `rug()`

```{r}
plot(x, y)
curve(x^3, lwd=3, col="red", add=TRUE) 
rug(x)
```

Drawing a surface
===

To draw a surface, use `surface()`, available at http://www.stat.cmu.edu/~ryantibs/statcomp-F16/surface.R. (This is a function written by your instructor, relying on the built-in `persp()` function)

```{r}
source("http://www.stat.cmu.edu/~ryantibs/statcomp-F16/surface.R")
surface(x^3 + y^3)
surface(x^3 + y^3, from.x=-3, to.x=3, from.y=-3, to.y=3)
surface(x^3 + y^3, from.x=-3, to.x=3, from.y=-3, to.y=3,
        theta=25, phi=15, col=terrain.colors(30), 
        ticktype="detailed", mar=c(2,2,2,2))
```

Adding points to a surface
===

To add points to a surface, save the output of `surface()`. Then use `trans3d()`, to transform (x,y,z) coordinates to (x,y) coordinates that you can pass to `points()`

```{r}
persp.mat = surface(x^3 + y^3, from.x=-3, to.x=3, from.y=-3, to.y=3,
                    theta=25, phi=15, col=rgb(0,0,1,alpha=0.2),
                    ticktype="detailed", mar=c(2,2,2,2))

n = 500
x = runif(n, -3, 3)
y = runif(n, -3, 3)
z = x^3 + y^3 + 5*rnorm(n)

xy.list = trans3d(x, y, z, persp.mat)
points(xy.list, pch=19)
```

Color palettes
===

Color palettes are functions for creating vectors of contiguous colors, like `gray.colors()`, `rainbow()`, `heat.colors()`, `terrain.colors()`, `topo.colors()`, `cm.colors()`. Given a number n, each of these functions just returns a vector of colors (names, stored as strings) of length n

```{r}
n = 50
plot(0, 0, type="n", xlim=c(1,n), ylim=c(1,6))
points(1:n, rep(1,n), col=gray.colors(n), pch=19)
points(1:n, rep(2,n), col=rainbow(n), pch=19)
points(1:n, rep(3,n), col=heat.colors(n), pch=19)
points(1:n, rep(4,n), col=terrain.colors(n), pch=19)
points(1:n, rep(5,n), col=topo.colors(n), pch=19)
points(1:n, rep(6,n), col=cm.colors(n), pch=19)
```

Creating a custom color palette
===

To create a custom palette, that interpolates between a set of base colors, `colorRampPalette()`

```{r}
cust.colors = colorRampPalette(c("red","purple","darkgreen"))
class(cust.colors)
plot(1:n, rep(1,n), col=cust.colors(n), pch=19)
```

Coloring points by value 
===

Coloring points according to the value of some variable can just be done with a bit of indexing, and the tools you already know about colors

```{r}
# Function to retrieve a color according to a value
# - val: the value in question
# - lim: a vector of length 2, lower and upper limits for possible values
# - col.vec: the color vector to choose from
get.col.from.val = function(val, lim, col.vec) {
  col.vec[(val-lim[1])/(lim[2]-lim[1]) * (length(col.vec)-1) + 1]
}

# Let's color points according to y value
col.vec = heat.colors(30)
lim = c(-1, 1)
theta = seq(0, 6*pi, length=200)

plot(theta, sin(theta), type="o", pch=19, 
     col=get.col.from.val(sin(theta), lim, col.vec))
```

Another example
===

```{r}
persp.mat = surface(x^3 + y^3, from.x=-3, to.x=3, from.y=-3, to.y=3,
                    theta=25, phi=15, col=rgb(1,1,1,alpha=0.2),
                    ticktype="detailed", mar=c(2,2,2,2))

# Let's color points according to z value
col.vec = terrain.colors(30)
lim = c(min(z), max(z))

xy.list = trans3d(x, y, z, persp.mat)
points(xy.list, pch=19, col=get.col.from.val(z, lim, col.vec))
```

Another example
===

```{r}
# Let's color points according to z value, on a 2d plot
# (this is kind of like a handmade heatmap)
plot(x, y, pch=19, col=get.col.from.val(z, lim, col.vec))
```