tests/testthat/test-ternary.R

test_that("Errors are handled gracefully", {
  expect_error(TernaryCoords(c(1, 2)))
  expect_error(TernaryCoords(c("a", "b", "c")))
  expect_error(TernaryPlot(point = "nowhere"))
  expect_error(TernaryPoints(rep(1, 5)))
  expect_error(HorizontalGrid(direction = 5))
  expect_warning(
    TernaryPlot(xlim = c(0, 10), ylim = c(0, 1), isometric = TRUE),
    "x range > y range.+setting ylim"
  )
  expect_warning(
    TernaryPlot(xlim = c(0, 1), ylim = c(0, -10), isometric = TRUE),
    "x range < y range.+setting xlim"
  )
  expect_error(CoordinatesToXY(array(1, dim = c(1, 1, 1))))
})

test_that("TernaryCoords gives correct coordinates", {
  options("ternDirection" = 2L)
  input <- cbind(
    c(a = 0, b = 0, c = 1),
    c(a = 0, b = 2, c = 0),
    c(a = 3, b = 0, c = 0),
    c(a = 0, b = 9, c = 9),
    c(a = 2, b = 1, c = 1)
  )
  listInput <- lapply(1:5, function(i) input[, i])
  output <- cbind(
    c(0, 0.5),
    c(0, -0.5),
    c(sin(pi / 3), 0),
    c(0, 0),
    c(sin(pi / 3) / 2, 0)
  )
  expect_equal(output, apply(input, 2, TernaryCoords))
  expect_equal(output, CoordinatesToXY(listInput))
  expect_equal(output, CoordinatesToXY(input))
  expect_equal(matrix(output[, 1], 2, 1), CoordinatesToXY(input[, 1]))

  expect_equal(input / rep(colSums(input), each = 3),
               XYToTernary(output[1, ], output[2, ]))
  expect_error(TernaryCoords(rep(1, 5), 1, 1))
  expect_equal(c(0, 0.5), TernaryCoords(0, 0, 1))
})

test_that("Ternary plotting functions", {
  TernaryPlotterXlim <- function() {
    TernaryPlot("A", "B", "C", xlim = c(0, 0.86), point = 2)
    JoinTheDots(list(c(1, 1, 1), c(0, 1, 2)), lwd = 2, col = "green")
    TernaryPoints(c(0.5, 1, 1))
    TernaryText(c(1.5, 1, 1), "A")
  }
  TernaryPlotterYlim <- function() {
    TernaryPlot("A", "B", "C", ylim = c(0, 0.82),
                point = 1, main = "... to plot")
    TernaryLines(list(c(1, 1, 1), c(0, 1, 2)), lwd = 2)
    TernaryArrows(c(1, 1.2, 1), c(0, 1.2, 2), lwd = 1)
    TernaryPolygon(matrix(c(
      30, 40, 30,
      30, 30, 40,
      55, 20, 25
    ), ncol = 3, byrow = TRUE))
  }

  skip_if_not_installed("vdiffr")
  vdiffr::expect_doppelganger("plot-to-ternary-x", TernaryPlotterXlim)
  vdiffr::expect_doppelganger("plot-to-ternary-y", TernaryPlotterYlim)
})

test_that("Axes can be styled individually", {
  AxisStyle <- function() {
    par(mfrow = 1:2, xpd = NA)
    cols <- c("red", "darkgreen", "blue")
    TernaryPlot(
      alab = "a", blab = "b", clab = "c",
      atip = "a", btip = "b", ctip = "c",
      lab.col = cols,
      lab.cex = 1:3 / 2,
      lab.offset = 1:3 / 15,
      grid.lines = 4,
      axis.lwd = 1:3,
      axis.lty = 1:3,
      axis.lab = list(0:4, 10:14, 20:24),
      ticks.lwd = 1:3,
      grid.col = cols,
      grid.lwd = 1:3,
      grid.lty = 1:3,
      grid.minor.col = c("#ff9999", "#99ff99", "#9999ff"),
      grid.minor.lty = 4:6,
      grid.minor.lwd = 1:3,
      axis.col = cols,
      axis.font = 1:3,
      ticks.col = cols,
      ticks.length = 1:3 / 50,
      tip.font = 1:3,
      tip.col = cols
    )
    TernaryPoints(c(2, 1, 0))

    TernaryPlot(
      alab = "a", blab = "b", clab = "c",
      atip = "a", btip = "b", ctip = "c",
      clockwise = FALSE,
      lab.col = cols,
      lab.cex = 1:3 / 2,
      lab.offset = 1:3 / 15,
      grid.lines = 4,
      axis.lwd = 1:3,
      axis.lty = 1:3,
      ticks.lwd = 1:3,
      grid.col = cols,
      grid.lwd = 1:3,
      grid.lty = 1:3,
      grid.minor.col = c("#ff9999", "#99ff99", "#9999ff"),
      grid.minor.lty = 4:6,
      grid.minor.lwd = 1:3,
      axis.col = cols,
      axis.font = 2,
      ticks.col = cols,
      ticks.length = 1:3 / 50,
      tip.font = 1:3,
      tip.col = cols
    )
    TernaryPoints(c(2, 1, 0))
  }
  skip_if_not_installed("vdiffr")
  vdiffr::expect_doppelganger("AxisStyle", AxisStyle)
})

test_that("panel.xxst parameter", {
  skip_if_not_installed("vdiffr")
  vdiffr::expect_doppelganger("panel.xxst-parameter", function() {
    TernaryPlot(
      panel.first = rect(0, -1, -1, 1, col = 2),
      panel.last = rect(0, -1, 1, 1, col = 3),
      atip = "Tip A", btip = "Tip B", clab = "Axis C",
      xpd = NA
    )
  })
})

test_that("Vignette plots are rendered correctly", {
  skip_if_not_installed("vdiffr")
  vdiffr::expect_doppelganger("Blank plot", TernaryPlot)

  BlankTernary <- function(dir, clockwise = TRUE) {
    TernaryPlot(
      point = dir,
      atip = "A vertex", btip = "B vertex", ctip = "C vertex",
      alab = "Aness", blab = "Bness", clab = "Cness",
      clockwise = clockwise
    )
    TernaryText(list(A = c(10, 01, 01), B = c(01, 10, 01), C = c(01, 01, 10)),
      col = cbPalette8[4], font = 2
    )
    HorizontalGrid(grid.col = "red")
  }

  TernaryUp <- function() BlankTernary("up")
  TernaryRight <- function() BlankTernary("right")
  TernaryDown <- function() BlankTernary("down")
  TernaryLe <- function() BlankTernary("le")


  TernaryUpAC <- function() BlankTernary("up", clockwise = FALSE)
  TernaryRightAC <- function() BlankTernary("right", clockwise = FALSE)
  TernaryDownAC <- function() BlankTernary("down", clockwise = FALSE)
  TernaryLeAC <- function() BlankTernary("le", clockwise = FALSE)

  vdiffr::expect_doppelganger("Blank up", TernaryUp)
  vdiffr::expect_doppelganger("Blank right", TernaryRight)
  vdiffr::expect_doppelganger("Blank down", TernaryDown)
  vdiffr::expect_doppelganger("Blank le", TernaryLe)

  vdiffr::expect_doppelganger("Blank up anticlockwise", TernaryUpAC)
  vdiffr::expect_doppelganger("Blank right anticlockwise", TernaryRightAC)
  vdiffr::expect_doppelganger("Blank down anticlockwise", TernaryDownAC)
  vdiffr::expect_doppelganger("Blank le anticlockwise", TernaryLeAC)

  TernaryCols <- function() {
    par(mfrow = c(1, 2), mar = rep(0.3, 4))
    TernaryPlot(
      alab = "Redder \u2192", blab = "\u2190 Greener", clab = "Bluer \u2192",
      lab.col = c("red", "green", "blue"),
      point = "right", lab.cex = 0.8, grid.minor.lines = 0,
      grid.lty = "solid", grid.col = "white",
      axis.col = rgb(0.6, 0.6, 0.6), ticks.col = rgb(0.6, 0.6, 0.6),
      padding = 0.08
    )
    cols <- TernaryPointValues(rgb)
    ColourTernary(cols, spectrum = NULL)
    data_points <- list(
      R = c(255, 0, 0),
      O = c(240, 180, 52),
      Y = c(210, 222, 102),
      G = c(111, 222, 16),
      B = c(25, 160, 243),
      I = c(92, 12, 243),
      V = c(225, 24, 208)
    )
    AddToTernary(points, data_points,
      pch = 21, cex = 2.8,
      bg = vapply(
        data_points,
        function(x) rgb(x[1], x[2], x[3], 128, maxColorValue = 255),
        character(1)
      )
    )
    AddToTernary(text, data_points, names(data_points), cex = 0.8, font = 2)
    legend("bottomright",
      legend = c("Red", "Orange", "Yellow", "Green"),
      cex = 0.8, bty = "n", pch = 21, pt.cex = 1.8,
      pt.bg = c(
        rgb(255, 0, 0, 128, NULL, 255),
        rgb(240, 180, 52, 128, NULL, 255),
        rgb(210, 222, 102, 128, NULL, 255),
        rgb(111, 222, 16, 128, NULL, 255)
      ),
    )

    TernaryPlot("Steam", "Ice", "Water",
      grid.lines = 5L, grid.lty = "dotted",
      grid.minor.lines = 1L, grid.minor.lty = "dotted",
      btip.rotate = 330L, ctip.rotate = 30L,
      col = rgb(0.9, 0.9, 0.9, alpha = 0.2),
      point = "West"
    )
    HorizontalGrid()
    middle_triangle <- matrix(c(
      30, 40, 30,
      30, 30, 40,
      55, 20, 25
    ), ncol = 3, byrow = TRUE)
    TernaryPolygon(middle_triangle, col = "#aaddfa", border = "grey")
    TernaryLines(list(c(0, 100, 0), middle_triangle[1, ]), col = "grey")
    TernaryLines(list(c(0, 0, 100), middle_triangle[2, ]), col = "grey")
    TernaryLines(list(c(100, 0, 0), middle_triangle[3, ]), col = "grey")
    TernaryArrows(c(20, 20, 60), c(30, 30, 40), length = 0.2, col = "darkblue")
    TernarySegments(rbind(c(25, 15, 60), c(15, 25, 60)),
      rbind(c(30, 30, 40), c(30, 30, 40)),
      col = c("lightblue", "#0000eecc")
    )
  }

  skip_if_not_installed("vdiffr")
  vdiffr::expect_doppelganger("colours-and-water", TernaryCols)

  Cartesian <- function() {
    TernaryPlot(point = "right")
    arrows(x0 = 0.5, y0 = 0.4, x1 = sqrt(3) / 2, y1 = 0.4,
           length = 0.1, col = cbPalette8[2])
    text(x = mean(c(0.5, sqrt(3) / 2)), y = 0.4, "Increasing X",
         pos = 3, col = cbPalette8[2])
    text(x = 0.5, y = 0, "(0.5, 0)", col = cbPalette8[3])
    text(x = 0.8, y = -0.5, "(0.8, -0.5)", col = cbPalette8[3])
  }
  skip_if_not_installed("vdiffr")
  vdiffr::expect_doppelganger("Cartesian", Cartesian)

  Padding <- function() {
    TernaryPlot(xlim = c(0.28, 0.38), ylim = c(0.1, 0.2), padding = 0.04)

    # Annotate grid lines at user-specified points:
    TernaryText(
      list(c(8, 72, 20), c(8, 82, 10)),
      c(20, 10), srt = -60, cex = 0.9, col = "darkgrey")
    TernaryText(list(c(10, 69, 21), c(20, 64, 16)),
                c(10, 20), srt = 0, cex = 0.9, col = "darkgrey")

    # Plot desired polygon
    my_corners <- list(c(22, 66, 12), c(22, 72, 6), c(15, 80, 5), c(12, 76, 12))
    TernaryPolygon(my_corners, col = "#2cbe4e")

    # Show xlim, ylim and padding, using cartesian coordinates
    lines(c(0.28, 0.28, 0.38, 0.38, 0.28), c(0.1, 0.2, 0.2, 0.1, 0.1))
    text(0.28, 0.15, "xlim[1]", pos = 2, srt = 90)
    text(0.38, 0.15, "xlim[2]", pos = 4, srt = 90)
    text(0.33, 0.1, "ylim[1]", pos = 1)
    text(0.33, 0.2, "ylim[2]", pos = 3)
    text(0.38, 0.1, "<padding>", pos = 4, cex = 0.75)
    text(0.38, 0.1, "<padding> ", pos = 2, cex = 0.75, srt = 90)
  }
  skip_if_not_installed("vdiffr")
  vdiffr::expect_doppelganger("padding", Padding)
})

Try the Ternary package in your browser

Any scripts or data that you put into this service are public.

Ternary documentation built on July 9, 2023, 6:51 p.m.