-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from ropensci/gganimate
get animation working with new version of gganimate
- Loading branch information
Showing
146 changed files
with
4,478 additions
and
11,669 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,13 @@ | ||
^README\.Rmd$ | ||
^.*\.Rproj$ | ||
^\.Rproj\.user$ | ||
.travis.yml | ||
README.Rmd | ||
README_cache | ||
README_files | ||
myPlot.png | ||
^README_files$ | ||
^README_old\.md$ | ||
^README_old\.Rmd$ | ||
^cran-comments\.md$ | ||
^tests$ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
inst/doc | ||
.Rproj.user | ||
.Rhistory | ||
.RData | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,40 @@ | ||
Package: plotdap | ||
Title: Easily visualize data from 'ERDDAP' Servers via the rerddap package | ||
Version: 0.0.1 | ||
Authors@R: c(person("Carson", "Sievert", role = c("aut","cre"), email = "[email protected]")) | ||
Description: Easily visualize 'tabledap' and 'griddap' objects obtained via the rerddap package. | ||
Title: Easily Visualize Data from 'ERDDAP' Servers via the 'rerddap' Package | ||
Version: 0.0.2 | ||
Date: 2019-04-29 | ||
Authors@R: c( | ||
person("Carson", "Sievert", role = "aut"), | ||
person("Roy", "Mendelssohn", role = c("aut", "ctb", "cre"), email = "[email protected]")) | ||
Description: Easily visualize and animate 'tabledap' and 'griddap' objects obtained via the 'rerddap' package in a simple one-line command, using either base graphics or 'ggplot2' graphics. 'plotdap' handles extracting and reshaping the data, map projections and continental outlines. Optionally the data can be animated through time using the 'gganmiate' package. | ||
License: MIT + file LICENSE | ||
URL: https://github.com/ropensci/plotdap | ||
BugReports: https://github.com/ropensci/plotdap/issues | ||
Depends: | ||
rerddap | ||
R (>= 3.5.0), | ||
rerddap | ||
Imports: | ||
magrittr, | ||
tidyr, | ||
dplyr, | ||
gganimate, | ||
ggplot2 (>= 3.1.0), | ||
lazyeval, | ||
ggplot2 (>= 2.2.1), | ||
scales, | ||
maps (>= 3.2.0), | ||
lubridate, | ||
magrittr, | ||
mapdata, | ||
maps (>= 3.2.0), | ||
maptools, | ||
plot3D, | ||
rgdal, | ||
rgeos, | ||
raster, | ||
scales, | ||
sf, | ||
rgeos, | ||
rgdal | ||
tidyr | ||
Suggests: | ||
testthat, | ||
Cairo, | ||
knitr, | ||
rmarkdown | ||
Remotes: | ||
tidyverse/ggplot2 | ||
RoxygenNote: 6.0.1 | ||
RoxygenNote: 6.1.1 | ||
LazyData: true | ||
Encoding: UTF-8 | ||
VignetteBuilder: knitr |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# plotdap 0.0.2 | ||
First CRAN release | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#' QMwind Data | ||
#' | ||
#' pre-Download of QMwind in `add_griddap()` example so that example | ||
#' can run within CRAN Time limits | ||
#' | ||
#' obtained using the `rerddap` command | ||
#' wind <- griddap('erdQMwindmday', | ||
#' time = c('2016-11-16', '2017-01-16'), latitude = c(30, 50), | ||
#' longitude = c(210, 240), | ||
#' fields = 'x_wind') | ||
#' ) | ||
"QMwind" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#' Add ggplot2 elements to a plotdap object | ||
#' | ||
#' \code{add_ggplot} allows for plotdap ggplot maps to be modified by | ||
#' further ggplot2 settings | ||
#' @param plot a plotdap object. | ||
#' @param ... arguments passed along to \code{geom_sf()} | ||
#' (if \code{method='ggplot2'}, otherwise ignored). | ||
#' @return A plotdap object | ||
#' @export | ||
#' @rdname add_ggplot | ||
#' @examples | ||
#' | ||
#' library(ggplot2) | ||
#' | ||
#' add_ggplot( | ||
#' plotdap( | ||
#' crs = "+proj=laea +y_0=0 +lon_0=155 +lat_0=-90 +ellps=WGS84 +no_defs", | ||
#' mapColor = "black" | ||
#' ), | ||
#' theme_bw() | ||
#' ) | ||
#' | ||
#' | ||
add_ggplot <- function(plot, ...) { | ||
if (!is_plotdap(plot)) { | ||
stop( | ||
"The first argument to `add_ggplot()` must be a `plotdap()` object", | ||
call. = FALSE | ||
) | ||
} | ||
dots <- list(...) | ||
for (i in seq_along(dots)) { | ||
plot$ggplot <- plot$ggplot + dots[[i]] | ||
} | ||
plot | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
#' Add rerddap::griddap() data to a plotdap map | ||
#' | ||
#' \code{add_griddap} adds the data from an 'rerddap::griddap() call to | ||
#' a 'plotdap' map | ||
#' @param plot a \link{plotdap} object. | ||
#' @param grid a \link{griddap} object. | ||
#' @param var a formula defining a variable, or function of variables to visualize. | ||
#' @param fill either a character string of length 1 matching a name in \\link[rerddap]{colors} | ||
#' or a vector of color codes. This defines the colorscale used to encode values | ||
#' of \code{var}. | ||
#' @param maxpixels integer > 0. Maximum number of cells to use for the plot. | ||
#' If maxpixels < ncell(x), sampleRegular is used before plotting. | ||
#' If gridded=TRUE maxpixels may be ignored to get a larger sample | ||
#' @param time how to resolve multiple time frames. Choose one of the following: | ||
#' \itemize{ | ||
#' \item A function to apply to each observation at a particular location | ||
#' (\link{mean} is the default). | ||
#' \item A character string (of length 1) matching a time value. | ||
#' } | ||
#' @param animate whether to animate over the \code{time} variable (if it exists). | ||
#' Currently only implemented for \code{method='ggplot2'} and requires the | ||
#' gganimate package. | ||
#' @param cumulative - if animation should be cumulative -default FALSE | ||
#' @param ... arguments passed along to \code{geom_sf()} | ||
#' (if \code{method='ggplot2'}, otherwise ignored). | ||
#' @return A plotdap object | ||
#' @export | ||
#' @rdname add_griddap | ||
#' @examples | ||
#' | ||
#' # base plotting tends to be faster, | ||
#' # but is less extensible plotdap("base") | ||
#' | ||
#' # actual datasets in data folder to meet execution timings | ||
#' | ||
#'\donttest{ | ||
#' murSST <- griddap( | ||
#' 'jplMURSST41', latitude = c(35, 40), longitude = c(-125, -1205), | ||
#' time = c('last', 'last'), fields = 'analysed_sst' | ||
#' ) | ||
#' | ||
#' QMwind <- griddap( | ||
#' 'erdQMwindmday', time = c('2016-11-16', '2017-01-16'), | ||
#' latitude = c(30, 50), longitude = c(210, 240), | ||
#' fields = 'x_wind' | ||
#' ) | ||
#' | ||
#' p <- plotdap(crs = "+proj=robin") | ||
#' add_griddap(p, murSST, ~analysed_sst) | ||
#' | ||
#' p <- plotdap(mapTitle = "Average wind over time") | ||
#' add_griddap(p, QMwind, ~x_wind) | ||
#' | ||
#'} | ||
#' | ||
# | ||
#' p <- plotdap("base", crs = "+proj=robin") | ||
#' p <- add_griddap(p, murSST, ~analysed_sst) | ||
#' | ||
#' # layer tables on top of grids | ||
#' require(magrittr) | ||
#' p <- plotdap("base") %>% | ||
#' add_griddap(murSST, ~analysed_sst) %>% | ||
#' add_tabledap(sardines, ~subsample_count) | ||
#' | ||
#' # multiple time periods | ||
#' p <- plotdap("base", mapTitle = "Average wind over time") | ||
#' p <- add_griddap(p, QMwind, ~x_wind) | ||
#' | ||
|
||
add_griddap <- function(plot, grid, var, fill = "viridis", | ||
maxpixels = 10000, time = mean, animate = FALSE, | ||
cumulative = FALSE, ...) { | ||
if (!is.grid(grid)) | ||
stop("The `grid` argument must be a `griddap()` object", call. = FALSE) | ||
if (!lazyeval::is_formula(var)) | ||
stop("The `var` argument must be a formula", call. = FALSE) | ||
if (!is.function(time) && !is.character(time)) | ||
stop("The `time` argument must be a function or a character string", | ||
call. = FALSE) | ||
|
||
# create raster object from filename; | ||
# otherwise create a sensible raster from data | ||
r <- get_raster(grid, var) | ||
|
||
# checks for naming and numeric lat/lon | ||
latlon_is_valid(r) | ||
# adjust to ensure everthing is on standard lat/lon scale | ||
r <- latlon_adjust(r) | ||
|
||
# if necessary, reduce a RasterBrick to a RasterLayer | ||
# http://gis.stackexchange.com/questions/82390/summarize-values-from-a-raster-brick-by-latitude-bands-in-r | ||
if (body(time) == 'UseMethod("mean")') { | ||
time <- function(x) mean(x, na.rm = TRUE) | ||
} | ||
if (raster::nlayers(r) > 1) { | ||
if (is.function(time)) { | ||
r <- raster::calc(r, time) | ||
} else { | ||
nm <- make.names(time) | ||
if (!nm %in% names(r)) { | ||
warning( | ||
"The `time` argument doesn't match any of time values.\n", | ||
sprintf( | ||
"Valid options include: '%s'", | ||
paste(unique(grid$data$time), collapse = "', '") | ||
), | ||
call. = FALSE | ||
) | ||
} | ||
r <- r[[nm]] | ||
} | ||
|
||
if (raster::nlayers(r) > 1 && !animate) { | ||
stop( | ||
"The `time` argument hasn't reduced the raster down to a single layer.\n", | ||
"Either set `animate=TRUE` or provide a suitable value to `time`.", | ||
call. = FALSE | ||
) | ||
} | ||
} | ||
|
||
# simplify raster, if necessary | ||
n <- raster::ncell(r) | ||
if (n > maxpixels) { | ||
message("grid object contains more than ", maxpixels, " pixels") | ||
message("increase `maxpixels` for a finer resolution") | ||
rnew <- raster::raster( | ||
nrow = floor(raster::nrow(r) * sqrt(maxpixels / n)), | ||
ncol = floor(raster::ncol(r) * sqrt(maxpixels / n)), | ||
crs = raster::crs(r), | ||
ext = raster::extent(r) | ||
) | ||
if (inherits(r, "RasterBrick")) { | ||
for (i in seq_len(raster::nlayers(r))) { | ||
r[[i]] <- raster::resample(r[[i]], rnew, method = 'bilinear') | ||
} | ||
} else { | ||
r <- raster::resample(r, rnew, method = 'bilinear') | ||
} | ||
} | ||
|
||
# assumes we apply sf::st_crs() to plot on initiation | ||
if (inherits(plot$crs, "crs")) { | ||
crs_string <- plot$crs$proj4string | ||
if (!is.na(plot$crs$epsg)) { | ||
epsg_string <- paste0("+init=epsg:", plot$crs$epsg) | ||
crs_string <- paste(epsg_string, crs_string) | ||
} | ||
#r <- raster::projectRaster(r, crs = plot$crs$proj4string) | ||
r <- raster::projectRaster(r, crs = crs_string) | ||
} | ||
|
||
# color scale | ||
cols <- if (length(fill) == 1) rerddap::colors[[fill]] else fill | ||
|
||
if (is_ggplotdap(plot)) { | ||
# TODO: not the most efficient approach, but it will have to do for now | ||
# https://twitter.com/hadleywickham/status/841763265344487424 | ||
s <- sf::st_as_sf(raster::rasterToPolygons(r)) | ||
vars <- setdiff(names(s), "geometry") | ||
sg <- sf::st_as_sf(tidyr::gather_(s, "variable", "value", vars)) | ||
if (animate) { | ||
try_gganimate() | ||
plot$animate <- TRUE | ||
plot$nper <- length(sg) | ||
plot$ggplot <- plot$ggplot + | ||
gganimate::transition_manual(variable, cumulative = cumulative) + | ||
ggplot2::labs(title = "{current_frame}") | ||
} | ||
|
||
return( | ||
add_ggplot( | ||
plot, | ||
geom_sf(data = sg, | ||
mapping = aes_string(fill = "value", colour = "value"), ...), | ||
scale_fill_gradientn(name = lazyeval::f_text(var), colors = cols), | ||
scale_colour_gradientn(colors = cols), | ||
guides(colour = FALSE) | ||
) | ||
) | ||
} | ||
|
||
if (animate) { | ||
warning( | ||
"Animations are currently only implemented for `method='ggplot2'`", | ||
call. = FALSE | ||
) | ||
} | ||
|
||
# TODO: more props! | ||
grid <- structure( | ||
r, props = list( | ||
name = lazyeval::f_text(var), | ||
values = raster::values(r), | ||
color = cols | ||
) | ||
) | ||
|
||
# Throw a warning if the grid extent overlaps with another grid? | ||
plot$layers <- c( | ||
plot$layers, list(grid) | ||
) | ||
|
||
plot | ||
} |
Oops, something went wrong.