Skip to content

Commit

Permalink
CRAN test modifications
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathancallahan committed Dec 12, 2017
1 parent 5f3444d commit a2c3de4
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 78 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Type: Package
Package: PWFSLSmoke
Version: 0.99.30
Version: 0.99.33
Title: Utilities for Working with Air Quality Monitoring Data
Authors@R: c(
person("Jonathan", "Callahan", email="[email protected]", role=c("aut","cre")),
Expand Down
15 changes: 14 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,25 @@ from the US EPA, AirNow, AIRSIS, WRCC and others.

## Version 0.99 -- Regularized and Consistent (beta)

### PWFSLSmoke 0.99.33

* tweaked esriMap_~ examples for CRAN upload

### PWFSLSmoke 0.99.32

* tweaked NowCast vignette for CRAN upload

### PWFSLSmoke 0.99.31

* refactored `esriMap_getMap()` to use `httr` package
* added NowCast vignette

### PWFSLSmoke 0.99.30

* new `airsis_availableUnits()` function
* new `AIRSIS` object with available monitor types
* fix to `esriMap_getMap()` to ensure that projected maps are the correct size
* `esriMap_getMap()` arguments changed to: `bboxString` and `mapType`
* `esriMap_getMap()` arguments changed to: `bboxString`

### PWFSLSmoke 0.99.29

Expand Down
116 changes: 53 additions & 63 deletions R/esriMap_getMap.R
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
#' @keywords plotting
#' @export
#' @title Create a RGB spatial raster from arcGIS REST
#' @title Download a Spatial Raster Object from ESRI
#' @param centerLon map center longitude
#' @param centerLat map center latitude
#' @param maptype map type. natGeo, worldStreetMap, worldTopoMap, satellite, or deLorme. Also accepts
#' map server identity, found at \url{http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Basemaps/02r3000001mt000000/}
#' @param maptype map type
#' @param zoom map zoom level; corresponds to googleMaps zoom level
#' @param bboxString comma separated string with bounding box (xmin, ymin, xmax, ymax). If not null, centerLon, centerLat, and zoom are ignored.
#' @param bboxSR spatial reference of the bounding box
#' @param width width of image, in pixels
#' @param height height of image, in pixels
#' @param crs object of class CRS. The Coordinate Reference System (CRS) for the returned map. If the CRS of the downloaded
#' map does not match, it will be projected to the specified CRS using \code{raster::projectRaster}.
#' @param additionalArgs additional arguments to be pasted into the image URL eg. \code{"&rotation=90"}
#' @param additionalArgs character string with additional arguments to be pasted into the image URL eg. \code{"&rotation=90"}
#' @description Downloads a PNG from ESRI and creates a \code{raster::rasterBrick} object with layers for red, green, and blue.
#' This can then passed as the \code{mapRaster} object to the \code{esriMap_plotOnStaticMap()} function for plotting.
#'
#' Available \code{maptypes} include:
#' \itemize{
#' \item{natGeo}
#' \item{worldStreetMap}
#' \item{worldTopoMap}
#' \item{satellite}
#' \item{deLorme}
#' }
#'
#' Additional base maps are found at:
#' \url{http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Basemaps/02r3000001mt000000/}
#'
#' @note The spatial reference of the image when it is downloaded is 3857. If the crs argument is different, projecting may cause
#' the size and extent of the image to differ very slightly from the input, on a scale of 1-2 pixels or 10^-3 degrees.
#'
#' If bboxString is specified and the bbox aspect ratio does not match the width/height aspect ratio the extent is resized to prevent
#' the map image from appearing stretched, so the map extent may not match the bbox argument exactly.
#' @return A rasterBrick object which can be plotted with \code{raster::plotRGB} and serve as a base plot.
#' @description Creates a rasterBrick using the \pkg{raster} package with layers for red, green, and blue color intensity.
#' @return A rasterBrick object which can be plotted with \code{esriMap_plotOnStaticMap()} or \code{raster::plotRGB()} and serve as a base plot.
#' @references \url{http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Export_Map/02r3000000v7000000/}
#' @examples
#' \dontrun{
#' map <- esriMap_getMap(-122.3318, 47.668)
#' esriMap_plotOnStaticMap(map)
#' }

#' @seealso \code{\link{esriMap_plotOnStaticMap}}
#'
esriMap_getMap <- function(centerLon = NULL,
centerLat = NULL,
bboxString = NULL,
Expand All @@ -39,23 +53,17 @@ esriMap_getMap <- function(centerLon = NULL,
additionalArgs = NULL) {


# calculate degrees per pixel from zoom to determine bbox:
# Calculate degrees per pixel from zoom to determine bbox:
# * google maps tiles are 256x256 pixels
# * zoom level 0 includes 360 degrees-EW
# * every time zoom level increases, scale halves. Thus, for degrees EW:
# pixels/degree = 256pixels*2^zoomLevel/360degrees
# degrees/pixel = 360degrees/(256pixels*2^zoomLevel)
# degrees-NS/pixel = degreesPerPixelNS*cos(latitude)
# Source: https://gis.stackexchange.com/questions/7430/what-ratio-scales-do-google-maps-zoom-levels-correspond-to

# TODO: Improve logic
# TODO: if (lat AND lon) { ... } else if (bboxString) { ... } else { ERROR }
if ( is.null(centerLat) && is.null(centerLon) && is.null(bboxString) ) {
stop("centerLat, centerLon, or bboxString must be specified")
}

# TODO: Merge this if block into the logic above
if ( is.null(bboxString) ) {

# Create components of webservice URL
if ( !is.null(centerLon) && !is.null(centerLat) ) {
degreesPerPixelEW <- 360/(256*2^zoom)
degreesPerPixelNS <- degreesPerPixelEW*cos(pi/180*centerLat) # R does trigonometry in radians
lonLo <- centerLon - degreesPerPixelEW*(width/2-.5)
Expand All @@ -64,16 +72,20 @@ esriMap_getMap <- function(centerLon = NULL,
latLo <- centerLat-degreesPerPixelNS*(height/2-.5)
latHi <- centerLat+degreesPerPixelNS*(height/2-.5)
bbox <- c(lonLo, latLo, lonHi, latHi)
bboxString <- paste0(bbox, collapse=",")
bboxSR <- "4326"
}
bboxString <- paste0(bbox, collapse = ",")
} else if ( !is.null(bboxString) ) {
bboxSR <- "4326"
} else {
stop("centerLat + centerLon, or bboxString must be specified")
}

# url text for maptype http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Basemaps/02r3000001mt000000/
# NatGeo_World_Map = natGeo
# World_Street_Map = worldStreetMap
# World_Topo_Map = worldTopoMap
# Specialty/DeLorme_World_Base_Map = deLorme
# World_Imagery = satellite
# NOTE: Url text for maptype http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Basemaps/02r3000001mt000000/
# NOTE: * NatGeo_World_Map = natGeo
# NOTE: * World_Street_Map = worldStreetMap
# NOTE: * World_Topo_Map = worldTopoMap
# NOTE: * Specialty/DeLorme_World_Base_Map = deLorme
# NOTE: * World_Imagery = satellite

if ( maptype == "natGeo" ) {
maptypeText <- "NatGeo_World_map"
Expand All @@ -89,46 +101,28 @@ esriMap_getMap <- function(centerLon = NULL,
maptypeText <- maptype
}

# Apply arguments to url

# TODO: Naming consistency: url, baseUrl, pngUrl, jsonUrl
# Create URLs from components
baseUrl <- paste0("http://server.arcgisonline.com/arcgis/rest/services/", maptypeText, "/MapServer/export")
url <- paste0(baseUrl, "?bbox=", bboxString, "&bboxSR=", bboxSR, "&size=", width, ",", height, additionalArgs)
pngUrl <- paste0(url, "&f=image")
jsonUrl <- paste0(url, "&f=json")

# TODO: Always use httr package to download stuff
# TODO: Much of the code below here can be replaced with:
# TODO:
# TODO: response <- httr::GET(jsonUrl)
# TODO: # check response$status_code and issue an intelligible error message if needed
# TODO: mapInfo <- jsonlite::fromJSON(httr::content(response))
# TODO: response <- httr::GET(pngUrl)
# TODO: # check status_code
# TODO: array <- httr::content(response)
# TODO: mapRaster <- raster::rasterImamge(array, ...)

# TODO: Test each web request by checking out

# Download and load PNG and metadata

dirName <- paste("esriMap", centerLat, centerLon, sep = "_")
if ( dir.exists(dirName) ) { dirName <- paste0(dirName, "(temp)") }
dir.create(dirName)

utils::download.file(pngUrl, paste0(dirName, "/image.png"))
utils::download.file(jsonUrl, paste0(dirName, "/info.json"))

imageArray <- png::readPNG(paste0(dirName, "/image.png"))
mapInfoJSON <- readr::read_file(paste0(dirName, "/info.json"))

unlink(dirName, recursive = TRUE)

mapInfo <- jsonlite::fromJSON(mapInfoJSON)

# Create raster with RBG layers and matching metadata
# Get ESRI JSON map metadata
response <- httr::GET(jsonUrl)
if ( httr::http_error(response) ) {
stop(paste0("ESRI JSON request failed with: ",httr::content(response)))
}
mapInfo <- jsonlite::fromJSON(httr::content(response))

mapRaster <- raster::brick(ncol=mapInfo$width,
# Get ESRI map png
response <- httr::GET(pngUrl)
if ( httr::http_error(response) ) {
stop(paste0("ESRI PNG request failed with: ",httr::content(response)))
}
imageArray <- httr::content(response, type="image/png")

# Convert PNG into a Raster object
mapRaster <- raster::brick(ncol=mapInfo$width,
nrow=mapInfo$height,
nl = 3)
mapRaster <- raster::setValues(mapRaster, imageArray*255)
Expand All @@ -139,14 +133,10 @@ esriMap_getMap <- function(centerLon = NULL,
raster::extent(mapRaster) <- c(mapInfo$extent$xmin, mapInfo$extent$xmax, mapInfo$extent$ymin, mapInfo$extent$ymax)
raster::crs(mapRaster) <- sp::CRS(paste0("+init=epsg:",mapInfo$extent$spatialReference$latestWkid))


if ( rgdal::CRSargs(crs) != rgdal::CRSargs(sp::CRS(paste0("+init=epsg:", mapInfo$extent$spatialReference$latestWkid))) ) {
mapRaster <- raster::projectRaster(mapRaster, crs = crs, method = "ngb")

# trim any extra NA on the edges generated by projectRaster

mapRaster <- raster::trim(mapRaster)

}

return(mapRaster)
Expand Down
5 changes: 4 additions & 1 deletion R/esriMap_plotOnStaticMap.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
#' @param grayscale logical, if TRUE one layer is plotted with grayscale values. If FALSE, a color
#' map is plotted from red, green, and blue colors.
#' @param ... arguments passed on to \code{plot} (for grayscale = TRUE) or \code{plotRGB} (for grayscale = FALSE)
#' @return An plot of the map
#' @description The map is plotted using \code{plotRGB} from \pkg{raster}.
#' @return An plot of the map
#' @examples
#' \dontrun{
#' map <- esriMap_getMap(-122.3318, 47.668)
#' esriMap_plotOnStaticMap(map)
#' esriMap_plotOnStaticMap(map, grayscale = TRUE)
#' }
#' @seealso \code{\link{esriMap_getMap}}

esriMap_plotOnStaticMap <- function(mapRaster,
grayscale = FALSE,
Expand Down
27 changes: 21 additions & 6 deletions man/esriMap_getMap.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions man/esriMap_plotOnStaticMap.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 4 additions & 6 deletions localVignettes/NowCast.Rmd → vignettes/NowCast.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,6 @@ We run the following code to get things set up to use our new funcitons.
library(PWFSLSmoke)
logger.setup()
library(MazamaSpatialUtils)
setSpatialDataDir('~/Data/Spatial')
loadSpatialData('NaturalEarthAdm1')
```

For the following examples we will use the Northwest Megafires data from the PWFSLSmoke package. In particular, we will look at PM~2.5~ data from Omak, WA, which was heavily impacted by smoke from wildfires during the second half of August, 2015:
Expand Down Expand Up @@ -541,10 +539,10 @@ plot(example5_df$datetime, example5_df$monitored)
lines(example5_df$datetime, example5_df$aqi, col="blue")
```

TODO: clean up and beef up this example
<!-- TODO: clean up and beef up this example -->

## Test Dataset
<!-- ## Test Dataset -->

> Under "test datasets" I'd like to see a simple CSV file with two columns: pm25_input, expected_output
<!-- > Under "test datasets" I'd like to see a simple CSV file with two columns: pm25_input, expected_output -->

TODO: add test datasets
<!-- TODO: add test datasets -->

0 comments on commit a2c3de4

Please sign in to comment.