Skip to content

Commit 4b7d23f

Browse files
committed
Merge pull request #25 from MagicForrest/dev-v0.8.0
Dev v0.8.0
2 parents 66c0880 + 5d6d5a1 commit 4b7d23f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1788
-925
lines changed

DESCRIPTION

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: DGVMTools
22
Type: Package
3-
Version: 0.7.1
3+
Version: 0.8.0
44
Title: DGVM Processing, Analysis and Plotting Tools
55
Date: 2019-02-27
66
Authors@R: c(person("Matthew", "Forrest", role=c("aut", "cre"), email="[email protected]"),
@@ -35,7 +35,6 @@ Suggests:
3535
rmarkdown,
3636
ncdf4,
3737
rgeos,
38-
udunits2,
3938
testthat
4039
License: GPL | file LICENSE
4140
URL: https://www.bik-f.de
@@ -65,7 +64,6 @@ Collate:
6564
'commonSTAInfo.R'
6665
'compareLayers.R'
6766
'copyLayers.R'
68-
'countCategoricalData.R'
6967
'crop-methods.R'
7068
'defineSource.R'
7169
'determinePFTs.R'
@@ -89,6 +87,7 @@ Collate:
8987
'plotSeasonal.R'
9088
'plotSpatial.R'
9189
'plotSpatialComparison.R'
90+
'plotSubannual.R'
9291
'plotTemporal.R'
9392
'plotting-framework-functions.R'
9493
'renameLayers.R'

NAMESPACE

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,13 @@ export(all.seasons)
3131
export(annual)
3232
export(availableQuantities)
3333
export(averageFields)
34-
export(byIDfromList)
3534
export(calcNewField)
3635
export(categoricalComparison)
3736
export(cmass.palette)
3837
export(commonSTAInfo)
3938
export(compareLayers)
4039
export(continuousComparison)
4140
export(copyLayers)
42-
export(countCategoricalData)
4341
export(defineSource)
4442
export(determinePFTs)
4543
export(difference.palette)
@@ -60,7 +58,6 @@ export(is.STAInfo)
6058
export(is.Source)
6159
export(is.Statistics)
6260
export(is.leapyear)
63-
export(lai.palette)
6461
export(layerOp)
6562
export(listPFTs)
6663
export(lookupQuantity)
@@ -75,6 +72,7 @@ export(plotScatterComparison)
7572
export(plotSeasonal)
7673
export(plotSpatial)
7774
export(plotSpatialComparison)
75+
export(plotSubannual)
7876
export(plotTemporal)
7977
export(promoteToRaster)
8078
export(proportionsComparison)
@@ -85,6 +83,7 @@ export(reversed.magma)
8583
export(reversed.plasma)
8684
export(reversed.tim.colors)
8785
export(reversed.viridis)
86+
export(seasonalComparison)
8887
export(selectDays)
8988
export(selectGridcells)
9089
export(selectLayers)

NEWS.md

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# DGVMTools v0.8.0 (2019-03-18)
2+
3+
This release has a couple of new features, few minor bug fixes and some tidying and cleaning. See also new repository for example scripts at https://github.com/MagicForrest/DGVMTools_Scripts
4+
5+
## Feature improvements:
6+
7+
* The getBiomes() function can now take a list of Source objects and average over them before calculating the biomes (#19)
8+
* Seasonal comparison metrics, including Mean Phase Difference, now included. plotSpatial also works for seasonal comparisons.
9+
* The compareLayers() function can now calculate user-defined metrics.
10+
* Function plotSubannual() included as a replacement for plotSeasonal(). plotSeasonal() had an inconsistent interface with the other plot functions and is now deprecated. In contrast, plotSubannual() has consistent arguments and also re-uses more code internally, however **facetting is not yet fully implemented**.
11+
* In selectGridcells(), the @spatial.extent now stores the gridcells or shapefile that was used.
12+
* Comparison objects now has an @type characters slot to say if they are "continuous", "categorical", "seasonal" or "relative.abundance" (this is also a potential break).
13+
14+
## Potential breaks:
15+
16+
* Fields are now saved to disk using the .RData file extension instead of .DGVMField to be more consistent with the R universe. You can simply rename your files of necessary.
17+
* Ugly LAI colour palette removed.
18+
* Function countCategoricalData() removed.
19+
* Function byIDfromList() now internal.
20+
* Function addArea() makes layers called "Area" instead of "area".
21+
* The @stats slot of a Comparison object is now a simple R list instead of a class, giving much more flexibility and the possibility for user-defined metrics.
22+
23+
## Bug fixes:
24+
25+
* Fields ids now done more consistently.
26+
* Function renameLayers() now actually returns the Field
27+
28+
## Behind the scenes:
29+
30+
* More code from plotSpatial() factored out into plotting-framework-functions.R
31+
* Benchmarking code re-organised
32+
* getBiomes() much slimmed down by removing code for cropping/aggregating (this was redundant since it was done in the getField calls)
33+
* udunits2 dependency removed
34+
35+
36+
# DGVMTools v0.7.1 (2019-02-27)
37+
38+
Bug fix due to a small regression in listPFTs(). Also took the opportunity to include examples for listPFTs, unit tests for listPFTs, and changed the 'print' functions to 'show' functions as is appropriate for S4 methods (but this does not effect users).
39+
40+
41+
# DGVMTools v0.7.0 (2019-02-27)
42+
43+
Changes are mostly bug fixes and behind the scenes improvements. However there have been a couple of user-facing changes which could break stuff (hence the minor version number increment from 0.6 to 0.7):
44+
45+
46+
## Potential breaks:
47+
48+
* Statistics class has been removed in favour of a simpler and more flexible list
49+
* determineQuantities() and determinePFTs() are not availableQuantities() and availablePFTs()
50+
* The 'sources' argument in plotSpatial() is not more accurately called 'fields'
51+
52+
## Feature improvements:
53+
54+
* Shapefiles can be now used to select gridcells by using them as an an argument to selectGridcells(), this can also be done in getField() which allows lower memory footprint when selecting regions from large files.
55+
* aDGVM support improved (thanks Simon!)
56+
* New benchmarking metrics included, also enhanced flexibility allowing custom metrics
57+
* plotSpatial() can call geom_tile() instead of geom_raster() which allows reprojections (ie polar views)
58+
59+
## Bug fixes:
60+
61+
* Many! (see commits, but none of them resulted in wrong results, but rather failing code)
62+
63+
## Behind the scenes:
64+
65+
* Unit tests!
66+
* Plotting code refactorised for consistency and efficient re-use within the package.
67+
* Benchmarking code re-worked
68+
* Day/Month/Year are now generally stored as integers (not numerics) to save a little memory
69+
70+
Also, from now on the master branch will be consider stable and usable. Bug fixes and small feature improvements will be pulled directly into master. For developers, there will be a dev-v0.8 branch to collect larger features and potentially breaking changes.
71+
72+
73+
# DGVMTools v0.6.2 (2018-10-29)
74+
75+
Removed dependency on external gzip on windows machines for better portability.
76+
77+
78+
# DGVMTools v0.6.1 (2018-10-26)
79+
80+
Featuring aggregation and time series plotting of daily data, use of gzip for compressed DGVMData (also on windows systems), extended vignette and bug fixes.
81+
82+
83+
# DGVMTools v0.6.0 (2018-10-23)
84+
85+
For FireMIP workshop.
86+
87+
88+
# DGVMTools v0.5.2 (2018-10-12)
89+
90+
For visiting collaborators. Release v0.6 still planned in the next two weeks.
91+
92+
93+
# DGVMTools v0.5.0 (2018-10-01)
94+
95+
DGVMTools is now publicly available! Whilst package is pretty much fully featured, there may be bugs, so it should be considered in the late-beta phase. New v0.6 release to come this month.

R/Format-DGVMData.R

+3-1
Original file line numberDiff line numberDiff line change
@@ -297,9 +297,11 @@ getField_DGVMData <- function(source,
297297

298298
# simple ones
299299
spatial.extent.id <- getGlobalAttribute("spatial.extent.id", global.attributes)
300+
if(!is.null(spatial.extent.id)) { sta.info@spatial.extent.id <- spatial.extent.id }
301+
else { sta.info@spatial.extent.id <- "Full" }
300302
spatial.aggregate.method <- getGlobalAttribute("spatial.aggregate.method", global.attributes)
301-
if(!is.null(spatial.extent.id)) sta.info@spatial.extent.id <- spatial.extent.id
302303
if(!is.null(spatial.aggregate.method)) sta.info@spatial.aggregate.method <- spatial.aggregate.method
304+
else { sta.info@spatial.aggregate.method <- "none" }
303305

304306
# first attempt to use the attributes from the NetCDF file
305307
xmin <- getGlobalAttribute("xmin", global.attributes)

R/Format-GUESS.R

+11-1
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,17 @@ openLPJOutputFile <- function(run,
167167
if(spatial.extent.class == "SpatialPolygonsDataFrame" || spatial.extent.class == "numeric" || is.data.frame(target.sta@spatial.extent) || is.data.table(target.sta@spatial.extent)) {
168168
dt <- selectGridcells(x = dt, gridcells = target.sta@spatial.extent, spatial.extent.id = target.sta@spatial.extent.id, ...)
169169
new.extent <- target.sta@spatial.extent
170+
# if new.extent is a data.frame, convery it to a data.table for consistency
171+
if(is.data.frame(new.extent) & !is.data.table(new.extent)) new.extent <- as.data.table(new.extent)
170172
}
171173

172174
else {
173175
dt <- crop(x = dt, y = target.sta@spatial.extent, spatial.extent.id = target.sta@spatial.extent.id)
174176
new.extent <- extent(dt)
175177
}
176178

179+
180+
177181
}
178182

179183
gc()
@@ -233,10 +237,16 @@ openLPJOutputFile <- function(run,
233237
subannual.resolution = subannual,
234238
subannual.original = subannual)
235239

240+
# if cropping has been done, set the new spatial.extent and spatial.extent.id
236241
if(!is.null(new.extent)) {
237-
sta.info@spatial.extent = extent(dt)
242+
sta.info@spatial.extent = new.extent
238243
sta.info@spatial.extent.id <- target.sta@spatial.extent.id
239244
}
245+
# otherwise set
246+
else {
247+
sta.info@spatial.extent = extent(dt)
248+
sta.info@spatial.extent.id <- "Full"
249+
}
240250

241251
gc()
242252

R/Format-aDGVM.R

+15
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,13 @@ getQuantity_aDGVM_Scheme1 <- function(run, variable, target.sta, adgvm.daily)
293293
# Now that we have the data we can set a spatial.extent
294294
actual.sta.info@spatial.extent <- extent(out.all)
295295

296+
# Set the spatial extent to "Full" if one not provided
297+
if(length(target.sta@spatial.extent.id) == 0) {
298+
actual.sta.info@spatial.extent.id <- "Full"
299+
}
300+
else {
301+
actual.sta.info@spatial.extent.id <- target.sta@spatial.extent.id
302+
}
296303

297304
# make the ID and then make and return Field
298305
field.id <- makeFieldID(source = run, var.string = variable@id, sta.info = actual.sta.info)
@@ -663,6 +670,14 @@ getQuantity_aDGVM_Scheme2 <- function(run, variable, target.sta)
663670
# Now that we have the data we can set a spatial.extent
664671
actual.sta.info@spatial.extent <- extent(out.all)
665672

673+
# Set the spatial extent to "Full" if one not provided
674+
if(length(target.sta@spatial.extent.id) == 0) {
675+
actual.sta.info@spatial.extent.id <- "Full"
676+
}
677+
else {
678+
actual.sta.info@spatial.extent.id <- target.sta@spatial.extent.id
679+
}
680+
666681
# make the ID and then make and return Field
667682
field.id <- makeFieldID(source = run, var.string = variable@id, sta.info = actual.sta.info)
668683

R/addArea.R

+51-21
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ gridarea2d <- function(lon, lat, scale=1.0, ellipse=FALSE) {
7878
area2d <- array(rep(area1d, each=length(lon)), c(length(lon), length(lat)))
7979
area <- data.frame(Lon=as.vector(lon2d),
8080
Lat=as.vector(lat2d),
81-
area=as.vector(area2d))
81+
Area=as.vector(area2d))
8282
area <- data.table(area, key=c("Lon", "Lat"))
8383
return(area)
8484
}
@@ -115,21 +115,62 @@ extract.seq <- function(x, force.regular=FALSE, descending=FALSE) {
115115

116116
#' Adds the gridcell area to a spatial Field or data.table/data.frame
117117
#'
118-
#' Adds the gridcell area to a spatial Field or data.table/data.frame.
119-
#' For unit conversion it makes use of \code{\link[udunits2]{ud.convert}}, if installed. If udunits2 is not installed the option is ignored and the returned unit is m^2.
118+
#' Adds the gridcell area to a spatial Field or data.table/data.frame. Makes a new layer/column called "area".
119+
#' Unit conversion from "m^2" (default) to "km^2" and "ha" is supported.
120120
#'
121121
#' @param input a spatial Field or a data.frame/data.table with at least the columns Lon and Lat.
122-
#' @param unit area unit. Default m^2, if something else is spefified udunits2 must be installed. If udunits2 is not installed this option is ignored.
122+
#' @param unit area unit. Default "m^2", can also be "km^2" and "ha"
123123
#' @param ellipse If the eath should be assumed to be a ellipsoid instead of a sphere.
124124
#' @param digits Numeric, number of digits to which to truncate the coordinates when merging the area data.table with the input. This is a technical detail,
125125
#' you only need to use it if you have troubles because of coordinates with a few decimal places.
126126
#' @param verbose print some information.
127+
#'
128+
#' The main use of this function is to calculate gridcell areas internally for gridcells weighted sums and averages in \code{aggregateSpatial} but it can
129+
#' be utilised by the user for any other purpose.
130+
#'
131+
#'
127132
#' @export
128133
#' @return same class as input
129134
#' @author Joerg Steinkamp \email{joerg.steinkamp@@senckenberg.de}
135+
#'
136+
#' @examples
137+
#'
138+
#' \donttest{
139+
#'
140+
#' # Get an example Field
141+
#' africa.dir <- system.file("extdata", "LPJ-GUESS_Runs", "CentralAfrica", package = "DGVMTools")
142+
#' africa.Source <- defineSource(name = "LPJ-GUESS", dir = africa.dir, format = GUESS)
143+
#' field <- getField(source = africa.Source, var = "cmass", year.aggregate.method="mean")
144+
#'
145+
#' # add area in m^2 - note "Area" column follows immediately after Lon and Lat
146+
#' field.m2 <- addArea(input = field, unit = "m^2")
147+
#' print(field.m2@data)
148+
#'
149+
#' # add area in km^2
150+
#' field.km2 <- addArea(input = field, unit = "km^2")
151+
#' print(field.km2@data)
152+
#'
153+
#' # plot area (also modify plot and legend title to be more meaningful)
154+
#' p <- plotSpatial(field.km2, "Area", title = "Gridcell Area (km^2)", subtitle = NULL)
155+
#' p <- p + guides(fill = guide_colourbar(title = "km^2"))
156+
#' print(p)
157+
#'
158+
#' # add area in km^2 using an ellipse
159+
#' field.km2.ellipse <- addArea(input = field, unit = "km^2", ellipse = TRUE)
160+
#' field.km2.ellipse <- renameLayers(field.km2.ellipse, "Area", "Area_ellipse")
161+
#'
162+
#' # compare areas just for fun
163+
#' comp.layer <- compareLayers(field1=field.km2, field2=field.km2.ellipse,
164+
#' layers1="Area", layers2="Area_ellipse")
165+
#' plot.title <- "Difference in gridcell area for spherical vs ellipsoid Earth"
166+
#' p <- plotSpatialComparison(comp.layer, title= plot.title, subtitle = NULL)
167+
#' p <- p + guides(fill = guide_colourbar(title = "km^2"))
168+
#' print(p)
169+
#'
170+
#' }
130171
addArea <- function(input, unit="m^2", ellipse=FALSE, verbose=TRUE, digits = 10) {
131172
## to avoid "no visible binding for global variable" during check
132-
Lat = Lon = NULL
173+
Lat = Lon = Area = NULL
133174
if (is.na(unit))
134175
unit="m^2"
135176

@@ -164,22 +205,11 @@ addArea <- function(input, unit="m^2", ellipse=FALSE, verbose=TRUE, digits = 10)
164205
}
165206

166207
if (unit!="m^2") {
167-
if (requireNamespace("udunits2", quietly=TRUE)) {
168-
if (udunits2::ud.is.parseable(unit)) {
169-
if (udunits2::ud.are.convertible("m^2", unit)) {
170-
area$area = udunits2::ud.convert(area$area, "m^2", unit)
171-
} else {
172-
warning(paste("m^2 not convertible to '", unit, "'. Using m^2 instead.", sep=""))
173-
unit="m^2"
174-
}
175-
} else {
176-
warning(paste("Unit '", unit, "' not parseable! Using m^2 instead.", sep=""))
177-
unit="m^2"
178-
}
179-
} else {
180-
message("Package 'udunits2' not installed! Using m^2 instead.")
181-
warning("Package 'udunits2' not installed! Using m^2 instead.")
182-
}
208+
209+
if(unit == "km^2") area[, Area := Area / 10^6]
210+
else if(unit == "ha") area[, Area := Area / 10^4]
211+
else stop(paste("Unsupported unit string in addArea", unit))
212+
183213
}
184214

185215

R/aggregateSpatial.R

+7-8
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ aggregateSpatial.uncompiled <- function(input.obj,
2727
...){
2828

2929
# Messy solution to stop "notes" about undeclared global variables stemming from data.table syntax
30-
Year = Lat = Lon = area = NULL
30+
Year = Lat = Lon = Area = NULL
3131

3232
### SET UP THE AGGREGATE METHOD
3333

@@ -71,19 +71,18 @@ aggregateSpatial.uncompiled <- function(input.obj,
7171

7272
# Do the aggregating
7373
if (method == "w.mean") {
74-
if (!any(colnames(input.dt)=="area")) {
74+
if (!any(colnames(input.dt)=="Area")) {
7575
if (verbose) message("Add column area.")
7676
input.dt <- addArea(input.dt, verbose=verbose, ...)
7777
}
7878
if(verbose) message(paste("Spatially averaging (with area weighting) ...", sep = ""))
7979

80-
81-
output.dt <- input.dt[,lapply(.SD, method.function, w=area), by=by.dims]
82-
output.dt[,area:=NULL]
80+
output.dt <- input.dt[,lapply(.SD, method.function, w=Area), by=by.dims]
81+
output.dt[,Area:=NULL]
8382

8483
}
8584
else if (method == "w.sum") {
86-
if (!any(colnames(input.dt)=="area")) {
85+
if (!any(colnames(input.dt)=="Area")) {
8786
if (verbose) message("Add column area.")
8887
input.dt <- addArea(input.dt, verbose=verbose)
8988
}
@@ -97,10 +96,10 @@ aggregateSpatial.uncompiled <- function(input.obj,
9796
col.names <- col.names[!col.names %in% remove]
9897

9998
# check to see if Year is still a column name (it might have been averaged away)
100-
input.dt[, (col.names) := lapply(.SD, function(x) x * input.dt[['area']] ), .SDcols = col.names]
99+
input.dt[, (col.names) := lapply(.SD, function(x) x * input.dt[['Area']] ), .SDcols = col.names]
101100

102101
output.dt <- input.dt[, lapply(.SD, method.function), by=by.dims]
103-
output.dt[,area:=NULL]
102+
output.dt[,Area:=NULL]
104103

105104
}
106105

0 commit comments

Comments
 (0)