Phyllotaxis @Datacamp

UPDATE: Given Datacamp’s catastrophic handling in the case of one of their managers sexual harassement of one of their employees, I would strongly advise against supporting this company any longer.


However, since I am still very thankful to the author of Phyllotaxis for what I have learned, I will leave this post as it is. I am optimistic, that in the future many authors will be much less willing to contribute to such a company but instead choose other (perhaps even non-commercial) platforms for sharing their knowledge.

I recently came across a tweet pointing me to the free Phyllotaxis-course at Data camp:

I took these examples from https://www.datacamp.com/projects/62.

Task 1: Patterns in nature

# This sets plot images to a nice size.
options(repr.plot.width = 4, repr.plot.height = 4)

# Loading in the ggplot2 package
library(tidyverse)
## ── Attaching packages ───────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 3.1.0       ✔ purrr   0.3.2  
## ✔ tibble  2.1.1       ✔ dplyr   0.8.0.1
## ✔ tidyr   0.8.3       ✔ stringr 1.4.0  
## ✔ readr   1.3.1       ✔ forcats 0.4.0
## ── Conflicts ──────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()

Task 2: Warming up: drawing points on a circle

t <- seq(0, 2*pi, length.out = 50)
x <- sin(t)
y <- cos(t)
df <- data.frame(t, x, y)

# Make a scatter plot of points in a circle
p <- ggplot(df, aes(x, y))
p + geom_point()

Task 3: Make it harmonious with the Golden Angle

# Defining the number of points
points <- 500

# Defining the Golden Angle
angle <- pi*(3-sqrt(5))

t <- (1:points) * angle
x <- sin(t)
y <-cos(t)
df <- data.frame(t, x, y)

# Make a scatter plot of points in a spiral
p <- ggplot(df, aes(x*t, y*t))
p + geom_point()

Task 4: Remove everything unnecessary

p + geom_point() + theme(panel.grid=element_blank(), 
                         axis.ticks=element_blank(), 
                         axis.text=element_blank(), 
                         axis.title=element_blank(), 
                         panel.background =element_rect(fill="white"))

Task 5: A bit of makeup: size, color and transparency¶

p + geom_point(colour="dark green", size = 5, alpha = 0.5) + theme(panel.grid=element_blank(), 
                         axis.ticks=element_blank(), 
                         axis.text=element_blank(), 
                         axis.title=element_blank(), 
                         panel.background =element_rect(fill="white")) 

Task 6: Play with aesthetics: the dandelion

ggplot(df, aes(x*t, y*t, size=t)) + geom_point(shape="*", colour="black", alpha = 0.5) + theme(panel.grid=element_blank(), 
                         axis.ticks=element_blank(), 
                         axis.text=element_blank(), 
                         axis.title=element_blank(), 
                         panel.background =element_rect(fill="white"), legend.position="none")

Task 7: Put all it together: the sunflower

ggplot(df, aes(x*t, y*t, size=t)) + geom_point(shape=17, colour="yellow", alpha = 0.5) + theme(panel.grid=element_blank(), 
                         axis.ticks=element_blank(), 
                         axis.text=element_blank(), 
                         axis.title=element_blank(), 
                         panel.background =element_rect(fill="darkmagenta"), legend.position="none")

Task 8: What if you modify the angle?

angle <- pi*(3-sqrt(5))
angle2 <- 2
angle3 <- 3
points <- 1000

t <- (1:points)*angle
t2 <- (1:points)*angle2
t3 <- (1:points)*angle3
x <- sin(t)
y <- cos(t)

df <- data.frame(t, t2, t3, x, y)

p <- ggplot(df, aes(x*t, y*t3))
p + geom_point(shape=17, aes(size=t), data = df,  colour="yellow", alpha = 0.5) + theme(panel.grid=element_blank(), 
                         axis.ticks=element_blank(), 
                         axis.text=element_blank(), 
                         axis.title=element_blank(), 
                         panel.background =element_rect(fill="darkmagenta"), legend.position="none")

Task 9: All together now: imaginary flowers

angle <- pi*(3-sqrt(5))
angle2 <- 2
angle3 <- 3
points <- 1000

t <- (1:points)*angle
t2 <- (1:points)*angle2
t3 <- (1:points)*angle3
x <- sin(t)
y <- cos(t)

df <- data.frame(t, t2, t3, x, y)

p <- ggplot(df, aes(x*t, y*t3))
p + geom_vline(xintercept = 0, col = "dark green") + geom_point(data = data.frame(x = 0, y = seq(0,6000, 100)), 
                                                                aes(x, y), size=12, colour="light blue") + 
  geom_point(data = data.frame(x = c(seq(-4900, 4900, 180)), y = rnorm(length(c(seq(-4900, 4900, 180))), mean=-24000, sd = 2000)), 
             aes(x, y), size=22, shape="l", colour="dark green") + 
  geom_point(data = data.frame(x = sample(-5000:5000, size=100), y = sample(-5000:-3000, size=100)),
             aes(x, y), colour="light green", size = sample(1:8, size=100, replace = TRUE), alpha = 0.8)+ 
  geom_point(data = data.frame(x = sample(-5000:5000, size=100), y = sample(-5000:-3000, size=100)), 
             aes(x, y), colour="dark green", size = sample(1:8, size=100, replace = TRUE), alpha = 0.5) + 
  geom_point(shape="*", colour="black", alpha = 0.2)+ 
  geom_point(data = data.frame(x = c(seq(-5000, 5000, 150)), y = rnorm(length(c(seq(-5000, 5000, 150))), mean=-20000, sd = 1000)), 
             aes(x, y), size=18, shape="l", colour="green")+ 
  geom_point(data = data.frame(x = sample(-5000:5000, size=100), y = sample(-5000:-3000, size=100)),
             aes(x, y), colour="dark green", size = sample(1:8, size=100, replace = TRUE), alpha = 0.5) + 
  geom_point(shape="*", colour="black", alpha = 0.2) + 
  geom_point(data = data.frame(x = c(seq(-5000, 5000, 150)), y = rnorm(length(c(seq(-5000, 5000, 150))), mean=-4000, sd = 1000)), 
             aes(x, y), size=19, shape="l", colour="green") +
  geom_point(data = data.frame(x = c(seq(-4900, 4900, 280)), y = rnorm(length(c(seq(-4900, 4900, 280))), mean=-4000, sd = 200)), 
             aes(x, y), size=26, shape="r", colour="dark green")+ 
  geom_point(shape=17, aes(size=t), data = df,  colour="yellow", alpha = 0.5) + theme(panel.grid=element_blank(), 
                         axis.ticks=element_blank(), 
                         axis.text=element_blank(), 
                         axis.title=element_blank(), 
                         panel.background =element_rect(fill="light blue"), legend.position="none") + 
  geom_point(shape="*", colour="black", alpha = 0.2) + 
  coord_cartesian(xlim = c(-5000,5000), ylim = c(-5000, 3000)) +
  geom_point(data = data.frame(x = sample(-5000:5000, size=100), y = sample(-25000:-10000, size=100)), 
             aes(x, y), colour="light green", size = sample(1:8, size=100, replace = TRUE), alpha = 0.8) + 
  geom_point(data = data.frame(x = sample(-5000:5000, size=100), y = sample(-5000:-2000, size=100)), 
             aes(x, y), colour="dark green", size = sample(1:8, size=100, replace = TRUE), alpha = 0.5)  

Special Task: gganimate

library(emojifont)
load.fontawesome()
angle <- pi*(3-sqrt(5))
points <- 1000
t <- (1:points)*angle
x <- sin(t)
y <- cos(t) 

bloom <-data.frame(t, x, y)
grass <- data.frame(x = rep(sample(-5000:5000, size=100),2),  
                    y = c(rep(-5000, 100), sample(-5000:-2500, size=100)),
                    id = rep(1:100, 2))  
grass$x <- grass$x + (round(runif(200)*1000)-500)
grass$y <- ifelse(grass$y==-5000,-5000, (grass$y-round(rnorm(100, mean =0, sd=10))))

grass  <- grass[order(grass$id),]
grass$t <- rnorm(200, mean =10, sd=2) *  rep(dnorm(c(0.0001, 0.001, 0.01,0.05, 0.1, 0.5, 0.8, 0.99, 2, 10)), 20)

# bloom$y <- bloom$y
grass_in <- grass
bloom_in <- bloom
grass$time  <- 1
bloom$time  <- 1
bloom$x  <- bloom$x/10
bloom$y  <- bloom$y/10
for (i in 2:10){
  grass  <- rbind(grass, cbind(x=ifelse(grass_in$y != -5000, grass_in$x  + (round(runif(200)*1000)-500),  
                                        grass_in$x),
                               y = grass_in$y,  id = grass_in$id, t =grass_in$t, time = i))
  bloom <- rbind(bloom, cbind(x = bloom_in$x*(i/10), y = bloom_in$y*(i/10), t =bloom_in$t, time = i))
}

grass$y  <- ifelse(grass$y==-5000, -5000, grass$y/grass$time)

any(is.na(grass))
## [1] FALSE
library(gganimate)
library(RColorBrewer)

grass$z  <- 1+ifelse(!duplicated(grass$id), 1, (round(runif(nrow(grass))*5)*grass$time))
bloom$z  <- bloom$time + (round(runif(nrow(grass))*10)-5)

p <- ggplot(bloom, aes(x*t, y*t, size=t))
p <- p + 
 geom_point( 
    aes(x, y, colour=runif(10000, min=1, max=100), alpha = t/10), size=18, data = data.frame(x=-4999:5000, 
                                                                              y=rnorm(10000, mean=-4000, sd=300), t = 
                          sample(5:50, size=10000, replace = TRUE))) + 
  geom_point( 
    aes(x, y, size=t, colour=runif(10000, min=1, max=100)), data = data.frame(x=-4999:5000, 
                                                                              y=rnorm(10000, mean=-3000, sd=200), t = 
                                                                                sample(5:50, size=10000, replace = TRUE))) +
  geom_point(aes(x, y, size=t), data = data.frame(x=seq(-4999,5000,10), y=rnorm(1000, mean=-5000, sd=100), t = 
                                                    sample(5:50, size=1000,  replace = TRUE)),fill="#ffffd4") +
  geom_point(aes(x, y, size=t), data = data.frame(x=seq(-4999,5000,10), y=rnorm(1000, mean=-5050, sd=150), t = 
                                                    sample(5:50, size=1000,  replace = TRUE)),fill="#fe9929") +
  geom_point(aes(x, y, size=t), data = data.frame(x=seq(-4999,5000,10), y=rnorm(1000, mean=-5100, sd=200), t = 
                                                    sample(5:50, size=1000,  replace = TRUE)),fill="#993404") +
  geom_path(data = grass, aes(x,y,group = id,  colour=runif(2000, min=1, max=100),
                            alpha= t/10,  size = max(z)), lineend = "round") +
  geom_path(data = grass,
          aes(x, y,  size = (z*id)/2,  group = id), colour="dark green", lineend = "round")+
  geom_vline(xintercept = 0, col = "#294209", alpha = 0.2, size = 12) +
  geom_vline(xintercept = 0, col = "#515e40", size = 8) +
  geom_point(aes(x,y), data = data.frame(x = 0, 
                               y = seq(5, 5000, 5)), size=20, colour="light blue") + 
  geom_point(data=bloom, aes(x*t, y*t, size=t), shape=17, colour="yellow") +
  geom_point(shape="*", colour="black", alpha = 0.2) + 
  theme(panel.grid=element_blank(), axis.ticks=element_blank(), axis.text=element_blank(), 
        axis.title=element_blank(), panel.background =element_rect(fill="light blue"),
        legend.position="none") +  
  scale_colour_gradient(low="#577538", high="#A7B473") +
  coord_cartesian(xlim = c(-5000,5000), ylim = c(-5000, 3000)) +
  geom_emoji("frog", color="#755e50", x = -3000, y = -4800, size = 5) +
  geom_emoji("frog", color="#fc8841", x =  3000, y = -4800, size = 5) +
  transition_time(time) +
  ease_aes('linear') + 
enter_fade() + enter_grow() +
exit_fly(x_loc = 3000, y_loc = -5000) + exit_recolour(fill = 'forestgreen')

  
 animate(p, 100, 10)

Johannes Johow
(Dr. rer. nat., Dipl.-Biol.)