## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

## ----setup--------------------------------------------------------------------
library(musicMCT)

## -----------------------------------------------------------------------------
tc(c(0, 2, 4, 5), c(0, 7))

## -----------------------------------------------------------------------------
scale_from_genus <- function(genus) {
 sd2 <- genus[1]
 sd3 <- genus[2]
 if (sd2 > sd3) {
   return(NA)
 }
 tc(c(0, sd2, sd3, 5), c(0, 7))
}

## ----out.width = '75%', echo = FALSE------------------------------------------
knitr::include_graphics("img/vhd_plane_embedding.png")

## ----fig.width=5, fig.height=5, fig.fullwidth=TRUE----------------------------
ionian <- scale_from_genus(c(2, 4)) #1
dorian <- scale_from_genus(c(2, 3)) #2
phrygian <- scale_from_genus(c(1, 3)) #3
double_harmonic <- scale_from_genus(c(1, 4)) #4
enharmonic <- scale_from_genus(c(.5, 1)) #5

demo_scales <- cbind(ionian, dorian, phrygian, double_harmonic, enharmonic)

## ----fig.width=5, fig.height=5, fig.fullwidth=TRUE----------------------------
tetra_plot <- function(scales, title, ...) {
  oldpar <- par(bg='aliceblue')
  on.exit(par(oldpar))

  plot(scales[2, ], 
       scales[3, ], 
       xlab="Height of scale degree 2", xlim=c(-.05, 5.05),
       ylab="Height of scale degree 3", ylim=c(-.01, 5.01),
       ...)
  grid(col="gray35")
  mtext(side=3, title, font=2, line=1)
}
tetra_plot(demo_scales, 
           "Location of 5 Reference Scales in the tc() Plane",
           pch=sapply(1:5, toString)) 

## ----fig.width=5, fig.height=5, fig.fullwidth=TRUE----------------------------
# Invert the original enharmonic scale:
inverted_enharmonic <- tni(enharmonic, 0)

# Define a new enharmonic scale based on where we expect to plot it:
new_enharmonic <- scale_from_genus(c(4, 4.5))

# The two are the same:
rbind(inverted_enharmonic, new_enharmonic)

# Let's plot them:
demo_scales <- cbind(demo_scales, inverted_enharmonic)

tetra_plot(demo_scales, 
           "Location of 6 Reference Scales in the tc() Plane",
           pch=sapply(1:6, toString)) 

## -----------------------------------------------------------------------------
show_landmarks <- function() {
  points(demo_scales[2, ], demo_scales[3, ], pch=19, cex=2.5, col="white")
  points(demo_scales[2, ], demo_scales[3, ], pch=sapply(1:6, toString), font=2)
}

## -----------------------------------------------------------------------------
num_points <- 4000
parhypatai <- runif(num_points, 0, 5)
lichanoi <- runif(num_points, 0, 5)
inputs <- rbind(parhypatai, lichanoi) |> apply(MARGIN=2, FUN=sort)
random_scales <- apply(inputs, 2, scale_from_genus)
all_signvectors <- apply(random_scales, 2, signvector)
unique_signvectors <- all_signvectors |> unique(MARGIN=2) |> apply(MARGIN=2, FUN=toString)
unique_signvectors <- sort(unique_signvectors)
length(unique_signvectors)

## ----echo=FALSE---------------------------------------------------------------
new_order <- c(1, 15, 17, 21, 3, 19, 25, 11, 9, 13, 5, 23, 7, 2, 16, 18, 22, 4, 20, 26, 12, 10, 6, 24, 8, 14)
unique_signvectors <- unique_signvectors[new_order]

## ----fig.width=5, fig.height=5, fig.fullwidth=TRUE----------------------------
match_sv <- function(sv) {
  res <- which(unique_signvectors == toString(sv))
  if (length(res)==0) {
    return(0)
  }
  res
}

scalar_colors <- apply(all_signvectors, 2, match_sv)
display_colors <- palette.colors(26, palette="Polychrome 36")[scalar_colors]

tetra_plot(random_scales, 
           "26 Scalar Colors in the tc() Plane",
           col=display_colors,
           pch=20)
show_landmarks()

## -----------------------------------------------------------------------------
howfree(double_harmonic)

## -----------------------------------------------------------------------------
howfree(ionian)
howfree(dorian)
howfree(phrygian)

## ----fig.width=5, fig.height=5, fig.fullwidth=TRUE----------------------------
projected_scales <- apply(random_scales, 2, match_flat, target_scale=double_harmonic)
colors_for_projected_scales <- rep("black", num_points)
scales_for_fig5 <- cbind(random_scales, projected_scales)
colors_for_fig5 <- c(display_colors, colors_for_projected_scales)

tetra_plot(scales_for_fig5,
           "Double Harmonic's Flat as a Line of Black Points",
           col=colors_for_fig5,
           pch=20)
show_landmarks()

## -----------------------------------------------------------------------------
test_for_pwf <- apply(projected_scales, 2, isgwf)
table(test_for_pwf)

## ----fig.width=5, fig.height=5, fig.fullwidth=TRUE----------------------------
evenness_values <- apply(projected_scales, 2, evenness)
sizes_for_fig6 <- c(rep(1, num_points), max(evenness_values)-evenness_values)

tetra_plot(scales_for_fig5,
           "Line Thickness Represents Scale Evenness",
           col=colors_for_fig5,
           pch=20,
           cex=sizes_for_fig6)
show_landmarks()

## ----fig.width=5, fig.height=5, fig.fullwidth=TRUE----------------------------
zoomed_tetra_plot <- function(scales, title, ...) {
  oldpar <- par(bg='aliceblue')
  on.exit(par(oldpar))
  plot(scales[2,], 
       scales[3, ], 
       xlab="Height of scale degree 2", xlim=c(0.95, 2.05),
       ylab="Height of scale degree 3", ylim=c(2.99, 4.01),
       ...)
  grid(col="gray35")
  mtext(side=3, title, font=2, line=1)
}

zoomed_parhypatai <- runif(num_points, 1, 2)
zoomed_lichanoi <- runif(num_points, 3, 4)
zoomed_inputs <- rbind(zoomed_parhypatai, zoomed_lichanoi)
zoomed_sets <- apply(zoomed_inputs, 2, scale_from_genus)
zoomed_signvectors <- apply(zoomed_sets, 2, signvector)
zoomed_scalar_colors <- apply(zoomed_signvectors, 2, match_sv)
zoomed_display_colors <- palette.colors(26, palette="Polychrome 36")[zoomed_scalar_colors]

points_for_fig7 <- cbind(zoomed_sets, projected_scales)
colors_for_fig7 <- c(zoomed_display_colors, colors_for_projected_scales)
sizes_for_fig7 <-c(rep(1, num_points), 3^(evenness(double_harmonic)-evenness_values))

zoomed_tetra_plot(points_for_fig7, 
                  "Scalar Colors in the tc() Plane's Most Interesting Zone",
                  col=colors_for_fig7,
                  pch=20,
                  cex=sizes_for_fig7)
show_landmarks()

## -----------------------------------------------------------------------------
which_most_even <- which.min(evenness_values)
projected_scales[, which_most_even]

## -----------------------------------------------------------------------------
naive_guess <- scale_from_genus(c(1+(2/3), 3+(1/3)))
actual_optimum <- scale_from_genus(c(23/14, 47/14))

evenness(naive_guess)
evenness(actual_optimum)

## ----fig.width=5, fig.height=5, fig.fullwidth=TRUE----------------------------
zoomed_tetra_plot(points_for_fig7, 
                  "Most Even Scale at the Point Labeled #7",
                  col=colors_for_fig7,
                  pch=20,
                  cex=sizes_for_fig7)
show_landmarks()
points(23/14, 47/14, pch=19, cex=2.5, col="white")
points(23/14, 47/14, pch="7", font=2)

## -----------------------------------------------------------------------------
howfree(naive_guess)
iswellformed(naive_guess)

## ----fig.width=5, fig.height=5, fig.fullwidth=TRUE----------------------------
# Define a grid that covers the tc() plane evenly.
# x and y both range from 0 to 5 but with slight offsets so that we only see 3-D scales:
grid_subdivisions <- 100
x <- seq(0.001, 4.999, length.out=grid_subdivisions) 
y <- seq(0, 4.98, length.out=grid_subdivisions)

# Calculate the scale structures. (Cf. the definition of `scalar_colors` for Figure 4.)
color_from_point <- function(x, y) scale_from_genus(c(x, y)) |> signvector() |> match_sv()
scalar_colors <- outer(x, y, Vectorize(color_from_point))

# Create visuals
color_palette <- c("aliceblue", palette.colors(26, palette="Polychrome 36"))
oldpar <- par(bg="aliceblue")

image(x, y, z=scalar_colors, col=color_palette,
      xlab="Height of Scale Degree 2", ylab="Height of Scale Degree 3")
mtext(side=3, "26 Scalar Colors in the tc() Plane", font=2, line=1)
show_landmarks()

## ----echo=FALSE---------------------------------------------------------------
par(oldpar)

## ----fig.width=7, fig.height=5, fig.fullwidth=TRUE----------------------------
# Position plot and legend
oldpar <- par(no.readonly=TRUE)
layout(matrix(c(1, 2), ncol=2), widths=c(5, 2))

# Plot the evenness values
measure_evenness <- function(x, y) scale_from_genus(c(x, y)) |> evenness()
evenness_values <- outer(x, y, Vectorize(measure_evenness))
fig10_palette <- hcl.colors(100, palette="Green-Brown")

par(bg="aliceblue")
image(x, y, z=evenness_values, col=fig10_palette,
      xlab="Height of Scale Degree 2", ylab="Height of Scale Degree 3")
points(23/14, 47/14, pch=4, col="white", cex=1.5)
mtext(side=3, "Evenness of Scales in the tc() Plane", font=2, line=1)

# Make the legend
color_legend <- as.raster(matrix(rev(fig10_palette), ncol=1))
ymin <- min(evenness_values[!is.na(evenness_values)])
ymax <- max(evenness_values[!is.na(evenness_values)])
plot(c(0, 1), c(ymin, ymax), type="n", axes=FALSE, xlab="", ylab="Evenness")

rasterImage(color_legend, 0, ymin, 1, ymax)
axis(2, at = round(seq(ymin, ymax, length.out=5), 2))

## ----echo=FALSE---------------------------------------------------------------
par(oldpar)

## ----fig.width=7, fig.height=5, fig.fullwidth=TRUE----------------------------
oldpar <- par(no.readonly=TRUE)
layout(matrix(c(1, 2), ncol=2), widths=c(5, 2))

# Plot the brightness ratio values
measure_ratio <- function(x, y) scale_from_genus(c(x, y)) |> ratio()
ratio_values <- outer(x, y, Vectorize(measure_ratio))
fig11_palette <- hcl.colors(100, palette="Green-Brown")

par(bg="aliceblue")
image(x, y, z=ratio_values, col=fig11_palette,
      xlab="Height of Scale Degree 2", ylab="Height of Scale Degree 3")
mtext(side=3, '"Brightness Ratio" Values in the tc() Plane', font=2, line=1)

# Make the legend
color_legend <- as.raster(matrix(rev(fig11_palette), ncol=1))
ymin <- min(ratio_values[!is.na(ratio_values)])
ymax <- max(ratio_values[!is.na(ratio_values)])
plot(c(0, 1), c(ymin, ymax), type="n", axes=FALSE, xlab="", ylab="Brightness Ratio")

rasterImage(color_legend, 0, ymin, 1, ymax)
axis(2, at = round(seq(ymin, ymax, length.out=5), 2))

## ----echo=FALSE---------------------------------------------------------------
par(oldpar)

## ----fig.width=7, fig.height=5, fig.fullwidth=TRUE----------------------------
oldpar <- par(no.readonly=TRUE)
layout(matrix(c(1, 2), ncol=2), widths=c(5, 2))

# Plot the brightness ratio values
measure_ratio <- function(x, y) scale_from_genus(c(x, y)) |> ratio()
ratio_values <- outer(x, y, Vectorize(measure_ratio))
fig11_palette <- hcl.colors(100, palette="Green-Brown")

par(bg="aliceblue")
image(x, y, z=ratio_values, col=fig11_palette,
      xlab="Height of Scale Degree 2", ylab="Height of Scale Degree 3")
mtext(side=3, 'Contour Plot of "Brightness Ratio" in the tc() Plane', font=2, line=1)

# Add the contour plot
contour(x, y, z=ratio_values, add=TRUE)

# Make the legend
color_legend <- as.raster(matrix(rev(fig11_palette), ncol=1))
ymin <- min(ratio_values[!is.na(ratio_values)])
ymax <- max(ratio_values[!is.na(ratio_values)])
plot(c(0, 1), c(ymin, ymax), type="n", axes=FALSE, xlab="", ylab="Brightness Ratio")
rasterImage(color_legend, 0, ymin, 1, ymax)
axis(2, at = round(seq(ymin, ymax, length.out=5), 2))

## ----echo=FALSE---------------------------------------------------------------
par(oldpar)

## ----fig.width=7, fig.height=5, fig.fullwidth=TRUE----------------------------
oldpar <- par(no.readonly=TRUE)
layout(matrix(c(1, 2), ncol=2), widths=c(5, 2))

grid_subdivisions <- 100
u <- seq(1.001, 1.999, length.out=grid_subdivisions)
v <- seq(3, 3.98, length.out=grid_subdivisions)

ratio_values2 <- outer(u, v, Vectorize(measure_ratio))
fig11_palette <- hcl.colors(100, palette="Green-Brown")

par(bg="aliceblue")
image(u, v, z=ratio_values2, col=fig11_palette,
      xlab="Height of Scale Degree 2", ylab="Height of Scale Degree 3")
contour(u, v, z=ratio_values2, add=TRUE)
mtext(side=3, "\"Brightness Ratio\" at Center of tc() Plane", font=2, line=1)

# Make the legend
color_legend <- as.raster(matrix(rev(fig11_palette), ncol=1))
ymin <- min(ratio_values2[!is.na(ratio_values)])
ymax <- max(ratio_values2[!is.na(ratio_values)])
plot(c(0, 1), c(ymin, ymax), type="n", axes=FALSE, xlab="", ylab="Brightness Ratio")

rasterImage(color_legend, 0, ymin, 1, ymax)
axis(2, at = round(seq(ymin, ymax, length.out=5), 2))

## ----echo=FALSE---------------------------------------------------------------
par(oldpar)

## -----------------------------------------------------------------------------
ratio(scale_from_genus(c(1.5, 3.5)))

