Skip to content

Commit

Permalink
Merge pull request #6 from pepijn-devries/work-in-progress
Browse files Browse the repository at this point in the history
Improved test coverage
  • Loading branch information
pepijn-devries authored Jul 28, 2024
2 parents c13679a + 77d8c58 commit 4b22914
Show file tree
Hide file tree
Showing 8 changed files with 621 additions and 15 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: ggfields
Title: Add Vector Field Layers to Ggplots
Version: 0.0.6.0001
Version: 0.0.6.0002
Authors@R: c(person("Pepijn", "de Vries", role = c("aut", "cre"),
email = "[email protected]",
comment = c(ORCID = "0000-0002-7961-6646")))
Expand Down
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
ggfields v0.0.6.0001
ggfields v0.0.6.0002
-------------

* Fixed test
* Added tests
* Added test coverage workflow

ggfields v0.0.6
Expand Down
9 changes: 4 additions & 5 deletions R/angle_correction.r
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ angle_correction <- function(data, panel_params, coord) {
if ("crs" %in% names(guides) && is.na(crs)) true_aspect <- 1 else
true_aspect <- coord$ratio %||% coord_aspect
if (is.na(crs)) {
rlang::message_cnd("ggfields", message = "CRS is not specified, correcting for aspect ratio only.")
rlang::inform("CRS is not specified, correcting for aspect ratio only.")
ref <- data.frame(angle = atan2(true_aspect*sin(data$angle), cos(data$angle))) |>
dplyr::mutate(angle = .data$angle - data$angle,
angle = atan2(sin(.data$angle), cos(.data$angle)))
Expand All @@ -99,10 +99,9 @@ angle_correction <- function(data, panel_params, coord) {
ref <- (north_of_ref - ref) |>
dplyr::mutate(y = .data$y*true_aspect, angle = -atan2(.data$y, .data$x) + pi/2)
}
rlang::message_cnd(
"ggfields", message = sprintf("Angle correction between %0.2f and %0.2f radials",
min(ref$angle), max(ref$angle)))

rlang::inform(sprintf("Angle correction between %0.2f and %0.2f radials",
min(ref$angle), max(ref$angle)), frequency = "regularly")

data |>
dplyr::mutate(
angle_correction = ref$angle
Expand Down
382 changes: 382 additions & 0 deletions tests/testthat/_snaps/plots/ggfields-annot.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 54 additions & 0 deletions tests/testthat/test_anglecorrection.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
params_mockup <-
c(
ggplot2::ggplot() + geom_fields(),
list(
x_range = c(1, 2),
y_range = c(50, 51),
crs = sf::st_crs(4326),
default_crs = 4326
)
)

coord <- ggplot2::coord_sf()

test_that(
"Angle correction won't work on geometries other then point", {
expect_error({
data <-
data.frame(
geometry = sf::st_sfc(sf::st_polygon())
) |>
sf::st_as_sf(crs = 4326)

angle_correction(data, params_mockup, coord)
})
}) |> suppressMessages()

test_that(
"Missing CRS is signalled", {
expect_message({
data <-
data.frame(
angle = 0,
geometry = sf::st_sfc(sf::st_polygon())
) |>
sf::st_as_sf()

angle_correction(data, params_mockup, coord)
})
}) |> suppressMessages()

test_that(
"Expect warning for proximity to North Pole", {
expect_warning({
data <-
data.frame(
x = seq(1, 2, 0.1),
y = seq(98.999, 99.999, 0.1),
angle = 0
) |>
sf::st_as_sf(coords = c("x", "y"), crs = 4326, remove = FALSE)

angle_correction(data, params_mockup, coord)
})
}) |> suppressMessages()
96 changes: 96 additions & 0 deletions tests/testthat/test_helpers.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
library(dplyr, quietly = TRUE)
library(sf, quietly = TRUE)
library(stars, quietly = TRUE)
library(ggplot2, quietly = TRUE)
} |>
suppressWarnings() |>
suppressMessages()

self <- GeomFields
data <- data.frame(
colour = "black",
geometry = st_point(c(1,50)) |> st_sfc(crs = 4326),
angle = 0,
PANEL = 1,
group = 1,
xmin = 1,
xmax = 1,
ymin = 50,
ymax = 50,
linewidth = 1,
linetype = 1,
alpha = 1,
radius = 1
) |>
st_as_sf()

params_mockup <-
c(
ggplot() + geom_fields(),
list(
x_range = c(1, 2),
y_range = c(50, 51),
crs = st_crs(4326),
default_crs = 4326
)
)

coord <- coord_sf()

test_that(
"Prep fields coerces stars to sf", {
expect_s3_class({
system.file("tif/L7_ETMs.tif", package = "stars") |> read_stars() -> x
ggfields:::.data_prep_fields(x)
}, "sf")
}
)

test_that(
"Setup params add linejoin and lineend when missing", {
expect_true({
params <- .setup_params_fields(params = list())
typeof(params) == "list" &&
all(c("linejoin", "lineend") %in% names(params))
})
}
)

test_that(
"Error when `x` aesthetic is not combined with `y`", {
expect_error({
data <- data |> st_drop_geometry() |>
mutate(x = 0)
ggfields:::.compute_panel_stat_fields(data = data)
})
}
)

test_that(
"radius and angle are coercible to numerics", {
expect_true({
test <- ggfields:::.compute_panel_stat_fields(data = data)
is.numeric(test$angle) && is.numeric(test$radius)
})
})

test_that(
"Geometry is added to mapping of sf objects when missing", {
expect_true({
test <- ggfields:::.mapping_prep_fields(data, aes())
("geometry" %in% names(test)) && inherits(test$geometry, "quosure")
})
})

test_that(
"Panel draw function returns a gTree object", {
testthat::expect_s3_class({
ggfields:::.draw_panel_fields(
self, data, params_mockup, coord,
FALSE, grid::unit(0.7, "cm"),
grid::arrow(), angle_correction, "mitre", "butt"
) |> suppressMessages()
}, c("gTree", "grob", "gDesc"))
}
)
83 changes: 75 additions & 8 deletions tests/testthat/test_plots.r
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
library(ggplot2, quietly = TRUE) |> suppressWarnings()
library(stars, quietly = TRUE) |> suppressWarnings()

data("seawatervelocity")
sw_sub <- seawatervelocity[,8:13,1:5]

test_that(
"Seawater velocity is visualised correctly", {
library(ggplot2) |> suppressWarnings()
data("seawatervelocity")
seawater_plot <-
ggplot() +
geom_fields(aes(radius = as.numeric(v), angle = as.numeric(angle)),
seawatervelocity)
seawatervelocity) +
stat_fields()
vdiffr::expect_doppelganger("ggfields seawater", seawater_plot)
}
)
) |> suppressMessages()

test_that(
"Angle corrections work as expected", {
library(ggplot2) |> suppressWarnings()
north_arrows <-
expand.grid(
x = seq(-5, 15, length.out = 10),
Expand All @@ -23,20 +27,83 @@ test_that(
stars::st_as_stars(nx = 10, ny = 10) |>
dplyr::mutate(angle = 0*(2*pi/360))

no_correction <-

north_plot <-
ggplot() +
theme(legend.position = "top") +
labs(colour = NULL) +
geom_fields(data = north_arrows, aes(angle = angle, col = "no correction"), radius = 1,
.angle_correction = NULL,
key_glyph = draw_key_fields,
max_radius = ggplot2::unit(0.7, "cm")) +
geom_fields(data = north_arrows, aes(angle = angle, col = "corrected"), radius = 1,
.angle_correction = angle_correction,
key_glyph = draw_key_fields,
max_radius = ggplot2::unit(0.7, "cm")) +
scale_colour_manual(values = c(`no correction` = "red", corrected = "green")) +
coord_sf(crs = 32631)

vdiffr::expect_doppelganger("ggfields north", north_plot)
}
)
) |> suppressMessages()

test_that(
"Annotation is visualised correctly", {

## Note that the `seawatervelocity` spans a much larger area,
## but the plot only focuses on `sw_sub`
annot_plot <- ggplot() +
geom_stars(data = sw_sub) +
annotation_fields(data = seawatervelocity,
aes(angle = as.numeric(atan2(vo, uo)),
radius = as.numeric(pythagoras(uo, vo)))) +
labs(radius = "v [m/s]")
vdiffr::expect_doppelganger("ggfields annot", annot_plot)
}
) |> suppressMessages()

test_that(
"Negative radii throws error in continuous scales", {
expect_error({
on.exit({grDevices::dev.off(); closeAllConnections()})
f <- tempfile(fileext = ".pdf")
p <- ggplot() +
geom_stars(data = sw_sub) +
geom_fields(data = sw_sub,
aes(angle = as.numeric(atan2(vo, uo)),
radius = -as.numeric(pythagoras(uo, vo))))
grDevices::pdf(f)
print(p) |> suppressMessages()
})
})

test_that(
"Binned scales work without error", {
expect_no_error({
on.exit({grDevices::dev.off(); closeAllConnections()})
f <- tempfile(fileext = ".pdf")
p <- ggplot() +
geom_stars(data = sw_sub) +
geom_fields(data = sw_sub,
aes(angle = as.numeric(atan2(vo, uo)),
radius = as.numeric(pythagoras(uo, vo)))) +
scale_radius_binned()
grDevices::pdf(f)
print(p) |> suppressMessages()
})
})

test_that(
"Discrete scales work without error", {
expect_no_error({
on.exit({grDevices::dev.off(); closeAllConnections()})
f <- tempfile(fileext = ".pdf")
p <- ggplot() +
geom_stars(data = sw_sub) +
annotation_fields(data = sw_sub,
aes(angle = as.numeric(atan2(vo, uo)),
radius = cut(as.numeric(pythagoras(uo, vo)), 3))) +
scale_radius_discrete()
grDevices::pdf(f)
print(p) |> suppressMessages()
})
})
7 changes: 7 additions & 0 deletions tests/testthat/test_simple.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
test_that(
"Pythagoras is correct", {
calc <- pythagoras(1:10, 10:1)
expect_equal(
sum(calc),
87.37186249587302)
})

0 comments on commit 4b22914

Please sign in to comment.