Skip to content

Commit

Permalink
Minor improvements to metadata handling
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenbi committed Jan 15, 2018
1 parent 6f6bfc0 commit 051c7a0
Show file tree
Hide file tree
Showing 12 changed files with 193 additions and 144 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: magclass
Type: Package
Title: Data Class and Tools for Handling Spatial-Temporal Data
Version: 4.72.3
Version: 4.72.4
Author: Jan Philipp Dietrich,
Benjamin Bodirsky,
Misko Stevanovic,
Expand Down
1 change: 0 additions & 1 deletion R/add_columns.R
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ add_columns<-function(x,addnm=c("new"),dim=3.1){
}}
new_columns[,,]<-NA
}
getMetadata(new_columns) <- NULL
output <- mbind(x,new_columns)
return(output)
}
23 changes: 12 additions & 11 deletions R/as.magpie.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ tmpfilter <- function(x, sep="\\.", replacement="_") {

setMethod("as.magpie",
signature(x = "lpj"),
function (x, ...)
function (x, unit="1", ...)
{
xdimnames <- dimnames(x)
xdim <- dim(x)
x <- array(x[magclassdata$half_deg$lpj_index,,,],dim=c(dim(x)[1:2],dim(x)[3]*dim(x)[4]))
dimnames(x) <- list(paste(magclassdata$half_deg$region,1:59199,sep='.'),
xdimnames[[2]],
paste(rep(xdimnames[[3]],xdim[4]),rep(xdimnames[[4]],each=xdim[3]),sep="."))
return(new("magpie",x))
return(updateMetadata(new("magpie",x), unit=unit))
}
)

setMethod("as.magpie",
signature(x = "array"),
function (x, spatial=NULL, temporal=NULL, ...)
function (x, spatial=NULL, temporal=NULL, unit="1", ...)
{
store_attributes <- copy.attributes(x,0)

Expand Down Expand Up @@ -148,15 +148,15 @@ setMethod("as.magpie",

#Now temporal and regiospatial dimension should both exist
#Return MAgPIE object
return(copy.attributes(store_attributes,new("magpie",wrap(x,list(d$regiospatial,d$temporal,NA)))))
return(updateMetadata(copy.attributes(store_attributes,new("magpie",wrap(x,list(d$regiospatial,d$temporal,NA)))), unit=unit))
}
)

setMethod("as.magpie",
signature(x = "numeric"),
function(x,...)
function(x, unit="1", ...)
{
return(copy.attributes(x,as.magpie(as.array(x),...)))
return(updateMetadata(copy.attributes(x,as.magpie(as.array(x),...)), unit=unit))
}
)

Expand All @@ -170,7 +170,7 @@ setMethod("as.magpie",

setMethod("as.magpie",
signature(x = "data.frame"),
function (x, datacol=NULL, tidy=FALSE, sep=".", replacement="_", ...)
function (x, datacol=NULL, tidy=FALSE, sep=".", replacement="_", unit="1", ...)
{
# filter illegal characters
for(i in 1:dim(x)[2]) {
Expand All @@ -193,7 +193,7 @@ setMethod("as.magpie",
if(datacol==dim(x)[2]) return(tidy2magpie(x,...))
x[[datacol-1]] <- as.factor(x[[datacol-1]])
}
return(copy.attributes(x,tidy2magpie(suppressMessages(reshape2::melt(x)),...)))
return(updateMetadata(copy.attributes(x,tidy2magpie(suppressMessages(reshape2::melt(x)),...)), unit=unit))
}
)

Expand Down Expand Up @@ -262,19 +262,20 @@ setMethod("as.magpie",

#put value column as last column
x <- x[c(which(names(x)!="value"),which(names(x)=="value"))]
return(tidy2magpie(x,spatial="region",temporal="period"))
return(updateMetadata(tidy2magpie(x,spatial="region",temporal="period")))
}
)

setMethod("as.magpie",
signature(x = "tbl_df"),
function(x, ...)
function(x, unit="1", ...)
{
if("quitte" %in% class(x)) {
class(x) <- c("quitte","data.frame")
return(updateMetadata(as.magpie(x,...)))
} else {
class(x) <- "data.frame"
return(updateMetadata(as.magpie(x,...), unit=unit))
}
return(as.magpie(x,...))
}
)
164 changes: 82 additions & 82 deletions R/clean_magpie.R
Original file line number Diff line number Diff line change
@@ -1,82 +1,82 @@
#' MAgPIE-Clean
#'
#' Function cleans MAgPIE objects so that they follow some extended magpie
#' object rules (currently it makes sure that the dimnames have names and
#' removes cell numbers if it is purely regional data)
#'
#'
#' @param x MAgPIE object which should be cleaned.
#' @param what term defining what type of cleaning should be performed. Current
#' modes are "cells" (removes cell numbers if the data seems to be regional -
#' this should be used carefully as it might remove cell numbers in some cases
#' in which they should not be removed), "sets" (making sure that all
#' dimensions have names) and "all" (performing all available cleaning methods)
#' @return The eventually corrected MAgPIE object
#' @author Jan Philipp Dietrich
#' @seealso \code{"\linkS4class{magpie}"}
#' @examples
#'
#' data(population_magpie)
#' a <- clean_magpie(population_magpie)
#'
#' @export clean_magpie
clean_magpie <- function(x,what="all") {
if(!(what %in% c("all","cells","sets"))) stop('Unknown setting for argument what ("',what,'")!')
#remove cell numbers if data is actually regional
if(what=="all" | what =="cells") {
if(ncells(x)==nregions(x)) {
getCells(x) <- getRegions(x)
if(!is.null(names(dimnames(x))[[1]])) {
if(!is.na(names(dimnames(x))[[1]])) {
names(dimnames(x))[[1]] <- sub("\\..*$","",names(dimnames(x))[[1]])
}
}
}
}
#make sure that all dimensions have names
if(what=="all" | what =="sets") {

if(is.null(names(dimnames(x)))) names(dimnames(x)) <- rep(NA,3)

.count_subdim <- function(x,sep="\\.") {
o <- nchar(gsub(paste0("[^",sep,"]*"),"",x))+1
if(length(o)==0) o <- 0
return(o)
}

names <- names(dimnames(x))
if(!is.na(names[1]) & (names[1]!="") & (names[1]!="NA")) {
c1 <- .count_subdim(dimnames(x)[[1]][1])
c2 <- .count_subdim(names[1])
if(c1!=c2) {
if(c1>2) stop("More than 2 spatial subdimensions not yet implemented")
names[1] <- paste(names[1],"cell",sep=".")
}
} else {
names[1] <- ifelse(all(grepl("\\.",dimnames(x)[[1]])),"region.cell","region")
}
if(is.na(names[2]) | names[2]=="NA" | names[2]=="") {
names[2] <- "year"
}
if(is.na(names[3]) | names[3]=="" | names[3]=="NA") {
ndim <- nchar(gsub("[^\\.]","",getNames(x)[1])) +1
names[3] <- ifelse(length(ndim)>0,paste0("data",1:ndim,collapse="."),"data1")
} else {
c1 <- .count_subdim(dimnames(x)[[3]][1])
c2 <- .count_subdim(names[3])
if(c1!=c2) {
if(c1>c2) {
names[3] <- paste(c(names[3],rep("data",c1-c2)),collapse=".")
} else {
search <- paste0(c(rep("\\.[^\\.]*",c2-c1),"$"),collapse="")
names[3] <- sub(search,"",names[3])
}
names[3] <- paste0(make.unique(strsplit(names[3],"\\.")[[1]],sep = ""),collapse=".")

}
}

names(dimnames(x)) <- names
}
return(x)
}
#' MAgPIE-Clean
#'
#' Function cleans MAgPIE objects so that they follow some extended magpie
#' object rules (currently it makes sure that the dimnames have names and
#' removes cell numbers if it is purely regional data)
#'
#'
#' @param x MAgPIE object which should be cleaned.
#' @param what term defining what type of cleaning should be performed. Current
#' modes are "cells" (removes cell numbers if the data seems to be regional -
#' this should be used carefully as it might remove cell numbers in some cases
#' in which they should not be removed), "sets" (making sure that all
#' dimensions have names) and "all" (performing all available cleaning methods)
#' @return The eventually corrected MAgPIE object
#' @author Jan Philipp Dietrich
#' @seealso \code{"\linkS4class{magpie}"}
#' @examples
#'
#' data(population_magpie)
#' a <- clean_magpie(population_magpie)
#'
#' @export clean_magpie
clean_magpie <- function(x,what="all") {
if(!(what %in% c("all","cells","sets"))) stop('Unknown setting for argument what ("',what,'")!')
#remove cell numbers if data is actually regional
if(what=="all" | what =="cells") {
if(ncells(x)==nregions(x)) {
getCells(x) <- getRegions(x)
if(!is.null(names(dimnames(x))[[1]])) {
if(!is.na(names(dimnames(x))[[1]])) {
names(dimnames(x))[[1]] <- sub("\\..*$","",names(dimnames(x))[[1]])
}
}
}
}
#make sure that all dimensions have names
if(what=="all" | what =="sets") {

if(is.null(names(dimnames(x)))) names(dimnames(x)) <- rep(NA,3)

.count_subdim <- function(x,sep="\\.") {
o <- nchar(gsub(paste0("[^",sep,"]*"),"",x))+1
if(length(o)==0) o <- 0
return(o)
}

names <- names(dimnames(x))
if(!is.na(names[1]) & (names[1]!="") & (names[1]!="NA")) {
c1 <- .count_subdim(dimnames(x)[[1]][1])
c2 <- .count_subdim(names[1])
if(c1!=c2) {
if(c1>2) stop("More than 2 spatial subdimensions not yet implemented")
names[1] <- paste(names[1],"cell",sep=".")
}
} else {
names[1] <- ifelse(all(grepl("\\.",dimnames(x)[[1]])),"region.cell","region")
}
if(is.na(names[2]) | names[2]=="NA" | names[2]=="") {
names[2] <- "year"
}
if(is.na(names[3]) | names[3]=="" | names[3]=="NA") {
ndim <- nchar(gsub("[^\\.]","",getNames(x)[1])) +1
names[3] <- ifelse(length(ndim)>0,paste0("data",1:ndim,collapse="."),"data1")
} else {
c1 <- .count_subdim(dimnames(x)[[3]][1])
c2 <- .count_subdim(names[3])
if(c1!=c2) {
if(c1>c2) {
names[3] <- paste(c(names[3],rep("data",c1-c2)),collapse=".")
} else {
search <- paste0(c(rep("\\.[^\\.]*",c2-c1),"$"),collapse="")
names[3] <- sub(search,"",names[3])
}
names[3] <- paste0(make.unique(strsplit(names[3],"\\.")[[1]],sep = ""),collapse=".")

}
}

names(dimnames(x)) <- names
}
return(updateMetadata(x))
}
2 changes: 1 addition & 1 deletion R/complete_magpie.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ complete_magpie<-function(x,fill=NA) {
out<-mbind(x,add)
} else {out<-x}
out<-out[,,order(getNames(out))]
if (isTRUE(getOption("magclass_metadata"))) getMetadata(out) <- getMetadata(x)
getMetadata(out) <- getMetadata(x)
return(out)
}
5 changes: 2 additions & 3 deletions R/dimReduce.R
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ dimReduce <- function(x, dim_exclude=NULL) {
if(dim(x_single)[2]==1) getYears(x_single) <- NULL
# same information in all dimension entries?
if(all(x - x_single == 0, na.rm = TRUE)) {
if(isTRUE(getOption("magclass_metadata"))) getMetadata(x_single) <- getMetadata(x)
getMetadata(x_single) <- getMetadata(x)
x <- x_single
}
}
if(isTRUE(getOption("magclass_metadata"))) x <- updateMetadata(x)
return(x)
return(updateMetadata(x))
}
70 changes: 57 additions & 13 deletions R/getMetadata.R
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
getMetadata <- function(x, type=NULL) {
if(!isTRUE(getOption("magclass_metadata"))) return(NULL)
M <- attr(x, "Metadata")
if(is.null(M$unit)) M$unit <- 1
if(is.null(M$unit)) M$unit <- '1'
if(is.null(type)) {
return(M)
} else if(length(type)>1){
Expand All @@ -63,29 +63,73 @@ getMetadata <- function(x, type=NULL) {
M <- attr(x, "Metadata")
if (!is.list(M)) M <- list()
if (is.null(type)){
if (!is.list(value) & !is.null(value)) stop("Metadata must be a list object if no type is specified")
if (!is.list(value) & !is.null(value)) stop("Metadata must be provided as a list if no type is specified")
else{
M <- value
if (length(value$unit)>1){
warning(value$unit," is an invalid argument for unit")
value$unit <- 1
}
if (!is.null(value$source)){
if (is.list(value$source)){
for (i in 1:(length(value$source)-1)){
if (is.list(value$source[[i]])){
if (!is.null(value$source[[i+1]]) & !is.list(value$source[[i+1]])){
warning("Source [",i+1,"] is not a list! Please include at least author, title, date, and journal. Also DOI, ISSN, URL, etc")
value$source[[i+1]] <- NULL
}
}else if (!is.null(value$source[[i]]) & is.list(value$source[[i+1]])){
warning("Source [",i,"] is not a list! Please include at least author, title, date, and journal. Also DOI, ISSN, URL, etc")
value$source[[i]] <- NULL
}
}
}else{
warning("Source must be a formatted as a list! Please include at least author, title, date, and journal. Also DOI, ISSN, URL, etc")
value$source <- NULL
}
}
if (!is.null(value$user)){
if (!is.character(value$user) & length(value$user)!=1){
warning(value$user," is an invalid argument for user! Please use getMetadata.R or updateMetadata.R to provide a user")
value$user <- NULL
}
}
if(!is.null(value$date)){
if(!is.character(value$date) & length(value$date)!=1){
warning(value$date," is an invalid argument for date! Please use getMetadata.R or updateMetadata.R to provide a date")
value$date <- NULL
}
}
if(!is.null(value$description)){
if(!is.character(value$description)){
warning(value$description," is an invalid argument for description!")
value$description <- NULL
}
}
}
M <- value
}else if (type=="unit"){
if (length(value)<=1) M[[type]] <- value
else warning(value," is an invalid argument for unit!")
}else if (type=="source"){
if (is.list(value) || is.null(value)) M[[type]] <- value
if (is.null(value) || is.list(value)) M[[type]] <- value
else warning("Source field must be a list! Please include at least author, title, date, and journal. DOI, ISSN, URL, etc are also encouraged")
}else if (type == "calcHistory"){
if (is.character(value)) M[[type]] <- value
else warning("calcHistory field must be a character!")
if (is.character(value)){
if (is.list(M$calcHistory)) M$calcHistory[[length(M$calcHistory)]] <- append(M$calcHistory[[length(M$calcHistory)]],value)
else if (is.null(M[[type]])) M[[type]] <- value
else M[[type]] <- list(M[[type]],value)
}else if (is.null(value)) M[[type]] <- value
else warning(value," is an invalid argument for calcHistory! Please use getMetadata.R to provide the most recent function executed on, ",x)
}else if (type=="date"){
if (is.character(value)) M[[type]] <- value
else warning("date field must be a character!")
if ((is.character(value) & length(value)==1)) M[[type]] <- value
else warning(value," is an invalid argument for date! Please use getMetadata.R or updateMetadata.R to provide a date for ",x)
}else if (type=="user"){
if (is.character(value)) M[[type]] <- value
else warning("user field must be a character!")
if ((is.character(value) & length(value)==1)) M[[type]] <- value
else warning(value," is an invalid argument for user! Please use getMetadata.R or updateMetadata.R to provide a user for ",x)
}else if (type=="description"){
if(is.character(value) || is.null(value)) M[[type]] <- value
else warning("description field must be a character!")
}
if(is.null(value) || is.character(value)) M[[type]] <- value
else warning(value," is an invalid argument for description! Please use getMetadata.R to provide a description for ",x)
}else warning(type," is not a valid metadata field!")
attr(x, "Metadata") <- M
return(x)
}
2 changes: 1 addition & 1 deletion R/magpply.R
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ magpply<-function(X,FUN,MARGIN,...,integrate=FALSE){
} else {
out<-as.magpie(out)
}
if(isTRUE(getOption("magclass_metadata"))) out <- updateMetadata(out,X,unit="copy",source="copy",calcHistory="copy",description="copy")
out <- updateMetadata(out,X,unit="copy",source="copy",calcHistory="copy",description="copy")
return(out)
}
Loading

0 comments on commit 051c7a0

Please sign in to comment.